texlive[67588] Build/source/libs: harfbuzz 8.0.0

commits+kakuto at tug.org commits+kakuto at tug.org
Sun Jul 9 07:55:35 CEST 2023


Revision: 67588
          http://tug.org/svn/texlive?view=revision&revision=67588
Author:   kakuto
Date:     2023-07-09 07:55:34 +0200 (Sun, 09 Jul 2023)
Log Message:
-----------
harfbuzz 8.0.0

Modified Paths:
--------------
    trunk/Build/source/libs/README
    trunk/Build/source/libs/harfbuzz/ChangeLog
    trunk/Build/source/libs/harfbuzz/Makefile.am
    trunk/Build/source/libs/harfbuzz/Makefile.in
    trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
    trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
    trunk/Build/source/libs/harfbuzz/configure
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/README
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.python.md
    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/OT/Color/CBDT/CBDT.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/sbix/sbix.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorFormat3.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/CursivePosFormat1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkArray.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairSet.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/ValueFormat.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Ligature.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Sequence.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SubsetGlyph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/VarCompositeGlyph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/coord-setter.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf-helpers.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/classdef-graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/coverage-graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/serialize.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-config.cmake.in
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h
    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-deprecated.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-limits.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-multimap.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-cff-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
    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-gsubgpos.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table-v2subset.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.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-syllabic.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.rl
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-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-vorg-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.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.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-accelerator.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan-member-list.hh
    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-subset.h
    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/main.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-get-alternates.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc
    trunk/Build/source/libs/harfbuzz/version.ac

Added Paths:
-----------
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-blob.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-buffer.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-face.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-font.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-shape.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc

Removed Paths:
-------------
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh

Modified: trunk/Build/source/libs/README
===================================================================
--- trunk/Build/source/libs/README	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/README	2023-07-09 05:55:34 UTC (rev 67588)
@@ -25,8 +25,8 @@
   http://sourceforge.net/projects/silgraphite/files/graphite2/
   (requires C++11)
 
-harfbuzz 7.3.0 - checked 10may23
-  https://github.com/harfbuzz/harfbuzz/releases/tag/7.3.0
+harfbuzz 8.0.0 - checked 09jul23
+  https://github.com/harfbuzz/harfbuzz/releases/tag/8.0.0
 
 icu 72.1 - checked 07jan23
   https://github.com/unicode-org/icu/releases/

Modified: trunk/Build/source/libs/harfbuzz/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/ChangeLog	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/ChangeLog	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,3 +1,8 @@
+2023-07-09  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
+
+	Import harfbuzz-8.0.0.
+	* version.ac, Makefile.am: Adjusted.
+
 2023-05-10  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
 
 	Import harfbuzz-7.3.0.

Modified: trunk/Build/source/libs/harfbuzz/Makefile.am
===================================================================
--- trunk/Build/source/libs/harfbuzz/Makefile.am	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/Makefile.am	2023-07-09 05:55:34 UTC (rev 67588)
@@ -138,11 +138,10 @@
 	@HARFBUZZ_TREE@/src/hb-subset-cff-common.cc \
 	@HARFBUZZ_TREE@/src/hb-subset-cff-common.hh \
 	@HARFBUZZ_TREE@/src/hb-subset-cff1.cc \
-	@HARFBUZZ_TREE@/src/hb-subset-cff1.hh \
 	@HARFBUZZ_TREE@/src/hb-subset-cff2.cc \
-	@HARFBUZZ_TREE@/src/hb-subset-cff2.hh \
 	@HARFBUZZ_TREE@/src/hb-subset-input.hh \
 	@HARFBUZZ_TREE@/src/hb-subset-instancer-solver.cc \
+	@HARFBUZZ_TREE@/src/hb-subset-instancer-solver.hh \
 	@HARFBUZZ_TREE@/src/hb-subset.hh \
 	@HARFBUZZ_TREE@/src/hb-ucd-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ucd.cc \

Modified: trunk/Build/source/libs/harfbuzz/Makefile.in
===================================================================
--- trunk/Build/source/libs/harfbuzz/Makefile.in	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/Makefile.in	2023-07-09 05:55:34 UTC (rev 67588)
@@ -822,11 +822,10 @@
 	@HARFBUZZ_TREE@/src/hb-subset-cff-common.cc \
 	@HARFBUZZ_TREE@/src/hb-subset-cff-common.hh \
 	@HARFBUZZ_TREE@/src/hb-subset-cff1.cc \
-	@HARFBUZZ_TREE@/src/hb-subset-cff1.hh \
 	@HARFBUZZ_TREE@/src/hb-subset-cff2.cc \
-	@HARFBUZZ_TREE@/src/hb-subset-cff2.hh \
 	@HARFBUZZ_TREE@/src/hb-subset-input.hh \
 	@HARFBUZZ_TREE@/src/hb-subset-instancer-solver.cc \
+	@HARFBUZZ_TREE@/src/hb-subset-instancer-solver.hh \
 	@HARFBUZZ_TREE@/src/hb-subset.hh \
 	@HARFBUZZ_TREE@/src/hb-ucd-table.hh \
 	@HARFBUZZ_TREE@/src/hb-ucd.cc \

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,3 +1,8 @@
+2023-07-09  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
+
+	Imported harfbuzz-8.0.0 source tree from:
+	https://github.com/harfbuzz/harfbuzz/releases/download/8.0.0/
+
 2023-05-10  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
 
 	Imported harfbuzz-7.3.0 source tree from:

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,5 +1,5 @@
-Changes applied to the harfbuzz-7.3.0/ tree as obtained from:
-	https://github.com/harfbuzz/harfbuzz/releases/download/7.3.0/
+Changes applied to the harfbuzz-8.0.0/ tree as obtained from:
+	https://github.com/harfbuzz/harfbuzz/releases/download/8.0.0/
 
 Removed:
 	COPYING

Modified: trunk/Build/source/libs/harfbuzz/configure
===================================================================
--- trunk/Build/source/libs/harfbuzz/configure	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/configure	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for harfbuzz (TeX Live) 7.3.0.
+# Generated by GNU Autoconf 2.71 for harfbuzz (TeX Live) 8.0.0.
 #
 # Report bugs to <tex-k at tug.org>.
 #
@@ -611,8 +611,8 @@
 # Identity of this package.
 PACKAGE_NAME='harfbuzz (TeX Live)'
 PACKAGE_TARNAME='harfbuzz--tex-live-'
-PACKAGE_VERSION='7.3.0'
-PACKAGE_STRING='harfbuzz (TeX Live) 7.3.0'
+PACKAGE_VERSION='8.0.0'
+PACKAGE_STRING='harfbuzz (TeX Live) 8.0.0'
 PACKAGE_BUGREPORT='tex-k at tug.org'
 PACKAGE_URL=''
 
@@ -1346,7 +1346,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) 7.3.0 to adapt to many kinds of systems.
+\`configure' configures harfbuzz (TeX Live) 8.0.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1418,7 +1418,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of harfbuzz (TeX Live) 7.3.0:";;
+     short | recursive ) echo "Configuration of harfbuzz (TeX Live) 8.0.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1523,7 +1523,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-harfbuzz (TeX Live) configure 7.3.0
+harfbuzz (TeX Live) configure 8.0.0
 generated by GNU Autoconf 2.71
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2064,7 +2064,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 7.3.0, which was
+It was created by harfbuzz (TeX Live) $as_me 8.0.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -4823,7 +4823,7 @@
 
 # Define the identity of the package.
  PACKAGE='harfbuzz--tex-live-'
- VERSION='7.3.0'
+ VERSION='8.0.0'
 
 
 # Some tools Automake needs.
@@ -5033,10 +5033,10 @@
 
 
 
-HB_VERSION_MAJOR=7
-HB_VERSION_MINOR=3
+HB_VERSION_MAJOR=8
+HB_VERSION_MINOR=0
 HB_VERSION_MICRO=0
-HB_VERSION=7.3.0
+HB_VERSION=8.0.0
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -8817,7 +8817,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 7.3.0, which was
+This file was extended by harfbuzz (TeX Live) $as_me 8.0.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -8885,7 +8885,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-harfbuzz (TeX Live) config.status 7.3.0
+harfbuzz (TeX Live) config.status 8.0.0
 configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,3 +1,5275 @@
+commit b4305532a7746422e0b615eee6304119c1092fd8
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sun Jul 9 02:54:30 2023 +0300
+
+    8.0.0
+
+ NEWS                   | 42 ++++++++++++++++++++++++++++++++++++++++++
+ configure.ac           |  2 +-
+ docs/harfbuzz-docs.xml |  1 +
+ meson.build            |  2 +-
+ src/hb-common.h        |  2 +-
+ src/hb-ot-layout.cc    |  8 ++++----
+ src/hb-version.h       |  6 +++---
+ 7 files changed, 53 insertions(+), 10 deletions(-)
+
+commit 5b8ba51251b8d1603c792366b7062de836bb525c
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sun Jul 9 02:50:45 2023 +0300
+
+    [doc] Fix warning about missing hb-gobject section
+    
+    We don’t build hb-gobject docs anymore, lets not bother gtk-doc with it.
+
+ src/hb-gobject-structs.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0ed946c379f1fe90c855f37dd31e5377beae4946
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sun Jul 9 03:01:47 2023 +0300
+
+    [wasm] Fix warning
+    
+    In file included from src/harfbuzz.cc:62:
+    src/hb-wasm-shape.cc:27:9: warning: 'HB_DEBUG_WASM' macro redefined [-Wmacro-redefined]
+            ^
+    src/hb-debug.hh:393:9: note: previous definition is here
+            ^
+    1 warning generated.
+
+ src/hb-wasm-shape.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit afe0910295f0b5bd245d68d5b142bcc9319b87ee
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sun Jul 9 02:45:52 2023 +0300
+
+    [font] Actually deprecate get_glyph_shape()
+    
+    We previously marked it as deprecated in the documentation but didn’t
+    actually deprecate it in code. Now the only known users have migrated to
+    draw_glyph(), lets deprecate o=it for good.
+
+ docs/harfbuzz-sections.txt |  6 +++---
+ src/hb-deprecated.h        | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-font.cc             |  4 ++++
+ src/hb-font.h              | 45 +--------------------------------------------
+ src/main.cc                |  4 ++--
+ test/api/test-ot-face.c    |  2 +-
+ 6 files changed, 57 insertions(+), 50 deletions(-)
+
+commit c6a01441d9ce638634f193dbc9aadd8c432de55b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 16:32:15 2023 -0600
+
+    [sanitize] Always-inline OffsetTo::sanitize()
+    
+    8% speed up in sanitizing Gulzar.
+
+ src/hb-open-type.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit f60dbd906a4bf89354af1ed0616a61a5099d8c1a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 16:21:24 2023 -0600
+
+    Fix thinko
+    
+    Fixes https://oss-fuzz.com/testcase-detail/4787105656864768
+
+ src/hb-open-type.hh                                        |   8 ++++----
+ ...uzz-testcase-minimized-hb-shape-fuzzer-4787105656864768 | Bin 0 -> 44 bytes
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+commit d84c5f29b71aa7b1ff2d09cf4dc2cf3fccc5659e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 15:22:51 2023 -0600
+
+    Revert "[gsubgpos] Make (Chain)Context funcs templatized"
+    
+    This reverts commit 03ac08d267eb7ad2f1ac039115fc0030ea475fae.
+
+ src/OT/Layout/GSUB/Ligature.hh                     | 13 +--
+ .../Layout/GSUB/ReverseChainSingleSubstFormat1.hh  |  8 +-
+ src/hb-ot-layout-gsubgpos.hh                       | 93 +++++++++-------------
+ 3 files changed, 47 insertions(+), 67 deletions(-)
+
+commit e73223b9e59a4f0af54880d3e26f8db55688f291
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 15:22:18 2023 -0600
+
+    [gsubgpos] Make (Chain)Context funcs templatized
+    
+    Unfortunately they still won't be inlined because the matcher_t
+    needs function pointers. So, no speed up.  Going to revert.
+
+ src/OT/Layout/GSUB/Ligature.hh                     | 13 ++-
+ .../Layout/GSUB/ReverseChainSingleSubstFormat1.hh  |  8 +-
+ src/hb-ot-layout-gsubgpos.hh                       | 93 +++++++++++++---------
+ 3 files changed, 67 insertions(+), 47 deletions(-)
+
+commit 3e3820badd9d72d908334a862d546bcb64ccfd30
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 14:36:23 2023 -0600
+
+    Simplify a few bool returns
+    
+    Unnecessary. Cast to bool does the job.
+
+ src/hb-ot-layout.hh | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 1c8d54deeff506d66e91ff84a8bd43698ec91387
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 14:28:07 2023 -0600
+
+    [shape] Another always-inline
+
+ src/hb-ot-layout-gsubgpos.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit df45067fbb14a62c2048bf1b01349bf17f90ee6d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 14:22:59 2023 -0600
+
+    [shape] More always-inline
+
+ src/hb-ot-layout-gsubgpos.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit c3a28be5094f23b0806f94c069ff3d888f065d48
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 14:20:45 2023 -0600
+
+    [shape] One more always-inline
+
+ src/hb-ot-layout-gsubgpos.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 728812348185194de87e5558a5770351d12447bf
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 14:14:27 2023 -0600
+
+    Allow overriding HB_ALWAYS_INLINE
+
+ src/hb.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 9fea19ebff62a4e9aa344e271d58acf416214d2a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 13:56:24 2023 -0600
+
+    [shape] Another always-inline
+
+ src/hb-ot-layout-gsubgpos.hh | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit 5b45c56c9ecae7a5d67d336219aab4d971573bab
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 13:47:41 2023 -0600
+
+    [shape] Always-inline more
+    
+    Another 10% speedup in BM_Shape Gulzar-Regular.
+
+ src/hb-ot-layout-gsubgpos.hh | 47 ++++++++++++++++++++++++++++++++------------
+ 1 file changed, 34 insertions(+), 13 deletions(-)
+
+commit bb9692e8a3b1a17481dae46c57e1727361f96e26
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 13:45:48 2023 -0600
+
+    [shape] Always-inline match_input
+    
+    10% speedup in BM_Shape Gulzar-Regular.
+
+ src/hb-ot-layout-gsubgpos.hh | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+commit 6c451054fbbee75ffc4a68e423786bf19648e315
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 12:55:34 2023 -0600
+
+    [sanitize] Sprinkle a few unlikely's
+
+ src/hb-ot-layout-gsubgpos.hh | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+commit 4ecc62c28d392a00d8f613da565fae335930a88d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 12:53:23 2023 -0600
+
+    [sanitize] Simplify ChainRule::sanitize again
+    
+    check_struct does the same now.
+
+ src/hb-ot-layout-gsubgpos.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 253ec08b3db433f07175f21f90555657a9ce55f3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 12:48:05 2023 -0600
+
+    [sanitize] Speed up check_struct on x64
+
+ src/hb-sanitize.hh | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+commit fb02f4a8975655b405ac4bc3f9982383f33ea6dc
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 8 12:29:18 2023 -0600
+
+    [sanitize] Micro-optimize ChainRule::sanitize
+
+ src/hb-ot-layout-gsubgpos.hh |  7 ++++---
+ src/hb-sanitize.hh           | 18 ++++++++++++++++++
+ 2 files changed, 22 insertions(+), 3 deletions(-)
+
+commit c650858c639764717f3d7276ad67bd5bf55aaedc
+Author: Khaled Hosny <khaled at libreoffice.org>
+Date:   Sat Jul 8 13:57:05 2023 +0300
+
+    [graphite] Fix cluster advance width
+    
+    Based on https://github.com/harfbuzz/harfbuzz/issues/4309#issuecomment-1624730406
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/4309
+
+ src/hb-graphite2.cc        | 5 +++--
+ src/wasm/graphite/shape.cc | 5 +++--
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+commit 73ee9c346f3acccbe14a4caf258b636de7c459be
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 22:47:20 2023 -0600
+
+    Revert "[sanitize] Only check trailing edge of ranges"
+    
+    This reverts commit e4856cf8098b9741a910e7f7979096cf11d8fead.
+    
+    This is wrong on at least 32-bit systems. Might add a condition
+    version later.
+
+ src/hb-sanitize.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 0b879afb5abda0af4624dd2cedf609acb4d17c87
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 22:35:43 2023 -0600
+
+    [sanitize] Inline Coverage::sanitize
+
+ src/OT/Layout/Common/Coverage.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 92448910a76e399afce6375923dbcf36bc3a541e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 22:16:24 2023 -0600
+
+    [sanitize] Minor inline a few more short functions
+
+ src/hb-open-type.hh | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+commit d84504206c420250bfe80bee25f6a59a7177c9eb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 21:56:17 2023 -0600
+
+    [sanitize] Optimize away an overflow check when not needed
+    
+    When the length argument is 16bit...
+
+ src/hb-open-type.hh |  8 ++++----
+ src/hb-sanitize.hh  | 14 ++++++++++++++
+ 2 files changed, 18 insertions(+), 4 deletions(-)
+
+commit e4856cf8098b9741a910e7f7979096cf11d8fead
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 21:21:33 2023 -0600
+
+    [sanitize] Only check trailing edge of ranges
+    
+    Assumptions...
+    
+    Speeds up Gulzar load_face_and_shape benchmark by 7%.
+
+ src/hb-sanitize.hh | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 6a683ea6ebc4d187d3f9ccf1a5c087b30cd82f27
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 21:02:15 2023 -0600
+
+    [sanitize] Enlighten check_range() some more
+    
+    No need to check for len=0 arrays. They must still be in range.
+
+ src/hb-ot-var-fvar-table.hh | 3 ++-
+ src/hb-sanitize.hh          | 7 +++----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit c24ea1036b45ea48ecc3081698ec04be646b74d0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 20:43:20 2023 -0600
+
+    [sanitize] Minor tweak to len=0 case which is handled otherwise anyway
+
+ src/hb-sanitize.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 403bc7caa41474644b4a7c14046c70ec8013c385
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 20:17:32 2023 -0600
+
+    [sanitize] Simplify Rule::sanitize()
+
+ src/hb-ot-layout-gsubgpos.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 385896ff665a167ffcc633ebf84280549d9f5b2e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 19:56:19 2023 -0600
+
+    [sanitize] Speed up ChainRule::sanitize()
+    
+    10% speedup in sanitizing Gulzar-Regular.
+
+ src/hb-ot-layout-gsubgpos.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 2006d3211f300b1f602d9701f4b26634fe6f21b7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 17:07:11 2023 -0600
+
+    [sanitize] Add "fastpath" for ArrayOfOffset16To<> objects with max size
+    
+    Unfortunately this doesn't speed up NotoNastaliq or Gulzar as I was
+    hoping for. Their GSUB tables are not large enough for this to kick
+    in...
+
+ src/OT/Layout/GSUB/Ligature.hh |  1 +
+ src/hb-machinery.hh            |  4 ++++
+ src/hb-null.hh                 |  9 +++++++++
+ src/hb-open-type.hh            | 25 +++++++++++++++++++++++++
+ src/hb-ot-layout-gsubgpos.hh   |  2 ++
+ 5 files changed, 41 insertions(+)
+
+commit 7a85663c2bd9a0e553bf6c02ca92f7c645bed915
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 19:21:18 2023 -0600
+
+    Revert "[sanitize] Add "fastpath" for ArrayOfOffset16To<> objects with max size"
+    
+    This reverts commit 10f8556c73f3cf231c6b5a900a6a1903f9516f90.
+    
+    This was, unfortunately, wrong :(.
+
+ src/OT/Layout/GSUB/Ligature.hh |  5 +----
+ src/hb-machinery.hh            |  4 ----
+ src/hb-null.hh                 |  9 ---------
+ src/hb-open-type.hh            | 25 -------------------------
+ src/hb-ot-layout-gsubgpos.hh   | 12 ++----------
+ 5 files changed, 3 insertions(+), 52 deletions(-)
+
+commit f2a3680fab317a67416c267ea8fc51cc7206b3f0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 19:21:03 2023 -0600
+
+    Revert "[gsubgpos] Limit (Chain)ContextFormat3 for consistency"
+    
+    This reverts commit 90b48917dadbef51bc5e90904d0f81e81199b9e2.
+
+ src/hb-ot-layout-gsubgpos.hh | 32 +++++++++++++-------------------
+ 1 file changed, 13 insertions(+), 19 deletions(-)
+
+commit 90b48917dadbef51bc5e90904d0f81e81199b9e2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 18:50:01 2023 -0600
+
+    [gsubgpos] Limit (Chain)ContextFormat3 for consistency
+
+ src/hb-ot-layout-gsubgpos.hh | 32 +++++++++++++++++++-------------
+ 1 file changed, 19 insertions(+), 13 deletions(-)
+
+commit 3b02f694e80dd3c1b0517145ef7b075c9c9acb05
+Merge: 10f8556c7 68b789145
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 18:39:28 2023 -0600
+
+    [sanitize/GSUBGPOS] Limit max-size of a few offset arrays
+    
+    This significantly speeds up Gulzar-Regular sanitize, by 40%.
+
+commit 10f8556c73f3cf231c6b5a900a6a1903f9516f90
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 17:07:11 2023 -0600
+
+    [sanitize] Add "fastpath" for ArrayOfOffset16To<> objects with max size
+
+ src/OT/Layout/GSUB/Ligature.hh |  5 ++++-
+ src/hb-machinery.hh            |  4 ++++
+ src/hb-null.hh                 |  9 +++++++++
+ src/hb-open-type.hh            | 25 +++++++++++++++++++++++++
+ src/hb-ot-layout-gsubgpos.hh   | 12 ++++++++++--
+ 5 files changed, 52 insertions(+), 3 deletions(-)
+
+commit 68b78914595347008eb344859699dc62257a7a67
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 17:07:11 2023 -0600
+
+    [sanitize] Add "fastpath" for ArrayOfOffset16To<> objects with max size
+    
+    Unfortunately this doesn't speed up NotoNastaliq or Gulzar as I was
+    hoping for. Their GSUB tables are not large enough for this to kick
+    in...
+
+ src/OT/Layout/GSUB/Ligature.hh |  1 +
+ src/hb-machinery.hh            |  4 ++++
+ src/hb-null.hh                 |  9 +++++++++
+ src/hb-open-type.hh            | 25 +++++++++++++++++++++++++
+ src/hb-ot-layout-gsubgpos.hh   |  2 ++
+ 5 files changed, 41 insertions(+)
+
+commit 90752cd5b76d1768afc10e9bcab4235d97e7686f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 15:47:28 2023 -0600
+
+    [type] Add HeadlessArray16Of
+
+ src/OT/Layout/GSUB/Ligature.hh | 2 +-
+ src/hb-open-type.hh            | 3 ++-
+ src/hb-ot-layout-gsubgpos.hh   | 2 +-
+ 3 files changed, 4 insertions(+), 3 deletions(-)
+
+commit 59abcda269e7148131d00d17218f5718f217bf13
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jul 7 14:27:18 2023 -0600
+
+    [sanitize] Add an ALWAYS_INLINE
+    
+    Looks like it was always inlined anyway.
+
+ src/hb-sanitize.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 45a17212304de8787b509cc9375bb92571fca9f5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jul 6 16:06:50 2023 -0600
+
+    [ot-font] Prefer CFF2 over CFF1
+
+ src/hb-ot-font.cc | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 43d0aff672981f2efca6b7398e81f020676ad442
+Author: أحمد المحمودي <96682+aelmahmoudy at users.noreply.github.com>
+Date:   Tue Jul 4 09:22:53 2023 +0300
+
+    [introspection] Pass both libharfbuzz_gobject & libharfbuzz as positional parameters
+    
+    Fixes #4304
+
+ src/meson.build | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 25297408de73f8bf31ebecd241f959455ed00e95
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jul 3 10:34:26 2023 -0600
+
+    [COLR] Fix PaintComposite sanitize timeout
+    
+    Was timing out after recent sanitize() change.
+    
+    Fixes https://oss-fuzz.com/testcase-detail/5692635449524224
+
+ src/OT/Color/COLR/COLR.hh                                 |   1 +
+ ...uzz-testcase-minimized-hb-draw-fuzzer-5692635449524224 | Bin 0 -> 185 bytes
+ 2 files changed, 1 insertion(+)
+
+commit a8c655e6510c33de2241b854c1a37ffbe2eee9ff
+Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
+Date:   Mon Jul 3 10:17:36 2023 +0000
+
+    Bump actions/checkout from 3.5.1 to 3.5.3
+    
+    Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.1 to 3.5.3.
+    - [Release notes](https://github.com/actions/checkout/releases)
+    - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
+    - [Commits](https://github.com/actions/checkout/compare/v3.5.1...c85c95e3d7251135ab7dc9ce3241c5835cc595a9)
+    
+    ---
+    updated-dependencies:
+    - dependency-name: actions/checkout
+      dependency-type: direct:production
+      update-type: version-update:semver-patch
+    ...
+    
+    Signed-off-by: dependabot[bot] <support at github.com>
+
+ .github/workflows/scorecard.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit de2c10732df151156ac55afdf648f3fd296dfa50
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 16:44:48 2023 -0600
+
+    [ot-map] Speed up for default shaper
+    
+    Sort late, the reduced number of features.
+
+ src/hb-ot-map.cc   | 6 ++++--
+ src/hb-ot-map.hh   | 8 ++++++++
+ src/hb-ot-shape.cc | 7 +++++++
+ 3 files changed, 19 insertions(+), 2 deletions(-)
+
+commit 8156c5a6856a3c9c0cc98714dc047fe4a703d603
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 16:35:32 2023 -0600
+
+    [ot-map] Minor micro-optimize
+
+ src/hb-ot-map.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 5ac9eaa035402fe0369baadea3c945c58a4534ed
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 16:18:08 2023 -0600
+
+    [sanitize] Minor micro-optimize
+
+ src/hb-sanitize.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e8948d634e1835f379053d9b924b834137967b86
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 15:35:18 2023 -0600
+
+    [set-digest] Micro-optimize more
+
+ src/hb-set-digest.hh | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+commit cb73ba710480f698828b8d6526605849d6899bad
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 15:27:26 2023 -0600
+
+    [set-digest] Fixup for previous commit
+
+ src/hb-set-digest.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 918ad8929403d2106fdca1370a1c3e9929e301f9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 14:54:24 2023 -0600
+
+    [set-digest] Early terminate add_range() if we're full
+
+ src/hb-set-digest.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit bb33675e60be3884a3d6adf6417c353f0202e70f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 14:11:40 2023 -0600
+
+    [sanitize] Micro-optimize check_range()
+
+ src/hb-sanitize.hh | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+commit d1c82a1cc68667ff8ca6c1fe2b4fa277504c0a5c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 13:38:22 2023 -0600
+
+    [sanitize] Speed up check_struct()
+    
+    Don't account for length here. Should not be a problem.
+    Fingers crossed fuzzers.
+    
+    18% speed up in load_face_and_shape Gulzar-Regular.
+
+ src/hb-sanitize.hh | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+commit ec943866229b44b26b79cd271a1e3f874fe16e7c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 13:29:53 2023 -0600
+
+    [OffsetTo] Micro-optimize away a check
+
+ src/hb-open-type.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit eae8278896e1dcd6d8eecb9401785acdf76f81a6
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 13:07:26 2023 -0600
+
+    [GPOS] Micro-optimize lazy_some_gpos check
+    
+    Speeds up 11% in:
+    BM_Font/load_face_and_shape/Roboto-Regular.ttf/hb
+
+ src/OT/Layout/GPOS/PairPosFormat2.hh | 5 +++--
+ src/OT/Layout/GPOS/PairSet.hh        | 5 +++--
+ src/OT/Layout/GPOS/ValueFormat.hh    | 6 +++---
+ 3 files changed, 9 insertions(+), 7 deletions(-)
+
+commit 46e54a23907eb5f46977ceac22abb4d43fcd7061
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 13:03:16 2023 -0600
+
+    [GPOS] Remove extra check
+
+ src/OT/Layout/GPOS/ValueFormat.hh | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit 13438da16e5967b2600cb347ad5a179812526ba2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 12:56:13 2023 -0600
+
+    [benchmark-font] Minor move a variable
+
+ perf/benchmark-font.cc | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 7f5380fe949ba64fab19d86f670e2215249cbb96
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 12:19:22 2023 -0600
+
+    [Composite] Don't apply transformation if phantom_only
+
+ src/OT/glyf/Glyph.hh | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+commit 0cf759b0d4c8c1252347f2d92dd10202672d4191
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 12:15:43 2023 -0600
+
+    [Glyph] Don't shift anchored Composite if phantom_only
+    
+    Fixes https://oss-fuzz.com/testcase-detail/5114131137822720
+
+ src/OT/glyf/Glyph.hh                                     |   2 +-
+ ...z-testcase-minimized-hb-shape-fuzzer-5114131137822720 | Bin 0 -> 5119 bytes
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 645bde473818a14368ea9f95261037160c574d05
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 12:07:22 2023 -0600
+
+    [Glyph] Pass phantom-only to gvar only for SIMPLE glyphs
+    
+    For Composites we need to get the translation offset deltas.
+
+ src/OT/glyf/Glyph.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e92eefaabbed7aa04fe98214ae43b061d1497735
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 11:35:51 2023 -0600
+
+    [gvar] Cache two values in shared_tuple_active_idx
+    
+    Speeds up varc-hangul.ttf draw_glyph by 10%.
+
+ src/hb-ot-var-common.hh     | 17 ++++++++++++-----
+ src/hb-ot-var-gvar-table.hh | 15 +++++++++------
+ 2 files changed, 21 insertions(+), 11 deletions(-)
+
+commit 7d72fdd5bf423dcbdf19b5bae25494e6b3c59cd0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jul 2 09:55:37 2023 -0600
+
+    [benchmark-font] Do some work in draw_glyph callbacks
+    
+    For no good reason other than matching what I'm adding to
+    skrifa benchmark.  Doesn't seem to affect benchmarks whatsoever.
+
+ perf/benchmark-font.cc | 33 +++++++++++++++++++++++++++------
+ 1 file changed, 27 insertions(+), 6 deletions(-)
+
+commit 47b5ee6789ca9125cc4299da1f3a3c05300dff78
+Merge: 7a3566825 2d6091fc4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jul 1 14:48:39 2023 -0400
+
+    Merge pull request #4306 from harfbuzz/gpos-lazy-device
+    
+    GPOS lazy Device
+
+commit 2d6091fc42c81ba68fe6710de42d313cfda7a309
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 30 11:48:56 2023 -0600
+
+    [GPOS] Make AnchorMatrix sanitize lazy again
+    
+    Was reverted in the previous commit, because it was incomplete.
+
+ src/OT/Layout/GPOS/AnchorFormat3.hh |  3 ---
+ src/OT/Layout/GPOS/AnchorMatrix.hh  | 14 ++++++++++----
+ src/OT/Layout/GPOS/MarkArray.hh     |  2 +-
+ src/OT/Layout/GPOS/ValueFormat.hh   |  6 +++---
+ src/hb-ot-layout-gsubgpos.hh        |  2 +-
+ src/hb-sanitize.hh                  |  4 ++--
+ 6 files changed, 17 insertions(+), 14 deletions(-)
+
+commit 0887382cdf64f9c590eb9c086f7f5622c482e32c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 30 11:39:46 2023 -0600
+
+    [GPOS] Fix sanitize
+
+ src/OT/Layout/GPOS/AnchorMatrix.hh | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit 83eb744e09bb8ff7a9c78c79569100f560f129fb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 30 11:33:39 2023 -0600
+
+    [sanizie] Inline check_range if not OPTIMIZE_SIZE
+    
+    BM_Font/load_face_and_shape/NotoNastaliqUrdu-Regular.ttf/hb                     -0.1046         -0.1051           194           173           193           172
+    BM_Font/load_face_and_shape/NotoSerifMyanmar-Regular.otf/hb                     -0.2401         -0.2412            36            27            36            27
+
+ src/hb-sanitize.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 690af7aa69b05db6a925bcdaeac4ea0d7efba5da
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 30 10:36:01 2023 -0600
+
+    [GPOS] Sanitize Device tables lazily
+    
+    This speeds up face loading for variable fonts by 80%!
+    
+    Comparing before to after
+    Benchmark                                                                          Time             CPU      Time Old      Time New       CPU Old       CPU New
+    ---------------------------------------------------------------------------------------------------------------------------------------------------------------
+    BM_Font/load_face_and_shape/Roboto-Regular.ttf/hb                               -0.0368         -0.0366            20            20            20            19
+    BM_Font/load_face_and_shape/RobotoFlex-Variable.ttf/hb                          -0.7149         -0.7162            77            22            77            22
+    BM_Font/load_face_and_shape/RobotoFlex-Variable.ttf/var/hb                      -0.7241         -0.7255            80            22            79            22
+    BM_Font/load_face_and_shape/SourceSansPro-Regular.otf/hb                        -0.1441         -0.1445            28            24            28            24
+    BM_Font/load_face_and_shape/AdobeVFPrototype.otf/hb                             -0.7893         -0.7910            66            14            66            14
+    BM_Font/load_face_and_shape/AdobeVFPrototype.otf/var/hb                         -0.7865         -0.7882            67            14            66            14
+    BM_Font/load_face_and_shape/SourceSerifVariable-Roman.ttf/hb                    -0.8895         -0.8900           227            25           226            25
+    BM_Font/load_face_and_shape/SourceSerifVariable-Roman.ttf/var/hb                -0.8895         -0.8900           226            25           225            25
+    BM_Font/load_face_and_shape/Comfortaa-Regular-new.ttf/hb                        -0.5512         -0.5531            42            19            42            19
+    BM_Font/load_face_and_shape/NotoNastaliqUrdu-Regular.ttf/hb                     -0.1511         -0.1510           227           192           225           191
+    BM_Font/load_face_and_shape/NotoSerifMyanmar-Regular.otf/hb                     -0.1494         -0.1498            41            35            40            34
+    OVERALL_GEOMEAN                                                                 -0.6443         -0.6456             0             0             0             0
+
+ src/OT/Layout/GPOS/AnchorFormat3.hh    | 11 +++++--
+ src/OT/Layout/GPOS/AnchorMatrix.hh     |  4 +++
+ src/OT/Layout/GPOS/SinglePosFormat1.hh |  3 +-
+ src/OT/Layout/GPOS/SinglePosFormat2.hh |  3 +-
+ src/OT/Layout/GPOS/ValueFormat.hh      | 52 +++++++++++++++++++++++++---------
+ src/hb-kern.hh                         |  2 +-
+ src/hb-ot-layout-gsubgpos.hh           | 12 ++++++--
+ src/hb-ot-layout.cc                    |  5 ++--
+ src/hb-ot-shaper-arabic-fallback.hh    |  2 +-
+ src/hb-sanitize.hh                     | 18 +++++++++++-
+ 10 files changed, 87 insertions(+), 25 deletions(-)
+
+commit 7a35668258f8e93c867cf560ca0999d8952d1c93
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 30 10:50:25 2023 -0600
+
+    Minor variable fix
+
+ src/hb-machinery.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d338506ccf892b0ce489314d2d2f94c6b875368a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 30 10:13:05 2023 -0600
+
+    [GPOS] Reuse sanitize_values_stride_unsafe in another function
+
+ src/OT/Layout/GPOS/ValueFormat.hh | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+commit 0fceaef0f7ec123e931fc31f9d71ba87fa60b079
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 30 08:50:49 2023 -0600
+
+    [benchmark-subset] Report in microseconds, not milli
+    
+    We're in that range now. :)
+
+ perf/benchmark-subset.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 547dc1a40ef6d83eb426afd1470bddf2b11bdfab
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 30 08:48:43 2023 -0600
+
+    [benchmark-font] Add load_face_and_shape benchmark
+    
+    To measure face-loading performance
+
+ perf/benchmark-font.cc | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+commit fcf70af1349f2eeb9f58f67d2cc7d8e2c3ebf012
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 30 08:43:10 2023 -0600
+
+    [perf] Fix break
+
+ perf/benchmark-font.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 794fac327cf13b4b4d8a66281c15df6aac2d15c6
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 20:55:52 2023 -0600
+
+    [glyf] Minor another range for loop
+
+ src/OT/glyf/glyf.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0ae167662657c084ecc26db27830b51c469240f2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 20:38:42 2023 -0600
+
+    [CompositeGlyph] Minor use a range for loop
+
+ src/OT/glyf/CompositeGlyph.hh | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+commit 05c01ad5d34cf6ca4f350233eccbec129f860231
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 16:49:20 2023 -0600
+
+    [SimpleGlyph] Minor use a range for loop
+
+ src/OT/glyf/SimpleGlyph.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 4123e0c75762ed1e6fa69e2926a4d4cee5e6747c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 16:27:35 2023 -0600
+
+    [path-builder] Speed up mid-point calculation
+
+ src/OT/glyf/path-builder.hh | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 73376b24cfe7cfe27b7b4b9abbe46ff441189b2a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 16:14:45 2023 -0600
+
+    [subset/cff1] More error handling
+
+ src/hb-subset-cff1.cc | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit cc44b3bce0a7be5536df7df910b5bc73a5e4a741
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 16:12:10 2023 -0600
+
+    [subset/cff1] Handle an error condition
+    
+    Fixes https://oss-fuzz.com/testcase-detail/5191907895279616
+
+ src/hb-subset-cff1.cc                                    |  11 +++++++----
+ ...-testcase-minimized-hb-subset-fuzzer-5191907895279616 | Bin 0 -> 2025 bytes
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+commit fc38c01ab06ac376b42b8d70c9453da45afabcc5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 15:29:15 2023 -0600
+
+    Minor inline a function
+
+ src/hb-ot-var-gvar-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit a520177e523eab8bf9a407aab46d8308ac12439a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 14:56:05 2023 -0600
+
+    [gvar] Remove unnecessary initialization
+
+ src/hb-ot-var-gvar-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit ca44c38c5298e9ffc9b0b843c3fd5df63c9747a7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 14:41:21 2023 -0600
+
+    Add HB_ALWAYS_INLINE
+    
+    With MSVC implementation as well.
+
+ src/OT/glyf/glyf.hh         |  2 +-
+ src/OT/glyf/path-builder.hh |  2 +-
+ src/hb-draw.hh              | 20 ++++++++++----------
+ src/hb.hh                   |  6 ++++++
+ 4 files changed, 18 insertions(+), 12 deletions(-)
+
+commit 0a00dc0c7197b61b7662d40d12e9432f27dbd6ec
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 14:17:47 2023 -0600
+
+    [draw] Add a few unlikely's
+
+ src/hb-draw.hh | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 2d9c3da06ad63066a748be486c33bed81f418868
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 13:31:11 2023 -0600
+
+    [draw] Inline more functions
+
+ src/hb-draw.hh | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+commit 17f29c81110bed6b9be684b6c0cfdacb01414bb1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 13:27:09 2023 -0600
+
+    [benchmark_font/draw_glyphs] Implement quadratic_to
+    
+    Not interested in the fallback implementation here.
+
+ perf/benchmark-font.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit d26b3adebee059cbcc72850f4ad31ecf3f2b913f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 13:25:52 2023 -0600
+
+    [draw-session] Inline small functions
+
+ src/hb-draw.hh | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit 7aba1e6dd2f5be40e818838ef23d0a0d605a8485
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 12:44:34 2023 -0600
+
+    [cache] Minor use a range for loop
+
+ src/hb-cache.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit afae537c3ca4d2ddae2b8bee400966a08bf74e6e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 12:42:44 2023 -0600
+
+    [cache] Minor remove .init()
+    
+    Use constructor.
+
+ src/hb-cache.hh   | 4 +---
+ src/hb-ft.cc      | 2 +-
+ src/hb-ot-font.cc | 6 +++---
+ 3 files changed, 5 insertions(+), 7 deletions(-)
+
+commit c49ca371151ef3afc3a4ecf0b8918cdd8ac16541
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 12:38:45 2023 -0600
+
+    [Glyph] Minor micro-optimize away a function call
+    
+    For when coords are not set.
+
+ src/OT/glyf/Glyph.hh        | 9 +++++----
+ src/hb-ot-var-gvar-table.hh | 2 --
+ 2 files changed, 5 insertions(+), 6 deletions(-)
+
+commit 5fb7b02ac1212e9dfde920738285a2a58d19f9e1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 12:28:43 2023 -0600
+
+    [CompositeGlyph] Minor use range loop
+
+ src/OT/glyf/CompositeGlyph.hh | 19 ++++++++-----------
+ 1 file changed, 8 insertions(+), 11 deletions(-)
+
+commit 20b32b049bad64d802b33979372c8cdc5a0c4cb4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 12:08:11 2023 -0600
+
+    [SimpleGlyph] Micro-optimize phantom_only
+
+ src/OT/glyf/SimpleGlyph.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit d1660eaf32777c50400326d99211926e82ec2f35
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 11:59:03 2023 -0600
+
+    [subset/cff] Minor use HB_OPTIMIZE_SIZE_VAL
+
+ src/hb-ot-cff-common.hh | 96 +++++++++++++++++++++++++------------------------
+ 1 file changed, 49 insertions(+), 47 deletions(-)
+
+commit 04809ede8e5d9943be8a294acecdffe2f0be492f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 11:58:53 2023 -0600
+
+    [CompositeGlyph] Micro-optimize translate()
+
+ src/OT/glyf/CompositeGlyph.hh | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+commit 229db9735e3832ca81a751ec318ba396aeb89d85
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 11:54:10 2023 -0600
+
+    [CompositeGlyph] Minor use vector::push()
+
+ src/OT/glyf/CompositeGlyph.hh | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit 75101802a169b48a69a82f64e49169d810ded741
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 10:54:49 2023 -0600
+
+    [CompositeGlyph] Micro-optimize
+
+ src/OT/glyf/CompositeGlyph.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e9d74d6bb352a2ac01554f8bdea65c3acc2879b5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 10:53:52 2023 -0600
+
+    [SimpleGlyph] Minor add an unlikely to error condition
+
+ src/OT/glyf/SimpleGlyph.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6abca413aeb7be1342180aa945f54fd45cdea12f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 10:39:49 2023 -0600
+
+    [path-builder] Micro-optimize
+    
+    No need to initialize these when has_data=false.
+
+ src/OT/glyf/path-builder.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 5703c1c4ea5cc47120cba8f8b0f4fc1178f6efef
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 29 10:35:23 2023 -0600
+
+    [path-builder] Add a couple of unlikely's
+
+ src/OT/glyf/path-builder.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit f5eead04e63e6092fba494471b18016cabe50a15
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 28 15:07:15 2023 -0600
+
+    [glyf/gvar] Optimize getting variable phantom points
+    
+    Used when there's no HVAR table and get_h_advance().
+    
+    I see some 10% speedup with a SourceSerifVariable-Roman with
+    the HVAR table removed.
+
+ src/OT/glyf/Glyph.hh        |  3 ++-
+ src/hb-ot-var-gvar-table.hh | 30 +++++++++++++++++-------------
+ 2 files changed, 19 insertions(+), 14 deletions(-)
+
+commit e42d6df55e034b92979fb41db852c648114c18c0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 28 14:25:11 2023 -0600
+
+    [glyf] Minor refactor a couple of lines and micro-optimize
+
+ src/OT/glyf/glyf.hh | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+commit c31471d10e14ca66a1b668905fac2ab40941ea41
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 28 13:51:54 2023 -0600
+
+    [glyf] Micro-optimize
+
+ src/OT/glyf/glyf.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 83d75d5e9b32866e62e21ca155bb176b6d3fa81e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 28 13:35:24 2023 -0600
+
+    [glyf] always_inline consume_point
+    
+    7% speedup in:
+    BM_Font/draw_glyph/Roboto-Regular.ttf/hb
+
+ src/OT/glyf/path-builder.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 8795ccedd61ea26793d0912b5ee02fe9ae45c9aa
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 28 13:29:29 2023 -0600
+
+    Revert "[SimpleGlyph] Avoid branches in read_points"
+    
+    This reverts commit ba062c713e469f91f57f3c85990f721789ec7c2a.
+
+ src/OT/glyf/SimpleGlyph.hh | 21 ++++-----------------
+ 1 file changed, 4 insertions(+), 17 deletions(-)
+
+commit ba062c713e469f91f57f3c85990f721789ec7c2a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 28 13:24:37 2023 -0600
+
+    [SimpleGlyph] Avoid branches in read_points
+    
+    Calculate total bytes in read_flags and bounds-check once.
+    
+    This slows things down apparently, so going to revert.
+
+ src/OT/glyf/SimpleGlyph.hh | 21 +++++++++++++++++----
+ 1 file changed, 17 insertions(+), 4 deletions(-)
+
+commit 62f5ed461ea5fa4fd63631ddeb505ea16e2becb4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 28 12:02:52 2023 -0600
+
+    [subset/cff] Fix an infinite loop
+    
+    Fixes https://oss-fuzz.com/testcase-detail/5419002026131456
+
+ src/hb-ot-cff-common.hh                                  |   6 +++---
+ src/hb-subset-cff-common.cc                              |   3 ++-
+ ...-testcase-minimized-hb-subset-fuzzer-5419002026131456 | Bin 0 -> 1718 bytes
+ 3 files changed, 5 insertions(+), 4 deletions(-)
+
+commit 87b573615f5f521650a325d8eb29afc736d1c8cc
+Author: Chun-wei Fan <fanchunwei at src.gnome.org>
+Date:   Wed Jun 28 15:38:40 2023 +0800
+
+    README.python.md: Add some notes for Windows
+    
+    Note that the DLLs for HarfBuzz and its deps must be found %PATH% on Windows so
+    that pygobject is able to import and use HarfBuzz in Python scripts.
+    
+    Also note that for Visual Studio builds, it is recommended that Visual Studio
+    2019 or later is used for the build, possibly in regards with how the
+    preprocessor handles C++ code when running g-ir-scanner.
+
+ README.python.md | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit 10b9ca54e17379584bc7583b018268697f925dfd
+Author: أحمد المحمودي (Ahmed El-Mahmoudy) <aelmahmoudy at users.sourceforge.net>
+Date:   Wed Jun 28 07:46:33 2023 +0200
+
+    Fix typo: subtitution -> substitution
+
+ src/OT/Layout/GSUB/Sequence.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 73a82af1f4abe15f3e96074b5bf1a636c890c85f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 27 17:05:22 2023 -0600
+
+    [subset/cff] Remove stale wrong code
+    
+    With my recent rewrite of serialize_header, this seems to
+    work now.
+
+ src/hb-ot-cff-common.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 158eba66b32c4e61a95d33fdcf9107de84073475
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 27 16:22:54 2023 -0600
+
+    [subset/cff] Fix compiler error
+    
+    About variable with internal linkage with no definition.
+
+ src/hb-ot-cff-common.hh | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+commit b04721993f0501519af4835d074fdfa3700935d1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 27 16:07:54 2023 -0600
+
+    [subset/cff1] Micro-optimize code
+    
+    Let compiler see whether optional argument is present.
+
+ src/hb-ot-cff-common.hh | 8 ++++++--
+ src/hb-subset-cff1.cc   | 2 +-
+ src/hb-subset-cff2.cc   | 2 +-
+ 3 files changed, 8 insertions(+), 4 deletions(-)
+
+commit 1cabb65b0a8cb4db16b7616f48f245f3ace08bd3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 27 16:01:17 2023 -0600
+
+    [subset/cff] Micro-optimize CFFIndex::serialize_header
+    
+    Unfortunately hb_array_t::begin/end are faster than its _begin/_end.
+    As such, a range loop on array itself is faster than range loop on
+    pipeline starting with array. Rework code to loop on the array always.
+
+ src/hb-ot-cff-common.hh | 69 ++++++++++++++++++++++++++++++-------------------
+ src/hb-subset-cff1.cc   |  2 +-
+ 2 files changed, 43 insertions(+), 28 deletions(-)
+
+commit dfaf9cd54b06e5d4d2765abae2e09183c7765815
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 27 14:56:32 2023 -0600
+
+    [subset/cff1] Minor optimize
+
+ src/hb-subset-cff1.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 41f85d0179dd60ee49e3064213bd4bbf5edaec96
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 27 12:50:04 2023 -0600
+
+    [benchmark-font] Add RobotoFlex
+    
+    We didn't have a variable TTF before!
+
+ perf/benchmark-font.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 585c84268dedc94cd41edf932b86b2a28c014032
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 27 11:28:38 2023 -0600
+
+    [subset/cff1] Minor micro-optimize
+
+ src/hb-subset-cff1.cc | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit 00904503d865c56495a49a5cf4b8c313f959dd9c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 27 08:18:18 2023 -0600
+
+    [config] Graduate avar2 from boring-expansion
+
+ src/hb-config.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 3edd6cdcd55dabec87ed8da9ffed82b1c41e0720
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 27 06:56:00 2023 -0600
+
+    [vector] Minor micro-optimize shrink_vector
+    
+    The compiler seems to understand this pattern better.
+
+ src/hb-vector.hh | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+commit aed215639a89a7241fa5d647483326c0cad6f535
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 22:51:50 2023 -0600
+
+    [subset/cff1] Micro-optimize
+
+ src/hb-ot-cff1-table.hh | 4 ++--
+ src/hb-subset-cff1.cc   | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 40a1c08f4c7a74b71a7a832b86b94fe8f6aa06b3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 19:03:04 2023 -0600
+
+    [subset/cff1] Micro-optimize
+
+ src/hb-subset-cff1.cc | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit bd3e78770e166c9813031d4be76ecd23c39c0c8b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 18:55:39 2023 -0600
+
+    [subset/cff1] Reuse a function
+
+ src/hb-ot-cff1-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit ffd23d3a310caf400d9458e286adbbd4aadcbece
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 18:54:06 2023 -0600
+
+    [subset/cff1] Micro-optimize Charset serialization
+
+ src/hb-ot-cff1-table.hh | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+commit 452557cd18e8072b07e48464a0428fecf732f32c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 18:40:54 2023 -0600
+
+    Replace a free with hb_free
+    
+    Ouch.
+
+ src/OT/glyf/CompositeGlyph.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 1fc128f6095f4caa29cc1001cd87090b9f0dce80
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 18:34:27 2023 -0600
+
+    Replace a few memset/memcpy's with hb_ equivalents
+
+ src/OT/glyf/VarCompositeGlyph.hh |  2 +-
+ src/OT/name/name.hh              |  2 +-
+ src/hb-cairo-utils.cc            |  2 +-
+ src/hb-cairo.cc                  |  2 +-
+ src/hb-map.hh                    |  2 +-
+ src/hb-shape.cc                  |  2 +-
+ src/hb-vector.hh                 |  4 ++--
+ src/hb-wasm-api-buffer.hh        | 12 ++++++------
+ src/hb-wasm-api-face.hh          |  2 +-
+ src/hb-wasm-api-font.hh          |  6 +++---
+ src/hb-wasm-shape.cc             |  2 +-
+ 11 files changed, 19 insertions(+), 19 deletions(-)
+
+commit 2c359635dfb05a9f3a1ed4740203b9efae2379a8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 18:28:11 2023 -0600
+
+    [face-builder] Don't zero allocation
+    
+    We overwrite it.
+
+ src/hb-open-file.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 347b94481100d2eefc88c1e6bc71aa20dcb907bb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 18:09:40 2023 -0600
+
+    [null] Fix getting Crap(hb_bytes_t)
+    
+    Fixes https://oss-fuzz.com/testcase-detail/6187272924692480
+
+ src/hb-null.hh                                            |   6 +++---
+ ...z-testcase-minimized-hb-subset-fuzzer-6187272924692480 | Bin 0 -> 609 bytes
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 49c52fa95316042390bc07bc9fe9438b63cd3320
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 17:55:29 2023 -0600
+
+    [cmap] Don't zero a few allocations unnecessarily
+
+ src/hb-ot-cmap-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit e4b2d9c3f33be4e216d5ab6893e9899907f20680
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 17:52:37 2023 -0600
+
+    [pool] Don't clear unused memory
+
+ src/hb-pool.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6129702eb8a13eac75176772a61adfc63c185f34
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 17:34:54 2023 -0600
+
+    [subset/cff] Simplify some allocation embedding
+
+ src/hb-ot-cff1-table.hh | 18 +++++-------------
+ 1 file changed, 5 insertions(+), 13 deletions(-)
+
+commit 99db06b4d2fa420f46dceccd4c9a625d5325d8b3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 17:30:31 2023 -0600
+
+    [var] Simplify a couple of copy operations
+
+ src/hb-ot-var-common.hh | 20 +++++---------------
+ 1 file changed, 5 insertions(+), 15 deletions(-)
+
+commit 73bcd3f241aa641935235753492ddfebebf9373f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 17:24:40 2023 -0600
+
+    [var] Adjust a few allocations to not clean space
+    
+    Since we immediately copy.
+
+ src/hb-ot-var-common.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit b1e7e8ba2f6705efee8633c4a63513686308c891
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 17:19:45 2023 -0600
+
+    [algs] Fix return of hb_memset()
+
+ src/hb-algs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c2bab073916870f336ca0b4b658bf70aa99a401c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 16:34:53 2023 -0600
+
+    [subset/cff] Minor optimization
+
+ src/hb-ot-cff-common.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 570fb4df58fcaa58c82b363f4edb5d61f1d948fb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 16:26:12 2023 -0600
+
+    [subset/cff] Add a vector pre-alloc
+
+ src/hb-ot-cff-common.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit e447d394a60ee2878e16bc772d36c988c546caa6
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 16:02:41 2023 -0600
+
+    [subset/cff1] Micro-optimize
+
+ src/hb-subset-cff1.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 50499e9e4094825700fdfbf19d85bcd0cdbd506d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 15:32:27 2023 -0600
+
+    [subset/cff1] Minor use rvalues in a few vector push() places
+
+ src/hb-subset-cff1.cc | 13 +++----------
+ 1 file changed, 3 insertions(+), 10 deletions(-)
+
+commit e5b3d4b10588befb7a2e63f5a3137344356908b7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 14:24:38 2023 -0600
+
+    [subset/cff1] Minor use ?:
+
+ src/hb-subset-cff1.cc | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+commit 81e2db7cbcb87668c562329390a49d95a3a604bb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 14:17:44 2023 -0600
+
+    [subset/cff1] Speed up plan_subset_charset
+
+ src/hb-ot-cff-common.hh |  2 +-
+ src/hb-ot-cff1-table.hh |  7 ++++---
+ src/hb-subset-cff1.cc   | 13 ++++++++++++-
+ 3 files changed, 17 insertions(+), 5 deletions(-)
+
+commit d3f90a8ca709f3f1b61484f832303b644ddb8744
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 14:02:26 2023 -0600
+
+    [subset/cff] Use a typedef for glyph_to_sid_map_t
+
+ src/hb-ot-cff-common.hh     |  2 ++
+ src/hb-ot-cff1-table.hh     | 12 ++++++------
+ src/hb-subset-cff-common.hh |  4 ++--
+ src/hb-subset-cff1.cc       |  8 ++++----
+ 4 files changed, 14 insertions(+), 12 deletions(-)
+
+commit 6783701b4e4443ae0db754d74349f05244e4316b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 12:31:22 2023 -0600
+
+    [subset] Handle an error condition
+    
+    Fixes https://oss-fuzz.com/testcase-detail/6306810588692480
+
+ src/hb-subset-plan.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 7d3d157de8c4ba87246f3ccefaede95e0f4b0566
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 12:02:21 2023 -0600
+
+    [subset/cff] Speed up hb_plan_subset_cff_fdselect
+
+ src/hb-subset-cff-common.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit f79d961a319e57213e194421bede954c148cdfd7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 11:32:37 2023 -0600
+
+    [vector] Speedup push()
+
+ src/hb-subset-cff1.cc | 8 +-------
+ src/hb-vector.hh      | 5 ++---
+ 2 files changed, 3 insertions(+), 10 deletions(-)
+
+commit b4b80bcaeabdc2e3c08649a2d75c4af0c4fb72ae
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 11:29:32 2023 -0600
+
+    [subset/cff1] Speed up plan_subset_charset
+
+ src/hb-subset-cff1.cc | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit 7305ec47b1359ad791b1ae152d3c39aa19423715
+Merge: 4a628b236 3bdb8639e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 26 12:35:03 2023 -0400
+
+    Merge pull request #4300 from pnacht/scorecard-action
+    
+    Add Scorecard action
+
+commit 4a628b236f2adbc715d5f923143022c097c298d5
+Author: arch1t3cht <arch1t3cht at gmail.com>
+Date:   Mon Jun 26 15:19:29 2023 +0200
+
+    [meson] Remove incorrect option for ICU subproject
+    
+    Fixes #4298 .
+
+ meson.build | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 3bdb8639e43ddf2f145c3b5c803d3648f49b834a
+Author: Pedro Nacht <pedro.k.night at gmail.com>
+Date:   Mon Jun 26 11:25:10 2023 -0300
+
+    Add Scorecard badge to README
+
+ README.md | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 27ef6c081ea26897d36d1ee3dbd6e503e72c9c33
+Author: Pedro Nacht <pedro.k.night at gmail.com>
+Date:   Mon Jun 26 11:22:18 2023 -0300
+
+    Create scorecard.yml
+
+ .github/workflows/scorecard.yml | 64 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 64 insertions(+)
+
+commit 6c4f975dcb7d807b30c074aacb5d2b551078dbd1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 23:37:08 2023 -0600
+
+    Add a fuzzer font
+
+ ...-testcase-minimized-hb-subset-fuzzer-4552226966994944 | Bin 0 -> 1524 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 87f1b80d27527d50d99b998a0d734115390bcd3f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 23:14:01 2023 -0600
+
+    [bimap] Write with a map & vector combo
+    
+    Faster for getting keys.
+    
+    Speeds up 10% in:
+    BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/retaingids/10
+
+ src/hb-bimap.hh            | 61 ++++++++++++++++++++++++++++++++++++++--------
+ src/hb-ot-layout-common.hh |  4 +--
+ 2 files changed, 53 insertions(+), 12 deletions(-)
+
+commit e7ad017ca6607d9576c4292d82b6c417710a4e54
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 22:25:24 2023 -0600
+
+    [subset/cff] Allocate more memory for retain-gids
+    
+    To avoid serializing twice.
+    
+    20% speedup in:
+    BM_subset/subset_glyphs/SourceSansPro-Regular.otf/retaingids/10
+
+ src/hb-subset.cc | 35 +++++++++++++++++++++++++----------
+ 1 file changed, 25 insertions(+), 10 deletions(-)
+
+commit 30f1ab86eacdaba8c98579f3d520d7b23989b4ca
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 19:29:03 2023 -0600
+
+    [subset/cff1] Fix typo
+
+ src/hb-subset-cff1.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 7c7db0fcba4513e5121f8a6ff74aaec634caa26a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 19:07:40 2023 -0600
+
+    [subset/cff1] Minor shuffle code around
+
+ src/hb-subset-cff1.cc | 26 ++++++++++++--------------
+ 1 file changed, 12 insertions(+), 14 deletions(-)
+
+commit 1e09ebebc1164108e7768b3ba1c66041c424daff
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 18:24:42 2023 -0600
+
+    [subset/cff1] Minor use vector length instead of map population
+
+ src/hb-subset-cff1.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 23109dde5ed517a0904a49f912c14017fcb3b10d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 18:21:57 2023 -0600
+
+    [subset/cff1] Minor use an exact allocation
+
+ src/hb-subset-cff1.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 393f0f9f16944654ddd2235eacef20951ce598b7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 18:14:56 2023 -0600
+
+    [map] Rename resize() to alloc()
+    
+    Better matches the functionality, and hb_vector_t.
+
+ src/hb-bimap.hh                  | 10 +++++-----
+ src/hb-map.hh                    | 12 ++++++------
+ src/hb-multimap.hh               |  4 ++--
+ src/hb-ot-cmap-table.hh          |  2 +-
+ src/hb-ot-post-table-v2subset.hh |  6 +++---
+ src/hb-subset-accelerator.hh     |  2 +-
+ src/hb-subset-cff-common.hh      |  2 +-
+ src/hb-subset-cff1.cc            |  6 +++---
+ src/hb-subset-plan.cc            | 10 +++++-----
+ 9 files changed, 27 insertions(+), 27 deletions(-)
+
+commit 793f663bad20a226919ec45e23ff03c3176777c3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 17:33:57 2023 -0600
+
+    [vector] Speed up hb_vector_t<hb_array_t<U>>
+
+ src/hb-vector.hh | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit 289bad82f0ff949403e5d058372e20cc32450cbd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 17:26:40 2023 -0600
+
+    [subset/cff1] Minor use a dagger
+
+ src/hb-ot-cff1-table.hh | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+commit 31d971d1aa410ef14513792b794ddb4514c0499d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 17:23:52 2023 -0600
+
+    [vector] Sprinkle std::addressof
+
+ src/hb-vector.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit c03c0a9d765f2ea0b67b15f4ead4aa35c76279ae
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 17:13:59 2023 -0600
+
+    [subset/cff1] Remove unnecessary remap_sid_t::reset
+    
+    The object is initialized automatically.
+
+ src/hb-subset-cff1.cc | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+commit 6ed0d04b699f6353feb3ce1d23eca9348271284a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 17:10:36 2023 -0600
+
+    [subset/cff1] In remap_sid_t::reset(), reset everything
+    
+    Previous code wasn't resetting next=0; tests were passing.
+    It's always called when sidmap is empty. So, redundant,
+    but keeping as is.
+
+ src/hb-subset-cff1.cc | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+commit 7e97233c352b614aa316dfeb3a161db62c7b2bcd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 17:06:02 2023 -0600
+
+    [subset/cff1] Comment
+
+ src/hb-ot-cff1-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 86a550dc7e182a53eb950278b42d0243b7185f73
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 17:01:40 2023 -0600
+
+    [subset/cff1] Speed up string writing
+
+ src/hb-ot-cff1-table.hh | 10 +++++-----
+ src/hb-subset-cff1.cc   | 17 ++++++++++++++++-
+ 2 files changed, 21 insertions(+), 6 deletions(-)
+
+commit dc1b172408ae02a64cac6edefd333d3651f7e92c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 16:35:36 2023 -0600
+
+    [subset/cff1] Minor reuse a returned value
+
+ src/hb-subset-cff1.cc | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 95341bcc15944efdb352c415a3b38b6c13ba5221
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 16:31:54 2023 -0600
+
+    [subset/cff1] Minor use {} initialization syntax
+
+ src/hb-subset-cff1.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit be0cec288b3cabf5d20f93fc32e3586cd4a9093e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 16:01:13 2023 -0600
+
+    [map] Micro-optimize iteration
+    
+    Make is_real() faster (removes a shift). is_used() gets inlined
+    so is not slowed down by this change.
+
+ src/hb-map.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 9dbea6071a41eb8595e888146c74ea7efb790455
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 25 14:28:02 2023 -0600
+
+    [subset/cff1] Fix resource leak in error case
+
+ src/hb-subset-cff1.cc | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+commit e310473cec824c91a249bd23910ccb975d278b50
+Author: David Corbett <corbett.dav at northeastern.edu>
+Date:   Sat Jun 24 21:50:58 2023 -0400
+
+    [use] Allow multiple CMAbv glyphs on subjoined
+
+ src/hb-ot-shaper-use-machine.rl | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d4bbe3f48663944385f25f608438e1eb678fc4b7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 18:13:30 2023 -0600
+
+    [subset/cff] Reuse a calculate index total data size
+
+ src/hb-ot-cff-common.hh | 24 ++++++++++++++++--------
+ src/hb-subset-cff1.cc   |  5 +++--
+ src/hb-subset-cff2.cc   |  5 +++--
+ 3 files changed, 22 insertions(+), 12 deletions(-)
+
+commit ec0fbf8fa6ada90f6564b2d5c69c181aa3f4011f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 16:13:13 2023 -0600
+
+    [subset/ClassDef] Micro-optimize use_class_zero calc
+    
+    Probably never matters.
+
+ src/hb-ot-layout-common.hh | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+commit b557a84123a0bc9dec4dc3178301fd9a67a6c709
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 15:31:54 2023 -0600
+
+    [algs] Speed up fasthash for aligned uint64_t
+
+ src/hb-algs.hh | 26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+commit fc80d20cb5cd25ee2d2579f2da018870e76aaa0e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 15:21:30 2023 -0600
+
+    [serialize] Only hash at most 128 bytes for object_t
+    
+    Optimization. Shouldn't in reality bring down the hash performance.
+    Byte objects differ in their early bytes anyway.
+
+ src/hb-serialize.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 19eb5e3b6ceb7f844af4f9cefdc2312ff2d763b1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 15:12:13 2023 -0600
+
+    [subset/cff1] Micro-optimize Charset::serialize
+
+ src/hb-ot-cff1-table.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit d36b87bde4ff91ad0eb0dbb19c7183c7d6d46d81
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 14:42:21 2023 -0600
+
+    [vector] Speed up hb_vector_t<hb_vector_t<U>>::realloc_vector
+    
+    Use in CFF subsetting.
+
+ src/hb-vector.hh | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+commit b96eed02942e816b723abab73b272ab99b430390
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 14:30:21 2023 -0600
+
+    [vector] Speed up vector_t<vector_t<U>>::resize()
+    
+    Used in CFF subsetting...
+
+ src/hb-vector.hh | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+commit b80b628a8aef423f7c04887e9802caab14fea187
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 13:41:42 2023 -0600
+
+    [subset/cff1] Speed up plan_subset_charset
+
+ src/hb-ot-cff1-table.hh | 21 +++++++++++++--------
+ src/hb-subset-cff1.cc   |  8 ++++++++
+ 2 files changed, 21 insertions(+), 8 deletions(-)
+
+commit 1902f6ccbb90fea33da74973657e6ecfec7a6c99
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 13:21:21 2023 -0600
+
+    [map] Inline an accessor function
+
+ src/hb-map.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 43d2ced8417c2a7666faf01f8e65fa14e40da2cb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 13:16:51 2023 -0600
+
+    [map] Minor remove a conditional
+
+ src/hb-map.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 817236dcb89672f1bd9fbbf9d43ffd5189da395e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 13:12:40 2023 -0600
+
+    [map] Speed up is_real
+
+ src/hb-map.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit 628ffd052e2c7d6c4e9ffdce529e29b319066c30
+Merge: 33507a9c2 b10cff990
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 14:43:09 2023 -0400
+
+    Merge pull request #4287 from googlefonts/tuple_varstore_compile
+    
+    [instancer] compile tuple variations
+
+commit 33507a9c27cb45947e9e1cf6999e69891d0a7ae3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 12:40:35 2023 -0600
+
+    [subset/cff] Micro-optimize hb_plan_subset_cff_fdselect
+
+ src/hb-subset-cff-common.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit ecb46f701376e127de68f40ee0bda98c0ec6c63a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 12:18:33 2023 -0600
+
+    [subset/cff1] Comment
+
+ src/hb-subset-plan.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 4332cb3376b03cf5d4acfb044228632da50a2a6a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 12:03:42 2023 -0600
+
+    [subset] Fix bot failure
+
+ src/hb-subset.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit c4b2950debbe5ebeca88c68ec43f42398d4969a7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 11:55:39 2023 -0600
+
+    [subset/cff1] Use cached subset-accel for seac calculations
+    
+    Before we were creating a new (non-subset) accel each time.
+
+ src/hb-ot-cff1-table.cc | 6 +++---
+ src/hb-ot-cff1-table.hh | 4 +++-
+ src/hb-ot-cff2-table.hh | 2 ++
+ src/hb-subset-plan.cc   | 9 +++++----
+ 4 files changed, 13 insertions(+), 8 deletions(-)
+
+commit b10cff9906de237cb7f56abd9e4ba99959966954
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jun 20 13:36:10 2023 -0700
+
+    [instancer] address review comments
+    
+    manage memory through vector when possible
+
+ src/hb-ot-var-common.hh     | 267 ++++++++++++++++++++++----------------------
+ src/hb-ot-var-cvar-table.hh |  18 ++-
+ src/test-tuple-varstore.cc  |   8 +-
+ 3 files changed, 149 insertions(+), 144 deletions(-)
+
+commit 5f3991391863e97f84842d32c0b18e83e5ed2081
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 11:22:01 2023 -0600
+
+    [subset/cff] Move lazy cff-accelerator to cff-subset-accelerator
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/4295
+
+ src/hb-ot-cff1-table.hh      |  8 ++++++++
+ src/hb-ot-cff2-table.hh      |  8 ++++++++
+ src/hb-subset-accelerator.hh |  4 ----
+ src/hb-subset-cff-common.hh  |  9 +++------
+ src/hb-subset-cff1.cc        | 13 ++++++-------
+ src/hb-subset-plan.cc        |  3 ---
+ src/hb-subset.cc             |  8 ++++++--
+ 7 files changed, 31 insertions(+), 22 deletions(-)
+
+commit 3a827123a1a4db75ab621e2c94e65816e4eaba58
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 11:16:57 2023 -0600
+
+    [benchmark-subset] Free cached face upon exist
+    
+    For better valgrind output.
+
+ perf/benchmark-subset.cc | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+commit 97d63e8d1d935cb1fdca08ccb0b53646a0165b13
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 10:43:34 2023 -0600
+
+    [subset/cff] Move serialize to accelerator
+
+ src/hb-ot-cff1-table.hh |  2 ++
+ src/hb-ot-cff2-table.hh |  3 +++
+ src/hb-subset-cff1.cc   | 33 ++++++++++++++++++---------------
+ src/hb-subset-cff2.cc   | 34 ++++++++++++++++++----------------
+ 4 files changed, 41 insertions(+), 31 deletions(-)
+
+commit 7344411cc248742358d623b4954558bcd21daa73
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 10:27:44 2023 -0600
+
+    [subset] Sprinkle some HB_NO_SUBSET_CFF
+
+ src/hb-subset-accelerator.hh | 3 +++
+ src/hb-subset-plan.cc        | 7 +++++--
+ src/hb-subset-plan.hh        | 2 ++
+ src/hb-subset.cc             | 2 ++
+ 4 files changed, 12 insertions(+), 2 deletions(-)
+
+commit 26f320dcd349813ec687fa0aaab40b2e844db6ca
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 10:24:32 2023 -0600
+
+    [subset/cff] Remove unused method
+
+ src/hb-ot-cff1-table.hh | 2 --
+ src/hb-ot-cff2-table.hh | 2 --
+ src/hb-subset-cff1.cc   | 7 -------
+ src/hb-subset-cff2.cc   | 7 -------
+ 4 files changed, 18 deletions(-)
+
+commit 43ec78f92c4c26c50a9cddabfb36de697b41d4e0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 23 10:22:30 2023 -0600
+
+    [subset/cff] Cache CFF accelerator in hb_subset_plan_t
+    
+    This shows 7% speedup in:
+    BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/retaingids/10
+
+ src/hb-atomic.hh             |  1 +
+ src/hb-machinery.hh          |  9 ++++++-
+ src/hb-ot-cff1-table.hh      | 15 ++++++++++-
+ src/hb-ot-cff2-table.hh      | 15 ++++++++++-
+ src/hb-subset-accelerator.hh | 29 +++++++++++----------
+ src/hb-subset-cff-common.hh  |  5 +---
+ src/hb-subset-cff1.cc        | 13 +++++-----
+ src/hb-subset-cff2.cc        | 11 ++++----
+ src/hb-subset-plan.cc        | 40 +++++++++++++++++++++++++++-
+ src/hb-subset-plan.hh        | 62 ++++++++++++++++++++++----------------------
+ src/hb-subset.cc             | 38 +++++++++++++++++++++------
+ 11 files changed, 165 insertions(+), 73 deletions(-)
+
+commit 154aae3af6db4c9b20060ec9e610fcdd0c1db366
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 20:41:16 2023 -0600
+
+    [subset] Minor use an auto variable
+    
+    I need this later. :D
+
+ src/hb-subset.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 64e49e0f71d02ccc1209f75aa725ef073a7fb036
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 20:27:20 2023 -0600
+
+    [subset-cff2] Store num_glyphs in plan
+    
+    Like cff1 code does.
+    
+    Also, check for .notdef, like cff1 code does.
+
+ src/hb-subset-cff2.cc | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+commit f05561dd4ef8002e89eaec4cac92b64090417660
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 20:25:04 2023 -0600
+
+    [subset-cff1] Use plan.num_glyphs instead of passing again
+
+ src/hb-subset-cff1.cc | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 7a124a0b4e4a3b901f3cb7bd9d4df76f176be0c6
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 20:18:20 2023 -0600
+
+    [cff1] Use constructor for accelerator_templ_t
+
+ src/hb-ot-cff1-table.hh | 68 ++++++++++++++++++++++++-------------------------
+ src/hb-ot-cff2-table.hh |  1 -
+ src/hb-subset-cff1.cc   |  8 ++----
+ 3 files changed, 36 insertions(+), 41 deletions(-)
+
+commit ad025ddf05f1c9dc3eaaea00cd1a80adba7fa8bd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 20:09:36 2023 -0600
+
+    [subset-cff] Simplify a bit
+
+ src/Makefile.sources        |  2 --
+ src/hb-ot-cff1-table.hh     |  3 +--
+ src/hb-ot-cff2-table.hh     |  3 +--
+ src/hb-subset-cff-common.hh |  3 +++
+ src/hb-subset-cff1.cc       |  3 +--
+ src/hb-subset-cff1.hh       | 37 -------------------------------------
+ src/hb-subset-cff2.cc       |  3 +--
+ src/hb-subset-cff2.hh       | 37 -------------------------------------
+ src/meson.build             |  2 --
+ 9 files changed, 7 insertions(+), 86 deletions(-)
+
+commit e1753782c18beea4cee93001924985b83db92ccf
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 19:45:29 2023 -0600
+
+    [subset-cff] Handle an error condition
+
+ src/hb-subset-cff-common.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit cb5f4d0c68d081f75245bdd0da9d75b0726acac5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 18:46:33 2023 -0600
+
+    [subset-plan] Avoid a copy in freeing name-table-overrides
+
+ src/hb-map.hh         | 2 +-
+ src/hb-subset-plan.hh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit d8fba5c6b016e7d6cead4b000b6947b9db240176
+Author: David Corbett <corbett.dav at northeastern.edu>
+Date:   Thu Jun 22 19:25:54 2023 -0400
+
+    [use] Add FM categories to `POST_BASE_FLAGS64`
+
+ src/hb-ot-shaper-use.cc                                  |   3 +++
+ .../fonts/d0430ea499348c420946f6abc2efc84fdf8f00e3.ttf   | Bin 0 -> 1308 bytes
+ test/shape/data/in-house/tests/use-syllable.tests        |   1 +
+ 3 files changed, 4 insertions(+)
+
+commit 6a17622a75cf8dea9f1cf5f7b1e4d9be9145ac49
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 18:35:10 2023 -0600
+
+    [array] Speed up iteration
+    
+    These are faster than relying on the random-access methods
+    (forward, rewind, item_it).
+
+ src/hb-array.hh | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+commit f839bd11d250b953712733bdb3187eec3bf67419
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 17:29:57 2023 -0600
+
+    [multimap] Use one fewer object
+    
+    Also fix error-checking to check for sub-object errors.
+
+ src/hb-multimap.hh | 29 ++++++++++++++---------------
+ 1 file changed, 14 insertions(+), 15 deletions(-)
+
+commit 280edb909b0f0b244b8deb6e0e24eb2516ac038f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 17:07:31 2023 -0600
+
+    [map] Use a variable instead of function for is_trivial
+
+ src/hb-map.hh | 17 +++++++----------
+ 1 file changed, 7 insertions(+), 10 deletions(-)
+
+commit 0aa939e70f575e8f7715530a48550ef12ae68d4d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 17:05:55 2023 -0600
+
+    [map] Add a constexpr
+
+ src/hb-map.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit cf386e8ce2f28ae1ca40cec849b55e71c36636cf
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 17:02:10 2023 -0600
+
+    [map] Speed up resize()
+
+ src/hb-map.hh | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+commit abd6c305ff5d1a6126624b906ceec870cd5f15ee
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 16:44:29 2023 -0600
+
+    [subset-plan] Micro-optimize
+
+ src/hb-subset-plan.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 7b53d2dbdde3b90f35651a449fc55ea27a7230d9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 16:35:11 2023 -0600
+
+    [subset] Avoid copying gid_to_unicode multimap
+    
+    Construct it in the accelerator directly.
+
+ src/hb-subset-accelerator.hh | 21 +++++++++++++--------
+ src/hb-subset-plan.cc        | 13 -------------
+ 2 files changed, 13 insertions(+), 21 deletions(-)
+
+commit 272e159c8987afb8b6d139b89cc1267b802027aa
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 16:31:50 2023 -0600
+
+    [subset] Speed up populating reverse cmap
+
+ src/hb-subset-plan.cc | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit 8f80d9d38db92a391ff5c0794f2a38176cd97e9e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 16:22:47 2023 -0600
+
+    [subset-accelerator] Avoid a multimap copy
+
+ src/hb-subset-accelerator.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f55619b8360505ff352c60e728dbf0c2e960e303
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jun 20 12:37:05 2023 -0700
+
+    [instancer] add subset () for cvar
+
+ src/hb-ot-var-cvar-table.hh | 40 +++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 39 insertions(+), 1 deletion(-)
+
+commit e39e02017e1537cd9f085b1f5999887a309c20c6
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jun 20 11:48:53 2023 -0700
+
+    [instancer] add serialize() method for TupleVariationData
+
+ src/hb-ot-var-common.hh | 67 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 67 insertions(+)
+
+commit 5ef0199da331959e6b27da90d1032f78d3d775ef
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jun 20 11:39:20 2023 -0700
+
+    [instancer] instantiate() and compile_bytes () for tuple_variations_t
+    
+    Also add testing code
+
+ src/hb-ot-var-common.hh    | 28 ++++++++++++++++++++++++++++
+ src/test-tuple-varstore.cc | 23 +++++++++++++++++++++++
+ 2 files changed, 51 insertions(+)
+
+commit 48c70ce5f667d6b24d7d4a72bc03095760dc3752
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jun 20 11:30:51 2023 -0700
+
+    [instancer] add compile_tuple_var_header()
+
+ src/hb-ot-var-common.hh | 116 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 116 insertions(+)
+
+commit 6354b71f81bb85951d84d245eb68ec4e107aea55
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jun 20 11:24:05 2023 -0700
+
+    [instancer] add compile_deltas() for tuple_delta_t
+
+ src/hb-ot-var-common.hh | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 70 insertions(+)
+
+commit a00ad83a3bc0e86a16a791c0085403dd9a42b5a4
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jun 20 11:17:11 2023 -0700
+
+    [instancer] add encode_delta_run()
+
+ src/hb-ot-var-common.hh | 165 ++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 158 insertions(+), 7 deletions(-)
+
+commit 19e5033b9c8d24ee6ce2df124576d5d724d80fc2
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jun 20 11:02:41 2023 -0700
+
+    [instancer] add compile_all_point_sets() and find_shared_points ()
+    
+    compiled bytes for points set are stored in a hashmap
+
+ src/hb-ot-var-common.hh | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 61 insertions(+)
+
+commit 065e0af5925f260a5fcd40ec0a502ec8aa3ada85
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Jun 20 10:58:24 2023 -0700
+
+    [instancer] add compile_point_set() for tuple_variations_t
+    
+    Also add a byte_data_t struct to store compiled bytes
+
+ src/hb-ot-var-common.hh | 103 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 103 insertions(+)
+
+commit e41b688b50506844739794d715596f24c6ae9545
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Jun 12 13:25:19 2023 -0700
+
+    [instancer] fix bug in tuple varstore decompiling
+    
+    when points count is 0, it means deltas will apply to all points
+
+ src/hb-ot-var-common.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 5c2aa1a8e726b657db49b881c88ccf2c95a64899
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 11:02:22 2023 -0600
+
+    [syllabic] Add buffer messages for inserting dotted-circle
+
+ src/hb-ot-shaper-syllabic.cc | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+commit f0f6f6a8057a80ddb8a96ed05f1584e7780f29f0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 10:58:44 2023 -0600
+
+    [layout] More message massaging
+
+ src/hb-ot-layout.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 7232c01dce7384ad6c9acd3c9b97780abbe85c1f
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Jun 22 09:37:48 2023 -0700
+
+    [instancer-solver] add tests for instancer-solver crossing calculation fix
+
+ src/test-subset-instancer-solver.cc | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+commit 37555f84891c50dfd7ca4478e81acfd8c9393988
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 22 10:21:19 2023 -0600
+
+    [layout] Trace chosen script tag
+
+ src/hb-ot-layout.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit c56275c09c426261723c029644f7f355823c05b8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 21 19:01:46 2023 -0600
+
+    [instancer-solver] Notation
+
+ src/hb-subset-instancer-solver.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit dbac23357f0ad9cba73965a4a00ca85bf01dcef9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 21 18:54:11 2023 -0600
+
+    [instancer-solver] Simplify, from upstream
+
+ src/hb-subset-instancer-solver.cc | 65 ++++++++-------------------------------
+ 1 file changed, 12 insertions(+), 53 deletions(-)
+
+commit 32a9ac2e3a581c68fffac0203d568944bb1d133b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 21 18:30:31 2023 -0600
+
+    [instancer/L4] Add a comment from upstream
+
+ src/hb-subset-instancer-solver.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 244f3224b9a6e9e22f65796a984ef7058e7af930
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 21 17:54:49 2023 -0600
+
+    [instancer-solver] Port optimization from upstream
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/4291
+
+ src/hb-subset-instancer-solver.cc   | 165 +++++++++++++++++++++---------------
+ src/test-subset-instancer-solver.cc |   6 +-
+ 2 files changed, 101 insertions(+), 70 deletions(-)
+
+commit 197bb35972d66fa01b26bf6fcb1a2268717ef574
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 21 15:16:53 2023 -0600
+
+    [instancer-solver] Further simplify
+    
+    From https://github.com/fonttools/fonttools/pull/3179/commits/94e081611c6b40fa6284049a753479d1038bdb1c
+
+ src/hb-subset-instancer-solver.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6788932d81c163cc7634a6b04115e556a1b19299
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 21 15:16:19 2023 -0600
+
+    [instancer-solver] Simplify
+    
+    From https://github.com/fonttools/fonttools/pull/3179/commits/7385cbbc34080d5ed3e9017eb38945cfb03cfe17
+
+ src/hb-subset-instancer-solver.cc | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit de0c5aed5b7ca26570eb91e25930813e9123fe56
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 21 15:14:23 2023 -0600
+
+    [instancer-solver] Backport bugfix from fonttools
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/4289
+    
+    Test not ported yet.
+
+ src/hb-subset-instancer-solver.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a77f28286569b1d187aa7470a4721222a3fc44e7
+Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
+Date:   Mon Jun 19 22:51:01 2023 +0000
+
+    Bump meson from 0.62.0 to 1.1.1 in /.ci
+    
+    Bumps [meson](https://github.com/mesonbuild/meson) from 0.62.0 to 1.1.1.
+    - [Release notes](https://github.com/mesonbuild/meson/releases)
+    - [Commits](https://github.com/mesonbuild/meson/compare/0.62.0...1.1.1)
+    
+    ---
+    updated-dependencies:
+    - dependency-name: meson
+      dependency-type: direct:production
+      update-type: version-update:semver-major
+    ...
+    
+    Signed-off-by: dependabot[bot] <support at github.com>
+
+ .ci/requirements.in  |  2 +-
+ .ci/requirements.txt | 14 +++++++-------
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+commit a094a6bd9c9504bb9b6f7673ec5a81e8f0f89cbb
+Merge: db700b567 0be1e5a73
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 19 18:50:02 2023 -0400
+
+    Merge pull request #4275 from pnacht/pinned_pip
+    
+    Hash-pin Python dependencies in CI
+
+commit 0be1e5a73dc0d987848ff32592c569d34e7b2024
+Author: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+Date:   Mon Jun 19 20:49:38 2023 +0000
+
+    Use meson 0.62.0, remove retry
+    
+    Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+
+ .ci/requirements.in           |  2 +-
+ .ci/requirements.txt          |  6 +++---
+ .github/workflows/msvc-ci.yml | 33 +++++++--------------------------
+ 3 files changed, 11 insertions(+), 30 deletions(-)
+
+commit 3679293a450f62c1eb5318d87992b8f727c6517a
+Author: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+Date:   Mon Jun 19 19:46:41 2023 +0000
+
+    msvc-ci: Retry if meson setup is flaky
+    
+    Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+
+ .github/workflows/msvc-ci.yml | 35 +++++++++++++++++++++++++++--------
+ 1 file changed, 27 insertions(+), 8 deletions(-)
+
+commit 0ccb5c365f61319a68506ab5c5c08c9f12ea1ca5
+Author: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+Date:   Mon Jun 19 19:39:58 2023 +0000
+
+    Only use fonttools in msys2-ci
+    
+    Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+
+ .github/workflows/msys2-ci.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 546508733d940202d009f95d9414aa229d17150c
+Author: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+Date:   Mon Jun 19 19:36:43 2023 +0000
+
+    Move fonttools to separate requirements file
+    
+    Necessary because msys2/mingw don't accept the other deps
+    (not supported?), and msys2-ci.yml only needs fonttools.
+    
+    Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+
+ .ci/requirements-fonttools.in  |  1 +
+ .ci/requirements-fonttools.txt | 42 ++++++++++++++++++++++++++++++++++++++++++
+ .ci/requirements.in            |  2 +-
+ .ci/requirements.txt           | 40 ++++++++++++++++++++++++++++++++++++----
+ 4 files changed, 80 insertions(+), 5 deletions(-)
+
+commit db700b5670d9475cc8ed4880cc9447b232c5e432
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon Jun 12 23:38:26 2023 +0000
+
+    [subset] fix fuzzer timeout.
+    
+    Fixes: https://oss-fuzz.com/testcase-detail/6681253479579648. Limits iteration of coverage table during MATH subset to valid glyphs.
+
+ src/hb-iter.hh                                           |   2 +-
+ src/hb-ot-math-table.hh                                  |   9 +++++----
+ ...-testcase-minimized-hb-subset-fuzzer-6681253479579648 | Bin 0 -> 3472 bytes
+ 3 files changed, 6 insertions(+), 5 deletions(-)
+
+commit e2722696793cacc8e58546e902451a9b2c65bac4
+Author: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+Date:   Mon Jun 12 14:36:49 2023 +0000
+
+    Bump meson to 0.60.0
+    
+    Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+
+ .ci/requirements.in  | 2 +-
+ .ci/requirements.txt | 5 +++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+commit e39c4cf5a92881d81ba0219a7153116bb53ad59c
+Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
+Date:   Mon Jun 12 10:58:52 2023 +0000
+
+    Bump ilammy/msvc-dev-cmd from 1.12.0 to 1.12.1
+    
+    Bumps [ilammy/msvc-dev-cmd](https://github.com/ilammy/msvc-dev-cmd) from 1.12.0 to 1.12.1.
+    - [Release notes](https://github.com/ilammy/msvc-dev-cmd/releases)
+    - [Commits](https://github.com/ilammy/msvc-dev-cmd/compare/7315a94840631165970262a99c72cfb48a65d25d...cec98b9d092141f74527d0afa6feb2af698cfe89)
+    
+    ---
+    updated-dependencies:
+    - dependency-name: ilammy/msvc-dev-cmd
+      dependency-type: direct:production
+      update-type: version-update:semver-patch
+    ...
+    
+    Signed-off-by: dependabot[bot] <support at github.com>
+
+ .github/workflows/msvc-ci.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d82c7623c5c146abeb4cea6e5dc8e6318a139a24
+Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
+Date:   Mon Jun 12 10:58:57 2023 +0000
+
+    Bump actions/checkout from 3.5.2 to 3.5.3
+    
+    Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
+    - [Release notes](https://github.com/actions/checkout/releases)
+    - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
+    - [Commits](https://github.com/actions/checkout/compare/8e5e7e5ab8b370d6c329ec480221332ada57f0ab...c85c95e3d7251135ab7dc9ce3241c5835cc595a9)
+    
+    ---
+    updated-dependencies:
+    - dependency-name: actions/checkout
+      dependency-type: direct:production
+      update-type: version-update:semver-patch
+    ...
+    
+    Signed-off-by: dependabot[bot] <support at github.com>
+
+ .github/workflows/arm-ci.yml        | 2 +-
+ .github/workflows/configs-build.yml | 2 +-
+ .github/workflows/coverity-scan.yml | 2 +-
+ .github/workflows/linux-ci.yml      | 2 +-
+ .github/workflows/macos-ci.yml      | 2 +-
+ .github/workflows/msvc-ci.yml       | 2 +-
+ .github/workflows/msys2-ci.yml      | 2 +-
+ 7 files changed, 7 insertions(+), 7 deletions(-)
+
+commit 1159b9d3ee0b5c772728aee035fe1a5220da11a9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 10 10:54:32 2023 -0600
+
+    [subset/cff1] Remove always-true check
+
+ src/hb-subset-cff1.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fad2c4aea6087e39c4589d5698acf93d1a56c173
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 10 10:22:27 2023 -0600
+
+    [subset/cff] Simplify a few serialize calls
+
+ src/hb-subset-cff1.cc | 24 ++++++++----------------
+ src/hb-subset-cff2.cc | 12 ++++--------
+ 2 files changed, 12 insertions(+), 24 deletions(-)
+
+commit 2e6919d5262e5fc747f6ac18057e8c0e286ade89
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 10 10:08:56 2023 -0600
+
+    [subset/cff2] Error handling
+    
+    Fixes https://oss-fuzz.com/testcase-detail/4916785942757376
+
+ src/hb-subset-cff2.cc                                     |  12 ++++++++++--
+ ...z-testcase-minimized-hb-subset-fuzzer-4916785942757376 | Bin 0 -> 331 bytes
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+commit 5906f90ce1feb3894da4019fe4b34e788eb21c5b
+Author: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+Date:   Wed Jun 7 18:54:57 2023 +0000
+
+    Hash-pin Actions
+    
+    Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+
+ .github/workflows/arm-ci.yml        | 2 +-
+ .github/workflows/cifuzz.yml        | 2 +-
+ .github/workflows/configs-build.yml | 2 +-
+ .github/workflows/coverity-scan.yml | 2 +-
+ .github/workflows/linux-ci.yml      | 6 +++---
+ .github/workflows/macos-ci.yml      | 6 +++---
+ .github/workflows/msvc-ci.yml       | 8 ++++----
+ .github/workflows/msys2-ci.yml      | 4 ++--
+ 8 files changed, 16 insertions(+), 16 deletions(-)
+
+commit 0935b3279565ca3c5608a43dc5a4ce65e90b851f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 18:47:33 2023 -0600
+
+    [vector] Speed up shrink_vector for trivial destructors
+
+ src/hb-vector.hh | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+commit da2e2c8c25b45cadcebd814a3f42e3d32c4b5e93
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 17:16:53 2023 -0600
+
+    [subset/cff] Speed up offset writing
+
+ src/hb-ot-cff-common.hh | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+commit c85ca75eff9658f727059afe3c79a8bc34281ece
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 15:57:49 2023 -0600
+
+    [buffer-verify] Simplify a couple ifs
+
+ src/hb-buffer-verify.cc | 19 ++++++-------------
+ 1 file changed, 6 insertions(+), 13 deletions(-)
+
+commit e527c17e239fbbc0856add5723be9b57e3a48662
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 15:56:12 2023 -0600
+
+    [buffer-verify] Don't consider shaping failure as error
+
+ src/hb-buffer-verify.cc | 18 ++----------------
+ 1 file changed, 2 insertions(+), 16 deletions(-)
+
+commit cb516075b6880352900d07016f1ccce2dada9c62
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 15:50:53 2023 -0600
+
+    [buffer-verify] Error handling
+
+ src/hb-buffer-verify.cc | 41 +++++++++++++++++++++++------------------
+ 1 file changed, 23 insertions(+), 18 deletions(-)
+
+commit 39dd777a12573d488c05c4b59693302cb38f37e7
+Merge: fea47dd3f 3669a6271
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 15:25:20 2023 -0600
+
+    Merge pull request #4271 from googlefonts/change_axis_limits
+    
+    [instancer] change tuple variations' axis limits
+
+commit 3669a6271043912de8d0ee566a4effc3a56927f9
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Jun 8 13:26:37 2023 -0700
+
+    fix bot
+
+ src/hb-ot-var-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9fd367663a25bbcdcdff958ebc3665ddf8017077
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Jun 8 12:27:36 2023 -0700
+
+    [instancer] add testing code for change_tuple_variation_axis_limits()
+    
+    Also fixed a small bug
+
+ src/Makefile.am            |  2 +-
+ src/hb-ot-var-common.hh    |  2 +-
+ src/meson.build            |  2 +-
+ src/test-tuple-varstore.cc | 35 +++++++++++++++++++++++++++++++++++
+ 4 files changed, 38 insertions(+), 3 deletions(-)
+
+commit 8057661f077dbca4f8b1f702771b70a9e1e29dd4
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Jun 8 12:10:27 2023 -0700
+
+    [instancer] use axis tag as hashmap key instead of axis index
+    
+    This makes remove_axis() and set_tent() faster, which are used by
+    change_axis_limits ()
+
+ src/hb-ot-var-common.hh     | 16 ++++++++++++----
+ src/hb-ot-var-cvar-table.hh |  2 ++
+ src/test-tuple-varstore.cc  | 11 ++++++++---
+ 3 files changed, 22 insertions(+), 7 deletions(-)
+
+commit 389446c563f9caab73df6d58a43fc5d1ed991920
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Jun 8 09:07:47 2023 -0700
+
+    [instancer] add merge_tuple_variations ()
+
+ src/hb-ot-var-common.hh           | 27 +++++++++++++++++++++++++++
+ src/hb-subset-instancer-solver.hh | 18 ++++++++++++++++++
+ 2 files changed, 45 insertions(+)
+
+commit fea47dd3f2186175feaa710200277158f3698506
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 15:03:27 2023 -0600
+
+    [vector] Fix vector error handling when allocation used to be 0
+
+ src/hb-vector.hh | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+commit 11308c4d1f4a8aaab11893810e9809cb76e4e1c6
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 14:51:18 2023 -0600
+
+    [graph] Remove manual destruction
+    
+    Happens automatically by destructor.
+
+ src/graph/graph.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit d08aee5a7e5dde5158393e8f03c63fad8a4f3682
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 13:20:28 2023 -0600
+
+    Add fuzzing test
+
+ ...-testcase-minimized-hb-subset-fuzzer-6442117271257088 | Bin 0 -> 4043 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit dbdeb2649d3506b5179ff1bdedf3bc9b5442a038
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 12:08:29 2023 -0600
+
+    [vector] Keep allocated size when in error
+
+ src/hb-vector.hh | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+commit 9df07c3c303299ea782176aad901cd7831f4e025
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 11:46:06 2023 -0600
+
+    [gsubgpos] Prevent a leak in closure
+    
+    If the push wasn't successful we were constructing an
+    hb_set_t on the Crap data...  At least that's my reading
+    of the code.
+
+ src/hb-ot-layout-gsubgpos.hh | 48 ++++++++++++++++++++++++++------------------
+ 1 file changed, 29 insertions(+), 19 deletions(-)
+
+commit 0f0b3bee2157be6ad0c2ef9bbac39a9cae29e85c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 8 11:13:33 2023 -0600
+
+    [map] Fix use-after-move issue
+
+ src/hb-map.hh | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit a67a7867d2f8e83b9c307f70b8997dedf3f9d154
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 20:24:02 2023 -0600
+
+    [cff] Tweak CFFIndex accessors again
+    
+    Faster; avoiding multiply.
+
+ src/hb-ot-cff-common.hh | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+commit 04c5e46ac6258cc7fafda479cfce1594edb90a2b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 19:18:04 2023 -0600
+
+    [subset/cff] Fix comment
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 8832da83091358c919f3b685d9d168bd92e1c1d5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 18:58:52 2023 -0600
+
+    [subset/cff] Comment
+
+ src/hb-ot-cff-common.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 092373f3512ea6b5f4e8280b5e81dc22ed2e4844
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 17:49:13 2023 -0600
+
+    [subset/cff] Comment
+
+ src/hb-ot-cff-common.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit e0b60bd08d8af88e61fea3b399b1654f3683be4f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 17:25:47 2023 -0600
+
+    [subset/cff1] Speed up remap_sids
+
+ src/hb-map.hh         | 13 +++++++++----
+ src/hb-subset-cff1.cc | 10 +++++-----
+ 2 files changed, 14 insertions(+), 9 deletions(-)
+
+commit 67b16247274d1fc04d36d4242680b0a06912eae0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 16:15:48 2023 -0600
+
+    [set] Simplify a few set iterations as range loop
+
+ src/OT/Layout/Common/CoverageFormat1.hh | 2 +-
+ src/OT/Layout/Common/CoverageFormat2.hh | 2 +-
+ src/graph/graph.hh                      | 3 +--
+ src/hb-bimap.hh                         | 3 +--
+ src/hb-ot-cmap-table.hh                 | 3 +--
+ src/hb-ot-layout-common.hh              | 5 ++---
+ src/hb-ot-layout.cc                     | 5 ++---
+ src/hb-ot-os2-table.hh                  | 3 +--
+ src/hb-subset-cff-common.hh             | 3 +--
+ src/test-gsub-get-alternates.cc         | 2 +-
+ 10 files changed, 12 insertions(+), 19 deletions(-)
+
+commit 988e4f068ebc3797a419eaefa16d2f8547c780bd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 15:57:47 2023 -0600
+
+    [iter] Comment
+
+ src/hb-iter.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0364c69e6d6209b65739968fb72f73e504e1fd20
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 15:52:18 2023 -0600
+
+    [iter] Add has_fast_len
+    
+    Set iterators are not random_access, but have fast len().
+
+ src/hb-array.hh              | 2 ++
+ src/hb-bit-set-invertible.hh | 1 +
+ src/hb-bit-set.hh            | 1 +
+ src/hb-iter.hh               | 1 +
+ src/hb-map.hh                | 2 +-
+ src/hb-vector.hh             | 2 +-
+ 6 files changed, 7 insertions(+), 2 deletions(-)
+
+commit 2d1589221ddcc64dedd6fa72b853e34b0fff0fab
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 15:47:08 2023 -0600
+
+    [subset/hdmx] Remove an unintended vector copy
+
+ src/hb-ot-hdmx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 81b2a56d5423d5b1476f279d0c720bb00ffa231b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 15:04:20 2023 -0600
+
+    [set] Micro-optimize iteration
+
+ src/hb-bit-set-invertible.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ad620af6f6d36f2e10d6affaf2112e3f35c656c9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 14:59:22 2023 -0600
+
+    Revert "[iter] Another try at writing some for loops as range loops"
+    
+    This reverts commit 69c6928289cad871b5b096fbdcd2827fdb80c3ad.
+    
+    This had code size increase, and slows down non-random-access
+    iterators since it accesses __end__ which is O(n).
+
+ src/hb-iter.hh | 23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+commit 59f2d2f6c2aa61e9e859934a7b710d822e905610
+Author: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+Date:   Wed Jun 7 19:50:09 2023 +0000
+
+    Set dependabot to update requirements.txt
+    
+    Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+
+ .github/dependabot.yml | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 7c08bb85d589cc1ae5f506832dd90efddf0a06a6
+Author: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+Date:   Wed Jun 7 19:47:57 2023 +0000
+
+    Adopt requirements.txt file in workflows
+    
+    Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+
+ .github/workflows/linux-ci.yml | 2 +-
+ .github/workflows/macos-ci.yml | 2 +-
+ .github/workflows/msvc-ci.yml  | 2 +-
+ .github/workflows/msys2-ci.yml | 2 +-
+ 4 files changed, 4 insertions(+), 4 deletions(-)
+
+commit a8e2f1b6eaf31d76e41e46dc70aba35263c671be
+Author: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+Date:   Wed Jun 7 19:40:26 2023 +0000
+
+    Add .ci/requirements files
+    
+    Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht at google.com>
+
+ .ci/requirements.in  |   4 ++
+ .ci/requirements.txt | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 179 insertions(+)
+
+commit 80d6e996d75e46e3aa2c3ab32fc898a6d22af556
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 14:21:40 2023 -0600
+
+    [subset/cff1] Fix wrong comma location!
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 69c6928289cad871b5b096fbdcd2827fdb80c3ad
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 14:11:02 2023 -0600
+
+    [iter] Another try at writing some for loops as range loops
+
+ src/hb-iter.hh | 23 +++++++++++------------
+ 1 file changed, 11 insertions(+), 12 deletions(-)
+
+commit 138461beb474cc65fe4b967efbd12b4e7753ead1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 14:07:39 2023 -0600
+
+    [susbet/cff] Minor remove one indirection
+
+ src/hb-ot-cff-common.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 41369b661735242937ebc7734edea27984ca3b1d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 14:04:42 2023 -0600
+
+    Revert "[subset/cff1] Optimize writing of consecutive names"
+    
+    This reverts commit 3b25a630403b65eb5608d10c3b8d082a141bd5c8.
+    
+    Not worth it. Shows 0.5% speedup only on SourceSansPro/retaingids/10
+    
+    Doesn't have code size increase though.
+
+ src/hb-ot-cff-common.hh | 23 -----------------------
+ src/hb-ot-cff1-table.hh |  2 +-
+ 2 files changed, 1 insertion(+), 24 deletions(-)
+
+commit 3b25a630403b65eb5608d10c3b8d082a141bd5c8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 14:04:25 2023 -0600
+
+    [subset/cff1] Optimize writing of consecutive names
+
+ src/hb-ot-cff-common.hh | 23 +++++++++++++++++++++++
+ src/hb-ot-cff1-table.hh |  2 +-
+ 2 files changed, 24 insertions(+), 1 deletion(-)
+
+commit 78082357c8bcee2adea53caa9da8cee1c7ec2970
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 12:43:05 2023 -0600
+
+    Revert "[iter] Rewrite some loops as range loops"
+    
+    This reverts commit 7a5242a30f3c41755a095909989221b4d22690ef.
+    
+    This times out test-set. Obviously broke something (in hb_all
+    I think). Not bothering to figure out right now.
+
+ src/hb-iter.hh | 35 ++++++++++++++++++-----------------
+ 1 file changed, 18 insertions(+), 17 deletions(-)
+
+commit 7a5242a30f3c41755a095909989221b4d22690ef
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 12:36:15 2023 -0600
+
+    [iter] Rewrite some loops as range loops
+
+ src/hb-iter.hh | 35 +++++++++++++++++------------------
+ 1 file changed, 17 insertions(+), 18 deletions(-)
+
+commit cc9651d55d4909ba3baed8b089ee44f8a2a6c270
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 12:20:48 2023 -0600
+
+    [map] Micro-optimize
+
+ src/hb-map.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 79113ec3b19b80f79efb92214c04774cb7556c7c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 12:14:43 2023 -0600
+
+    [subset/cff1] Micro-optimize String writing
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 5fe96213aae0cac6f6ef25fdbb7ef64a0c6cd557
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 12:05:57 2023 -0600
+
+    [subset/cff] Micro-optimize CFFIndex writing
+
+ src/hb-ot-cff-common.hh | 25 +++++++++++++------------
+ 1 file changed, 13 insertions(+), 12 deletions(-)
+
+commit 70b13ef00ba86f8315a56d44f3ad065b9a81763c
+Merge: b80b6a4f5 01f9b7977
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Jun 7 11:46:37 2023 -0600
+
+    Merge pull request #4267 from googlefonts/decompile_tuple_varstore
+    
+    [instancer] decompile tuple varstore
+
+commit b80b6a4f5fc64027c43adbe60942a468db81a017
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 18:11:55 2023 -0600
+
+    [cff] Remove unused types
+
+ src/hb-ot-cff-common.hh | 5 +----
+ src/hb-ot-cff1-table.hh | 3 +--
+ src/hb-ot-cff2-table.hh | 1 -
+ 3 files changed, 2 insertions(+), 7 deletions(-)
+
+commit 26ac1d4b485c2b96fdc9069583f443b1ab455ab5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 18:08:59 2023 -0600
+
+    [cff] Remove unused method
+
+ src/hb-ot-cff-common.hh | 40 +---------------------------------------
+ 1 file changed, 1 insertion(+), 39 deletions(-)
+
+commit c6ce1f81ece74e20e4ae8b4b4d424a1694c3ed15
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 17:17:29 2023 -0600
+
+    [cff] Micro-optimize CFFIndex::operator[]
+
+ src/hb-ot-cff-common.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit a55d0b88662c01471f254a452650703586820b4e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 17:13:09 2023 -0600
+
+    [subset/cff] Inline type only used once
+
+ src/hb-cff-interp-common.hh | 2 --
+ src/hb-ot-cff1-table.hh     | 2 +-
+ 2 files changed, 1 insertion(+), 3 deletions(-)
+
+commit 2960d13f1bcd573f985b44a40f7340694a99dd9b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 16:24:28 2023 -0600
+
+    [subset/cff1] Micro-optimize string writing
+
+ src/hb-ot-cff1-table.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 35e152b9f44a3bbac48a1837d91962fa8619d80f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 16:21:14 2023 -0600
+
+    [subset/cff] Micro-optimize CFFIndex for empty strings
+
+ src/hb-ot-cff-common.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit acae5ed25c0da62153c9dd5c1d377886039384cc
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 16:18:44 2023 -0600
+
+    [subset/cff1] Speed up sid mapping
+    
+    Don't need a full inc_bimap.
+
+ src/hb-ot-cff1-table.hh |  2 +-
+ src/hb-subset-cff1.cc   | 13 +++++++++++--
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+commit 9e80f6b1b6a8481252368923ae5b4f10ee7c1d2c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 15:38:14 2023 -0600
+
+    [subset/cff1] Speed up plan_subset_charset
+    
+    25% speedup in --benchmark_filter=subset_glyphs/SourceSansPro'.*retaingids/10
+
+ src/hb-subset-cff1.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit fd13aa9effceb1ad87d48ad35c2271217324b6c0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 15:33:51 2023 -0600
+
+    [subset/cff1] Optimize CFF::CFF1StringIndex::serialize
+
+ src/hb-ot-cff1-table.hh | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+commit ada1e9a924b7a38071757511117892d3b76cb475
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 14:46:06 2023 -0600
+
+    [graph/serialize] Handle empty blob
+    
+    Fixes https://oss-fuzz.com/testcase-detail/4877513265119232
+
+ src/graph/serialize.hh                                     |   3 +++
+ ...-testcase-minimized-hb-repacker-fuzzer-4877513265119232 | Bin 0 -> 10 bytes
+ 2 files changed, 3 insertions(+)
+
+commit a92b288e655a94e076f0c3205f99e9162d35e20c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Jun 6 14:32:25 2023 -0600
+
+    [serializer] Handle snapshotting when current is nullptr
+    
+    Happens with memory failure / fuzzing.
+    
+    Fixes https://oss-fuzz.com/testcase-detail/6292420615340032
+
+ src/hb-serialize.hh                                    |  17 +++++++++++++----
+ ...estcase-minimized-hb-subset-fuzzer-6292420615340032 | Bin 0 -> 2116 bytes
+ 2 files changed, 13 insertions(+), 4 deletions(-)
+
+commit 01f9b79777ab4ad26a04b37f96bd6db841fdbe33
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Jun 5 17:26:20 2023 -0700
+
+    address review comments
+
+ src/Makefile.am                                    |  8 +++----
+ src/hb-ot-var-common.hh                            | 26 ++++++----------------
+ src/hb-ot-var-cvar-table.hh                        |  2 +-
+ src/meson.build                                    |  2 +-
+ ...le-tuple-varstore.cc => test-tuple-varstore.cc} |  0
+ 5 files changed, 13 insertions(+), 25 deletions(-)
+
+commit f01ebe97b294444704c06c0501afddf999faddbe
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 21:38:37 2023 -0600
+
+    [vector] Minor write more idiomatic
+
+ src/hb-vector.hh | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+commit cd8f7c02017e8b574639463587460d09f12b4477
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 17:17:44 2023 -0600
+
+    [subset/cff] Optimize fdselect
+
+ src/hb-subset-cff-common.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 796a0df93e7c84f97aaba13ddb41a00447e2e902
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Jun 5 15:33:43 2023 -0700
+
+    try to fix bot
+
+ src/hb-ot-var-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit dcecb4d16b6ed34a79db245bb191d7b295585fdd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 16:03:36 2023 -0600
+
+    [subset/ValueFormat] Micro-optimize
+
+ src/OT/Layout/GPOS/ValueFormat.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 5676adefbc49174aaa654bf2df826c2712a039a9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 15:56:19 2023 -0600
+
+    [subset/cff1] Remove an unneeded copy method
+    
+    Same as serializer embed().
+
+ src/hb-ot-cff-common.hh | 10 ----------
+ src/hb-subset-cff1.cc   |  2 +-
+ 2 files changed, 1 insertion(+), 11 deletions(-)
+
+commit 7d9698123ce38fbada898760c748bddad0662831
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 15:44:50 2023 -0600
+
+    [subset/cff1] Micro-optimize
+    
+    Is ugly but shows speedup.
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 469e82a2275355e8dd814fc9d6b3f01788c08dfa
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 15:23:22 2023 -0600
+
+    [subset/PairPos] Micro-optimize
+
+ src/OT/Layout/GPOS/PairPosFormat2.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 6593d2aabac47a1e1953a0b9e74a401c02a02e93
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 15:11:43 2023 -0600
+
+    [subset/PairPos] Speed up
+
+ src/OT/Layout/GPOS/PairPosFormat2.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit ed6bee20047ed5b97e6ed9ee460bf5c551341e71
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Jun 5 14:03:22 2023 -0700
+
+    [instancer] add a test for decompile cvar tuple variations data
+
+ src/Makefile.am                      |  5 +++
+ src/meson.build                      |  1 +
+ src/test-decompile-tuple-varstore.cc | 79 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 85 insertions(+)
+
+commit bd9cdecd59b24f0886df3ce605fc1a8be18c4546
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Jun 5 13:52:05 2023 -0700
+
+    [instancer] add decompile_tuple_variations() for cvar table
+
+ src/hb-ot-var-cvar-table.hh | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+commit 452990edcae85e5f46e083cbb4494a38845ae791
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 17:46:36 2023 -0600
+
+    [cff1] Add TODO
+
+ src/hb-ot-cff1-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 072c9c06e0ebba7b93e1e1eb1388c59dac6d8d8f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 16:04:29 2023 -0600
+
+    Revert "[subset/cff1] Micro-optimize"
+    
+    This reverts commit 93020621f0651920ff92e19f543fbf2351c8311b.
+    
+    This slowed down the common path actually.
+
+ src/hb-ot-cff1-table.hh | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit f102d57a526a8c32de2e89bec630c0f8aa417bc7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 16:03:34 2023 -0600
+
+    [subset/cff1] Micro-optimize
+
+ src/hb-ot-cff1-table.hh | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+commit cdfbd7b6c6d00a6ff31496d1797c957406b94239
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:58:14 2023 -0600
+
+    [subset/cff1] Micro-optimize
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 7b97262b03bf86fe19901820903fe508e563787a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:55:18 2023 -0600
+
+    [subset/cff1] Micro-optimize
+
+ src/hb-ot-cff1-table.hh | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+commit 59387dbe43806d37e094bea15ee3b017a3fbaa8c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 14:47:27 2023 -0600
+
+    [subset/cff] Speed up sid mapping
+
+ src/hb-ot-cff1-table.hh | 47 +++++++++++++++++++++++++++++++++--------------
+ src/hb-subset-cff1.cc   | 14 ++++++++------
+ 2 files changed, 41 insertions(+), 20 deletions(-)
+
+commit 2012df0755f88f7d104e7c08897ad85b52b659ea
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Jun 5 13:46:04 2023 -0700
+
+    [instancer] add struct tuple_variation_t
+    
+    And add function to decompile TupleVariationData into the struct
+
+ src/hb-ot-var-common.hh | 111 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 111 insertions(+)
+
+commit 9f508b7393ed4cb9dbcd3ebf1ccd30cc33e5add8
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Jun 5 13:35:28 2023 -0700
+
+    [instancer] add unpack_axis_tuples () in TupleVariationHeader
+
+ src/hb-ot-var-common.hh | 47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+
+commit ffc6899b0cb788304d2ee7a8c415c3be8d04691b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 14:16:47 2023 -0600
+
+    [subset/cff1] Use a vector, instead of map, for glyph_to_sid_map
+    
+    Much faster.
+
+ src/hb-ot-cff1-table.hh     | 20 ++++++++++++--------
+ src/hb-ot-cff2-table.hh     |  2 +-
+ src/hb-subset-cff-common.hh | 12 +++++++++---
+ src/hb-subset-cff1.cc       | 13 ++++++++-----
+ 4 files changed, 30 insertions(+), 17 deletions(-)
+
+commit 7b0ecbd8960e376c9c2d8bb9e95b4d9b616d1743
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Jun 5 13:08:12 2023 -0700
+
+    [instancer] add struct tuple_delta_t to represent 1 tuple variation
+
+ src/hb-ot-var-common.hh | 126 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 126 insertions(+)
+
+commit 1636e112c477369e0c95192ce7c94966fe48c85c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 13:44:00 2023 -0600
+
+    [cff] Micro-optimize
+
+ src/hb-ot-cff-common.hh | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+commit 27299e0d20fa06dfbde60631c6273db8624ac0c4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 13:41:04 2023 -0600
+
+    [subset/cff] Minor use hb_len()
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 377ccb31e16389887980bdea2830ce7829b50960
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 13:38:06 2023 -0600
+
+    [subset/cff] Speed up set_offset_at
+
+ src/hb-ot-cff-common.hh | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+commit 90122925ffcd786365bfb1907c3e6b88230b73d0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 13:33:10 2023 -0600
+
+    [subset/cff1] Minor speedup
+
+ src/hb-subset-cff1.cc | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit 238cb0fbfd6f7143ad718c7aa488c30865f253fd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon Jun 5 13:27:03 2023 -0600
+
+    [subset/cff1] Speed up for retaingids
+
+ src/hb-subset-cff1.cc | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 9de413bf010d7a73082931ee081f595fa5e24acd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 17:43:48 2023 -0600
+
+    [subset/cff1] Micro-optimize
+
+ src/hb-subset-cff1.cc | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit ca353e644d3b920f9559cdc7b29b7460edee7f88
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 17:25:29 2023 -0600
+
+    [subset/cff1] Style
+
+ src/hb-subset-cff1.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit e077ca893eadd993bd52bb902c6f43e488f4a509
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 16:23:36 2023 -0600
+
+    [subset/cff] Micro-optimize
+
+ src/hb-subset-cff1.cc | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit 126d1441964840808a1551fe404beec7f1fe8c5e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 16:23:36 2023 -0600
+
+    [subset/cff] Micro-optimize
+
+ src/hb-subset-cff-common.cc | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit a24025c90d6ccc2846b1bec71fa3ad86329fe3c4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 16:15:43 2023 -0600
+
+    [subset/cff1] Micro-optimize
+
+ src/hb-subset-cff1.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 5a3ac0ab349067308dec04a36fac4d58f46c4c42
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:37:25 2023 -0600
+
+    [subset/cff1] Another micro-optimization
+
+ src/hb-subset-cff1.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 331398286aa5a7ec7fc7066ae9959756f8ee1735
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:33:22 2023 -0600
+
+    [subset/cff1] Micro-optimize
+
+ src/hb-subset-cff1.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 595aa58379bbbb14149212b9619f6047751d6f78
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:24:36 2023 -0600
+
+    [UnsizedArray] Minor simplify operator[]
+
+ src/hb-open-type.hh | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 319ea3b967fdcac14af55ce229740f2fd3c764af
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:23:20 2023 -0600
+
+    [UnsizedArrayOf] Simplify operator[]
+    
+    No need to check for overflow. Caller is responsible for correct
+    access.
+
+ src/hb-open-type.hh | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+commit 6188a3f5a42644b1b86082012c046c23ba443393
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:12:56 2023 -0600
+
+    [subset/cff] Minor signedness change
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 887f299351a79f608ac93fbee1ec4f4f7fc7e02c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:11:17 2023 -0600
+
+    [susbet/cff] Reuse iterator
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f5b82846336fd01e6ef613c8bd0cf5456da2db35
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:10:08 2023 -0600
+
+    [subset/cff1] Minor use hb_len
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 70638170714e417921eb98db001c3248ed235d46
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 15:03:16 2023 -0600
+
+    [subset/cff1] Speed up writing 1byte charstrings
+    
+    As in the holes of retaingids.
+
+ src/hb-ot-cff-common.hh | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+commit 21ff023a46b567b4d2b6297088e205b83ab1bbdf
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 14:08:24 2023 -0600
+
+    [subset/cff1] Speed up encoding for retaingids
+
+ src/hb-subset-cff1.cc | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+commit b15222399822baf52a735743ca281bcd98173fec
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 13:58:10 2023 -0600
+
+    [cff] Minor type change
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 640774b9f190226609d5948183d1df8055ceceb4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 13:26:14 2023 -0600
+
+    [subset/cff] Speed up subsr subset for retaingids
+
+ src/hb-subset-cff-common.hh | 32 +++++++++++++++-----------------
+ 1 file changed, 15 insertions(+), 17 deletions(-)
+
+commit 6b11a3d971807f6fa90f284739491acc4ed21cca
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 13:18:43 2023 -0600
+
+    [subset/cff] Speed up closure_subroutines for retaingids
+
+ src/hb-subset-cff-common.hh | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+commit 31014832a9925bbc2ad892fa5de1704e8e8f5312
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 12:58:02 2023 -0600
+
+    [cff1] More hygiene
+
+ src/hb-ot-cff1-table.hh | 15 ++++++++++-----
+ src/hb-subset-cff1.cc   |  4 ++--
+ 2 files changed, 12 insertions(+), 7 deletions(-)
+
+commit bf0a08c930506a7301517f5678c2fdb1b34b6595
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 12:54:35 2023 -0600
+
+    [cff1] Hygiene
+
+ src/hb-open-type.hh     |  2 +-
+ src/hb-ot-cff1-table.hh | 13 +++++++------
+ src/hb-subset-cff1.cc   |  2 +-
+ 3 files changed, 9 insertions(+), 8 deletions(-)
+
+commit ebc5257e29fb803e0b7c893a2dc0187c3641040f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 11:25:16 2023 -0600
+
+    [cff1] Add a couple of unlikely's
+
+ src/hb-ot-cff1-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 9cdc0b6419d3371c94c919a100b64ece99e89fe0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 11:18:56 2023 -0600
+
+    [subset/cff] Speed up subset_cff_fdselect
+
+ src/hb-ot-cff-common.hh     | 31 +++++++++++++++++++++++++++----
+ src/hb-subset-cff-common.cc |  5 ++++-
+ 2 files changed, 31 insertions(+), 5 deletions(-)
+
+commit 858a022358807720d6ff7fc20206484997766524
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 10:55:41 2023 -0600
+
+    Revert "[cff] Optimize writing out Index offsets"
+    
+    This reverts commit 78ba23c58766c16992ddc4e3af403824aa845fe2.
+    
+    Not enough gain, and bloats code size.
+
+ src/hb-ot-cff-common.hh | 52 -------------------------------------------------
+ 1 file changed, 52 deletions(-)
+
+commit 78ba23c58766c16992ddc4e3af403824aa845fe2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 10:52:19 2023 -0600
+
+    [cff] Optimize writing out Index offsets
+
+ src/hb-ot-cff-common.hh | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+commit 89ce804833a3d4f53cbdfdc728eea3c393a84ecd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 10:20:39 2023 -0600
+
+    [serialize] Remove attribute malloc
+    
+    This broke tests. It wasn't technically correct.
+
+ src/hb-serialize.hh | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 3f2a1b644a470d5dcc9b8347a2cc1914b3550da3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 10:13:53 2023 -0600
+
+    Fix build
+
+ src/hb-ot-cmap-table.hh | 2 +-
+ src/hb-serialize.hh     | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit e1715056fc15ce37ff486486ea89ee51412d3e51
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 10:09:02 2023 -0600
+
+    [serialize] One more attribute
+
+ src/hb-serialize.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 15048e50ece21a8b22b4c00c728f7c841175f560
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 10:07:04 2023 -0600
+
+    [serialize] Add more function attributes
+
+ src/OT/glyf/SubsetGlyph.hh | 2 +-
+ src/hb-serialize.hh        | 6 ++++--
+ 2 files changed, 5 insertions(+), 3 deletions(-)
+
+commit aad12ca649ddb0979f4815b0fd824bae9c918abe
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 09:57:51 2023 -0600
+
+    [serialize] Add a few function attributes
+
+ src/hb-serialize.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 4e076da9d0492dba35d38305876cc6d5badf6f75
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 09:48:42 2023 -0600
+
+    Another try at fixing build
+
+ src/OT/name/name.hh | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+commit b08866afda7f88b8df4e6603e4e35adfbe7e0761
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 09:44:37 2023 -0600
+
+    Fix build
+
+ src/OT/name/name.hh | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 82741304d3636de1a6ffbe5ca13012bebb94229b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 09:41:41 2023 -0600
+
+    [subset] start_embed never returns nullptr
+    
+    Remove checks.
+
+ src/OT/Color/CBDT/CBDT.hh                          |  8 +-----
+ src/OT/Color/COLR/COLR.hh                          |  3 +--
+ src/OT/Color/sbix/sbix.hh                          |  5 ----
+ src/OT/Layout/GDEF/GDEF.hh                         |  3 ---
+ src/OT/Layout/GPOS/AnchorFormat3.hh                |  1 -
+ src/OT/Layout/GPOS/CursivePosFormat1.hh            |  1 -
+ .../Layout/GSUB/ReverseChainSingleSubstFormat1.hh  |  1 -
+ src/OT/glyf/glyf.hh                                |  5 ++--
+ src/OT/name/name.hh                                |  3 +--
+ src/hb-ot-cff-common.hh                            |  2 +-
+ src/hb-ot-cmap-table.hh                            |  8 ++----
+ src/hb-ot-hdmx-table.hh                            |  3 +--
+ src/hb-ot-hmtx-table.hh                            |  3 +--
+ src/hb-ot-layout-common.hh                         | 14 +++++-----
+ src/hb-ot-layout-gsubgpos.hh                       |  6 +----
+ src/hb-ot-math-table.hh                            |  4 ---
+ src/hb-ot-post-table.hh                            |  3 +--
+ src/hb-ot-stat-table.hh                            |  2 --
+ src/hb-ot-var-common.hh                            |  1 -
+ src/hb-ot-vorg-table.hh                            |  2 +-
+ src/hb-subset-cff1.cc                              | 31 +++++++---------------
+ src/hb-subset-cff2.cc                              | 20 +++++---------
+ 22 files changed, 37 insertions(+), 92 deletions(-)
+
+commit c2eaedd2cda2da854834f1fd59dadffeec9b45cd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 09:25:07 2023 -0600
+
+    [fuzzing] Add a test font
+    
+    From https://oss-fuzz.com/testcase-detail/5855710991482880
+
+ ...case-minimized-hb-subset-fuzzer-5855710991482880.fuzz | Bin 0 -> 1048 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit af3fdf1f9e09fb7e47d4528d81fd510730b80745
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 09:22:42 2023 -0600
+
+    [subset/glyf] Simplify error handling
+
+ src/OT/glyf/glyf.hh | 31 ++++++++++---------------------
+ 1 file changed, 10 insertions(+), 21 deletions(-)
+
+commit 3dd1de46d637f36bc30bbd7dd8be3a058d1f1864
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 09:15:14 2023 -0600
+
+    [subset/glyf] Fix a few return_trace's
+
+ src/OT/glyf/glyf.hh | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+commit 73f2f935a077274fef3343e36352b4e01678d662
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Jun 4 09:12:18 2023 -0600
+
+    [subset/glyf] Fix another leak
+
+ src/OT/glyf/glyf.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit 3d08a2f10cada7c72513d9491ddf66820ef008fb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 23:38:38 2023 -0600
+
+    [subset/glyf] Fix leak
+
+ src/OT/glyf/glyf.hh | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+commit fc33200d79aacd007773b8ed6c64486848b8ebc7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 23:29:39 2023 -0600
+
+    [subset/glyf] Avoid a vector copy
+    
+    Oops!
+
+ src/OT/glyf/glyf.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 3bfcbd61490a3fc44f28b813aa8a89bcb9e60e48
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 23:17:56 2023 -0600
+
+    [subset/glyf] Minor use range lopp
+
+ src/OT/glyf/glyf.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 917c8d0ac526ef1a0217e74f2e9553fd81cbb6b9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 23:15:56 2023 -0600
+
+    [subset/glyf] Minor change of value
+
+ src/OT/glyf/glyf.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2b8c43135ad409c9d613a1e80a43924594fa1c3f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 23:01:27 2023 -0600
+
+    [vector] Oops!
+
+ src/hb-vector.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 054f966a570ef37e0153b6591cbb2ff165517738
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 22:52:16 2023 -0600
+
+    [subset/cff1] Don't allocate memory for retaingid holes
+    
+    40% speedup in BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/retaingids/10
+    benchmark.
+
+ src/hb-cff-interp-common.hh |  2 ++
+ src/hb-static.cc            |  3 +++
+ src/hb-subset-cff-common.hh | 14 ++++++++++++--
+ src/hb-vector.hh            | 10 ++++++++--
+ 4 files changed, 25 insertions(+), 4 deletions(-)
+
+commit b5792f117a8df69025baf0543bc978a0e0f6ee72
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 22:24:06 2023 -0600
+
+    [subset] Reuse num_glyphs in various places
+
+ src/OT/Color/CBDT/CBDT.hh   | 3 ++-
+ src/hb-ot-var-hvar-table.hh | 3 ++-
+ src/hb-subset-cff-common.hh | 6 ++++--
+ src/hb-subset-cff1.cc       | 5 +++--
+ 4 files changed, 11 insertions(+), 6 deletions(-)
+
+commit 7e4311a868e33d21eccb0f714572f552028931c0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 22:11:47 2023 -0600
+
+    [cff] Speed up for retaingids
+
+ src/hb-subset-cff-common.hh | 26 ++++++++++++++++----------
+ 1 file changed, 16 insertions(+), 10 deletions(-)
+
+commit ca237e6ba89193c92161298accc57b2a6542a296
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 22:07:29 2023 -0600
+
+    [subset/cff] Reuse num_glyphs
+
+ src/hb-subset-cff-common.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 1590754ba8f292df6e1e1b58ff874fb0efda87ee
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 22:04:52 2023 -0600
+
+    [subset/cff] Speed up for retaingids
+
+ src/hb-subset-cff-common.cc | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+commit dff3a936d21703d0a548546f5fcfa3a122beda27
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 22:00:28 2023 -0600
+
+    [subset/cff1] Speed up for retaingids
+
+ src/hb-subset-cff1.cc | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+commit fa8d15d520b9b1f9012aef7ecdf4f3947c162e96
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 21:58:21 2023 -0600
+
+    [subset/cff1] Reuse num_glyphs
+
+ src/hb-subset-cff1.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 937ead2f02a13d551b428a8358a5e17550387ee6
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 21:38:56 2023 -0600
+
+    [subset/hvar] Speed up for retaingids
+
+ src/hb-ot-var-hvar-table.hh | 32 ++++++++++++++++++--------------
+ 1 file changed, 18 insertions(+), 14 deletions(-)
+
+commit acab716b1c8b1a071d0551f8e4df07444b2c0446
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 21:15:36 2023 -0600
+
+    [subset/hvar] Speed up for retaingids
+
+ src/hb-ot-var-hvar-table.hh | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+commit bc6dbf436a373579f405b6bf91c256b7ac779f92
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 21:09:33 2023 -0600
+
+    [subset/gvar] Micro-optimize
+
+ src/hb-ot-var-gvar-table.hh | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+commit 841347533adfbdc3de79f7bb288220e380246d56
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 21:08:30 2023 -0600
+
+    [subset/gvar] Speed up for retaingids
+
+ src/hb-ot-var-gvar-table.hh | 53 ++++++++++++++++++++++++++++++---------------
+ 1 file changed, 36 insertions(+), 17 deletions(-)
+
+commit 87cf09bd2c7b7bb001a974296de13617a34e6627
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 21:00:56 2023 -0600
+
+    [subset/loca] Fix up for retaingid null glyphs at the end
+    
+    We currently don't have those, but in case we add.
+
+ src/OT/glyf/glyf-helpers.hh | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+commit 2fb670a5281bbfe057d9ebc1dd84fb67d9d6c8f7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 20:56:04 2023 -0600
+
+    [subset/gvar] Speed up for retaingids
+
+ src/hb-ot-var-gvar-table.hh | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 5b1679343afc9d6a7acc8a6e0f3c1974516e3501
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 20:45:52 2023 -0600
+
+    [subset/hdmx] Micro-optimize
+
+ src/hb-ot-hdmx-table.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit 9b733532dff1e31b93d03a30443af6e67229da4c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 20:44:08 2023 -0600
+
+    [subset/hdmx] Fix build
+
+ src/hb-ot-hdmx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4d4792ce3db59844b8a220712e12cd6873d3d7c3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 20:34:51 2023 -0600
+
+    [subset/hdmx] Speed up more for retaingids
+
+ src/hb-ot-hdmx-table.hh | 37 +++++++++++++++++++++----------------
+ 1 file changed, 21 insertions(+), 16 deletions(-)
+
+commit a3f7ed709b8dec880fab338d8db6494c2d7de998
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 20:25:14 2023 -0600
+
+    [subset/hdmx] Don't clear memory unnecessarily
+
+ src/hb-ot-hdmx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e263c3ccbbca438767c180431e695a99c575a695
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 20:20:57 2023 -0600
+
+    [subset/hdmx] Speed up
+
+ src/hb-ot-hdmx-table.hh | 2 +-
+ src/hb-subset-plan.hh   | 9 ---------
+ 2 files changed, 1 insertion(+), 10 deletions(-)
+
+commit 0e16be9b2cfc549edbaa4a643d9c15c6570771bd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 19:45:44 2023 -0600
+
+    [subset-plan] Reuse glyph_for_gid result
+
+ src/hb-subset-plan.cc | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 590fb3529a27a2a652c74baa2c8bebad34ec5c42
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 19:21:22 2023 -0600
+
+    [subset] Reduce memory pressure
+
+ src/hb-subset.cc | 67 +++++++++++++++++++++++++++++---------------------------
+ 1 file changed, 35 insertions(+), 32 deletions(-)
+
+commit c03c3000164c873275a8b60fa07661a9fe74243e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 19:05:10 2023 -0600
+
+    [subset] Tweak memory allocation
+    
+    Reduces chances of rework, specially for glyf table if padding
+    is needed...
+
+ src/hb-subset.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 38fa0323303bf6c289314932ad4d41ac40734eac
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 18:51:09 2023 -0600
+
+    Revert "[subset/loca] Build in the serializer memory"
+    
+    This reverts commit 546b51818666ca1ddb01824f752eccbd6a751b4b.
+
+ src/OT/glyf/glyf-helpers.hh | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+commit 546b51818666ca1ddb01824f752eccbd6a751b4b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 18:50:35 2023 -0600
+
+    [subset/loca] Build in the serializer memory
+    
+    Because it's hot. Doesn't seem to speed up though. Slight
+    slowdown. Going to revert.
+
+ src/OT/glyf/glyf-helpers.hh | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+commit 3cb2b49e61fed1aef8c17432abd25f536a919c30
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 18:44:56 2023 -0600
+
+    [subset/loca] Shuffle code around
+
+ src/OT/glyf/glyf-helpers.hh | 15 +++++++--------
+ src/OT/glyf/glyf.hh         | 21 +++++++++------------
+ 2 files changed, 16 insertions(+), 20 deletions(-)
+
+commit f014112d16a205e5b9e9406205e7854076df8b02
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 18:27:24 2023 -0600
+
+    Revert "[subset] Allow adding table directly from subset()"
+    
+    This reverts commit 25a6514887ebe899bd4ede1e283e067f97e15def.
+
+ src/hb-ot-hmtx-table.hh | 39 +++++++++++++++++----------------------
+ src/hb-subset.cc        | 18 ++----------------
+ 2 files changed, 19 insertions(+), 38 deletions(-)
+
+commit 25a6514887ebe899bd4ede1e283e067f97e15def
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 18:26:36 2023 -0600
+
+    [subset] Allow adding table directly from subset()
+    
+    And do it for hmtx. Going to revert since it slows things down.
+    Apparently the serializer buffer is in caches and hot, so faster
+    to write to and copy even.
+
+ src/hb-ot-hmtx-table.hh | 39 ++++++++++++++++++++++-----------------
+ src/hb-subset.cc        | 18 ++++++++++++++++--
+ 2 files changed, 38 insertions(+), 19 deletions(-)
+
+commit b0d0babb2e9fe81ee1e96dddfc1fadfeac0b3bab
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 17:14:55 2023 -0600
+
+    [subset/loca] Rewrite loop faster
+
+ src/OT/glyf/glyf-helpers.hh | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+commit 8dab4441021822f37b3c17194357932c1afc3313
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 17:06:30 2023 -0600
+
+    [subset/hmtx] Micro-optimize last commit
+    
+    hb_zip has its own overhead...
+
+ src/hb-ot-hmtx-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit e981dc24c8f04c42addce2a595ab4d60d76dae36
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 17:01:52 2023 -0600
+
+    [subset/hmtx] Rewrite loop faster for retaingid
+
+ src/hb-ot-hmtx-table.hh | 23 ++++++++++-------------
+ 1 file changed, 10 insertions(+), 13 deletions(-)
+
+commit 4a9da0261925c116e738917d8692ecf9d5c90d77
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 16:46:29 2023 -0600
+
+    [subset/hmtx] Micro-optimize
+
+ src/hb-ot-hmtx-table.hh | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+commit 6a3fcc64f3f8d72eb87c15f23720665b42c22f27
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 16:38:18 2023 -0600
+
+    [map] Don't call hash() if map is empty
+
+ src/hb-map.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 735d249639a83b7c12c1792551ed4cbbebce7ef2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 16:35:03 2023 -0600
+
+    [map] Remove an unlikely
+    
+    Empty maps are common in some subsetting operations.
+
+ src/hb-map.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ca27925d55b89a049c1013888a55c4784d255f47
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 16:18:15 2023 -0600
+
+    Use hb_codepoint_pair_t in more places
+
+ src/OT/Layout/GSUB/Common.hh      |  2 --
+ src/OT/glyf/glyf-helpers.hh       |  4 ++--
+ src/graph/pairpos-graph.hh        | 10 +++++-----
+ src/graph/test-classdef-graph.cc  |  2 +-
+ src/hb-algs.hh                    |  2 ++
+ src/hb-bit-set-invertible.hh      |  4 ++--
+ src/hb-bit-set.hh                 |  2 +-
+ src/hb-map.hh                     |  2 +-
+ src/hb-ot-cmap-table.hh           |  6 +++---
+ src/hb-ot-hmtx-table.hh           |  4 ++--
+ src/hb-ot-layout-common.hh        |  8 ++++----
+ src/hb-set.hh                     |  4 ++--
+ src/hb-subset-plan-member-list.hh |  4 ++--
+ src/hb-subset-plan.cc             |  9 ++++-----
+ src/test-map.cc                   |  6 +++---
+ src/test-set.cc                   |  2 +-
+ 16 files changed, 35 insertions(+), 36 deletions(-)
+
+commit 841e86fd9873dba727af843d638880d8257c89fb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 16:09:45 2023 -0600
+
+    [subset/hmtx] Further speedup!
+
+ src/hb-ot-hmtx-table.hh | 44 +++++++++++++++++++++++++++-----------------
+ 1 file changed, 27 insertions(+), 17 deletions(-)
+
+commit de729ec10566e8dd8bf1f22d9bbf73c2b9f54aeb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 15:48:54 2023 -0600
+
+    [meta] Return reference from reference-wrapper
+
+ src/hb-iter.hh | 6 +++---
+ src/hb-meta.hh | 8 ++++----
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+commit c7493efeafcf2ac9af39e8049a2a907065e26756
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 15:39:27 2023 -0600
+
+    [subset/loca] Micro-optimize
+
+ src/OT/glyf/glyf-helpers.hh | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+commit 13a4c7b3d3bb6c3fb2cbbed1f1de717f58162dae
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 15:12:53 2023 -0600
+
+    [subset/hmtx] Comment
+
+ src/hb-ot-hmtx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4da2996fe2dba5134e7e7f40cb089c9a1e30fb64
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 15:08:20 2023 -0600
+
+    [doc] Fix
+
+ src/hb-common.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c3e7f4516658d18c60160b567939bad746404d6e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Jun 3 14:56:47 2023 -0600
+
+    Add HB_CODEPOINT_INVALID
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/4262
+
+ docs/harfbuzz-sections.txt |  1 +
+ src/hb-common.h            | 10 ++++++++++
+ src/hb-map.h               |  2 +-
+ src/hb-set.h               |  2 +-
+ 4 files changed, 13 insertions(+), 2 deletions(-)
+
+commit efefec13ccedc1461867544e2066e2042e86c66f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 20:33:52 2023 -0600
+
+    [subset/glyf] Remove unneeded codepath
+
+ src/OT/glyf/SubsetGlyph.hh | 7 -------
+ 1 file changed, 7 deletions(-)
+
+commit ac1f5ca0d9cb94089954a2e4ddf7e064600c5004
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 17:07:44 2023 -0600
+
+    [subset/loca] Micro-optimize
+
+ src/OT/glyf/glyf-helpers.hh | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 6eae932566330f1485be920bc942069020ca24b0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 17:05:27 2023 -0600
+
+    [subset/loca] Reduce a vector allocation
+
+ src/OT/glyf/glyf-helpers.hh | 46 +++++++++++++++++++++++++++++----------------
+ src/OT/glyf/glyf.hh         | 34 ++++++++++++++-------------------
+ 2 files changed, 44 insertions(+), 36 deletions(-)
+
+commit cd249d236494784b21502b151d90b326259bae93
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 16:15:05 2023 -0600
+
+    [subset/hmtx] Micro-optimize
+
+ src/hb-ot-hmtx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ec8965e432db27f81b3275c6979fef707f3b9da9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 16:10:25 2023 -0600
+
+    [subset/glyf] Don't clear loca allocation
+
+ src/OT/glyf/glyf-helpers.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 916629d1827bbf450d41f06639af27a708634713
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 16:08:49 2023 -0600
+
+    [subset/hmtx] Don't clear allocation
+
+ src/hb-ot-hmtx-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 24b069cd53cec2d8afa4e7b90cf5b47c91e215c9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 15:55:53 2023 -0600
+
+    [subset] Pre-alloc a few maps
+
+ src/hb-multimap.hh               |  5 +++++
+ src/hb-ot-post-table-v2subset.hh | 12 +++++++++---
+ src/hb-subset-plan.cc            |  2 ++
+ 3 files changed, 16 insertions(+), 3 deletions(-)
+
+commit 7319d0d71226c15c6c744c6d4e2def72cd20b368
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 15:41:47 2023 -0600
+
+    [subset-plan] Add a couple of map pre-allocations
+    
+    Approximate...
+
+ src/hb-subset-plan.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 76904b0423119ad1a2540bd98bb69246781eacc5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 15:30:12 2023 -0600
+
+    [subset-plan] Simplify / speedup planning glyphset
+
+ src/hb-subset-plan.cc | 27 ++++++++-------------------
+ 1 file changed, 8 insertions(+), 19 deletions(-)
+
+commit 965ce7bba4bf8203cce04b6d21b393532e2e7131
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 15:24:00 2023 -0600
+
+    [subset-plan] Speed up planning new_to_old_gid_list
+
+ src/hb-subset-plan.cc | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+commit b67e464b1cefb733df073590588ab8fcca320bfc
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 15:11:06 2023 -0600
+
+    [subset/retaingid] Regain perf lost
+    
+    In 0f12fd5a66a5dd1c3c9ac5ea8a52341bafcfe567
+
+ src/OT/glyf/glyf.hh               | 20 ++++++--------------
+ src/hb-ot-hmtx-table.hh           | 14 ++++++++------
+ src/hb-subset-plan-member-list.hh |  2 +-
+ src/hb-subset-plan.cc             | 10 ++++------
+ 4 files changed, 19 insertions(+), 27 deletions(-)
+
+commit 0f12fd5a66a5dd1c3c9ac5ea8a52341bafcfe567
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 13:58:55 2023 -0600
+
+    [subset/glyf] Fix for non-monotonic glyphmap
+    
+    Slows things down again, but is correct. Still a good win
+    combined with the previous changes.
+
+ src/OT/glyf/glyf.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit 66ce902c3aeccede074a21abafa7482ca24e5031
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 13:53:21 2023 -0600
+
+    [glyf] Reduce allocation again
+
+ src/OT/glyf/glyf.hh | 35 ++++++++++++++++++++++-------------
+ 1 file changed, 22 insertions(+), 13 deletions(-)
+
+commit 0e0110e7f210e568e8afc6d63a200e2e28004ebe
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 13:34:58 2023 -0600
+
+    [glyf] Avoid a SubsetGlyph copy
+    
+    Unfortunately hb_second() always does a copy...
+
+ src/OT/glyf/glyf.hh | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+commit 33ea8b5e5d152159cd2acbd4054b99cd5559d195
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Jun 2 13:10:52 2023 -0600
+
+    [subset/glyf] Don't allocate empty SubsetGlyf's
+    
+    Shows 33% speedup on Mplus/retaingid/10 benchmark:
+    
+    Comparing before to after
+    Benchmark                                                                   Time             CPU      Time Old      Time New       CPU Old       CPU New
+    --------------------------------------------------------------------------------------------------------------------------------------------------------
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10                -0.3296         -0.3294             0             0             0             0
+
+ src/OT/glyf/glyf.hh | 47 +++++++++++++++++++++++++++++------------------
+ 1 file changed, 29 insertions(+), 18 deletions(-)
+
+commit ad872e231349a5cfdd2daf34a8021216431f5d59
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Jun 2 18:32:09 2023 +0000
+
+    [subset] Optimize hmtx/vmtx serialization.
+    
+    Make serializer allocation up front to avoid bounds checking overhead for each metric.
+    
+    Benchmarks:
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10_median                   -0.1005         -0.1005             0             0             0             0
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/64_median                   -0.0693         -0.0692             0             0             0             0
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/512_median                  -0.0294         -0.0293             1             1             1             1
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/4096_median                 -0.0033         -0.0032             3             3             3             3
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10000_median                +0.0170         +0.0171             7             7             7             7
+
+ src/hb-ot-hmtx-table.hh | 24 +++++++++---------------
+ 1 file changed, 9 insertions(+), 15 deletions(-)
+
+commit c6368e014dbfaef1515507b41414a99f998d8616
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 20:51:17 2023 -0600
+
+    [map] Return const reference from operator()
+    
+    Like we do in operator[].
+
+ src/hb-map.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b04ca1c188bfd7113c9c4ef546fa8b1535a28d30
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 20:43:07 2023 -0600
+
+    Revert "[subset/glyf] Exact allocation"
+    
+    This reverts commit a830f085c849846f8441f5d92d4db36130ef71f8.
+    
+    Weirdly enough in a benchmark I'm running I see this show
+    some slowdown. Makes zero sense.
+
+ src/OT/glyf/glyf.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a830f085c849846f8441f5d92d4db36130ef71f8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 20:37:29 2023 -0600
+
+    [subset/glyf] Exact allocation
+
+ src/OT/glyf/glyf.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ff0b85cf571cb94dbbc5091179f7874926a88dbe
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 20:30:56 2023 -0600
+
+    [subset/glyf] Empty .notdef only if old-gid was also 0
+    
+    Otherwise it wasn't a .notdef, even if new-gid is 0.
+
+ src/OT/glyf/glyf.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit 65a7d8c6f033963d70d03885226bb5a07a397488
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 20:20:00 2023 -0600
+
+    [glyf] Empty glyphs need no padding
+
+ src/OT/glyf/SubsetGlyph.hh | 12 +-----------
+ 1 file changed, 1 insertion(+), 11 deletions(-)
+
+commit 73c18d1d42792cba70634a0cf8b7324f79c9e701
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 20:06:42 2023 -0600
+
+    [glyf] Micro-optimize padded_offsets
+
+ src/OT/glyf/glyf.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 88d8a6d69f7baf57d29aaa1fe29be0f05956652b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 19:24:02 2023 -0600
+
+    [BEInt] Use packed-int trick for writing as well
+
+ src/hb-algs.hh | 67 +++++++++++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 45 insertions(+), 22 deletions(-)
+
+commit 4d853b8ba6e491ec85a7077abb208740b44e61bf
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 18:47:58 2023 -0600
+
+    [subset/regaingid/glyf] Add a fastpath for empty glyphs
+    
+    Mplus benchmark:
+    Comparing before to after
+    Benchmark                                                                      Time             CPU      Time Old      Time New       CPU Old       CPU New
+    -----------------------------------------------------------------------------------------------------------------------------------------------------------
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10                   -0.1764         -0.1771             0             0             0             0
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/64                   -0.1394         -0.1394             0             0             0             0
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/512                  -0.0644         -0.0645             0             0             0             0
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/4096                 +0.0132         +0.0131             1             1             1             1
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10000                -0.0029         -0.0034             3             3             3             3
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/10                              +0.0364         +0.0362             0             0             0             0
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/64                              +0.0346         +0.0343             0             0             0             0
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/512                             +0.0271         +0.0268             0             0             0             0
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/4096                            +0.0193         +0.0193             1             1             1             1
+    BM_subset/subset_glyphs/Mplus1p-Regular.ttf/10000                           -0.0240         -0.0243             2             2             2             2
+    OVERALL_GEOMEAN                                                             -0.0305         -0.0307             0             0             0             0
+
+ src/OT/glyf/SubsetGlyph.hh | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+commit 6ec7629fba96f8be175eac108f7eee83de6cae21
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 18:18:30 2023 -0600
+
+    [subset/glyf] Add a const
+
+ src/OT/glyf/SubsetGlyph.hh | 2 +-
+ src/OT/glyf/glyf.hh        | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 9f54ab922f42e954f19432aeacb4bb4022c27e3d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 17:45:03 2023 -0600
+
+    [subset-plan] Keep a reverse-gid vector
+    
+    To speed up iteration.
+
+ src/hb-ot-hmtx-table.hh           | 16 +++++++++-------
+ src/hb-subset-plan-member-list.hh |  2 ++
+ src/hb-subset-plan.cc             |  9 ++++++++-
+ 3 files changed, 19 insertions(+), 8 deletions(-)
+
+commit 6b0d3867978c3f42ab8dfbebcedd7567adf28bfe
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Jun 1 23:59:55 2023 +0000
+
+    [subset] in subset benchmarks switch nohinting with retaingids.
+    
+    retain gids is a more interesting case than no hinting for performance.
+
+ perf/benchmark-subset.cc | 21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+commit 1ae99d1a10e4add937488591632f94edca7bdbdd
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Jun 1 15:22:26 2023 -0700
+
+    bug fix
+
+ src/hb-ot-var-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit aa7dd70a862d6fa516e0aa8194e4cd4983cda934
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Jun 1 14:24:33 2023 -0600
+
+    [hmtx] Reduce map usage slightly
+
+ src/hb-ot-hmtx-table.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit f41c5ec961c559a99045cc84760bac422998b2e3
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Jun 1 18:38:05 2023 +0000
+
+    [map] update map benchmark to also test lookups that hit.
+
+ perf/benchmark-map.cc | 52 ++++++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 45 insertions(+), 7 deletions(-)
+
+commit 4acf6a82bf47a602a9378c84d80a9ccb885145d0
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue May 30 09:26:58 2023 -0700
+
+    [instancer-solver] port solver fix from fonttools
+    
+    See https://github.com/fonttools/fonttools/issues/3139
+
+ src/hb-subset-instancer-solver.cc   |  2 +-
+ src/test-subset-instancer-solver.cc | 18 ++++++++++++++++++
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+commit f3b4d35f362efb818959814b741e94facda5fd29
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon May 29 22:38:40 2023 +0000
+
+    [subset] Fix fuzzer crash.
+    
+    https://oss-fuzz.com/testcase-detail/6608005089853440
+
+ src/hb-serialize.hh                                       |   6 +++++-
+ ...z-testcase-minimized-hb-subset-fuzzer-6608005089853440 | Bin 0 -> 999 bytes
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+commit ff326fbe8f5dfb579b6468ffba13bad279322d2b
+Author: Garret Rieger <grieger at google.com>
+Date:   Mon May 29 21:31:01 2023 +0000
+
+    [repacker] check the result of add_buffer() in other places where it's called.
+
+ src/graph/classdef-graph.hh |  8 +++++++-
+ src/graph/coverage-graph.hh |  8 +++++++-
+ src/graph/gsubgpos-graph.hh | 12 +++++++++---
+ 3 files changed, 23 insertions(+), 5 deletions(-)
+
+commit 66a84355ab8a6c2b1e724e844ef4a79ca22a5cf7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon May 29 17:17:15 2023 -0600
+
+    [hash] Use unsigned types
+    
+    Hopefully ubsan wouldn't complain about overflows now.
+
+ src/hb-algs.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 4a93576bca0f56e82a1d8ad67733df9c5ddb8dcd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun May 28 13:22:35 2023 -0600
+
+    Revert "[map] Speedup for int types"
+    
+    This reverts commit c1b75f5ff0460274229801816265a0efe5731b3a.
+    
+    I was seeing very long chains (140) and a 17% slowdown in
+    BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/512
+    
+    Bummer.
+
+ src/hb-map.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit c1b75f5ff0460274229801816265a0efe5731b3a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun May 28 12:53:17 2023 -0600
+
+    [map] Speedup for int types
+    
+    Since our int hash is now good, we don't need the modulo prime
+    here, so forgo it.  Major speedup:
+    
+    Comparing before to after
+    Benchmark                              Time             CPU      Time Old      Time New       CPU Old       CPU New
+    -------------------------------------------------------------------------------------------------------------------
+    BM_MapInsert/16                     -0.4136         -0.4137             6             4             6             4
+    BM_MapInsert/64                     -0.4442         -0.4441             6             3             6             3
+    BM_MapInsert/512                    -0.5382         -0.5383             8             4             8             4
+    BM_MapInsert/4096                   -0.4160         -0.4162             8             5             8             5
+    BM_MapInsert/32768                  -0.3256         -0.3258            12             8            12             8
+    BM_MapInsert/262144                 -0.1723         -0.1727            11            10            11             9
+    BM_MapInsert/1048576                -0.2310         -0.2309            28            22            28            22
+    BM_MapLookup/16                     -0.0247         -0.0247             3             3             3             3
+    BM_MapLookup/64                     -0.1039         -0.1038             3             3             3             3
+    BM_MapLookup/512                    -0.1076         -0.1079             4             3             4             3
+    BM_MapLookup/4096                   -0.3729         -0.3732             9             6             9             6
+    BM_MapLookup/32768                  +0.2467         +0.2468             9            12             9            12
+    BM_MapLookup/262144                 -0.1862         -0.1868            14            11            14            11
+    BM_MapLookup/1048576                +0.1159         +0.1160            15            17            15            17
+    OVERALL_GEOMEAN                     -0.2414         -0.2416             0             0             0             0
+
+ src/hb-map.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 7f111787e467a52b9b29daae3783a27b620c5593
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat May 27 12:41:05 2023 -0600
+
+    [benchmark-map] Remove overhead
+
+ perf/benchmark-map.cc | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+commit 5666807328c0cf0f6ac5d6f9079d33edb5b42d88
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat May 27 12:37:36 2023 -0600
+
+    [benchmark-map] Improve Insert benchmark
+    
+    Previously it was enlarging the map depending on whatever
+    number of runs the benchmark-runner decided to run the loop.
+    That wasn't very useful...
+
+ perf/benchmark-map.cc | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit 00900f761f45fd963f727241ffe56d14b2b1b768
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat May 27 10:13:53 2023 -0600
+
+    [hash] Enable better hash for integers
+    
+    https://github.com/harfbuzz/harfbuzz/pull/4228#issuecomment-1565079537
+
+ src/hb-algs.hh | 13 +++----------
+ 1 file changed, 3 insertions(+), 10 deletions(-)
+
+commit 20c564bc7620be7f9325376601797fc20622f845
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri May 26 23:04:25 2023 +0000
+
+    [repacker] Fix fuzzer memory leak.
+    
+    https://oss-fuzz.com/testcase-detail/6419865171525632
+
+ src/graph/graph.hh                                      |   3 ++-
+ src/graph/gsubgpos-context.cc                           |   6 +++++-
+ src/graph/gsubgpos-context.hh                           |   4 ++--
+ ...stcase-minimized-hb-repacker-fuzzer-6419865171525632 | Bin 0 -> 65751 bytes
+ 4 files changed, 9 insertions(+), 4 deletions(-)
+
+commit 5abe713203210cfc190a1b94482b9aceab0ec724
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 26 15:56:30 2023 -0600
+
+    [map] Resize map on long chain probes
+
+ src/hb-map.hh | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit a652281ed6125e49ab43f0b25e88bc72b2d98085
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri May 26 19:47:50 2023 +0000
+
+    [subset] Fix fuzzer timeout.
+    
+    Fixes https://oss-fuzz.com/testcase-detail/5979721620652032. Timeout was caused by degenerate map insert behaviour due to poor integer hash function. Presize the map to avoid it. Also fixes collect_mapping() for cmap format 13.
+
+ src/hb-ot-cmap-table.hh                                    |  13 ++++++++++---
+ .../clusterfuzz-testcase-hb-subset-fuzzer-5979721620652032 | Bin 0 -> 80 bytes
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+commit 208c9490cb29e057dd57f897de739076746d84c2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 26 12:02:03 2023 -0600
+
+    [VarComposite] Limit number of axes that are copied
+    
+    Bandaid for https://oss-fuzz.com/testcase-detail/4591122882887680
+
+ src/OT/glyf/Glyph.hh        | 5 ++++-
+ src/OT/glyf/coord-setter.hh | 2 ++
+ src/hb-limits.hh            | 4 ++++
+ 3 files changed, 10 insertions(+), 1 deletion(-)
+
+commit 5872bdf64ddbf99f7863da382f79ab408cd99e8c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 26 11:41:54 2023 -0600
+
+    [vector] Add copy-constructor for array_t's
+
+ src/OT/glyf/Glyph.hh |  2 +-
+ src/hb-vector.hh     | 22 +++++++++++++++++-----
+ src/test-vector.cc   |  5 +++++
+ 3 files changed, 23 insertions(+), 6 deletions(-)
+
+commit 42aba5ff30647587d446ab6279d02f8dbe2a84cf
+Author: Chun-wei Fan <fanc999 at yahoo.com.tw>
+Date:   Wed May 24 12:19:50 2023 +0800
+
+    harfbuzz-config.cmake.in: Support Windows usage
+    
+    Apply the appropriate library prefix/suffix by whether we are building
+    as a statib build in Meson, or by using
+    ${CMAKE_[SHARED|IMPORT]_LIBRARY_PREFIX} and
+    ${CMAKE_[SHARED|IMPORT]_LIRBARY_SUFFIX} as appropriate according to
+    the target platform for shared builds.
+
+ src/harfbuzz-config.cmake.in | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+commit 84354d3f23241a17878b54d635ff68c65508aa71
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 23 11:57:22 2023 -0600
+
+    [cff] When max-ops is reached return false
+    
+    Slight speedup too.
+
+ src/hb-cff-interp-cs-common.hh | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+commit 2655b7607c21e1233378959f87a210e4431ad4d7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 23 10:57:58 2023 -0600
+
+    [map] Micro-optimize
+    
+    This shows a speedup.
+
+ src/hb-map.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 12b0680e60ece83844436f61d4269ce38f689c8f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 23 10:49:41 2023 -0600
+
+    [map] Fix set()
+    
+    This was broken in 2133aa2407657d0b3b4b73a4951c05ed26d055f2.
+    
+    We have to keep probing over tombstones.
+
+ src/hb-map.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit 4056315c868693c655373856a83603fdc1587aab
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon May 22 14:17:12 2023 -0600
+
+    [font] Remove redundant avar mapping line
+    
+    The avar mapping happens in hb_ot_var_normalize_coords() call.
+
+ src/hb-font.cc | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit 592a3d0e96db8ba75432ea2de1fa106a533da09f
+Merge: 2f21dc23b 0d354e044
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun May 21 22:00:53 2023 +0200
+
+    Merge pull request #4237 from harfbuzz/layout-font-extents
+    
+    [layout] Add hb_ot_layout_get_font_extents()
+
+commit 0d354e0442d12b71aec58ac83e7b6ede377c263e
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sun May 21 19:01:04 2023 +0300
+
+    [layout] Add tests for baseline 2 APIs
+
+ test/api/test-baseline.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+commit e047b1abbcb7edc9c4a5263b524a9a52f6a6198d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat May 20 10:27:31 2023 -0600
+
+    [layout] Improve docs
+
+ src/hb-ot-layout.cc | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit 132391ad62b90c27a95429b81a27febf4b183a37
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 19 15:01:49 2023 -0600
+
+    [layout] Add test for font_extents
+
+ test/api/Makefile.am           |   1 +
+ test/api/fonts/base-minmax.ttf | Bin 0 -> 352 bytes
+ test/api/meson.build           |   1 +
+ test/api/test-base-minmax.c    |  66 +++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 68 insertions(+)
+
+commit 6996e64f72896ee1d210f5fdc5fea143590f9f3f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 19 14:22:13 2023 -0600
+
+    [BASE] Sanitize and get_min_max fixups
+    
+    Seems to work now.
+
+ src/hb-ot-layout-base-table.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit 02e0e9394b42d8f5290a2e9699890b180c09d151
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 19 13:18:06 2023 -0600
+
+    [layout] Fetch default font extents if localized extents not found
+
+ src/hb-ot-layout.cc | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+commit 8ccc1ff21e404ab02f673a0727af58cbadc822a9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 19 13:14:57 2023 -0600
+
+    [layout] Mark language as nullable
+    
+    GI needs it apparently.
+
+ src/hb-ot-layout.cc | 6 +++---
+ src/hb-ot-tag.cc    | 2 +-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+commit 792ca22ca3212dc5f69f3c85901f63b538ae00b5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 19 11:42:20 2023 -0600
+
+    [layout] Document new API
+
+ src/hb-ot-layout.cc | 39 ++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 36 insertions(+), 3 deletions(-)
+
+commit 0894813a38d7ba7db1e58c829be15fe4149811b3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 19 11:30:03 2023 -0600
+
+    [layout] Add "2" version of BASE table API
+    
+    ...that do the script/language resolution.
+    
+    Part of https://github.com/harfbuzz/harfbuzz/pull/4237
+    
+    Ref https://github.com/harfbuzz/harfbuzz/issues/3439
+
+ docs/harfbuzz-sections.txt |   3 ++
+ src/hb-ot-layout.cc        | 109 +++++++++++++++++++++++++++++++++++++++++++--
+ src/hb-ot-layout.h         |  32 +++++++++++--
+ 3 files changed, 136 insertions(+), 8 deletions(-)
+
+commit 3e110c69c45a0d4d453ca9db74848442b6670671
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri May 19 11:06:26 2023 -0600
+
+    [layout] Add hb_ot_layout_get_font_extents()
+    
+    Untested.
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/3290
+
+ docs/harfbuzz-sections.txt     |  1 +
+ src/hb-ot-layout-base-table.hh |  3 +--
+ src/hb-ot-layout.cc            | 21 +++++++++++++++++++++
+ src/hb-ot-layout.h             |  6 ++++++
+ 4 files changed, 29 insertions(+), 2 deletions(-)
+
+commit 2f21dc23b51043bb95343d3c6a910a105536f8c2
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu May 18 07:14:28 2023 +0100
+
+    [wasm] [docs] Improve build flags information
+
+ docs/wasm-shaper.md | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+commit 134cc8edfa14bd50be0802f644f36b03030d17a7
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Wed May 17 16:58:49 2023 +0100
+
+    [wasm] [docs] How to build
+
+ docs/wasm-shaper.md | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+commit 5543d05885011d5acb0ef53759a85e759168918f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed May 17 17:29:44 2023 +0200
+
+    [subset] Use vector instead of map for glyph bounds (#4232)
+    
+    * [subset] Use vector instead of map for glyph bounds
+    
+    Is faster.
+    
+    Part of https://github.com/harfbuzz/harfbuzz/issues/4231
+    
+    * [subset] initialize bounds_vec value to 0xFFFFFFFF
+    
+    Some non-EMPTY glyph might have 0 bounds width/height
+    
+    ---------
+    
+    Co-authored-by: Qunxin Liu <qxliu at google.com>
+
+ src/OT/glyf/Glyph.hh              |  8 ++++----
+ src/hb-ot-hmtx-table.hh           | 12 +++++++-----
+ src/hb-subset-plan-member-list.hh |  4 ++--
+ src/hb-subset-plan.cc             | 11 +++++++++--
+ 4 files changed, 22 insertions(+), 13 deletions(-)
+
+commit ccfd7ef08c28c2f49d7fc52dbbc4b3fa7461b5e5
+Merge: c248fd913 6ed792ef4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed May 17 16:00:33 2023 +0200
+
+    Merge pull request #4131 from harfbuzz/wasm
+    
+    [wasm] WebAssembly shaper
+
+commit 6ed792ef4b00287e16e0b5eda7fe9488e6060e9a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed May 17 07:58:27 2023 -0600
+
+    [meson] Report WebAssembly build
+
+ meson.build       | 3 ++-
+ meson_options.txt | 2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+commit 56af88d04848dec4d4d4ad6d713b22d92edff7e8
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Wed May 17 12:38:59 2023 +0100
+
+    [wasm] More thorough API docs
+
+ docs/wasm-shaper.md | 368 +++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 367 insertions(+), 1 deletion(-)
+
+commit c248fd91334feb0a427051aab75dfe9fb93f6d22
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed May 10 01:44:10 2023 -0600
+
+    [hash] Comment
+
+ src/hb-algs.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 42f4dab8dbd0fab994170047700076fbf1c85a23
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed May 10 01:11:32 2023 -0600
+
+    [hash] Switch to Knuth multiplicative hash
+    
+    Wow, the old adhoc one was why the cmap test was timing out!
+
+ src/hb-algs.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0270e3e97492d975c7f65bb01dd819a4c9314cae
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 23:46:18 2023 -0600
+
+    [map] Reinstate quadratic probing
+
+ src/hb-map.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 19b628bdf074a30c222b04b5f2c50f1db655f03b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 23:40:07 2023 -0600
+
+    Revert "[map] Implement Robinhood hashing"
+    
+    This reverts commit 705617856818056a44a627f340c91e335c57f310.
+
+ src/hb-algs.hh |  2 +-
+ src/hb-map.hh  | 40 ++++++----------------------------------
+ 2 files changed, 7 insertions(+), 35 deletions(-)
+
+commit 18c3ba5018a7c1cd6701775e397d699cb7e7a11b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 22:44:22 2023 -0600
+
+    [map] Implement Robinhood hashing
+    
+    Numbers are not improved though. :(
+
+ src/hb-algs.hh |  2 +-
+ src/hb-map.hh  | 40 ++++++++++++++++++++++++++++++++++------
+ 2 files changed, 35 insertions(+), 7 deletions(-)
+
+commit 2133aa2407657d0b3b4b73a4951c05ed26d055f2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 21:06:17 2023 -0600
+
+    [map] Inline code for set()
+
+ src/hb-map.hh | 32 ++++++++++++++------------------
+ 1 file changed, 14 insertions(+), 18 deletions(-)
+
+commit 5bf5188ea2d31cd162f61b923e56614c446e7ad3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 20:47:46 2023 -0600
+
+    [map] Simplify del()
+
+ src/hb-map.hh | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+commit 2ffec3a6f4881cabab6f4ca8d3e200a952f2d083
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 20:44:23 2023 -0600
+
+    [map] Shuffle fetch_item
+
+ src/hb-map.hh | 28 ++++++++++++++++------------
+ 1 file changed, 16 insertions(+), 12 deletions(-)
+
+commit 1dc99128b92f4bb7b2737c129961082e642f7c4c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 20:37:12 2023 -0600
+
+    [map] Separate has() code from set() code
+
+ src/hb-map.hh | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+commit 2dd0803c850521d104bb927de8fc54e2b9d64166
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 20:35:09 2023 -0600
+
+    [map] Downgrade from quadratic to linear probing
+
+ src/hb-map.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 498197671a8d828d4a4254818693dbd502707ed2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 20:24:12 2023 -0600
+
+    [map] Write get() in terms of has()
+
+ src/hb-map.hh | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+commit f37941bb52457f3be81f34de62e4f5b93f048cf0
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue May 9 11:53:15 2023 -0700
+
+    [instancer] add tests for instancer-solver from python test suite
+    
+    Also fix bug in the solver code
+
+ src/Makefile.am                     |   5 +
+ src/hb-subset-instancer-solver.cc   |   4 +-
+ src/meson.build                     |   1 +
+ src/test-subset-instancer-solver.cc | 351 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 359 insertions(+), 2 deletions(-)
+
+commit 39ac79a7f5afb812880e8f376b00a85c509c0cf5
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Wed May 10 10:22:49 2023 -0700
+
+    address review comments
+
+ src/hb-ot-stat-table.hh           | 20 ++++-------------
+ src/hb-ot-var-fvar-table.hh       | 47 ++++++++++++++++++++-------------------
+ src/hb-subset-instancer-solver.hh |  3 +++
+ src/hb-subset-plan.cc             |  3 ---
+ 4 files changed, 31 insertions(+), 42 deletions(-)
+
+commit 58f68dd37a595c51f8e9545de165cd5a1ff5479e
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu May 4 14:25:14 2023 -0700
+
+    [instancer] wrap hb_subset_input_Set_axis_range() under experimental
+    
+    Also add notes: it's not actually working yet.
+
+ docs/harfbuzz-sections.txt | 1 +
+ src/gen-def.py             | 1 +
+ src/hb-subset-input.cc     | 6 +++++-
+ src/hb-subset.h            | 2 +-
+ 4 files changed, 8 insertions(+), 2 deletions(-)
+
+commit f3a3c3b29d2c0e4557dc8bc9666bb1efab11af82
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu May 4 13:19:12 2023 -0700
+
+    fix bot
+
+ src/hb-ot-stat-table.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit efc77dc68fea89e8ddc03d09b605e7d6ad6ff240
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu May 4 10:59:09 2023 -0700
+
+    [instancer] update code for collecting FeatureVariationRecord
+
+ src/hb-ot-layout-common.hh | 95 +++++++++++++++++++++++++++++-----------------
+ src/hb-subset-plan.cc      | 27 +++++++++----
+ 2 files changed, 80 insertions(+), 42 deletions(-)
+
+commit bf298e505064e6b02757e31d5557a611a0a065be
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon May 1 13:40:19 2023 -0700
+
+    [instancer ]update OS_2/post/glyf tables to accept Triple for axes positions
+
+ src/OT/glyf/glyf.hh     | 2 +-
+ src/hb-ot-os2-table.hh  | 4 ++--
+ src/hb-ot-post-table.hh | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+commit 51c7451bb52ab0a16539b33b46f7d9a725f8f989
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon May 1 13:38:02 2023 -0700
+
+    [instancer] update fvar table to accept Tripe for axes positions
+
+ src/hb-ot-stat-table.hh     |  2 +-
+ src/hb-ot-var-fvar-table.hh | 78 +++++++++++++++++++++++++++++++--------------
+ src/hb-subset-plan.cc       |  2 +-
+ 3 files changed, 56 insertions(+), 26 deletions(-)
+
+commit bf46d566f9522b39cd4d1def1e33335b1918fff1
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon May 1 11:23:51 2023 -0700
+
+    [instancer] update STAT table to accept Triples for axes positions
+
+ src/hb-ot-stat-table.hh | 59 +++++++++++++++++++++++++++++--------------------
+ 1 file changed, 35 insertions(+), 24 deletions(-)
+
+commit 779e8ba080014402fc62ec9dcef3b61d4a5aa21a
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Apr 27 13:48:24 2023 -0700
+
+    [instancer] update subset-plan.cc to accept Triple as axes positions
+
+ src/hb-subset-plan.cc | 27 +++++++++++++++++++--------
+ 1 file changed, 19 insertions(+), 8 deletions(-)
+
+commit 22cca43dedecdec80278d26bd1626c8a1992787f
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Apr 20 14:37:29 2023 -0700
+
+    [instancer ]update internal hashmap to use Triple instead of single value
+    
+    -Added hb-subset-instancer-solver.hh file and moved Triple struct to the
+    head file
+
+ src/Makefile.sources              |  1 +
+ src/hb-subset-input.cc            |  7 ++--
+ src/hb-subset-input.hh            |  3 +-
+ src/hb-subset-instancer-solver.cc | 39 +---------------------
+ src/hb-subset-instancer-solver.hh | 69 +++++++++++++++++++++++++++++++++++++++
+ src/hb-subset-plan-member-list.hh |  8 ++---
+ src/hb-subset-plan.hh             |  4 +++
+ src/meson.build                   |  1 +
+ 8 files changed, 86 insertions(+), 46 deletions(-)
+
+commit 0799afe2b6b9c1e06505a7e6a604cfb597b5c9ef
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Thu Apr 20 14:02:20 2023 -0700
+
+    [instancer] Add hb_subset_input_set_axis_range() API
+
+ src/hb-subset-input.cc | 40 ++++++++++++++++++++++++++++++++++++++++
+ src/hb-subset.h        |  7 +++++++
+ 2 files changed, 47 insertions(+)
+
+commit 5d543d64222c6ce45332d0c188790f90691ef112
+Merge: 4584bcdc3 5d0cc0062
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 19:02:26 2023 -0600
+
+    Merge pull request #4228 from harfbuzz/better-hash
+    
+    Better hash
+
+commit 5d0cc0062a75013a388f6929b59cbfa7939dc6e1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 18:40:35 2023 -0600
+
+    [hash] Disable int hash as it has negative performance gain
+
+ src/hb-algs.hh | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+commit 1fbb08584b172553651a7842ec9ee977991c93c7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 17:11:05 2023 -0600
+
+    [hash] Adjust prime number
+    
+    Previous one wasn't a prime. Ouch!
+
+ src/hb-algs.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 9cc7eb80ffac20cc5cfa90b80bcff2872f6c466b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 16:13:46 2023 -0600
+
+    [hash] Speed-up int64 hash
+
+ src/hb-algs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
 commit 4584bcdc326564829d3cee3572386c90e4fd1974
 Author: Khaled Hosny <khaled at aliftype.com>
 Date:   Wed May 10 00:20:25 2023 +0300
@@ -12,6 +5284,214 @@
  src/hb-version.h       |  4 ++--
  6 files changed, 27 insertions(+), 5 deletions(-)
 
+commit 826fe2c9f78932af8c5aed4ba4db6328f83f44fe
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 13:48:38 2023 -0600
+
+    [hash] Wrap specialization in HB_OPTIMIZE_SIZE_MORE
+
+ src/hb-array.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit b2b15fa30aeaad022a7953f2a150442d69e30e5b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 13:39:52 2023 -0600
+
+    [hash] Links
+
+ src/hb-algs.hh  | 3 ++-
+ src/hb-array.hh | 3 +++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+commit 05567da082b59bc422356c8c10cbe8fc87a6bd13
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 12:22:43 2023 -0600
+
+    Revert "[hash] Use fasthash for integer hash"
+    
+    This reverts commit 3bf758a57071572a0ffae3c359b4cfec5a096312.
+    
+    This was resulting in long chains again :(.
+
+ src/hb-algs.hh | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+commit bdaa74d25ff5477c72f69249181b5d840cb4cb59
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 11:58:35 2023 -0600
+
+    [hash] Use fasthash for integer hash
+    
+    This seems to speed things up surprisingly.
+
+ src/hb-algs.hh | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+commit a58bbe5408b76c6b22d3b097649b7eef530c3e13
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 12:06:35 2023 -0600
+
+    [set] Use better hash
+
+ src/hb-bit-page.hh | 5 +----
+ src/hb-bit-set.hh  | 6 +++++-
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+commit fe3339ea241528652f3480fb061abca3c6bb2ed8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 11:31:06 2023 -0600
+
+    [algs] Add hash for 64bit ints
+
+ src/hb-algs.hh | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+commit 33ef96b649fd249808af6a13f376efb819e31882
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 11:13:51 2023 -0600
+
+    [glyf] Micro-optimize a few hash operations
+
+ src/OT/glyf/Glyph.hh | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit abb92388cc8bebff0cf40cbed0045292e038bcd8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 10:54:54 2023 -0600
+
+    Revert "[map] Adjust resizing criteria"
+    
+    This reverts commit 1fa4b415315257bdbae08e6539f2ca63423572e8.
+
+ src/hb-map.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 1fa4b415315257bdbae08e6539f2ca63423572e8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 10:52:58 2023 -0600
+
+    [map] Adjust resizing criteria
+
+ src/hb-map.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f04d08b883d9b4894d5329cec351d2f0ea50590b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 02:14:30 2023 -0600
+
+    [fasthash] Remove GNU extension
+
+ src/hb-algs.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 99f5050ccd35e6e447661af2ed330f509ae9bcd8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 02:07:54 2023 -0600
+
+    [algs] Remove HB_NO_PACKED
+    
+    We depend on packed attribute in fasthash now.
+
+ src/hb-algs.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit da619c69c8f1a4be9e29bbc95cf684bf38641468
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 02:06:37 2023 -0600
+
+    [fasthash] Try to fix unaligned access
+
+ src/hb-algs.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit 075ecff750088854854147d0b32b88b120693a48
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 01:43:39 2023 -0600
+
+    [hash] Work around g++ bug?!
+    
+    I kid you not. Revert this and see src/test-map loop forever
+    eating your memory freezing your maching.
+    
+    In this loop:
+    
+      {
+        hb_hashmap_t<int, int> m0;
+        hb_hashmap_t<std::string, int> m1;
+        hb_hashmap_t<int, std::string> m2;
+        hb_hashmap_t<std::string, std::string> m3;
+    
+        std::string s;
+        for (unsigned i = 1; i < 1000; i++)
+        {
+          s += "x";
+          m0.set (i, i);
+          m1.set (s, i);
+          m2.set (i, s);
+          m3.set (s, s);
+        }
+      }
+    
+    i will not stop at 1000 and just keeps going.  If you figure out
+    what's going on, please enlighten me!
+
+ src/hb-algs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9fbab46f2636aabf70ff10acc6c141b147794a2a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue May 9 01:42:44 2023 -0600
+
+    [cairo] Fix a clang warning
+
+ src/hb-cairo-utils.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e2fd49ff1a419dad6d6dd077aa25c20d054530ff
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon May 8 23:37:47 2023 -0600
+
+    [hash] Comment
+
+ src/hb-algs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fa64e42d755709df2837fcfb8d60ff6d8b1179fb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon May 8 23:31:52 2023 -0600
+
+    [algs] Adjust int hash
+
+ src/hb-algs.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 078b2a510189088ceda4cf23bc7c0197518831dd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon May 8 22:28:48 2023 -0600
+
+    [hash] Use a Mersenne prime for int hash
+    
+    And hope that compiler optimizes to int ops instead of modula.
+    
+    Improves chaining it seems.
+    
+    Part of https://github.com/harfbuzz/harfbuzz/pull/4228
+
+ src/hb-algs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fe0f7dc57bc7411c7cc7eb80fa44c8dd8c5e4644
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon May 8 22:19:02 2023 -0600
+
+    [bytes] Use fasthash as hash algorithm
+    
+    Part of https://github.com/harfbuzz/harfbuzz/pull/4228
+
+ src/hb-algs.hh  | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-array.hh | 18 ++------------
+ 2 files changed, 78 insertions(+), 16 deletions(-)
+
 commit 4bbcff2c5c00d4e2029a176c3388ad4fe77945df
 Author: Rod S <rsheeter at google.com>
 Date:   Mon May 8 20:29:35 2023 -0700
@@ -21,6 +5501,28 @@
  docs/usermanual-getting-started.xml | 4 ++++
  1 file changed, 4 insertions(+)
 
+commit c005e3a2e30eaea700e67907dc816709263b4046
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon May 8 16:33:31 2023 -0600
+
+    [bytes] Simplify hash function
+    
+    Part of https://github.com/harfbuzz/harfbuzz/issues/4227
+
+ src/hb-array.hh | 32 ++++----------------------------
+ 1 file changed, 4 insertions(+), 28 deletions(-)
+
+commit 0e026808036f59d3ea4e5954b1a19fcfcb9a9702
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Mon May 8 16:31:58 2023 -0600
+
+    [hash] Add hash impl for integers
+    
+    Part of https://github.com/harfbuzz/harfbuzz/issues/4227
+
+ src/hb-algs.hh | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
 commit b7a8d23bc8594c84c72d54dbbffa1c1acbb92c67
 Author: Behdad Esfahbod <behdad at behdad.org>
 Date:   Mon May 8 14:32:24 2023 -0600
@@ -2444,6 +7946,1599 @@
  test/subset/meson.build                            |   1 +
  11 files changed, 128 insertions(+), 1 deletion(-)
 
+commit 2663a9b6f98a4afebe43ee213c5c14af6c2c5ce5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Mar 31 17:38:23 2023 -0600
+
+    [wasm] Rename a couple APIs
+
+ src/hb-wasm-api-blob.hh | 20 --------------------
+ src/hb-wasm-api-face.hh | 27 ++++++++++++++++++---------
+ src/hb-wasm-api-font.hh | 11 +++++++++++
+ src/hb-wasm-api-list.hh |  4 ++--
+ src/hb-wasm-api.h       | 10 +++++-----
+ 5 files changed, 36 insertions(+), 36 deletions(-)
+
+commit d2fb583a5a2e7839a88a8a4b3c1832459223c732
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Mar 31 12:18:41 2023 -0600
+
+    [wasm-graphite] Fix advance signedness
+
+ src/wasm/graphite/shape.cc | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit f9dd402ef8c49bbb89d7c1311a6008a492f4182d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Mar 31 12:18:35 2023 -0600
+
+    [wasm] Fix header
+
+ src/hb-wasm-api.h | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 85a1fdd93fcafbfdd91bec2d16cf0ce6f3a0cd79
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Mon Mar 27 14:42:21 2023 +0100
+
+    [wasm] get/set font variation parameters
+
+ src/hb-wasm-api-font.hh | 56 +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-api-list.hh |  2 ++
+ src/hb-wasm-api.h       | 14 +++++++++++++
+ 3 files changed, 72 insertions(+)
+
+commit 0bfad127c3a907d5c50e59ab61a2beac69853cb1
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sun Mar 26 17:44:55 2023 +0100
+
+    [wasm] Make _hb_wasm_module_reader conditional
+    
+    Or else uharfbuzz doesn't build.
+
+ src/hb-wasm-shape.cc | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit 3fc48d4ada4e4ed1535f7a38cba9b3f85d21ad9b
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sun Mar 26 17:43:14 2023 +0100
+
+    [wasm] [experimental] wrap hb_face_create and hb_create_font
+
+ src/hb-wasm-api-blob.hh | 20 ++++++++++++++++++++
+ src/hb-wasm-api-face.hh |  9 +++++++++
+ src/hb-wasm-api-list.hh |  2 ++
+ src/hb-wasm-api.h       |  5 +++++
+ 4 files changed, 36 insertions(+)
+
+commit 0a16c60b42a03603d12affd9746da1d0a0e67adf
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Fri Mar 10 14:31:56 2023 +0000
+
+    [wasm-rust] Derive some friendly traits
+
+ src/wasm/rust/harfbuzz-wasm/src/lib.rs | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 6ff994f31d4dc0a929dffae2ff6772096a2e51fd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Mar 3 15:33:48 2023 -0700
+
+    [wasm-api-shape] Avoid a couple of crashes
+
+ src/hb-wasm-api-shape.hh | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+commit b6c18144106955f30ac9ec645b0c7eac860c6a7f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Mar 3 11:31:08 2023 -0700
+
+    [wasm] Comment
+
+ src/hb-wasm-api-list.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit e78d8653cebc1803f669c238b2e42300717af7c8
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu Mar 2 19:47:33 2023 +0000
+
+    [wasm-rust] panic if buffer_set_contents fails
+
+ src/wasm/rust/harfbuzz-wasm/src/lib.rs | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 74a2f338c67a8c3cd5220b19366f0331332dd69d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Mar 2 10:29:01 2023 -0700
+
+    [wasm-shape] Don't crash if font is bad
+
+ src/hb-wasm-shape.cc | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit 7df9b3dd892abfcb31be072ae47193cb0482b51e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Feb 26 14:54:07 2023 -0700
+
+    [wasm-api-list] Add TODO
+
+ src/hb-wasm-api-list.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit f5a0bd223b2194203aa7435ac09fc73468544a46
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Feb 26 14:05:26 2023 -0700
+
+    [wasm-shape] Comment re thread-safety
+
+ src/hb-wasm-shape.cc | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit 7e5064ac1b259f5f92a588fc42096337c2f37a1c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Feb 26 14:01:56 2023 -0700
+
+    [wasm-shape] Comment re thread-safety
+
+ src/hb-wasm-shape.cc | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+commit 5235ee68adc1bec46fb7e0cb4f327f814961d595
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Feb 26 13:15:39 2023 -0700
+
+    [wasm-shape] Remove explicit running-mode setting
+    
+    It does it automatically.
+
+ src/hb-wasm-shape.cc | 5 -----
+ 1 file changed, 5 deletions(-)
+
+commit e89415b5b9f82ae1893343496ec659a0947b7055
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Feb 26 13:14:37 2023 -0700
+
+    [wasm-shape] Print another error message
+
+ src/hb-wasm-shape.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 6aea77c643777b7ed550edc63f65859c05430e53
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Feb 26 12:28:25 2023 -0700
+
+    [wasm-shape] Add (disabled) module support
+
+ meson.build                |  1 +
+ src/hb-wasm-shape.cc       | 66 +++++++++++++++++++++++++++++++++++++++++++++-
+ src/wasm/graphite/Makefile |  2 +-
+ 3 files changed, 67 insertions(+), 2 deletions(-)
+
+commit 142ceaf2466b66fc868f125b4adc6e727b981f3b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sun Feb 26 12:18:31 2023 -0700
+
+    [wasm-shape] Print module instantiation error
+
+ src/hb-wasm-shape.cc | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit 7e397d8695f32c91bddbf373cd19f4c6e61fa882
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sun Feb 26 13:57:34 2023 +0000
+
+    [wasm-rust] Fix shape parameters
+
+ src/wasm/sample/rust/hello-wasm/src/lib.rs | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit d942f72c2a6325a25e213bbce5bc3a943be39861
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sun Feb 26 13:57:07 2023 +0000
+
+    [wasm-rust] Fix path
+
+ src/wasm/sample/rust/hello-wasm/Cargo.toml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 52b11546c8b76206b97fd49d65ae2e850a7212d3
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sun Feb 26 13:57:00 2023 +0000
+
+    [wasm-rust] Optional kurbo dependency
+
+ src/wasm/rust/harfbuzz-wasm/Cargo.toml |  1 +
+ src/wasm/rust/harfbuzz-wasm/src/lib.rs | 92 ++++++++++++++++++++++++++++++++--
+ 2 files changed, 88 insertions(+), 5 deletions(-)
+
+commit 0c90555e5932817f7c3d820c5883172dd86844a9
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sun Feb 26 13:55:17 2023 +0000
+
+    [wasm] Fix Rust docs
+
+ docs/wasm-shaper.md | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 4f537df67de6d1475de5caf14d9cfd9886621dc1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 15:29:35 2023 -0700
+
+    [wasm] Disable check-libstdc++ test
+    
+    Since libiwasm.so links to it.
+
+ src/meson.build | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit 2482bb120b8f29c830fe1c05d9b6bc75a651eae1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 15:14:25 2023 -0700
+
+    [wasm-shape] Add XXX item
+
+ src/hb-wasm-shape.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit a53690a937bc7c4273e5f46a7f87ac8945ff282b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 15:10:10 2023 -0700
+
+    [wasm-shape] Minor rename
+
+ src/hb-wasm-shape.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 3226b4342b88e44764393a6a9e1af458d70fa5fe
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 15:03:03 2023 -0700
+
+    [wasm-shape] Use hb allocators
+
+ src/hb-wasm-shape.cc | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 4096115b48e88881a73218b15e4f83ea128abbad
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 14:22:03 2023 -0700
+
+    [wasm-graphite] Export malloc/free
+    
+    Makes the wasm-micro-runtime use these instead of internal heap.
+
+ src/wasm/graphite/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 7b1c5e86aea4babcecb572a9b69f04cf95f5d102
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 14:18:09 2023 -0700
+
+    [wasm-shape] Minor conditionalize allocation
+
+ src/hb-wasm-shape.cc | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+commit 196c6b6c1f8f528c5fbdce540156fb6375e03a80
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 14:05:15 2023 -0700
+
+    [wasm-buffer] Fix buffer_contents_realloc
+
+ src/hb-wasm-api-buffer.hh | 30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+commit b9d4758bf9679a1ad502f0beba7db75569fbf1a4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 13:07:56 2023 -0700
+
+    [wasm/graphite] Add commented out allocator export
+
+ src/wasm/graphite/Makefile | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 3c599434332ba806babf4f280e491b5560ff0778
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 13:04:54 2023 -0700
+
+    [wasm/graphite] Remove stale comment
+
+ src/wasm/graphite/shape.cc | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 6311b72fcce18703eff35010bd20c05a748ae3e5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 12:57:57 2023 -0700
+
+    [wasm-shape] Shuffle code around
+
+ src/hb-wasm-shape.cc | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit 9b66e45481c81c9af43d3dd5c2babad2121a9f59
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 12:44:32 2023 -0700
+
+    [wasm/graphite] Remove unused variable
+    
+    Wasm cannot export those?
+
+ src/wasm/graphite/shape.cc | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit c5a88a068b933ab67ffa8c39c97ad11f2dfbd7d0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 12:43:22 2023 -0700
+
+    [wasm-api] Minor cleanup
+
+ src/hb-wasm-api.h | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+commit 8215e7063232ffe3ff262c9839f1841e6d9bd7a1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 12:37:11 2023 -0700
+
+    [wasm-graphite] Memory hygiene
+
+ src/wasm/graphite/shape.cc | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit faaae04359862e49d0750592d0fc1ddf8b6d4e37
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 12:36:57 2023 -0700
+
+    [wasm-shape] Minor
+
+ src/hb-wasm-shape.cc | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit d5d8fc046fbd7b758f2e31b74e1b86b06b3acf8d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 12:17:30 2023 -0700
+
+    [wasm/graphite] Include standard headers
+    
+    Since we use emcc here.
+
+ src/wasm/graphite/shape.cc | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+commit 1f86890b7526821279c6bf2bd3ead189bf558459
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 11:55:34 2023 -0700
+
+    [wasm/graphite] Typo
+
+ src/wasm/graphite/Makefile | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit f95c2cc6d5ce9db646efde99768e2847016afc38
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 11:10:28 2023 -0700
+
+    [wasm] Infra for iwasm llvm build
+
+ meson.build     | 2 ++
+ src/meson.build | 1 +
+ 2 files changed, 3 insertions(+)
+
+commit 65f7bac73c774e3e75efc35566b2d9466726ffd2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 11:07:31 2023 -0700
+
+    Revert "[wasm-shape] No need to set default runnint mode"
+    
+    This reverts commit fa484fac08a868e885b3252522668824f0f0fe71.
+
+ src/hb-wasm-shape.cc | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit d894a10699c08ebf2f4854f28b6343a6b5ff7aea
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 10:48:41 2023 -0700
+
+    [wasm-shape] Debug message
+
+ src/hb-wasm-shape.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 91eb2f49dbf1e84da5e64f20a2b3c5b6f37f3c83
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 10:44:45 2023 -0700
+
+    [wasm-api-buffer] Minor variable
+
+ src/hb-wasm-api-buffer.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 4260de12c1bb271033d9cd3b0f47a4cf77190bf3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 10:43:27 2023 -0700
+
+    [wasm] Add HB_ARRAY_APP2NATIVE
+
+ src/hb-wasm-api-buffer.hh | 7 +++----
+ src/hb-wasm-api-face.hh   | 2 +-
+ src/hb-wasm-api-font.hh   | 4 ++--
+ src/hb-wasm-api.hh        | 5 +++++
+ 4 files changed, 11 insertions(+), 7 deletions(-)
+
+commit 1537e252bad82ea03b2a1550d2464bddc24e6e49
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 10:35:15 2023 -0700
+
+    [wasm] Minor blob validation
+
+ src/hb-wasm-api-face.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 918df8ccaf48041994e3b107ed7d2f32d643ff03
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 10:29:03 2023 -0700
+
+    [wasm-api] Add glyph_outline_free
+
+ src/hb-wasm-api-font.hh             | 16 ++++++++++++++++
+ src/hb-wasm-api-list.hh             |  3 +++
+ src/hb-wasm-api.h                   |  4 ++++
+ src/wasm/sample/c/shape-fallback.cc |  8 +++++++-
+ 4 files changed, 30 insertions(+), 1 deletion(-)
+
+commit 7fff4a19ad0dc598f9eae271d2314003b2e44df5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 10:25:19 2023 -0700
+
+    [wasm-api] Reuse allocation in font_copy_glyph_outline
+
+ src/hb-wasm-api-font.hh             | 19 +++++++++++++++++++
+ src/hb-wasm-api.h                   |  1 +
+ src/wasm/sample/c/shape-fallback.cc |  2 +-
+ 3 files changed, 21 insertions(+), 1 deletion(-)
+
+commit 41362cc339d2e6e547291cf73dcc147fe39966d1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 10:08:22 2023 -0700
+
+    [wasm] Simplify memory cleaning
+
+ src/hb-wasm-api-buffer.hh | 3 ++-
+ src/hb-wasm-api-face.hh   | 2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+commit 6746ca4ae2aa0623a56676eb77bb63975e1016b0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 09:41:20 2023 -0700
+
+    [wasm] Minor remove undefine function
+
+ src/wasm/sample/c/shape-fallback.cc | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit b08026187ab7fbec7f8d6d4adca0a8dc9d02d74b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 09:34:03 2023 -0700
+
+    [wasm-api] Memory house-keeping
+
+ src/hb-wasm-api-buffer.hh | 2 ++
+ src/hb-wasm-api-face.hh   | 2 ++
+ 2 files changed, 4 insertions(+)
+
+commit f2d227ad9f03038ddbdb70b5a45adb29a19f5fb0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 09:30:40 2023 -0700
+
+    [wasm-api] Respect existing blob allocation in face_copy_blob
+
+ src/hb-wasm-api-face.hh             | 19 +++++++++++++++++--
+ src/hb-wasm-api.h                   |  1 +
+ src/wasm/graphite/shape.cc          |  2 +-
+ src/wasm/sample/c/shape-fallback.cc |  2 +-
+ 4 files changed, 20 insertions(+), 4 deletions(-)
+
+commit e7540043de3f38c4f442e696b569bcc6af90587f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 09:18:40 2023 -0700
+
+    [wasm-api] Make buffer_copy_contents reuse contents
+
+ src/hb-wasm-api-buffer.hh           | 26 +++++++++++++++++++++++++-
+ src/hb-wasm-api.h                   |  1 +
+ src/wasm/graphite/shape.cc          |  2 +-
+ src/wasm/sample/c/shape-fallback.cc |  2 +-
+ 4 files changed, 28 insertions(+), 3 deletions(-)
+
+commit 65966e0c3da0fdb5a59abcc76533dfceccbc1425
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 08:59:03 2023 -0700
+
+    [wasm-api] Add font_copy_glyph_outline
+
+ src/hb-wasm-api-font.hh             | 46 +++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-api-list.hh             |  1 +
+ src/hb-wasm-api.h                   | 36 +++++++++++++++++++++++++++--
+ src/wasm/sample/c/shape-fallback.cc |  4 ++++
+ 4 files changed, 85 insertions(+), 2 deletions(-)
+
+commit 92a57b4b4aa60620040dd5a31dcb764643da9496
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sat Feb 25 15:38:08 2023 +0000
+
+    [wasm-rust] update font_copy_table API
+
+ src/wasm/rust/harfbuzz-wasm/src/lib.rs | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+commit db789eacb41ecd74ee3c32d245e7e15640c58198
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sat Feb 25 15:35:37 2023 +0000
+
+    [wasm-rust] Docs and API update
+
+ docs/wasm-shaper.md                    |  8 ++++----
+ src/wasm/rust/harfbuzz-wasm/src/lib.rs | 12 ++++++++++--
+ 2 files changed, 14 insertions(+), 6 deletions(-)
+
+commit 0d237d062e0826138769c405bb1c04c9ed8da247
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 08:32:35 2023 -0700
+
+    [wasm-shape] No need to set default runnint mode
+    
+    It's detected automatically apparently.
+
+ src/hb-wasm-shape.cc | 5 -----
+ 1 file changed, 5 deletions(-)
+
+commit 2004528cf8375b82c687e8b9eb12d485d14427f1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 08:23:14 2023 -0700
+
+    [wasm-api] Change face_copy_table to return success
+
+ src/hb-wasm-api-face.hh             | 29 ++++++++++++++++++++---------
+ src/hb-wasm-api-list.hh             |  2 +-
+ src/hb-wasm-api.h                   |  7 ++++---
+ src/wasm/graphite/shape.cc          |  4 +++-
+ src/wasm/sample/c/shape-fallback.cc |  5 ++++-
+ 5 files changed, 32 insertions(+), 15 deletions(-)
+
+commit 83b9c34f0b5d9b6b6f65aae0e1bb92877972a5ed
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sat Feb 25 15:23:22 2023 +0000
+
+    [wasm] Add rust example
+
+ src/wasm/sample/rust/hello-wasm/Cargo.toml | 13 +++++++++++++
+ src/wasm/sample/rust/hello-wasm/src/lib.rs | 18 ++++++++++++++++++
+ 2 files changed, 31 insertions(+)
+
+commit 840b5dff734e566b258fc3a1ee556739af31b45c
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sat Feb 25 15:20:39 2023 +0000
+
+    [wasm] Improve Rust docs, refer to new crate
+
+ docs/wasm-shaper.md | 103 +++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 69 insertions(+), 34 deletions(-)
+
+commit 28a7c1f93247d692475ded0ea4dd6d0b5dd94044
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 08:16:31 2023 -0700
+
+    [wasm-api] Rename face_reference_table to face_copy_table
+
+ src/hb-wasm-api-face.hh                | 6 +++---
+ src/hb-wasm-api-list.hh                | 2 +-
+ src/hb-wasm-api.h                      | 6 +++---
+ src/wasm/graphite/shape.cc             | 2 +-
+ src/wasm/rust/harfbuzz-wasm/src/lib.rs | 4 ++--
+ src/wasm/sample/c/shape-fallback.cc    | 2 +-
+ 6 files changed, 11 insertions(+), 11 deletions(-)
+
+commit b5b577f29fd20016fab21b454403510d1098f132
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 08:12:16 2023 -0700
+
+    [wasm-api] Make buffer_copy_contents return success
+
+ src/hb-wasm-api-buffer.hh           | 24 ++++++++++++++++--------
+ src/hb-wasm-api-list.hh             |  2 +-
+ src/hb-wasm-api.h                   |  5 +++--
+ src/wasm/graphite/shape.cc          |  4 ++--
+ src/wasm/sample/c/shape-fallback.cc |  4 +++-
+ 5 files changed, 25 insertions(+), 14 deletions(-)
+
+commit 1023a80d395318e444458d0eebccab363133d5ef
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 07:57:04 2023 -0700
+
+    [wasm] Fix up samples
+
+ src/{wasm/graphite => }/addTable.py |  0
+ src/wasm/graphite/Makefile          | 17 ++++++++++-------
+ src/wasm/sample/addTable.py         | 16 ----------------
+ src/wasm/sample/c/Makefile          | 14 ++++++++------
+ 4 files changed, 18 insertions(+), 29 deletions(-)
+
+commit 4ad659a6088d4b86599a3334a9c0f7ceeec8c79e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Feb 25 07:48:35 2023 -0700
+
+    [wasm] Move wasm-graphite
+
+ src/{wasm-graphite => wasm/graphite}/Makefile    | 0
+ src/{wasm-graphite => wasm/graphite}/addTable.py | 0
+ src/{wasm-graphite => wasm/graphite}/shape.cc    | 0
+ 3 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 514a8d58d8820b7b21e2f25933bc9b0d6ea70672
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sat Feb 25 14:42:13 2023 +0000
+
+    [wasm-api] Add ergonomic Rust interface
+
+ src/wasm/rust/harfbuzz-wasm/Cargo.toml |   8 +
+ src/wasm/rust/harfbuzz-wasm/src/lib.rs | 364 +++++++++++++++++++++++++++++++++
+ 2 files changed, 372 insertions(+)
+
+commit 74deaa9e7888f1433c053802877911cb643221f9
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Sat Feb 25 13:33:49 2023 +0000
+
+    [wasm-api] Restructure samples/libraries
+
+ src/{wasm-sample => wasm/sample}/addTable.py         |   0
+ src/{wasm-sample => wasm/sample/c}/Makefile          |   0
+ src/{wasm-sample => wasm/sample/c}/shape-fallback.cc |   0
+ src/{wasm-sample => wasm/sample/c}/shape-ot.cc       |   0
+ src/{wasm-sample => wasm/sample/c}/test.ttf          | Bin
+ 5 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 4bdfaeecefae4136b9ceb451138f8055c7b74d02
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 20:05:35 2023 -0700
+
+    [wasm-shape] Set glyph flags
+
+ src/hb-wasm-shape.cc | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+commit 77f0f3c11a5b9e2d5bbf20a6e2840c19822bc134
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 20:01:22 2023 -0700
+
+    [wasm-api] Make buffer_copy_contents return zero length on mem fail
+
+ src/hb-wasm-api-buffer.hh  |  4 ++--
+ src/hb-wasm-shape.cc       | 15 ++-------------
+ src/wasm-graphite/shape.cc |  2 ++
+ 3 files changed, 6 insertions(+), 15 deletions(-)
+
+commit 16ecb96922e2f1389cd634a2b908df0a72f8ac1f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 19:53:47 2023 -0700
+
+    [wasm-api] Return success from buffer_contents_realloc
+
+ src/hb-wasm-api-buffer.hh  | 42 ++++++++++++++++++++++++++++--------------
+ src/hb-wasm-api-list.hh    |  2 +-
+ src/hb-wasm-api.h          |  6 +++---
+ src/wasm-graphite/shape.cc |  3 ++-
+ 4 files changed, 34 insertions(+), 19 deletions(-)
+
+commit 2568890d15f2a271738a2ef23ca73d173bf120df
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 19:04:39 2023 -0700
+
+    [wasm-shape] Retry shaping if out-of-memory
+
+ src/hb-wasm-shape.cc       | 26 +++++++++++++++++++++++---
+ src/wasm-graphite/shape.cc |  4 ++++
+ 2 files changed, 27 insertions(+), 3 deletions(-)
+
+commit cb382e489d656a3d955c15feb99ea887f6d8985a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 17:56:14 2023 -0700
+
+    [wasm-shape] Cache wasm-shape-plan
+
+ src/hb-wasm-api-buffer.hh |   3 +
+ src/hb-wasm-shape.cc      | 202 +++++++++++++++++++++++++++++++---------------
+ 2 files changed, 140 insertions(+), 65 deletions(-)
+
+commit 73de7d4d05ab2c78e56a4b6156b52ebd2f107c8f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 17:44:33 2023 -0700
+
+    [wasm-api] Add shape_plan
+
+ src/hb-wasm-api.h                 |  9 ++++-
+ src/hb-wasm-shape.cc              | 75 ++++++++++++++++++++++++++++++++-------
+ src/wasm-graphite/shape.cc        | 24 ++++++++++---
+ src/wasm-sample/shape-fallback.cc |  3 +-
+ src/wasm-sample/shape-ot.cc       |  3 +-
+ 5 files changed, 93 insertions(+), 21 deletions(-)
+
+commit a267249930503f99a2517cd35f90556cefdea854
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 17:22:22 2023 -0700
+
+    [wasm] Typo
+
+ src/harfbuzz.cc      | 2 ++
+ src/hb-wasm-shape.cc | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+commit 99d2dab30f317058075d5a82c0dfedc898d6912d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 17:04:05 2023 -0700
+
+    [wasm] Try at autotools build
+
+ configure.ac         | 23 +++++++++++++++++++++++
+ src/Makefile.am      | 10 ++++++++++
+ src/Makefile.sources | 15 +++++++++++++--
+ src/harfbuzz.cc      |  2 --
+ 4 files changed, 46 insertions(+), 4 deletions(-)
+
+commit ed39e0766194194e0fcdd4b45cd428c4c1abd43d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 16:20:06 2023 -0700
+
+    [wasm] Fix docs
+
+ docs/harfbuzz-sections.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit c5af08c0dc7388198019eab3ff16eccd614fce94
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 15:57:10 2023 -0700
+
+    [wasm] Add to harfbuzz.cc and hb-features
+
+ src/Makefile.am      | 9 +++++----
+ src/harfbuzz.cc      | 2 ++
+ src/hb-features.h.in | 7 +++++++
+ src/hb-wasm-api.cc   | 6 ++++++
+ src/meson.build      | 3 ++-
+ 5 files changed, 22 insertions(+), 5 deletions(-)
+
+commit aa8f9eed63698ae5b40b7f3cca284a5535eaf661
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 15:20:37 2023 -0700
+
+    [wasm-shape] Use JIT running-modes if available
+    
+    Build wasm-micro-runtime with:
+    
+    $ cmake . -DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_FAST_JIT=1
+    
+    or:
+    
+    $ cmake . -DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_JIT=1
+    
+    The latter needs llvm and is harder to get working. Still trying.
+
+ src/hb-wasm-shape.cc | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+commit 8d960dfe68da0393eafd92a66fa4277b2e1d6e63
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 15:07:40 2023 -0700
+
+    [wasm-sample] Remove Wasm table from test.ttf again
+    
+    Was added by mistake.
+
+ src/wasm-sample/test.ttf | Bin 23468 -> 22116 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 1c6d640e1fbf459b3cf2ef66ad48560e8469f72e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 15:01:36 2023 -0700
+
+    [wasm-shaper] Whitespace
+
+ src/hb-wasm-shape.cc       | 9 +++------
+ src/wasm-graphite/Makefile | 2 +-
+ 2 files changed, 4 insertions(+), 7 deletions(-)
+
+commit 9f8ad3928afeaf10a0dac8e7d0f3df6bd822c63d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 14:16:11 2023 -0700
+
+    [wasm-api] Bind shaper features
+
+ src/hb-wasm-api-blob.hh           |  2 +-
+ src/hb-wasm-api-buffer.hh         |  6 +++---
+ src/hb-wasm-api-font.hh           |  6 +++---
+ src/hb-wasm-api-list.hh           |  2 +-
+ src/hb-wasm-api-shape.hh          | 14 ++++++++++++--
+ src/hb-wasm-api.h                 | 18 +++++++++++++++---
+ src/hb-wasm-api.hh                | 11 ++++++++++-
+ src/hb-wasm-shape.cc              | 12 +++++++++++-
+ src/wasm-graphite/shape.cc        |  5 ++++-
+ src/wasm-sample/shape-fallback.cc |  5 ++++-
+ src/wasm-sample/shape-ot.cc       |  7 +++++--
+ 11 files changed, 69 insertions(+), 19 deletions(-)
+
+commit 2327fe9d8a77c930ec5e939060c714ef3008d325
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 13:35:47 2023 -0700
+
+    [hb-wasm] Remove TODO
+
+ src/hb-wasm-shape.cc | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit b130b2b3317d296f0120acf5f9aab4bab39f2506
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 13:34:16 2023 -0700
+
+    [graphite] Simplify direction handling
+
+ src/hb-graphite2.cc | 23 +++++++++++------------
+ 1 file changed, 11 insertions(+), 12 deletions(-)
+
+commit ec3270c7bb162a8e8996192922628502dab9d5a2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 13:31:10 2023 -0700
+
+    [wasm-graphite] Ensure native direction here too
+    
+    Binds buffer_get_script and script_get_horizontal_direction.
+
+ src/hb-wasm-api-buffer.hh  |  8 ++++++++
+ src/hb-wasm-api-common.hh  | 44 ++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-api-list.hh    |  3 +++
+ src/hb-wasm-api.cc         |  1 +
+ src/hb-wasm-api.h          | 11 +++++++++++
+ src/meson.build            |  1 +
+ src/wasm-graphite/shape.cc | 21 +++++++++++++++------
+ 7 files changed, 83 insertions(+), 6 deletions(-)
+
+commit cbc71c56bcc5eded3e2393a0b1d2b380fa5944a0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 13:15:11 2023 -0700
+
+    [graphite] Ensure native direction
+    
+    Mirrored characters come out wrong. Oh well. Better than before though.
+
+ src/hb-graphite2.cc | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+commit 39f8703df17cc49b8630597fc250b13ef61870b8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 12:42:22 2023 -0700
+
+    [wasm-api] Match interface and implementation signatures
+
+ src/hb-wasm-api-blob.hh   |  5 ++--
+ src/hb-wasm-api-buffer.hh | 65 +++++++++++++++++++++--------------------------
+ src/hb-wasm-api-face.hh   | 12 ++++-----
+ src/hb-wasm-api-font.hh   | 55 +++++++++++++++++----------------------
+ src/hb-wasm-api-shape.hh  |  9 +++----
+ src/hb-wasm-api.hh        |  1 -
+ 6 files changed, 64 insertions(+), 83 deletions(-)
+
+commit fea3ffe03147c35180be09b42caee90a96c61a34
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 12:31:32 2023 -0700
+
+    [wasm-api] Beautify internal API
+
+ src/hb-wasm-api-blob.hh   |  2 +-
+ src/hb-wasm-api-buffer.hh | 16 +++++++-------
+ src/hb-wasm-api-face.hh   |  4 ++--
+ src/hb-wasm-api-font.hh   | 20 +++++++++---------
+ src/hb-wasm-api-shape.hh  |  4 ++--
+ src/hb-wasm-api.h         | 53 +++++++++++++++++++++++++----------------------
+ src/hb-wasm-api.hh        |  3 ++-
+ 7 files changed, 53 insertions(+), 49 deletions(-)
+
+commit fe557e2f21108181496b8f23c92595e0d24d7d20
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 12:20:31 2023 -0700
+
+    [wasm-api] Bind font_get_glyph_extents
+    
+    Untested.
+
+ src/hb-wasm-api-font.hh | 17 +++++++++++++++++
+ src/hb-wasm-api-list.hh |  1 +
+ src/hb-wasm-api.h       | 12 ++++++++++++
+ 3 files changed, 30 insertions(+)
+
+commit b3b6e8da86b8bda05311fe9524ac169040ba9cf3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 12:03:53 2023 -0700
+
+    [wasm-api] Bind buffer_reverse
+
+ src/hb-wasm-api-buffer.hh | 9 +++++++++
+ src/hb-wasm-api-list.hh   | 1 +
+ src/hb-wasm-api.h         | 3 +++
+ 3 files changed, 13 insertions(+)
+
+commit 863ec70e1240379875fe72baeada79c0d9f79fe4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 12:00:29 2023 -0700
+
+    [wasm-shape] Add TODO items
+
+ src/hb-wasm-shape.cc | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit 1acff90b0337d9a0158c4b8afddaf485a8037b67
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 11:53:47 2023 -0700
+
+    [wasm-api] Bind font_glyph_to_string
+
+ src/hb-wasm-api-font.hh           | 12 ++++++++++++
+ src/hb-wasm-api-list.hh           |  1 +
+ src/hb-wasm-api.h                 |  5 +++++
+ src/wasm-graphite/shape.cc        |  3 +++
+ src/wasm-sample/shape-fallback.cc |  8 +++++++-
+ 5 files changed, 28 insertions(+), 1 deletion(-)
+
+commit 7537d48f081f25e3bd78dcacf9218535a1e40c2f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 11:47:17 2023 -0700
+
+    [wasm] Remove a few lingering hb_
+
+ src/hb-wasm-api-font.hh    | 12 ++++++------
+ src/hb-wasm-api.h          | 32 ++++++++++++++++----------------
+ src/wasm-graphite/shape.cc |  2 +-
+ 3 files changed, 23 insertions(+), 23 deletions(-)
+
+commit d7f76f30b0dcfda3f4322b3e240be30b4a141cc7
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 11:31:04 2023 -0700
+
+    [wasm-graphite] Memory cleanup
+
+ src/wasm-graphite/shape.cc | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+commit 5738851b1ca0471b4ac270b89549466202fddf10
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 11:05:59 2023 -0700
+
+    [wasm-api] Disallow "wasm" shaper in shape_with
+
+ src/hb-wasm-api-shape.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 2bde2f66f1391ca4d1c0e38142a6ea0f175173ab
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 11:03:13 2023 -0700
+
+    [wasm-api] Bind shape_with
+
+ src/hb-wasm-api-list.hh                        |  3 ++
+ src/hb-wasm-api-shape.hh                       | 50 ++++++++++++++++++++++++++
+ src/hb-wasm-api.cc                             |  1 +
+ src/hb-wasm-api.h                              |  8 +++++
+ src/meson.build                                |  1 +
+ src/wasm-sample/Makefile                       | 15 ++++----
+ src/wasm-sample/{shape.c => shape-fallback.cc} |  6 ++--
+ src/wasm-sample/shape-ot.cc                    | 14 ++++++++
+ 8 files changed, 90 insertions(+), 8 deletions(-)
+
+commit a08dbf41cd20bf36828b58a4e4b448671ee036c1
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 10:13:21 2023 -0700
+
+    [wasm-api] Bind buffer_reverse_clusters
+
+ src/hb-wasm-api-buffer.hh  | 8 ++++++++
+ src/hb-wasm-api-list.hh    | 1 +
+ src/hb-wasm-api.h          | 2 ++
+ src/wasm-graphite/Makefile | 2 +-
+ src/wasm-graphite/shape.cc | 6 +++---
+ 5 files changed, 15 insertions(+), 4 deletions(-)
+
+commit 0a51ed31b0bba05727210f27548ebd3b55052fe3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 10:07:59 2023 -0700
+
+    [wasm-api] Bind buffer_get_direction
+
+ src/hb-wasm-api-buffer.hh  | 10 ++++++++++
+ src/hb-wasm-api-list.hh    |  1 +
+ src/hb-wasm-api.h          | 17 +++++++++++++++++
+ src/wasm-graphite/shape.cc | 11 ++++++-----
+ 4 files changed, 34 insertions(+), 5 deletions(-)
+
+commit a5c844a1de2a6f5c0acda723d4367c41d7a7b90c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 09:52:38 2023 -0700
+
+    [wasm] Rename macro
+
+ src/hb-wasm-api-blob.hh   | 2 +-
+ src/hb-wasm-api-buffer.hh | 6 +++---
+ src/hb-wasm-api-font.hh   | 4 ++--
+ src/hb-wasm-api.hh        | 2 +-
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+commit 23b58b5667aa6ffe2780860e7a9202149e05eac3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 09:50:34 2023 -0700
+
+    [wasm-api] Bind font_get_scale
+
+ src/hb-wasm-api-buffer.hh  |  2 +-
+ src/hb-wasm-api-face.hh    |  2 +-
+ src/hb-wasm-api-font.hh    | 15 ++++++++++++++-
+ src/hb-wasm-api-list.hh    |  1 +
+ src/hb-wasm-api.h          |  5 +++++
+ src/hb-wasm-api.hh         |  2 +-
+ src/wasm-graphite/shape.cc |  6 ++++--
+ 7 files changed, 27 insertions(+), 6 deletions(-)
+
+commit 149199ee26cfac1ff211b2283f8c79b1c7b8cdd0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 09:39:25 2023 -0700
+
+    [wasm-api] Bind face_get_upem
+
+ src/hb-wasm-api-face.hh    | 9 +++++++++
+ src/hb-wasm-api-list.hh    | 1 +
+ src/hb-wasm-api.h          | 5 +++++
+ src/wasm-graphite/shape.cc | 4 ++--
+ 4 files changed, 17 insertions(+), 2 deletions(-)
+
+commit 2d295183b8ed47fa3efa4b83aff1d7781d97ab4f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 09:20:42 2023 -0700
+
+    [wasm-api] Add buffer_contents_realloc
+
+ src/hb-wasm-api-buffer.hh  | 33 ++++++++++++++++++++++++++++++++-
+ src/hb-wasm-api-list.hh    |  1 +
+ src/hb-wasm-api.h          |  4 ++++
+ src/wasm-graphite/shape.cc |  3 +--
+ 4 files changed, 38 insertions(+), 3 deletions(-)
+
+commit 07ece174954a3345f05be3c23766119e6554dbf5
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Fri Feb 24 08:08:18 2023 -0700
+
+    [wasm-graphite] Initial code
+
+ src/hb-wasm-api-face.hh       |   2 +-
+ src/hb-wasm-shape.cc          |   2 +-
+ src/wasm-graphite/Makefile    |  22 +++++
+ src/wasm-graphite/addTable.py |  16 ++++
+ src/wasm-graphite/shape.cc    | 210 ++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 250 insertions(+), 2 deletions(-)
+
+commit ae981eec8e33abe7052176733c1ed84cdaeb082f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 21:36:17 2023 -0700
+
+    [graphite] Remove script handling
+    
+    https://github.com/harfbuzz/harfbuzz/issues/3439#issuecomment-1442650148
+
+ src/hb-graphite2.cc | 10 +---------
+ 1 file changed, 1 insertion(+), 9 deletions(-)
+
+commit 5ab7f7a7d41720bb8ea189df0c5c47db1a22d550
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 16:11:54 2023 -0700
+
+    [wasm-sample] Make addTable take args
+
+ src/wasm-sample/Makefile    |   2 +-
+ src/wasm-sample/addTable.py |  11 ++++++++---
+ src/wasm-sample/test.ttf    | Bin 22116 -> 23468 bytes
+ 3 files changed, 9 insertions(+), 4 deletions(-)
+
+commit 551528a6e6bef10b3bfbc254c949d7247fba8176
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 16:06:39 2023 -0700
+
+    [wasm-sample] Remove unused prototype
+
+ src/wasm-sample/shape.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 926f8a326e42b557d2991bddf5e234289677c362
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 15:52:13 2023 -0700
+
+    [wasm-sample] Actually shape text!
+
+ src/wasm-sample/shape.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit c1dc112121e8ce7e3c75fae0c9e3589176bbc2f8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 15:47:56 2023 -0700
+
+    [wasm-api] Bind buffer_set_contents
+
+ src/hb-buffer.hh          |  7 +++++++
+ src/hb-wasm-api-buffer.hh | 34 +++++++++++++++++++++++++++++++---
+ src/hb-wasm-api-list.hh   |  7 ++++---
+ src/hb-wasm-api.h         |  4 ++++
+ src/wasm-sample/shape.c   |  8 +++++++-
+ 5 files changed, 53 insertions(+), 7 deletions(-)
+
+commit e0fec1dda01f1060dd474537dcbe5084ef46a88f
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu Feb 23 22:18:22 2023 +0000
+
+    [wasm-api] Wrap some of hb-font
+
+ src/hb-wasm-api-font.hh | 31 +++++++++++++++++++++++++++++++
+ src/hb-wasm-api-list.hh |  5 ++++-
+ src/hb-wasm-api.h       | 13 ++++++++++++-
+ 3 files changed, 47 insertions(+), 2 deletions(-)
+
+commit af1f41a43ee7b7bb06e43e7000101019ae24f66a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 15:17:18 2023 -0700
+
+    [wasm-api] Clear structs in _free()
+
+ src/hb-wasm-api-blob.hh   | 3 +++
+ src/hb-wasm-api-buffer.hh | 4 ++++
+ 2 files changed, 7 insertions(+)
+
+commit 099a0150e1ba3af96d52629a04fe5def489c4b34
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 15:15:06 2023 -0700
+
+    [wasm] Add HB_STRUCT_TYPE
+
+ src/hb-wasm-api-blob.hh   | 5 ++---
+ src/hb-wasm-api-buffer.hh | 5 ++---
+ src/hb-wasm-api.hh        | 9 +++++++++
+ 3 files changed, 13 insertions(+), 6 deletions(-)
+
+commit 851ef1380aec550e51a4d8055a9c8aef2b57aeeb
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 15:06:18 2023 -0700
+
+    [wasm-api] Add buffer-contents-free
+
+ src/hb-wasm-api-buffer.hh | 13 +++++++++++++
+ src/hb-wasm-api-list.hh   |  1 +
+ src/hb-wasm-api.h         |  5 +++--
+ src/wasm-sample/shape.c   |  2 ++
+ 4 files changed, 19 insertions(+), 2 deletions(-)
+
+commit d38f02ab30e3696614c295f88beadb655110599a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 15:03:03 2023 -0700
+
+    [wasm-api] Make ref types actual pointers on the wasm side
+
+ src/hb-wasm-api-buffer.hh |  2 +-
+ src/hb-wasm-api-face.hh   |  2 +-
+ src/hb-wasm-api-font.hh   |  4 ++--
+ src/hb-wasm-api.h         | 25 ++++++++++++-------------
+ src/wasm-sample/shape.c   |  4 ++--
+ 5 files changed, 18 insertions(+), 19 deletions(-)
+
+commit cbd5c554fb28d3aa2ac834c28e6d89600e969f62
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 14:54:46 2023 -0700
+
+    [wasm-api] Add blob_free
+
+ src/hb-wasm-api-blob.hh  | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-api-list.hh  |  3 +++
+ src/hb-wasm-api.cc       |  1 +
+ src/hb-wasm-api.h        |  3 ++-
+ src/meson.build          |  1 +
+ src/wasm-sample/Makefile |  2 ++
+ src/wasm-sample/shape.c  |  2 +-
+ 7 files changed, 59 insertions(+), 2 deletions(-)
+
+commit 3bec8dca1ca108a9c64af36c768eda58bdec2d95
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 14:35:01 2023 -0700
+
+    [wasm-sample] Free blob data for now
+
+ src/wasm-sample/shape.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit d45a13f1018a18a8ea797b717253cbf6f42f9fe8
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 14:28:16 2023 -0700
+
+    [wasm] Add wasm-sample/
+
+ src/wasm-sample/Makefile    |  18 ++++++++++++++++++
+ src/wasm-sample/addTable.py |  11 +++++++++++
+ src/wasm-sample/shape.c     |  25 +++++++++++++++++++++++++
+ src/wasm-sample/test.ttf    | Bin 0 -> 22116 bytes
+ 4 files changed, 54 insertions(+)
+
+commit 5cecfe865919ff2c72a0409e34265d79f78750d0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 13:58:40 2023 -0700
+
+    [wasm-api] Bind buffer_copy_contents
+
+ src/hb-wasm-api-buffer.hh | 58 +++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-api-face.hh   |  8 +++----
+ src/hb-wasm-api-font.hh   |  8 +++----
+ src/hb-wasm-api-list.hh   |  3 +++
+ src/hb-wasm-api.cc        |  1 +
+ src/hb-wasm-api.h         | 43 ++++++++++++++++++++++++++++++++++-
+ src/meson.build           |  9 +++++++-
+ 7 files changed, 120 insertions(+), 10 deletions(-)
+
+commit 50b22368d04893afa9227ac2c3321ef43c5ae638
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 13:41:41 2023 -0700
+
+    Revert "Fix function signature"
+    
+    This reverts commit d70ebf98b0c696f3c66a20b1243cb347e3e3abc8.
+    
+    Nope. A struct return is not returned that way.
+
+ src/hb-wasm-api-list.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 743cd2c46ee0c81958e2c360d56391da679107f6
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu Feb 23 20:35:16 2023 +0000
+
+    Fix function signature
+
+ src/hb-wasm-api-list.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 3b88bd9742b06e5f0ebd90b39f1fdce6b2129e91
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 13:27:46 2023 -0700
+
+    [wasm-api] Make ptr_t a pointer on the wasm side
+
+ src/hb-wasm-api.h  | 7 ++++---
+ src/hb-wasm-api.hh | 4 +++-
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+commit d7a6671676f9ec5b6b2e8f3a964d1ef9f85f9e3a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 13:16:49 2023 -0700
+
+    [wasm-api] Add debugprint1/2/3/4
+
+ src/hb-wasm-api-list.hh | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+commit 108995bbc67aa4a45657127eab6b9f89171355fd
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 13:04:38 2023 -0700
+
+    [wasm-api] Finish face_reference_table
+
+ src/hb-wasm-api-face.hh | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+commit 69b1707d82b498eb88a097c72595a848c3e0007f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 13:00:06 2023 -0700
+
+    [wasm] Return empty object when ref2obj fails
+
+ src/hb-wasm-api-face.hh | 2 --
+ src/hb-wasm-api-font.hh | 3 ---
+ src/hb-wasm-api.hh      | 2 +-
+ 3 files changed, 1 insertion(+), 6 deletions(-)
+
+commit e87b1b3ec3a67bf42edac41236e1e70a56ff7072
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 12:23:52 2023 -0700
+
+    [wasm-api] Try to add face_reference_table
+
+ src/hb-wasm-api-face.hh | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-api-list.hh |  3 +++
+ src/hb-wasm-api.cc      |  4 +---
+ src/hb-wasm-api.h       | 41 ++++++++++++++++++++++++++++++---------
+ src/hb-wasm-api.hh      | 19 ++++++++++++++++--
+ 5 files changed, 104 insertions(+), 14 deletions(-)
+
+commit e03726d26948b6f9cf2c64df75230c3e15433f44
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 12:00:42 2023 -0700
+
+    [wasm] Ignore API in the docs
+
+ docs/meson.build | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 747dcf561d710d324b02249806fa0b113178c3d2
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 11:53:08 2023 -0700
+
+    [wasm] Strong typing for object references
+    
+    Such that wasm cannot crash us by passing wrong object refs.
+    
+    https://github.com/bytecodealliance/wasm-micro-runtime/discussions/1987
+    
+    It still is unsafe if some code in the process other than HarfBuzz
+    registers refs with wasm-micro-runtime, since wasm_externref_ref2obj()
+    takes no context variable and looks up refs globally :(.
+    
+    Maybe I fix that later by keeping a hash table of ref->obj-type instead.
+
+ src/hb-wasm-api.cc   | 11 ++---------
+ src/hb-wasm-api.hh   | 32 ++++++++++++++++++++++++++++++++
+ src/hb-wasm-shape.cc | 41 +++++++++++++++++++++--------------------
+ 3 files changed, 55 insertions(+), 29 deletions(-)
+
+commit 6b72a18c7b981ac0126ea3b585f16449ce3dd25b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 11:06:48 2023 -0700
+
+    [wasm-api] Rename file
+
+ src/{hb-wasm-font.hh => hb-wasm-api-font.hh} | 0
+ src/hb-wasm-api.cc                           | 2 +-
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 42d121ae79ce547f1bbe82b9fa771725604546d3
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 11:05:19 2023 -0700
+
+    [wasm] Add hb-wasm-api.cc
+
+ src/hb-wasm-api-list.hh |  1 -
+ src/hb-wasm-api.cc      | 45 +++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-api.hh      | 20 --------------------
+ src/hb-wasm-shape.cc    |  1 +
+ src/meson.build         |  2 +-
+ 5 files changed, 47 insertions(+), 22 deletions(-)
+
+commit 980706441b58878cb168543eef70247eccc6abf6
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 10:58:22 2023 -0700
+
+    [wasm] Add hb-wasm-api-list.hh
+
+ src/hb-wasm-api-list.hh | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-api.hh      | 30 +-----------------------
+ 2 files changed, 62 insertions(+), 29 deletions(-)
+
+commit 65efad6b59f6252b2b314e5e16b958bf1b8f4e80
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 10:49:02 2023 -0700
+
+    [wasm] Make debugprint use debug API
+
+ src/hb-wasm-api.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit bb8a04cbadc16c8195b87e8fd307a2403d2212fa
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 10:37:44 2023 -0700
+
+    [wasm] Remove the print(returnval) and use it to fail shaper
+
+ docs/wasm-shaper.md  | 2 --
+ src/hb-wasm-shape.cc | 8 +-------
+ 2 files changed, 1 insertion(+), 9 deletions(-)
+
+commit 11fc83c0ba349a6f376a8409971b5698bba39b19
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu Feb 23 17:34:02 2023 +0000
+
+    [Docs] Pass a C string from Rust to HB
+
+ docs/wasm-shaper.md | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+commit 36dd27bf3f4c35fde6041a91aeb275d4c8624624
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu Feb 23 17:33:50 2023 +0000
+
+    Just printf, don't take length
+
+ src/hb-wasm-api.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 3bc0ecf28c97a5891a9f2cfb371c41505640beef
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 10:30:35 2023 -0700
+
+    [wasm-api] Add ref_t
+
+ src/hb-wasm-api.h | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+commit 62f3c7cf67c8b468b49380346a0dbd22c0ad174e
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 10:29:04 2023 -0700
+
+    [wasm-api] Add macros for ref handling
+
+ src/hb-wasm-api.hh  | 13 ++++++++++++-
+ src/hb-wasm-font.hh |  9 ++++-----
+ 2 files changed, 16 insertions(+), 6 deletions(-)
+
+commit 4c8a414a101c9657fda42d2fdb9789407b034c99
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 10:22:12 2023 -0700
+
+    [wasm-api] Clean up debugprint
+
+ src/hb-wasm-api.hh | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+commit 63904538c8215312489afd0277d78199c88a512a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 10:11:22 2023 -0700
+
+    [wasm-api] Use i32 instead of externref in API spec
+    
+    Oh well...
+
+ src/hb-wasm-api.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit bd28d01a6a1e562dc611e386544075f6caeacf21
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 09:49:46 2023 -0700
+
+    [wasm-api] Add HB_WASM_INTERFACE
+
+ src/hb-wasm-api.h | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+commit ed1a70c7e8ddf78ea3fd3e6208e683870ff7e893
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu Feb 23 16:41:17 2023 +0000
+
+    Only export debugprint when HB_DEBUG_WASM
+
+ src/hb-wasm-api.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 89c50b0ccb60fc0d73f2b9d65ccbdaebe6fef5b1
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu Feb 23 16:41:04 2023 +0000
+
+    Fix debugprint format string
+
+ src/hb-wasm-api.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f0200445d0606019cec868dfc92b1cde5015e6d5
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu Feb 23 16:38:39 2023 +0000
+
+    Initial WASM docs and Rust example
+
+ docs/wasm-shaper.md | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 116 insertions(+)
+
+commit fd1f7f46f46cd9dba29ad4975f09f6d4073edae4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 09:25:05 2023 -0700
+
+    [wasm-api] Implement font_get_face
+
+ src/hb-wasm-api.hh  |  7 ++++++-
+ src/hb-wasm-font.hh | 12 ++++++++++--
+ 2 files changed, 16 insertions(+), 3 deletions(-)
+
+commit 9f4dc2e103290cd7447ab24b2561c52d0f66344b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 09:18:25 2023 -0700
+
+    [wasm] Bind native API
+
+ src/hb-wasm-api.h    | 10 ++++++++--
+ src/hb-wasm-api.hh   | 27 +++++++++++++++++++++++++++
+ src/hb-wasm-font.hh  |  3 ++-
+ src/hb-wasm-shape.cc | 25 ++-----------------------
+ 4 files changed, 39 insertions(+), 26 deletions(-)
+
+commit e79a7318c4956fa9a8974812332480ccc5a13991
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 09:03:06 2023 -0700
+
+    [wasm] Start adding wasm-api
+
+ src/harfbuzz-subset.cc |  1 -
+ src/harfbuzz.cc        |  1 -
+ src/hb-wasm-api.h      | 29 +++++++++++++++++------------
+ src/hb-wasm-api.hh     | 45 +++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-font.hh    | 44 ++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-wasm-shape.cc   |  4 ++--
+ 6 files changed, 108 insertions(+), 16 deletions(-)
+
+commit 829ba7428476da0616d6b92b88189224acc36cf0
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 08:32:14 2023 -0700
+
+    [wasm] Add hb-wasm-api.h
+
+ src/hb-wasm-api.h | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 70 insertions(+)
+
+commit 11c6d46086f5758a71df8e58059e087cd9c1766f
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Feb 23 08:16:49 2023 -0700
+
+    [wasm] Pass font & buff to shape() function
+
+ src/hb-wasm-shape.cc | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+commit 05bf9842128376db20b1c1da91efe0257b23a351
+Author: Simon Cozens <simon at simon-cozens.org>
+Date:   Thu Feb 23 14:55:49 2023 +0000
+
+    Add a simple callback native function
+
+ src/hb-wasm-shape.cc | 27 ++++++++++++---------------
+ 1 file changed, 12 insertions(+), 15 deletions(-)
+
+commit bdbc1568bac50371d4b552e179ecfc338f12fd43
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Feb 22 23:30:28 2023 -0700
+
+    [wasm] Port from c_api to wasm-micro-runtime wasm_runtime API
+
+ src/hb-debug.hh      |   4 ++
+ src/hb-wasm-shape.cc | 190 +++++++++++++++++++++++++++++++--------------------
+ 2 files changed, 119 insertions(+), 75 deletions(-)
+
+commit db8e51e01b972aaf6d32309ef5aa381964950af4
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Feb 22 13:33:34 2023 -0700
+
+    [wasm] More boilerplate
+
+ src/hb-wasm-shape.cc | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 67 insertions(+), 2 deletions(-)
+
+commit fcc8be409b8a8034af54caa0ccd0a91206fdbf6b
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Feb 22 12:57:19 2023 -0700
+
+    [wasm] Add meson build option
+    
+    Autotools support missing.
+
+ meson.build          |  5 ++++-
+ meson_options.txt    |  2 ++
+ src/hb-wasm-shape.cc | 57 +++++++++++++++++++++++++++++++++++++++++++---------
+ src/meson.build      | 10 ++++++++-
+ 4 files changed, 63 insertions(+), 11 deletions(-)
+
+commit 425fc7f3ee257b7aee9a481a04d368c4ccf57c4d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Feb 22 12:19:06 2023 -0700
+
+    [wasm] Add wasm shaper skeleton
+
+ meson.build            |   2 +
+ src/Makefile.sources   |   1 +
+ src/harfbuzz-subset.cc |   1 +
+ src/harfbuzz.cc        |   1 +
+ src/hb-shaper-list.hh  |   5 +++
+ src/hb-wasm-shape.cc   | 100 +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/meson.build        |   1 +
+ 7 files changed, 111 insertions(+)
+
 commit 04a47932a3844f7e73e3af8b05fb98c8b54fb779
 Author: Behdad Esfahbod <behdad at behdad.org>
 Date:   Fri Mar 31 11:44:08 2023 -0600

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,3 +1,45 @@
+Overview of changes leading to 8.0.0
+Sunday, July 9, 2023
+====================================
+- New, experimental, WebAssembly (WASM) shaper, that provides greater
+  flexibility over OpenType/AAT/Graphite shaping, using WebAssembly embedded
+  inside the font file. Currently WASM shaper is disabled by default and needs
+  to be enabled at build time. For details, see:
+
+    https://github.com/harfbuzz/harfbuzz/blob/main/docs/wasm-shaper.md
+
+  For example fonts making use of the WASM shaper, see:
+
+    https://github.com/simoncozens/wasm-examples
+
+- Improvements to Experimental features introduced in earlier releases:
+  - Support for subsetting beyond-64k and VarComposites fonts.
+  - Support for instancing variable fonts with cubic “glyf” table.
+
+- Many big speed optimizations:
+  - Up to 89% speedup loading variable fonts for shaping.
+  - Up to 88% speedup in small subsets of large (eg. CJK) fonts (both TTF and
+    OTF), essential for Incremental Font Transfer (IFT).
+  - Over 50% speedup in loading Roboto font for shaping.
+  - Up to 40% speed up in loading (sanitizing) complex fonts.
+  - 30% speed up in shaping Gulzar font.
+  - Over 25% speedup in glyph loading Roboto font.
+  - 10% speed up loading glyph shapes in VarComposite Hangul font.
+  - hb-hashmap optimizations & hashing improvements.
+
+- New macro HB_ALWAYS_INLINE. HarfBuzz now inlines functions more aggressively,
+  which results in some speedup at the expense of bigger code size. To disable
+  this feature define the macro to just inline.
+
+- New API:
++HB_CODEPOINT_INVALID
++hb_ot_layout_get_baseline2()
++hb_ot_layout_get_baseline_with_fallback2()
++hb_ot_layout_get_font_extents()
++hb_ot_layout_get_font_extents2()
++hb_subset_input_set_axis_range()
+
+
 Overview of changes leading to 7.3.0
 Tuesday, May 9, 2023
 ====================================

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/README
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/README	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/README	2023-07-09 05:55:34 UTC (rev 67588)
@@ -5,7 +5,9 @@
 [![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&utm_medium=referral&utm_content=harfbuzz/harfbuzz&utm_campaign=Badge_Grade)
 [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
 [![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions)
+[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/harfbuzz/harfbuzz/badge)](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz)
 
+
 # HarfBuzz
 
 HarfBuzz is a text shaping engine. It primarily supports [OpenType][1], but also

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md	2023-07-09 05:55:34 UTC (rev 67588)
@@ -5,7 +5,9 @@
 [![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&utm_medium=referral&utm_content=harfbuzz/harfbuzz&utm_campaign=Badge_Grade)
 [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
 [![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions)
+[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/harfbuzz/harfbuzz/badge)](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz)
 
+
 # HarfBuzz
 
 HarfBuzz is a text shaping engine. It primarily supports [OpenType][1], but also

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.python.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.python.md	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.python.md	2023-07-09 05:55:34 UTC (rev 67588)
@@ -9,9 +9,13 @@
 And then run `meson setup` and make sure that `Introspection` is reported
 enabled in output.
 
+If you are building with Visual Studio, it is recommended that Visual Studio
+2019 or later is used for this build, for the best build experience.
+
 Compile and install.
 
-Make sure you have the installation lib dir in `LD_LIBRARY_PATH`, as needed
+Make sure you have the installation lib dir in `LD_LIBRARY_PATH` (or the
+installation DLL dir in `PATH` for Windows systems), as needed
 for the linker to find the library.
 
 Then make sure you also have `GI_TYPELIB_PATH` pointing to the resulting

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in	2023-07-09 05:55:34 UTC (rev 67588)
@@ -136,6 +136,12 @@
 /* Define to 1 if you have the <usp10.h> header file. */
 #undef HAVE_USP10_H
 
+/* Have wasm-micro-runtime library */
+#undef HAVE_WASM
+
+/* Define to 1 if you have the <wasm_export.h> header file. */
+#undef HAVE_WASM_EXPORT_H
+
 /* Define to 1 if you have the <windows.h> header file. */
 #undef HAVE_WINDOWS_H
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [7.3.0],
+        [8.0.0],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
@@ -417,6 +417,28 @@
 
 dnl ===========================================================================
 
+AC_ARG_WITH(wasm,
+	[AS_HELP_STRING([--with-wasm=@<:@yes/no/auto@:>@],
+			[Use the wasm-micro-runtime library @<:@default=no@:>@])],,
+	[with_wasm=no])
+have_wasm=false
+if test "x$with_wasm" = "xyes" -o "x$with_wasm" = "xauto"; then
+	AC_CHECK_HEADERS(wasm_export.h, have_wasm=true)
+fi
+if test "x$with_wasm" = "xyes" -a "x$have_wasm" != "xtrue"; then
+	AC_MSG_ERROR([wasm support requested but not found])
+fi
+if $have_wasm; then
+	WASM_CFLAGS=
+	WASM_LIBS="-liwasm"
+	AC_SUBST(WASM_CFLAGS)
+	AC_SUBST(WASM_LIBS)
+	AC_DEFINE(HAVE_WASM, 1, [Have wasm-micro-runtime library])
+fi
+AM_CONDITIONAL(HAVE_WASM, $have_wasm)
+
+dnl ===========================================================================
+
 AC_CONFIG_FILES([
 Makefile
 src/Makefile
@@ -478,6 +500,7 @@
 	DirectWrite:		${have_directwrite}
 	GDI:			${have_gdi}
 	Uniscribe:		${have_uniscribe}
+	WebAssembly:		${have_wasm}
 
 Other features:
 	Documentation:		${enable_gtk_doc}

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,6 +1,6 @@
 project('harfbuzz', 'c', 'cpp',
   meson_version: '>= 0.55.0',
-  version: '7.3.0',
+  version: '8.0.0',
   default_options: [
     'cpp_eh=none',          # Just to support msvc, we are passing -fno-exceptions also anyway
     'cpp_rtti=false',       # Just to support msvc, we are passing -fno-rtti also anyway
@@ -115,6 +115,9 @@
 gobject_dep = dependency('gobject-2.0', required: get_option('gobject'))
 graphite2_dep = dependency('graphite2', required: get_option('graphite2'))
 graphite_dep = dependency('graphite2', required: get_option('graphite'))
+wasm_dep = cpp.find_library('iwasm', required: get_option('wasm'))
+# How to check whether iwasm was built, and hence requires, LLVM?
+#llvm_dep = cpp.find_library('LLVM-15', required: get_option('wasm'))
 
 if meson.version().version_compare('>=0.60.0')
   # pkg-config: icu-uc, cmake: ICU but with components
@@ -121,7 +124,6 @@
   icu_dep = dependency('icu-uc', 'ICU',
                             components: 'uc',
                             required: get_option('icu'),
-                            default_options: ['harfbuzz=disabled'],
                             allow_fallback: true)
 else
   # painful hack to handle multiple dependencies but also respect options
@@ -230,6 +232,11 @@
   conf.set('HAVE_CHAFA', 1)
 endif
 
+if wasm_dep.found()
+  conf.set('HAVE_WASM', 1)
+  conf.set('HB_WASM_MODULE_DIR', '"'+get_option('prefix')+'/'+get_option('libdir')+'/harfbuzz/wasm"')
+endif
+
 if graphite2_dep.found() or graphite_dep.found()
   conf.set('HAVE_GRAPHITE2', 1)
 endif
@@ -419,10 +426,11 @@
     },
   'Additional shapers':
     {'Graphite2': conf.get('HAVE_GRAPHITE2', 0) == 1,
+     'WebAssembly (experimental)': conf.get('HAVE_WASM', 0) == 1,
     },
   'Platform shapers (not normally needed)':
     {'CoreText': conf.get('HAVE_CORETEXT', 0) == 1,
-     'DirectWrite': conf.get('HAVE_DIRECTWRITE', 0) == 1,
+     'DirectWrite (experimental)': conf.get('HAVE_DIRECTWRITE', 0) == 1,
      'GDI/Uniscribe': (conf.get('HAVE_GDI', 0) == 1) and (conf.get('HAVE_UNISCRIBE', 0) == 1),
     },
   'Other features':

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt	2023-07-09 05:55:34 UTC (rev 67588)
@@ -21,6 +21,8 @@
   description: 'Enable DirectWrite shaper backend on Windows (experimental)')
 option('coretext', type: 'feature', value: 'disabled',
   description: 'Enable CoreText shaper backend on macOS')
+option('wasm', type: 'feature', value: 'disabled',
+  description: 'Enable WebAssembly shaper backend (experimental)')
 
 # Common feature options
 option('tests', type: 'feature', value: 'enabled', yield: true,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am	2023-07-09 05:55:34 UTC (rev 67588)
@@ -114,7 +114,17 @@
 HB_HAS_CORETEXT_DEF = undef HB_HAS_CORETEXT
 endif
 
+if HAVE_WASM
+HBCFLAGS += $(WASM_CFLAGS)
+HBNONPCLIBS += $(WASM_LIBS)
+HBSOURCES += $(HB_WASM_sources)
+HBHEADERS += $(HB_WASM_headers)
+HB_HAS_WASM_DEF = define HB_HAS_WASM 1
+else
+HB_HAS_WASM_DEF = undef HB_HAS_WASM
+endif
 
+
 BUILT_SOURCES += \
 	hb-version.h
 
@@ -273,16 +283,17 @@
 hb-features.h: hb-features.h.in $(top_builddir)/config.status
 	$(AM_V_GEN) $(SED) \
 		-e 's/mesondefine HB_HAS_CAIRO/$(HB_HAS_CAIRO_DEF)/' \
+		-e 's/mesondefine HB_HAS_CORETEXT/$(HB_HAS_CORETEXT_DEF)/' \
+		-e 's/mesondefine HB_HAS_DIRECTWRITE/$(HB_HAS_DIRECTWRITE_DEF)/' \
 		-e 's/mesondefine HB_HAS_FREETYPE/$(HB_HAS_FREETYPE_DEF)/' \
 		-e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \
 		-e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \
-		-e 's/mesondefine HB_HAS_GRAPHITE/$(HB_HAS_GRAPHITE_DEF)/' \
 		-e 's/mesondefine HB_HAS_GLIB/$(HB_HAS_GLIB_DEF)/' \
 		-e 's/mesondefine HB_HAS_GOBJECT/$(HB_HAS_GOBJECT_DEF)/' \
+		-e 's/mesondefine HB_HAS_GRAPHITE/$(HB_HAS_GRAPHITE_DEF)/' \
+		-e 's/mesondefine HB_HAS_ICU/$(HB_HAS_ICU_DEF)/' \
 		-e 's/mesondefine HB_HAS_UNISCRIBE/$(HB_HAS_UNISCRIBE_DEF)/' \
-		-e 's/mesondefine HB_HAS_DIRECTWRITE/$(HB_HAS_DIRECTWRITE_DEF)/' \
-		-e 's/mesondefine HB_HAS_CORETEXT/$(HB_HAS_CORETEXT_DEF)/' \
-		-e 's/mesondefine HB_HAS_ICU/$(HB_HAS_ICU_DEF)/' \
+		-e 's/mesondefine HB_HAS_WASM/$(HB_HAS_WASM_DEF)/' \
 		"$<" > "$@" || ($(RM) "$@"; false)
 
 
@@ -445,6 +456,8 @@
 	test-vector \
 	test-repacker \
 	test-classdef-graph \
+	test-instancer-solver \
+	test-tuple-varstore \
 	$(NULL)
 COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
 COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
@@ -515,6 +528,14 @@
 test_vector_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
 test_vector_LDADD = $(COMPILED_TESTS_LDADD)
 
+test_instancer_solver_SOURCES = test-subset-instancer-solver.cc hb-subset-instancer-solver.cc hb-static.cc
+test_instancer_solver_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_instancer_solver_LDADD = $(COMPILED_TESTS_LDADD)
+
+test_tuple_varstore_SOURCES = test-tuple-varstore.cc hb-subset-instancer-solver.cc hb-static.cc
+test_tuple_varstore_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_tuple_varstore_LDADD = $(COMPILED_TESTS_LDADD)
+
 dist_check_SCRIPTS = \
 	check-c-linkage-decls.py \
 	check-externs.py \

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources	2023-07-09 05:55:34 UTC (rev 67588)
@@ -338,10 +338,22 @@
 HB_UNISCRIBE_sources = hb-uniscribe.cc
 HB_UNISCRIBE_headers = hb-uniscribe.h
 
-# Sources for libharfbuzz-gobject and libharfbuzz-icu
 HB_ICU_sources = hb-icu.cc
 HB_ICU_headers = hb-icu.h
 
+HB_WASM_sources = \
+	hb-wasm-api.cc \
+	hb-wasm-api.hh \
+	hb-wasm-api-blob.hh \
+	hb-wasm-api-buffer.hh \
+	hb-wasm-api-common.hh \
+	hb-wasm-api-face.hh \
+	hb-wasm-api-font.hh \
+	hb-wasm-api-shape.hh \
+	hb-wasm-shape.cc \
+	$(NULL)
+HB_WASM_headers = hb-wasm-api.h
+
 # Sources for libharfbuzz-subset
 HB_SUBSET_sources = \
 	hb-number.cc \
@@ -353,11 +365,10 @@
 	hb-subset-cff-common.cc \
 	hb-subset-cff-common.hh \
 	hb-subset-cff1.cc \
-	hb-subset-cff1.hh \
 	hb-subset-cff2.cc \
-	hb-subset-cff2.hh \
 	hb-subset-input.cc \
 	hb-subset-input.hh \
+	hb-subset-instancer-solver.hh \
 	hb-subset-instancer-solver.cc \
 	hb-subset-accelerator.hh \
 	hb-subset-plan.cc \

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -397,7 +397,6 @@
     TRACE_SERIALIZE (this);
 
     auto *subtable = c->serializer->start_embed<IndexSubtable> ();
-    if (unlikely (!subtable)) return_trace (false);
     if (unlikely (!c->serializer->extend_min (subtable))) return_trace (false);
 
     auto *old_subtable = get_subtable (base);
@@ -545,7 +544,8 @@
 		const IndexSubtableRecord*>> *lookup /* OUT */) const
   {
     bool start_glyph_is_set = false;
-    for (hb_codepoint_t new_gid = 0; new_gid < c->plan->num_output_glyphs (); new_gid++)
+    unsigned num_glyphs = c->plan->num_output_glyphs ();
+    for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
     {
       hb_codepoint_t old_gid;
       if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) continue;
@@ -576,9 +576,6 @@
   {
     TRACE_SUBSET (this);
 
-    auto *dst = c->serializer->start_embed<IndexSubtableArray> ();
-    if (unlikely (!dst)) return_trace (false);
-
     hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> lookup;
     build_lookup (c, bitmap_size_context, &lookup);
     if (unlikely (!c->serializer->propagate_error (lookup)))
@@ -993,12 +990,10 @@
 {
   TRACE_SUBSET (this);
 
-  auto *cblc_prime = c->serializer->start_embed<CBLC> ();
-
   // Use a vector as a secondary buffer as the tables need to be built in parallel.
   hb_vector_t<char> cbdt_prime;
 
-  if (unlikely (!cblc_prime)) return_trace (false);
+  auto *cblc_prime = c->serializer->start_embed<CBLC> ();
   if (unlikely (!c->serializer->extend_min (cblc_prime))) return_trace (false);
   cblc_prime->version = version;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -409,7 +409,6 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (this);
-    if (unlikely (!out)) return_trace (false);
     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
     if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
@@ -1434,6 +1433,7 @@
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+		  c->check_ops (this->min_size) && // PainComposite can get exponential
                   src.sanitize (c, this) &&
                   backdrop.sanitize (c, this));
   }
@@ -2167,7 +2167,7 @@
     if (version == 0 && (!base_it || !layer_it))
       return_trace (false);
 
-    COLR *colr_prime = c->serializer->start_embed<COLR> ();
+    auto *colr_prime = c->serializer->start_embed<COLR> ();
     if (unlikely (!c->serializer->extend_min (colr_prime)))  return_trace (false);
 
     if (version == 0)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/sbix/sbix.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/sbix/sbix.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/sbix/sbix.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -48,7 +48,6 @@
   {
     TRACE_SERIALIZE (this);
     SBIXGlyph* new_glyph = c->start_embed<SBIXGlyph> ();
-    if (unlikely (!new_glyph)) return_trace (nullptr);
     if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr);
 
     new_glyph->xOffset = xOffset;
@@ -143,7 +142,6 @@
     unsigned int num_output_glyphs = c->plan->num_output_glyphs ();
 
     auto* out = c->serializer->start_embed<SBIXStrike> ();
-    if (unlikely (!out)) return_trace (false);
     auto snap = c->serializer->snapshot ();
     if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false);
     out->ppem = ppem;
@@ -388,7 +386,6 @@
     TRACE_SERIALIZE (this);
 
     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<Offset32To<SBIXStrike>*> new_strikes;
@@ -423,8 +420,6 @@
   {
     TRACE_SUBSET (this);
 
-    sbix *sbix_prime = c->serializer->start_embed<sbix> ();
-    if (unlikely (!sbix_prime)) return_trace (false);
     if (unlikely (!c->serializer->embed (this->version))) return_trace (false);
     if (unlikely (!c->serializer->embed (this->flags))) return_trace (false);
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -57,6 +57,9 @@
   public:
   DEFINE_SIZE_UNION (2, format);
 
+#ifndef HB_OPTIMIZE_SIZE
+  HB_ALWAYS_INLINE
+#endif
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -79,7 +79,7 @@
   {
     if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
     {
-      for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+      for (auto g : *glyphs)
         if (get_coverage (g) != NOT_COVERED)
 	  return true;
       return false;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -122,7 +122,7 @@
   {
     if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
     {
-      for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+      for (auto g : *glyphs)
         if (get_coverage (g) != NOT_COVERED)
 	  return true;
       return false;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -49,8 +49,6 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out)) return_trace (false);
-
     return_trace (out->serialize (c->serializer, + iter ()));
   }
 };
@@ -202,7 +200,6 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out)) return_trace (false);
     if (!c->serializer->embed (caretValueFormat)) return_trace (false);
     if (!c->serializer->embed (coordinate)) return_trace (false);
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorFormat3.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorFormat3.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorFormat3.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -25,7 +25,9 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+
+    return_trace (xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
   }
 
   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
@@ -35,9 +37,9 @@
     *x = font->em_fscale_x (xCoordinate);
     *y = font->em_fscale_y (yCoordinate);
 
-    if (font->x_ppem || font->num_coords)
+    if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this))
       *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
-    if (font->y_ppem || font->num_coords)
+    if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
       *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
   }
 
@@ -45,7 +47,6 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out)) return_trace (false);
     if (unlikely (!c->serializer->embed (format))) return_trace (false);
     if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
     if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -21,18 +21,25 @@
     if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
     unsigned int count = rows * cols;
     if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
+
+    if (c->lazy_some_gpos)
+      return_trace (true);
+
     for (unsigned int i = 0; i < count; i++)
       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
     return_trace (true);
   }
 
-  const Anchor& get_anchor (unsigned int row, unsigned int col,
-                            unsigned int cols, bool *found) const
+  const Anchor& get_anchor (hb_ot_apply_context_t *c,
+			    unsigned int row, unsigned int col,
+			    unsigned int cols, bool *found) const
   {
     *found = false;
     if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
-    *found = !matrixZ[row * cols + col].is_null ();
-    return this+matrixZ[row * cols + col];
+    auto &offset = matrixZ[row * cols + col];
+    if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor);
+    *found = !offset.is_null ();
+    return this+offset;
   }
 
   template <typename Iterator,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/CursivePosFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/CursivePosFormat1.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/CursivePosFormat1.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -278,7 +278,6 @@
     const hb_map_t &glyph_map = *c->plan->glyph_map;
 
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out)) return_trace (false);
 
     auto it =
     + hb_zip (this+coverage, entryExitRecord)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkArray.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkArray.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkArray.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -28,7 +28,7 @@
 
     const Anchor& mark_anchor = this + record.markAnchor;
     bool found;
-    const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
+    const Anchor& glyph_anchor = anchors.get_anchor (c, glyph_index, mark_class, class_count, &found);
     /* If this subtable doesn't have an anchor for this base and this class,
      * return false such that the subsequent subtables have a chance at it. */
     if (unlikely (!found)) return_trace (false);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -54,8 +54,9 @@
     return_trace (c->check_range ((const void *) values,
                                   count,
                                   stride) &&
-                  valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
-                  valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
+		  (c->lazy_some_gpos ||
+		   (valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
+		    valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride))));
   }
 
   bool intersects (const hb_set_t *glyphs) const
@@ -298,11 +299,13 @@
       out->valueFormat2 = out->valueFormat2.drop_device_table_flags ();
     }
 
+    unsigned total_len = len1 + len2;
+    hb_vector_t<unsigned> class2_idxs (+ hb_range ((unsigned) class2Count) | hb_filter (klass2_map));
     for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
     {
-      for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+      for (unsigned class2_idx : class2_idxs)
       {
-        unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+        unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * total_len;
         valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], &c->plan->layout_variation_idx_delta_map);
         valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &c->plan->layout_variation_idx_delta_map);
       }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairSet.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairSet.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairSet.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -52,8 +52,9 @@
 
     unsigned int count = len;
     const PairValueRecord *record = &firstPairValueRecord;
-    return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
-                  closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
+    return_trace (c->lazy_some_gpos ||
+		  (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
+                   closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)));
   }
 
   bool intersects (const hb_set_t *glyphs,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -90,6 +90,7 @@
 
   bool
   position_single (hb_font_t           *font,
+		   hb_blob_t           *table_blob,
 		   hb_direction_t       direction,
 		   hb_codepoint_t       gid,
 		   hb_glyph_position_t &pos) const
@@ -100,7 +101,7 @@
     /* This is ugly... */
     hb_buffer_t buffer;
     buffer.props.direction = direction;
-    OT::hb_ot_apply_context_t c (1, font, &buffer);
+    OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
 
     valueFormat.apply_value (&c, this, values, pos);
     return true;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -94,6 +94,7 @@
 
   bool
   position_single (hb_font_t           *font,
+		   hb_blob_t           *table_blob,
 		   hb_direction_t       direction,
 		   hb_codepoint_t       gid,
 		   hb_glyph_position_t &pos) const
@@ -105,7 +106,7 @@
     /* This is ugly... */
     hb_buffer_t buffer;
     buffer.props.direction = direction;
-    OT::hb_ot_apply_context_t c (1, font, &buffer);
+    OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
 
     valueFormat.apply_value (&c, this,
                              &values[index * valueFormat.get_len ()],

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/ValueFormat.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/ValueFormat.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/ValueFormat.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -118,21 +118,25 @@
     auto *cache = c->var_store_cache;
 
     /* pixel -> fractional pixel */
-    if (format & xPlaDevice) {
-      if (use_x_device) glyph_pos.x_offset  += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+    if (format & xPlaDevice)
+    {
+      if (use_x_device) glyph_pos.x_offset  += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache);
       values++;
     }
-    if (format & yPlaDevice) {
-      if (use_y_device) glyph_pos.y_offset  += (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+    if (format & yPlaDevice)
+    {
+      if (use_y_device) glyph_pos.y_offset  += get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache);
       values++;
     }
-    if (format & xAdvDevice) {
-      if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+    if (format & xAdvDevice)
+    {
+      if (horizontal && use_x_device) glyph_pos.x_advance += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache);
       values++;
     }
-    if (format & yAdvDevice) {
+    if (format & yAdvDevice)
+    {
       /* y_advance values grow downward but font-space grows upward, hence negation */
-      if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+      if (!horizontal && use_y_device) glyph_pos.y_advance -= get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache);
       values++;
     }
     return ret;
@@ -174,6 +178,9 @@
     if (format & xAdvance)   x_adv = copy_value (c, new_format, xAdvance, *values++);
     if (format & yAdvance)   y_adv = copy_value (c, new_format, yAdvance, *values++);
 
+    if (!has_device ())
+      return;
+
     if (format & xPlaDevice)
     {
       add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map);
@@ -233,7 +240,6 @@
 
     if (format & ValueFormat::xAdvDevice)
     {
-
       (base + get_device (&(values[i]))).collect_variation_indices (c);
       i++;
     }
@@ -240,7 +246,6 @@
 
     if (format & ValueFormat::yAdvDevice)
     {
-
       (base + get_device (&(values[i]))).collect_variation_indices (c);
       i++;
     }
@@ -277,12 +282,24 @@
   {
     return *static_cast<Offset16To<Device> *> (value);
   }
-  static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
+  static inline const Offset16To<Device>& get_device (const Value* value)
   {
-    if (worked) *worked |= bool (*value);
     return *static_cast<const Offset16To<Device> *> (value);
   }
+  static inline const Device& get_device (const Value* value,
+					  bool *worked,
+					  const void *base,
+					  hb_sanitize_context_t &c)
+  {
+    if (worked) *worked |= bool (*value);
+    auto &offset = *static_cast<const Offset16To<Device> *> (value);
 
+    if (unlikely (!offset.sanitize (&c, base)))
+      return Null(Device);
+
+    return base + offset;
+  }
+
   void add_delta_to_value (HBINT16 *value,
                            const void *base,
                            const Value *src_value,
@@ -340,25 +357,26 @@
   bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
+
+    if (unlikely (!c->check_range (values, get_size ()))) return_trace (false);
+
+    if (c->lazy_some_gpos)
+      return_trace (true);
+
+    return_trace (!has_device () || sanitize_value_devices (c, base, values));
   }
 
   bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
   {
     TRACE_SANITIZE (this);
-    unsigned int len = get_len ();
+    unsigned size = get_size ();
 
-    if (!c->check_range (values, count, get_size ())) return_trace (false);
+    if (!c->check_range (values, count, size)) return_trace (false);
 
-    if (!has_device ()) return_trace (true);
+    if (c->lazy_some_gpos)
+      return_trace (true);
 
-    for (unsigned int i = 0; i < count; i++) {
-      if (!sanitize_value_devices (c, base, values))
-        return_trace (false);
-      values += len;
-    }
-
-    return_trace (true);
+    return_trace (sanitize_values_stride_unsafe (c, base, values, count, size));
   }
 
   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Common.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Common.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -8,8 +8,6 @@
 namespace Layout {
 namespace GSUB_impl {
 
-typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
-
 template<typename Iterator>
 static void SingleSubst_serialize (hb_serialize_context_t *c,
                                    Iterator it);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Ligature.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Ligature.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Ligature.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -13,12 +13,13 @@
   public:
   typename Types::HBGlyphID
 		ligGlyph;               /* GlyphID of ligature to substitute */
-  HeadlessArrayOf<typename Types::HBGlyphID>
+  HeadlessArray16Of<typename Types::HBGlyphID>
 		component;              /* Array of component GlyphIDs--start
                                          * with the second  component--ordered
                                          * in writing direction */
   public:
   DEFINE_SIZE_ARRAY (Types::size + 2, component);
+  DEFINE_SIZE_MAX (65536 * Types::HBGlyphID::static_size);
 
   bool sanitize (hb_sanitize_context_t *c) const
   {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -191,7 +191,6 @@
     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);
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Sequence.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Sequence.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Sequence.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -53,7 +53,7 @@
       if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
       {
 	c->buffer->message (c->font,
-			    "replaced glyph at %u (multiple subtitution)",
+			    "replaced glyph at %u (multiple substitution)",
 			    c->buffer->idx - 1u);
       }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -90,24 +90,36 @@
   static void transform (const float (&matrix)[4],
 			 hb_array_t<contour_point_t> points)
   {
-    auto arrayZ = points.arrayZ;
-    unsigned count = points.length;
-
     if (matrix[0] != 1.f || matrix[1] != 0.f ||
 	matrix[2] != 0.f || matrix[3] != 1.f)
-      for (unsigned i = 0; i < count; i++)
-        arrayZ[i].transform (matrix);
+      for (auto &point : points)
+        point.transform (matrix);
   }
 
   static void translate (const contour_point_t &trans,
 			 hb_array_t<contour_point_t> points)
   {
-    auto arrayZ = points.arrayZ;
-    unsigned count = points.length;
-
-    if (trans.x != 0.f || trans.y != 0.f)
-      for (unsigned i = 0; i < count; i++)
-        arrayZ[i].translate (trans);
+    if (HB_OPTIMIZE_SIZE_VAL)
+    {
+      if (trans.x != 0.f || trans.y != 0.f)
+        for (auto &point : points)
+	  point.translate (trans);
+    }
+    else
+    {
+      if (trans.x != 0.f && trans.y != 0.f)
+        for (auto &point : points)
+	  point.translate (trans);
+      else
+      {
+	if (trans.x != 0.f)
+	  for (auto &point : points)
+	    point.x += trans.x;
+	else if (trans.y != 0.f)
+	  for (auto &point : points)
+	    point.y += trans.y;
+      }
+    }
   }
 
   void transform_points (hb_array_t<contour_point_t> points,
@@ -131,9 +143,8 @@
     float matrix[4];
     contour_point_t trans;
     get_transformation (matrix, trans);
-    points.alloc (points.length + 4); // For phantom points
-    if (unlikely (!points.resize (points.length + 1))) return false;
-    points.arrayZ[points.length - 1] = trans;
+    if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points
+    points.push (trans);
     return true;
   }
 
@@ -382,7 +393,7 @@
     {
       /* last 4 points in points_with_deltas are phantom points and should not be included */
       if (i >= points_with_deltas.length - 4) {
-        free (o);
+        hb_free (o);
         return false;
       }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -114,8 +114,8 @@
 
     if (type != EMPTY)
     {
-      plan->bounds_width_map.set (new_gid, xMax - xMin);
-      plan->bounds_height_map.set (new_gid, yMax - yMin);
+      plan->bounds_width_vec[new_gid] = xMax - xMin;
+      plan->bounds_height_vec[new_gid] = yMax - yMin;
     }
 
     unsigned len = all_points.length;
@@ -124,10 +124,12 @@
     float topSideY = all_points[len - 2].y;
     float bottomSideY = all_points[len - 1].y;
 
+    uint32_t hash = hb_hash (new_gid);
+
     signed hori_aw = roundf (rightSideX - leftSideX);
     if (hori_aw < 0) hori_aw = 0;
     int lsb = roundf (xMin - leftSideX);
-    plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
+    plan->hmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) hori_aw, lsb));
     //flag value should be computed using non-empty glyphs
     if (type != EMPTY && lsb != xMin)
       plan->head_maxp_info.allXMinIsLsb = false;
@@ -135,7 +137,7 @@
     signed vert_aw = roundf (topSideY - bottomSideY);
     if (vert_aw < 0) vert_aw = 0;
     int tsb = roundf (topSideY - yMax);
-    plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
+    plan->vmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) vert_aw, tsb));
   }
 
   bool compile_header_bytes (const hb_subset_plan_t *plan,
@@ -369,9 +371,11 @@
     }
 
 #ifndef HB_NO_VAR
-    glyf_accelerator.gvar->apply_deltas_to_points (gid,
-						   coords,
-						   points.as_array ().sub_array (old_length));
+    if (coords)
+      glyf_accelerator.gvar->apply_deltas_to_points (gid,
+						     coords,
+						     points.as_array ().sub_array (old_length),
+						     phantom_only && type == SIMPLE);
 #endif
 
     // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
@@ -379,7 +383,7 @@
     if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
     {
       if (unlikely (!points_with_deltas->resize (points.length))) return false;
-      points_with_deltas->copy_vector (points);
+      *points_with_deltas = points;
     }
 
     switch (type) {
@@ -417,14 +421,17 @@
 	  for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
 	    phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
 
-	float matrix[4];
-	contour_point_t default_trans;
-	item.get_transformation (matrix, default_trans);
+	if (comp_points) // Empty in case of phantom_only
+	{
+	  float matrix[4];
+	  contour_point_t default_trans;
+	  item.get_transformation (matrix, default_trans);
 
-	/* Apply component transformation & translation (with deltas applied) */
-	item.transform_points (comp_points, matrix, points[comp_index]);
+	  /* Apply component transformation & translation (with deltas applied) */
+	  item.transform_points (comp_points, matrix, points[comp_index]);
+	}
 
-	if (item.is_anchored ())
+	if (item.is_anchored () && !phantom_only)
 	{
 	  unsigned int p1, p2;
 	  item.get_anchor_points (p1, p2);
@@ -466,7 +473,10 @@
 	assert (record_points.length == item_num_points);
 
 	auto component_coords = coords;
-	if (item.is_reset_unspecified_axes ())
+	/* Copying coords is expensive; so we have put an arbitrary
+	 * limit on the max number of coords for now. */
+	if (item.is_reset_unspecified_axes () ||
+	    coords.length > HB_GLYF_VAR_COMPOSITE_MAX_AXES)
 	  component_coords = hb_array<int> ();
 
 	coord_setter_t coord_setter (component_coords);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -154,10 +154,9 @@
   {
     int v = 0;
 
-    unsigned count = points_.length;
-    for (unsigned i = 0; i < count; i++)
+    for (auto &point : points_)
     {
-      unsigned flag = points_.arrayZ[i].flag;
+      unsigned flag = point.flag;
       if (flag & short_flag)
       {
 	if (unlikely (p + 1 > end)) return false;
@@ -175,7 +174,7 @@
 	  p += HBINT16::static_size;
 	}
       }
-      points_.arrayZ[i].*m = v;
+      point.*m = v;
     }
     return true;
   }
@@ -192,9 +191,10 @@
 
     unsigned old_length = points.length;
     points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy
-    if (!points.resize (points.length + num_points, false)) return false;
+    if (unlikely (!points.resize (points.length + num_points, false))) return false;
     auto points_ = points.as_array ().sub_array (old_length);
-    hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points);
+    if (!phantom_only)
+      hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points);
     if (phantom_only) return true;
 
     for (int i = 0; i < num_contours; i++)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SubsetGlyph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SubsetGlyph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SubsetGlyph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -22,7 +22,7 @@
 
   bool serialize (hb_serialize_context_t *c,
 		  bool use_short_loca,
-		  const hb_subset_plan_t *plan)
+		  const hb_subset_plan_t *plan) const
   {
     TRACE_SERIALIZE (this);
 
@@ -40,7 +40,7 @@
     pad = 0;
     while (pad_length > 0)
     {
-      c->embed (pad);
+      (void) c->embed (pad);
       pad_length--;
     }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/VarCompositeGlyph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/VarCompositeGlyph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/VarCompositeGlyph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -214,7 +214,7 @@
     points.alloc (points.length + num_points + 4); // For phantom points
     if (unlikely (!points.resize (points.length + num_points, false))) return false;
     contour_point_t *rec_points = points.arrayZ + (points.length - num_points);
-    memset (rec_points, 0, num_points * sizeof (rec_points[0]));
+    hb_memset (rec_points, 0, num_points * sizeof (rec_points[0]));
 
     unsigned fl = flags;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/coord-setter.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/coord-setter.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/coord-setter.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -16,6 +16,8 @@
 
   int& operator [] (unsigned idx)
   {
+    if (unlikely (idx >= HB_GLYF_VAR_COMPOSITE_MAX_AXES))
+      return Crap(int);
     if (coords.length < idx + 1)
       coords.resize (idx + 1);
     return coords[idx];

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf-helpers.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf-helpers.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf-helpers.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -12,24 +12,44 @@
 namespace glyf_impl {
 
 
-template<typename IteratorIn, typename IteratorOut,
-	 hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
-	 hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
+template<typename IteratorIn, typename TypeOut,
+	 hb_requires (hb_is_source_of (IteratorIn, unsigned int))>
 static void
-_write_loca (IteratorIn&& it, bool short_offsets, IteratorOut&& dest)
+_write_loca (IteratorIn&& it,
+	     const hb_sorted_vector_t<hb_codepoint_pair_t> new_to_old_gid_list,
+	     bool short_offsets,
+	     TypeOut *dest,
+	     unsigned num_offsets)
 {
   unsigned right_shift = short_offsets ? 1 : 0;
-  unsigned int offset = 0;
-  dest << 0;
-  + it
-  | hb_map ([=, &offset] (unsigned int padded_size)
-	    {
-	      offset += padded_size;
-	      DEBUG_MSG (SUBSET, nullptr, "loca entry offset %u", offset);
-	      return offset >> right_shift;
-	    })
-  | hb_sink (dest)
-  ;
+  unsigned offset = 0;
+  TypeOut value;
+  value = 0;
+  *dest++ = value;
+  hb_codepoint_t last = 0;
+  for (auto _ : new_to_old_gid_list)
+  {
+    hb_codepoint_t gid = _.first;
+    for (; last < gid; last++)
+    {
+      DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset);
+      *dest++ = value;
+    }
+
+    unsigned padded_size = *it++;
+    offset += padded_size;
+    DEBUG_MSG (SUBSET, nullptr, "loca entry gid %u offset %u padded-size %u", gid, offset, padded_size);
+    value = offset >> right_shift;
+    *dest++ = value;
+
+    last++; // Skip over gid
+  }
+  unsigned num_glyphs = num_offsets - 1;
+  for (; last < num_glyphs; last++)
+  {
+    DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset);
+    *dest++ = value;
+  }
 }
 
 static bool
@@ -67,12 +87,15 @@
 template<typename Iterator,
 	 hb_requires (hb_is_source_of (Iterator, unsigned int))>
 static bool
-_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
+_add_loca_and_head (hb_subset_context_t *c,
+		    Iterator padded_offsets,
+		    bool use_short_loca)
 {
-  unsigned num_offsets = padded_offsets.len () + 1;
+  unsigned num_offsets = c->plan->num_output_glyphs () + 1;
   unsigned entry_size = use_short_loca ? 2 : 4;
-  char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
 
+  char *loca_prime_data = (char *) hb_malloc (entry_size * num_offsets);
+
   if (unlikely (!loca_prime_data)) return false;
 
   DEBUG_MSG (SUBSET, nullptr, "loca entry_size %u num_offsets %u size %u",
@@ -79,9 +102,9 @@
 	     entry_size, num_offsets, entry_size * num_offsets);
 
   if (use_short_loca)
-    _write_loca (padded_offsets, true, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
+    _write_loca (padded_offsets, c->plan->new_to_old_gid_list, true, (HBUINT16 *) loca_prime_data, num_offsets);
   else
-    _write_loca (padded_offsets, false, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
+    _write_loca (padded_offsets, c->plan->new_to_old_gid_list, false, (HBUINT32 *) loca_prime_data, num_offsets);
 
   hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
 					 entry_size * num_offsets,
@@ -89,8 +112,8 @@
 					 loca_prime_data,
 					 hb_free);
 
-  bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
-	     && _add_head_and_set_loca_version (plan, use_short_loca);
+  bool result = c->plan->add_table (HB_OT_TAG_loca, loca_blob)
+	     && _add_head_and_set_loca_version (c->plan, use_short_loca);
 
   hb_blob_destroy (loca_blob);
   return result;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -85,29 +85,23 @@
       return_trace (false);
     }
 
-    glyf *glyf_prime = c->serializer->start_embed <glyf> ();
-    if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
-
     hb_font_t *font = nullptr;
     if (c->plan->normalized_coords)
     {
       font = _create_font_for_instancing (c->plan);
-      if (unlikely (!font)) return false;
+      if (unlikely (!font))
+	return_trace (false);
     }
 
     hb_vector_t<unsigned> padded_offsets;
-    unsigned num_glyphs = c->plan->num_output_glyphs ();
-    if (unlikely (!padded_offsets.resize (num_glyphs)))
-    {
-      hb_font_destroy (font);
-      return false;
-    }
+    if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true)))
+      return_trace (false);
 
     hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
     if (!_populate_subset_glyphs (c->plan, font, glyphs))
     {
       hb_font_destroy (font);
-      return false;
+      return_trace (false);
     }
 
     if (font)
@@ -114,10 +108,11 @@
       hb_font_destroy (font);
 
     unsigned max_offset = 0;
-    for (unsigned i = 0; i < num_glyphs; i++)
+    for (auto &g : glyphs)
     {
-      padded_offsets[i] = glyphs[i].padded_size ();
-      max_offset += padded_offsets[i];
+      unsigned size = g.padded_size ();
+      padded_offsets.push (size);
+      max_offset += size;
     }
 
     bool use_short_loca = false;
@@ -124,28 +119,30 @@
     if (likely (!c->plan->force_long_loca))
       use_short_loca = max_offset < 0x1FFFF;
 
-    if (!use_short_loca) {
-      for (unsigned i = 0; i < num_glyphs; i++)
-        padded_offsets[i] = glyphs[i].length ();
+    if (!use_short_loca)
+    {
+      padded_offsets.resize (0);
+      for (auto &g : glyphs)
+	padded_offsets.push (g.length ());
     }
 
-    bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan);
+    auto *glyf_prime = c->serializer->start_embed <glyf> ();
+    bool result = glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
     if (c->plan->normalized_coords && !c->plan->pinned_at_default)
       _free_compiled_subset_glyphs (glyphs);
 
-    if (!result) return false;
+    if (unlikely (!c->serializer->check_success (glyf_impl::_add_loca_and_head (c,
+						 padded_offsets.iter (),
+						 use_short_loca))))
+      return_trace (false);
 
-    if (unlikely (c->serializer->in_error ())) return_trace (false);
-
-    return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
-									       padded_offsets.iter (),
-									       use_short_loca)));
+    return result;
   }
 
   bool
   _populate_subset_glyphs (const hb_subset_plan_t   *plan,
 			   hb_font_t                *font,
-			   hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
+			   hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const;
 
   hb_font_t *
   _create_font_for_instancing (const hb_subset_plan_t *plan) const;
@@ -152,8 +149,8 @@
 
   void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs) const
   {
-    for (unsigned i = 0; i < glyphs.length; i++)
-      glyphs[i].free_compiled_bytes ();
+    for (auto &g : glyphs)
+      g.free_compiled_bytes ();
   }
 
   protected:
@@ -222,13 +219,14 @@
     if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only)))
       return false;
 
+    unsigned count = all_points.length;
+    assert (count >= glyf_impl::PHANTOM_COUNT);
+    count -= glyf_impl::PHANTOM_COUNT;
+
     if (consumer.is_consuming_contour_points ())
     {
-      unsigned count = all_points.length;
-      assert (count >= glyf_impl::PHANTOM_COUNT);
-      count -= glyf_impl::PHANTOM_COUNT;
-      for (unsigned point_index = 0; point_index < count; point_index++)
-	consumer.consume_point (all_points[point_index]);
+      for (auto &point : all_points.as_array ().sub_array (0, count))
+	consumer.consume_point (point);
       consumer.points_end ();
     }
 
@@ -236,7 +234,7 @@
     contour_point_t *phantoms = consumer.get_phantoms_sink ();
     if (phantoms)
       for (unsigned i = 0; i < glyf_impl::PHANTOM_COUNT; ++i)
-	phantoms[i] = all_points[all_points.length - glyf_impl::PHANTOM_COUNT + i];
+	phantoms[i] = all_points.arrayZ[count + i];
 
     return true;
   }
@@ -299,6 +297,7 @@
       if (extents) bounds = contour_bounds_t ();
     }
 
+    HB_ALWAYS_INLINE
     void consume_point (const contour_point_t &point) { bounds.add (point); }
     void points_end () { bounds.get_extents (font, extents, scaled); }
 
@@ -431,16 +430,17 @@
 			       hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
 {
   OT::glyf_accelerator_t glyf (plan->source);
-  unsigned num_glyphs = plan->num_output_glyphs ();
-  if (!glyphs.resize (num_glyphs)) return false;
+  if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false;
 
-  for (auto p : plan->glyph_map->iter ())
+  for (const auto &pair : plan->new_to_old_gid_list)
   {
-    unsigned new_gid = p.second;
-    glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid];
-    subset_glyph.old_gid = p.first;
+    hb_codepoint_t new_gid = pair.first;
+    hb_codepoint_t old_gid = pair.second;
+    glyf_impl::SubsetGlyph *p = glyphs.push ();
+    glyf_impl::SubsetGlyph& subset_glyph = *p;
+    subset_glyph.old_gid = old_gid;
 
-    if (unlikely (new_gid == 0 &&
+    if (unlikely (old_gid == 0 && new_gid == 0 &&
                   !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
                   !plan->normalized_coords)
       subset_glyph.source_glyph = glyf_impl::Glyph ();
@@ -487,7 +487,7 @@
   {
     hb_variation_t var;
     var.tag = _.first;
-    var.value = _.second;
+    var.value = _.second.middle;
     vars.push (var);
   }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -21,11 +21,11 @@
     operator bool () const { return has_data; }
 
     bool has_data = false;
-    float x = 0.;
-    float y = 0.;
+    float x;
+    float y;
 
-    optional_point_t lerp (optional_point_t p, float t)
-    { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
+    optional_point_t mid (optional_point_t p)
+    { return optional_point_t ((x + p.x) * 0.5f, (y + p.y) * 0.5f); }
   } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2;
 
   path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) :
@@ -37,6 +37,7 @@
      * https://stackoverflow.com/a/20772557
      *
      * Cubic support added. */
+  HB_ALWAYS_INLINE
   void consume_point (const contour_point_t &point)
   {
     bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
@@ -46,7 +47,7 @@
     bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
 #endif
     optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
-    if (!first_oncurve)
+    if (unlikely (!first_oncurve))
     {
       if (is_on_curve)
       {
@@ -62,7 +63,7 @@
 	}
 	else if (first_offcurve)
 	{
-	  optional_point_t mid = first_offcurve.lerp (p, .5f);
+	  optional_point_t mid = first_offcurve.mid (p);
 	  first_oncurve = mid;
 	  last_offcurve = p;
 	  draw_session->move_to (mid.x, mid.y);
@@ -98,7 +99,7 @@
 	  }
 	  else
 	  {
-	    optional_point_t mid = last_offcurve.lerp (p, .5f);
+	    optional_point_t mid = last_offcurve.mid (p);
 
 	    if (is_cubic)
 	    {
@@ -123,13 +124,13 @@
       }
     }
 
-    if (point.is_end_point)
+    if (unlikely (point.is_end_point))
     {
       if (first_offcurve && last_offcurve)
       {
-	optional_point_t mid = last_offcurve.lerp (first_offcurve2 ?
-						   first_offcurve2 :
-						   first_offcurve, .5f);
+	optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
+						  first_offcurve2 :
+						  first_offcurve);
 	if (last_offcurve2)
 	  draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
 				  last_offcurve.x, last_offcurve.y,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -359,7 +359,7 @@
       record.nameID = ids.name_id;
       record.length = 0; // handled in NameRecord copy()
       record.offset = 0;
-      memcpy (name_records, &record, NameRecord::static_size);
+      hb_memcpy (name_records, &record, NameRecord::static_size);
       name_records++;
     }
 #endif
@@ -384,11 +384,8 @@
 
   bool subset (hb_subset_context_t *c) const
   {
-    TRACE_SUBSET (this);
+    auto *name_prime = c->serializer->start_embed<name> ();
 
-    name *name_prime = c->serializer->start_embed<name> ();
-    if (unlikely (!name_prime)) return_trace (false);
-
 #ifdef HB_EXPERIMENTAL_API
     const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides =
         &c->plan->name_table_overrides;
@@ -436,7 +433,7 @@
     if (!name_table_overrides->is_empty ())
     {
       if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population (), true)))
-        return_trace (false);
+        return false;
       for (const auto& record_ids : name_table_overrides->keys ())
       {
         if (name_table_overrides->get (record_ids).length == 0)
@@ -448,13 +445,13 @@
     }
 #endif
 
-    return (name_prime->serialize (c->serializer, it,
-                                   std::addressof (this + stringOffset)
+    return name_prime->serialize (c->serializer, it,
+				  std::addressof (this + stringOffset)
 #ifdef HB_EXPERIMENTAL_API
-                                   , insert_name_records
-                                   , name_table_overrides
+				  , insert_name_records
+				  , name_table_overrides
 #endif
-                                   ));
+				  );
   }
 
   bool sanitize_records (hb_sanitize_context_t *c) const

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py	2023-07-09 05:55:34 UTC (rev 67588)
@@ -22,6 +22,7 @@
 """hb_shape_justify
 hb_subset_repack_or_fail
 hb_subset_input_override_name_table
+hb_subset_input_set_axis_range
 """.splitlines ()
 	symbols = [x for x in symbols if x not in experimental_symbols]
 symbols = "\n".join (symbols)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/classdef-graph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/classdef-graph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/classdef-graph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -94,7 +94,13 @@
     }
 
     hb_bytes_t class_def_copy = serializer.copy_bytes ();
-    c.add_buffer ((char *) class_def_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
+    if (!class_def_copy.arrayZ) return false;
+    // Give ownership to the context, it will cleanup the buffer.
+    if (!c.add_buffer ((char *) class_def_copy.arrayZ))
+    {
+      hb_free ((char *) class_def_copy.arrayZ);
+      return false;
+    }
 
     auto& obj = c.graph.vertices_[dest_obj].obj;
     obj.head = (char *) class_def_copy.arrayZ;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/coverage-graph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/coverage-graph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/coverage-graph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -118,7 +118,13 @@
     }
 
     hb_bytes_t coverage_copy = serializer.copy_bytes ();
-    c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
+    if (!coverage_copy.arrayZ) return false;
+    // Give ownership to the context, it will cleanup the buffer.
+    if (!c.add_buffer ((char *) coverage_copy.arrayZ))
+    {
+      hb_free ((char *) coverage_copy.arrayZ);
+      return false;
+    }
 
     auto& obj = c.graph.vertices_[dest_obj].obj;
     obj.head = (char *) coverage_copy.arrayZ;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -359,7 +359,6 @@
 
   ~graph_t ()
   {
-    vertices_.fini ();
     for (char* b : buffers)
       hb_free (b);
   }
@@ -401,9 +400,10 @@
     return vertices_[i].obj;
   }
 
-  void add_buffer (char* buffer)
+  bool add_buffer (char* buffer)
   {
     buffers.push (buffer);
+    return !buffers.in_error ();
   }
 
   /*
@@ -732,8 +732,7 @@
     remap_obj_indices (index_map, parents.iter (), true);
 
     // Update roots set with new indices as needed.
-    uint32_t next = HB_SET_VALUE_INVALID;
-    while (roots.next (&next))
+    for (auto next : roots)
     {
       const uint32_t *v;
       if (index_map.has (next, &v))

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -52,7 +52,11 @@
   if (!buffer)
     return -1;
 
-  add_buffer (buffer);
+  if (!add_buffer (buffer)) {
+    // Allocation did not get stored for freeing later.
+    hb_free (buffer);
+    return -1;
+  }
 
   return graph.new_node (buffer, buffer + size);
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -47,9 +47,9 @@
 
   HB_INTERNAL unsigned create_node (unsigned size);
 
-  void add_buffer (char* buffer)
+  bool add_buffer (char* buffer)
   {
-    graph.add_buffer (buffer);
+    return graph.add_buffer (buffer);
   }
 
  private:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -166,7 +166,7 @@
     }
 
     if (all_new_subtables) {
-      add_sub_tables (c, this_index, type, all_new_subtables);
+      return add_sub_tables (c, this_index, type, all_new_subtables);
     }
 
     return true;
@@ -184,7 +184,7 @@
     return sub_table->split_subtables (c, parent_idx, objidx);
   }
 
-  void add_sub_tables (gsubgpos_graph_context_t& c,
+  bool add_sub_tables (gsubgpos_graph_context_t& c,
                        unsigned this_index,
                        unsigned type,
                        hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids)
@@ -200,7 +200,12 @@
     size_t new_size = v.table_size ()
                       + new_subtable_count * OT::Offset16::static_size;
     char* buffer = (char*) hb_calloc (1, new_size);
-    c.add_buffer (buffer);
+    if (!buffer) return false;
+    if (!c.add_buffer (buffer))
+    {
+      hb_free (buffer);
+     return false;
+    }
     hb_memcpy (buffer, v.obj.head, v.table_size());
 
     v.obj.head = buffer;
@@ -239,6 +244,7 @@
     // The head location of the lookup has changed, invalidating the lookups map entry
     // in the context. Update the map.
     c.lookups.set (this_index, new_lookup);
+    return true;
   }
 
   void fix_existing_subtable_links (gsubgpos_graph_context_t& c,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -215,7 +215,7 @@
     auto gid_and_class =
         + coverage->iter ()
         | hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
-          return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1->get_class (gid));
+          return hb_codepoint_pair_t (gid, class_def_1->get_class (gid));
         })
         ;
     class_def_size_estimator_t estimator (gid_and_class);
@@ -386,14 +386,14 @@
     auto klass_map =
     + coverage_table->iter ()
     | hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
-      return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1_table->get_class (gid));
+      return hb_codepoint_pair_t (gid, class_def_1_table->get_class (gid));
     })
     | hb_filter ([&] (hb_codepoint_t klass) {
       return klass >= start && klass < end;
     }, hb_second)
-    | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, hb_codepoint_t> gid_and_class) {
+    | hb_map_retains_sorting ([&] (hb_codepoint_pair_t gid_and_class) {
       // Classes must be from 0...N so subtract start
-      return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid_and_class.first, gid_and_class.second - start);
+      return hb_codepoint_pair_t (gid_and_class.first, gid_and_class.second - start);
     })
     ;
 
@@ -519,7 +519,7 @@
     auto klass_map =
     + coverage.table->iter ()
     | hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
-      return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1.table->get_class (gid));
+      return hb_codepoint_pair_t (gid, class_def_1.table->get_class (gid));
     })
     | hb_filter ([&] (hb_codepoint_t klass) {
       return klass < count;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/serialize.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/serialize.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/serialize.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -226,6 +226,9 @@
 {
   hb_vector_t<char> buffer;
   size_t size = graph.total_size_in_bytes ();
+
+  if (!size) return hb_blob_get_empty ();
+
   if (!buffer.alloc (size)) {
     DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
     return nullptr;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -27,7 +27,7 @@
 #include "gsubgpos-context.hh"
 #include "classdef-graph.hh"
 
-typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> gid_and_class_t;
+typedef hb_codepoint_pair_t gid_and_class_t;
 typedef hb_vector_t<gid_and_class_t> gid_and_class_list_t;
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-config.cmake.in
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-config.cmake.in	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-config.cmake.in	2023-07-09 05:55:34 UTC (rev 67588)
@@ -13,12 +13,18 @@
 unset(_harfbuzz_version_info)
 
 if ("@default_library@" MATCHES "static")
+  set(_harfbuzz_lib_prefix "lib")
   set(_harfbuzz_lib_suffix ".a")
 else ()
   if (APPLE)
+    set(_harfbuzz_lib_prefix "${CMAKE_SHARED_LIBRARY_PREFIX}")
     set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}")
   elseif (UNIX)
+    set(_harfbuzz_lib_prefix "${CMAKE_SHARED_LIBRARY_PREFIX}")
     set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}")
+  elseif (WIN32)
+    set(_harfbuzz_lib_prefix "${CMAKE_IMPORT_LIBRARY_PREFIX}")
+    set(_harfbuzz_lib_suffix "${CMAKE_IMPORT_LIBRARY_SUFFIX}")
   else ()
     # Unsupported.
     set(harfbuzz_FOUND 0)
@@ -29,19 +35,19 @@
 add_library(harfbuzz::harfbuzz SHARED IMPORTED)
 set_target_properties(harfbuzz::harfbuzz PROPERTIES
   INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
-  IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
+  IMPORTED_LOCATION "${_harfbuzz_libdir}/${_harfbuzz_lib_prefix}harfbuzz${_harfbuzz_lib_suffix}")
 
 add_library(harfbuzz::icu SHARED IMPORTED)
 set_target_properties(harfbuzz::icu PROPERTIES
   INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
   INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
-  IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}")
+  IMPORTED_LOCATION "${_harfbuzz_libdir}/${_harfbuzz_lib_prefix}harfbuzz-icu${_harfbuzz_lib_suffix}")
 
 add_library(harfbuzz::subset SHARED IMPORTED)
 set_target_properties(harfbuzz::subset PROPERTIES
   INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
   INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
-  IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}")
+  IMPORTED_LOCATION "${_harfbuzz_libdir}/${_harfbuzz_lib_prefix}harfbuzz-subset${_harfbuzz_lib_suffix}")
 
 # Only add the gobject library if it was built.
 set(_harfbuzz_have_gobject "@have_gobject@")
@@ -50,10 +56,11 @@
   set_target_properties(harfbuzz::gobject PROPERTIES
     INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
     INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
-    IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}")
+    IMPORTED_LOCATION "${_harfbuzz_libdir}/${_harfbuzz_lib_prefix}harfbuzz-gobject${_harfbuzz_lib_suffix}")
 endif ()
 
 # Clean out variables we used in our scope.
+unset(_harfbuzz_lib_prefix)
 unset(_harfbuzz_lib_suffix)
 unset(_harfbuzz_current)
 unset(_harfbuzz_revision)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -58,3 +58,5 @@
 #include "hb-ucd.cc"
 #include "hb-unicode.cc"
 #include "hb-uniscribe.cc"
+#include "hb-wasm-api.cc"
+#include "hb-wasm-shape.cc"

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -87,6 +87,19 @@
 static inline constexpr uint32_t hb_uint32_swap (uint32_t v)
 { return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
 
+#ifndef HB_FAST_INT_ACCESS
+#if defined(__OPTIMIZE__) && \
+    defined(__BYTE_ORDER) && \
+    (__BYTE_ORDER == __BIG_ENDIAN || \
+     (__BYTE_ORDER == __LITTLE_ENDIAN && \
+      hb_has_builtin(__builtin_bswap16) && \
+      hb_has_builtin(__builtin_bswap32)))
+#define HB_FAST_INT_ACCESS 1
+#else
+#define HB_FAST_INT_ACCESS 0
+#endif
+#endif
+
 template <typename Type, int Bytes = sizeof (Type)>
 struct BEInt;
 template <typename Type>
@@ -101,22 +114,26 @@
 template <typename Type>
 struct BEInt<Type, 2>
 {
+  struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
+
   public:
   BEInt () = default;
-  constexpr BEInt (Type V) : v {uint8_t ((V >>  8) & 0xFF),
-			        uint8_t ((V      ) & 0xFF)} {}
 
-  struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
-  constexpr operator Type () const
-  {
-#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
-    defined(__BYTE_ORDER) && \
-    (__BYTE_ORDER == __BIG_ENDIAN || \
-     (__BYTE_ORDER == __LITTLE_ENDIAN && \
-      hb_has_builtin(__builtin_bswap16)))
-    /* Spoon-feed the compiler a big-endian integer with alignment 1.
-     * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+  BEInt (Type V)
+#if HB_FAST_INT_ACCESS
 #if __BYTE_ORDER == __LITTLE_ENDIAN
+  { ((packed_uint16_t *) v)->v = __builtin_bswap16 (V); }
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+  { ((packed_uint16_t *) v)->v = V; }
+#endif
+#else
+    : v {uint8_t ((V >>  8) & 0xFF),
+	 uint8_t ((V      ) & 0xFF)} {}
+#endif
+
+  constexpr operator Type () const {
+#if HB_FAST_INT_ACCESS
+#if __BYTE_ORDER == __LITTLE_ENDIAN
     return __builtin_bswap16 (((packed_uint16_t *) v)->v);
 #else /* __BYTE_ORDER == __BIG_ENDIAN */
     return ((packed_uint16_t *) v)->v;
@@ -146,22 +163,27 @@
 template <typename Type>
 struct BEInt<Type, 4>
 {
+  struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+
   public:
   BEInt () = default;
-  constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF),
-			        uint8_t ((V >> 16) & 0xFF),
-			        uint8_t ((V >>  8) & 0xFF),
-			        uint8_t ((V      ) & 0xFF)} {}
 
-  struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+  BEInt (Type V)
+#if HB_FAST_INT_ACCESS
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  { ((packed_uint32_t *) v)->v = __builtin_bswap32 (V); }
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+  { ((packed_uint32_t *) v)->v = V; }
+#endif
+#else
+    : v {uint8_t ((V >> 24) & 0xFF),
+	 uint8_t ((V >> 16) & 0xFF),
+	 uint8_t ((V >>  8) & 0xFF),
+	 uint8_t ((V      ) & 0xFF)} {}
+#endif
+
   constexpr operator Type () const {
-#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
-    defined(__BYTE_ORDER) && \
-    (__BYTE_ORDER == __BIG_ENDIAN || \
-     (__BYTE_ORDER == __LITTLE_ENDIAN && \
-      hb_has_builtin(__builtin_bswap32)))
-    /* Spoon-feed the compiler a big-endian integer with alignment 1.
-     * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+#if HB_FAST_INT_ACCESS
 #if __BYTE_ORDER == __LITTLE_ENDIAN
     return __builtin_bswap32 (((packed_uint32_t *) v)->v);
 #else /* __BYTE_ORDER == __BIG_ENDIAN */
@@ -231,13 +253,120 @@
 }
 HB_FUNCOBJ (hb_bool);
 
+
+/* The MIT License
+
+   Copyright (C) 2012 Zilong Tan (eric.zltan at gmail.com)
+
+   Permission is hereby granted, free of charge, to any person
+   obtaining a copy of this software and associated documentation
+   files (the "Software"), to deal in the Software without
+   restriction, including without limitation the rights to use, copy,
+   modify, merge, publish, distribute, sublicense, and/or sell copies
+   of the Software, and to permit persons to whom the Software is
+   furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+   SOFTWARE.
+*/
+
+
+// Compression function for Merkle-Damgard construction.
+// This function is generated using the framework provided.
+#define mix(h) (					\
+			(h) ^= (h) >> 23,		\
+			(h) *= 0x2127599bf4325c37ULL,	\
+			(h) ^= (h) >> 47)
+
+static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
+{
+	struct __attribute__((packed)) packed_uint64_t { uint64_t v; };
+	const uint64_t    m = 0x880355f21e6d1965ULL;
+	const packed_uint64_t *pos = (const packed_uint64_t *)buf;
+	const packed_uint64_t *end = pos + (len / 8);
+	const unsigned char *pos2;
+	uint64_t h = seed ^ (len * m);
+	uint64_t v;
+
+#ifndef HB_OPTIMIZE_SIZE
+	if (((uintptr_t) pos & 7) == 0)
+	{
+	  while (pos != end)
+	  {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+	    v  = * (const uint64_t *) (pos++);
+#pragma GCC diagnostic pop
+	    h ^= mix(v);
+	    h *= m;
+	  }
+	}
+	else
+#endif
+	{
+	  while (pos != end)
+	  {
+	    v  = pos++->v;
+	    h ^= mix(v);
+	    h *= m;
+	  }
+	}
+
+	pos2 = (const unsigned char*)pos;
+	v = 0;
+
+	switch (len & 7) {
+	case 7: v ^= (uint64_t)pos2[6] << 48; HB_FALLTHROUGH;
+	case 6: v ^= (uint64_t)pos2[5] << 40; HB_FALLTHROUGH;
+	case 5: v ^= (uint64_t)pos2[4] << 32; HB_FALLTHROUGH;
+	case 4: v ^= (uint64_t)pos2[3] << 24; HB_FALLTHROUGH;
+	case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH;
+	case 2: v ^= (uint64_t)pos2[1] <<  8; HB_FALLTHROUGH;
+	case 1: v ^= (uint64_t)pos2[0];
+		h ^= mix(v);
+		h *= m;
+	}
+
+	return mix(h);
+}
+
+static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
+{
+	// the following trick converts the 64-bit hashcode to Fermat
+	// residue, which shall retain information from both the higher
+	// and lower parts of hashcode.
+        uint64_t h = fasthash64(buf, len, seed);
+	return h - (h >> 32);
+}
+
 struct
 {
   private:
 
   template <typename T> constexpr auto
-  impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
+  impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
 
+  // Horrible: std:hash() of integers seems to be identity in gcc / clang?!
+  // https://github.com/harfbuzz/harfbuzz/pull/4228
+  //
+  // For performance characteristics see:
+  // https://github.com/harfbuzz/harfbuzz/pull/4228#issuecomment-1565079537
+  template <typename T,
+	    hb_enable_if (std::is_integral<T>::value && sizeof (T) <= sizeof (uint32_t))> constexpr auto
+  impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, v * 2654435761u /* Knuh's multiplicative hash */)
+  template <typename T,
+	    hb_enable_if (std::is_integral<T>::value && sizeof (T) > sizeof (uint32_t))> constexpr auto
+  impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (v ^ (v >> 32)) * 2654435761u /* Knuth's multiplicative hash */)
+
   template <typename T> constexpr auto
   impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
 
@@ -551,6 +680,8 @@
 template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
 hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
 
+typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
+
 struct
 {
   template <typename Pair> constexpr typename Pair::first_t
@@ -853,7 +984,7 @@
 hb_memset (void *s, int c, unsigned int n)
 {
   /* It's illegal to pass NULL to memset(), even if n is zero. */
-  if (unlikely (!n)) return 0;
+  if (unlikely (!n)) return s;
   return memset (s, c, n);
 }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -75,11 +75,25 @@
    */
   typedef Type& __item_t__;
   static constexpr bool is_random_access_iterator = true;
+  static constexpr bool has_fast_len = true;
+  Type& __item__ () const
+  {
+    if (unlikely (!length)) return CrapOrNull (Type);
+    return *arrayZ;
+  }
   Type& __item_at__ (unsigned i) const
   {
     if (unlikely (i >= length)) return CrapOrNull (Type);
     return arrayZ[i];
   }
+  void __next__ ()
+  {
+    if (unlikely (!length))
+      return;
+    length--;
+    backwards_length++;
+    arrayZ++;
+  }
   void __forward__ (unsigned n)
   {
     if (unlikely (n > length))
@@ -88,6 +102,14 @@
     backwards_length += n;
     arrayZ += n;
   }
+  void __prev__ ()
+  {
+    if (unlikely (!backwards_length))
+      return;
+    length++;
+    backwards_length--;
+    arrayZ--;
+  }
   void __rewind__ (unsigned n)
   {
     if (unlikely (n > backwards_length))
@@ -123,6 +145,7 @@
   uint32_t hash () const
   {
     // FNV-1a hash function
+    // https://github.com/harfbuzz/harfbuzz/pull/4228
     uint32_t current = /*cbf29ce4*/0x84222325;
     for (auto &v : *this)
     {
@@ -326,6 +349,7 @@
   HB_ITER_USING (iter_base_t);
   static constexpr bool is_random_access_iterator = true;
   static constexpr bool is_sorted_iterator = true;
+  static constexpr bool has_fast_len = true;
 
   hb_sorted_array_t () = default;
   hb_sorted_array_t (const hb_sorted_array_t&) = default;
@@ -453,57 +477,23 @@
 
 /* Specialize hash() for byte arrays. */
 
+#ifndef HB_OPTIMIZE_SIZE_MORE
 template <>
 inline uint32_t hb_array_t<const char>::hash () const
 {
-  // FNV-1a hash function
-  uint32_t current = /*cbf29ce4*/0x84222325;
-  unsigned i = 0;
-
-#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
-    ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
-  struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
-  for (; i + 4 <= this->length; i += 4)
-  {
-    current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v);
-    current = current * 16777619;
-  }
-#endif
-
-  for (; i < this->length; i++)
-  {
-    current = current ^ hb_hash (this->arrayZ[i]);
-    current = current * 16777619;
-  }
-  return current;
+  // https://github.com/harfbuzz/harfbuzz/pull/4228
+  return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */);
 }
 
 template <>
 inline uint32_t hb_array_t<const unsigned char>::hash () const
 {
-  // FNV-1a hash function
-  uint32_t current = /*cbf29ce4*/0x84222325;
-  unsigned i = 0;
-
-#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
-    ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
-  struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
-  for (; i + 4 <= this->length; i += 4)
-  {
-    current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v);
-    current = current * 16777619;
-  }
+  // https://github.com/harfbuzz/harfbuzz/pull/4228
+  return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */);
+}
 #endif
 
-  for (; i < this->length; i++)
-  {
-    current = current ^ hb_hash (this->arrayZ[i]);
-    current = current * 16777619;
-  }
-  return current;
-}
 
-
 typedef hb_array_t<const char> hb_bytes_t;
 typedef hb_array_t<const unsigned char> hb_ubytes_t;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -204,6 +204,7 @@
 
   hb_atomic_ptr_t () = default;
   constexpr hb_atomic_ptr_t (T* v) : v (v) {}
+  hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete;
 
   void init (T* v_ = nullptr) { set_relaxed (v_); }
   void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -39,10 +39,10 @@
     back_map.reset ();
   }
 
-  void resize (unsigned pop)
+  void alloc (unsigned pop)
   {
-    forw_map.resize (pop);
-    back_map.resize (pop);
+    forw_map.alloc (pop);
+    back_map.alloc (pop);
   }
 
   bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
@@ -83,7 +83,6 @@
 
   unsigned int get_population () const { return forw_map.get_population (); }
 
-
   protected:
   hb_map_t  forw_map;
   hb_map_t  back_map;
@@ -95,8 +94,30 @@
 };
 
 /* Inremental bimap: only lhs is given, rhs is incrementally assigned */
-struct hb_inc_bimap_t : hb_bimap_t
+struct hb_inc_bimap_t
 {
+  bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
+
+  unsigned int get_population () const { return forw_map.get_population (); }
+
+  void reset ()
+  {
+    forw_map.reset ();
+    back_map.reset ();
+  }
+
+  void alloc (unsigned pop)
+  {
+    forw_map.alloc (pop);
+    back_map.alloc (pop);
+  }
+
+  void clear ()
+  {
+    forw_map.clear ();
+    back_map.resize (0);
+  }
+
   /* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
    * Return the rhs value as the result.
    */
@@ -105,25 +126,34 @@
     hb_codepoint_t  rhs = forw_map[lhs];
     if (rhs == HB_MAP_VALUE_INVALID)
     {
-      rhs = next_value++;
-      set (lhs, rhs);
+      rhs = back_map.length;
+      forw_map.set (lhs, rhs);
+      back_map.push (lhs);
     }
     return rhs;
   }
 
   hb_codepoint_t skip ()
-  { return next_value++; }
+  {
+    hb_codepoint_t start = back_map.length;
+    back_map.push (HB_MAP_VALUE_INVALID);
+    return start;
+  }
 
   hb_codepoint_t skip (unsigned count)
-  { return next_value += count; }
+  {
+    hb_codepoint_t start = back_map.length;
+    for (unsigned i = 0; i < count; i++)
+      back_map.push (HB_MAP_VALUE_INVALID);
+    return start;
+  }
 
   hb_codepoint_t get_next_value () const
-  { return next_value; }
+  { return back_map.length; }
 
   void add_set (const hb_set_t *set)
   {
-    hb_codepoint_t i = HB_SET_VALUE_INVALID;
-    while (hb_set_next (set, &i)) add (i);
+    for (auto i : *set) add (i);
   }
 
   /* Create an identity map. */
@@ -130,7 +160,7 @@
   bool identity (unsigned int size)
   {
     clear ();
-    for (hb_codepoint_t i = 0; i < size; i++) set (i, i);
+    for (hb_codepoint_t i = 0; i < size; i++) add (i);
     return !in_error ();
   }
 
@@ -145,20 +175,30 @@
   {
     hb_codepoint_t  count = get_population ();
     hb_vector_t <hb_codepoint_t> work;
-    work.resize (count);
+    if (unlikely (!work.resize (count, false))) return;
 
     for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
-      work[rhs] = back_map[rhs];
+      work.arrayZ[rhs] = back_map[rhs];
 
     work.qsort (cmp_id);
 
     clear ();
     for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
-      set (work[rhs], rhs);
+      add (work.arrayZ[rhs]);
   }
 
+  hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
+  hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; }
+
+  hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
+  bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); }
+
   protected:
-  unsigned int next_value = 0;
+  hb_map_t forw_map;
+  hb_vector_t<hb_codepoint_t> back_map;
+
+  public:
+  auto keys () const HB_AUTO_RETURN (+ back_map.iter())
 };
 
 #endif /* HB_BIMAP_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -104,10 +104,7 @@
   }
   uint32_t hash () const
   {
-    return
-    + hb_iter (v)
-    | hb_reduce ([] (uint32_t h, const elt_t &_) { return h * 31 + hb_hash (_); }, (uint32_t) 0u)
-    ;
+    return hb_bytes_t ((const char *) &v, sizeof (v)).hash ();
   }
 
   void add (hb_codepoint_t g) { elt (g) |= mask (g); }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -136,7 +136,7 @@
   /* Sink interface. */
   hb_bit_set_invertible_t& operator << (hb_codepoint_t v)
   { add (v); return *this; }
-  hb_bit_set_invertible_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+  hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range)
   { add_range (range.first, range.second); return *this; }
 
   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
@@ -162,7 +162,7 @@
       auto it1 = iter ();
       auto it2 = other.iter ();
       return hb_all (+ hb_zip (it1, it2)
-		     | hb_map ([](hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) { return _.first == _.second; }));
+		     | hb_map ([](hb_codepoint_pair_t _) { return _.first == _.second; }));
     }
   }
 
@@ -345,6 +345,7 @@
   struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
   {
     static constexpr bool is_sorted_iterator = true;
+    static constexpr bool has_fast_len = true;
     iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t),
 	    bool init = true) : s (&s_), v (INVALID), l(0)
     {
@@ -363,7 +364,7 @@
     unsigned __len__ () const { return l; }
     iter_t end () const { return iter_t (*s, false); }
     bool operator != (const iter_t& o) const
-    { return s != o.s || v != o.v; }
+    { return v != o.v || s != o.s; }
 
     protected:
     const hb_bit_set_invertible_t *s;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -134,7 +134,11 @@
   {
     uint32_t h = 0;
     for (auto &map : page_map)
-      h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]);
+    {
+      auto &page = pages.arrayZ[map.index];
+      if (unlikely (page.is_empty ())) continue;
+      h = h * 31 + hb_hash (map.major) + hb_hash (page);
+    }
     return h;
   }
 
@@ -342,7 +346,7 @@
   /* Sink interface. */
   hb_bit_set_t& operator << (hb_codepoint_t v)
   { add (v); return *this; }
-  hb_bit_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+  hb_bit_set_t& operator << (const hb_codepoint_pair_t& range)
   { add_range (range.first, range.second); return *this; }
 
   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
@@ -862,6 +866,7 @@
   struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
   {
     static constexpr bool is_sorted_iterator = true;
+    static constexpr bool has_fast_len = true;
     iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t),
 	    bool init = true) : s (&s_), v (INVALID), l(0)
     {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -162,17 +162,11 @@
     hb_buffer_set_flags (fragment, flags);
 
     hb_buffer_append (fragment, text_buffer, text_start, text_end);
-    if (!hb_shape_full (font, fragment, features, num_features, shapers))
+    if (!hb_shape_full (font, fragment, features, num_features, shapers) ||
+	fragment->successful || fragment->shaping_failed)
     {
-      buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
       hb_buffer_destroy (reconstruction);
       hb_buffer_destroy (fragment);
-      return false;
-    }
-    else if (!fragment->successful || fragment->shaping_failed)
-    {
-      hb_buffer_destroy (reconstruction);
-      hb_buffer_destroy (fragment);
       return true;
     }
     hb_buffer_append (reconstruction, fragment, 0, -1);
@@ -185,15 +179,18 @@
   }
 
   bool ret = true;
-  hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
-  if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
+  if (likely (reconstruction->successful))
   {
-    buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed.");
-    ret = false;
+    hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+    if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
+    {
+      buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed.");
+      ret = false;
 
-    /* Return the reconstructed result instead so it can be inspected. */
-    hb_buffer_set_length (buffer, 0);
-    hb_buffer_append (buffer, reconstruction, 0, -1);
+      /* Return the reconstructed result instead so it can be inspected. */
+      hb_buffer_set_length (buffer, 0);
+      hb_buffer_append (buffer, reconstruction, 0, -1);
+    }
   }
 
   hb_buffer_destroy (reconstruction);
@@ -316,28 +313,13 @@
   /*
    * Shape the two fragment streams.
    */
-  if (!hb_shape_full (font, fragments[0], features, num_features, shapers))
-  {
-    buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
-    ret = false;
+  if (!hb_shape_full (font, fragments[0], features, num_features, shapers) ||
+      !fragments[0]->successful || fragments[0]->shaping_failed)
     goto out;
-  }
-  else if (!fragments[0]->successful || fragments[0]->shaping_failed)
-  {
-    ret = true;
+
+  if (!hb_shape_full (font, fragments[1], features, num_features, shapers) ||
+      !fragments[1]->successful || fragments[1]->shaping_failed)
     goto out;
-  }
-  if (!hb_shape_full (font, fragments[1], features, num_features, shapers))
-  {
-    buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
-    ret = false;
-    goto out;
-  }
-  else if (!fragments[1]->successful || fragments[1]->shaping_failed)
-  {
-    ret = true;
-    goto out;
-  }
 
   if (!forward)
   {
@@ -377,21 +359,23 @@
     hb_buffer_reverse (reconstruction);
   }
 
-  /*
-   * Diff results.
-   */
-  diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
-  if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
+  if (likely (reconstruction->successful))
   {
-    buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed.");
-    ret = false;
+    /*
+     * Diff results.
+     */
+    diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+    if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
+    {
+      buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed.");
+      ret = false;
 
-    /* Return the reconstructed result instead so it can be inspected. */
-    hb_buffer_set_length (buffer, 0);
-    hb_buffer_append (buffer, reconstruction, 0, -1);
+      /* Return the reconstructed result instead so it can be inspected. */
+      hb_buffer_set_length (buffer, 0);
+      hb_buffer_append (buffer, reconstruction, 0, -1);
+    }
   }
 
-
 out:
   hb_buffer_destroy (reconstruction);
   hb_buffer_destroy (fragments[0]);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -493,6 +493,13 @@
 
   HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size);
 
+  HB_NODISCARD bool resize (unsigned length)
+  {
+    assert (!have_output);
+    if (unlikely (!ensure (length))) return false;
+    len = length;
+    return true;
+  }
   HB_NODISCARD bool ensure (unsigned int size)
   { return likely (!size || size < allocated) ? true : enlarge (size); }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -62,14 +62,12 @@
   static_assert ((key_bits >= cache_bits), "");
   static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), "");
 
-  hb_cache_t () { init (); }
+  hb_cache_t () { clear (); }
 
-  void init () { clear (); }
-
   void clear ()
   {
-    for (unsigned i = 0; i < ARRAY_LENGTH (values); i++)
-      values[i] = -1;
+    for (auto &v : values)
+      v = -1;
   }
 
   bool get (unsigned int key, unsigned int *value) const

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -80,7 +80,7 @@
   if (r->offset + length > size)
     return CAIRO_STATUS_READ_ERROR;
 
-  memcpy (data, d + r->offset, length);
+  hb_memcpy (data, d + r->offset, length);
   r->offset += length;
 
   return CAIRO_STATUS_SUCCESS;
@@ -763,7 +763,7 @@
     }
 
     //assert (angles[0] + k * span <= 0 && 0 < angles[n_stops - 1] + k * span);
-    span = fabs (span);
+    span = fabsf (span);
 
     for (signed l = k; l < 1000; l++)
     {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -956,7 +956,7 @@
 
   if (clusters && *num_clusters && utf8)
   {
-    memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0]));
+    hb_memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0]));
     hb_bool_t backward = HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (buffer));
     *cluster_flags = backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : (cairo_text_cluster_flags_t) 0;
     unsigned int cluster = 0;

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -26,6 +26,8 @@
 #ifndef HB_CFF_INTERP_COMMON_HH
 #define HB_CFF_INTERP_COMMON_HH
 
+extern HB_INTERNAL const unsigned char *endchar_str;
+
 namespace CFF {
 
 using namespace OT;
@@ -336,8 +338,6 @@
   hb_ubytes_t       str;
 };
 
-using byte_str_array_t = hb_vector_t<hb_ubytes_t>;
-
 /* stack */
 template <typename ELEM, int LIMIT>
 struct cff_stack_t

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -883,14 +883,12 @@
 
     unsigned max_ops = HB_CFF_MAX_OPS;
     for (;;) {
-      if (unlikely (!--max_ops))
+      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
+      if (unlikely (SUPER::env.in_error () || !--max_ops))
       {
 	SUPER::env.set_error ();
-	break;
+	return false;
       }
-      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
-      if (unlikely (SUPER::env.in_error ()))
-	return false;
       if (SUPER::env.is_endchar ())
 	break;
     }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h	2023-07-09 05:55:34 UTC (rev 67588)
@@ -104,7 +104,17 @@
  *
  **/
 typedef uint32_t hb_codepoint_t;
+
 /**
+ * HB_CODEPOINT_INVALID:
+ *
+ * Unused #hb_codepoint_t value.
+ *
+ * Since: 8.0.0
+ */
+#define HB_CODEPOINT_INVALID ((hb_codepoint_t) -1)
+
+/**
  * hb_position_t:
  * 
  * Data type for holding a single coordinate value.

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -113,7 +113,6 @@
 /* Closure of options. */
 
 #ifdef HB_NO_BORING_EXPANSION
-#define HB_NO_AVAR2
 #define HB_NO_BEYOND_64K
 #define HB_NO_CUBIC_GLYF
 #define HB_NO_VAR_COMPOSITES

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -389,6 +389,10 @@
 #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
 #endif
 
+#ifndef HB_DEBUG_WASM
+#define HB_DEBUG_WASM (HB_DEBUG+0)
+#endif
+
 /*
  * With tracing.
  */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h	2023-07-09 05:55:34 UTC (rev 67588)
@@ -255,6 +255,52 @@
 hb_font_get_glyph_v_kerning (hb_font_t *font,
 			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
 
+
+/**
+ * hb_font_get_glyph_shape_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @draw_funcs: The draw functions to send the shape data to
+ * @draw_data: The data accompanying the draw functions
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
+ *
+ * Since: 4.0.0
+ * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead
+ **/
+typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
+						hb_codepoint_t glyph,
+						hb_draw_funcs_t *draw_funcs, void *draw_data,
+						void *user_data);
+
+/**
+ * hb_font_funcs_set_glyph_shape_func:
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets the implementation function for #hb_font_get_glyph_shape_func_t,
+ * which is the same as #hb_font_draw_glyph_func_t.
+ *
+ * Since: 4.0.0
+ * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead
+ **/
+HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func)
+HB_EXTERN void
+hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
+				    hb_font_get_glyph_shape_func_t func,
+				    void *user_data, hb_destroy_func_t destroy);
+
+HB_DEPRECATED_FOR (hb_font_draw_glyph)
+HB_EXTERN void
+hb_font_get_glyph_shape (hb_font_t *font,
+			 hb_codepoint_t glyph,
+			 hb_draw_funcs_t *dfuncs, void *draw_data);
+
+
 #endif
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -93,18 +93,22 @@
 		     !user_data ? nullptr : user_data->close_path); }
 
 
-  void move_to (void *draw_data, hb_draw_state_t &st,
-		float to_x, float to_y)
+  void
+  HB_ALWAYS_INLINE
+  move_to (void *draw_data, hb_draw_state_t &st,
+	   float to_x, float to_y)
   {
-    if (st.path_open) close_path (draw_data, st);
+    if (unlikely (st.path_open)) close_path (draw_data, st);
     st.current_x = to_x;
     st.current_y = to_y;
   }
 
-  void line_to (void *draw_data, hb_draw_state_t &st,
-		float to_x, float to_y)
+  void
+  HB_ALWAYS_INLINE
+  line_to (void *draw_data, hb_draw_state_t &st,
+	   float to_x, float to_y)
   {
-    if (!st.path_open) start_path (draw_data, st);
+    if (unlikely (!st.path_open)) start_path (draw_data, st);
     emit_line_to (draw_data, st, to_x, to_y);
     st.current_x = to_x;
     st.current_y = to_y;
@@ -111,11 +115,12 @@
   }
 
   void
+  HB_ALWAYS_INLINE
   quadratic_to (void *draw_data, hb_draw_state_t &st,
 		float control_x, float control_y,
 		float to_x, float to_y)
   {
-    if (!st.path_open) start_path (draw_data, st);
+    if (unlikely (!st.path_open)) start_path (draw_data, st);
     emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
     st.current_x = to_x;
     st.current_y = to_y;
@@ -122,12 +127,13 @@
   }
 
   void
+  HB_ALWAYS_INLINE
   cubic_to (void *draw_data, hb_draw_state_t &st,
 	    float control1_x, float control1_y,
 	    float control2_x, float control2_y,
 	    float to_x, float to_y)
   {
-    if (!st.path_open) start_path (draw_data, st);
+    if (unlikely (!st.path_open)) start_path (draw_data, st);
     emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
     st.current_x = to_x;
     st.current_y = to_y;
@@ -134,9 +140,10 @@
   }
 
   void
+  HB_ALWAYS_INLINE
   close_path (void *draw_data, hb_draw_state_t &st)
   {
-    if (st.path_open)
+    if (likely (st.path_open))
     {
       if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y))
 	emit_line_to (draw_data, st, st.path_start_x, st.path_start_y);
@@ -168,6 +175,7 @@
 
   ~hb_draw_session_t () { close_path (); }
 
+  HB_ALWAYS_INLINE
   void move_to (float to_x, float to_y)
   {
     if (likely (not_slanted))
@@ -177,6 +185,7 @@
       funcs->move_to (draw_data, st,
 		      to_x + to_y * slant, to_y);
   }
+  HB_ALWAYS_INLINE
   void line_to (float to_x, float to_y)
   {
     if (likely (not_slanted))
@@ -187,6 +196,7 @@
 		      to_x + to_y * slant, to_y);
   }
   void
+  HB_ALWAYS_INLINE
   quadratic_to (float control_x, float control_y,
 		float to_x, float to_y)
   {
@@ -200,6 +210,7 @@
 			   to_x + to_y * slant, to_y);
   }
   void
+  HB_ALWAYS_INLINE
   cubic_to (float control1_x, float control1_y,
 	    float control2_x, float control2_y,
 	    float to_x, float to_y)
@@ -215,6 +226,7 @@
 		       control2_x + control2_y * slant, control2_y,
 		       to_x + to_y * slant, to_y);
   }
+  HB_ALWAYS_INLINE
   void close_path ()
   {
     funcs->close_path (draw_data, st);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1389,6 +1389,7 @@
   return font->get_glyph_from_name (name, len, glyph);
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_font_get_glyph_shape:
  * @font: #hb_font_t to work upon
@@ -1410,6 +1411,7 @@
 {
   hb_font_draw_glyph (font, glyph, dfuncs, draw_data);
 }
+#endif
 
 /**
  * hb_font_draw_glyph:
@@ -2648,7 +2650,6 @@
       if (axes[axis_index].axisTag == tag)
 	design_coords[axis_index] = v;
   }
-  font->face->table.avar->map_coords (normalized, coords_length);
 
   hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized);
   _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
@@ -2720,8 +2721,6 @@
     if (axes[axis_index].axisTag == tag)
       design_coords[axis_index] = value;
 
-  font->face->table.avar->map_coords (normalized, coords_length);
-
   hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized);
   _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
 
@@ -3058,6 +3057,7 @@
 #endif
 
 
+#ifndef HB_DISABLE_DEPRECATED
 void
 hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t               *ffuncs,
                                    hb_font_get_glyph_shape_func_t  func,
@@ -3066,3 +3066,4 @@
 {
   hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
 }
+#endif

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h	2023-07-09 05:55:34 UTC (rev 67588)
@@ -486,25 +486,6 @@
 							 void *user_data);
 
 /**
- * hb_font_get_glyph_shape_func_t:
- * @font: #hb_font_t to work upon
- * @font_data: @font user data pointer
- * @glyph: The glyph ID to query
- * @draw_funcs: The draw functions to send the shape data to
- * @draw_data: The data accompanying the draw functions
- * @user_data: User data pointer passed by the caller
- *
- * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
- *
- * Since: 4.0.0
- * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead
- **/
-typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
-						hb_codepoint_t glyph,
-						hb_draw_funcs_t *draw_funcs, void *draw_data,
-						void *user_data);
-
-/**
  * hb_font_draw_glyph_func_t:
  * @font: #hb_font_t to work upon
  * @font_data: @font user data pointer
@@ -804,24 +785,6 @@
 					void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_font_funcs_set_glyph_shape_func:
- * @ffuncs: A font-function structure
- * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
- * @user_data: Data to pass to @func
- * @destroy: (nullable): The function to call when @user_data is not needed anymore
- *
- * Sets the implementation function for #hb_font_get_glyph_shape_func_t,
- * which is the same as #hb_font_draw_glyph_func_t.
- *
- * Since: 4.0.0
- * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
-				    hb_font_get_glyph_shape_func_t func,
-				    void *user_data, hb_destroy_func_t destroy);
-
-/**
  * hb_font_funcs_set_draw_glyph_func:
  * @ffuncs: A font-function structure
  * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
@@ -828,8 +791,7 @@
  * @user_data: Data to pass to @func
  * @destroy: (nullable): The function to call when @user_data is not needed anymore
  *
- * Sets the implementation function for #hb_font_draw_glyph_func_t,
- * which is the same as #hb_font_get_glyph_shape_func_t.
+ * Sets the implementation function for #hb_font_draw_glyph_func_t.
  *
  * Since: 7.0.0
  **/
@@ -935,11 +897,6 @@
 			     hb_codepoint_t *glyph);
 
 HB_EXTERN void
-hb_font_get_glyph_shape (hb_font_t *font,
-			 hb_codepoint_t glyph,
-			 hb_draw_funcs_t *dfuncs, void *draw_data);
-
-HB_EXTERN void
 hb_font_draw_glyph (hb_font_t *font,
                     hb_codepoint_t glyph,
                     hb_draw_funcs_t *dfuncs, void *draw_data);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -114,7 +114,7 @@
   ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
 
   ft_font->cached_serial = (unsigned) -1;
-  ft_font->advance_cache.init ();
+  new (&ft_font->advance_cache) hb_ft_advance_cache_t;
 
   return ft_font;
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -29,7 +29,7 @@
 #ifdef HAVE_GOBJECT
 
 
-/**
+/*
  * SECTION:hb-gobject
  * @title: hb-gobject
  * @short_description: GObject integration support

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -248,6 +248,21 @@
       gr_fref_set_feature_value (fref, features[i].value, feats);
   }
 
+  hb_direction_t direction = buffer->props.direction;
+  hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script);
+  /* TODO vertical:
+   * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
+   * Ogham fonts are supposed to be implemented BTT or not.  Need to research that
+   * first. */
+  if ((HB_DIRECTION_IS_HORIZONTAL (direction) &&
+       direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) ||
+      (HB_DIRECTION_IS_VERTICAL   (direction) &&
+       direction != HB_DIRECTION_TTB))
+  {
+    hb_buffer_reverse_clusters (buffer);
+    direction = HB_DIRECTION_REVERSE (direction);
+  }
+
   gr_segment *seg = nullptr;
   const gr_slot *is;
   unsigned int ci = 0, ic = 0;
@@ -261,21 +276,11 @@
   for (unsigned int i = 0; i < buffer->len; ++i)
     chars[i] = buffer->info[i].codepoint;
 
-  /* TODO ensure_native_direction. */
-
-  hb_tag_t script_tag[HB_OT_MAX_TAGS_PER_SCRIPT];
-  unsigned int count = HB_OT_MAX_TAGS_PER_SCRIPT;
-  hb_ot_tags_from_script_and_language (hb_buffer_get_script (buffer),
-				       HB_LANGUAGE_INVALID,
-				       &count,
-				       script_tag,
-				       nullptr, nullptr);
-
   seg = gr_make_seg (nullptr, grface,
-		     count ? script_tag[count - 1] : HB_OT_TAG_DEFAULT_SCRIPT,
+		     HB_TAG_NONE, // https://github.com/harfbuzz/harfbuzz/issues/3439#issuecomment-1442650148
 		     feats,
 		     gr_utf32, chars, buffer->len,
-		     2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
+		     2 | (direction == HB_DIRECTION_RTL ? 1 : 0));
 
   if (unlikely (!seg)) {
     if (feats) gr_featureval_destroy (feats);
@@ -327,7 +332,7 @@
   float yscale = (float) font->y_scale / upem;
   yscale *= yscale / xscale;
   unsigned int curradv = 0;
-  if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
+  if (HB_DIRECTION_IS_BACKWARD (direction))
   {
     curradv = gr_slot_origin_X(gr_seg_first_slot(seg)) * xscale;
     clusters[0].advance = gr_seg_advance_X(seg) * xscale - curradv;
@@ -356,7 +361,7 @@
       c->num_chars = before - c->base_char;
       c->base_glyph = ic;
       c->num_glyphs = 0;
-      if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
+      if (HB_DIRECTION_IS_BACKWARD (direction))
       {
 	c->advance = curradv - gr_slot_origin_X(is) * xscale;
 	curradv -= c->advance;
@@ -363,9 +368,10 @@
       }
       else
       {
+	auto origin_X = gr_slot_origin_X (is) * xscale;
 	c->advance = 0;
-	clusters[ci].advance += gr_slot_origin_X(is) * xscale - curradv;
-	curradv += clusters[ci].advance;
+	clusters[ci].advance += origin_X - curradv;
+	curradv = origin_X;
       }
       ci++;
     }
@@ -375,7 +381,7 @@
 	clusters[ci].num_chars = after + 1 - clusters[ci].base_char;
   }
 
-  if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
+  if (HB_DIRECTION_IS_BACKWARD (direction))
     clusters[ci].advance += curradv;
   else
     clusters[ci].advance += gr_seg_advance_X(seg) * xscale - curradv;
@@ -397,7 +403,7 @@
   unsigned int currclus = UINT_MAX;
   const hb_glyph_info_t *info = buffer->info;
   hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, nullptr);
-  if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
+  if (!HB_DIRECTION_IS_BACKWARD (direction))
   {
     curradvx = 0;
     for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is))

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -63,6 +63,7 @@
   static constexpr bool is_iterator = true;
   static constexpr bool is_random_access_iterator = false;
   static constexpr bool is_sorted_iterator = false;
+  static constexpr bool has_fast_len = false; // Should be checked in combination with is_random_access_iterator.
 
   private:
   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
@@ -393,7 +394,7 @@
 
   private:
   Iter it;
-  hb_reference_wrapper<Proj> f;
+  mutable hb_reference_wrapper<Proj> f;
 };
 
 template <typename Proj, hb_function_sortedness_t Sorted>
@@ -456,8 +457,8 @@
 
   private:
   Iter it;
-  hb_reference_wrapper<Pred> p;
-  hb_reference_wrapper<Proj> f;
+  mutable hb_reference_wrapper<Pred> p;
+  mutable hb_reference_wrapper<Proj> f;
 };
 template <typename Pred, typename Proj>
 struct hb_filter_iter_factory_t
@@ -841,7 +842,7 @@
   template <typename Iterable,
 	    hb_requires (hb_is_iterable (Iterable))>
   auto operator () (Iterable&& it, unsigned count) const HB_AUTO_RETURN
-  ( hb_zip (hb_range (count), it) | hb_map (hb_second) )
+  ( hb_zip (hb_range (count), it) | hb_map_retains_sorting (hb_second) )
 
   /* Specialization arrays. */
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -53,7 +53,7 @@
       return;
 
     buffer->unsafe_to_concat ();
-    OT::hb_ot_apply_context_t c (1, font, buffer);
+    OT::hb_ot_apply_context_t c (1, font, buffer, hb_blob_get_empty ());
     c.set_lookup_mask (kern_mask);
     c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
     auto &skippy_iter = c.iter_input;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-limits.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-limits.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-limits.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -89,6 +89,10 @@
 #endif
 
 
+#ifndef HB_GLYF_VAR_COMPOSITE_MAX_AXES
+#define HB_GLYF_VAR_COMPOSITE_MAX_AXES 4096
+#endif
+
 #ifndef HB_GLYF_MAX_POINTS
 #define HB_GLYF_MAX_POINTS 20000
 #endif

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -131,8 +131,12 @@
   unsigned int get_size () const { return (size - (array).min_size + (array).get_size ()); } \
   DEFINE_SIZE_ARRAY(size, array)
 
+#define DEFINE_SIZE_MAX(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) <= (size)) \
+  static constexpr unsigned max_size = (size)
 
 
+
 /*
  * Lazy loaders.
  *
@@ -180,6 +184,9 @@
 				 hb_lazy_loader_t<Returned,Subclass,Data,WheresData,Stored>
 				>::value Funcs;
 
+  hb_lazy_loader_t () = default;
+  hb_lazy_loader_t (const hb_lazy_loader_t &other) = delete;
+
   void init0 () {} /* Init, when memory is already set to 0. No-op for us. */
   void init ()  { instance.set_relaxed (nullptr); }
   void fini ()  { do_destroy (instance.get_acquire ()); init (); }
@@ -278,7 +285,11 @@
 template <typename T, unsigned int WheresFace>
 struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
 						hb_face_lazy_loader_t<T, WheresFace>,
-						hb_face_t, WheresFace> {};
+						hb_face_t, WheresFace>
+{
+  // Hack; have them here for API parity with hb_table_lazy_loader_t
+  hb_blob_t *get_blob () { return this->get ()->get_blob (); }
+};
 
 template <typename T, unsigned int WheresFace, bool core=false>
 struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
@@ -288,7 +299,7 @@
 {
   static hb_blob_t *create (hb_face_t *face)
   {
-    auto c = hb_sanitize_context_t ();
+    hb_sanitize_context_t c;
     if (core)
       c.set_num_glyphs (0); // So we don't recurse ad infinitum, or doesn't need num_glyphs
     return c.reference_table<T> (face);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h	2023-07-09 05:55:34 UTC (rev 67588)
@@ -44,7 +44,7 @@
  *
  * Since: 1.7.7
  */
-#define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1)
+#define HB_MAP_VALUE_INVALID HB_CODEPOINT_INVALID
 
 /**
  * hb_map_t:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -45,9 +45,9 @@
   hb_hashmap_t ()  { init (); }
   ~hb_hashmap_t () { fini (); }
 
-  hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (o.population); hb_copy (o, *this); }
+  hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { alloc (o.population); hb_copy (o, *this); }
   hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
-  hb_hashmap_t& operator= (const hb_hashmap_t& o)  { reset (); resize (o.population); hb_copy (o, *this); return *this; }
+  hb_hashmap_t& operator= (const hb_hashmap_t& o)  { reset (); alloc (o.population); hb_copy (o, *this); return *this; }
   hb_hashmap_t& operator= (hb_hashmap_t&& o)  { hb_swap (*this, o); return *this; }
 
   hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t ()
@@ -60,8 +60,8 @@
   hb_hashmap_t (const Iterable &o) : hb_hashmap_t ()
   {
     auto iter = hb_iter (o);
-    if (iter.is_random_access_iterator)
-      resize (hb_len (iter));
+    if (iter.is_random_access_iterator || iter.has_fast_len)
+      alloc (hb_len (iter));
     hb_copy (iter, *this);
   }
 
@@ -68,21 +68,20 @@
   struct item_t
   {
     K key;
+    uint32_t is_real_ : 1;
+    uint32_t is_used_ : 1;
     uint32_t hash : 30;
-    uint32_t is_used_ : 1;
-    uint32_t is_tombstone_ : 1;
     V value;
 
     item_t () : key (),
+		is_real_ (false), is_used_ (false),
 		hash (0),
-		is_used_ (false), is_tombstone_ (false),
 		value () {}
 
     bool is_used () const { return is_used_; }
     void set_used (bool is_used) { is_used_ = is_used; }
-    bool is_tombstone () const { return is_tombstone_; }
-    void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; }
-    bool is_real () const { return is_used_ && !is_tombstone_; }
+    void set_real (bool is_real) { is_real_ = is_real; }
+    bool is_real () const { return is_real_; }
 
     template <bool v = minus_one,
 	      hb_enable_if (v == false)>
@@ -98,10 +97,15 @@
     bool operator == (const K &o) const { return hb_deref (key) == hb_deref (o); }
     bool operator == (const item_t &o) const { return *this == o.key; }
     hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
-    hb_pair_t<const K &, const V &> get_pair_ref() const { return hb_pair_t<const K &, const V &> (key, value); }
+    hb_pair_t<const K &, V &> get_pair_ref() { return hb_pair_t<const K &, V &> (key, value); }
 
     uint32_t total_hash () const
     { return (hash * 31) + hb_hash (value); }
+
+    static constexpr bool is_trivial = std::is_trivially_constructible<K>::value &&
+				       std::is_trivially_destructible<K>::value &&
+				       std::is_trivially_constructible<V>::value &&
+				       std::is_trivially_destructible<V>::value;
   };
 
   hb_object_header_t header;
@@ -110,6 +114,7 @@
   unsigned int occupancy; /* Including tombstones. */
   unsigned int mask;
   unsigned int prime;
+  unsigned int max_chain_length;
   item_t *items;
 
   friend void swap (hb_hashmap_t& a, hb_hashmap_t& b)
@@ -123,6 +128,7 @@
     hb_swap (a.occupancy, b.occupancy);
     hb_swap (a.mask, b.mask);
     hb_swap (a.prime, b.prime);
+    hb_swap (a.max_chain_length, b.max_chain_length);
     hb_swap (a.items, b.items);
   }
   void init ()
@@ -133,6 +139,7 @@
     population = occupancy = 0;
     mask = 0;
     prime = 0;
+    max_chain_length = 0;
     items = nullptr;
   }
   void fini ()
@@ -139,10 +146,12 @@
   {
     hb_object_fini (this);
 
-    if (likely (items)) {
+    if (likely (items))
+    {
       unsigned size = mask + 1;
-      for (unsigned i = 0; i < size; i++)
-        items[i].~item_t ();
+      if (!item_t::is_trivial)
+	for (unsigned i = 0; i < size; i++)
+	  items[i].~item_t ();
       hb_free (items);
       items = nullptr;
     }
@@ -157,7 +166,7 @@
 
   bool in_error () const { return !successful; }
 
-  bool resize (unsigned new_population = 0)
+  bool alloc (unsigned new_population = 0)
   {
     if (unlikely (!successful)) return false;
 
@@ -171,8 +180,11 @@
       successful = false;
       return false;
     }
-    for (auto &_ : hb_iter (new_items, new_size))
-      new (&_) item_t ();
+    if (!item_t::is_trivial)
+      for (auto &_ : hb_iter (new_items, new_size))
+	new (&_) item_t ();
+    else
+      hb_memset (new_items, 0, (size_t) new_size * sizeof (item_t));
 
     unsigned int old_size = size ();
     item_t *old_items = items;
@@ -181,6 +193,7 @@
     population = occupancy = 0;
     mask = new_size - 1;
     prime = prime_for (power);
+    max_chain_length = power * 2;
     items = new_items;
 
     /* Insert back old items. */
@@ -192,7 +205,8 @@
 		       old_items[i].hash,
 		       std::move (old_items[i].value));
       }
-      old_items[i].~item_t ();
+      if (!item_t::is_trivial)
+	old_items[i].~item_t ();
     }
 
     hb_free (old_items);
@@ -201,20 +215,38 @@
   }
 
   template <typename KK, typename VV>
-  bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool is_delete=false)
+  bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool overwrite = true)
   {
     if (unlikely (!successful)) return false;
-    if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
-    item_t &item = item_for_hash (key, hash);
+    if (unlikely ((occupancy + occupancy / 2) >= mask && !alloc ())) return false;
 
-    if (is_delete && !(item == key))
-      return true; /* Trying to delete non-existent key. */
+    hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
+    unsigned int tombstone = (unsigned int) -1;
+    unsigned int i = hash % prime;
+    unsigned length = 0;
+    unsigned step = 0;
+    while (items[i].is_used ())
+    {
+      if ((std::is_integral<K>::value || items[i].hash == hash) &&
+	  items[i] == key)
+      {
+        if (!overwrite)
+	  return false;
+        else
+	  break;
+      }
+      if (!items[i].is_real () && tombstone == (unsigned) -1)
+        tombstone = i;
+      i = (i + ++step) & mask;
+      length++;
+    }
 
+    item_t &item = items[tombstone == (unsigned) -1 ? i : tombstone];
+
     if (item.is_used ())
     {
       occupancy--;
-      if (!item.is_tombstone ())
-	population--;
+      population -= item.is_real ();
     }
 
     item.key = std::forward<KK> (key);
@@ -221,52 +253,86 @@
     item.value = std::forward<VV> (value);
     item.hash = hash;
     item.set_used (true);
-    item.set_tombstone (is_delete);
+    item.set_real (true);
 
     occupancy++;
-    if (!is_delete)
-      population++;
+    population++;
 
+    if (unlikely (length > max_chain_length) && occupancy * 8 > mask)
+      alloc (mask - 8); // This ensures we jump to next larger size
+
     return true;
   }
 
   template <typename VV>
-  bool set (const K &key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
+  bool set (const K &key, VV&& value, bool overwrite = true) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value), overwrite); }
   template <typename VV>
-  bool set (K &&key, VV&& value) { return set_with_hash (std::move (key), hb_hash (key), std::forward<VV> (value)); }
+  bool set (K &&key, VV&& value, bool overwrite = true)
+  {
+    uint32_t hash = hb_hash (key);
+    return set_with_hash (std::move (key), hash, std::forward<VV> (value), overwrite);
+  }
 
   const V& get_with_hash (const K &key, uint32_t hash) const
   {
-    if (unlikely (!items)) return item_t::default_value ();
-    auto &item = item_for_hash (key, hash);
-    return item.is_real () && item == key ? item.value : item_t::default_value ();
+    if (!items) return item_t::default_value ();
+    auto *item = fetch_item (key, hb_hash (key));
+    if (item)
+      return item->value;
+    return item_t::default_value ();
   }
   const V& get (const K &key) const
   {
-    if (unlikely (!items)) return item_t::default_value ();
+    if (!items) return item_t::default_value ();
     return get_with_hash (key, hb_hash (key));
   }
 
-  void del (const K &key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
+  void del (const K &key)
+  {
+    if (!items) return;
+    auto *item = fetch_item (key, hb_hash (key));
+    if (item)
+    {
+      item->set_real (false);
+      population--;
+    }
+  }
 
   /* Has interface. */
   const V& operator [] (K k) const { return get (k); }
   template <typename VV=V>
-  bool has (K key, VV **vp = nullptr) const
+  bool has (const K &key, VV **vp = nullptr) const
   {
-    if (unlikely (!items))
-      return false;
-    auto &item = item_for_hash (key, hb_hash (key));
-    if (item.is_real () && item == key)
+    if (!items) return false;
+    auto *item = fetch_item (key, hb_hash (key));
+    if (item)
     {
-      if (vp) *vp = std::addressof (item.value);
+      if (vp) *vp = std::addressof (item->value);
       return true;
     }
-    else
-      return false;
+    return false;
   }
+  item_t *fetch_item (const K &key, uint32_t hash) const
+  {
+    hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
+    unsigned int i = hash % prime;
+    unsigned step = 0;
+    while (items[i].is_used ())
+    {
+      if ((std::is_integral<K>::value || items[i].hash == hash) &&
+	  items[i] == key)
+      {
+	if (items[i].is_real ())
+	  return &items[i];
+	else
+	  return nullptr;
+      }
+      i = (i + ++step) & mask;
+    }
+    return nullptr;
+  }
   /* Projection. */
-  V operator () (K k) const { return get (k); }
+  const V& operator () (K k) const { return get (k); }
 
   unsigned size () const { return mask ? mask + 1 : 0; }
 
@@ -393,24 +459,6 @@
   hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v)
   { set (std::move (v.first), std::move (v.second)); return *this; }
 
-  item_t& item_for_hash (const K &key, uint32_t hash) const
-  {
-    hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
-    unsigned int i = hash % prime;
-    unsigned int step = 0;
-    unsigned int tombstone = (unsigned) -1;
-    while (items[i].is_used ())
-    {
-      if ((hb_is_same (K, hb_codepoint_t) || items[i].hash == hash) &&
-	  items[i] == key)
-	return items[i];
-      if (tombstone == (unsigned) -1 && items[i].is_tombstone ())
-	tombstone = i;
-      i = (i + ++step) & mask;
-    }
-    return items[tombstone == (unsigned) -1 ? i : tombstone];
-  }
-
   static unsigned int prime_for (unsigned int shift)
   {
     /* Following comment and table copied from glib. */
@@ -481,7 +529,7 @@
   hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {}
   hb_map_t& operator= (const hb_map_t&) = default;
   hb_map_t& operator= (hb_map_t&&) = default;
-  hb_map_t (std::initializer_list<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> lst) : hashmap (lst) {}
+  hb_map_t (std::initializer_list<hb_codepoint_pair_t> lst) : hashmap (lst) {}
   template <typename Iterable,
 	    hb_requires (hb_is_iterable (Iterable))>
   hb_map_t (const Iterable &o) : hashmap (o) {}

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -153,8 +153,8 @@
   hb_reference_wrapper (T v) : v (v) {}
   bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
   bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
-  operator T () const { return v; }
-  T get () const { return v; }
+  operator T& () { return v; }
+  T& get () { return v; }
   T v;
 };
 template <typename T>
@@ -163,8 +163,8 @@
   hb_reference_wrapper (T& v) : v (std::addressof (v)) {}
   bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
   bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
-  operator T& () const { return *v; }
-  T& get () const { return *v; }
+  operator T& () { return *v; }
+  T& get () { return *v; }
   T* v;
 };
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-multimap.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-multimap.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-multimap.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -38,10 +38,10 @@
 {
   void add (hb_codepoint_t k, hb_codepoint_t v)
   {
-    hb_codepoint_t *i;
-    if (multiples_indices.has (k, &i))
+    hb_vector_t<hb_codepoint_t> *m;
+    if (multiples.has (k, &m))
     {
-      multiples_values[*i].push (v);
+      m->push (v);
       return;
     }
 
@@ -51,12 +51,7 @@
       hb_codepoint_t old = *old_v;
       singulars.del (k);
 
-      multiples_indices.set (k, multiples_values.length);
-      auto *vec = multiples_values.push ();
-
-      vec->push (old);
-      vec->push (v);
-
+      multiples.set (k, hb_vector_t<hb_codepoint_t> {old, v});
       return;
     }
 
@@ -69,9 +64,9 @@
     if (singulars.has (k, &v))
       return hb_array (v, 1);
 
-    hb_codepoint_t *i;
-    if (multiples_indices.has (k, &i))
-      return multiples_values[*i].as_array ();
+    hb_vector_t<hb_codepoint_t> *m;
+    if (multiples.has (k, &m))
+      return m->as_array ();
 
     return hb_array_t<const hb_codepoint_t> ();
   }
@@ -78,13 +73,22 @@
 
   bool in_error () const
   {
-    return singulars.in_error () || multiples_indices.in_error () || multiples_values.in_error ();
+    if (singulars.in_error () || multiples.in_error ())
+      return true;
+    for (const auto &m : multiples.values_ref ())
+      if (m.in_error ())
+        return true;
+    return false;
   }
 
+  void alloc (unsigned size)
+  {
+    singulars.alloc (size);
+  }
+
   protected:
   hb_map_t singulars;
-  hb_map_t multiples_indices;
-  hb_vector_t<hb_vector_t<hb_codepoint_t>> multiples_values;
+  hb_hashmap_t<hb_codepoint_t, hb_vector_t<hb_codepoint_t>> multiples;
 };
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -49,6 +49,15 @@
 #define hb_has_min_size(T) hb_has_min_size<T>::value
 
 template <typename T, typename>
+struct _hb_has_max_size : hb_false_type {};
+template <typename T>
+struct _hb_has_max_size<T, hb_void_t<decltype (T::max_size)>>
+	: hb_true_type {};
+template <typename T>
+using hb_has_max_size = _hb_has_max_size<T, void>;
+#define hb_has_max_size(T) hb_has_max_size<T>::value
+
+template <typename T, typename>
 struct _hb_has_null_size : hb_false_type {};
 template <typename T>
 struct _hb_has_null_size<T, hb_void_t<decltype (T::null_size)>>
@@ -176,7 +185,7 @@
 static inline Type& Crap () {
   static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
   Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
-  memcpy (obj, &Null (Type), sizeof (*obj));
+  memcpy (obj, std::addressof (Null (Type)), sizeof (*obj));
   return *obj;
 }
 template <typename QType>
@@ -211,11 +220,11 @@
   T * operator = (T *v_)   { return v = v_; }
   T * operator -> () const { return get (); }
   T & operator * () const  { return *get (); }
-  T ** operator & () const { return &v; }
+  T ** operator & () const { return std::addressof (v); }
   /* Only auto-cast to const types. */
   template <typename C> operator const C * () const { return get (); }
   operator const char * () const { return (const char *) get (); }
-  T * get () const { return v ? v : const_cast<T *> (&Null (T)); }
+  T * get () const { return v ? v : const_cast<T *> (std::addressof (Null (T))); }
   T * get_raw () const { return v; }
 
   private:

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -131,7 +131,7 @@
     sfnt_version = sfnt_tag;
     /* Take space for numTables, searchRange, entrySelector, RangeShift
      * and the TableRecords themselves.  */
-    unsigned num_items = it.len ();
+    unsigned num_items = hb_len (it);
     if (unlikely (!tables.serialize (c, num_items))) return_trace (false);
 
     const char *dir_end = (const char *) c->head;
@@ -145,7 +145,7 @@
       unsigned len = blob->length;
 
       /* Allocate room for the table and copy it. */
-      char *start = (char *) c->allocate_size<void> (len);
+      char *start = (char *) c->allocate_size<void> (len, false);
       if (unlikely (!start)) return false;
 
       TableRecord &rec = tables.arrayZ[i];

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -312,6 +312,8 @@
 template <typename Type, typename OffsetType, bool has_null=true>
 struct OffsetTo : Offset<OffsetType, has_null>
 {
+  using target_t = Type;
+
   // Make sure Type is not unbounded; works only for types that are fully defined at OffsetTo time.
   static_assert (has_null == false ||
 		 (hb_has_null_size (Type) || !hb_has_min_size (Type)), "");
@@ -416,12 +418,15 @@
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return_trace (false);
-    if (unlikely (this->is_null ())) return_trace (true);
+    //if (unlikely (this->is_null ())) return_trace (true);
     if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false);
     return_trace (true);
   }
 
   template <typename ...Ts>
+#ifndef HB_OPTIMIZE_SIZE
+  HB_ALWAYS_INLINE
+#endif
   bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
@@ -462,24 +467,16 @@
 
   HB_DELETE_CREATE_COPY_ASSIGN (UnsizedArrayOf);
 
-  const Type& operator [] (int i_) const
+  const Type& operator [] (unsigned int i) const
   {
-    unsigned int i = (unsigned int) i_;
-    const Type *p = &arrayZ[i];
-    if (unlikely ((const void *) p < (const void *) arrayZ)) return Null (Type); /* Overflowed. */
-    _hb_compiler_memory_r_barrier ();
-    return *p;
+    return arrayZ[i];
   }
-  Type& operator [] (int i_)
+  Type& operator [] (unsigned int i)
   {
-    unsigned int i = (unsigned int) i_;
-    Type *p = &arrayZ[i];
-    if (unlikely ((const void *) p < (const void *) arrayZ)) return Crap (Type); /* Overflowed. */
-    _hb_compiler_memory_r_barrier ();
-    return *p;
+    return arrayZ[i];
   }
 
-  unsigned int get_size (unsigned int len) const
+  static unsigned int get_size (unsigned int len)
   { return len * Type::static_size; }
 
   template <typename T> operator T * () { return arrayZ; }
@@ -533,6 +530,7 @@
   }
 
   template <typename ...Ts>
+  HB_ALWAYS_INLINE
   bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
@@ -720,7 +718,32 @@
     return_trace (out);
   }
 
+  /* Special-case ArrayOf Offset16To structs with a maximum size. */
+  template <typename T = Type,
+	    typename Base = void,
+	    hb_enable_if (hb_has_max_size (typename T::target_t) &&
+			  sizeof (T) == 2)>
+  HB_ALWAYS_INLINE
+  bool sanitize (hb_sanitize_context_t *c, const Base *base) const
+  {
+    TRACE_SANITIZE (this);
+
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    unsigned max_len = 65536 + Type::target_t::max_size;
+
+    if (unlikely (c->check_range_fast (base, max_len)))
+      return_trace (true);
+
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!c->dispatch (arrayZ[i], base)))
+	return_trace (false);
+    return_trace (true);
+  }
+
   template <typename ...Ts>
+  HB_ALWAYS_INLINE
   bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
@@ -736,7 +759,7 @@
   bool sanitize_shallow (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) && c->check_array (arrayZ, len));
+    return_trace (len.sanitize (c) && c->check_array_sized (arrayZ, len, sizeof (LenType)));
   }
 
   public:
@@ -797,7 +820,7 @@
 using List16OfOffset16To = List16OfOffsetTo<Type, HBUINT16>;
 
 /* An array starting at second element. */
-template <typename Type, typename LenType=HBUINT16>
+template <typename Type, typename LenType>
 struct HeadlessArrayOf
 {
   static constexpr unsigned item_size = Type::static_size;
@@ -861,6 +884,7 @@
   }
 
   template <typename ...Ts>
+  HB_ALWAYS_INLINE
   bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
@@ -878,7 +902,7 @@
   {
     TRACE_SANITIZE (this);
     return_trace (lenP1.sanitize (c) &&
-		  (!lenP1 || c->check_array (arrayZ, lenP1 - 1)));
+		  (!lenP1 || c->check_array_sized (arrayZ, lenP1 - 1, sizeof (LenType))));
   }
 
   public:
@@ -887,6 +911,7 @@
   public:
   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
 };
+template <typename Type> using HeadlessArray16Of = HeadlessArrayOf<Type, HBUINT16>;
 
 /* An array storing length-1. */
 template <typename Type, typename LenType=HBUINT16>
@@ -912,6 +937,7 @@
   { return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
 
   template <typename ...Ts>
+  HB_ALWAYS_INLINE
   bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
@@ -929,7 +955,7 @@
   {
     TRACE_SANITIZE (this);
     return_trace (lenM1.sanitize (c) &&
-		  (c->check_array (arrayZ, lenM1 + 1)));
+		  (c->check_array_sized (arrayZ, lenM1 + 1, sizeof (LenType))));
   }
 
   public:
@@ -1096,6 +1122,7 @@
   { return header.static_size + header.nUnits * header.unitSize; }
 
   template <typename ...Ts>
+  HB_ALWAYS_INLINE
   bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -48,13 +48,25 @@
 
 struct code_pair_t
 {
-  hb_codepoint_t code;
+  unsigned code;
   hb_codepoint_t glyph;
 };
 
+
 using str_buff_t = hb_vector_t<unsigned char>;
 using str_buff_vec_t = hb_vector_t<str_buff_t>;
+using glyph_to_sid_map_t = hb_vector_t<code_pair_t>;
 
+struct length_f_t
+{
+  template <typename Iterable,
+	    hb_requires (hb_is_iterable (Iterable))>
+  unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); }
+
+  unsigned operator () (unsigned _) const { return _; }
+}
+HB_FUNCOBJ (length_f);
+
 /* CFF INDEX */
 template <typename COUNT>
 struct CFFIndex
@@ -62,26 +74,36 @@
   unsigned int offset_array_size () const
   { return offSize * (count + 1); }
 
-  CFFIndex *copy (hb_serialize_context_t *c) const
-  {
-    TRACE_SERIALIZE (this);
-    unsigned int size = get_size ();
-    CFFIndex *out = c->allocate_size<CFFIndex> (size, false);
-    if (likely (out))
-      hb_memcpy (out, this, size);
-    return_trace (out);
-  }
-
   template <typename Iterable,
 	    hb_requires (hb_is_iterable (Iterable))>
   bool serialize (hb_serialize_context_t *c,
-		  const Iterable &iterable)
+		  const Iterable &iterable,
+		  const unsigned *p_data_size = nullptr)
   {
     TRACE_SERIALIZE (this);
+    unsigned data_size;
+    if (p_data_size)
+      data_size = *p_data_size;
+    else
+      total_size (iterable, &data_size);
+
     auto it = hb_iter (iterable);
-    serialize_header(c, + it | hb_map (hb_iter) | hb_map (hb_len));
+    if (unlikely (!serialize_header (c, +it, data_size))) return_trace (false);
+    unsigned char *ret = c->allocate_size<unsigned char> (data_size, false);
+    if (unlikely (!ret)) return_trace (false);
     for (const auto &_ : +it)
-      hb_iter (_).copy (c);
+    {
+      unsigned len = _.length;
+      if (len <= 1)
+      {
+        if (!len)
+	  continue;
+	*ret++ = *_.arrayZ;
+	continue;
+      }
+      hb_memcpy (ret, _.arrayZ, len);
+      ret += len;
+    }
     return_trace (true);
   }
 
@@ -88,16 +110,16 @@
   template <typename Iterator,
 	    hb_requires (hb_is_iterator (Iterator))>
   bool serialize_header (hb_serialize_context_t *c,
-			Iterator it)
+			 Iterator it,
+			 unsigned data_size)
   {
     TRACE_SERIALIZE (this);
 
-    unsigned total = + it | hb_reduce (hb_add, 0);
-    unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
+    unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8;
 
     /* serialize CFFIndex header */
     if (unlikely (!c->extend_min (this))) return_trace (false);
-    this->count = it.len ();
+    this->count = hb_len (it);
     if (!this->count) return_trace (true);
     if (unlikely (!c->extend (this->offSize))) return_trace (false);
     this->offSize = off_size;
@@ -106,25 +128,88 @@
 
     /* serialize indices */
     unsigned int offset = 1;
-    unsigned int i = 0;
-    for (unsigned _ : +it)
+    if (HB_OPTIMIZE_SIZE_VAL)
     {
-      set_offset_at (i++, offset);
-      offset += _;
+      unsigned int i = 0;
+      for (const auto &_ : +it)
+      {
+	set_offset_at (i++, offset);
+	offset += length_f (_);
+      }
+      set_offset_at (i, offset);
     }
-    set_offset_at (i, offset);
+    else
+      switch (off_size)
+      {
+	case 1:
+	{
+	  HBUINT8 *p = (HBUINT8 *) offsets;
+	  for (const auto &_ : +it)
+	  {
+	    *p++ = offset;
+	    offset += length_f (_);
+	  }
+	  *p = offset;
+	}
+	break;
+	case 2:
+	{
+	  HBUINT16 *p = (HBUINT16 *) offsets;
+	  for (const auto &_ : +it)
+	  {
+	    *p++ = offset;
+	    offset += length_f (_);
+	  }
+	  *p = offset;
+	}
+	break;
+	case 3:
+	{
+	  HBUINT24 *p = (HBUINT24 *) offsets;
+	  for (const auto &_ : +it)
+	  {
+	    *p++ = offset;
+	    offset += length_f (_);
+	  }
+	  *p = offset;
+	}
+	break;
+	case 4:
+	{
+	  HBUINT32 *p = (HBUINT32 *) offsets;
+	  for (const auto &_ : +it)
+	  {
+	    *p++ = offset;
+	    offset += length_f (_);
+	  }
+	  *p = offset;
+	}
+	break;
+	default:
+	break;
+      }
 
+    assert (offset == data_size + 1);
     return_trace (true);
   }
 
   template <typename Iterable,
 	    hb_requires (hb_is_iterable (Iterable))>
-  static unsigned total_size (const Iterable &iterable)
+  static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr)
   {
-    auto it = + hb_iter (iterable) | hb_map (hb_iter) | hb_map (hb_len);
-    if (!it) return 0;
+    auto it = + hb_iter (iterable);
+    if (!it)
+    {
+      if (data_size) *data_size = 0;
+      return min_size;
+    }
 
-    unsigned total = + it | hb_reduce (hb_add, 0);
+    unsigned total = 0;
+    for (const auto &_ : +it)
+      total += length_f (_);
+
+    if (data_size) *data_size = total;
+
     unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
 
     return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
@@ -133,13 +218,16 @@
   void set_offset_at (unsigned int index, unsigned int offset)
   {
     assert (index <= count);
-    HBUINT8 *p = offsets + offSize * index + offSize;
+
     unsigned int size = offSize;
-    for (; size; size--)
+    const HBUINT8 *p = offsets;
+    switch (size)
     {
-      --p;
-      *p = offset & 0xFF;
-      offset >>= 8;
+      case 1: ((HBUINT8  *) p)[index] = offset; break;
+      case 2: ((HBUINT16 *) p)[index] = offset; break;
+      case 3: ((HBUINT24 *) p)[index] = offset; break;
+      case 4: ((HBUINT32 *) p)[index] = offset; break;
+      default: return;
     }
   }
 
@@ -149,28 +237,19 @@
     assert (index <= count);
 
     unsigned int size = offSize;
-    const HBUINT8 *p = offsets + size * index;
+    const HBUINT8 *p = offsets;
     switch (size)
     {
-      case 1: return * (HBUINT8  *) p;
-      case 2: return * (HBUINT16 *) p;
-      case 3: return * (HBUINT24 *) p;
-      case 4: return * (HBUINT32 *) p;
+      case 1: return ((HBUINT8  *) p)[index];
+      case 2: return ((HBUINT16 *) p)[index];
+      case 3: return ((HBUINT24 *) p)[index];
+      case 4: return ((HBUINT32 *) p)[index];
       default: return 0;
     }
   }
 
-  unsigned int length_at (unsigned int index) const
-  {
-    unsigned offset0 = offset_at (index);
-    unsigned offset1 = offset_at (index + 1);
-    if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
-      return 0;
-    return offset1 - offset0;
-  }
-
   const unsigned char *data_base () const
-  { return (const unsigned char *) this + min_size + offSize.static_size + offset_array_size (); }
+  { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); }
   public:
 
   hb_ubytes_t operator [] (unsigned int index) const
@@ -177,9 +256,11 @@
   {
     if (unlikely (index >= count)) return hb_ubytes_t ();
     _hb_compiler_memory_r_barrier ();
-    unsigned length = length_at (index);
-    if (unlikely (!length)) return hb_ubytes_t ();
-    return hb_ubytes_t (data_base () + offset_at (index) - 1, length);
+    unsigned offset0 = offset_at (index);
+    unsigned offset1 = offset_at (index + 1);
+    if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
+      return hb_ubytes_t ();
+    return hb_ubytes_t (data_base () + offset0, offset1 - offset0);
   }
 
   unsigned int get_size () const
@@ -197,7 +278,7 @@
 			   (count < count + 1u &&
 			    c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 &&
 			    c->check_array (offsets, offSize, count + 1u) &&
-			    c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count) - 1)))));
+			    c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count))))));
   }
 
   public:
@@ -211,47 +292,6 @@
   DEFINE_SIZE_MIN (COUNT::static_size);
 };
 
-template <typename COUNT, typename TYPE>
-struct CFFIndexOf : CFFIndex<COUNT>
-{
-  template <typename DATA, typename PARAM1, typename PARAM2>
-  bool serialize (hb_serialize_context_t *c,
-		  unsigned int offSize_,
-		  const DATA *dataArray,
-		  unsigned int dataArrayLen,
-		  const hb_vector_t<unsigned int> &dataSizeArray,
-		  const PARAM1 &param1,
-		  const PARAM2 &param2)
-  {
-    TRACE_SERIALIZE (this);
-    /* serialize CFFIndex header */
-    if (unlikely (!c->extend_min (this))) return_trace (false);
-    this->count = dataArrayLen;
-    this->offSize = offSize_;
-    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1), false)))
-      return_trace (false);
-
-    /* serialize indices */
-    unsigned int  offset = 1;
-    unsigned int  i = 0;
-    for (; i < dataArrayLen; i++)
-    {
-      this->set_offset_at (i, offset);
-      offset += dataSizeArray[i];
-    }
-    this->set_offset_at (i, offset);
-
-    /* serialize data */
-    for (unsigned int i = 0; i < dataArrayLen; i++)
-    {
-      TYPE *dest = c->start_embed<TYPE> ();
-      if (unlikely (!dest || !dest->serialize (c, dataArray[i], param1, param2)))
-	return_trace (false);
-    }
-    return_trace (true);
-  }
-};
-
 /* Top Dict, Font Dict, Private Dict */
 struct Dict : UnsizedByteStr
 {
@@ -327,7 +367,7 @@
 };
 
 template <typename COUNT>
-struct FDArray : CFFIndexOf<COUNT, FontDict>
+struct FDArray : CFFIndex<COUNT>
 {
   template <typename DICTVAL, typename INFO, typename Iterator, typename OP_SERIALIZER>
   bool serialize (hb_serialize_context_t *c,
@@ -338,7 +378,11 @@
 
     /* serialize INDEX data */
     hb_vector_t<unsigned> sizes;
+    if (it.is_random_access_iterator)
+      sizes.alloc (hb_len (it));
+
     c->push ();
+    char *data_base = c->head;
     + it
     | hb_map ([&] (const hb_pair_t<const DICTVAL&, const INFO&> &_)
     {
@@ -348,10 +392,16 @@
 	      })
     | hb_sink (sizes)
     ;
+    unsigned data_size = c->head - data_base;
     c->pop_pack (false);
 
+    if (unlikely (sizes.in_error ())) return_trace (false);
+
+    /* It just happens that the above is packed right after the header below.
+     * Such a hack. */
+
     /* serialize INDEX header */
-    return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes)));
+    return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes), data_size));
   }
 };
 
@@ -368,9 +418,12 @@
     return_trace (true);
   }
 
-  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
-  { return (hb_codepoint_t) fds[glyph]; }
+  unsigned get_fd (hb_codepoint_t glyph) const
+  { return fds[glyph]; }
 
+  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
+  { return {fds[glyph], glyph + 1}; }
+
   unsigned int get_size (unsigned int num_glyphs) const
   { return HBUINT8::static_size * num_glyphs; }
 
@@ -427,12 +480,20 @@
     return +1;
   }
 
-  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  unsigned get_fd (hb_codepoint_t glyph) const
   {
     auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
     return range ? range->fd : ranges[nRanges () - 1].fd;
   }
 
+  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
+  {
+    auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
+    unsigned fd = range ? range->fd : ranges[nRanges () - 1].fd;
+    hb_codepoint_t end = range ? range[1].first : ranges[nRanges () - 1].first;
+    return {fd, end};
+  }
+
   GID_TYPE        &nRanges ()       { return ranges.len; }
   GID_TYPE         nRanges () const { return ranges.len; }
   GID_TYPE       &sentinel ()       { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
@@ -469,7 +530,7 @@
     }
   }
 
-  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  unsigned get_fd (hb_codepoint_t glyph) const
   {
     if (this == &Null (FDSelect)) return 0;
 
@@ -480,7 +541,19 @@
     default:return 0;
     }
   }
+  /* Returns pair of fd and one after last glyph in range. */
+  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
+  {
+    if (this == &Null (FDSelect)) return {0, 1};
 
+    switch (format)
+    {
+    case 0: return u.format0.get_fd_range (glyph);
+    case 3: return u.format3.get_fd_range (glyph);
+    default:return {0, 1};
+    }
+  }
+
   bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
   {
     TRACE_SANITIZE (this);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -574,11 +574,11 @@
 
 struct get_seac_param_t
 {
-  get_seac_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) {}
+  get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {}
 
   bool has_seac () const { return base && accent; }
 
-  const OT::cff1::accelerator_t *cff;
+  const OT::cff1::accelerator_subset_t *cff;
   hb_codepoint_t  base = 0;
   hb_codepoint_t  accent = 0;
 };
@@ -596,7 +596,7 @@
   }
 };
 
-bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
+bool OT::cff1::accelerator_subset_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
 {
   if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
 

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -28,7 +28,7 @@
 #define HB_OT_CFF1_TABLE_HH
 
 #include "hb-ot-cff-common.hh"
-#include "hb-subset-cff1.hh"
+#include "hb-subset-cff-common.hh"
 #include "hb-draw.hh"
 #include "hb-paint.hh"
 
@@ -52,7 +52,6 @@
 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
 
 typedef CFFIndex<HBUINT16>  CFF1Index;
-template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
 
 typedef CFFIndex<HBUINT16> CFF1Index;
 typedef CFF1Index          CFF1CharStrings;
@@ -110,6 +109,7 @@
 
   hb_codepoint_t get_code (hb_codepoint_t glyph) const
   {
+    /* TODO: Add cache like get_sid. */
     assert (glyph > 0);
     glyph--;
     for (unsigned int i = 0; i < nRanges (); i++)
@@ -173,11 +173,7 @@
   bool serialize (hb_serialize_context_t *c, const Encoding &src)
   {
     TRACE_SERIALIZE (this);
-    unsigned int size = src.get_size ();
-    Encoding *dest = c->allocate_size<Encoding> (size);
-    if (unlikely (!dest)) return_trace (false);
-    hb_memcpy (dest, &src, size);
-    return_trace (true);
+    return_trace (c->embed (src));
   }
 
   /* serialize a subset Encoding */
@@ -312,26 +308,29 @@
 };
 
 /* Charset */
-struct Charset0 {
-  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+struct Charset0
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
+    if (num_charset_entries) *num_charset_entries = num_glyphs;
+    return_trace (sids.sanitize (c, num_glyphs - 1));
   }
 
   hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
   {
     if (unlikely (glyph >= num_glyphs)) return 0;
-    if (glyph == 0)
+    if (unlikely (glyph == 0))
       return 0;
     else
       return sids[glyph - 1];
   }
 
-  void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+  void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
   {
+    mapping->resize (num_glyphs, false);
     for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
-      mapping->set (gid, sids[gid - 1]);
+      mapping->arrayZ[gid] = {sids[gid - 1], gid};
   }
 
   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
@@ -347,13 +346,13 @@
     return 0;
   }
 
-  unsigned int get_size (unsigned int num_glyphs) const
+  static unsigned int get_size (unsigned int num_glyphs)
   {
     assert (num_glyphs > 0);
-    return HBUINT16::static_size * (num_glyphs - 1);
+    return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1);
   }
 
-  HBUINT16  sids[HB_VAR_ARRAY];
+  UnsizedArrayOf<HBUINT16> sids;
 
   DEFINE_SIZE_ARRAY(0, sids);
 };
@@ -374,38 +373,62 @@
 
 template <typename TYPE>
 struct Charset1_2 {
-  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
     num_glyphs--;
-    for (unsigned int i = 0; num_glyphs > 0; i++)
+    unsigned i;
+    for (i = 0; num_glyphs > 0; i++)
     {
       if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
 	return_trace (false);
       num_glyphs -= (ranges[i].nLeft + 1);
     }
+    if (num_charset_entries)
+      *num_charset_entries = i;
     return_trace (true);
   }
 
-  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
+  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs,
+			  code_pair_t *cache = nullptr) const
   {
     if (unlikely (glyph >= num_glyphs)) return 0;
-    if (glyph == 0) return 0;
-    glyph--;
-    for (unsigned int i = 0;; i++)
+    unsigned i;
+    hb_codepoint_t start_glyph;
+    if (cache && likely (cache->glyph <= glyph))
     {
-      if (glyph <= ranges[i].nLeft)
-	return (hb_codepoint_t) ranges[i].first + glyph;
-      glyph -= (ranges[i].nLeft + 1);
+      i = cache->code;
+      start_glyph = cache->glyph;
     }
+    else
+    {
+      if (unlikely (glyph == 0)) return 0;
+      i = 0;
+      start_glyph = 1;
+    }
+    glyph -= start_glyph;
+    for (;; i++)
+    {
+      unsigned count = ranges[i].nLeft;
+      if (glyph <= count)
+      {
+        if (cache)
+	  *cache = {i, start_glyph};
+	return ranges[i].first + glyph;
+      }
+      count++;
+      start_glyph += count;
+      glyph -= count;
+    }
 
     return 0;
   }
 
-  void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+  void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
   {
+    mapping->resize (num_glyphs, false);
     hb_codepoint_t gid = 1;
     if (gid >= num_glyphs)
       return;
@@ -413,8 +436,9 @@
     {
       hb_codepoint_t sid = ranges[i].first;
       unsigned count = ranges[i].nLeft + 1;
+      unsigned last = gid + count;
       for (unsigned j = 0; j < count; j++)
-	mapping->set (gid++, sid++);
+	mapping->arrayZ[gid++] = {sid++, last - 1};
 
       if (gid >= num_glyphs)
         break;
@@ -439,8 +463,8 @@
 
   unsigned int get_size (unsigned int num_glyphs) const
   {
-    unsigned int size = HBUINT8::static_size;
-    int glyph = (int)num_glyphs;
+    int glyph = (int) num_glyphs;
+    unsigned num_ranges = 0;
 
     assert (glyph > 0);
     glyph--;
@@ -447,14 +471,19 @@
     for (unsigned int i = 0; glyph > 0; i++)
     {
       glyph -= (ranges[i].nLeft + 1);
-      size += Charset_Range<TYPE>::static_size;
+      num_ranges++;
     }
 
-    return size;
+    return get_size_for_ranges (num_ranges);
   }
 
-  Charset_Range<TYPE>   ranges[HB_VAR_ARRAY];
+  static unsigned int get_size_for_ranges (unsigned int num_ranges)
+  {
+    return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges);
+  }
 
+  UnsizedArrayOf<Charset_Range<TYPE>> ranges;
+
   DEFINE_SIZE_ARRAY (0, ranges);
 };
 
@@ -469,11 +498,7 @@
   bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
   {
     TRACE_SERIALIZE (this);
-    unsigned int size = src.get_size (num_glyphs);
-    Charset *dest = c->allocate_size<Charset> (size);
-    if (unlikely (!dest)) return_trace (false);
-    hb_memcpy (dest, &src, size);
-    return_trace (true);
+    return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs)));
   }
 
   /* serialize a subset Charset */
@@ -490,13 +515,13 @@
     {
     case 0:
     {
-      Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
+      Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false);
       if (unlikely (!fmt0)) return_trace (false);
       unsigned int glyph = 0;
       for (unsigned int i = 0; i < sid_ranges.length; i++)
       {
-	hb_codepoint_t sid = sid_ranges[i].code;
-	for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
+	hb_codepoint_t sid = sid_ranges.arrayZ[i].code;
+	for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--)
 	  fmt0->sids[glyph++] = sid++;
       }
     }
@@ -504,29 +529,35 @@
 
     case 1:
     {
-      Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
+      Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false);
       if (unlikely (!fmt1)) return_trace (false);
+      hb_codepoint_t all_glyphs = 0;
       for (unsigned int i = 0; i < sid_ranges.length; i++)
       {
-	if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
-	  return_trace (false);
-	fmt1->ranges[i].first = sid_ranges[i].code;
-	fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
+        auto &_ = sid_ranges.arrayZ[i];
+        all_glyphs |= _.glyph;
+	fmt1->ranges[i].first = _.code;
+	fmt1->ranges[i].nLeft = _.glyph;
       }
+      if (unlikely (!(all_glyphs <= 0xFF)))
+	return_trace (false);
     }
     break;
 
     case 2:
     {
-      Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
+      Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false);
       if (unlikely (!fmt2)) return_trace (false);
+      hb_codepoint_t all_glyphs = 0;
       for (unsigned int i = 0; i < sid_ranges.length; i++)
       {
-	if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
-	  return_trace (false);
-	fmt2->ranges[i].first = sid_ranges[i].code;
-	fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
+        auto &_ = sid_ranges.arrayZ[i];
+        all_glyphs |= _.glyph;
+	fmt2->ranges[i].first = _.code;
+	fmt2->ranges[i].nLeft = _.glyph;
       }
+      if (unlikely (!(all_glyphs <= 0xFFFF)))
+	return_trace (false);
     }
     break;
 
@@ -545,18 +576,19 @@
     }
   }
 
-  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
+  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs,
+			  code_pair_t *cache = nullptr) const
   {
     switch (format)
     {
     case 0: return u.format0.get_sid (glyph, num_glyphs);
-    case 1: return u.format1.get_sid (glyph, num_glyphs);
-    case 2: return u.format2.get_sid (glyph, num_glyphs);
+    case 1: return u.format1.get_sid (glyph, num_glyphs, cache);
+    case 2: return u.format2.get_sid (glyph, num_glyphs, cache);
     default:return 0;
     }
   }
 
-  void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+  void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
   {
     switch (format)
     {
@@ -578,7 +610,7 @@
     }
   }
 
-  bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
@@ -586,9 +618,9 @@
 
     switch (format)
     {
-    case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
-    case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
-    case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
+    case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+    case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+    case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
     default:return_trace (false);
     }
   }
@@ -606,10 +638,10 @@
 struct CFF1StringIndex : CFF1Index
 {
   bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
-		  const hb_inc_bimap_t &sidmap)
+		  const hb_vector_t<unsigned> &sidmap)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
+    if (unlikely ((strings.count == 0) || (sidmap.length == 0)))
     {
       if (unlikely (!c->extend_min (this->count)))
 	return_trace (false);
@@ -617,16 +649,14 @@
       return_trace (true);
     }
 
-    byte_str_array_t bytesArray;
-    if (!bytesArray.resize (sidmap.get_population ()))
-      return_trace (false);
-    for (unsigned int i = 0; i < strings.count; i++)
-    {
-      hb_codepoint_t  j = sidmap[i];
-      if (j != HB_MAP_VALUE_INVALID)
-	bytesArray[j] = strings[i];
-    }
+    if (unlikely (sidmap.in_error ())) return_trace (false);
 
+    // Save this in a vector since serialize() iterates it twice.
+    hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap)
+					 | hb_map (strings));
+
+    if (unlikely (bytesArray.in_error ())) return_trace (false);
+
     bool result = CFF1Index::serialize (c, bytesArray);
     return_trace (result);
   }
@@ -932,7 +962,7 @@
   }
 };
 
-struct cff1_private_dict_opset_subset : dict_opset_t
+struct cff1_private_dict_opset_subset_t : dict_opset_t
 {
   static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
   {
@@ -978,7 +1008,7 @@
 typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
 
 typedef CFF1Index CFF1NameIndex;
-typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
+typedef CFF1Index CFF1TopDictIndex;
 
 struct cff1_font_dict_values_mod_t
 {
@@ -1031,8 +1061,10 @@
   template <typename PRIVOPSET, typename PRIVDICTVAL>
   struct accelerator_templ_t
   {
-    void init (hb_face_t *face)
+    accelerator_templ_t (hb_face_t *face)
     {
+      if (!face) return;
+
       topDict.init ();
       fontDicts.init ();
       privateDicts.init ();
@@ -1046,22 +1078,22 @@
       const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
 
       if (cff == &Null (OT::cff1))
-      { fini (); return; }
+        goto fail;
 
       nameIndex = &cff->nameIndex (cff);
       if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
-      { fini (); return; }
+        goto fail;
 
       topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
       if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
-      { fini (); return; }
+        goto fail;
 
       { /* parse top dict */
 	const hb_ubytes_t topDictStr = (*topDictIndex)[0];
-	if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
+	if (unlikely (!topDictStr.sanitize (&sc)))   goto fail;
 	cff1_top_dict_interp_env_t env (topDictStr);
 	cff1_top_dict_interpreter_t top_interp (env);
-	if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
+	if (unlikely (!top_interp.interpret (topDict)))   goto fail;
       }
 
       if (is_predef_charset ())
@@ -1069,7 +1101,7 @@
       else
       {
 	charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
-	if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
+	if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries)))   goto fail;
       }
 
       fdCount = 1;
@@ -1079,7 +1111,7 @@
 	fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
 	if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
 	    (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
-	{ fini (); return; }
+	  goto fail;
 
 	fdCount = fdArray->count;
       }
@@ -1092,7 +1124,7 @@
       encoding = &Null (Encoding);
       if (is_CID ())
       {
-	if (unlikely (charset == &Null (Charset))) { fini (); return; }
+	if (unlikely (charset == &Null (Charset)))   goto fail;
       }
       else
       {
@@ -1099,29 +1131,29 @@
 	if (!is_predef_encoding ())
 	{
 	  encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
-	  if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
+	  if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc)))   goto fail;
 	}
       }
 
       stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
       if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
-      { fini (); return; }
+        goto fail;
 
       globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
       if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
-      { fini (); return; }
+        goto fail;
 
       charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
 
       if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
-      { fini (); return; }
+        goto fail;
 
       num_glyphs = charStrings->count;
       if (num_glyphs != sc.get_num_glyphs ())
-      { fini (); return; }
+        goto fail;
 
       if (unlikely (!privateDicts.resize (fdCount)))
-      { fini (); return; }
+        goto fail;
       for (unsigned int i = 0; i < fdCount; i++)
 	privateDicts[i].init ();
 
@@ -1131,27 +1163,27 @@
 	for (unsigned int i = 0; i < fdCount; i++)
 	{
 	  hb_ubytes_t fontDictStr = (*fdArray)[i];
-	  if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
+	  if (unlikely (!fontDictStr.sanitize (&sc)))   goto fail;
 	  cff1_font_dict_values_t *font;
 	  cff1_top_dict_interp_env_t env (fontDictStr);
 	  cff1_font_dict_interpreter_t font_interp (env);
 	  font = fontDicts.push ();
-	  if (unlikely (fontDicts.in_error ())) { fini (); return; }
+	  if (unlikely (fontDicts.in_error ()))   goto fail;
 
 	  font->init ();
-	  if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
+	  if (unlikely (!font_interp.interpret (*font)))   goto fail;
 	  PRIVDICTVAL *priv = &privateDicts[i];
 	  const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
-	  if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+	  if (unlikely (!privDictStr.sanitize (&sc)))   goto fail;
 	  num_interp_env_t env2 (privDictStr);
 	  dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
 	  priv->init ();
-	  if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+	  if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
 
 	  priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
 	  if (priv->localSubrs != &Null (CFF1Subrs) &&
 	      unlikely (!priv->localSubrs->sanitize (&sc)))
-	  { fini (); return; }
+	    goto fail;
 	}
       }
       else  /* non-CID */
@@ -1160,20 +1192,25 @@
 	PRIVDICTVAL *priv = &privateDicts[0];
 
 	const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
-	if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+	if (unlikely (!privDictStr.sanitize (&sc)))   goto fail;
 	num_interp_env_t env (privDictStr);
 	dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
 	priv->init ();
-	if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+	if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
 
 	priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
 	if (priv->localSubrs != &Null (CFF1Subrs) &&
 	    unlikely (!priv->localSubrs->sanitize (&sc)))
-	{ fini (); return; }
+	  goto fail;
       }
+
+      return;
+
+      fail:
+        _fini ();
     }
-
-    void fini ()
+    ~accelerator_templ_t () { _fini (); }
+    void _fini ()
     {
       sc.end_processing ();
       topDict.fini ();
@@ -1183,6 +1220,8 @@
       blob = nullptr;
     }
 
+    hb_blob_t *get_blob () const { return blob; }
+
     bool is_valid () const { return blob; }
     bool   is_CID () const { return topDict.is_CID (); }
 
@@ -1203,13 +1242,14 @@
 
     bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
 
-    hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
+    hb_codepoint_t glyph_to_code (hb_codepoint_t glyph,
+				  code_pair_t *glyph_to_sid_cache = nullptr) const
     {
       if (encoding != &Null (Encoding))
 	return encoding->get_code (glyph);
       else
       {
-	hb_codepoint_t sid = glyph_to_sid (glyph);
+	hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache);
 	if (sid == 0) return 0;
 	hb_codepoint_t code = 0;
 	switch (topDict.EncodingOffset)
@@ -1227,12 +1267,14 @@
       }
     }
 
-    hb_map_t *create_glyph_to_sid_map () const
+    glyph_to_sid_map_t *create_glyph_to_sid_map () const
     {
       if (charset != &Null (Charset))
       {
-	hb_map_t *mapping = hb_map_create ();
-	mapping->set (0, 0);
+	auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t));
+	if (unlikely (!mapping)) return nullptr;
+	mapping = new (mapping) glyph_to_sid_map_t ();
+	mapping->push (code_pair_t {0, 1});
 	charset->collect_glyph_to_sid_map (mapping, num_glyphs);
 	return mapping;
       }
@@ -1240,10 +1282,11 @@
 	return nullptr;
     }
 
-    hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
+    hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph,
+				 code_pair_t *cache = nullptr) const
     {
       if (charset != &Null (Charset))
-	return charset->get_sid (glyph, num_glyphs);
+	return charset->get_sid (glyph, num_glyphs, cache);
       else
       {
 	hb_codepoint_t sid = 0;
@@ -1312,19 +1355,17 @@
     hb_vector_t<PRIVDICTVAL> privateDicts;
 
     unsigned int	     num_glyphs = 0;
+    unsigned int	     num_charset_entries = 0;
   };
 
   struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
   {
-    accelerator_t (hb_face_t *face)
+    accelerator_t (hb_face_t *face) : SUPER (face)
     {
-      SUPER::init (face);
-
       glyph_names.set_relaxed (nullptr);
 
       if (!is_valid ()) return;
       if (is_CID ()) return;
-
     }
     ~accelerator_t ()
     {
@@ -1334,8 +1375,6 @@
 	names->fini ();
 	hb_free (names);
       }
-
-      SUPER::fini ();
     }
 
     bool get_glyph_name (hb_codepoint_t glyph,
@@ -1386,9 +1425,10 @@
 	  /* TODO */
 
 	  /* fill glyph names */
+	  code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
 	  for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
 	  {
-	    hb_codepoint_t	sid = glyph_to_sid (gid);
+	    hb_codepoint_t	sid = glyph_to_sid (gid, &glyph_to_sid_cache);
 	    gname_t	gname;
 	    gname.sid = sid;
 	    if (sid < cff1_std_strings_length)
@@ -1426,7 +1466,6 @@
 
     HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
     HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
-    HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
 
     private:
@@ -1453,10 +1492,25 @@
     typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
   };
 
-  struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {};
+  struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t>
+  {
+    accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
+    ~accelerator_subset_t ()
+    {
+      if (cff_accelerator)
+	cff_subset_accelerator_t::destroy (cff_accelerator);
+    }
 
-  bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); }
+    HB_INTERNAL bool subset (hb_subset_context_t *c) const;
+    HB_INTERNAL bool serialize (hb_serialize_context_t *c,
+				struct cff1_subset_plan &plan) const;
+    HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
 
+    mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
+
+    typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER;
+  };
+
   protected:
   HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
   HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
@@ -1479,6 +1533,10 @@
   cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
 };
 
+struct cff1_subset_accelerator_t : cff1::accelerator_subset_t {
+  cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {}
+};
+
 } /* namespace OT */
 
 #endif /* HB_OT_CFF1_TABLE_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -28,7 +28,7 @@
 #define HB_OT_CFF2_TABLE_HH
 
 #include "hb-ot-cff-common.hh"
-#include "hb-subset-cff2.hh"
+#include "hb-subset-cff-common.hh"
 #include "hb-draw.hh"
 #include "hb-paint.hh"
 
@@ -41,7 +41,6 @@
 #define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2')
 
 typedef CFFIndex<HBUINT32>  CFF2Index;
-template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {};
 
 typedef CFF2Index         CFF2CharStrings;
 typedef Subrs<HBUINT32>   CFF2Subrs;
@@ -393,6 +392,8 @@
   {
     accelerator_templ_t (hb_face_t *face)
     {
+      if (!face) return;
+
       topDict.init ();
       fontDicts.init ();
       privateDicts.init ();
@@ -464,7 +465,6 @@
 	  goto fail;
       }
 
-
       return;
 
       fail:
@@ -481,11 +481,13 @@
       blob = nullptr;
     }
 
-    hb_map_t *create_glyph_to_sid_map () const
+    hb_vector_t<uint16_t> *create_glyph_to_sid_map () const
     {
       return nullptr;
     }
 
+    hb_blob_t *get_blob () const { return blob; }
+
     bool is_valid () const { return blob; }
 
     protected:
@@ -518,10 +520,25 @@
     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
   };
 
-  typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
+  struct accelerator_subset_t : accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t>
+  {
+    accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
+    ~accelerator_subset_t ()
+    {
+      if (cff_accelerator)
+	cff_subset_accelerator_t::destroy (cff_accelerator);
+    }
 
-  bool subset (hb_subset_context_t *c) const { return hb_subset_cff2 (c); }
+    HB_INTERNAL bool subset (hb_subset_context_t *c) const;
+    HB_INTERNAL bool serialize (hb_serialize_context_t *c,
+				struct cff2_subset_plan &plan,
+				hb_array_t<int> normalized_coords) const;
 
+    mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
+
+    typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> SUPER;
+  };
+
   public:
   FixedVersion<HBUINT8>		version;	/* Version of CFF2 table. set to 0x0200u */
   NNOffsetTo<TopDict, HBUINT8>	topDict;	/* headerSize = Offset to Top DICT. */
@@ -535,6 +552,10 @@
   cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {}
 };
 
+struct cff2_subset_accelerator_t : cff2::accelerator_subset_t {
+  cff2_subset_accelerator_t (hb_face_t *face) : cff2::accelerator_subset_t (face) {}
+};
+
 } /* namespace OT */
 
 #endif /* HB_OT_CFF2_TABLE_HH */

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -277,10 +277,10 @@
       }
     } writer(c);
 
-    writer.end_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
-    c->allocate_size<HBUINT16> (2); // padding
-    writer.start_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
-    writer.id_delta_ = c->allocate_size<HBINT16> (HBINT16::static_size * segcount);
+    writer.end_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount, false);
+    (void) c->allocate_size<HBUINT16> (2); // padding
+    writer.start_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount, false);
+    writer.id_delta_ = c->allocate_size<HBINT16> (HBINT16::static_size * segcount, false);
 
     if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false;
 
@@ -325,7 +325,7 @@
   {
     auto format4_iter =
     + it
-    | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
+    | hb_filter ([&] (const hb_codepoint_pair_t _)
 		 { return _.first <= 0xFFFF; })
     ;
 
@@ -335,7 +335,7 @@
     if (unlikely (!c->extend_min (this))) return;
     this->format = 4;
 
-    hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> cp_to_gid {
+    hb_vector_t<hb_codepoint_pair_t> cp_to_gid {
       format4_iter
     };
 
@@ -757,8 +757,7 @@
       hb_codepoint_t gid = this->groups[i].glyphID;
       if (!gid)
       {
-	/* Intention is: if (hb_is_same (T, CmapSubtableFormat13)) continue; */
-	if (! T::group_get_glyph (this->groups[i], end)) continue;
+        if (T::formatNumber == 13) continue;
 	start++;
 	gid++;
       }
@@ -766,11 +765,13 @@
       if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
 	end = start + (hb_codepoint_t) num_glyphs - gid;
 
+      mapping->alloc (mapping->get_population () + end - start + 1);
+
       for (unsigned cp = start; cp <= end; cp++)
       {
 	unicodes->add (cp);
 	mapping->set (cp, gid);
-	gid++;
+        gid += T::increment;
       }
     }
   }
@@ -794,6 +795,9 @@
 
 struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
 {
+  static constexpr int increment = 1;
+  static constexpr int formatNumber = 12;
+
   static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
 					 hb_codepoint_t u)
   { return likely (group.startCharCode <= group.endCharCode) ?
@@ -866,6 +870,9 @@
 
 struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
 {
+  static constexpr int increment = 0;
+  static constexpr int formatNumber = 13;
+
   static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
 					 hb_codepoint_t u HB_UNUSED)
   { return group.glyphID; }
@@ -917,8 +924,7 @@
   DefaultUVS* copy (hb_serialize_context_t *c,
 		    const hb_set_t *unicodes) const
   {
-    DefaultUVS *out = c->start_embed<DefaultUVS> ();
-    if (unlikely (!out)) return nullptr;
+    auto *out = c->start_embed<DefaultUVS> ();
     auto snap = c->snapshot ();
 
     HBUINT32 len;
@@ -931,8 +937,7 @@
       hb_codepoint_t start = HB_SET_VALUE_INVALID;
       hb_codepoint_t end = HB_SET_VALUE_INVALID;
 
-      for (hb_codepoint_t u = HB_SET_VALUE_INVALID;
-	   unicodes->next (&u);)
+      for (auto u : *unicodes)
       {
         if (!as_array ().bsearch (u))
 	  continue;
@@ -1067,9 +1072,7 @@
 		       const hb_set_t *glyphs_requested,
 		       const hb_map_t *glyph_map) const
   {
-    NonDefaultUVS *out = c->start_embed<NonDefaultUVS> ();
-    if (unlikely (!out)) return nullptr;
-
+    auto *out = c->start_embed<NonDefaultUVS> ();
     auto it =
     + as_array ()
     | hb_filter ([&] (const UVSMapping& _)
@@ -1767,7 +1770,6 @@
     TRACE_SUBSET (this);
 
     cmap *cmap_prime = c->serializer->start_embed<cmap> ();
-    if (unlikely (!c->serializer->check_success (cmap_prime))) return_trace (false);
 
     auto encodingrec_iter =
     + hb_iter (encodingRecord)
@@ -1798,7 +1800,7 @@
 
     auto it =
     + c->plan->unicode_to_new_gid_list.iter ()
-    | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
+    | hb_filter ([&] (const hb_codepoint_pair_t _)
 		 { return (_.second != HB_MAP_VALUE_INVALID); })
     ;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -38,8 +38,8 @@
 
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff2-table.hh"
 #include "hb-ot-cff1-table.hh"
-#include "hb-ot-cff2-table.hh"
 #include "hb-ot-hmtx-table.hh"
 #include "hb-ot-post-table.hh"
 #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
@@ -98,7 +98,7 @@
   {
     cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t));
     if (unlikely (!cmap_cache)) goto out;
-    cmap_cache->init ();
+    new (cmap_cache) hb_ot_font_cmap_cache_t ();
     if (unlikely (!hb_face_set_user_data (font->face,
 					  &hb_ot_font_cmap_cache_user_data_key,
 					  cmap_cache,
@@ -230,8 +230,8 @@
 	use_cache = false;
 	goto out;
       }
+      new (cache) hb_ot_font_advance_cache_t;
 
-      cache->init ();
       if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
       {
 	hb_free (cache);
@@ -255,7 +255,7 @@
   { /* Use cache. */
     if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords)
     {
-      ot_font->advance_cache->init ();
+      ot_font->advance_cache->clear ();
       ot_font->cached_coords_serial.set_release (font->serial_coords);
     }
 
@@ -436,8 +436,8 @@
 #endif
   if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
 #ifndef HB_NO_OT_FONT_CFF
+  if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
   if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
-  if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
 #endif
 
   return false;
@@ -525,8 +525,8 @@
 				    embolden ? &outline : draw_data, font->slant_xy);
     if (!font->face->table.glyf->get_path (font, glyph, draw_session))
 #ifndef HB_NO_CFF
+    if (!font->face->table.cff2->get_path (font, glyph, draw_session))
     if (!font->face->table.cff1->get_path (font, glyph, draw_session))
-    if (!font->face->table.cff2->get_path (font, glyph, draw_session))
 #endif
     {}
   }
@@ -565,8 +565,8 @@
 #endif
   if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
 #ifndef HB_NO_CFF
+  if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
   if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
-  if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
 #endif
 }
 #endif

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -46,21 +46,23 @@
 
   template<typename Iterator,
 	   hb_requires (hb_is_iterator (Iterator))>
-  bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it)
+  bool serialize (hb_serialize_context_t *c,
+		  unsigned pixelSize,
+		  Iterator it,
+		  const hb_vector_t<hb_codepoint_pair_t> new_to_old_gid_list,
+		  unsigned num_glyphs)
   {
     TRACE_SERIALIZE (this);
 
-    unsigned length = it.len ();
+    if (unlikely (!c->extend (this, num_glyphs)))  return_trace (false);
 
-    if (unlikely (!c->extend (this, length)))  return_trace (false);
-
     this->pixelSize = pixelSize;
     this->maxWidth =
     + it
     | hb_reduce (hb_max, 0u);
 
-    + it
-    | hb_sink (widthsZ.as_array (length));
+    for (auto &_ : new_to_old_gid_list)
+      widthsZ[_.first] = *it++;
 
     return_trace (true);
   }
@@ -89,7 +91,11 @@
 
   template<typename Iterator,
 	   hb_requires (hb_is_iterator (Iterator))>
-  bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
+  bool serialize (hb_serialize_context_t *c,
+		  unsigned version,
+		  Iterator it,
+		  const hb_vector_t<hb_codepoint_pair_t> &new_to_old_gid_list,
+		  unsigned num_glyphs)
   {
     TRACE_SERIALIZE (this);
 
@@ -97,10 +103,10 @@
 
     this->version = version;
     this->numRecords = it.len ();
-    this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0);
+    this->sizeDeviceRecord = DeviceRecord::get_size (num_glyphs);
 
     for (const hb_item_type<Iterator>& _ : +it)
-      c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
+      c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second, new_to_old_gid_list, num_glyphs);
 
     return_trace (c->successful ());
   }
@@ -110,24 +116,21 @@
   {
     TRACE_SUBSET (this);
 
-    hdmx *hdmx_prime = c->serializer->start_embed <hdmx> ();
-    if (unlikely (!hdmx_prime)) return_trace (false);
+    auto *hdmx_prime = c->serializer->start_embed <hdmx> ();
 
+    unsigned num_input_glyphs = get_num_glyphs ();
     auto it =
     + hb_range ((unsigned) numRecords)
-    | hb_map ([c, this] (unsigned _)
+    | hb_map ([c, num_input_glyphs, this] (unsigned _)
 	{
 	  const DeviceRecord *device_record =
 	    &StructAtOffset<DeviceRecord> (&firstDeviceRecord,
 					   _ * sizeDeviceRecord);
 	  auto row =
-	    + hb_range (c->plan->num_output_glyphs ())
-	    | hb_map (c->plan->reverse_glyph_map)
-	    | hb_map ([this, c, device_record] (hb_codepoint_t _)
+	    + hb_iter (c->plan->new_to_old_gid_list)
+	    | hb_map ([num_input_glyphs, device_record] (hb_codepoint_pair_t _)
 		      {
-			if (c->plan->is_empty_glyph (_))
-			  return Null (HBUINT8);
-			return device_record->widthsZ.as_array (get_num_glyphs ()) [_];
+			return device_record->widthsZ.as_array (num_input_glyphs) [_.second];
 		      })
 	    ;
 	  return hb_pair ((unsigned) device_record->pixelSize, +row);
@@ -134,7 +137,9 @@
 	})
     ;
 
-    hdmx_prime->serialize (c->serializer, version, it);
+    hdmx_prime->serialize (c->serializer, version, it,
+			   c->plan->new_to_old_gid_list,
+			   c->plan->num_output_glyphs ());
     return_trace (true);
   }
 

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -83,7 +83,7 @@
   bool subset_update_header (hb_subset_context_t *c,
 			     unsigned int num_hmetrics,
 			     const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map,
-			     const hb_map_t *bounds_map) const
+			     const hb_vector_t<unsigned> &bounds_vec) const
   {
     hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (c->plan->source, H::tableTag);
     hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
@@ -114,6 +114,7 @@
 	HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET,   caretOffset);
       }
 
+      bool empty = true;
       int min_lsb = 0x7FFF;
       int min_rsb = 0x7FFF;
       int max_extent = -0x7FFF;
@@ -125,9 +126,10 @@
         int lsb = _.second.second;
         max_adv = hb_max (max_adv, adv);
 
-        if (bounds_map->has (gid))
+        if (bounds_vec[gid] != 0xFFFFFFFF)
         {
-          unsigned bound_width = bounds_map->get (gid);
+	  empty = false;
+          unsigned bound_width = bounds_vec[gid];
           int rsb = adv - lsb - bound_width;
           int extent = lsb + bound_width;
           min_lsb = hb_min (min_lsb, lsb);
@@ -137,7 +139,7 @@
       }
 
       table->advanceMax = max_adv;
-      if (!bounds_map->is_empty ())
+      if (!empty)
       {
         table->minLeadingBearing = min_lsb;
         table->minTrailingBearing = min_rsb;
@@ -156,32 +158,31 @@
 	   hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_serialize_context_t *c,
 		  Iterator it,
-		  unsigned num_long_metrics)
+		  const hb_vector_t<hb_codepoint_pair_t> new_to_old_gid_list,
+		  unsigned num_long_metrics,
+                  unsigned total_num_metrics)
   {
-    unsigned idx = 0;
-    for (auto _ : it)
+    LongMetric* long_metrics = c->allocate_size<LongMetric> (num_long_metrics * LongMetric::static_size);
+    FWORD* short_metrics = c->allocate_size<FWORD> ((total_num_metrics - num_long_metrics) * FWORD::static_size);
+    if (!long_metrics || !short_metrics) return;
+
+    short_metrics -= num_long_metrics;
+
+    for (auto _ : new_to_old_gid_list)
     {
-      if (idx < num_long_metrics)
+      hb_codepoint_t gid = _.first;
+      auto mtx = *it++;
+
+      if (gid < num_long_metrics)
       {
-	LongMetric lm;
-	lm.advance = _.first;
-	lm.sb = _.second;
-	if (unlikely (!c->embed<LongMetric> (&lm))) return;
+	LongMetric& lm = long_metrics[gid];
+	lm.advance = mtx.first;
+	lm.sb = mtx.second;
       }
-      else if (idx < 0x10000u)
-      {
-	FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
-	if (unlikely (!sb)) return;
-	*sb = _.second;
-      }
+      else if (gid < 0x10000u)
+        short_metrics[gid] = mtx.second;
       else
-      {
-        // TODO: This does not do tail optimization.
-	UFWORD *adv = c->allocate_size<UFWORD> (UFWORD::static_size);
-	if (unlikely (!adv)) return;
-	*adv = _.first;
-      }
-      idx++;
+        ((UFWORD*) short_metrics)[gid] = mtx.first;
     }
   }
 
@@ -189,8 +190,7 @@
   {
     TRACE_SUBSET (this);
 
-    T *table_prime = c->serializer->start_embed <T> ();
-    if (unlikely (!table_prime)) return_trace (false);
+    auto *table_prime = c->serializer->start_embed <T> ();
 
     accelerator_t _mtx (c->plan->source);
     unsigned num_long_metrics;
@@ -209,24 +209,29 @@
     }
 
     auto it =
-    + hb_range (c->plan->num_output_glyphs ())
-    | hb_map ([c, &_mtx, mtx_map] (unsigned _)
+    + hb_iter (c->plan->new_to_old_gid_list)
+    | hb_map ([c, &_mtx, mtx_map] (hb_codepoint_pair_t _)
 	      {
-		if (!mtx_map->has (_))
+		hb_codepoint_t new_gid = _.first;
+		hb_codepoint_t old_gid = _.second;
+
+		hb_pair_t<unsigned, int> *v = nullptr;
+		if (!mtx_map->has (new_gid, &v))
 		{
-		  hb_codepoint_t old_gid;
-		  if (!c->plan->old_gid_for_new_gid (_, &old_gid))
-		    return hb_pair (0u, 0);
 		  int lsb = 0;
 		  if (!_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
 		    (void) _glyf_get_leading_bearing_without_var_unscaled (c->plan->source, old_gid, !T::is_horizontal, &lsb);
 		  return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
 		}
-		return mtx_map->get (_);
+		return *v;
 	      })
     ;
 
-    table_prime->serialize (c->serializer, it, num_long_metrics);
+    table_prime->serialize (c->serializer,
+			    it,
+			    c->plan->new_to_old_gid_list,
+			    num_long_metrics,
+			    c->plan->num_output_glyphs ());
 
     if (unlikely (c->serializer->in_error ()))
       return_trace (false);
@@ -233,7 +238,7 @@
 
     // Amend header num hmetrics
     if (unlikely (!subset_update_header (c, num_long_metrics, mtx_map,
-                                         T::is_horizontal ? &c->plan->bounds_width_map : &c->plan->bounds_height_map)))
+                                         T::is_horizontal ? c->plan->bounds_width_vec : c->plan->bounds_height_vec)))
       return_trace (false);
 
     return_trace (true);

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -170,8 +170,8 @@
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-			  minCoord.sanitize (c, this) &&
-			  maxCoord.sanitize (c, this)));
+			  minCoord.sanitize (c, base) &&
+			  maxCoord.sanitize (c, base)));
   }
 
   protected:
@@ -187,7 +187,6 @@
 				 * of MinMax table (may be NULL) */
   public:
   DEFINE_SIZE_STATIC (8);
-
 };
 
 struct MinMax
@@ -274,7 +273,7 @@
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-			  minMax.sanitize (c, this)));
+			  minMax.sanitize (c, base)));
   }
 
   protected:
@@ -297,7 +296,8 @@
   const BaseCoord &get_base_coord (int baseline_tag_index) const
   { return (this+baseValues).get_base_coord (baseline_tag_index); }
 
-  bool has_data () const { return baseValues; }
+  bool has_values () const { return baseValues; }
+  bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -383,7 +383,7 @@
 		     const BaseCoord **coord) const
   {
     const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
-    if (!base_script.has_data ())
+    if (!base_script.has_values ())
     {
       *coord = nullptr;
       return false;
@@ -410,7 +410,7 @@
 		    const BaseCoord **max_coord) const
   {
     const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
-    if (!base_script.has_data ())
+    if (!base_script.has_min_max ())
     {
       *min_coord = *max_coord = nullptr;
       return false;
@@ -425,8 +425,8 @@
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-			  (this+baseTagList).sanitize (c) &&
-			  (this+baseScriptList).sanitize (c)));
+			  baseTagList.sanitize (c, this) &&
+			  baseScriptList.sanitize (c, this)));
   }
 
   protected:
@@ -473,7 +473,6 @@
     return true;
   }
 
-  /* TODO: Expose this separately sometime? */
   bool get_min_max (hb_font_t      *font,
 		    hb_direction_t  direction,
 		    hb_tag_t        script_tag,
@@ -480,7 +479,7 @@
 		    hb_tag_t        language_tag,
 		    hb_tag_t        feature_tag,
 		    hb_position_t  *min,
-		    hb_position_t  *max)
+		    hb_position_t  *max) const
   {
     const BaseCoord *min_coord, *max_coord;
     if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag,

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -55,19 +55,22 @@
     hb_serialize_context_t *c,
     const hb_set_t &klasses,
     bool use_class_zero,
-    hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+    hb_sorted_vector_t<hb_codepoint_pair_t> &glyph_and_klass, /* IN/OUT */
     hb_map_t *klass_map /*IN/OUT*/);
 
 struct hb_collect_feature_substitutes_with_var_context_t
 {
   const hb_map_t *axes_index_tag_map;
-  const hb_hashmap_t<hb_tag_t, int> *axes_location;
+  const hb_hashmap_t<hb_tag_t, Triple> *axes_location;
   hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map;
   hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
+  bool& insert_catch_all_feature_variation_record;
 
   // not stored in subset_plan
   hb_set_t *feature_indices;
   bool apply;
+  bool variation_applied;
+  bool universal;
   unsigned cur_record_idx;
   hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map;
 };
@@ -807,7 +810,7 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
     out->featureParams.serialize_subset (c, featureParams, this, tag);
 
@@ -981,7 +984,7 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
     + hb_enumerate (*this)
     | hb_filter (l->feature_index_map, hb_first)
@@ -1078,7 +1081,7 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
     const uint32_t *v;
     out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
@@ -1188,7 +1191,7 @@
       return false;
 
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
     bool defaultLang = false;
     if (has_default_lang_sys ())
@@ -1247,7 +1250,7 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
     for (auto _ : + hb_enumerate (*this))
     {
@@ -1367,7 +1370,7 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
     out->lookupType = lookupType;
     out->lookupFlag = lookupFlag;
 
@@ -1456,7 +1459,7 @@
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (this);
-    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
     + hb_enumerate (*this)
     | hb_filter (l->lookup_index_map, hb_first)
@@ -1482,7 +1485,7 @@
 static bool ClassDef_remap_and_serialize (hb_serialize_context_t *c,
 					  const hb_set_t &klasses,
                                           bool use_class_zero,
-                                          hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+                                          hb_sorted_vector_t<hb_codepoint_pair_t> &glyph_and_klass, /* IN/OUT */
 					  hb_map_t *klass_map /*IN/OUT*/)
 {
   if (!klass_map)
@@ -1573,7 +1576,7 @@
     TRACE_SUBSET (this);
     const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
 
-    hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
+    hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass;
     hb_set_t orig_klasses;
 
     hb_codepoint_t start = startGlyph;
@@ -1592,10 +1595,13 @@
       orig_klasses.add (klass);
     }
 
-    unsigned glyph_count = glyph_filter
-                           ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter))
-                           : glyph_map.get_population ();
-    use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+    if (use_class_zero)
+    {
+      unsigned glyph_count = glyph_filter
+			     ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter))
+			     : glyph_map.get_population ();
+      use_class_zero = glyph_count <= glyph_and_klass.length;
+    }
     if (!ClassDef_remap_and_serialize (c->serializer,
                                        orig_klasses,
                                        use_class_zero,
@@ -1830,7 +1836,7 @@
     const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
     const hb_set_t &glyph_set = *c->plan->glyphset_gsub ();
 
-    hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
+    hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass;
     hb_set_t orig_klasses;
 
     if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2
@@ -1916,7 +1922,7 @@
   {
     if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
     {
-      for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+      for (auto g : *glyphs)
         if (get_class (g))
 	  return true;
       return false;
@@ -1976,8 +1982,7 @@
     unsigned count = rangeRecord.len;
     if (count > glyphs->get_population () * hb_bit_storage (count) * 8)
     {
-      for (hb_codepoint_t g = HB_SET_VALUE_INVALID;
-	   glyphs->next (&g);)
+      for (auto g : *glyphs)
       {
         unsigned i;
         if (rangeRecord.as_array ().bfind (g, &i) &&
@@ -2377,7 +2382,7 @@
     return_trace (c->check_struct (this) && axesZ.sanitize (c, axisCount * regionCount));
   }
 
-  bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_bimap_t &region_map)
+  bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_inc_bimap_t &region_map)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (this))) return_trace (false);
@@ -2494,7 +2499,7 @@
   bool serialize (hb_serialize_context_t *c,
 		  const VarData *src,
 		  const hb_inc_bimap_t &inner_map,
-		  const hb_bimap_t &region_map)
+		  const hb_inc_bimap_t &region_map)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (this))) return_trace (false);
@@ -2905,9 +2910,9 @@
 enum Cond_with_Var_flag_t
 {
   KEEP_COND_WITH_VAR = 0,
-  DROP_COND_WITH_VAR = 1,
-  DROP_RECORD_WITH_VAR = 2,
-  MEM_ERR_WITH_VAR = 3,
+  KEEP_RECORD_WITH_VAR = 1,
+  DROP_COND_WITH_VAR = 2,
+  DROP_RECORD_WITH_VAR = 3,
 };
 
 struct ConditionFormat1
@@ -2940,29 +2945,42 @@
 
     hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
 
-    //axis not pinned, keep the condition
-    if (!c->axes_location->has (axis_tag))
+    Triple axis_range (-1.f, 0.f, 1.f);
+    if (c->axes_location->has (axis_tag))
+      axis_range = c->axes_location->get (axis_tag);
+
+    int axis_min_val = axis_range.minimum;
+    int axis_default_val = axis_range.middle;
+    int axis_max_val = axis_range.maximum;
+
+    int16_t filter_min_val = filterRangeMinValue.to_int ();
+    int16_t filter_max_val = filterRangeMaxValue.to_int ();
+
+    if (axis_default_val < filter_min_val ||
+        axis_default_val > filter_max_val)
+      c->apply = false;
+
+    //condition not met, drop the entire record
+    if (axis_min_val > filter_max_val || axis_max_val < filter_min_val ||
+        filter_min_val > filter_max_val)
+      return DROP_RECORD_WITH_VAR;
+
+    //condition met and axis pinned, drop the condition
+    if (c->axes_location->has (axis_tag) &&
+        c->axes_location->get (axis_tag).is_point ())
+      return DROP_COND_WITH_VAR;
+
+    if (filter_max_val != axis_max_val || filter_min_val != axis_min_val)
     {
       // add axisIndex->value into the hashmap so we can check if the record is
       // unique with variations
-      int16_t min_val = filterRangeMinValue.to_int ();
-      int16_t max_val = filterRangeMaxValue.to_int ();
-      hb_codepoint_t val = (max_val << 16) + min_val;
+      hb_codepoint_t val = (filter_max_val << 16) + filter_min_val;
 
       condition_map->set (axisIndex, val);
       return KEEP_COND_WITH_VAR;
     }
 
-    //axis pinned, check if condition is met
-    //TODO: add check for axis Ranges
-    int v = c->axes_location->get (axis_tag);
-
-    //condition not met, drop the entire record
-    if (v < filterRangeMinValue.to_int () || v > filterRangeMaxValue.to_int ())
-      return DROP_RECORD_WITH_VAR;
-
-    //axis pinned and condition met, drop the condition
-    return DROP_COND_WITH_VAR;
+    return KEEP_RECORD_WITH_VAR;
   }
 
   bool evaluate (const int *coords, unsigned int coord_len) const
@@ -3001,7 +3019,7 @@
   {
     switch (u.format) {
     case 1: return u.format1.keep_with_variations (c, condition_map);
-    default:return KEEP_COND_WITH_VAR;
+    default: c->apply = false; return KEEP_COND_WITH_VAR;
     }
   }
 
@@ -3046,45 +3064,50 @@
     return true;
   }
 
-  Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+  void keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
   {
     hb_map_t *condition_map = hb_map_create ();
-    if (unlikely (!condition_map)) return MEM_ERR_WITH_VAR;
+    if (unlikely (!condition_map)) return;
     hb::shared_ptr<hb_map_t> p {condition_map};
 
     hb_set_t *cond_set = hb_set_create ();
-    if (unlikely (!cond_set)) return MEM_ERR_WITH_VAR;
+    if (unlikely (!cond_set)) return;
     hb::shared_ptr<hb_set_t> s {cond_set};
 
+    c->apply = true;
+    bool should_keep = false;
     unsigned num_kept_cond = 0, cond_idx = 0;
     for (const auto& offset : conditions)
     {
       Cond_with_Var_flag_t ret = (this+offset).keep_with_variations (c, condition_map);
-      // one condition is not met, drop the entire record
+      // condition is not met or condition out of range, drop the entire record
       if (ret == DROP_RECORD_WITH_VAR)
-        return DROP_RECORD_WITH_VAR;
+        return;
 
-      // axis not pinned, keep this condition
       if (ret == KEEP_COND_WITH_VAR)
       {
+        should_keep = true;
         cond_set->add (cond_idx);
         num_kept_cond++;
       }
+
+      if (ret == KEEP_RECORD_WITH_VAR)
+        should_keep = true;
+
       cond_idx++;
     }
 
-    // all conditions met
-    if (num_kept_cond == 0) return DROP_COND_WITH_VAR;
+    if (!should_keep) return;
 
     //check if condition_set is unique with variations
     if (c->conditionset_map->has (p))
       //duplicate found, drop the entire record
-      return DROP_RECORD_WITH_VAR;
+      return;
 
     c->conditionset_map->set (p, 1);
     c->record_cond_idx_map->set (c->cur_record_idx, s);
-
-    return KEEP_COND_WITH_VAR;
+    if (should_keep && num_kept_cond == 0)
+      c->universal = true;
   }
 
   bool subset (hb_subset_context_t *c,
@@ -3289,12 +3312,11 @@
   void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
                                                     const void *base) const
   {
-    // ret == 1, all conditions met
-    if ((base+conditions).keep_with_variations (c) == DROP_COND_WITH_VAR &&
-        c->apply)
+    (base+conditions).keep_with_variations (c);
+    if (c->apply && !c->variation_applied)
     {
       (base+substitutions).collect_feature_substitutes_with_variations (c);
-      c->apply = false; // set variations only once
+      c->variation_applied = true; // set variations only once
     }
   }
 
@@ -3361,7 +3383,12 @@
     {
       c->cur_record_idx = i;
       varRecords[i].collect_feature_substitutes_with_variations (c, this);
+      if (c->universal)
+        break;
     }
+    if (c->variation_applied && !c->universal &&
+        !c->record_cond_idx_map->is_empty ())
+      c->insert_catch_all_feature_variation_record = true;
   }
 
   FeatureVariations* copy (hb_serialize_context_t *c) const

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -143,9 +143,12 @@
     return active_glyphs_stack.tail ();
   }
 
-  hb_set_t& push_cur_active_glyphs ()
+  hb_set_t* push_cur_active_glyphs ()
   {
-    return *active_glyphs_stack.push ();
+    hb_set_t *s = active_glyphs_stack.push ();
+    if (unlikely (active_glyphs_stack.in_error ()))
+      return nullptr;
+    return s;
   }
 
   bool pop_cur_done_glyphs ()
@@ -427,6 +430,9 @@
       MATCH_MAYBE
     };
 
+#ifndef HB_OPTIMIZE_SIZE
+    HB_ALWAYS_INLINE
+#endif
     may_match_t may_match (hb_glyph_info_t &info,
 			   hb_codepoint_t glyph_data) const
     {
@@ -446,6 +452,9 @@
       SKIP_MAYBE
     };
 
+#ifndef HB_OPTIMIZE_SIZE
+    HB_ALWAYS_INLINE
+#endif
     may_skip_t may_skip (const hb_ot_apply_context_t *c,
 			 const hb_glyph_info_t       &info) const
     {
@@ -516,6 +525,9 @@
     }
 #endif
 
+#ifndef HB_OPTIMIZE_SIZE
+    HB_ALWAYS_INLINE
+#endif
     void reset (unsigned int start_index_,
 		unsigned int num_items_)
     {
@@ -525,6 +537,9 @@
       matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
     }
 
+#ifndef HB_OPTIMIZE_SIZE
+    HB_ALWAYS_INLINE
+#endif
     void reset_fast (unsigned int start_index_,
 		     unsigned int num_items_)
     {
@@ -540,6 +555,9 @@
     }
 
     matcher_t::may_skip_t
+#ifndef HB_OPTIMIZE_SIZE
+    HB_ALWAYS_INLINE
+#endif
     may_skip (const hb_glyph_info_t &info) const
     { return matcher.may_skip (c, info); }
 
@@ -549,6 +567,9 @@
       SKIP
     };
 
+#ifndef HB_OPTIMIZE_SIZE
+    HB_ALWAYS_INLINE
+#endif
     match_t match (hb_glyph_info_t &info)
     {
       matcher_t::may_skip_t skip = matcher.may_skip (c, info);
@@ -567,6 +588,9 @@
       return SKIP;
   }
 
+#ifndef HB_OPTIMIZE_SIZE
+    HB_ALWAYS_INLINE
+#endif
     bool next (unsigned *unsafe_to = nullptr)
     {
       assert (num_items > 0);
@@ -600,6 +624,9 @@
         *unsafe_to = end;
       return false;
     }
+#ifndef HB_OPTIMIZE_SIZE
+    HB_ALWAYS_INLINE
+#endif
     bool prev (unsigned *unsafe_from = nullptr)
     {
       assert (num_items > 0);
@@ -703,6 +730,7 @@
   hb_font_t *font;
   hb_face_t *face;
   hb_buffer_t *buffer;
+  hb_sanitize_context_t sanitizer;
   recurse_func_t recurse_func = nullptr;
   const GDEF &gdef;
   const GDEF::accelerator_t &gdef_accel;
@@ -729,9 +757,11 @@
 
   hb_ot_apply_context_t (unsigned int table_index_,
 			 hb_font_t *font_,
-			 hb_buffer_t *buffer_) :
+			 hb_buffer_t *buffer_,
+			 hb_blob_t *table_blob_) :
 			table_index (table_index_),
 			font (font_), face (font->face), buffer (buffer_),
+			sanitizer (table_blob_),
 			gdef (
 #ifndef HB_NO_OT_LAYOUT
 			      *face->table.GDEF->table
@@ -808,6 +838,9 @@
     return true;
   }
 
+#ifndef HB_OPTIMIZE_SIZE
+  HB_ALWAYS_INLINE
+#endif
   bool check_glyph_property (const hb_glyph_info_t *info,
 			     unsigned int  match_props) const
   {
@@ -1213,14 +1246,17 @@
   return true;
 }
 template <typename HBUINT>
-static inline bool match_input (hb_ot_apply_context_t *c,
-				unsigned int count, /* Including the first glyph (not matched) */
-				const HBUINT input[], /* Array of input values--start with second glyph */
-				match_func_t match_func,
-				const void *match_data,
-				unsigned int *end_position,
-				unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
-				unsigned int *p_total_component_count = nullptr)
+#ifndef HB_OPTIMIZE_SIZE
+HB_ALWAYS_INLINE
+#endif
+static bool match_input (hb_ot_apply_context_t *c,
+			 unsigned int count, /* Including the first glyph (not matched) */
+			 const HBUINT input[], /* Array of input values--start with second glyph */
+			 match_func_t match_func,
+			 const void *match_data,
+			 unsigned int *end_position,
+			 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
+			 unsigned int *p_total_component_count = nullptr)
 {
   TRACE_APPLY (nullptr);
 
@@ -1456,12 +1492,15 @@
 }
 
 template <typename HBUINT>
-static inline bool match_backtrack (hb_ot_apply_context_t *c,
-				    unsigned int count,
-				    const HBUINT backtrack[],
-				    match_func_t match_func,
-				    const void *match_data,
-				    unsigned int *match_start)
+#ifndef HB_OPTIMIZE_SIZE
+HB_ALWAYS_INLINE
+#endif
+static bool match_backtrack (hb_ot_apply_context_t *c,
+			     unsigned int count,
+			     const HBUINT backtrack[],
+			     match_func_t match_func,
+			     const void *match_data,
+			     unsigned int *match_start)
 {
   TRACE_APPLY (nullptr);
 
@@ -1485,13 +1524,16 @@
 }
 
 template <typename HBUINT>
-static inline bool match_lookahead (hb_ot_apply_context_t *c,
-				    unsigned int count,
-				    const HBUINT lookahead[],
-				    match_func_t match_func,
-				    const void *match_data,
-				    unsigned int start_index,
-				    unsigned int *end_index)
+#ifndef HB_OPTIMIZE_SIZE
+HB_ALWAYS_INLINE
+#endif
+static bool match_lookahead (hb_ot_apply_context_t *c,
+			     unsigned int count,
+			     const HBUINT lookahead[],
+			     match_func_t match_func,
+			     const void *match_data,
+			     unsigned int start_index,
+			     unsigned int *end_index)
 {
   TRACE_APPLY (nullptr);
 
@@ -1615,10 +1657,13 @@
     }
 
     covered_seq_indicies.add (seqIndex);
+    hb_set_t *cur_active_glyphs = c->push_cur_active_glyphs ();
+    if (unlikely (!cur_active_glyphs))
+      return;
     if (has_pos_glyphs) {
-      c->push_cur_active_glyphs () = std::move (pos_glyphs);
+      *cur_active_glyphs = std::move (pos_glyphs);
     } else {
-      c->push_cur_active_glyphs ().set (*c->glyphs);
+      *cur_active_glyphs = *c->glyphs;
     }
 
     unsigned endIndex = inputCount;
@@ -2001,8 +2046,7 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (inputCount.sanitize (c) &&
-		  lookupCount.sanitize (c) &&
+    return_trace (c->check_struct (this) &&
 		  c->check_range (inputZ.arrayZ,
 				  inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
 				  LookupRecord::static_size * lookupCount));
@@ -2021,6 +2065,7 @@
 					 * design order */
   public:
   DEFINE_SIZE_ARRAY (4, inputZ);
+  DEFINE_SIZE_MAX (65536 * (Types::HBUINT::static_size + LookupRecord::static_size));
 };
 
 template <typename Types>
@@ -2168,8 +2213,9 @@
 
   void closure (hb_closure_context_t *c) const
   {
-    hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
-    get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs);
+    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+    if (unlikely (!cur_active_glyphs)) return;
+    get_coverage ().intersect_set (c->previous_parent_active_glyphs (), *cur_active_glyphs);
 
     struct ContextClosureLookupContext lookup_context = {
       {intersects_glyph, intersected_glyph},
@@ -2338,9 +2384,10 @@
     if (!(this+coverage).intersects (c->glyphs))
       return;
 
-    hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+    if (unlikely (!cur_active_glyphs)) return;
     get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
-                                                 cur_active_glyphs);
+				   *cur_active_glyphs);
 
     const ClassDef &class_def = this+classDef;
 
@@ -2583,11 +2630,11 @@
     if (!(this+coverageZ[0]).intersects (c->glyphs))
       return;
 
-    hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+    if (unlikely (!cur_active_glyphs)) return;
     get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
-                                                 cur_active_glyphs);
+				   *cur_active_glyphs);
 
-
     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
     struct ContextClosureLookupContext lookup_context = {
       {intersects_coverage, intersected_coverage_glyphs},
@@ -2687,14 +2734,14 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!c->check_struct (this)) return_trace (false);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
     unsigned int count = glyphCount;
-    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
-    if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false);
+    if (unlikely (!count)) return_trace (false); /* We want to access coverageZ[0] freely. */
+    if (unlikely (!c->check_array (coverageZ.arrayZ, count))) return_trace (false);
     for (unsigned int i = 0; i < count; i++)
-      if (!coverageZ[i].sanitize (c, this)) return_trace (false);
+      if (unlikely (!coverageZ[i].sanitize (c, this))) return_trace (false);
     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
-    return_trace (c->check_array (lookupRecord, lookupCount));
+    return_trace (likely (c->check_array (lookupRecord, lookupCount)));
   }
 
   protected:
@@ -3014,8 +3061,6 @@
 		  const hb_map_t *lookahead_map = nullptr) const
   {
     TRACE_SERIALIZE (this);
-    auto *out = c->start_embed (this);
-    if (unlikely (!out)) return_trace (false);
 
     const hb_map_t *mapping = backtrack_map;
     serialize_array (c, backtrack.len, + backtrack.iter ()
@@ -3077,13 +3122,14 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c)) return_trace (false);
+    /* Hyper-optimized sanitized because this is really hot. */
+    if (unlikely (!backtrack.len.sanitize (c))) return_trace (false);
     const auto &input = StructAfter<decltype (inputX)> (backtrack);
-    if (!input.sanitize (c)) return_trace (false);
+    if (unlikely (!input.lenP1.sanitize (c))) return_trace (false);
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
-    if (!lookahead.sanitize (c)) return_trace (false);
+    if (unlikely (!lookahead.len.sanitize (c))) return_trace (false);
     const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
-    return_trace (lookup.sanitize (c));
+    return_trace (likely (lookup.sanitize (c)));
   }
 
   protected:
@@ -3091,7 +3137,7 @@
 		backtrack;		/* Array of backtracking values
 					 * (to be matched before the input
 					 * sequence) */
-  HeadlessArrayOf<typename Types::HBUINT>
+  HeadlessArray16Of<typename Types::HBUINT>
 		inputX;			/* Array of input values (start with
 					 * second glyph) */
   Array16Of<typename Types::HBUINT>
@@ -3102,6 +3148,7 @@
 					 * design order) */
   public:
   DEFINE_SIZE_MIN (8);
+  DEFINE_SIZE_MAX (65536 * (3 * Types::HBUINT::static_size + LookupRecord::static_size));
 };
 
 template <typename Types>
@@ -3251,9 +3298,10 @@
 
   void closure (hb_closure_context_t *c) const
   {
-    hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+    if (unlikely (!cur_active_glyphs)) return;
     get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
-                                                 cur_active_glyphs);
+				   *cur_active_glyphs);
 
     struct ChainContextClosureLookupContext lookup_context = {
       {intersects_glyph, intersected_glyph},
@@ -3423,11 +3471,11 @@
     if (!(this+coverage).intersects (c->glyphs))
       return;
 
-    hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+    if (unlikely (!cur_active_glyphs)) return;
     get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
-                                                 cur_active_glyphs);
+				   *cur_active_glyphs);
 
-
     const ClassDef &backtrack_class_def = this+backtrackClassDef;
     const ClassDef &input_class_def = this+inputClassDef;
     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
@@ -3727,11 +3775,12 @@
     if (!(this+input[0]).intersects (c->glyphs))
       return;
 
-    hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+    if (unlikely (!cur_active_glyphs))
+      return;
     get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
-                                                 cur_active_glyphs);
+				   *cur_active_glyphs);
 
-
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
     const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
     struct ChainContextClosureLookupContext lookup_context = {
@@ -3849,8 +3898,6 @@
   {
     TRACE_SUBSET (this);
 
-    auto *out = c->serializer->start_embed (this);
-    if (unlikely (!out)) return_trace (false);
     if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
 
     if (!serialize_coverage_offsets (c, backtrack.iter (), this))
@@ -3877,14 +3924,14 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c, this)) return_trace (false);
+    if (unlikely (!backtrack.sanitize (c, this))) return_trace (false);
     const auto &input = StructAfter<decltype (inputX)> (backtrack);
-    if (!input.sanitize (c, this)) return_trace (false);
-    if (!input.len) return_trace (false); /* To be consistent with Context. */
+    if (unlikely (!input.sanitize (c, this))) return_trace (false);
+    if (unlikely (!input.len)) return_trace (false); /* To be consistent with Context. */
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
-    if (!lookahead.sanitize (c, this)) return_trace (false);
+    if (unlikely (!lookahead.sanitize (c, this))) return_trace (false);
     const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
-    return_trace (lookup.sanitize (c));
+    return_trace (likely (lookup.sanitize (c)));
   }
 
   protected:
@@ -3974,7 +4021,7 @@
     TRACE_SUBSET (this);
 
     auto *out = c->serializer->start_embed (this);
-    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
     out->format = format;
     out->extensionLookupType = extensionLookupType;
@@ -4503,7 +4550,10 @@
   {
     accelerator_t (hb_face_t *face)
     {
-      this->table = hb_sanitize_context_t ().reference_table<T> (face);
+      hb_sanitize_context_t sc;
+      sc.lazy_some_gpos = true;
+      this->table = sc.reference_table<T> (face);
+
       if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
       {
 	hb_blob_destroy (this->table.get_blob ());
@@ -4528,6 +4578,8 @@
       this->table.destroy ();
     }
 
+    hb_blob_t *get_blob () const { return table.get_blob (); }
+
     hb_ot_layout_lookup_accelerator_t *get_accel (unsigned lookup_index) const
     {
       if (unlikely (lookup_index >= lookup_count)) return nullptr;

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1316,8 +1316,7 @@
   hb_set_t feature_indexes;
   hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
 
-  for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
-       hb_set_next (&feature_indexes, &feature_index);)
+  for (auto feature_index : feature_indexes)
     g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
 
   g.feature_variation_collect_lookups (&feature_indexes, nullptr, lookup_indexes);
@@ -1570,7 +1569,7 @@
     glyphs_length = glyphs->get_population ();
     if (lookups)
     {
-      for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);)
+      for (auto lookup_index : *lookups)
 	gsub.get_lookup (lookup_index).closure (&c, lookup_index);
     }
     else
@@ -1953,7 +1952,7 @@
 {
   const unsigned int table_index = proxy.table_index;
   unsigned int i = 0;
-  OT::hb_ot_apply_context_t c (table_index, font, buffer);
+  OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob ());
   c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func<OT::hb_ot_apply_context_t>);
 
   for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++)
@@ -2011,10 +2010,10 @@
 {
   GSUBProxy proxy (font->face);
   if (buffer->messaging () &&
-      !buffer->message (font, "start table GSUB")) return;
+      !buffer->message (font, "start table GSUB script tag '%c%c%c%c'", HB_UNTAG (chosen_script[0]))) return;
   apply (proxy, plan, font, buffer);
   if (buffer->messaging ())
-    (void) buffer->message (font, "end table GSUB");
+    (void) buffer->message (font, "end table GSUB script tag '%c%c%c%c'", HB_UNTAG (chosen_script[0]));
 }
 
 void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
@@ -2021,10 +2020,10 @@
 {
   GPOSProxy proxy (font->face);
   if (buffer->messaging () &&
-      !buffer->message (font, "start table GPOS")) return;
+      !buffer->message (font, "start table GPOS script tag '%c%c%c%c'", HB_UNTAG (chosen_script[1]))) return;
   apply (proxy, plan, font, buffer);
   if (buffer->messaging ())
-    (void) buffer->message (font, "end table GPOS");
+    (void) buffer->message (font, "end table GPOS script tag '%c%c%c%c'", HB_UNTAG (chosen_script[1]));
 }
 
 void
@@ -2036,7 +2035,113 @@
 }
 
 #ifndef HB_NO_BASE
+
+static void
+choose_base_tags (hb_script_t    script,
+		  hb_language_t  language,
+		  hb_tag_t      *script_tag,
+		  hb_tag_t      *language_tag)
+{
+  hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
+  unsigned script_count = ARRAY_LENGTH (script_tags);
+
+  hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
+  unsigned language_count = ARRAY_LENGTH (language_tags);
+
+  hb_ot_tags_from_script_and_language (script, language,
+				       &script_count, script_tags,
+				       &language_count, language_tags);
+
+  *script_tag = script_count ? script_tags[script_count - 1] : HB_OT_TAG_DEFAULT_SCRIPT;
+  *language_tag = language_count ? language_tags[language_count - 1] : HB_OT_TAG_DEFAULT_LANGUAGE;
+}
+
 /**
+ * hb_ot_layout_get_font_extents:
+ * @font: a font
+ * @direction: text direction.
+ * @script_tag:  script tag.
+ * @language_tag: language tag.
+ * @extents: (out) (nullable): font extents if found.
+ *
+ * Fetches script/language-specific font extents.  These values are
+ * looked up in the `BASE` table's `MinMax` records.
+ *
+ * If no such extents are found, the default extents for the font are
+ * fetched. As such, the return value of this function can for the
+ * most part be ignored.  Note that the per-script/language extents
+ * do not have a line-gap value, and the line-gap is set to zero in
+ * that case.
+ *
+ * Return value: `true` if found script/language-specific font extents.
+ *
+ * Since: 8.0.0
+ **/
+hb_bool_t
+hb_ot_layout_get_font_extents (hb_font_t         *font,
+			       hb_direction_t     direction,
+			       hb_tag_t           script_tag,
+			       hb_tag_t           language_tag,
+			       hb_font_extents_t *extents)
+{
+  hb_position_t min, max;
+  if (font->face->table.BASE->get_min_max (font, direction, script_tag, language_tag, HB_TAG_NONE,
+					   &min, &max))
+  {
+    if (extents)
+    {
+      extents->ascender  = max;
+      extents->descender = min;
+      extents->line_gap  = 0;
+    }
+    return true;
+  }
+
+  hb_font_get_extents_for_direction (font, direction, extents);
+  return false;
+}
+
+/**
+ * hb_ot_layout_get_font_extents2:
+ * @font: a font
+ * @direction: text direction.
+ * @script:  script.
+ * @language: (nullable): language.
+ * @extents: (out) (nullable): font extents if found.
+ *
+ * Fetches script/language-specific font extents.  These values are
+ * looked up in the `BASE` table's `MinMax` records.
+ *
+ * If no such extents are found, the default extents for the font are
+ * fetched. As such, the return value of this function can for the
+ * most part be ignored.  Note that the per-script/language extents
+ * do not have a line-gap value, and the line-gap is set to zero in
+ * that case.
+ *
+ * This function is like hb_ot_layout_get_font_extents() but takes
+ * #hb_script_t and #hb_language_t instead of OpenType #hb_tag_t.
+ *
+ * Return value: `true` if found script/language-specific font extents.
+ *
+ * Since: 8.0.0
+ **/
+hb_bool_t
+hb_ot_layout_get_font_extents2 (hb_font_t         *font,
+				hb_direction_t     direction,
+				hb_script_t        script,
+				hb_language_t      language,
+				hb_font_extents_t *extents)
+{
+  hb_tag_t script_tag, language_tag;
+  choose_base_tags (script, language, &script_tag, &language_tag);
+  return hb_ot_layout_get_font_extents (font,
+					direction,
+					script_tag,
+					language_tag,
+					extents);
+}
+
+/**
  * hb_ot_layout_get_horizontal_baseline_tag_for_script:
  * @script: a script tag.
  *
@@ -2134,6 +2239,42 @@
 }
 
 /**
+ * hb_ot_layout_get_baseline2:
+ * @font: a font
+ * @baseline_tag: a baseline tag
+ * @direction: text direction.
+ * @script:  script.
+ * @language: (nullable): language, currently unused.
+ * @coord: (out) (nullable): baseline value if found.
+ *
+ * Fetches a baseline value from the face.
+ *
+ * This function is like hb_ot_layout_get_baseline() but takes
+ * #hb_script_t and #hb_language_t instead of OpenType #hb_tag_t.
+ *
+ * Return value: `true` if found baseline value in the font.
+ *
+ * Since: 8.0.0
+ **/
+hb_bool_t
+hb_ot_layout_get_baseline2 (hb_font_t                   *font,
+			    hb_ot_layout_baseline_tag_t  baseline_tag,
+			    hb_direction_t               direction,
+			    hb_script_t                  script,
+			    hb_language_t                language,
+			    hb_position_t               *coord        /* OUT.  May be NULL. */)
+{
+  hb_tag_t script_tag, language_tag;
+  choose_base_tags (script, language, &script_tag, &language_tag);
+  return hb_ot_layout_get_baseline (font,
+				    baseline_tag,
+				    direction,
+				    script_tag,
+				    language_tag,
+				    coord);
+}
+
+/**
  * hb_ot_layout_get_baseline_with_fallback:
  * @font: a font
  * @baseline_tag: a baseline tag
@@ -2355,6 +2496,41 @@
   }
 }
 
+/**
+ * hb_ot_layout_get_baseline_with_fallback2:
+ * @font: a font
+ * @baseline_tag: a baseline tag
+ * @direction: text direction.
+ * @script:  script.
+ * @language: (nullable): language, currently unused.
+ * @coord: (out): baseline value if found.
+ *
+ * Fetches a baseline value from the face, and synthesizes
+ * it if the font does not have it.
+ *
+ * This function is like hb_ot_layout_get_baseline_with_fallback() but takes
+ * #hb_script_t and #hb_language_t instead of OpenType #hb_tag_t.
+ *
+ * Since: 8.0.0
+ **/
+void
+hb_ot_layout_get_baseline_with_fallback2 (hb_font_t                   *font,
+					  hb_ot_layout_baseline_tag_t  baseline_tag,
+					  hb_direction_t               direction,
+					  hb_script_t                  script,
+					  hb_language_t                language,
+					  hb_position_t               *coord        /* OUT */)
+{
+  hb_tag_t script_tag, language_tag;
+  choose_base_tags (script, language, &script_tag, &language_tag);
+  hb_ot_layout_get_baseline_with_fallback (font,
+					   baseline_tag,
+					   direction,
+					   script_tag,
+					   language_tag,
+					   coord);
+}
+
 #endif
 
 
@@ -2451,9 +2627,10 @@
 				       hb_codepoint_t  glyph)
 {
   const OT::PosLookup &lookup = font->face->table.GPOS->table->get_lookup (lookup_index);
+  hb_blob_t *blob = font->face->table.GPOS->get_blob ();
   hb_glyph_position_t pos = {0};
   hb_position_single_dispatch_t c;
-  lookup.dispatch (&c, font, direction, glyph, pos);
+  lookup.dispatch (&c, font, blob, direction, glyph, pos);
   hb_position_t ret = 0;
   switch (direction)
   {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h	2023-07-09 05:55:34 UTC (rev 67588)
@@ -447,6 +447,20 @@
  * BASE
  */
 
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_font_extents (hb_font_t         *font,
+			       hb_direction_t     direction,
+			       hb_tag_t           script_tag,
+			       hb_tag_t           language_tag,
+			       hb_font_extents_t *extents);
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_font_extents2 (hb_font_t         *font,
+				hb_direction_t     direction,
+				hb_script_t        script,
+				hb_language_t      language,
+				hb_font_extents_t *extents);
+
 /**
  * hb_ot_layout_baseline_tag_t:
  * @HB_OT_LAYOUT_BASELINE_TAG_ROMAN: The baseline used by alphabetic scripts such as Latin, Cyrillic and Greek.
@@ -499,6 +513,14 @@
 			   hb_tag_t                     language_tag,
 			   hb_position_t               *coord        /* OUT.  May be NULL. */);
 
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_baseline2 (hb_font_t                   *font,
+			    hb_ot_layout_baseline_tag_t  baseline_tag,
+			    hb_direction_t               direction,
+			    hb_script_t                  script,
+			    hb_language_t                language,
+			    hb_position_t               *coord        /* OUT.  May be NULL. */);
+
 HB_EXTERN void
 hb_ot_layout_get_baseline_with_fallback (hb_font_t                   *font,
 					 hb_ot_layout_baseline_tag_t  baseline_tag,
@@ -507,6 +529,14 @@
 					 hb_tag_t                     language_tag,
 					 hb_position_t               *coord        /* OUT */);
 
+HB_EXTERN void
+hb_ot_layout_get_baseline_with_fallback2 (hb_font_t                   *font,
+					  hb_ot_layout_baseline_tag_t  baseline_tag,
+					  hb_direction_t               direction,
+					  hb_script_t                  script,
+					  hb_language_t                language,
+					  hb_position_t               *coord        /* OUT */);
+
 HB_END_DECLS
 
 #endif /* HB_OT_LAYOUT_H */

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -448,7 +448,7 @@
 static inline bool
 _hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
 {
-  return !!(info->lig_props() & IS_LIG_BASE);
+  return info->lig_props() & IS_LIG_BASE;
 }
 
 static inline unsigned int
@@ -496,37 +496,37 @@
 static inline bool
 _hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
 {
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
+  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
 }
 
 static inline bool
 _hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
 {
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
+  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
 }
 
 static inline bool
 _hb_glyph_info_is_mark (const hb_glyph_info_t *info)
 {
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
+  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK;
 }
 
 static inline bool
 _hb_glyph_info_substituted (const hb_glyph_info_t *info)
 {
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
+  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
 }
 
 static inline bool
 _hb_glyph_info_ligated (const hb_glyph_info_t *info)
 {
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
+  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
 }
 
 static inline bool
 _hb_glyph_info_multiplied (const hb_glyph_info_t *info)
 {
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
 }
 
 static inline bool

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -213,7 +213,8 @@
   /* Sort features and merge duplicates */
   if (feature_infos.length)
   {
-    feature_infos.qsort ();
+    if (!is_simple)
+      feature_infos.qsort ();
     auto *f = feature_infos.arrayZ;
     unsigned int j = 0;
     unsigned count = feature_infos.length;
@@ -314,8 +315,9 @@
     map->needs_fallback = !found;
   }
   //feature_infos.shrink (0); /* Done with these */
+  if (is_simple)
+    m.features.qsort ();
 
-
   add_gsub_pause (nullptr);
   add_gpos_pause (nullptr);
 
@@ -350,7 +352,7 @@
       }
 
       /* Sort lookups and merge duplicates */
-      if (last_num_lookups < lookups.length)
+      if (last_num_lookups + 1 < lookups.length)
       {
 	lookups.as_array ().sub_array (last_num_lookups, lookups.length - last_num_lookups).qsort ();
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -60,6 +60,13 @@
 
     int cmp (const hb_tag_t tag_) const
     { return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
+
+    HB_INTERNAL static int cmp (const void *pa, const void *pb)
+    {
+      const feature_map_t *a = (const feature_map_t *) pa;
+      const feature_map_t *b = (const feature_map_t *) pb;
+      return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0;
+    }
   };
 
   struct lookup_map_t {
@@ -273,6 +280,7 @@
 
   hb_face_t *face;
   hb_segment_properties_t props;
+  bool is_simple;
 
   hb_tag_t chosen_script[2];
   bool found_script[2];

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -73,7 +73,6 @@
   {
     TRACE_SERIALIZE (this);
     auto *out = c->start_embed (this);
-    if (unlikely (!out)) return_trace (nullptr);
 
     HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2);
     if (unlikely (!p)) return_trace (nullptr);
@@ -310,7 +309,6 @@
   {
     TRACE_SERIALIZE (this);
     auto *out = c->start_embed (this);
-    if (unlikely (!out)) return_trace (nullptr);
 
     if (unlikely (!c->embed (heightCount))) return_trace (nullptr);
 
@@ -572,6 +570,7 @@
 
     auto it =
     + hb_iter (this+extendedShapeCoverage)
+    | hb_take (c->plan->source->get_num_glyphs ())
     | hb_filter (glyphset)
     | hb_map_retains_sorting (glyph_map)
     ;
@@ -757,8 +756,6 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!out)) return_trace (false);
 
     if (!c->serializer->copy (italicsCorrection, this)) return_trace (false);
     if (!c->serializer->copy<HBUINT16> (partRecords.len)) return_trace (false);
@@ -945,13 +942,13 @@
     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
     if (!c->serializer->check_assign (out->minConnectorOverlap, minConnectorOverlap, HB_SERIALIZE_ERROR_INT_OVERFLOW))
       return_trace (false);
-    
+
     hb_sorted_vector_t<hb_codepoint_t> new_vert_coverage;
     hb_sorted_vector_t<hb_codepoint_t> new_hori_coverage;
     hb_set_t indices;
     collect_coverage_and_indices (new_vert_coverage, vertGlyphCoverage, 0, vertGlyphCount, indices, glyphset, glyph_map);
     collect_coverage_and_indices (new_hori_coverage, horizGlyphCoverage, vertGlyphCount, vertGlyphCount + horizGlyphCount, indices, glyphset, glyph_map);
-    
+
     if (!c->serializer->check_assign (out->vertGlyphCount, new_vert_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
       return_trace (false);
     if (!c->serializer->check_assign (out->horizGlyphCount, new_hori_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
@@ -963,10 +960,10 @@
       if (!o) return_trace (false);
       o->serialize_subset (c, glyphConstruction[i], this);
     }
-    
+
     if (new_vert_coverage)
       out->vertGlyphCoverage.serialize_serialize (c->serializer, new_vert_coverage.iter ());
-    
+
     if (new_hori_coverage)
     out->horizGlyphCoverage.serialize_serialize (c->serializer, new_hori_coverage.iter ());
     return_trace (true);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -249,7 +249,7 @@
     if (c->plan->user_axes_location.has (HB_TAG ('w','g','h','t')) &&
         !c->plan->pinned_at_default)
     {
-      float weight_class = c->plan->user_axes_location.get (HB_TAG ('w','g','h','t'));
+      float weight_class = c->plan->user_axes_location.get (HB_TAG ('w','g','h','t')).middle;
       if (!c->serializer->check_assign (os2_prime->usWeightClass,
                                         roundf (hb_clamp (weight_class, 1.0f, 1000.0f)),
                                         HB_SERIALIZE_ERROR_INT_OVERFLOW))
@@ -259,7 +259,7 @@
     if (c->plan->user_axes_location.has (HB_TAG ('w','d','t','h')) &&
         !c->plan->pinned_at_default)
     {
-      float width = c->plan->user_axes_location.get (HB_TAG ('w','d','t','h'));
+      float width = c->plan->user_axes_location.get (HB_TAG ('w','d','t','h')).middle;
       if (!c->serializer->check_assign (os2_prime->usWidthClass,
                                         roundf (map_wdth_to_widthclass (width)),
                                         HB_SERIALIZE_ERROR_INT_OVERFLOW))
@@ -287,8 +287,7 @@
     /* This block doesn't show up in profiles. If it ever did,
      * we can rewrite it to iterate over OS/2 ranges and use
      * set iteration to check if the range matches. */
-    for (hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-	 codepoints->next (&cp);)
+    for (auto cp : *codepoints)
     {
       unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
       if (bit < 128)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table-v2subset.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table-v2subset.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table-v2subset.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -79,6 +79,11 @@
   post::accelerator_t _post (c->plan->source);
 
   hb_hashmap_t<hb_bytes_t, uint32_t, true> glyph_name_to_new_index;
+
+  old_new_index_map.alloc (num_glyphs);
+  old_gid_new_index_map.alloc (num_glyphs);
+  glyph_name_to_new_index.alloc (num_glyphs);
+
   for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
   {
     hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
@@ -86,11 +91,12 @@
 
     unsigned new_index;
     const uint32_t *new_index2;
-    if (old_index <= 257) new_index = old_index;
+    if (old_index <= 257)
+      new_index = old_index;
     else if (old_new_index_map.has (old_index, &new_index2))
+      new_index = *new_index2;
+    else
     {
-      new_index = *new_index2;
-    } else {
       hb_bytes_t s = _post.find_glyph_name (old_gid);
       new_index = glyph_name_to_new_index.get (s);
       if (new_index == (unsigned)-1)

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -96,8 +96,7 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    post *post_prime = c->serializer->start_embed<post> ();
-    if (unlikely (!post_prime)) return_trace (false);
+    auto *post_prime = c->serializer->start_embed<post> ();
 
     bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
     if (!serialize (c->serializer, glyph_names))
@@ -117,7 +116,7 @@
     if (c->plan->user_axes_location.has (HB_TAG ('s','l','n','t')) &&
         !c->plan->pinned_at_default)
     {
-      float italic_angle = c->plan->user_axes_location.get (HB_TAG ('s','l','n','t'));
+      float italic_angle = c->plan->user_axes_location.get (HB_TAG ('s','l','n','t')).middle;
       italic_angle = hb_max (-90.f, hb_min (italic_angle, 90.f));
       post_prime->italicAngle.set_float (italic_angle);
     }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -313,6 +313,8 @@
 {
   hb_ot_map_builder_t *map = &planner->map;
 
+  map->is_simple = true;
+
   map->enable_feature (HB_TAG('r','v','r','n'));
   map->add_gsub_pause (nullptr);
 
@@ -354,7 +356,10 @@
   map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */
 
   if (planner->shaper->collect_features)
+  {
+    map->is_simple = false;
     planner->shaper->collect_features (planner);
+  }
 
   map->enable_feature (HB_TAG ('B','u','z','z')); /* Considered required. */
   map->enable_feature (HB_TAG ('B','U','Z','Z')); /* Considered discretionary. */
@@ -378,6 +383,8 @@
     map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
   }
 
+  if (num_user_features)
+    map->is_simple = false;
   for (unsigned int i = 0; i < num_user_features; i++)
   {
     const hb_feature_t *feature = &user_features[i];

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -368,7 +368,7 @@
 			    hb_font_t *font,
 			    hb_buffer_t *buffer)
 {
-  OT::hb_ot_apply_context_t c (0, font, buffer);
+  OT::hb_ot_apply_context_t c (0, font, buffer, hb_blob_get_empty ());
   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
     if (fallback_plan->lookup_array[i]) {
       c.set_lookup_mask (fallback_plan->mask_array[i]);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -53,7 +53,7 @@
 };
 
 
-#line 57 "hb-ot-shaper-indic-machine.hh"
+#line 54 "hb-ot-shaper-indic-machine.hh"
 #define indic_syllable_machine_ex_A 9u
 #define indic_syllable_machine_ex_C 1u
 #define indic_syllable_machine_ex_CM 16u
@@ -76,7 +76,7 @@
 #define indic_syllable_machine_ex_ZWNJ 5u
 
 
-#line 80 "hb-ot-shaper-indic-machine.hh"
+#line 75 "hb-ot-shaper-indic-machine.hh"
 static const unsigned char _indic_syllable_machine_trans_keys[] = {
 	8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 
 	8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 
@@ -460,7 +460,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 464 "hb-ot-shaper-indic-machine.hh"
+#line 453 "hb-ot-shaper-indic-machine.hh"
 	{
 	cs = indic_syllable_machine_start;
 	ts = 0;
@@ -476,7 +476,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 480 "hb-ot-shaper-indic-machine.hh"
+#line 465 "hb-ot-shaper-indic-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -490,7 +490,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 494 "hb-ot-shaper-indic-machine.hh"
+#line 477 "hb-ot-shaper-indic-machine.hh"
 	}
 
 	_keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -593,7 +593,7 @@
 #line 114 "hb-ot-shaper-indic-machine.rl"
 	{act = 6;}
 	break;
-#line 597 "hb-ot-shaper-indic-machine.hh"
+#line 559 "hb-ot-shaper-indic-machine.hh"
 	}
 
 _again:
@@ -602,7 +602,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 606 "hb-ot-shaper-indic-machine.hh"
+#line 566 "hb-ot-shaper-indic-machine.hh"
 	}
 
 	if ( ++p != pe )

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-syllabic.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-syllabic.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-syllabic.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -40,8 +40,16 @@
   if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
     return false;
   if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE)))
+  {
+    if (buffer->messaging ())
+      (void) buffer->message (font, "skipped inserting dotted-circles because there is no broken syllables");
     return false;
+  }
 
+  if (buffer->messaging () &&
+      !buffer->message (font, "start inserting dotted-circles"))
+    return false;
+
   hb_codepoint_t dottedcircle_glyph;
   if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
     return false;
@@ -84,6 +92,10 @@
       (void) buffer->next_glyph ();
   }
   buffer->sync ();
+
+  if (buffer->messaging ())
+    (void) buffer->message (font, "end inserting dotted-circles");
+
   return true;
 }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.rl
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.rl	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.rl	2023-07-09 05:55:34 UTC (rev 67588)
@@ -110,7 +110,7 @@
 
 h = H | HVM | IS | Sk;
 
-consonant_modifiers = CMAbv* CMBlw* ((h B | SUB) CMAbv? CMBlw*)*;
+consonant_modifiers = CMAbv* CMBlw* ((h B | SUB) CMAbv* CMBlw*)*;
 medial_consonants = MPre? MAbv? MBlw? MPst?;
 dependent_vowels = VPre* VAbv* VBlw* VPst* | H;
 vowel_modifiers = HVM? VMPre* VMAbv* VMBlw* VMPst*;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -377,6 +377,9 @@
 #define POST_BASE_FLAGS64 (FLAG64 (USE(FAbv)) | \
 			   FLAG64 (USE(FBlw)) | \
 			   FLAG64 (USE(FPst)) | \
+			   FLAG64 (USE(FMAbv)) | \
+			   FLAG64 (USE(FMBlw)) | \
+			   FLAG64 (USE(FMPst)) | \
 			   FLAG64 (USE(MAbv)) | \
 			   FLAG64 (USE(MBlw)) | \
 			   FLAG64 (USE(MPst)) | \

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -57,6 +57,16 @@
   // Reserved = 0xFFFC				/* Reserved for future use — set to zero. */
 };
 
+static bool axis_value_is_outside_axis_range (hb_tag_t axis_tag, float axis_value,
+                                              const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location)
+{
+  if (!user_axes_location->has (axis_tag))
+    return false;
+
+  Triple axis_range = user_axes_location->get (axis_tag);
+  return (axis_value < axis_range.minimum || axis_value > axis_range.maximum);
+}
+
 struct StatAxisRecord
 {
   int cmp (hb_tag_t key) const { return tag.cmp (key); }
@@ -96,16 +106,12 @@
   }
 
   bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
-                        const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+                        const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
   {
     hb_tag_t axis_tag = get_axis_tag (axis_records);
     float axis_value = get_value ();
 
-    if (!user_axes_location->has (axis_tag) ||
-        fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
-      return true;
-
-    return false;
+    return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location);
   }
 
   bool subset (hb_subset_context_t *c,
@@ -112,7 +118,7 @@
                const hb_array_t<const StatAxisRecord> axis_records) const
   {
     TRACE_SUBSET (this);
-    const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
+    const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location;
 
     if (keep_axis_value (axis_records, user_axes_location))
       return_trace (c->serializer->embed (this));
@@ -155,16 +161,12 @@
   }
 
   bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
-                        const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+                        const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
   {
     hb_tag_t axis_tag = get_axis_tag (axis_records);
     float axis_value = get_value ();
 
-    if (!user_axes_location->has (axis_tag) ||
-        fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
-      return true;
-
-    return false;
+    return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location);
   }
 
   bool subset (hb_subset_context_t *c,
@@ -171,7 +173,7 @@
                const hb_array_t<const StatAxisRecord> axis_records) const
   {
     TRACE_SUBSET (this);
-    const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
+    const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location;
 
     if (keep_axis_value (axis_records, user_axes_location))
       return_trace (c->serializer->embed (this));
@@ -218,16 +220,12 @@
   }
 
   bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
-                        const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+                        const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
   {
     hb_tag_t axis_tag = get_axis_tag (axis_records);
     float axis_value = get_value ();
 
-    if (!user_axes_location->has (axis_tag) ||
-        fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
-      return true;
-
-    return false;
+    return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location);
   }
 
   bool subset (hb_subset_context_t *c,
@@ -234,7 +232,7 @@
                const hb_array_t<const StatAxisRecord> axis_records) const
   {
     TRACE_SUBSET (this);
-    const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
+    const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location;
 
     if (keep_axis_value (axis_records, user_axes_location))
       return_trace (c->serializer->embed (this));
@@ -291,7 +289,7 @@
   { return axisValues.as_array (axisCount)[axis_index]; }
 
   bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
-                        const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+                        const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
   {
     hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount);
 
@@ -301,8 +299,7 @@
       float axis_value = rec.get_value ();
       hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag ();
 
-      if (user_axes_location->has (axis_tag) &&
-          fabsf(axis_value - user_axes_location->get (axis_tag)) > 0.001f)
+      if (axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location))
         return false;
     }
 
@@ -313,7 +310,7 @@
                const hb_array_t<const StatAxisRecord> axis_records) const
   {
     TRACE_SUBSET (this);
-    const hb_hashmap_t<hb_tag_t, float> *user_axes_location = &c->plan->user_axes_location;
+    const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location = &c->plan->user_axes_location;
     if (!keep_axis_value (axis_records, user_axes_location))
       return_trace (false);
 
@@ -402,7 +399,7 @@
   }
 
   bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
-                        hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+                        hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
   {
     switch (u.format)
     {
@@ -451,8 +448,6 @@
                const hb_array_t<const StatAxisRecord> axis_records) const
   {
     TRACE_SUBSET (this);
-    auto *out = c->serializer->start_embed (this);
-    if (unlikely (!out)) return_trace (false);
 
     auto axisValueOffsets = as_array (axisValueCount);
     count = 0;
@@ -517,7 +512,7 @@
     return axis_value.get_value_name_id ();
   }
 
-  void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+  void collect_name_ids (hb_hashmap_t<hb_tag_t, Triple> *user_axes_location,
                          hb_set_t *nameids_to_retain /* OUT */) const
   {
     if (!has_data ()) return;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -412,7 +412,7 @@
 /**
  * hb_ot_tags_from_script_and_language:
  * @script: an #hb_script_t to convert.
- * @language: an #hb_language_t to convert.
+ * @language: (nullable): an #hb_language_t to convert.
  * @script_count: (inout) (optional): maximum number of script tags to retrieve (IN)
  * and actual number of script tags retrieved (OUT)
  * @script_tags: (out) (optional): array of size at least @script_count to store the

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -36,19 +36,14 @@
 {
   friend struct DeltaSetIndexMap;
 
+  unsigned get_size () const
+  { return min_size + mapCount * get_width (); }
+
   private:
   DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
   {
     TRACE_SERIALIZE (this);
-    auto *out = c->start_embed (this);
-    if (unlikely (!out)) return_trace (nullptr);
-
-    unsigned total_size = min_size + mapCount * get_width ();
-    HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
-    if (unlikely (!p)) return_trace (nullptr);
-
-    hb_memcpy (p, this, HBUINT8::static_size * total_size);
-    return_trace (out);
+    return_trace (c->embed (this));
   }
 
   template <typename T>
@@ -65,7 +60,7 @@
 
     entryFormat = ((width-1)<<4)|(inner_bit_count-1);
     mapCount = output_map.length;
-    HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
+    HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length, false);
     if (unlikely (!p)) return_trace (false);
     for (unsigned int i = 0; i < output_map.length; i++)
     {
@@ -242,6 +237,7 @@
 /* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
 struct TupleVariationHeader
 {
+  friend struct tuple_delta_t;
   unsigned get_size (unsigned axis_count) const
   { return min_size + get_all_tuples (axis_count).get_size (); }
 
@@ -250,14 +246,67 @@
   const TupleVariationHeader &get_next (unsigned axis_count) const
   { return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count)); }
 
+  bool unpack_axis_tuples (unsigned axis_count,
+                           const hb_array_t<const F2DOT14> shared_tuples,
+                           const hb_map_t *axes_old_index_tag_map,
+                           hb_hashmap_t<hb_tag_t, Triple>& axis_tuples /* OUT */) const
+  {
+    const F2DOT14 *peak_tuple = nullptr;
+    if (has_peak ())
+      peak_tuple = get_peak_tuple (axis_count).arrayZ;
+    else
+    {
+      unsigned int index = get_index ();
+      if (unlikely ((index + 1) * axis_count > shared_tuples.length))
+        return false;
+      peak_tuple = shared_tuples.sub_array (axis_count * index, axis_count).arrayZ;
+    }
+
+    const F2DOT14 *start_tuple = nullptr;
+    const F2DOT14 *end_tuple = nullptr;
+    bool has_interm = has_intermediate ();
+
+    if (has_interm)
+    {
+      start_tuple = get_start_tuple (axis_count).arrayZ;
+      end_tuple = get_end_tuple (axis_count).arrayZ;
+    }
+
+    for (unsigned i = 0; i < axis_count; i++)
+    {
+      float peak = peak_tuple[i].to_float ();
+      if (peak == 0.f) continue;
+
+      hb_tag_t *axis_tag;
+      if (!axes_old_index_tag_map->has (i, &axis_tag))
+        return false;
+
+      float start, end;
+      if (has_interm)
+      {
+        start = start_tuple[i].to_float ();
+        end = end_tuple[i].to_float ();
+      }
+      else
+      {
+        start = hb_min (peak, 0.f);
+        end = hb_max (peak, 0.f);
+      }
+      axis_tuples.set (*axis_tag, Triple (start, peak, end));
+    }
+
+    return true;
+  }
+
   float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
                           const hb_array_t<const F2DOT14> shared_tuples,
-			  const hb_vector_t<int> *shared_tuple_active_idx = nullptr) const
+			  const hb_vector_t<hb_pair_t<int,int>> *shared_tuple_active_idx = nullptr) const
   {
     const F2DOT14 *peak_tuple;
 
     unsigned start_idx = 0;
     unsigned end_idx = coord_count;
+    unsigned step = 1;
 
     if (has_peak ())
       peak_tuple = get_peak_tuple (coord_count).arrayZ;
@@ -272,10 +321,16 @@
       {
 	if (unlikely (index >= shared_tuple_active_idx->length))
 	  return 0.f;
-	int v = (*shared_tuple_active_idx).arrayZ[index];
-	if (v != -1)
+	auto _ = (*shared_tuple_active_idx).arrayZ[index];
+	if (_.second != -1)
 	{
-	  start_idx = v;
+	  start_idx = _.first;
+	  end_idx = _.second + 1;
+	  step = _.second - _.first;
+	}
+	else if (_.first != -1)
+	{
+	  start_idx = _.first;
 	  end_idx = start_idx + 1;
 	}
       }
@@ -291,7 +346,7 @@
     }
 
     float scalar = 1.f;
-    for (unsigned int i = start_idx; i < end_idx; i++)
+    for (unsigned int i = start_idx; i < end_idx; i += step)
     {
       int peak = peak_tuple[i].to_int ();
       if (!peak) continue;
@@ -333,6 +388,7 @@
       TupleIndexMask      = 0x0FFFu
     };
 
+    TuppleIndex& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
     DEFINE_SIZE_STATIC (2);
   };
 
@@ -365,6 +421,468 @@
   DEFINE_SIZE_MIN (4);
 };
 
+/* not using hb_bytes_t: avoid potential build issues with some compilers */
+struct byte_data_t
+{
+  hb_bytes_t bytes;
+
+  byte_data_t () = default;
+  byte_data_t (const char *p_, unsigned len_) : bytes (hb_bytes_t (p_, len_)) {}
+
+  void fini () { bytes.fini (); }
+
+  bool operator == (const byte_data_t& o) const
+  { return bytes.arrayZ == o.bytes.arrayZ && bytes.length == o.bytes.length; }
+
+  explicit operator bool () const { return bytes.length; }
+
+  void copy (hb_serialize_context_t *c) const
+  { c->embed (bytes.arrayZ, bytes.length); }
+};
+
+enum packed_delta_flag_t
+{
+  DELTAS_ARE_ZERO      = 0x80,
+  DELTAS_ARE_WORDS     = 0x40,
+  DELTA_RUN_COUNT_MASK = 0x3F
+};
+
+struct tuple_delta_t
+{
+  public:
+  hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
+
+  /* indices_length = point_count, indice[i] = 1 means point i is referenced */
+  hb_vector_t<bool> indices;
+  
+  hb_vector_t<float> deltas_x;
+  /* empty for cvar tuples */
+  hb_vector_t<float> deltas_y;
+
+  /* compiled data: header and deltas
+   * compiled point data is saved in a hashmap within tuple_variations_t cause
+   * some point sets might be reused by different tuple variations */
+  hb_vector_t<char> compiled_tuple_header;
+  hb_vector_t<char> compiled_deltas;
+
+  tuple_delta_t () = default;
+  tuple_delta_t (const tuple_delta_t& o) = default;
+
+  tuple_delta_t (tuple_delta_t&& o) : tuple_delta_t ()
+  {
+    axis_tuples = std::move (o.axis_tuples);
+    indices = std::move (o.indices);
+    deltas_x = std::move (o.deltas_x);
+    deltas_y = std::move (o.deltas_y);
+  }
+
+  tuple_delta_t& operator = (tuple_delta_t&& o)
+  {
+    hb_swap (*this, o);
+    return *this;
+  }
+
+  void remove_axis (hb_tag_t axis_tag)
+  { axis_tuples.del (axis_tag); }
+
+  bool set_tent (hb_tag_t axis_tag, Triple tent)
+  { return axis_tuples.set (axis_tag, tent); }
+
+  tuple_delta_t& operator += (const tuple_delta_t& o)
+  {
+    unsigned num = indices.length;
+    for (unsigned i = 0; i < num; i++)
+    {
+      if (indices.arrayZ[i])
+      {
+        if (o.indices.arrayZ[i])
+        {
+          deltas_x[i] += o.deltas_x[i];
+          if (deltas_y && o.deltas_y)
+            deltas_y[i] += o.deltas_y[i];
+        }
+      }
+      else
+      {
+        if (!o.indices.arrayZ[i]) continue;
+        deltas_x[i] = o.deltas_x[i];
+        if (deltas_y && o.deltas_y)
+          deltas_y[i] = o.deltas_y[i];
+      }
+    }
+    return *this;
+  }
+
+  tuple_delta_t& operator *= (float scalar)
+  {
+    if (scalar == 1.0f)
+      return *this;
+
+    unsigned num = indices.length;
+    for (unsigned i = 0; i < num; i++)
+    {
+      if (!indices.arrayZ[i]) continue;
+
+      deltas_x[i] *= scalar;
+      if (deltas_y)
+        deltas_y[i] *= scalar;
+    }
+    return *this;
+  }
+
+  hb_vector_t<tuple_delta_t> change_tuple_var_axis_limit (hb_tag_t axis_tag, Triple axis_limit) const
+  {
+    hb_vector_t<tuple_delta_t> out;
+    Triple *tent;
+    if (!axis_tuples.has (axis_tag, &tent))
+    {
+      out.push (*this);
+      return out;
+    }
+
+    if ((tent->minimum < 0.f && tent->maximum > 0.f) ||
+        !(tent->minimum <= tent->middle && tent->middle <= tent->maximum))
+      return out;
+
+    if (tent->middle == 0.f)
+    {
+      out.push (*this);
+      return out;
+    }
+
+    result_t solutions = rebase_tent (*tent, axis_limit);
+    for (auto t : solutions)
+    {
+      tuple_delta_t new_var = *this;
+      if (t.second == Triple ())
+        new_var.remove_axis (axis_tag);
+      else
+        new_var.set_tent (axis_tag, t.second);
+
+      new_var *= t.first;
+      out.push (std::move (new_var));
+    }
+
+    return out;
+  }
+
+  /* deltas should be compiled already before we compile tuple
+   * variation header cause we need to fill in the size of the
+   * serialized data for this tuple variation */
+  //TODO(qxliu):add option to use sharedTuples in gvar
+  bool compile_tuple_var_header (const hb_map_t& axes_index_map,
+                                 unsigned points_data_length,
+                                 const hb_map_t& axes_old_index_tag_map)
+  {
+    if (!compiled_deltas) return false;
+
+    unsigned cur_axis_count = axes_index_map.get_population ();
+    /* allocate enough memory: 1 peak + 2 intermediate coords + fixed header size */
+    unsigned alloc_len = 3 * cur_axis_count * (F2DOT14::static_size) + 4;
+    if (unlikely (!compiled_tuple_header.resize (alloc_len))) return false;
+
+    unsigned flag = 0;
+    /* skip the first 4 header bytes: variationDataSize+tupleIndex */
+    F2DOT14* p = reinterpret_cast<F2DOT14 *> (compiled_tuple_header.begin () + 4);
+    F2DOT14* end = reinterpret_cast<F2DOT14 *> (compiled_tuple_header.end ());
+    hb_array_t<F2DOT14> coords (p, end - p);
+
+    /* encode peak coords */
+    unsigned peak_count = encode_peak_coords(coords, flag, axes_index_map, axes_old_index_tag_map);
+    if (!peak_count) return false;
+
+    /* encode interim coords, it's optional so returned num could be 0 */
+    unsigned interim_count = encode_interm_coords (coords.sub_array (peak_count), flag, axes_index_map, axes_old_index_tag_map);
+
+    //TODO(qxliu): add option to use shared_points in gvar
+    flag |= TupleVariationHeader::TuppleIndex::PrivatePointNumbers;
+
+    unsigned serialized_data_size = points_data_length + compiled_deltas.length;
+    TupleVariationHeader *o = reinterpret_cast<TupleVariationHeader *> (compiled_tuple_header.begin ());
+    o->varDataSize = serialized_data_size;
+    o->tupleIndex = flag;
+
+    unsigned total_header_len = 4 + (peak_count + interim_count) * (F2DOT14::static_size);
+    return compiled_tuple_header.resize (total_header_len);
+  }
+
+  unsigned encode_peak_coords (hb_array_t<F2DOT14> peak_coords,
+                               unsigned& flag,
+                               const hb_map_t& axes_index_map,
+                               const hb_map_t& axes_old_index_tag_map) const
+  {
+    unsigned orig_axis_count = axes_old_index_tag_map.get_population ();
+    auto it = peak_coords.iter ();
+    unsigned count = 0;
+    for (unsigned i = 0; i < orig_axis_count; i++)
+    {
+      if (!axes_index_map.has (i)) /* axis pinned */
+        continue;
+      hb_tag_t axis_tag = axes_old_index_tag_map.get (i);
+      Triple *coords;
+      if (!axis_tuples.has (axis_tag, &coords))
+        (*it).set_int (0);
+      else
+        (*it).set_float (coords->middle);
+      it++;
+      count++;
+    }
+    flag |= TupleVariationHeader::TuppleIndex::EmbeddedPeakTuple;
+    return count;
+  }
+
+  /* if no need to encode intermediate coords, then just return p */
+  unsigned encode_interm_coords (hb_array_t<F2DOT14> coords,
+                                 unsigned& flag,
+                                 const hb_map_t& axes_index_map,
+                                 const hb_map_t& axes_old_index_tag_map) const
+  {
+    unsigned orig_axis_count = axes_old_index_tag_map.get_population ();
+    unsigned cur_axis_count = axes_index_map.get_population ();
+
+    auto start_coords_iter = coords.sub_array (0, cur_axis_count).iter ();
+    auto end_coords_iter = coords.sub_array (cur_axis_count).iter ();
+    bool encode_needed = false;
+    unsigned count = 0;
+    for (unsigned i = 0; i < orig_axis_count; i++)
+    {
+      if (!axes_index_map.has (i)) /* axis pinned */
+        continue;
+      hb_tag_t axis_tag = axes_old_index_tag_map.get (i);
+      Triple *coords;
+      float min_val = 0.f, val = 0.f, max_val = 0.f;
+      if (axis_tuples.has (axis_tag, &coords))
+      {
+        min_val = coords->minimum;
+        val = coords->middle;
+        max_val = coords->maximum;
+      }
+
+      (*start_coords_iter).set_float (min_val);
+      (*end_coords_iter).set_float (max_val);
+
+      start_coords_iter++;
+      end_coords_iter++;
+      count += 2;
+      if (min_val != hb_min (val, 0.f) || max_val != hb_max (val, 0.f))
+        encode_needed = true;
+    }
+
+    if (encode_needed)
+    {
+      flag |= TupleVariationHeader::TuppleIndex::IntermediateRegion;
+      return count;
+    }
+    return 0;
+  }
+
+  bool compile_deltas ()
+  {
+    hb_vector_t<int> rounded_deltas;
+    if (unlikely (!rounded_deltas.alloc (indices.length)))
+      return false;
+
+    for (unsigned i = 0; i < indices.length; i++)
+    {
+      if (!indices[i]) continue;
+      int rounded_delta = (int) roundf (deltas_x[i]);
+      rounded_deltas.push (rounded_delta);
+    }
+
+    if (!rounded_deltas) return false;
+    /* allocate enough memories 3 * num_deltas */
+    unsigned alloc_len = 3 * rounded_deltas.length;
+    if (deltas_y)
+      alloc_len *= 2;
+
+    if (unlikely (!compiled_deltas.resize (alloc_len))) return false;
+
+    unsigned i = 0;
+    unsigned encoded_len = encode_delta_run (i, compiled_deltas.as_array (), rounded_deltas);
+
+    if (deltas_y)
+    {
+      /* reuse the rounded_deltas vector, check that deltas_y have the same num of deltas as deltas_x */
+      unsigned j = 0;
+      for (unsigned idx = 0; idx < indices.length; idx++)
+      {
+        if (!indices[idx]) continue;
+        int rounded_delta = (int) roundf (deltas_y[idx]);
+
+        if (j >= rounded_deltas.length) return false;
+
+        rounded_deltas[j++] = rounded_delta;
+      }
+
+      if (j != rounded_deltas.length) return false;
+      encoded_len += encode_delta_run (i, compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas);
+    }
+    return compiled_deltas.resize (encoded_len);
+  }
+
+  unsigned encode_delta_run (unsigned& i,
+                             hb_array_t<char> encoded_bytes,
+                             const hb_vector_t<int>& deltas) const
+  {
+    unsigned num_deltas = deltas.length;
+    unsigned encoded_len = 0;
+    while (i < num_deltas)
+    {
+      int val = deltas[i];
+      if (val == 0)
+        encoded_len += encode_delta_run_as_zeroes (i, encoded_bytes.sub_array (encoded_len), deltas);
+      else if (val >= -128 && val <= 127)
+        encoded_len += encode_delta_run_as_bytes (i, encoded_bytes.sub_array (encoded_len), deltas);
+      else
+        encoded_len += encode_delta_run_as_words (i, encoded_bytes.sub_array (encoded_len), deltas);
+    }
+    return encoded_len;
+  }
+
+  unsigned encode_delta_run_as_zeroes (unsigned& i,
+                                       hb_array_t<char> encoded_bytes,
+                                       const hb_vector_t<int>& deltas) const
+  {
+    unsigned num_deltas = deltas.length;
+    unsigned run_length = 0;
+    auto it = encoded_bytes.iter ();
+    unsigned encoded_len = 0;
+    while (i < num_deltas && deltas[i] == 0)
+    {
+      i++;
+      run_length++;
+    }
+
+    while (run_length >= 64)
+    {
+      *it++ = (DELTAS_ARE_ZERO | 63);
+      run_length -= 64;
+      encoded_len++;
+    }
+
+    if (run_length)
+    {
+      *it++ = (DELTAS_ARE_ZERO | (run_length - 1));
+      encoded_len++;
+    }
+    return encoded_len;
+  }
+
+  unsigned encode_delta_run_as_bytes (unsigned &i,
+                                      hb_array_t<char> encoded_bytes,
+                                      const hb_vector_t<int>& deltas) const
+  {
+    unsigned start = i;
+    unsigned num_deltas = deltas.length;
+    while (i < num_deltas)
+    {
+      int val = deltas[i];
+      if (val > 127 || val < -128)
+        break;
+
+      /* from fonttools: if there're 2 or more zeros in a sequence,
+       * it is better to start a new run to save bytes. */
+      if (val == 0 && i + 1 < num_deltas && deltas[i+1] == 0)
+        break;
+
+      i++;
+    }
+    unsigned run_length = i - start;
+
+    unsigned encoded_len = 0;
+    auto it = encoded_bytes.iter ();
+
+    while (run_length >= 64)
+    {
+      *it++ = 63;
+      encoded_len++;
+
+      for (unsigned j = 0; j < 64; j++)
+      {
+        *it++ = static_cast<char> (deltas[start + j]);
+        encoded_len++;
+      }
+
+      start += 64;
+      run_length -= 64;
+    }
+
+    if (run_length)
+    {
+      *it++ = run_length - 1;
+      encoded_len++;
+
+      while (start < i)
+      {
+        *it++ = static_cast<char> (deltas[start++]);
+        encoded_len++;
+      }
+    }
+
+    return encoded_len;
+  }
+
+  unsigned encode_delta_run_as_words (unsigned &i,
+                                      hb_array_t<char> encoded_bytes,
+                                      const hb_vector_t<int>& deltas) const
+  {
+    unsigned start = i;
+    unsigned num_deltas = deltas.length;
+    while (i < num_deltas)
+    {
+      int val = deltas[i];
+      
+      /* start a new run for a single zero value*/
+      if (val == 0) break;
+
+      /* from fonttools: continue word-encoded run if there's only one
+       * single value in the range [-128, 127] because it is more compact.
+       * Only start a new run when there're 2 continuous such values. */
+      if (val >= -128 && val <= 127 &&
+          i + 1 < num_deltas &&
+          deltas[i+1] >= -128 && deltas[i+1] <= 127)
+        break;
+
+      i++;
+    }
+
+    unsigned run_length = i - start;
+    auto it = encoded_bytes.iter ();
+    unsigned encoded_len = 0;
+    while (run_length >= 64)
+    {
+      *it++ = (DELTAS_ARE_WORDS | 63);
+      encoded_len++;
+
+      for (unsigned j = 0; j < 64; j++)
+      {
+        int16_t delta_val = deltas[start + j];
+        *it++ = static_cast<char> (delta_val >> 8);
+        *it++ = static_cast<char> (delta_val & 0xFF);
+
+        encoded_len += 2;
+      }
+
+      start += 64;
+      run_length -= 64;
+    }
+
+    if (run_length)
+    {
+      *it++ = (DELTAS_ARE_WORDS | (run_length - 1));
+      while (start < i)
+      {
+        int16_t delta_val = deltas[start++];
+        *it++ = static_cast<char> (delta_val >> 8);
+        *it++ = static_cast<char> (delta_val & 0xFF);
+
+        encoded_len += 2;
+      }
+    }
+    return encoded_len;
+  }
+};
+
 struct TupleVariationData
 {
   bool sanitize (hb_sanitize_context_t *c) const
@@ -378,7 +896,7 @@
   unsigned get_size (unsigned axis_count) const
   {
     unsigned total_size = min_size;
-    unsigned count = tupleVarCount;
+    unsigned count = tupleVarCount.get_count ();
     const TupleVariationHeader *tuple_var_header = &(get_tuple_var_header());
     for (unsigned i = 0; i < count; i++)
     {
@@ -392,8 +910,354 @@
   const TupleVariationHeader &get_tuple_var_header (void) const
   { return StructAfter<TupleVariationHeader> (data); }
 
+  struct tuple_iterator_t;
+  struct tuple_variations_t
+  {
+    hb_vector_t<tuple_delta_t> tuple_vars;
+
+    private:
+    /* referenced point set->compiled point data map */
+    hb_hashmap_t<const hb_vector_t<bool>*, byte_data_t> point_data_map;
+    /* referenced point set-> count map, used in finding shared points */
+    hb_hashmap_t<const hb_vector_t<bool>*, unsigned> point_set_count_map;
+
+    public:
+    ~tuple_variations_t () { fini (); }
+    void fini ()
+    {
+      for (auto _ : point_data_map.values ())
+        _.fini ();
+
+      point_set_count_map.fini ();
+      tuple_vars.fini ();
+    }
+
+    unsigned get_var_count () const
+    { return tuple_vars.length; }
+
+    bool create_from_tuple_var_data (tuple_iterator_t iterator,
+                                     unsigned tuple_var_count,
+                                     unsigned point_count,
+                                     bool is_gvar,
+                                     const hb_map_t *axes_old_index_tag_map,
+                                     const hb_vector_t<unsigned> &shared_indices,
+                                     const hb_array_t<const F2DOT14> shared_tuples)
+    {
+      do
+      {
+        const HBUINT8 *p = iterator.get_serialized_data ();
+        unsigned int length = iterator.current_tuple->get_data_size ();
+        if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
+        { fini (); return false; }
+
+        hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
+        if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, axes_old_index_tag_map, axis_tuples)
+            || axis_tuples.is_empty ())
+        { fini (); return false; }
+
+        hb_vector_t<unsigned> private_indices;
+        bool has_private_points = iterator.current_tuple->has_private_points ();
+        const HBUINT8 *end = p + length;
+        if (has_private_points &&
+            !TupleVariationData::unpack_points (p, private_indices, end))
+        { fini (); return false; }
+
+        const hb_vector_t<unsigned> &indices = has_private_points ? private_indices : shared_indices;
+        bool apply_to_all = (indices.length == 0);
+        unsigned num_deltas = apply_to_all ? point_count : indices.length;
+
+        hb_vector_t<int> deltas_x;
+
+        if (unlikely (!deltas_x.resize (num_deltas, false) ||
+                      !TupleVariationData::unpack_deltas (p, deltas_x, end)))
+        { fini (); return false; }
+
+        hb_vector_t<int> deltas_y;
+        if (is_gvar)
+        {
+          if (unlikely (!deltas_y.resize (num_deltas, false) ||
+                        !TupleVariationData::unpack_deltas (p, deltas_y, end)))
+          { fini (); return false; }
+        }
+
+        tuple_delta_t var;
+        var.axis_tuples = std::move (axis_tuples);
+        if (unlikely (!var.indices.resize (point_count) ||
+                      !var.deltas_x.resize (point_count, false)))
+        { fini (); return false; }
+
+        if (is_gvar && unlikely (!var.deltas_y.resize (point_count, false)))
+        { fini (); return false; }
+
+        for (unsigned i = 0; i < num_deltas; i++)
+        {
+          unsigned idx = apply_to_all ? i : indices[i];
+          if (idx >= point_count) continue;
+          var.indices[idx] = true;
+          var.deltas_x[idx] = static_cast<float> (deltas_x[i]);
+          if (is_gvar)
+            var.deltas_y[idx] = static_cast<float> (deltas_y[i]);
+        }
+        tuple_vars.push (std::move (var));
+      } while (iterator.move_to_next ());
+      return true;
+    }
+
+    void change_tuple_variations_axis_limits (const hb_hashmap_t<hb_tag_t, Triple> *normalized_axes_location)
+    {
+      for (auto _ : *normalized_axes_location)
+      {
+        hb_tag_t axis_tag = _.first;
+        Triple axis_limit = _.second;
+        hb_vector_t<tuple_delta_t> new_vars;
+        for (const tuple_delta_t& var : tuple_vars)
+        {
+          hb_vector_t<tuple_delta_t> out = var.change_tuple_var_axis_limit (axis_tag, axis_limit);
+          if (!out) continue;
+          unsigned new_len = new_vars.length + out.length;
+
+          if (unlikely (!new_vars.alloc (new_len, false)))
+          { fini (); return;}
+
+          for (unsigned i = 0; i < out.length; i++)
+            new_vars.push (std::move (out[i]));
+        }
+        tuple_vars.fini ();
+        tuple_vars = std::move (new_vars);
+      }
+    }
+
+    /* merge tuple variations with overlapping tents */
+    void merge_tuple_variations ()
+    {
+      hb_vector_t<tuple_delta_t> new_vars;
+      hb_hashmap_t<hb_hashmap_t<hb_tag_t, Triple>, unsigned> m;
+      unsigned i = 0;
+      for (const tuple_delta_t& var : tuple_vars)
+      {
+        /* if all axes are pinned, drop the tuple variation */
+        if (var.axis_tuples.is_empty ()) continue;
+
+        unsigned *idx;
+        if (m.has (var.axis_tuples, &idx))
+        {
+          new_vars[*idx] += var;
+        }
+        else
+        {
+          new_vars.push (var);
+          m.set (var.axis_tuples, i);
+          i++;
+        }
+      }
+      tuple_vars.fini ();
+      tuple_vars = std::move (new_vars);
+    }
+
+    byte_data_t compile_point_set (const hb_vector_t<bool> &point_indices)
+    {
+      unsigned num_points = 0;
+      for (bool i : point_indices)
+        if (i) num_points++;
+
+      unsigned indices_length = point_indices.length;
+      /* If the points set consists of all points in the glyph, it's encoded with a
+       * single zero byte */
+      if (num_points == indices_length)
+      {
+        char *p = (char *) hb_calloc (1, sizeof (char));
+        if (unlikely (!p)) return byte_data_t ();
+
+        return byte_data_t (p, 1);
+      }
+
+      /* allocate enough memories: 2 bytes for count + 3 bytes for each point */
+      unsigned num_bytes = 2 + 3 *num_points;
+      char *p = (char *) hb_calloc (num_bytes, sizeof (char));
+      if (unlikely (!p)) return byte_data_t ();
+
+      unsigned pos = 0;
+      /* binary data starts with the total number of reference points */
+      if (num_points < 0x80)
+        p[pos++] = num_points;
+      else
+      {
+        p[pos++] = ((num_points >> 8) | 0x80);
+        p[pos++] = num_points & 0xFF;
+      }
+
+      const unsigned max_run_length = 0x7F;
+      unsigned i = 0;
+      unsigned last_value = 0;
+      unsigned num_encoded = 0;
+      while (i < indices_length && num_encoded < num_points)
+      {
+        unsigned run_length = 0;
+        unsigned header_pos = pos;
+        p[pos++] = 0;
+
+        bool use_byte_encoding = false;
+        bool new_run = true;
+        while (i < indices_length && num_encoded < num_points &&
+               run_length <= max_run_length)
+        {
+          // find out next referenced point index
+          while (i < indices_length && !point_indices[i])
+            i++;
+
+          if (i >= indices_length) break;
+
+          unsigned cur_value = i;
+          unsigned delta = cur_value - last_value;
+
+          if (new_run)
+          {
+            use_byte_encoding = (delta <= 0xFF);
+            new_run = false;
+          }
+
+          if (use_byte_encoding && delta > 0xFF)
+            break;
+
+          if (use_byte_encoding)
+            p[pos++] = delta;
+          else
+          {
+            p[pos++] = delta >> 8;
+            p[pos++] = delta & 0xFF;
+          }
+          i++;
+          last_value = cur_value;
+          run_length++;
+          num_encoded++;
+        }
+
+        if (use_byte_encoding)
+          p[header_pos] = run_length - 1;
+        else
+          p[header_pos] = (run_length - 1) | 0x80;
+      }
+      return byte_data_t (p, pos);
+    }
+
+    /* compile all point set and store byte data in a point_set->byte_data_t hashmap,
+     * also update point_set->count map, which will be used in finding shared
+     * point set*/
+    bool compile_all_point_sets ()
+    {
+      for (const auto& tuple: tuple_vars)
+      {
+        const hb_vector_t<bool>* points_set = &(tuple.indices);
+        if (point_data_map.has (points_set))
+        {
+          unsigned *count;
+          if (unlikely (!point_set_count_map.has (points_set, &count) ||
+                        !point_set_count_map.set (points_set, (*count) + 1)))
+            return false;
+          continue;
+        }
+        
+        byte_data_t compiled_data = compile_point_set (*points_set);
+        if (unlikely (compiled_data == byte_data_t ()))
+          return false;
+        
+        if (!point_data_map.set (points_set, compiled_data) ||
+            !point_set_count_map.set (points_set, 1))
+          return false;
+      }
+      return true;
+    }
+
+    /* find shared points set which saves most bytes */
+    byte_data_t find_shared_points ()
+    {
+      unsigned max_saved_bytes = 0;
+      byte_data_t res{};
+
+      for (const auto& _ : point_data_map.iter ())
+      {
+        const hb_vector_t<bool>* points_set = _.first;
+        unsigned data_length = _.second.bytes.length;
+        unsigned *count;
+        if (unlikely (!point_set_count_map.has (points_set, &count) ||
+                      *count <= 1))
+          return byte_data_t ();
+
+        unsigned saved_bytes = data_length * ((*count) -1);
+        if (saved_bytes > max_saved_bytes)
+        {
+          max_saved_bytes = saved_bytes;
+          res = _.second;
+        }
+      }
+      return res;
+    }
+
+    void instantiate (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location)
+    {
+      change_tuple_variations_axis_limits (&normalized_axes_location);
+      merge_tuple_variations ();
+    }
+
+    bool compile_bytes (const hb_map_t& axes_index_map,
+                        const hb_map_t& axes_old_index_tag_map)
+    {
+      // compile points set and store data in hashmap
+      if (!compile_all_point_sets ())
+        return false;
+      // compile delta and tuple var header for each tuple variation
+      for (auto& tuple: tuple_vars)
+      {
+        const hb_vector_t<bool>* points_set = &(tuple.indices);
+        byte_data_t *points_data;
+        if (unlikely (!point_data_map.has (points_set, &points_data)))
+          return false;
+
+        if (!tuple.compile_deltas ())
+          return false;
+
+        if (!tuple.compile_tuple_var_header (axes_index_map, points_data->bytes.length, axes_old_index_tag_map))
+          return false;
+      }
+      return true;
+    }
+
+    bool serialize_var_headers (hb_serialize_context_t *c, unsigned& total_header_len) const
+    {
+      TRACE_SERIALIZE (this);
+      for (const auto& tuple: tuple_vars)
+      {
+        byte_data_t compiled_bytes {tuple.compiled_tuple_header.arrayZ, tuple.compiled_tuple_header.length};
+        compiled_bytes.copy (c);
+        if (c->in_error ()) return_trace (false);
+        total_header_len += tuple.compiled_tuple_header.length;
+      }
+      return_trace (true);
+    }
+
+    bool serialize_var_data (hb_serialize_context_t *c) const
+    {
+      TRACE_SERIALIZE (this);
+      for (const auto& tuple: tuple_vars)
+      {
+        const hb_vector_t<bool>* points_set = &(tuple.indices);
+        byte_data_t *point_data;
+        if (!point_data_map.has (points_set, &point_data))
+          return_trace (false);
+
+        point_data->copy (c);
+        byte_data_t compiled_bytes {tuple.compiled_deltas.arrayZ, tuple.compiled_deltas.length};
+        compiled_bytes.copy (c);
+        if (c->in_error ()) return_trace (false);
+      }
+      return_trace (true);
+    }
+  };
+
   struct tuple_iterator_t
   {
+    unsigned get_axis_count () const { return axis_count; }
+
     void init (hb_bytes_t var_data_bytes_, unsigned int axis_count_, const void *table_base_)
     {
       var_data_bytes = var_data_bytes_;
@@ -517,13 +1381,6 @@
                              hb_vector_t<int> &deltas /* IN/OUT */,
                              const HBUINT8 *end)
   {
-    enum packed_delta_flag_t
-    {
-      DELTAS_ARE_ZERO      = 0x80,
-      DELTAS_ARE_WORDS     = 0x40,
-      DELTA_RUN_COUNT_MASK = 0x3F
-    };
-
     unsigned i = 0;
     unsigned count = deltas.length;
     while (i < count)
@@ -561,11 +1418,50 @@
 
   bool has_data () const { return tupleVarCount; }
 
+  bool decompile_tuple_variations (unsigned point_count,
+                                   bool is_gvar,
+                                   tuple_iterator_t iterator,
+                                   const hb_map_t *axes_old_index_tag_map,
+                                   const hb_vector_t<unsigned> &shared_indices,
+                                   const hb_array_t<const F2DOT14> shared_tuples,
+                                   tuple_variations_t& tuple_variations /* OUT */) const
+  {
+    return tuple_variations.create_from_tuple_var_data (iterator, tupleVarCount,
+                                                        point_count, is_gvar,
+                                                        axes_old_index_tag_map,
+                                                        shared_indices,
+                                                        shared_tuples);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  bool is_gvar,
+                  tuple_variations_t& tuple_variations) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->start_embed (this);
+    if (unlikely (!c->extend_min (out))) return_trace (false);
+
+    if (!c->check_assign (out->tupleVarCount, tuple_variations.get_var_count (),
+                          HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
+
+    unsigned total_header_len = 0;
+
+    if (!tuple_variations.serialize_var_headers (c, total_header_len))
+      return_trace (false);
+    
+    unsigned data_offset = min_size + total_header_len;
+    if (!is_gvar) data_offset += 4;
+    if (!c->check_assign (out->data, data_offset, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
+
+    return tuple_variations.serialize_var_data (c);
+  }
+
   protected:
   struct TupleVarCount : HBUINT16
   {
     bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); }
     unsigned int get_count () const { return (*this) & CountMask; }
+    TupleVarCount& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
 
     protected:
     enum Flags

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -27,6 +27,7 @@
 #define HB_OT_VAR_CVAR_TABLE_HH
 
 #include "hb-ot-var-common.hh"
+#include "hb-ot-var-fvar-table.hh"
 
 
 namespace OT {
@@ -51,6 +52,27 @@
   const TupleVariationData* get_tuple_var_data (void) const
   { return &tupleVariationData; }
 
+  bool decompile_tuple_variations (unsigned axis_count,
+                                   unsigned point_count,
+                                   bool is_gvar,
+                                   const hb_map_t *axes_old_index_tag_map,
+                                   TupleVariationData::tuple_variations_t& tuple_variations /* OUT */) const
+  {
+    hb_vector_t<unsigned> shared_indices;
+    TupleVariationData::tuple_iterator_t iterator;
+    unsigned var_data_length = tupleVariationData.get_size (axis_count);
+    hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast<const char*> (get_tuple_var_data ()), var_data_length);
+    if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, this,
+                                                 shared_indices, &iterator))
+      return false;
+    
+    return tupleVariationData.decompile_tuple_variations (point_count, is_gvar, iterator,
+                                                          axes_old_index_tag_map,
+                                                          shared_indices,
+                                                          hb_array<const F2DOT14> (),
+                                                          tuple_variations);
+  }
+
   static bool calculate_cvt_deltas (unsigned axis_count,
                                     hb_array_t<int> coords,
                                     unsigned num_cvt_item,
@@ -104,7 +126,54 @@
 
     return true;
   }
+  
+  bool serialize (hb_serialize_context_t *c,
+                  TupleVariationData::tuple_variations_t& tuple_variations) const
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->embed (version))) return_trace (false);
 
+    return_trace (tupleVariationData.serialize (c, false, tuple_variations));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    if (c->plan->all_axes_pinned)
+      return_trace (false);
+
+    /* subset() for cvar is called by partial instancing only, we always pass
+     * through cvar table in other cases */
+    if (!c->plan->normalized_coords)
+    {
+      unsigned axis_count = c->plan->source->table.fvar->get_axis_count ();
+      unsigned total_size = min_size + tupleVariationData.get_size (axis_count);
+      char *out = c->serializer->allocate_size<char> (total_size);
+      if (unlikely (!out)) return_trace (false);
+
+      hb_memcpy (out, this, total_size);
+      return_trace (true);
+    }
+
+    OT::TupleVariationData::tuple_variations_t tuple_variations;
+    unsigned axis_count = c->plan->axes_old_index_tag_map.get_population ();
+
+    const hb_tag_t cvt = HB_TAG('c','v','t',' ');
+    hb_blob_t *cvt_blob = hb_face_reference_table (c->plan->source, cvt);
+    unsigned point_count = hb_blob_get_length (cvt_blob) / FWORD::static_size;
+
+    if (!decompile_tuple_variations (axis_count, point_count, false,
+                                     &(c->plan->axes_old_index_tag_map),
+                                     tuple_variations))
+      return_trace (false);
+
+    tuple_variations.instantiate (c->plan->axes_location);
+    if (!tuple_variations.compile_bytes (c->plan->axes_index_map, c->plan->axes_old_index_tag_map))
+      return_trace (false);
+
+    return_trace (serialize (c->serializer, tuple_variations));
+  }
+
   static bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan,
                                         const TupleVariationData *tuple_var_data,
                                         const void *base)

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -39,6 +39,24 @@
 
 namespace OT {
 
+static bool axis_coord_pinned_or_within_axis_range (const hb_array_t<const F16DOT16> coords,
+                                                    unsigned axis_index,
+                                                    Triple axis_limit)
+{
+  float axis_coord = coords[axis_index].to_float ();
+  if (axis_limit.is_point ())
+  {
+    if (axis_limit.minimum != axis_coord)
+      return false;
+  }
+  else
+  {
+    if (axis_coord < axis_limit.minimum ||
+        axis_coord > axis_limit.maximum)
+      return false;
+  }
+  return true;
+}
 
 struct InstanceRecord
 {
@@ -47,6 +65,27 @@
   hb_array_t<const F16DOT16> get_coordinates (unsigned int axis_count) const
   { return coordinatesZ.as_array (axis_count); }
 
+  bool keep_instance (unsigned axis_count,
+                      const hb_map_t *axes_index_tag_map,
+                      const hb_hashmap_t<hb_tag_t, Triple> *axes_location) const
+  {
+    if (axes_location->is_empty ()) return true;
+    const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count);
+    for (unsigned i = 0 ; i < axis_count; i++)
+    {
+      uint32_t *axis_tag;
+      if (!axes_index_tag_map->has (i, &axis_tag))
+        return false;
+      if (!axes_location->has (*axis_tag))
+        continue;
+      
+      Triple axis_limit = axes_location->get (*axis_tag);
+      if (!axis_coord_pinned_or_within_axis_range (coords, i, axis_limit))
+        return false;
+    }
+    return true;
+  }
+
   bool subset (hb_subset_context_t *c,
                unsigned axis_count,
                bool has_postscript_nameid) const
@@ -56,20 +95,23 @@
     if (unlikely (!c->serializer->embed (flags))) return_trace (false);
 
     const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count);
-    const hb_hashmap_t<hb_tag_t, float> *axes_location = &c->plan->user_axes_location;
+    const hb_hashmap_t<hb_tag_t, Triple> *axes_location = &c->plan->user_axes_location;
     for (unsigned i = 0 ; i < axis_count; i++)
     {
       uint32_t *axis_tag;
       // only keep instances whose coordinates == pinned axis location
       if (!c->plan->axes_old_index_tag_map.has (i, &axis_tag)) continue;
+      if (axes_location->has (*axis_tag))
+      {
+        Triple axis_limit = axes_location->get (*axis_tag);
+        if (!axis_coord_pinned_or_within_axis_range (coords, i, axis_limit))
+          return_trace (false);
+        
+        //skip pinned axis
+        if (axis_limit.is_point ())
+          continue;
+      }
 
-      if (axes_location->has (*axis_tag) &&
-          fabsf (axes_location->get (*axis_tag) - coords[i].to_float ()) > 0.001f)
-        return_trace (false);
-
-      if (!c->plan->axes_index_map.has (i))
-        continue;
-
       if (!c->serializer->embed (coords[i]))
         return_trace (false);
     }
@@ -216,7 +258,8 @@
 		  axisSize == 20 && /* Assumed in our code. */
 		  instanceSize >= axisCount * 4 + 4 &&
 		  get_axes ().sanitize (c) &&
-		  c->check_range (get_instance (0), instanceCount, instanceSize));
+		  c->check_range (&StructAfter<InstanceRecord> (get_axes ()),
+				  instanceCount, instanceSize));
   }
 
   unsigned int get_axis_count () const { return axisCount; }
@@ -314,21 +357,19 @@
     return axisCount;
   }
 
-  void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+  void collect_name_ids (hb_hashmap_t<hb_tag_t, Triple> *user_axes_location,
+			 hb_map_t *axes_old_index_tag_map,
 			 hb_set_t *nameids  /* IN/OUT */) const
   {
     if (!has_data ()) return;
-    hb_map_t pinned_axes;
 
     auto axis_records = get_axes ();
     for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
     {
       hb_tag_t axis_tag = axis_records[i].get_axis_tag ();
-      if (user_axes_location->has (axis_tag))
-      {
-        pinned_axes.set (i, axis_tag);
+      if (user_axes_location->has (axis_tag) &&
+          user_axes_location->get (axis_tag).is_point ())
         continue;
-      }
 
       nameids->add (axis_records[i].get_name_id ());
     }
@@ -337,16 +378,7 @@
     {
       const InstanceRecord *instance = get_instance (i);
 
-      if (hb_any (+ hb_enumerate (instance->get_coordinates (axisCount))
-                  | hb_filter (pinned_axes, hb_first)
-                  | hb_map ([&] (const hb_pair_t<unsigned, const F16DOT16&>& _)
-                            {
-                              hb_tag_t axis_tag = pinned_axes.get (_.first);
-                              float location = user_axes_location->get (axis_tag);
-                              if (fabs ((double)location - (double)_.second.to_float ()) > 0.001) return true;
-                              return false;
-                            })
-                  ))
+      if (!instance->keep_instance (axisCount, axes_old_index_tag_map, user_axes_location))
         continue;
 
       nameids->add (instance->subfamilyNameID);

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -50,13 +50,14 @@
 	  y  = x * matrix[1] + y * matrix[3];
     x  = x_;
   }
+  HB_ALWAYS_INLINE
   void translate (const contour_point_t &p) { x += p.x; y += p.y; }
 
 
-  float x = 0.f;
-  float y = 0.f;
-  uint8_t flag = 0;
-  bool is_end_point = false;
+  float x;
+  float y;
+  uint8_t flag;
+  bool is_end_point;
 };
 
 struct contour_point_vector_t : hb_vector_t<contour_point_t>
@@ -110,13 +111,13 @@
     unsigned int num_glyphs = c->plan->num_output_glyphs ();
     out->glyphCountX = hb_min (0xFFFFu, num_glyphs);
 
+    auto it = hb_iter (c->plan->new_to_old_gid_list);
+    if (it->first == 0 && !(c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+      it++;
     unsigned int subset_data_size = 0;
-    for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
-         gid < num_glyphs;
-         gid++)
+    for (auto &_ : it)
     {
-      hb_codepoint_t old_gid;
-      if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue;
+      hb_codepoint_t old_gid = _.second;
       subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length;
     }
 
@@ -123,7 +124,7 @@
     bool long_offset = subset_data_size & ~0xFFFFu;
     out->flags = long_offset ? 1 : 0;
 
-    HBUINT8 *subset_offsets = c->serializer->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1));
+    HBUINT8 *subset_offsets = c->serializer->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1), false);
     if (!subset_offsets) return_trace (false);
 
     /* shared tuples */
@@ -138,36 +139,61 @@
       hb_memcpy (tuples, this+sharedTuples, shared_tuple_size);
     }
 
-    char *subset_data = c->serializer->allocate_size<char> (subset_data_size);
+    char *subset_data = c->serializer->allocate_size<char> (subset_data_size, false);
     if (!subset_data) return_trace (false);
     out->dataZ = subset_data - (char *) out;
 
+
+    if (long_offset)
+    {
+      ((HBUINT32 *) subset_offsets)[0] = 0;
+      subset_offsets += 4;
+    }
+    else
+    {
+      ((HBUINT16 *) subset_offsets)[0] = 0;
+      subset_offsets += 2;
+    }
     unsigned int glyph_offset = 0;
-    for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
-         gid < num_glyphs;
-         gid++)
+
+    hb_codepoint_t last = 0;
+    it = hb_iter (c->plan->new_to_old_gid_list);
+    if (it->first == 0 && !(c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+      it++;
+    for (auto &_ : it)
     {
-      hb_codepoint_t old_gid;
-      hb_bytes_t var_data_bytes = c->plan->old_gid_for_new_gid (gid, &old_gid)
-				? get_glyph_var_data_bytes (c->source_blob,
+      hb_codepoint_t gid = _.first;
+      hb_codepoint_t old_gid = _.second;
+
+      if (long_offset)
+	for (; last < gid; last++)
+	  ((HBUINT32 *) subset_offsets)[last] = glyph_offset;
+      else
+	for (; last < gid; last++)
+	  ((HBUINT16 *) subset_offsets)[last] = glyph_offset / 2;
+
+      hb_bytes_t var_data_bytes = get_glyph_var_data_bytes (c->source_blob,
 							    glyph_count,
-							    old_gid)
-				: hb_bytes_t ();
+							    old_gid);
 
+      hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
+      subset_data += var_data_bytes.length;
+      glyph_offset += var_data_bytes.length;
+
       if (long_offset)
 	((HBUINT32 *) subset_offsets)[gid] = glyph_offset;
       else
 	((HBUINT16 *) subset_offsets)[gid] = glyph_offset / 2;
 
-      if (var_data_bytes.length > 0)
-	hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
-      subset_data += var_data_bytes.length;
-      glyph_offset += var_data_bytes.length;
+      last++; // Skip over gid
     }
+
     if (long_offset)
-      ((HBUINT32 *) subset_offsets)[num_glyphs] = glyph_offset;
+      for (; last < num_glyphs; last++)
+	((HBUINT32 *) subset_offsets)[last] = glyph_offset;
     else
-      ((HBUINT16 *) subset_offsets)[num_glyphs] = glyph_offset / 2;
+      for (; last < num_glyphs; last++)
+	((HBUINT16 *) subset_offsets)[last] = glyph_offset / 2;
 
     return_trace (true);
   }
@@ -216,21 +242,24 @@
       for (unsigned i = 0; i < count; i++)
       {
 	hb_array_t<const F2DOT14> tuple = shared_tuples.sub_array (axis_count * i, axis_count);
-	int idx = -1;
+	int idx1 = -1, idx2 = -1;
 	for (unsigned j = 0; j < axis_count; j++)
 	{
 	  const F2DOT14 &peak = tuple.arrayZ[j];
 	  if (peak.to_int () != 0)
 	  {
-	    if (idx != -1)
+	    if (idx1 == -1)
+	      idx1 = j;
+	    else if (idx2 == -1)
+	      idx2 = j;
+	    else
 	    {
-	      idx = -1;
+	      idx1 = idx2 = -1;
 	      break;
 	    }
-	    idx = j;
 	  }
 	}
-	shared_tuple_active_idx.arrayZ[i] = idx;
+	shared_tuple_active_idx.arrayZ[i] = {idx1, idx2};
       }
     }
     ~accelerator_t () { table.destroy (); }
@@ -266,10 +295,9 @@
     public:
     bool apply_deltas_to_points (hb_codepoint_t glyph,
 				 hb_array_t<int> coords,
-				 const hb_array_t<contour_point_t> points) const
+				 const hb_array_t<contour_point_t> points,
+				 bool phantom_only = false) const
     {
-      if (!coords) return true;
-
       if (unlikely (glyph >= glyphCount)) return true;
 
       hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyphCount, glyph);
@@ -297,6 +325,7 @@
       hb_vector_t<unsigned int> private_indices;
       hb_vector_t<int> x_deltas;
       hb_vector_t<int> y_deltas;
+      unsigned count = points.length;
       bool flush = false;
       do
       {
@@ -310,9 +339,10 @@
 
 	if (!deltas)
 	{
-	  if (unlikely (!deltas_vec.resize (points.length, false))) return false;
+	  if (unlikely (!deltas_vec.resize (count, false))) return false;
 	  deltas = deltas_vec.as_array ();
-	  hb_memset (deltas.arrayZ, 0, deltas.get_size ()); // Faster than vector resize
+	  hb_memset (deltas.arrayZ + (phantom_only ? count - 4 : 0), 0,
+		     (phantom_only ? 4 : count) * sizeof (deltas[0]));
 	}
 
 	const HBUINT8 *end = p + length;
@@ -332,7 +362,7 @@
 
 	if (!apply_to_all)
 	{
-	  if (!orig_points)
+	  if (!orig_points && !phantom_only)
 	  {
 	    orig_points_vec.extend (points);
 	    if (unlikely (orig_points_vec.in_error ())) return false;
@@ -341,13 +371,13 @@
 
 	  if (flush)
 	  {
-	    unsigned count = points.length;
-	    for (unsigned int i = 0; i < count; i++)
+	    for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
 	      points.arrayZ[i].translate (deltas.arrayZ[i]);
 	    flush = false;
 
 	  }
-	  hb_memset (deltas.arrayZ, 0, deltas.get_size ());
+	  hb_memset (deltas.arrayZ + (phantom_only ? count - 4 : 0), 0,
+		     (phantom_only ? 4 : count) * sizeof (deltas[0]));
 	}
 
 	if (HB_OPTIMIZE_SIZE_VAL)
@@ -362,6 +392,7 @@
 	      pt_index = indices[i];
 	      if (unlikely (pt_index >= deltas.length)) continue;
 	    }
+	    if (phantom_only && pt_index < count - 4) continue;
 	    auto &delta = deltas.arrayZ[pt_index];
 	    delta.flag = 1;	/* this point is referenced, i.e., explicit deltas specified */
 	    delta.x += x_deltas.arrayZ[i] * scalar;
@@ -374,7 +405,7 @@
 	  if (scalar != 1.0f)
 	  {
 	    if (apply_to_all)
-	      for (unsigned int i = 0; i < num_deltas; i++)
+	      for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
 	      {
 		unsigned int pt_index = i;
 		auto &delta = deltas.arrayZ[pt_index];
@@ -386,6 +417,7 @@
 	      {
 		unsigned int pt_index = indices[i];
 		if (unlikely (pt_index >= deltas.length)) continue;
+		if (phantom_only && pt_index < count - 4) continue;
 		auto &delta = deltas.arrayZ[pt_index];
 		delta.flag = 1;	/* this point is referenced, i.e., explicit deltas specified */
 		delta.x += x_deltas.arrayZ[i] * scalar;
@@ -395,7 +427,7 @@
 	  else
 	  {
 	    if (apply_to_all)
-	      for (unsigned int i = 0; i < num_deltas; i++)
+	      for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
 	      {
 		unsigned int pt_index = i;
 		auto &delta = deltas.arrayZ[pt_index];
@@ -407,6 +439,7 @@
 	      {
 		unsigned int pt_index = indices[i];
 		if (unlikely (pt_index >= deltas.length)) continue;
+		if (phantom_only && pt_index < count - 4) continue;
 		auto &delta = deltas.arrayZ[pt_index];
 		delta.flag = 1;	/* this point is referenced, i.e., explicit deltas specified */
 		delta.x += x_deltas.arrayZ[i];
@@ -416,11 +449,10 @@
 	}
 
 	/* infer deltas for unreferenced points */
-	if (!apply_to_all)
+	if (!apply_to_all && !phantom_only)
 	{
 	  if (!end_points)
 	  {
-	    unsigned count = points.length;
 	    for (unsigned i = 0; i < count; ++i)
 	      if (points.arrayZ[i].is_end_point)
 		end_points.push (i);
@@ -482,8 +514,7 @@
 
       if (flush)
       {
-        unsigned count = points.length;
-	for (unsigned int i = 0; i < count; i++)
+	for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
 	  points.arrayZ[i].translate (deltas.arrayZ[i]);
       }
 
@@ -495,7 +526,7 @@
     private:
     hb_blob_ptr_t<gvar> table;
     unsigned glyphCount;
-    hb_vector_t<signed> shared_tuple_active_idx;
+    hb_vector_t<hb_pair_t<int, int>> shared_tuple_active_idx;
   };
 
   protected:

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -56,8 +56,8 @@
     if (&index_map == &Null (DeltaSetIndexMap)) return;
 
     unsigned int	last_val = (unsigned int)-1;
-    hb_codepoint_t	last_gid = (hb_codepoint_t)-1;
-    hb_codepoint_t	gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ());
+    hb_codepoint_t	last_gid = HB_CODEPOINT_INVALID;
+    hb_codepoint_t	num_gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ());
 
     outer_bit_count = (index_map.get_width () * 8) - index_map.get_inner_bit_count ();
     max_inners.resize (inner_sets.length);
@@ -64,44 +64,48 @@
     for (unsigned i = 0; i < inner_sets.length; i++) max_inners[i] = 0;
 
     /* Search backwards for a map value different from the last map value */
-    for (; gid > 0; gid--)
+    auto &new_to_old_gid_list = plan->new_to_old_gid_list;
+    unsigned count = new_to_old_gid_list.length;
+    for (unsigned j = count; j; j--)
     {
-      hb_codepoint_t	old_gid;
-      if (!plan->old_gid_for_new_gid (gid - 1, &old_gid))
-      {
-	if (last_gid == (hb_codepoint_t) -1)
-	  continue;
-	else
-	  break;
-      }
+      hb_codepoint_t gid = new_to_old_gid_list[j - 1].first;
+      if (gid >= num_gid) continue;
 
+      hb_codepoint_t old_gid = new_to_old_gid_list[j - 1].second;
+
       unsigned int v = index_map.map (old_gid);
-      if (last_gid == (hb_codepoint_t) -1)
+      if (last_gid == HB_CODEPOINT_INVALID)
       {
+	if (gid + 1 != num_gid)
+	{
+	  last_gid = gid + 1;
+	  break;
+	}
 	last_val = v;
 	last_gid = gid;
 	continue;
       }
-      if (v != last_val) break;
+      if (v != last_val || gid + 1 != last_gid)
+	break;
 
       last_gid = gid;
     }
 
     if (unlikely (last_gid == (hb_codepoint_t)-1)) return;
-    map_count = last_gid;
-    for (gid = 0; gid < map_count; gid++)
+    map_count = last_gid + 1;
+    for (auto _ : plan->new_to_old_gid_list)
     {
-      hb_codepoint_t	old_gid;
-      if (plan->old_gid_for_new_gid (gid, &old_gid))
-      {
-	unsigned int v = index_map.map (old_gid);
-	unsigned int outer = v >> 16;
-	unsigned int inner = v & 0xFFFF;
-	outer_map.add (outer);
-	if (inner > max_inners[outer]) max_inners[outer] = inner;
-	if (outer >= inner_sets.length) return;
-	inner_sets[outer]->add (inner);
-      }
+      hb_codepoint_t gid = _.first;
+      if (gid >= map_count) break;
+
+      hb_codepoint_t old_gid = _.second;
+      unsigned int v = index_map.map (old_gid);
+      unsigned int outer = v >> 16;
+      unsigned int inner = v & 0xFFFF;
+      outer_map.add (outer);
+      if (inner > max_inners[outer]) max_inners[outer] = inner;
+      if (outer >= inner_sets.length) return;
+      inner_sets[outer]->add (inner);
     }
   }
 
@@ -197,7 +201,8 @@
 
     if (retain_adv_map)
     {
-      for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
+      unsigned num_glyphs = plan->num_output_glyphs ();
+      for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
       {
 	if (inner_sets[0]->has (gid))
 	  inner_maps[0].add (gid);

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -90,7 +90,7 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    VORG *vorg_prime = c->serializer->start_embed<VORG> ();
+    auto *vorg_prime = c->serializer->start_embed<VORG> ();
     if (unlikely (!c->serializer->check_success (vorg_prime))) return_trace (false);
 
     auto it =

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -58,7 +58,7 @@
     if (unlikely (!next))
     {
       if (unlikely (!chunks.alloc (chunks.length + 1))) return nullptr;
-      chunk_t *chunk = (chunk_t *) hb_calloc (1, sizeof (chunk_t));
+      chunk_t *chunk = (chunk_t *) hb_malloc (sizeof (chunk_t));
       if (unlikely (!chunk)) return nullptr;
       chunks.push (chunk);
       next = chunk->thread ();

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -122,12 +122,14 @@
 {
   hb_sanitize_context_t () :
 	start (nullptr), end (nullptr),
+	length (0),
 	max_ops (0), max_subtables (0),
         recursion_depth (0),
 	writable (false), edit_count (0),
 	blob (nullptr),
 	num_glyphs (65536),
-	num_glyphs_set (false) {}
+	num_glyphs_set (false),
+	lazy_some_gpos (false) {}
 
   const char *get_name () { return "SANITIZE"; }
   template <typename T, typename F>
@@ -155,7 +157,20 @@
   dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
   ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
 
+  hb_sanitize_context_t (hb_blob_t *b) : hb_sanitize_context_t ()
+  {
+    init (b);
 
+    if (blob)
+      start_processing ();
+  }
+
+  ~hb_sanitize_context_t ()
+  {
+    if (blob)
+      end_processing ();
+  }
+
   void init (hb_blob_t *b)
   {
     this->blob = hb_blob_reference (b);
@@ -180,11 +195,15 @@
 
     const char *obj_start = (const char *) obj;
     if (unlikely (obj_start < this->start || this->end <= obj_start))
+    {
       this->start = this->end = nullptr;
+      this->length = 0;
+    }
     else
     {
       this->start = obj_start;
       this->end   = obj_start + hb_min (size_t (this->end - obj_start), obj->get_size ());
+      this->length = this->end - this->start;
     }
   }
 
@@ -192,6 +211,7 @@
   {
     this->start = this->blob->data;
     this->end = this->start + this->blob->length;
+    this->length = this->end - this->start;
     assert (this->start <= this->end); /* Must not overflow. */
   }
 
@@ -224,6 +244,7 @@
     hb_blob_destroy (this->blob);
     this->blob = nullptr;
     this->start = this->end = nullptr;
+    this->length = 0;
   }
 
   unsigned get_edit_count () { return edit_count; }
@@ -240,15 +261,16 @@
     return (this->max_ops -= (int) count) > 0;
   }
 
+#ifndef HB_OPTIMIZE_SIZE
+  HB_ALWAYS_INLINE
+#endif
   bool check_range (const void *base,
 		    unsigned int len) const
   {
     const char *p = (const char *) base;
-    bool ok = !len ||
-	      (this->start <= p &&
-	       p <= this->end &&
-	       (unsigned int) (this->end - p) >= len &&
-	       (this->max_ops -= len) > 0);
+    bool ok = (uintptr_t) (p - this->start) <= this->length &&
+	      (unsigned int) (this->end - p) >= len &&
+	      ((this->max_ops -= len) > 0);
 
     DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
 		     "check_range [%p..%p]"
@@ -259,7 +281,44 @@
 
     return likely (ok);
   }
+#ifndef HB_OPTIMIZE_SIZE
+  HB_ALWAYS_INLINE
+#endif
+  bool check_range_fast (const void *base,
+			 unsigned int len) const
+  {
+    const char *p = (const char *) base;
+    bool ok = ((uintptr_t) (p - this->start) <= this->length &&
+	       (unsigned int) (this->end - p) >= len);
 
+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+		     "check_range_fast [%p..%p]"
+		     " (%u bytes) in [%p..%p] -> %s",
+		     p, p + len, len,
+		     this->start, this->end,
+		     ok ? "OK" : "OUT-OF-RANGE");
+
+    return likely (ok);
+  }
+
+#ifndef HB_OPTIMIZE_SIZE
+  HB_ALWAYS_INLINE
+#endif
+  bool check_point (const void *base) const
+  {
+    const char *p = (const char *) base;
+    bool ok = (uintptr_t) (p - this->start) <= this->length;
+
+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+		     "check_point [%p]"
+		     " in [%p..%p] -> %s",
+		     p,
+		     this->start, this->end,
+		     ok ? "OK" : "OUT-OF-RANGE");
+
+    return likely (ok);
+  }
+
   template <typename T>
   bool check_range (const T *base,
 		    unsigned int a,
@@ -282,6 +341,20 @@
   }
 
   template <typename T>
+  HB_ALWAYS_INLINE
+  bool check_array_sized (const T *base, unsigned int len, unsigned len_size) const
+  {
+    if (len_size >= 4)
+    {
+      if (unlikely (hb_unsigned_mul_overflows (len, hb_static_size (T), &len)))
+	return false;
+    }
+    else
+      len = len * hb_static_size (T);
+    return this->check_range (base, len);
+  }
+
+  template <typename T>
   bool check_array (const T *base, unsigned int len) const
   {
     return this->check_range (base, len, hb_static_size (T));
@@ -292,7 +365,7 @@
 		    unsigned int a,
 		    unsigned int b) const
   {
-    return this->check_range (base, a, b, hb_static_size (T));
+    return this->check_range (base, hb_static_size (T), a, b);
   }
 
   bool check_start_recursion (int max_depth)
@@ -309,7 +382,12 @@
 
   template <typename Type>
   bool check_struct (const Type *obj) const
-  { return likely (this->check_range (obj, obj->min_size)); }
+  {
+    if (sizeof (uintptr_t) == sizeof (uint32_t))
+      return likely (this->check_range_fast (obj, obj->min_size));
+    else
+      return likely (this->check_point ((const char *) obj + obj->min_size));
+  }
 
   bool may_edit (const void *base, unsigned int len)
   {
@@ -416,6 +494,7 @@
   }
 
   const char *start, *end;
+  unsigned length;
   mutable int max_ops, max_subtables;
   private:
   int recursion_depth;
@@ -424,6 +503,8 @@
   hb_blob_t *blob;
   unsigned int num_glyphs;
   bool  num_glyphs_set;
+  public:
+  bool lazy_some_gpos;
 };
 
 struct hb_sanitize_with_object_t

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -113,7 +113,7 @@
     {
       // Virtual links aren't considered for equality since they don't affect the functionality
       // of the object.
-      return hb_bytes_t (head, tail - head).hash () ^
+      return hb_bytes_t (head, hb_min (128, tail - head)).hash () ^
           real_links.as_bytes ().hash ();
     }
 
@@ -172,8 +172,14 @@
   };
 
   snapshot_t snapshot ()
-  { return snapshot_t {
-      head, tail, current, current->real_links.length, current->virtual_links.length, errors }; }
+  {
+    return snapshot_t {
+      head, tail, current,
+      current ? current->real_links.length : 0,
+      current ? current->virtual_links.length : 0,
+      errors
+     };
+  }
 
   hb_serialize_context_t (void *start_, unsigned int size) :
     start ((char *) start_),
@@ -261,6 +267,7 @@
 
   /* To be called around main operation. */
   template <typename Type>
+  __attribute__((returns_nonnull))
   Type *start_serialize ()
   {
     DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
@@ -303,6 +310,7 @@
   }
 
   template <typename Type = void>
+  __attribute__((returns_nonnull))
   Type *push ()
   {
     if (unlikely (in_error ())) return start_embed<Type> ();
@@ -323,6 +331,8 @@
   {
     object_t *obj = current;
     if (unlikely (!obj)) return;
+    // Allow cleanup when we've error'd out on int overflows which don't compromise
+    // the serializer state.
     if (unlikely (in_error() && !only_overflow ())) return;
 
     current = current->next;
@@ -340,7 +350,9 @@
   {
     object_t *obj = current;
     if (unlikely (!obj)) return 0;
-    if (unlikely (in_error())) return 0;
+    // Allow cleanup when we've error'd out on int overflows which don't compromise
+    // the serializer state.
+    if (unlikely (in_error()  && !only_overflow ())) return 0;
 
     current = current->next;
     obj->tail = head;
@@ -405,8 +417,11 @@
     // Overflows that happened after the snapshot will be erased by the revert.
     if (unlikely (in_error () && !only_overflow ())) return;
     assert (snap.current == current);
-    current->real_links.shrink (snap.num_real_links);
-    current->virtual_links.shrink (snap.num_virtual_links);
+    if (current)
+    {
+      current->real_links.shrink (snap.num_real_links);
+      current->virtual_links.shrink (snap.num_virtual_links);
+    }
     errors = snap.errors;
     revert (snap.head, snap.tail);
   }
@@ -563,13 +578,15 @@
   {
     unsigned int l = length () % alignment;
     if (l)
-      allocate_size<void> (alignment - l);
+      (void) allocate_size<void> (alignment - l);
   }
 
   template <typename Type = void>
+  __attribute__((returns_nonnull))
   Type *start_embed (const Type *obj HB_UNUSED = nullptr) const
   { return reinterpret_cast<Type *> (this->head); }
   template <typename Type>
+  __attribute__((returns_nonnull))
   Type *start_embed (const Type &obj) const
   { return start_embed (std::addressof (obj)); }
 
@@ -597,6 +614,7 @@
   }
 
   template <typename Type>
+  HB_NODISCARD
   Type *allocate_size (size_t size, bool clear = true)
   {
     if (unlikely (in_error ())) return nullptr;
@@ -618,6 +636,7 @@
   { return this->allocate_size<Type> (Type::min_size); }
 
   template <typename Type>
+  HB_NODISCARD
   Type *embed (const Type *obj)
   {
     unsigned int size = obj->get_size ();
@@ -627,6 +646,7 @@
     return ret;
   }
   template <typename Type>
+  HB_NODISCARD
   Type *embed (const Type &obj)
   { return embed (std::addressof (obj)); }
   char *embed (const char *obj, unsigned size)

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -88,14 +88,19 @@
 
   bool add_range (hb_codepoint_t a, hb_codepoint_t b)
   {
+    if (mask == (mask_t) -1) return false;
     if ((b >> shift) - (a >> shift) >= mask_bits - 1)
+    {
       mask = (mask_t) -1;
-    else {
+      return false;
+    }
+    else
+    {
       mask_t ma = mask_for (a);
       mask_t mb = mask_for (b);
       mask |= mb + (mb - ma) - (mb < ma);
+      return true;
     }
-    return true;
   }
 
   template <typename T>
@@ -154,8 +159,7 @@
 
   bool add_range (hb_codepoint_t a, hb_codepoint_t b)
   {
-    return head.add_range (a, b) &&
-	   tail.add_range (a, b);
+    return (int) head.add_range (a, b) | (int) tail.add_range (a, b);
   }
   template <typename T>
   void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.h	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.h	2023-07-09 05:55:34 UTC (rev 67588)
@@ -43,7 +43,7 @@
  *
  * Since: 0.9.21
  */
-#define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1)
+#define HB_SET_VALUE_INVALID HB_CODEPOINT_INVALID
 
 /**
  * hb_set_t:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -115,7 +115,7 @@
   /* Sink interface. */
   hb_sparseset_t& operator << (hb_codepoint_t v)
   { add (v); return *this; }
-  hb_sparseset_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+  hb_sparseset_t& operator << (const hb_codepoint_pair_t& range)
   { add_range (range.first, range.second); return *this; }
 
   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
@@ -174,7 +174,7 @@
 
   hb_set_t& operator << (hb_codepoint_t v)
   { sparseset::operator<< (v); return *this; }
-  hb_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+  hb_set_t& operator << (const hb_codepoint_pair_t& range)
   { sparseset::operator<< (range); return *this; }
 };
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -220,7 +220,7 @@
   assert (buffer->ensure (text.length));
   buffer->have_positions = false;
   buffer->len = text.length;
-  memcpy (buffer->info, text.arrayZ, text.length * sizeof (buffer->info[0]));
+  hb_memcpy (buffer->info, text.arrayZ, text.length * sizeof (buffer->info[0]));
   hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
 }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -33,6 +33,11 @@
 
 /* v--- Add new shapers in the right place here. */
 
+#ifdef HAVE_WASM
+/* Only picks up fonts that have a "Wasm" table. */
+HB_SHAPER_IMPLEMENT (wasm)
+#endif
+
 #ifdef HAVE_GRAPHITE2
 /* Only picks up fonts that have a "Silf" table. */
 HB_SHAPER_IMPLEMENT (graphite2)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -31,6 +31,7 @@
 
 #include "hb-aat-layout-common.hh"
 #include "hb-aat-layout-feat-table.hh"
+#include "hb-cff-interp-common.hh"
 #include "hb-ot-layout-common.hh"
 #include "hb-ot-cmap-table.hh"
 #include "OT/Color/COLR/COLR.hh"
@@ -58,6 +59,8 @@
 /* hb_map_t */
 
 const hb_codepoint_t minus_1 = -1;
+static const unsigned char static_endchar_str[] = {OpCode_endchar};
+const unsigned char *endchar_str = static_endchar_str;
 
 /* hb_face_t */
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-accelerator.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-accelerator.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-accelerator.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -42,7 +42,9 @@
 
 namespace OT {
 struct SubtableUnicodesCache;
-};
+struct cff1_subset_accelerator_t;
+struct cff2_subset_accelerator_t;
+}
 
 struct hb_subset_accelerator_t
 {
@@ -51,8 +53,8 @@
     return &_hb_subset_accelerator_user_data_key;
   }
 
-  static hb_subset_accelerator_t* create(const hb_map_t& unicode_to_gid_,
-					 const hb_multimap_t gid_to_unicodes_,
+  static hb_subset_accelerator_t* create(hb_face_t *source,
+					 const hb_map_t& unicode_to_gid_,
 					 const hb_set_t& unicodes_,
 					 bool has_seac_) {
     hb_subset_accelerator_t* accel =
@@ -60,8 +62,8 @@
 
     if (unlikely (!accel)) return accel;
 
-    new (accel) hb_subset_accelerator_t (unicode_to_gid_,
-					 gid_to_unicodes_,
+    new (accel) hb_subset_accelerator_t (source,
+					 unicode_to_gid_,
 					 unicodes_,
 					 has_seac_);
 
@@ -79,36 +81,36 @@
     hb_free (accel);
   }
 
-  hb_subset_accelerator_t (const hb_map_t& unicode_to_gid_,
-			   const hb_multimap_t& gid_to_unicodes_,
+  hb_subset_accelerator_t (hb_face_t *source,
+			   const hb_map_t& unicode_to_gid_,
 			   const hb_set_t& unicodes_,
 			   bool has_seac_) :
     unicode_to_gid(unicode_to_gid_),
-    gid_to_unicodes (gid_to_unicodes_),
     unicodes(unicodes_),
     cmap_cache(nullptr),
     destroy_cmap_cache(nullptr),
     has_seac(has_seac_),
-    cff_accelerator(nullptr),
-    destroy_cff_accelerator(nullptr) {}
-
-  ~hb_subset_accelerator_t ()
+    source(hb_face_reference (source))
   {
-    if (cff_accelerator && destroy_cff_accelerator)
-      destroy_cff_accelerator ((void*) cff_accelerator);
-
-    if (cmap_cache && destroy_cmap_cache)
-      destroy_cmap_cache ((void*) cmap_cache);
+    gid_to_unicodes.alloc (unicode_to_gid.get_population ());
+    for (const auto &_ : unicode_to_gid)
+    {
+      auto unicode = _.first;
+      auto gid = _.second;
+      gid_to_unicodes.add (gid, unicode);
+    }
   }
 
+  HB_INTERNAL ~hb_subset_accelerator_t ();
+
   // Generic
 
   mutable hb_mutex_t sanitized_table_cache_lock;
   mutable hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>> sanitized_table_cache;
 
-  const hb_map_t unicode_to_gid;
-  const hb_multimap_t gid_to_unicodes;
-  const hb_set_t unicodes;
+  hb_map_t unicode_to_gid;
+  hb_multimap_t gid_to_unicodes;
+  hb_set_t unicodes;
 
   // cmap
   const OT::SubtableUnicodesCache* cmap_cache;
@@ -116,8 +118,6 @@
 
   // CFF
   bool has_seac;
-  const CFF::cff_subset_accelerator_t* cff_accelerator;
-  hb_destroy_func_t destroy_cff_accelerator;
 
   // TODO(garretrieger): cumulative glyf checksum map
 
@@ -128,6 +128,13 @@
 	   unicodes.in_error () ||
 	   sanitized_table_cache.in_error ();
   }
+
+  hb_face_t *source;
+#ifndef HB_NO_SUBSET_CFF
+  // These have to be immediately after source:
+  mutable hb_face_lazy_loader_t<OT::cff1_subset_accelerator_t, 1> cff1_accel;
+  mutable hb_face_lazy_loader_t<OT::cff2_subset_accelerator_t, 2> cff2_accel;
+#endif
 };
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -68,24 +68,35 @@
     /* use hb_set to determine the subset of font dicts */
     hb_set_t set;
     hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
-    for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
+    hb_pair_t<unsigned, hb_codepoint_t> last_range {0, 0};
+    auto it = hb_iter (plan->new_to_old_gid_list);
+    auto _ = *it;
+    for (hb_codepoint_t gid = 0; gid < subset_num_glyphs; gid++)
     {
-      hb_codepoint_t glyph;
-      hb_codepoint_t fd;
-      if (!plan->old_gid_for_new_gid (i, &glyph))
+      hb_codepoint_t old_glyph;
+      if (gid == _.first)
       {
+	old_glyph = _.second;
+	_ = *++it;
+      }
+      else
+      {
 	/* fonttools retains FDSelect & font dicts for missing glyphs. do the same */
-	glyph = i;
+	old_glyph = gid;
       }
-      fd = src.get_fd (glyph);
-      set.add (fd);
+      if (old_glyph >= last_range.second)
+	last_range = src.get_fd_range (old_glyph);
+      unsigned fd = last_range.first;
 
       if (fd != prev_fd)
       {
+	set.add (fd);
 	num_ranges++;
 	prev_fd = fd;
-	code_pair_t pair = { fd, i };
-	fdselect_ranges.push (pair);
+	fdselect_ranges.push (code_pair_t { fd, gid });
+
+	if (gid == old_glyph)
+	  gid = hb_min (_.first - 1, last_range.second - 1);
       }
     }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -480,6 +480,7 @@
       const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs) {
     cff_subset_accelerator_t* accel =
         (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t));
+    if (unlikely (!accel)) return nullptr;
     new (accel) cff_subset_accelerator_t (original_blob,
                                           parsed_charstrings,
                                           parsed_global_subrs,
@@ -510,15 +511,21 @@
     original_blob = hb_blob_reference (original_blob_);
   }
 
-  ~cff_subset_accelerator_t() {
+  ~cff_subset_accelerator_t()
+  {
     hb_blob_destroy (original_blob);
-    hb_map_destroy (glyph_to_sid_map.get_relaxed ());
+    auto *mapping = glyph_to_sid_map.get_relaxed ();
+    if (mapping)
+    {
+      mapping->~glyph_to_sid_map_t ();
+      hb_free (mapping);
+    }
   }
 
   parsed_cs_str_vec_t parsed_charstrings;
   parsed_cs_str_vec_t parsed_global_subrs;
   hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
-  mutable hb_atomic_ptr_t<hb_map_t> glyph_to_sid_map = nullptr;
+  mutable hb_atomic_ptr_t<glyph_to_sid_map_t> glyph_to_sid_map;
 
  private:
   hb_blob_t* original_blob;
@@ -600,9 +607,8 @@
      * no optimization based on usage counts. fonttools doesn't appear doing that either.
      */
 
-    resize (closure->get_population ());
-    hb_codepoint_t old_num = HB_SET_VALUE_INVALID;
-    while (hb_set_next (closure, &old_num))
+    alloc (closure->get_population ());
+    for (auto old_num : *closure)
       add (old_num);
 
     if (get_population () < 1240)
@@ -672,8 +678,8 @@
   {
     unsigned fd_count = acc.fdCount;
     const cff_subset_accelerator_t* cff_accelerator = nullptr;
-    if (plan->accelerator && plan->accelerator->cff_accelerator) {
-      cff_accelerator = plan->accelerator->cff_accelerator;
+    if (acc.cff_accelerator) {
+      cff_accelerator = acc.cff_accelerator;
       fd_count = cff_accelerator->parsed_local_subrs.length;
     }
 
@@ -709,14 +715,13 @@
     }
 
     /* phase 1 & 2 */
-    for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+    for (auto _ : plan->new_to_old_gid_list)
     {
-      hb_codepoint_t  glyph;
-      if (!plan->old_gid_for_new_gid (i, &glyph))
-        continue;
+      hb_codepoint_t new_glyph = _.first;
+      hb_codepoint_t old_glyph = _.second;
 
-      const hb_ubytes_t str = (*acc.charStrings)[glyph];
-      unsigned int fd = acc.fdSelect->get_fd (glyph);
+      const hb_ubytes_t str = (*acc.charStrings)[old_glyph];
+      unsigned int fd = acc.fdSelect->get_fd (old_glyph);
       if (unlikely (fd >= acc.fdCount))
         return false;
 
@@ -725,9 +730,9 @@
         // parsed string already exists in accelerator, copy it and move
         // on.
         if (cached_charstrings)
-          cached_charstrings[i] = &cff_accelerator->parsed_charstrings[glyph];
+          cached_charstrings[new_glyph] = &cff_accelerator->parsed_charstrings[old_glyph];
         else
-          parsed_charstrings[i] = cff_accelerator->parsed_charstrings[glyph];
+          parsed_charstrings[new_glyph] = cff_accelerator->parsed_charstrings[old_glyph];
 
         continue;
       }
@@ -735,8 +740,8 @@
       ENV env (str, acc, fd);
       cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env);
 
-      parsed_charstrings[i].alloc (str.length);
-      subr_subset_param_t  param (&parsed_charstrings[i],
+      parsed_charstrings[new_glyph].alloc (str.length);
+      subr_subset_param_t  param (&parsed_charstrings[new_glyph],
                                   &parsed_global_subrs_storage,
                                   &parsed_local_subrs_storage[fd],
                                   &closures.global_closure,
@@ -747,12 +752,12 @@
         return false;
 
       /* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
-      SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
+      SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[new_glyph]);
 
       /* mark hint ops and arguments for drop */
       if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING) || plan->inprogress_accelerator)
       {
-	subr_subset_param_t  param (&parsed_charstrings[i],
+	subr_subset_param_t  param (&parsed_charstrings[new_glyph],
 				    &parsed_global_subrs_storage,
 				    &parsed_local_subrs_storage[fd],
 				    &closures.global_closure,
@@ -760,11 +765,11 @@
 				    plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
 
 	drop_hints_param_t  drop;
-	if (drop_hints_in_str (parsed_charstrings[i], param, drop))
+	if (drop_hints_in_str (parsed_charstrings[new_glyph], param, drop))
 	{
-	  parsed_charstrings[i].set_hint_dropped ();
+	  parsed_charstrings[new_glyph].set_hint_dropped ();
 	  if (drop.vsindex_dropped)
-	    parsed_charstrings[i].set_vsindex_dropped ();
+	    parsed_charstrings[new_glyph].set_vsindex_dropped ();
 	}
       }
 
@@ -774,7 +779,7 @@
        * The compacting both saves memory and makes further operations
        * faster.
        */
-      parsed_charstrings[i].compact ();
+      parsed_charstrings[new_glyph].compact ();
     }
 
     /* Since parsed strings were loaded from accelerator, we still need
@@ -797,23 +802,40 @@
 
   bool encode_charstrings (str_buff_vec_t &buffArray, bool encode_prefix = true) const
   {
-    if (unlikely (!buffArray.resize_exact (plan->num_output_glyphs ())))
+    unsigned num_glyphs = plan->num_output_glyphs ();
+    if (unlikely (!buffArray.resize_exact (num_glyphs)))
       return false;
-    for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+    hb_codepoint_t last = 0;
+    for (auto _ : plan->new_to_old_gid_list)
     {
-      hb_codepoint_t  glyph;
-      if (!plan->old_gid_for_new_gid (i, &glyph))
-      {
-	/* add an endchar only charstring for a missing glyph if CFF1 */
-	if (endchar_op != OpCode_Invalid) buffArray.arrayZ[i].push (endchar_op);
-	continue;
-      }
-      unsigned int  fd = acc.fdSelect->get_fd (glyph);
+      hb_codepoint_t gid = _.first;
+      hb_codepoint_t old_glyph = _.second;
+
+      if (endchar_op != OpCode_Invalid)
+        for (; last < gid; last++)
+	{
+	  // Hack to point vector to static string.
+	  auto &b = buffArray.arrayZ[last];
+	  b.length = 1;
+	  b.arrayZ = const_cast<unsigned char *>(endchar_str);
+	}
+
+      last++; // Skip over gid
+      unsigned int  fd = acc.fdSelect->get_fd (old_glyph);
       if (unlikely (fd >= acc.fdCount))
 	return false;
-      if (unlikely (!encode_str (get_parsed_charstring (i), fd, buffArray.arrayZ[i], encode_prefix)))
+      if (unlikely (!encode_str (get_parsed_charstring (gid), fd, buffArray.arrayZ[gid], encode_prefix)))
 	return false;
     }
+    if (endchar_op != OpCode_Invalid)
+      for (; last < num_glyphs; last++)
+      {
+	// Hack to point vector to static string.
+	auto &b = buffArray.arrayZ[last];
+	b.length = 1;
+	b.arrayZ = const_cast<unsigned char *>(endchar_str);
+      }
+
     return true;
   }
 
@@ -980,24 +1002,23 @@
                             const hb_vector_t<parsed_cs_str_vec_t>& local_subrs)
   {
     closures.reset ();
-    for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+    for (auto _ : plan->new_to_old_gid_list)
     {
-      hb_codepoint_t  glyph;
-      if (!plan->old_gid_for_new_gid (i, &glyph))
-        continue;
-      unsigned int fd = acc.fdSelect->get_fd (glyph);
+      hb_codepoint_t new_glyph = _.first;
+      hb_codepoint_t old_glyph = _.second;
+      unsigned int fd = acc.fdSelect->get_fd (old_glyph);
       if (unlikely (fd >= acc.fdCount))
         return false;
 
       // Note: const cast is safe here because the collect_subr_refs_in_str only performs a
       //       closure and does not modify any of the charstrings.
-      subr_subset_param_t  param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (i)),
+      subr_subset_param_t  param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (new_glyph)),
                                   const_cast<parsed_cs_str_vec_t*> (&global_subrs),
                                   const_cast<parsed_cs_str_vec_t*> (&local_subrs[fd]),
                                   &closures.global_closure,
                                   &closures.local_closures[fd],
                                   plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
-      collect_subr_refs_in_str (get_parsed_charstring (i), param);
+      collect_subr_refs_in_str (get_parsed_charstring (new_glyph), param);
     }
 
     return true;
@@ -1105,14 +1126,11 @@
 
     compact_parsed_subrs ();
 
-    plan->inprogress_accelerator->cff_accelerator =
+    acc.cff_accelerator =
         cff_subset_accelerator_t::create(acc.blob,
                                          parsed_charstrings,
                                          parsed_global_subrs_storage,
                                          parsed_local_subrs_storage);
-    plan->inprogress_accelerator->destroy_cff_accelerator =
-        cff_subset_accelerator_t::destroy;
-
   }
 
   const parsed_cs_str_t& get_parsed_charstring (unsigned i) const

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -32,7 +32,6 @@
 #include "hb-ot-cff1-table.hh"
 #include "hb-set.h"
 #include "hb-bimap.hh"
-#include "hb-subset-cff1.hh"
 #include "hb-subset-plan.hh"
 #include "hb-subset-cff-common.hh"
 #include "hb-cff1-interp-cs.hh"
@@ -39,29 +38,53 @@
 
 using namespace CFF;
 
-struct remap_sid_t : hb_inc_bimap_t
+struct remap_sid_t
 {
+  unsigned get_population () const { return vector.length; }
+
+  void alloc (unsigned size)
+  {
+    map.alloc (size);
+    vector.alloc (size, true);
+  }
+
+  bool in_error () const
+  { return map.in_error () || vector.in_error (); }
+
   unsigned int add (unsigned int sid)
   {
-    if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
-      return offset_sid (hb_inc_bimap_t::add (unoffset_sid (sid)));
+    if (is_std_str (sid) || (sid == CFF_UNDEF_SID))
+      return sid;
+
+    sid = unoffset_sid (sid);
+    unsigned v = next;
+    if (map.set (sid, v, false))
+    {
+      vector.push (sid);
+      next++;
+    }
     else
-      return sid;
+      v = map.get (sid); // already exists
+    return offset_sid (v);
   }
 
   unsigned int operator[] (unsigned int sid) const
   {
-    if (is_std_std (sid) || (sid == CFF_UNDEF_SID))
+    if (is_std_str (sid) || (sid == CFF_UNDEF_SID))
       return sid;
-    else
-      return offset_sid (get (unoffset_sid (sid)));
+
+    return offset_sid (map.get (unoffset_sid (sid)));
   }
 
   static const unsigned int num_std_strings = 391;
 
-  static bool is_std_std (unsigned int sid) { return sid < num_std_strings; }
+  static bool is_std_str (unsigned int sid) { return sid < num_std_strings; }
   static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
   static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
+  unsigned next = 0;
+
+  hb_map_t map;
+  hb_vector_t<unsigned> vector;
 };
 
 struct cff1_sub_table_info_t : cff_sub_table_info_t
@@ -271,16 +294,17 @@
   /* replace the first glyph ID in the "glyph" field each range with a nLeft value */
   bool complete (unsigned int last_glyph)
   {
-    bool two_byte = false;
+    hb_codepoint_t all_glyphs = 0;
     unsigned count = this->length;
     for (unsigned int i = count; i; i--)
     {
       code_pair_t &pair = arrayZ[i - 1];
       unsigned int nLeft = last_glyph - pair.glyph - 1;
-      two_byte |= nLeft >= 0x100;
+      all_glyphs |= nLeft;
       last_glyph = pair.glyph;
       pair.glyph = nLeft;
     }
+    bool two_byte = all_glyphs >= 0x100;
     return two_byte;
   }
 };
@@ -391,8 +415,10 @@
   }
 };
 
-struct cff_subset_plan {
-  cff_subset_plan ()
+namespace OT {
+struct cff1_subset_plan
+{
+  cff1_subset_plan ()
   {
     for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
       topDictModSIDs[i] = CFF_UNDEF_SID;
@@ -402,7 +428,7 @@
   {
     const Encoding *encoding = acc.encoding;
     unsigned int  size0, size1;
-    hb_codepoint_t  code, last_code = CFF_UNDEF_CODE;
+    unsigned code, last_code = CFF_UNDEF_CODE - 1;
     hb_vector_t<hb_codepoint_t> supp_codes;
 
     if (unlikely (!subset_enc_code_ranges.resize (0)))
@@ -413,17 +439,26 @@
 
     supp_codes.init ();
 
+    code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
     subset_enc_num_codes = plan->num_output_glyphs () - 1;
     unsigned int glyph;
-    for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
+    auto it = hb_iter (plan->new_to_old_gid_list);
+    if (it->first == 0) it++;
+    auto _ = *it;
+    for (glyph = 1; glyph < num_glyphs; glyph++)
     {
-      hb_codepoint_t  old_glyph;
-      if (!plan->old_gid_for_new_gid (glyph, &old_glyph))
+      hb_codepoint_t old_glyph;
+      if (glyph == _.first)
       {
-	/* Retain the code for the old missing glyph ID */
+	old_glyph = _.second;
+	_ = *++it;
+      }
+      else
+      {
+	/* Retain the SID for the old missing glyph ID */
 	old_glyph = glyph;
       }
-      code = acc.glyph_to_code (old_glyph);
+      code = acc.glyph_to_code (old_glyph, &glyph_to_sid_cache);
       if (code == CFF_UNDEF_CODE)
       {
 	subset_enc_num_codes = glyph - 1;
@@ -430,22 +465,16 @@
 	break;
       }
 
-      if ((last_code == CFF_UNDEF_CODE) || (code != last_code + 1))
-      {
-	code_pair_t pair = { code, glyph };
-	subset_enc_code_ranges.push (pair);
-      }
+      if (code != last_code + 1)
+	subset_enc_code_ranges.push (code_pair_t {code, glyph});
       last_code = code;
 
       if (encoding != &Null (Encoding))
       {
-	hb_codepoint_t  sid = acc.glyph_to_sid (old_glyph);
+	hb_codepoint_t  sid = acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache);
 	encoding->get_supplement_codes (sid, supp_codes);
 	for (unsigned int i = 0; i < supp_codes.length; i++)
-	{
-	  code_pair_t pair = { supp_codes[i], sid };
-	  subset_enc_supp_codes.push (pair);
-	}
+	  subset_enc_supp_codes.push (code_pair_t {supp_codes[i], sid});
       }
     }
     supp_codes.fini ();
@@ -462,47 +491,74 @@
       subset_enc_format = 1;
   }
 
-  void plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+  bool plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
   {
     unsigned int  size0, size_ranges;
-    hb_codepoint_t  sid, last_sid = CFF_UNDEF_CODE;
+    unsigned last_sid = CFF_UNDEF_CODE - 1;
 
     if (unlikely (!subset_charset_ranges.resize (0)))
     {
       plan->check_success (false);
-      return;
+      return false;
     }
 
-    hb_map_t *glyph_to_sid_map = (plan->accelerator && plan->accelerator->cff_accelerator) ?
-				  plan->accelerator->cff_accelerator->glyph_to_sid_map :
-				  nullptr;
+    code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
+
+    unsigned num_glyphs = plan->num_output_glyphs ();
+
+    if (unlikely (!subset_charset_ranges.alloc (hb_min (num_glyphs,
+							acc.num_charset_entries))))
+    {
+      plan->check_success (false);
+      return false;
+    }
+
+    glyph_to_sid_map_t *glyph_to_sid_map = acc.cff_accelerator ?
+					   acc.cff_accelerator->glyph_to_sid_map.get_acquire () :
+					   nullptr;
     bool created_map = false;
-    if (!glyph_to_sid_map &&
-	((plan->accelerator && plan->accelerator->cff_accelerator) ||
-	 plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.))
+    if (!glyph_to_sid_map && acc.cff_accelerator)
     {
       created_map = true;
       glyph_to_sid_map = acc.create_glyph_to_sid_map ();
     }
 
-    unsigned int glyph;
-    for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
+    auto it = hb_iter (plan->new_to_old_gid_list);
+    if (it->first == 0) it++;
+    auto _ = *it;
+    bool not_is_cid = !acc.is_CID ();
+    bool skip = !not_is_cid && glyph_to_sid_map;
+    if (not_is_cid)
+      sidmap.alloc (num_glyphs);
+    for (hb_codepoint_t glyph = 1; glyph < num_glyphs; glyph++)
     {
-      hb_codepoint_t  old_glyph;
-      if (!plan->old_gid_for_new_gid (glyph, &old_glyph))
+      hb_codepoint_t old_glyph;
+      if (glyph == _.first)
       {
+	old_glyph = _.second;
+	_ = *++it;
+      }
+      else
+      {
 	/* Retain the SID for the old missing glyph ID */
 	old_glyph = glyph;
       }
-      sid = glyph_to_sid_map ? glyph_to_sid_map->get (old_glyph) : acc.glyph_to_sid (old_glyph);
+      unsigned sid = glyph_to_sid_map ?
+		     glyph_to_sid_map->arrayZ[old_glyph].code :
+		     acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache);
 
-      if (!acc.is_CID ())
+      if (not_is_cid)
 	sid = sidmap.add (sid);
 
-      if ((last_sid == CFF_UNDEF_CODE) || (sid != last_sid + 1))
+      if (sid != last_sid + 1)
       {
-	code_pair_t pair = { sid, glyph };
-	subset_charset_ranges.push (pair);
+	subset_charset_ranges.push (code_pair_t {sid, glyph});
+
+	if (glyph == old_glyph && skip)
+	{
+	  glyph = hb_min (_.first - 1, glyph_to_sid_map->arrayZ[old_glyph].glyph);
+	  sid += glyph - old_glyph;
+	}
       }
       last_sid = sid;
     }
@@ -509,18 +565,21 @@
 
     if (created_map)
     {
-      if (!(plan->accelerator && plan->accelerator->cff_accelerator) ||
-	  !plan->accelerator->cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map))
-	hb_map_destroy (glyph_to_sid_map);
+      if ((!plan->accelerator && acc.cff_accelerator) ||
+	  !acc.cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map))
+      {
+	glyph_to_sid_map->~glyph_to_sid_map_t ();
+	hb_free (glyph_to_sid_map);
+      }
     }
 
-    bool two_byte = subset_charset_ranges.complete (glyph);
+    bool two_byte = subset_charset_ranges.complete (num_glyphs);
 
-    size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1);
+    size0 = Charset0::get_size (plan->num_output_glyphs ());
     if (!two_byte)
-      size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length;
+      size_ranges = Charset1::get_size_for_ranges (subset_charset_ranges.length);
     else
-      size_ranges = Charset2::min_size + Charset2_Range::static_size * subset_charset_ranges.length;
+      size_ranges = Charset2::get_size_for_ranges (subset_charset_ranges.length);
 
     if (size0 < size_ranges)
       subset_charset_format = 0;
@@ -528,19 +587,18 @@
       subset_charset_format = 1;
     else
       subset_charset_format = 2;
+
+    return true;
   }
 
   bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
   {
-    sidmap.reset ();
-
     for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
     {
       unsigned int sid = acc.topDict.nameSIDs[i];
       if (sid != CFF_UNDEF_SID)
       {
-	(void)sidmap.add (sid);
-	topDictModSIDs[i] = sidmap[sid];
+	topDictModSIDs[i] = sidmap.add (sid);
       }
     }
 
@@ -564,19 +622,18 @@
     drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
     desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE;
 
-    /* check whether the subset renumbers any glyph IDs */
-    gid_renum = false;
-    for (hb_codepoint_t new_glyph = 0; new_glyph < plan->num_output_glyphs (); new_glyph++)
-    {
-      if (!plan->old_gid_for_new_gid(new_glyph, &old_glyph))
-	continue;
-      if (new_glyph != old_glyph) {
-	gid_renum = true;
-	break;
+    subset_charset = !acc.is_predef_charset ();
+    if (!subset_charset)
+      /* check whether the subset renumbers any glyph IDs */
+      for (const auto &_ : plan->new_to_old_gid_list)
+      {
+	if (_.first != _.second)
+	{
+	  subset_charset = true;
+	  break;
+	}
       }
-    }
 
-    subset_charset = gid_renum || !acc.is_predef_charset ();
     subset_encoding = !acc.is_CID() && !acc.is_predef_encoding ();
 
     /* top dict INDEX */
@@ -618,7 +675,8 @@
       if (unlikely (sidmap.get_population () > 0x8000))	/* assumption: a dict won't reference that many strings */
 	return false;
 
-      if (subset_charset) plan_subset_charset (acc, plan);
+      if (subset_charset && !plan_subset_charset (acc, plan))
+        return false;
 
       topdict_mod.reassignSIDs (sidmap);
     }
@@ -682,8 +740,9 @@
       ;
     }
 
-    return ((subset_charstrings.length == plan->num_output_glyphs ())
-	   && (fontdicts_mod.length == subset_fdcount));
+    return !plan->in_error () &&
+	   (subset_charstrings.length == plan->num_output_glyphs ()) &&
+	   (fontdicts_mod.length == subset_fdcount);
   }
 
   cff1_top_dict_values_mod_t	topdict_mod;
@@ -722,14 +781,14 @@
 
   bool		desubroutinize = false;
 };
+} // namespace OT
 
-static bool _serialize_cff1 (hb_serialize_context_t *c,
-			     cff_subset_plan &plan,
-			     const OT::cff1::accelerator_subset_t  &acc,
-			     unsigned int num_glyphs)
+bool
+OT::cff1::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+					   struct OT::cff1_subset_plan &plan) const
 {
   /* private dicts & local subrs */
-  for (int i = (int)acc.privateDicts.length; --i >= 0 ;)
+  for (int i = (int) privateDicts.length; --i >= 0 ;)
   {
     if (plan.fdmap.has (i))
     {
@@ -736,10 +795,8 @@
       objidx_t	subrs_link = 0;
       if (plan.subset_localsubrs[i].length > 0)
       {
-	CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
-	if (unlikely (!dest)) return false;
-	c->push ();
-	if (likely (dest && dest->serialize (c, plan.subset_localsubrs[i])))
+	auto *dest = c->push <CFF1Subrs> ();
+	if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
 	  subrs_link = c->pop_pack ();
 	else
 	{
@@ -748,12 +805,10 @@
 	}
       }
 
-      PrivateDict *pd = c->start_embed<PrivateDict> ();
-      if (unlikely (!pd)) return false;
-      c->push ();
+      auto *pd = c->push<PrivateDict> ();
       cff1_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
       /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
-      if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link)))
+      if (likely (pd->serialize (c, privateDicts[i], privSzr, subrs_link)))
       {
 	unsigned fd = plan.fdmap[i];
 	plan.fontdicts_mod[fd].privateDictInfo.size = c->length ();
@@ -767,7 +822,7 @@
     }
   }
 
-  if (!acc.is_CID ())
+  if (!is_CID ())
     plan.info.privateDictInfo = plan.fontdicts_mod[0].privateDictInfo;
 
   /* CharStrings */
@@ -774,14 +829,13 @@
   {
     c->push<CFF1CharStrings> ();
 
-    unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings);
+    unsigned data_size = 0;
+    unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size);
     if (unlikely (!c->start_zerocopy (total_size)))
        return false;
 
-    CFF1CharStrings  *cs = c->start_embed<CFF1CharStrings> ();
-    if (unlikely (!cs)) return false;
-
-    if (likely (cs->serialize (c, plan.subset_charstrings)))
+    auto *cs = c->start_embed<CFF1CharStrings> ();
+    if (likely (cs->serialize (c, plan.subset_charstrings, &data_size)))
       plan.info.char_strings_link = c->pop_pack (false);
     else
     {
@@ -791,11 +845,9 @@
   }
 
   /* FDArray (FD Index) */
-  if (acc.fdArray != &Null (CFF1FDArray))
+  if (fdArray != &Null (CFF1FDArray))
   {
-    CFF1FDArray *fda = c->start_embed<CFF1FDArray> ();
-    if (unlikely (!fda)) return false;
-    c->push ();
+    auto *fda = c->push<CFF1FDArray> ();
     cff1_font_dict_op_serializer_t  fontSzr;
     auto it = + hb_zip (+ hb_iter (plan.fontdicts_mod), + hb_iter (plan.fontdicts_mod));
     if (likely (fda->serialize (c, it, fontSzr)))
@@ -808,10 +860,10 @@
   }
 
   /* FDSelect */
-  if (acc.fdSelect != &Null (CFF1FDSelect))
+  if (fdSelect != &Null (CFF1FDSelect))
   {
     c->push ();
-    if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *acc.fdSelect, acc.fdCount,
+    if (likely (hb_serialize_cff_fdselect (c, plan.num_glyphs, *fdSelect, fdCount,
 					   plan.subset_fdselect_format, plan.info.fd_select.size,
 					   plan.subset_fdselect_ranges)))
       plan.info.fd_select.link = c->pop_pack ();
@@ -825,9 +877,7 @@
   /* Charset */
   if (plan.subset_charset)
   {
-    Charset *dest = c->start_embed<Charset> ();
-    if (unlikely (!dest)) return false;
-    c->push ();
+    auto *dest = c->push<Charset> ();
     if (likely (dest->serialize (c,
 				 plan.subset_charset_format,
 				 plan.num_glyphs,
@@ -843,9 +893,7 @@
   /* Encoding */
   if (plan.subset_encoding)
   {
-    Encoding *dest = c->start_embed<Encoding> ();
-    if (unlikely (!dest)) return false;
-    c->push ();
+    auto *dest = c->push<Encoding> ();
     if (likely (dest->serialize (c,
 				 plan.subset_enc_format,
 				 plan.subset_enc_num_codes,
@@ -861,9 +909,7 @@
 
   /* global subrs */
   {
-    c->push ();
-    CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
-    if (unlikely (!dest)) return false;
+    auto *dest = c->push <CFF1Subrs> ();
     if (likely (dest->serialize (c, plan.subset_globalsubrs)))
       c->pop_pack (false);
     else
@@ -875,10 +921,9 @@
 
   /* String INDEX */
   {
-    CFF1StringIndex *dest = c->start_embed<CFF1StringIndex> ();
-    if (unlikely (!dest)) return false;
-    c->push ();
-    if (likely (dest->serialize (c, *acc.stringIndex, plan.sidmap)))
+    auto *dest = c->push<CFF1StringIndex> ();
+    if (likely (!plan.sidmap.in_error () &&
+		dest->serialize (c, *stringIndex, plan.sidmap.vector)))
       c->pop_pack ();
     else
     {
@@ -898,14 +943,12 @@
   cff->offSize = 4; /* unused? */
 
   /* name INDEX */
-  if (unlikely (!(*acc.nameIndex).copy (c))) return false;
+  if (unlikely (!c->embed (*nameIndex))) return false;
 
   /* top dict INDEX */
   {
     /* serialize singleton TopDict */
-    TopDict *top = c->start_embed<TopDict> ();
-    if (!top) return false;
-    c->push ();
+    auto *top = c->push<TopDict> ();
     cff1_top_dict_op_serializer_t topSzr;
     unsigned top_size = 0;
     top_dict_modifiers_t  modifier (plan.info, plan.topDictModSIDs);
@@ -920,37 +963,24 @@
       return false;
     }
     /* serialize INDEX header for above */
-    CFF1Index *dest = c->start_embed<CFF1Index> ();
-    if (!dest) return false;
-    return dest->serialize_header (c, hb_iter (hb_array_t<unsigned> (&top_size, 1)));
+    auto *dest = c->start_embed<CFF1Index> ();
+    return dest->serialize_header (c, hb_iter (&top_size, 1), top_size);
   }
 }
 
-static bool
-_hb_subset_cff1 (const OT::cff1::accelerator_subset_t  &acc,
-		hb_subset_context_t	*c)
+bool
+OT::cff1::accelerator_subset_t::subset (hb_subset_context_t *c) const
 {
-  cff_subset_plan cff_plan;
+  cff1_subset_plan cff_plan;
 
-  if (unlikely (!cff_plan.create (acc, c->plan)))
+  if (unlikely (!cff_plan.create (*this, c->plan)))
   {
     DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan.");
     return false;
   }
 
-  return _serialize_cff1 (c->serializer, cff_plan, acc, c->plan->num_output_glyphs ());
+  return serialize (c->serializer, cff_plan);
 }
 
-bool
-hb_subset_cff1 (hb_subset_context_t *c)
-{
-  OT::cff1::accelerator_subset_t acc;
-  acc.init (c->plan->source);
-  bool result = likely (acc.is_valid ()) && _hb_subset_cff1 (acc, c);
-  acc.fini ();
 
-  return result;
-}
-
-
 #endif

Deleted: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,37 +0,0 @@
-/*
- * Copyright © 2018 Adobe Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Adobe Author(s): Michiharu Ariza
- */
-
-#ifndef HB_SUBSET_CFF1_HH
-#define HB_SUBSET_CFF1_HH
-
-#include "hb.hh"
-
-#include "hb-subset-plan.hh"
-
-HB_INTERNAL bool
-hb_subset_cff1 (hb_subset_context_t *c);
-
-#endif /* HB_SUBSET_CFF1_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -31,7 +31,6 @@
 #include "hb-open-type.hh"
 #include "hb-ot-cff2-table.hh"
 #include "hb-set.h"
-#include "hb-subset-cff2.hh"
 #include "hb-subset-plan.hh"
 #include "hb-subset-cff-common.hh"
 #include "hb-cff2-interp-cs.hh"
@@ -422,11 +421,17 @@
 };
 
 
+namespace OT {
 struct cff2_subset_plan
 {
   bool create (const OT::cff2::accelerator_subset_t &acc,
 	      hb_subset_plan_t *plan)
   {
+    /* make sure notdef is first */
+    hb_codepoint_t old_glyph;
+    if (!plan->old_gid_for_new_gid (0, &old_glyph) || (old_glyph != 0)) return false;
+
+    num_glyphs = plan->num_output_glyphs ();
     orig_fdcount = acc.fdArray->count;
 
     drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
@@ -489,6 +494,7 @@
 
   cff2_sub_table_info_t info;
 
+  unsigned int    num_glyphs;
   unsigned int    orig_fdcount = 0;
   unsigned int    subset_fdcount = 1;
   unsigned int    subset_fdselect_size = 0;
@@ -505,18 +511,18 @@
   bool	    drop_hints = false;
   bool	    desubroutinize = false;
 };
+} // namespace OT
 
-static bool _serialize_cff2 (hb_serialize_context_t *c,
-			     cff2_subset_plan &plan,
-			     const OT::cff2::accelerator_subset_t  &acc,
-			     unsigned int num_glyphs,
-			     hb_array_t<int> normalized_coords)
+bool
+OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+					   struct cff2_subset_plan &plan,
+					   hb_array_t<int> normalized_coords) const
 {
   /* private dicts & local subrs */
   hb_vector_t<table_info_t>  private_dict_infos;
   if (unlikely (!private_dict_infos.resize (plan.subset_fdcount))) return false;
 
-  for (int i = (int)acc.privateDicts.length; --i >= 0 ;)
+  for (int i = (int)privateDicts.length; --i >= 0 ;)
   {
     if (plan.fdmap.has (i))
     {
@@ -524,9 +530,7 @@
 
       if (plan.subset_localsubrs[i].length > 0)
       {
-	CFF2Subrs *dest = c->start_embed <CFF2Subrs> ();
-	if (unlikely (!dest)) return false;
-	c->push ();
+	auto *dest = c->push <CFF2Subrs> ();
 	if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
 	  subrs_link = c->pop_pack (false);
 	else
@@ -535,12 +539,10 @@
 	  return false;
 	}
       }
-      PrivateDict *pd = c->start_embed<PrivateDict> ();
-      if (unlikely (!pd)) return false;
-      c->push ();
+      auto *pd = c->push<PrivateDict> ();
       cff2_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints, plan.pinned,
-						 acc.varStore, normalized_coords);
-      if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link)))
+						 varStore, normalized_coords);
+      if (likely (pd->serialize (c, privateDicts[i], privSzr, subrs_link)))
       {
 	unsigned fd = plan.fdmap[i];
 	private_dict_infos[fd].size = c->length ();
@@ -558,14 +560,13 @@
   {
     c->push ();
 
-    unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings);
+    unsigned data_size = 0;
+    unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings, &data_size);
     if (unlikely (!c->start_zerocopy (total_size)))
        return false;
 
-    CFF2CharStrings  *cs = c->start_embed<CFF2CharStrings> ();
-    if (unlikely (!cs)) return false;
-
-    if (likely (cs->serialize (c, plan.subset_charstrings)))
+    auto *cs = c->start_embed<CFF2CharStrings> ();
+    if (likely (cs->serialize (c, plan.subset_charstrings, &data_size)))
       plan.info.char_strings_link = c->pop_pack (false);
     else
     {
@@ -575,10 +576,10 @@
   }
 
   /* FDSelect */
-  if (acc.fdSelect != &Null (CFF2FDSelect))
+  if (fdSelect != &Null (CFF2FDSelect))
   {
     c->push ();
-    if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect,
+    if (likely (hb_serialize_cff_fdselect (c, plan.num_glyphs, *(const FDSelect *)fdSelect,
 					   plan.orig_fdcount,
 					   plan.subset_fdselect_format, plan.subset_fdselect_size,
 					   plan.subset_fdselect_ranges)))
@@ -592,27 +593,32 @@
 
   /* FDArray (FD Index) */
   {
-    c->push ();
-    CFF2FDArray *fda = c->start_embed<CFF2FDArray> ();
-    if (unlikely (!fda)) return false;
+    auto *fda = c->push<CFF2FDArray> ();
     cff_font_dict_op_serializer_t fontSzr;
     auto it =
-    + hb_zip (+ hb_iter (acc.fontDicts)
+    + hb_zip (+ hb_iter (fontDicts)
 	      | hb_filter ([&] (const cff2_font_dict_values_t &_)
-		{ return plan.fdmap.has (&_ - &acc.fontDicts[0]); }),
+		{ return plan.fdmap.has (&_ - &fontDicts[0]); }),
 	      hb_iter (private_dict_infos))
     ;
-    if (unlikely (!fda->serialize (c, it, fontSzr))) return false;
+    if (unlikely (!fda->serialize (c, it, fontSzr)))
+    {
+      c->pop_discard ();
+      return false;
+    }
     plan.info.fd_array_link = c->pop_pack (false);
   }
 
   /* variation store */
-  if (acc.varStore != &Null (CFF2VariationStore) &&
+  if (varStore != &Null (CFF2VariationStore) &&
       !plan.pinned)
   {
-    c->push ();
-    CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> ();
-    if (unlikely (!dest || !dest->serialize (c, acc.varStore))) return false;
+    auto *dest = c->push<CFF2VariationStore> ();
+    if (unlikely (!dest->serialize (c, varStore)))
+    {
+      c->pop_discard ();
+      return false;
+    }
     plan.info.var_store_link = c->pop_pack (false);
   }
 
@@ -628,34 +634,25 @@
   {
     TopDict &dict = cff2 + cff2->topDict;
     cff2_top_dict_op_serializer_t topSzr;
-    if (unlikely (!dict.serialize (c, acc.topDict, topSzr, plan.info))) return false;
+    if (unlikely (!dict.serialize (c, topDict, topSzr, plan.info))) return false;
     cff2->topDictSize = c->head - (const char *)&dict;
   }
 
   /* global subrs */
   {
-    CFF2Subrs *dest = c->start_embed <CFF2Subrs> ();
-    if (unlikely (!dest)) return false;
+    auto *dest = c->start_embed <CFF2Subrs> ();
     return dest->serialize (c, plan.subset_globalsubrs);
   }
 }
 
-static bool
-_hb_subset_cff2 (const OT::cff2::accelerator_subset_t  &acc,
-		 hb_subset_context_t	*c)
+bool
+OT::cff2::accelerator_subset_t::subset (hb_subset_context_t *c) const
 {
   cff2_subset_plan cff2_plan;
 
-  if (unlikely (!cff2_plan.create (acc, c->plan))) return false;
-  return _serialize_cff2 (c->serializer, cff2_plan, acc, c->plan->num_output_glyphs (),
-			  c->plan->normalized_coords.as_array ());
+  if (unlikely (!cff2_plan.create (*this, c->plan))) return false;
+  return serialize (c->serializer, cff2_plan,
+		    c->plan->normalized_coords.as_array ());
 }
 
-bool
-hb_subset_cff2 (hb_subset_context_t *c)
-{
-  OT::cff2::accelerator_subset_t acc (c->plan->source);
-  return acc.is_valid () && _hb_subset_cff2 (acc, c);
-}
-
 #endif

Deleted: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -1,37 +0,0 @@
-/*
- * Copyright © 2018 Adobe Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Adobe Author(s): Michiharu Ariza
- */
-
-#ifndef HB_SUBSET_CFF2_HH
-#define HB_SUBSET_CFF2_HH
-
-#include "hb.hh"
-
-#include "hb-subset-plan.hh"
-
-HB_INTERNAL bool
-hb_subset_cff2 (hb_subset_context_t *c);
-
-#endif /* HB_SUBSET_CFF2_HH */

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -438,7 +438,8 @@
   if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
     return false;
 
-  return input->axes_location.set (axis_tag, axis_info.default_value);
+  float default_val = axis_info.default_value;
+  return input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val));
 }
 
 /**
@@ -468,9 +469,53 @@
     return false;
 
   float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value);
-  return input->axes_location.set (axis_tag, val);
+  return input->axes_location.set (axis_tag, Triple (val, val, val));
 }
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_subset_input_set_axis_range: (skip)
+ * @input: a #hb_subset_input_t object.
+ * @face: a #hb_face_t object.
+ * @axis_tag: Tag of the axis
+ * @axis_min_value: Minimum value of the axis variation range to set
+ * @axis_max_value: Maximum value of the axis variation range to set
+ *
+ * Restricting the range of variation on an axis in the given subset input object.
+ * New min/max values will be clamped if they're not within the fvar axis range.
+ * If the fvar axis default value is not within the new range, the new default
+ * value will be changed to the new min or max value, whichever is closer to the fvar
+ * axis default.
+ *
+ * Note: input min value can not be bigger than input max value
+ * Note: currently this API does not support changing axis limits yet.It'd be only
+ * used internally for setting axis limits in the internal data structures
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * XSince: EXPERIMENTAL
+ **/
+HB_EXTERN hb_bool_t
+hb_subset_input_set_axis_range (hb_subset_input_t  *input,
+                                hb_face_t          *face,
+                                hb_tag_t            axis_tag,
+                                float               axis_min_value,
+                                float               axis_max_value)
+{
+  if (axis_min_value > axis_max_value)
+    return false;
+
+  hb_ot_var_axis_info_t axis_info;
+  if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+    return false;
+
+  float new_min_val = hb_clamp(axis_min_value, axis_info.min_value, axis_info.max_value);
+  float new_max_val = hb_clamp(axis_max_value, axis_info.min_value, axis_info.max_value);
+  float new_default_val = hb_clamp(axis_info.default_value, new_min_val, new_max_val);
+  return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val));
+}
 #endif
+#endif
 
 /**
  * hb_subset_preprocess:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -35,6 +35,7 @@
 #include "hb-set.hh"
 #include "hb-cplusplus.hh"
 #include "hb-font.hh"
+#include "hb-subset-instancer-solver.hh"
 
 struct hb_ot_name_record_ids_t
 {
@@ -118,7 +119,7 @@
   // If set loca format will always be the long version.
   bool force_long_loca = false;
 
-  hb_hashmap_t<hb_tag_t, float> axes_location;
+  hb_hashmap_t<hb_tag_t, Triple> axes_location;
   hb_map_t glyph_map;
 #ifdef HB_EXPERIMENTAL_API
   hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> name_table_overrides;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -22,7 +22,7 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  */
 
-#include "hb.hh"
+#include "hb-subset-instancer-solver.hh"
 
 /* This file is a straight port of the following:
  *
@@ -35,26 +35,6 @@
 constexpr static float EPSILON = 1.f / (1 << 14);
 constexpr static float MAX_F2DOT14 = float (0x7FFF) / (1 << 14);
 
-struct Triple {
-
-  Triple () :
-    minimum (0.f), middle (0.f), maximum (0.f) {}
-
-  Triple (float minimum_, float middle_, float maximum_) :
-    minimum (minimum_), middle (middle_), maximum (maximum_) {}
-
-  bool operator == (const Triple &o) const
-  {
-    return minimum == o.minimum &&
-	   middle  == o.middle  &&
-	   maximum == o.maximum;
-  }
-
-  float minimum;
-  float middle;
-  float maximum;
-};
-
 static inline Triple _reverse_negate(const Triple &v)
 { return {-v.maximum, -v.middle, -v.minimum}; }
 
@@ -82,10 +62,6 @@
     return  (end - coord) / (end - peak);
 }
 
-
-using result_item_t = hb_pair_t<float, Triple>;
-using result_t = hb_vector_t<result_item_t>;
-
 static inline result_t
 _solve (Triple tent, Triple axisLimit, bool negative = false)
 {
@@ -195,9 +171,9 @@
   if (gain > outGain)
   {
     // Crossing point on the axis.
-    float crossing = peak + ((1 - gain) * (upper - peak) / (1 - outGain));
+    float crossing = peak + (1 - gain) * (upper - peak);
 
-    Triple loc{peak, peak, crossing};
+    Triple loc{axisDef, peak, crossing};
     float scalar = 1.f;
 
     // The part before the crossing point.
@@ -213,7 +189,7 @@
     if (upper >= axisMax)
     {
       Triple loc {crossing, axisMax, axisMax};
-      float scalar = supportScalar (axisMax, tent);
+      float scalar = outGain;
 
       out.push (hb_pair (scalar - gain, loc));
     }
@@ -247,7 +223,7 @@
 
       // Eternity justify.
       Triple loc2 {upper, axisMax, axisMax};
-      float scalar2 = 1.f; // supportScalar({"tag": axisMax}, {"tag": tent})
+      float scalar2 = 0.f;
 
       out.push (hb_pair (scalar1 - gain, loc1));
       out.push (hb_pair (scalar2 - gain, loc2));
@@ -254,82 +230,76 @@
     }
   }
 
-  /* Case 3: Outermost limit still fits within F2Dot14 bounds;
-   * we keep deltas as is and only scale the axes bounds. Deltas beyond -1.0
-   * or +1.0 will never be applied as implementations must clamp to that range.
-   *
-   * A second tent is needed for cases when gain is positive, though we add it
-   * unconditionally and it will be dropped because scalar ends up 0.
-   *
-   * TODO: See if we can just move upper closer to adjust the slope, instead of
-   * second tent.
-   *
-   *            |           peak |
-   *  1.........|............o...|..................
-   *            |           /x\  |
-   *            |          /xxx\ |
-   *            |         /xxxxx\|
-   *            |        /xxxxxxx+
-   *            |       /xxxxxxxx|\
-   *  0---|-----|------oxxxxxxxxx|xo---------------1
-   *    axisMin |  lower         | upper
-   *            |                |
-   *          axisDef          axisMax
-   */
-  else if (axisDef + (axisMax - axisDef) * 2 >= upper)
+  else
   {
-    if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper)
-    {
-      // we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience
-      upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14;
-      assert (peak < upper);
-    }
-
     // Special-case if peak is at axisMax.
     if (axisMax == peak)
 	upper = peak;
 
-    Triple loc1 {hb_max (axisDef, lower), peak, upper};
-    float scalar1 = 1.f;
+    /* Case 3:
+     * we keep deltas as is and only scale the axis upper to achieve
+     * the desired new tent if feasible.
+     *
+     *                        peak
+     *  1.....................o....................
+     *                       / \_|
+     *  ..................../....+_.........outGain
+     *                     /     | \
+     *  gain..............+......|..+_.............
+     *                   /|      |  | \
+     *  0---|-----------o |      |  |  o----------1
+     *    axisMin    lower|      |  |   upper
+     *                    |      |  newUpper
+     *              axisDef      axisMax
+     */
+    float newUpper = peak + (1 - gain) * (upper - peak);
+    // I feel like the first condition is always true because
+    // outGain >= gain.
+    if (axisMax <= newUpper && newUpper <= axisDef + (axisMax - axisDef) * 2)
+    {
+      upper = newUpper;
+      if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper)
+      {
+	// we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience
+	upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14;
+	assert (peak < upper);
+      }
 
-    Triple loc2 {peak, upper, upper};
-    float scalar2 = 0.f;
+      Triple loc {hb_max (axisDef, lower), peak, upper};
+      float scalar = 1.f;
 
-    // Don't add a dirac delta!
-    if (axisDef < upper)
-	out.push (hb_pair (scalar1 - gain, loc1));
-    if (peak < upper)
-	out.push (hb_pair (scalar2 - gain, loc2));
-  }
+      out.push (hb_pair (scalar - gain, loc));
+    }
 
-  /* Case 4: New limit doesn't fit; we need to chop into two tents,
-   * because the shape of a triangle with part of one side cut off
-   * cannot be represented as a triangle itself.
-   *
-   *            |   peak |
-   *  1.........|......o.|...................
-   *            |     /x\|
-   *            |    |xxy|\_
-   *            |   /xxxy|  \_
-   *            |  |xxxxy|    \_
-   *            |  /xxxxy|      \_
-   *  0---|-----|-oxxxxxx|        o----------1
-   *    axisMin | lower  |        upper
-   *            |        |
-   *          axisDef  axisMax
-   */
-  else
-  {
-    Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
-    float scalar1 = 1.f;
+    /* Case 4: New limit doesn't fit; we need to chop into two tents,
+     * because the shape of a triangle with part of one side cut off
+     * cannot be represented as a triangle itself.
+     *
+     *            |   peak |
+     *  1.........|......o.|....................
+     *  ..........|...../x\|.............outGain
+     *            |    |xxy|\_
+     *            |   /xxxy|  \_
+     *            |  |xxxxy|    \_
+     *            |  /xxxxy|      \_
+     *  0---|-----|-oxxxxxx|        o----------1
+     *    axisMin | lower  |        upper
+     *            |        |
+     *          axisDef  axisMax
+     */
+    else
+    {
+      Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
+      float scalar1 = 1.f;
 
-    Triple loc2 {peak, axisMax, axisMax};
-    float scalar2 = supportScalar (axisMax, tent);
+      Triple loc2 {peak, axisMax, axisMax};
+      float scalar2 = outGain;
 
-    out.push (hb_pair (scalar1 - gain, loc1));
-    // Don't add a dirac delta!
-    if (peak < axisMax)
-      out.push (hb_pair (scalar2 - gain, loc2));
+      out.push (hb_pair (scalar1 - gain, loc1));
+      // Don't add a dirac delta!
+      if (peak < axisMax)
+	out.push (hb_pair (scalar2 - gain, loc2));
+    }
   }
 
   /* Now, the negative side
@@ -422,19 +392,6 @@
   }
 }
 
-/* Given a tuple (lower,peak,upper) "tent" and new axis limits
- * (axisMin,axisDefault,axisMax), solves how to represent the tent
- * under the new axis configuration.  All values are in normalized
- * -1,0,+1 coordinate system. Tent values can be outside this range.
- *
- * Return value: a list of tuples. Each tuple is of the form
- * (scalar,tent), where scalar is a multipler to multiply any
- * delta-sets by, and tent is a new tent for that output delta-set.
- * If tent value is Triple{}, that is a special deltaset that should
- * be always-enabled (called "gain").
- */
-HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit);
-
 result_t
 rebase_tent (Triple tent, Triple axisLimit)
 {
@@ -460,5 +417,5 @@
 		       Triple{n (t.minimum), n (t.middle), n (t.maximum)}));
   }
 
-  return sols;
+  return out;
 }

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_SUBSET_INSTANCER_SOLVER_HH
+#define HB_SUBSET_INSTANCER_SOLVER_HH
+
+#include "hb.hh"
+
+struct Triple {
+
+  Triple () :
+    minimum (0.f), middle (0.f), maximum (0.f) {}
+
+  Triple (float minimum_, float middle_, float maximum_) :
+    minimum (minimum_), middle (middle_), maximum (maximum_) {}
+
+  bool operator == (const Triple &o) const
+  {
+    return minimum == o.minimum &&
+	   middle  == o.middle  &&
+	   maximum == o.maximum;
+  }
+
+  bool operator != (const Triple o) const
+  { return !(*this == o); }
+
+  bool is_point () const
+  { return minimum == middle && middle == maximum; }
+
+  bool contains (float point) const
+  { return minimum <= point && point <= maximum; }
+
+  /* from hb_array_t hash ()*/
+  uint32_t hash () const
+  {
+    uint32_t current = /*cbf29ce4*/0x84222325;
+    current = current ^ hb_hash (minimum);
+    current = current * 16777619;
+
+    current = current ^ hb_hash (middle);
+    current = current * 16777619;
+
+    current = current ^ hb_hash (maximum);
+    current = current * 16777619;
+    return current;
+  }
+
+  float minimum;
+  float middle;
+  float maximum;
+};
+
+using result_item_t = hb_pair_t<float, Triple>;
+using result_t = hb_vector_t<result_item_t>;
+
+/* Given a tuple (lower,peak,upper) "tent" and new axis limits
+ * (axisMin,axisDefault,axisMax), solves how to represent the tent
+ * under the new axis configuration.  All values are in normalized
+ * -1,0,+1 coordinate system. Tent values can be outside this range.
+ *
+ * Return value: a list of tuples. Each tuple is of the form
+ * (scalar,tent), where scalar is a multipler to multiply any
+ * delta-sets by, and tent is a new tent for that output delta-set.
+ * If tent value is Triple{}, that is a special deltaset that should
+ * be always-enabled (called "gain").
+ */
+HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit);
+
+#endif /* HB_SUBSET_INSTANCER_SOLVER_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan-member-list.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan-member-list.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan-member-list.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -33,8 +33,10 @@
 
 // For each cp that we'd like to retain maps to the corresponding gid.
 HB_SUBSET_PLAN_MEMBER (hb_set_t, unicodes)
-HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t E(<hb_pair_t<hb_codepoint_t, hb_codepoint_t>>), unicode_to_new_gid_list)
+HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t<hb_codepoint_pair_t>, unicode_to_new_gid_list)
 
+HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t<hb_codepoint_pair_t>, new_to_old_gid_list)
+
 // name_ids we would like to retain
 HB_SUBSET_PLAN_MEMBER (hb_set_t, name_ids)
 
@@ -97,12 +99,12 @@
 
 HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, hb::unique_ptr<hb_blob_t>>), sanitized_table_cache)
 
-//normalized axes location map
-HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, int>), axes_location)
+//normalized axes range map
+HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, Triple>), axes_location)
 HB_SUBSET_PLAN_MEMBER (hb_vector_t<int>, normalized_coords)
 
-//user specified axes location map
-HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, float>), user_axes_location)
+//user specified axes range map
+HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, Triple>), user_axes_location)
 
 //retained old axis index -> new axis index mapping in fvar axis array
 HB_SUBSET_PLAN_MEMBER (hb_map_t, axes_index_map)
@@ -115,9 +117,9 @@
 //vmtx metrics map: new gid->(advance, lsb)
 HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<hb_codepoint_t, hb_pair_t E(<unsigned, int>)>), vmtx_map)
 //boundsWidth map: new gid->boundsWidth, boundWidth=xMax - xMin
-HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_width_map)
+HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_width_vec)
 //boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin
-HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_height_map)
+HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_height_vec)
 
 #ifdef HB_EXPERIMENTAL_API
 // name table overrides map: hb_ot_name_record_ids_t-> name string new value or

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -48,10 +48,24 @@
 using OT::Layout::GSUB;
 using OT::Layout::GPOS;
 
+
+hb_subset_accelerator_t::~hb_subset_accelerator_t ()
+{
+  if (cmap_cache && destroy_cmap_cache)
+    destroy_cmap_cache ((void*) cmap_cache);
+
+#ifndef HB_NO_SUBSET_CFF
+  cff1_accel.fini ();
+  cff2_accel.fini ();
+#endif
+  hb_face_destroy (source);
+}
+
+
 typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
 #ifndef HB_NO_SUBSET_CFF
 static inline bool
-_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
+_add_cff_seac_components (const OT::cff1::accelerator_subset_t &cff,
 			  hb_codepoint_t gid,
 			  hb_set_t *gids_to_retain)
 {
@@ -135,7 +149,8 @@
                                      hb_set_t		  *lookup_indices, /* OUT */
                                      hb_set_t		  *feature_indices, /* OUT */
                                      hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */
-                                     hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map /* OUT */)
+                                     hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, /* OUT */
+                                     bool& insert_catch_all_feature_variation_record)
 {
   unsigned num_features = table.get_feature_count ();
   hb_vector_t<hb_tag_t> features;
@@ -171,8 +186,11 @@
       &plan->axes_location,
       feature_record_cond_idx_map,
       feature_substitutes_map,
+      insert_catch_all_feature_variation_record,
       feature_indices,
-      true,
+      false,
+      false,
+      false,
       0,
       &conditionset_map
     };
@@ -283,7 +301,8 @@
 				  hb_map_t	     *features,
 				  script_langsys_map *langsys_map,
 				  hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
-				  hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map)
+				  hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
+				  bool& insert_catch_all_feature_variation_record)
 {
   hb_blob_ptr_t<T> table = plan->source_table<T> ();
   hb_tag_t table_tag = table->tableTag;
@@ -293,7 +312,8 @@
                               &lookup_indices,
                               &feature_indices,
                               feature_record_cond_idx_map,
-                              feature_substitutes_map);
+                              feature_substitutes_map,
+                              insert_catch_all_feature_variation_record);
 
   if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE))
     hb_ot_layout_lookups_substitute_closure (plan->source,
@@ -329,7 +349,7 @@
 {
   if (varidx_set.is_empty () || subtable_count == 0) return;
 
-  inner_maps.resize (subtable_count);
+  if (unlikely (!inner_maps.resize (subtable_count))) return;
   for (unsigned idx : varidx_set)
   {
     uint16_t major = idx >> 16;
@@ -356,7 +376,7 @@
   {
     hb_variation_t var;
     var.tag = _.first;
-    var.value = _.second;
+    var.value = _.second.middle;
     vars.push (var);
   }
 
@@ -541,6 +561,8 @@
 	unicodes->get_population () < cmap_unicodes->get_population () &&
 	glyphs->get_population () < cmap_unicodes->get_population ())
     {
+      plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ());
+
       auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes;
       for (hb_codepoint_t gid : *glyphs)
       {
@@ -569,6 +591,7 @@
     }
     else
     {
+      plan->codepoint_to_glyph->alloc (cmap_unicodes->get_population ());
       for (hb_codepoint_t cp : *cmap_unicodes)
       {
 	hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
@@ -581,9 +604,10 @@
     }
 
     /* Add gids which where requested, but not mapped in cmap */
+    unsigned num_glyphs = plan->source->get_num_glyphs ();
     for (hb_codepoint_t gid : *glyphs)
     {
-      if (gid >= plan->source->get_num_glyphs ())
+      if (gid >= num_glyphs)
 	break;
       plan->_glyphset_gsub.add (gid);
     }
@@ -616,7 +640,9 @@
   if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
   if (unlikely (--operation_count < 0)) return operation_count;
 
-  for (auto &item : glyf.glyph_for_gid (gid).get_composite_iterator ())
+  auto glyph = glyf.glyph_for_gid (gid);
+
+  for (auto &item : glyph.get_composite_iterator ())
     operation_count =
       _glyf_add_gid_and_children (glyf,
 				  item.get_gid (),
@@ -625,7 +651,7 @@
 				  depth);
 
 #ifndef HB_NO_VAR_COMPOSITES
-  for (auto &item : glyf.glyph_for_gid (gid).get_var_composite_iterator ())
+  for (auto &item : glyph.get_var_composite_iterator ())
    {
     operation_count =
       _glyf_add_gid_and_children (glyf,
@@ -648,7 +674,7 @@
 #endif
 #ifndef HB_NO_VAR
   if (!plan->all_axes_pinned)
-    plan->source->table.fvar->collect_name_ids (&plan->user_axes_location, &plan->name_ids);
+    plan->source->table.fvar->collect_name_ids (&plan->user_axes_location, &plan->axes_old_index_tag_map, &plan->name_ids);
 #endif
 #ifndef HB_NO_COLOR
   if (!drop_tables->has (HB_OT_TAG_CPAL))
@@ -677,7 +703,11 @@
 {
   OT::glyf_accelerator_t glyf (plan->source);
 #ifndef HB_NO_SUBSET_CFF
-  OT::cff1::accelerator_t cff (plan->source);
+  // Note: we cannot use inprogress_accelerator here, since it has not been
+  // created yet. So in case of preprocessed-face (and otherwise), we do an
+  // extra sanitize pass here, which is not ideal.
+  OT::cff1::accelerator_subset_t stack_cff (plan->accelerator ? nullptr : plan->source);
+  const OT::cff1::accelerator_subset_t *cff (plan->accelerator ? plan->accelerator->cff1_accel.get () : &stack_cff);
 #endif
 
   plan->_glyphset_gsub.add (0); // Not-def
@@ -694,7 +724,8 @@
         &plan->gsub_features,
         &plan->gsub_langsys,
         &plan->gsub_feature_record_cond_idx_map,
-        &plan->gsub_feature_substitutes_map);
+        &plan->gsub_feature_substitutes_map,
+        plan->gsub_insert_catch_all_feature_variation_rec);
 
   if (!drop_tables->has (HB_OT_TAG_GPOS))
     _closure_glyphs_lookups_features<GPOS> (
@@ -704,7 +735,8 @@
         &plan->gpos_features,
         &plan->gpos_langsys,
         &plan->gpos_feature_record_cond_idx_map,
-        &plan->gpos_feature_substitutes_map);
+        &plan->gpos_feature_substitutes_map,
+        plan->gpos_insert_catch_all_feature_variation_rec);
 #endif
   _remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ());
 
@@ -737,9 +769,9 @@
   if (!plan->accelerator || plan->accelerator->has_seac)
   {
     bool has_seac = false;
-    if (cff.is_valid ())
+    if (cff->is_valid ())
       for (hb_codepoint_t gid : cur_glyphset)
-	if (_add_cff_seac_components (cff, gid, &plan->_glyphset))
+	if (_add_cff_seac_components (*cff, gid, &plan->_glyphset))
 	  has_seac = true;
     plan->has_seac = has_seac;
   }
@@ -747,7 +779,6 @@
 
   _remove_invalid_gids (&plan->_glyphset, plan->source->get_num_glyphs ());
 
-
 #ifndef HB_NO_VAR
   if (!drop_tables->has (HB_OT_TAG_GDEF))
     _collect_layout_variation_indices (plan);
@@ -759,10 +790,10 @@
                         const hb_map_t* glyph_map,
                         hb_map_t* out)
 {
+  out->alloc (glyph_set_gsub->get_population ());
   + hb_iter (glyph_set_gsub)
   | hb_map ([&] (hb_codepoint_t gid) {
-    return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid,
-                                                      glyph_map->get (gid));
+    return hb_codepoint_pair_t (gid, glyph_map->get (gid));
   })
   | hb_sink (out)
   ;
@@ -775,11 +806,13 @@
                                 const hb_map_t  *requested_glyph_map,
 				hb_map_t	*glyph_map, /* OUT */
 				hb_map_t	*reverse_glyph_map, /* OUT */
+				hb_sorted_vector_t<hb_codepoint_pair_t> *new_to_old_gid_list /* OUT */,
 				unsigned int	*num_glyphs /* OUT */)
 {
   unsigned pop = all_gids_to_retain->get_population ();
-  reverse_glyph_map->resize (pop);
-  glyph_map->resize (pop);
+  reverse_glyph_map->alloc (pop);
+  glyph_map->alloc (pop);
+  new_to_old_gid_list->alloc (pop);
 
   if (*requested_glyph_map)
   {
@@ -803,7 +836,7 @@
     for (auto old_gid : all_gids_to_retain->iter ())
     {
       if (old_gid == 0) {
-        reverse_glyph_map->set(0, 0);
+	new_to_old_gid_list->push (hb_pair<hb_codepoint_t, hb_codepoint_t> (0u, 0u));
         continue;
       }
 
@@ -810,21 +843,20 @@
       hb_codepoint_t* new_gid;
       if (!requested_glyph_map->has (old_gid, &new_gid))
       {
-        remaining.add(old_gid);  
+        remaining.add(old_gid);
         continue;
       }
 
       if (*new_gid > max_glyph)
         max_glyph = *new_gid;
-      reverse_glyph_map->set (*new_gid, old_gid);
+      new_to_old_gid_list->push (hb_pair (*new_gid, old_gid));
     }
+    new_to_old_gid_list->qsort ();
 
     // Anything that wasn't mapped by the requested mapping should
     // be placed after the requested mapping.
     for (auto old_gid : remaining)
-    {
-      reverse_glyph_map->set(++max_glyph, old_gid);
-    }
+      new_to_old_gid_list->push (hb_pair (++max_glyph, old_gid));
 
     *num_glyphs = max_glyph + 1;
   }
@@ -831,17 +863,17 @@
   else if (!retain_gids)
   {
     + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0)
-    | hb_sink (reverse_glyph_map)
+    | hb_sink (new_to_old_gid_list)
     ;
-    *num_glyphs = reverse_glyph_map->get_population ();
+    *num_glyphs = new_to_old_gid_list->length;
   }
   else
   {
     + hb_iter (all_gids_to_retain)
     | hb_map ([] (hb_codepoint_t _) {
-		return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, _);
+		return hb_codepoint_pair_t (_, _);
 	      })
-    | hb_sink (reverse_glyph_map)
+    | hb_sink (new_to_old_gid_list)
     ;
 
     hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID;
@@ -850,8 +882,11 @@
     *num_glyphs = max_glyph + 1;
   }
 
-  + reverse_glyph_map->iter ()
-  | hb_map (&hb_pair_t<hb_codepoint_t, hb_codepoint_t>::reverse)
+  + hb_iter (new_to_old_gid_list)
+  | hb_sink (reverse_glyph_map)
+  ;
+  + hb_iter (new_to_old_gid_list)
+  | hb_map (&hb_codepoint_pair_t::reverse)
   | hb_sink (glyph_map)
   ;
 
@@ -884,24 +919,35 @@
     hb_tag_t axis_tag = axis.get_axis_tag ();
     plan->axes_old_index_tag_map.set (old_axis_idx, axis_tag);
 
-    if (!plan->user_axes_location.has (axis_tag))
+    if (!plan->user_axes_location.has (axis_tag) ||
+        !plan->user_axes_location.get (axis_tag).is_point ())
     {
       axis_not_pinned = true;
       plan->axes_index_map.set (old_axis_idx, new_axis_idx);
       new_axis_idx++;
     }
-    else
+
+    if (plan->user_axes_location.has (axis_tag))
     {
-      int normalized_v = axis.normalize_axis_value (plan->user_axes_location.get (axis_tag));
+      Triple axis_range = plan->user_axes_location.get (axis_tag);
+      int normalized_min = axis.normalize_axis_value (axis_range.minimum);
+      int normalized_default = axis.normalize_axis_value (axis_range.middle);
+      int normalized_max = axis.normalize_axis_value (axis_range.maximum);
+
       if (has_avar && old_axis_idx < avar_axis_count)
       {
-        normalized_v = seg_maps->map (normalized_v);
+        normalized_min = seg_maps->map (normalized_min);
+        normalized_default = seg_maps->map (normalized_default);
+        normalized_max = seg_maps->map (normalized_max);
       }
-      plan->axes_location.set (axis_tag, normalized_v);
-      if (normalized_v != 0)
+      plan->axes_location.set (axis_tag, Triple (static_cast<float> (normalized_min),
+                                                 static_cast<float> (normalized_default),
+                                                 static_cast<float> (normalized_max)));
+
+      if (normalized_default != 0)
         plan->pinned_at_default = false;
 
-      plan->normalized_coords[old_axis_idx] = normalized_v;
+      plan->normalized_coords[old_axis_idx] = normalized_default;
     }
 
     old_axis_idx++;
@@ -968,7 +1014,7 @@
           continue;
       }
       plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
-      plan->bounds_width_map.set (new_gid, extents.width);
+      plan->bounds_width_vec[new_gid] = extents.width;
     }
 
     if (_vmtx.has_data ())
@@ -985,7 +1031,7 @@
           continue;
       }
       plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
-      plan->bounds_height_map.set (new_gid, extents.height);
+      plan->bounds_height_vec[new_gid] = extents.height;
     }
   }
   hb_font_destroy (font);
@@ -1018,6 +1064,8 @@
   glyph_map = hb_map_create ();
   reverse_glyph_map = hb_map_create ();
 
+  gsub_insert_catch_all_feature_variation_rec = false;
+  gpos_insert_catch_all_feature_variation_rec = false;
   gdef_varstore_inner_maps.init ();
 
   user_axes_location = input->axes_location;
@@ -1065,6 +1113,7 @@
           &input->glyph_map,
           glyph_map,
           reverse_glyph_map,
+	  &new_to_old_gid_list,
           &_num_output_glyphs))) {
     return;
   }
@@ -1082,6 +1131,13 @@
         glyph_map->get(unicode_to_new_gid_list.arrayZ[i].second);
   }
 
+  bounds_width_vec.resize (_num_output_glyphs, false);
+  for (auto &v : bounds_width_vec)
+    v = 0xFFFFFFFF;
+  bounds_height_vec.resize (_num_output_glyphs, false);
+  for (auto &v : bounds_height_vec)
+    v = 0xFFFFFFFF;
+
   if (unlikely (in_error ()))
     return;
 
@@ -1091,19 +1147,9 @@
 
   if (attach_accelerator_data)
   {
-    hb_multimap_t gid_to_unicodes;
-
-    hb_map_t &unicode_to_gid = *codepoint_to_glyph;
-
-    for (auto unicode : unicodes)
-    {
-      auto gid = unicode_to_gid[unicode];
-      gid_to_unicodes.add (gid, unicode);
-    }
-
     inprogress_accelerator =
-      hb_subset_accelerator_t::create (*codepoint_to_glyph,
-				       gid_to_unicodes,
+      hb_subset_accelerator_t::create (source,
+				       *codepoint_to_glyph,
                                        unicodes,
 				       has_seac);
 
@@ -1115,6 +1161,29 @@
 #undef HB_SUBSET_PLAN_MEMBER
 }
 
+hb_subset_plan_t::~hb_subset_plan_t()
+{
+  hb_face_destroy (dest);
+
+  hb_map_destroy (codepoint_to_glyph);
+  hb_map_destroy (glyph_map);
+  hb_map_destroy (reverse_glyph_map);
+#ifndef HB_NO_SUBSET_CFF
+  cff1_accel.fini ();
+  cff2_accel.fini ();
+#endif
+  hb_face_destroy (source);
+
+#ifdef HB_EXPERIMENTAL_API
+  for (auto _ : name_table_overrides.iter_ref ())
+    _.second.fini ();
+#endif
+
+  if (inprogress_accelerator)
+    hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
+}
+
+
 /**
  * hb_subset_plan_create_or_fail:
  * @face: font face to create the plan for.

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	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -67,29 +67,18 @@
 
 typedef struct head_maxp_info_t head_maxp_info_t;
 
+namespace OT {
+  struct cff1_subset_accelerator_t;
+  struct cff2_subset_accelerator_t;
+}
+
 struct hb_subset_plan_t
 {
   HB_INTERNAL hb_subset_plan_t (hb_face_t *,
 				const hb_subset_input_t *input);
 
-  ~hb_subset_plan_t()
-  {
-    hb_face_destroy (source);
-    hb_face_destroy (dest);
+  HB_INTERNAL ~hb_subset_plan_t();
 
-    hb_map_destroy (codepoint_to_glyph);
-    hb_map_destroy (glyph_map);
-    hb_map_destroy (reverse_glyph_map);
-
-#ifdef HB_EXPERIMENTAL_API
-    for (auto _ : name_table_overrides)
-      _.second.fini ();
-#endif
-
-    if (inprogress_accelerator)
-      hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
-  }
-
   hb_object_header_t header;
 
   bool successful;
@@ -106,6 +95,12 @@
 
   // Plan is only good for a specific source/dest so keep them with it
   hb_face_t *source;
+#ifndef HB_NO_SUBSET_CFF
+  // These have to be immediately after source:
+  hb_face_lazy_loader_t<OT::cff1_subset_accelerator_t, 1> cff1_accel;
+  hb_face_lazy_loader_t<OT::cff2_subset_accelerator_t, 2> cff2_accel;
+#endif
+
   hb_face_t *dest;
 
   unsigned int _num_output_glyphs;
@@ -114,6 +109,10 @@
   bool pinned_at_default;
   bool has_seac;
 
+  // whether to insert a catch-all FeatureVariationRecord
+  bool gsub_insert_catch_all_feature_variation_rec;
+  bool gpos_insert_catch_all_feature_variation_rec;
+
 #define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name;
 #include "hb-subset-plan-member-list.hh"
 #undef HB_SUBSET_PLAN_MEMBER
@@ -127,26 +126,32 @@
  public:
 
   template<typename T>
-  hb_blob_ptr_t<T> source_table()
+  struct source_table_loader
   {
-    hb_lock_t lock (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
+    hb_blob_ptr_t<T> operator () (hb_subset_plan_t *plan)
+    {
+      hb_lock_t lock (plan->accelerator ? &plan->accelerator->sanitized_table_cache_lock : nullptr);
 
-    auto *cache = accelerator ? &accelerator->sanitized_table_cache : &sanitized_table_cache;
-    if (cache
-        && !cache->in_error ()
-        && cache->has (+T::tableTag)) {
-      return hb_blob_reference (cache->get (+T::tableTag).get ());
-    }
+      auto *cache = plan->accelerator ? &plan->accelerator->sanitized_table_cache : &plan->sanitized_table_cache;
+      if (cache
+	  && !cache->in_error ()
+	  && cache->has (+T::tableTag)) {
+	return hb_blob_reference (cache->get (+T::tableTag).get ());
+      }
 
-    hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)};
-    hb_blob_t* ret = hb_blob_reference (table_blob.get ());
+      hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (plan->source)};
+      hb_blob_t* ret = hb_blob_reference (table_blob.get ());
 
-    if (likely (cache))
-      cache->set (+T::tableTag, std::move (table_blob));
+      if (likely (cache))
+	cache->set (+T::tableTag, std::move (table_blob));
 
-    return ret;
-  }
+      return ret;
+    }
+  };
 
+  template<typename T>
+  auto source_table() HB_AUTO_RETURN (source_table_loader<T> {} (this))
+
   bool in_error () const { return !successful; }
 
   bool check_success(bool success)
@@ -184,15 +189,6 @@
     return _num_output_glyphs;
   }
 
-  /*
-   * Given an output gid , returns true if that glyph id is an empty
-   * glyph (ie. it's a gid that we are dropping all data for).
-   */
-  inline bool is_empty_glyph (hb_codepoint_t gid) const
-  {
-    return !_glyphset.has (gid);
-  }
-
   inline bool new_gid_for_codepoint (hb_codepoint_t codepoint,
 				     hb_codepoint_t *new_gid) const
   {
@@ -242,4 +238,5 @@
   }
 };
 
+
 #endif /* HB_SUBSET_PLAN_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -62,6 +62,27 @@
 using OT::Layout::GSUB;
 using OT::Layout::GPOS;
 
+
+#ifndef HB_NO_SUBSET_CFF
+template<>
+struct hb_subset_plan_t::source_table_loader<const OT::cff1>
+{
+  auto operator () (hb_subset_plan_t *plan)
+  HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff1_accel :
+		  plan->inprogress_accelerator ? plan->inprogress_accelerator->cff1_accel :
+		  plan->cff1_accel)
+};
+template<>
+struct hb_subset_plan_t::source_table_loader<const OT::cff2>
+{
+  auto operator () (hb_subset_plan_t *plan)
+  HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff2_accel :
+		  plan->inprogress_accelerator ? plan->inprogress_accelerator->cff2_accel :
+		  plan->cff2_accel)
+};
+#endif
+
+
 /**
  * SECTION:hb-subset
  * @title: hb-subset
@@ -192,15 +213,36 @@
 static unsigned
 _plan_estimate_subset_table_size (hb_subset_plan_t *plan,
 				  unsigned table_len,
-				  bool same_size)
+				  hb_tag_t table_tag)
 {
   unsigned src_glyphs = plan->source->get_num_glyphs ();
   unsigned dst_glyphs = plan->glyphset ()->get_population ();
 
+  unsigned bulk = 8192;
+  /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's
+   * because those are expensive to subset, so giving them more room is fine. */
+  bool same_size = table_tag == HB_OT_TAG_GSUB ||
+		   table_tag == HB_OT_TAG_GPOS ||
+		   table_tag == HB_OT_TAG_name;
+
+  if (plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS)
+  {
+    if (table_tag == HB_OT_TAG_CFF1)
+    {
+      /* Add some extra room for the CFF charset. */
+      bulk += src_glyphs * 16;
+    }
+    else if (table_tag == HB_OT_TAG_CFF2)
+    {
+      /* Just extra CharString offsets. */
+      bulk += src_glyphs * 4;
+    }
+  }
+
   if (unlikely (!src_glyphs) || same_size)
-    return 512 + table_len;
+    return bulk + table_len;
 
-  return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
+  return bulk + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
 }
 
 /*
@@ -262,35 +304,36 @@
   return _try_subset (table, buf, c);
 }
 
+template <typename T>
+static auto _do_destroy (T &t, hb_priority<1>) HB_RETURN (void, t.destroy ())
+
+template <typename T>
+static void _do_destroy (T &t, hb_priority<0>) {}
+
 template<typename TableType>
 static bool
 _subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
 {
-  hb_blob_ptr_t<TableType> source_blob = plan->source_table<TableType> ();
-  const TableType *table = source_blob.get ();
+  auto &&source_blob = plan->source_table<TableType> ();
+  auto *table = source_blob.get ();
 
   hb_tag_t tag = TableType::tableTag;
-  if (!source_blob.get_blob()->data)
+  hb_blob_t *blob = source_blob.get_blob();
+  if (unlikely (!blob || !blob->data))
   {
     DEBUG_MSG (SUBSET, nullptr,
                "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
-    source_blob.destroy ();
+    _do_destroy (source_blob, hb_prioritize);
     return false;
   }
 
-  /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's
-   * because those are expensive to subset, so giving them more room is fine. */
-  bool same_size_table = TableType::tableTag == HB_OT_TAG_GSUB ||
-			 TableType::tableTag == HB_OT_TAG_GPOS ||
-			 TableType::tableTag == HB_OT_TAG_name;
-
-  unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob.get_length (), same_size_table);
+  unsigned buf_size = _plan_estimate_subset_table_size (plan, blob->length, TableType::tableTag);
   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);
-    source_blob.destroy ();
+    _do_destroy (source_blob, hb_prioritize);
     return false;
   }
 
@@ -297,10 +340,10 @@
   bool needed = false;
   hb_serialize_context_t serializer (buf.arrayZ, buf.allocated);
   {
-    hb_subset_context_t c (source_blob.get_blob (), plan, &serializer, tag);
+    hb_subset_context_t c (blob, plan, &serializer, tag);
     needed = _try_subset (table, &buf, &c);
   }
-  source_blob.destroy ();
+  _do_destroy (source_blob, hb_prioritize);
 
   if (serializer.in_error () && !serializer.only_offset_overflow ())
   {
@@ -587,46 +630,49 @@
     offset += num_tables;
   }
 
-  hb_vector_t<char> buf;
-  buf.alloc (4096 - 16);
-
-
   bool success = true;
 
-  while (!pending_subset_tags.is_empty ())
   {
-    if (subsetted_tags.in_error ()
-        || pending_subset_tags.in_error ()) {
-      success = false;
-      goto end;
-    }
+    // Grouping to deallocate buf before calling hb_face_reference (plan->dest).
 
-    bool made_changes = false;
-    for (hb_tag_t tag : pending_subset_tags)
+    hb_vector_t<char> buf;
+    buf.alloc (8192 - 16);
+
+    while (!pending_subset_tags.is_empty ())
     {
-      if (!_dependencies_satisfied (plan, tag,
-                                    subsetted_tags,
-                                    pending_subset_tags))
-      {
-        // delayed subsetting for some tables since they might have dependency on other tables
-        // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated
-        // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values
-        continue;
+      if (subsetted_tags.in_error ()
+	  || pending_subset_tags.in_error ()) {
+	success = false;
+	goto end;
       }
 
-      pending_subset_tags.del (tag);
-      subsetted_tags.add (tag);
-      made_changes = true;
+      bool made_changes = false;
+      for (hb_tag_t tag : pending_subset_tags)
+      {
+	if (!_dependencies_satisfied (plan, tag,
+				      subsetted_tags,
+				      pending_subset_tags))
+	{
+	  // delayed subsetting for some tables since they might have dependency on other tables
+	  // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated
+	  // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values
+	  continue;
+	}
 
-      success = _subset_table (plan, buf, tag);
-      if (unlikely (!success)) goto end;
-    }
+	pending_subset_tags.del (tag);
+	subsetted_tags.add (tag);
+	made_changes = true;
 
-    if (!made_changes)
-    {
-      DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed.");
-      success = false;
-      goto end;
+	success = _subset_table (plan, buf, tag);
+	if (unlikely (!success)) goto end;
+      }
+
+      if (!made_changes)
+      {
+	DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed.");
+	success = false;
+	goto end;
+      }
     }
   }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h	2023-07-09 05:55:34 UTC (rev 67588)
@@ -177,6 +177,13 @@
 
 #ifdef HB_EXPERIMENTAL_API
 HB_EXTERN hb_bool_t
+hb_subset_input_set_axis_range (hb_subset_input_t  *input,
+				hb_face_t          *face,
+				hb_tag_t            axis_tag,
+				float               axis_min_value,
+				float               axis_max_value);
+
+HB_EXTERN hb_bool_t
 hb_subset_input_override_name_table (hb_subset_input_t  *input,
 				     hb_ot_name_id_t     name_id,
 				     unsigned            platform_id,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -54,7 +54,7 @@
   hb_vector_t (const Iterable &o) : hb_vector_t ()
   {
     auto iter = hb_iter (o);
-    if (iter.is_random_access_iterator)
+    if (iter.is_random_access_iterator || iter.has_fast_len)
       alloc (hb_len (iter), true);
     hb_copy (iter, *this);
   }
@@ -62,8 +62,20 @@
   {
     alloc (o.length, true);
     if (unlikely (in_error ())) return;
-    copy_vector (o);
+    copy_array (o.as_array ());
   }
+  hb_vector_t (array_t o) : hb_vector_t ()
+  {
+    alloc (o.length, true);
+    if (unlikely (in_error ())) return;
+    copy_array (o);
+  }
+  hb_vector_t (c_array_t o) : hb_vector_t ()
+  {
+    alloc (o.length, true);
+    if (unlikely (in_error ())) return;
+    copy_array (o);
+  }
   hb_vector_t (hb_vector_t &&o)
   {
     allocated = o.allocated;
@@ -74,7 +86,7 @@
   ~hb_vector_t () { fini (); }
 
   public:
-  int allocated = 0; /* == -1 means allocation failed. */
+  int allocated = 0; /* < 0 means allocation failed. */
   unsigned int length = 0;
   public:
   Type *arrayZ = nullptr;
@@ -90,8 +102,14 @@
 
   void fini ()
   {
-    shrink_vector (0);
-    hb_free (arrayZ);
+    /* We allow a hack to make the vector point to a foriegn array
+     * by the user. In that case length/arrayZ are non-zero but
+     * allocated is zero. Don't free anything. */
+    if (allocated)
+    {
+      shrink_vector (0);
+      hb_free (arrayZ);
+    }
     init ();
   }
 
@@ -98,11 +116,7 @@
   void reset ()
   {
     if (unlikely (in_error ()))
-      /* Big Hack! We don't know the true allocated size before
-       * an allocation failure happened. But we know it was at
-       * least as big as length. Restore it to that and continue
-       * as if error did not happen. */
-      allocated = length;
+      reset_error ();
     resize (0);
   }
 
@@ -119,7 +133,7 @@
     alloc (o.length, true);
     if (unlikely (in_error ())) return *this;
 
-    copy_vector (o);
+    copy_array (o.as_array ());
 
     return *this;
   }
@@ -191,7 +205,7 @@
   Type *push ()
   {
     if (unlikely (!resize (length + 1)))
-      return &Crap (Type);
+      return std::addressof (Crap (Type));
     return std::addressof (arrayZ[length - 1]);
   }
   template <typename T,
@@ -201,7 +215,7 @@
   Type *push (T&& v)
   {
     Type *p = push ();
-    if (p == &Crap (Type))
+    if (p == std::addressof (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.
@@ -214,24 +228,33 @@
 	    hb_enable_if (std::is_copy_constructible<T2>::value)>
   Type *push (T&& v)
   {
-    if (unlikely (!alloc (length + 1)))
+    if (unlikely ((int) length >= allocated && !alloc (length + 1)))
       // 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 &Crap (Type);
+      return std::addressof (Crap (Type));
 
     /* Emplace. */
-    length++;
-    Type *p = std::addressof (arrayZ[length - 1]);
+    Type *p = std::addressof (arrayZ[length++]);
     return new (p) Type (std::forward<T> (v));
   }
 
   bool in_error () const { return allocated < 0; }
+  void set_error ()
+  {
+    assert (allocated >= 0);
+    allocated = -allocated - 1;
+  }
+  void reset_error ()
+  {
+    assert (allocated < 0);
+    allocated = -(allocated + 1);
+  }
 
   template <typename T = Type,
 	    hb_enable_if (hb_is_trivially_copy_assignable(T))>
   Type *
-  realloc_vector (unsigned new_allocated)
+  realloc_vector (unsigned new_allocated, hb_priority<0>)
   {
     if (!new_allocated)
     {
@@ -243,7 +266,7 @@
   template <typename T = Type,
 	    hb_enable_if (!hb_is_trivially_copy_assignable(T))>
   Type *
-  realloc_vector (unsigned new_allocated)
+  realloc_vector (unsigned new_allocated, hb_priority<0>)
   {
     if (!new_allocated)
     {
@@ -263,31 +286,52 @@
     }
     return new_array;
   }
+  /* Specialization for hb_vector_t<hb_{vector,array}_t<U>> to speed up. */
+  template <typename T = Type,
+	    hb_enable_if (hb_is_same (T, hb_vector_t<typename T::item_t>) ||
+			  hb_is_same (T, hb_array_t <typename T::item_t>))>
+  Type *
+  realloc_vector (unsigned new_allocated, hb_priority<1>)
+  {
+    if (!new_allocated)
+    {
+      hb_free (arrayZ);
+      return nullptr;
+    }
+    return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
+  }
 
   template <typename T = Type,
 	    hb_enable_if (hb_is_trivially_constructible(T))>
   void
-  grow_vector (unsigned size)
+  grow_vector (unsigned size, hb_priority<0>)
   {
-    memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
+    hb_memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
     length = size;
   }
   template <typename T = Type,
 	    hb_enable_if (!hb_is_trivially_constructible(T))>
   void
-  grow_vector (unsigned size)
+  grow_vector (unsigned size, hb_priority<0>)
   {
-    while (length < size)
-    {
-      length++;
-      new (std::addressof (arrayZ[length - 1])) Type ();
-    }
+    for (; length < size; length++)
+      new (std::addressof (arrayZ[length])) Type ();
   }
+  /* Specialization for hb_vector_t<hb_{vector,array}_t<U>> to speed up. */
+  template <typename T = Type,
+	    hb_enable_if (hb_is_same (T, hb_vector_t<typename T::item_t>) ||
+			  hb_is_same (T, hb_array_t <typename T::item_t>))>
+  void
+  grow_vector (unsigned size, hb_priority<1>)
+  {
+    hb_memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
+    length = size;
+  }
 
   template <typename T = Type,
 	    hb_enable_if (hb_is_trivially_copyable (T))>
   void
-  copy_vector (const hb_vector_t &other)
+  copy_array (hb_array_t<const Type> other)
   {
     length = other.length;
     if (!HB_OPTIMIZE_SIZE_VAL && sizeof (T) >= sizeof (long long))
@@ -301,7 +345,7 @@
 	    hb_enable_if (!hb_is_trivially_copyable (T) &&
 			   std::is_copy_constructible<T>::value)>
   void
-  copy_vector (const hb_vector_t &other)
+  copy_array (hb_array_t<const Type> other)
   {
     length = 0;
     while (length < other.length)
@@ -316,7 +360,7 @@
 			  std::is_default_constructible<T>::value &&
 			  std::is_copy_assignable<T>::value)>
   void
-  copy_vector (const hb_vector_t &other)
+  copy_array (hb_array_t<const Type> other)
   {
     length = 0;
     while (length < other.length)
@@ -330,11 +374,15 @@
   void
   shrink_vector (unsigned size)
   {
-    while ((unsigned) length > size)
+    assert (size <= length);
+    if (!std::is_trivially_destructible<Type>::value)
     {
-      arrayZ[(unsigned) length - 1].~Type ();
-      length--;
+      unsigned count = length - size;
+      Type *p = arrayZ + length - 1;
+      while (count--)
+        p--->~Type ();
     }
+    length = size;
   }
 
   void
@@ -381,11 +429,11 @@
 
     if (unlikely (overflows))
     {
-      allocated = -1;
+      set_error ();
       return false;
     }
 
-    Type *new_array = realloc_vector (new_allocated);
+    Type *new_array = realloc_vector (new_allocated, hb_prioritize);
 
     if (unlikely (new_allocated && !new_array))
     {
@@ -392,7 +440,7 @@
       if (new_allocated <= (unsigned) allocated)
         return true; // shrinking failed; it's okay; happens in our fuzzer
 
-      allocated = -1;
+      set_error ();
       return false;
     }
 
@@ -411,7 +459,7 @@
     if (size > length)
     {
       if (initialize)
-	grow_vector (size);
+	grow_vector (size, hb_prioritize);
     }
     else if (size < length)
     {

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-blob.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-blob.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-blob.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_BLOB_HH
+#define HB_WASM_API_BLOB_HH
+
+#include "hb-wasm-api.hh"
+
+namespace hb {
+namespace wasm {
+
+
+HB_WASM_API (void, blob_free) (HB_WASM_EXEC_ENV
+			       ptr_d(blob_t, blob))
+{
+  HB_PTR_PARAM (blob_t, blob);
+  if (unlikely (!blob))
+    return;
+
+  module_free (blob->data);
+
+  blob->data = nullref;
+  blob->length = 0;
+}
+
+
+}}
+
+#endif /* HB_WASM_API_BLOB_HH */

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-buffer.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-buffer.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-buffer.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,217 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_BUFFER_HH
+#define HB_WASM_API_BUFFER_HH
+
+#include "hb-wasm-api.hh"
+
+#include "hb-buffer.hh"
+
+namespace hb {
+namespace wasm {
+
+static_assert (sizeof (glyph_info_t) == sizeof (hb_glyph_info_t), "");
+static_assert (sizeof (glyph_position_t) == sizeof (hb_glyph_position_t), "");
+
+HB_WASM_API (bool_t, buffer_contents_realloc) (HB_WASM_EXEC_ENV
+					       ptr_d(buffer_contents_t, contents),
+					       uint32_t size)
+{
+  HB_PTR_PARAM (buffer_contents_t, contents);
+  if (unlikely (!contents))
+    return false;
+
+  if (size <= contents->length)
+    return true;
+
+  unsigned bytes;
+  if (hb_unsigned_mul_overflows (size, sizeof (glyph_info_t), &bytes))
+    return false;
+
+  glyph_info_t *info = HB_ARRAY_APP2NATIVE (glyph_info_t, contents->info, contents->length);
+  glyph_position_t *pos = HB_ARRAY_APP2NATIVE (glyph_position_t, contents->pos, contents->length);
+
+  if (unlikely (!info || !pos))
+    return false;
+
+  glyph_info_t *new_info = nullptr;
+  uint32_t new_inforef = module_malloc (bytes, (void **) &new_info);
+  glyph_position_t *new_pos = nullptr;
+  uint32_t new_posref = module_malloc (bytes, (void **) &new_pos);
+
+  unsigned old_bytes = contents->length * sizeof (glyph_info_t);
+  if (likely (new_inforef))
+  {
+    hb_memcpy (new_info, info, old_bytes);
+    module_free (contents->info);
+    contents->info = new_inforef;
+  }
+  if (likely (new_posref))
+  {
+    hb_memcpy (new_pos, pos, old_bytes);
+    module_free (contents->pos);
+    contents->pos = new_posref;
+  }
+
+  if (likely (new_info && new_pos))
+  {
+    contents->length = size;
+    return true;
+  }
+
+  return false;
+}
+
+HB_WASM_API (void, buffer_contents_free) (HB_WASM_EXEC_ENV
+					  ptr_d(buffer_contents_t, contents))
+{
+  HB_PTR_PARAM (buffer_contents_t, contents);
+  if (unlikely (!contents))
+    return;
+
+  module_free (contents->info);
+  module_free (contents->pos);
+
+  contents->info = nullref;
+  contents->pos = nullref;
+  contents->length = 0;
+}
+
+HB_WASM_API (bool_t, buffer_copy_contents) (HB_WASM_EXEC_ENV
+					    ptr_d(buffer_t, buffer),
+					    ptr_d(buffer_contents_t, contents))
+{
+  HB_REF2OBJ (buffer);
+  HB_PTR_PARAM (buffer_contents_t, contents);
+  if (unlikely (!contents))
+    return false;
+
+  if (buffer->have_output)
+    buffer->sync ();
+  if (!buffer->have_positions)
+    buffer->clear_positions ();
+
+  unsigned length = buffer->len;
+
+  if (length <= contents->length)
+  {
+    glyph_info_t *info = HB_ARRAY_APP2NATIVE (glyph_info_t, contents->info, length);
+    glyph_position_t *pos = HB_ARRAY_APP2NATIVE (glyph_position_t, contents->pos, length);
+
+    if (unlikely (!info || !pos))
+    {
+      contents->length = 0;
+      return false;
+    }
+
+    unsigned bytes = length * sizeof (hb_glyph_info_t);
+    hb_memcpy (info, buffer->info, bytes);
+    hb_memcpy (pos, buffer->pos, bytes);
+
+    return true;
+  }
+
+  module_free (contents->info);
+  module_free (contents->pos);
+
+  contents->length = length;
+  unsigned bytes = length * sizeof (hb_glyph_info_t);
+  contents->info = wasm_runtime_module_dup_data (module_inst, (const char *) buffer->info, bytes);
+  contents->pos = wasm_runtime_module_dup_data (module_inst, (const char *) buffer->pos, bytes);
+
+  if (length && (!contents->info || !contents->pos))
+  {
+    contents->length = 0;
+    return false;
+  }
+
+  return true;
+}
+
+HB_WASM_API (bool_t, buffer_set_contents) (HB_WASM_EXEC_ENV
+					   ptr_d(buffer_t, buffer),
+					   ptr_d(const buffer_contents_t, contents))
+{
+  HB_REF2OBJ (buffer);
+  HB_PTR_PARAM (buffer_contents_t, contents);
+  if (unlikely (!contents))
+    return false;
+
+  unsigned length = contents->length;
+  unsigned bytes;
+  if (unlikely (hb_unsigned_mul_overflows (length, sizeof (buffer->info[0]), &bytes)))
+    return false;
+
+  if (unlikely (!buffer->resize (length)))
+    return false;
+
+  glyph_info_t *info = (glyph_info_t *) (validate_app_addr (contents->info, bytes) ? addr_app_to_native (contents->info) : nullptr);
+  glyph_position_t *pos = (glyph_position_t *) (validate_app_addr (contents->pos, bytes) ? addr_app_to_native (contents->pos) : nullptr);
+
+  if (!buffer->have_positions)
+    buffer->clear_positions (); /* This is wasteful. */
+
+  hb_memcpy (buffer->info, info, bytes);
+  hb_memcpy (buffer->pos, pos, bytes);
+  buffer->len = length;
+
+  return true;
+}
+
+HB_WASM_API (direction_t, buffer_get_direction) (HB_WASM_EXEC_ENV
+						 ptr_d(buffer_t, buffer))
+{
+  HB_REF2OBJ (buffer);
+
+  return (direction_t) hb_buffer_get_direction (buffer);
+}
+
+HB_WASM_API (script_t, buffer_get_script) (HB_WASM_EXEC_ENV
+					   ptr_d(buffer_t, buffer))
+{
+  HB_REF2OBJ (buffer);
+
+  return hb_script_to_iso15924_tag (hb_buffer_get_script (buffer));
+}
+
+HB_WASM_API (void, buffer_reverse) (HB_WASM_EXEC_ENV
+				    ptr_d(buffer_t, buffer))
+{
+  HB_REF2OBJ (buffer);
+
+  hb_buffer_reverse (buffer);
+}
+
+HB_WASM_API (void, buffer_reverse_clusters) (HB_WASM_EXEC_ENV
+					     ptr_d(buffer_t, buffer))
+{
+  HB_REF2OBJ (buffer);
+
+  hb_buffer_reverse_clusters (buffer);
+}
+
+}}
+
+#endif /* HB_WASM_API_BUFFER_HH */

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-common.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-common.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_COMMON_HH
+#define HB_WASM_API_COMMON_HH
+
+#include "hb-wasm-api.hh"
+
+namespace hb {
+namespace wasm {
+
+
+HB_WASM_API (direction_t, script_get_horizontal_direction) (HB_WASM_EXEC_ENV
+							    script_t script)
+{
+  return (direction_t)
+	 hb_script_get_horizontal_direction (hb_script_from_iso15924_tag (script));
+}
+
+
+}}
+
+#endif /* HB_WASM_API_COMMON_HH */

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-face.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-face.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-face.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_FACE_HH
+#define HB_WASM_API_FACE_HH
+
+#include "hb-wasm-api.hh"
+
+namespace hb {
+namespace wasm {
+
+
+HB_WASM_API (ptr_t(face_t), face_create) (HB_WASM_EXEC_ENV
+					  ptr_d(blob_t, blob),
+					  unsigned int index)
+{
+  HB_PTR_PARAM (blob_t, blob);
+  hb_blob_t *hb_blob = hb_blob_create(
+				      HB_ARRAY_APP2NATIVE (char, blob->data, blob->length),
+				      blob->length,
+				      HB_MEMORY_MODE_DUPLICATE,
+				      NULL,
+				      NULL);
+
+  hb_face_t *face = hb_face_create(hb_blob, index);
+
+  HB_OBJ2REF (face);
+  return faceref;
+}
+
+HB_WASM_API (bool_t, face_copy_table) (HB_WASM_EXEC_ENV
+				       ptr_d(face_t, face),
+				       tag_t table_tag,
+				       ptr_d(blob_t, blob))
+{
+  HB_REF2OBJ (face);
+  HB_PTR_PARAM (blob_t, blob);
+  if (unlikely (!blob))
+    return false;
+
+  hb_blob_t *hb_blob = hb_face_reference_table (face, table_tag);
+
+  unsigned length;
+  const char *hb_data = hb_blob_get_data (hb_blob, &length);
+
+  if (length <= blob->length)
+  {
+    char *data = HB_ARRAY_APP2NATIVE (char, blob->data, length);
+
+    if (unlikely (!data))
+    {
+      blob->length = 0;
+      return false;
+    }
+
+    hb_memcpy (data, hb_data, length);
+
+    return true;
+  }
+
+  module_free (blob->data);
+
+  blob->length = length;
+  blob->data = wasm_runtime_module_dup_data (module_inst, hb_data, length);
+
+  hb_blob_destroy (hb_blob);
+
+  if (blob->length && !blob->data)
+  {
+    blob->length = 0;
+    return false;
+  }
+
+  return true;
+}
+
+HB_WASM_API (unsigned, face_get_upem) (HB_WASM_EXEC_ENV
+				       ptr_d(face_t, face))
+{
+  HB_REF2OBJ (face);
+
+  return hb_face_get_upem (face);
+}
+
+
+}}
+
+#endif /* HB_WASM_API_FACE_HH */

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-font.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-font.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-font.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,263 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_FONT_HH
+#define HB_WASM_API_FONT_HH
+
+#include "hb-wasm-api.hh"
+
+#include "hb-outline.hh"
+
+namespace hb {
+namespace wasm {
+
+
+HB_WASM_API (ptr_t(font_t), font_create) (HB_WASM_EXEC_ENV
+					  ptr_d(face_t, face))
+{
+  HB_REF2OBJ (face);
+
+  hb_font_t *font = hb_font_create (face);
+
+  HB_OBJ2REF (font);
+  return fontref;
+}
+
+HB_WASM_API (ptr_t(face_t), font_get_face) (HB_WASM_EXEC_ENV
+					    ptr_d(font_t, font))
+{
+  HB_REF2OBJ (font);
+
+  hb_face_t *face = hb_font_get_face (font);
+
+  HB_OBJ2REF (face);
+  return faceref;
+}
+
+HB_WASM_API (void, font_get_scale) (HB_WASM_EXEC_ENV
+				    ptr_d(font_t, font),
+				    ptr_d(int32_t, x_scale),
+				    ptr_d(int32_t, y_scale))
+{
+  HB_REF2OBJ (font);
+
+  HB_PTR_PARAM(int32_t, x_scale);
+  HB_PTR_PARAM(int32_t, y_scale);
+
+  hb_font_get_scale (font, x_scale, y_scale);
+}
+
+HB_WASM_API (codepoint_t, font_get_glyph) (HB_WASM_EXEC_ENV
+					      ptr_d(font_t, font),
+					      codepoint_t unicode,
+					      codepoint_t variation_selector)
+{
+  HB_REF2OBJ (font);
+  codepoint_t glyph;
+
+  hb_font_get_glyph (font, unicode, variation_selector, &glyph);
+  return glyph;
+}
+
+HB_WASM_API (position_t, font_get_glyph_h_advance) (HB_WASM_EXEC_ENV
+						    ptr_d(font_t, font),
+						    codepoint_t glyph)
+{
+  HB_REF2OBJ (font);
+  return hb_font_get_glyph_h_advance (font, glyph);
+}
+
+HB_WASM_API (position_t, font_get_glyph_v_advance) (HB_WASM_EXEC_ENV
+						    ptr_d(font_t, font),
+						    codepoint_t glyph)
+{
+  HB_REF2OBJ (font);
+  return hb_font_get_glyph_v_advance (font, glyph);
+}
+
+static_assert (sizeof (glyph_extents_t) == sizeof (hb_glyph_extents_t), "");
+
+HB_WASM_API (bool_t, font_get_glyph_extents) (HB_WASM_EXEC_ENV
+					      ptr_d(font_t, font),
+					      codepoint_t glyph,
+					      ptr_d(glyph_extents_t, extents))
+{
+  HB_REF2OBJ (font);
+  HB_PTR_PARAM (glyph_extents_t, extents);
+  if (unlikely (!extents))
+    return false;
+
+  return hb_font_get_glyph_extents (font, glyph,
+				    (hb_glyph_extents_t *) extents);
+}
+
+HB_WASM_API (void, font_glyph_to_string) (HB_WASM_EXEC_ENV
+					  ptr_d(font_t, font),
+					  codepoint_t glyph,
+					  char *s, uint32_t size)
+{
+  HB_REF2OBJ (font);
+
+  hb_font_glyph_to_string (font, glyph, s, size);
+}
+
+static_assert (sizeof (glyph_outline_point_t) == sizeof (hb_outline_point_t), "");
+static_assert (sizeof (uint32_t) == sizeof (hb_outline_t::contours[0]), "");
+
+HB_WASM_API (bool_t, font_copy_glyph_outline) (HB_WASM_EXEC_ENV
+					       ptr_d(font_t, font),
+					       codepoint_t glyph,
+					       ptr_d(glyph_outline_t, outline))
+{
+  HB_REF2OBJ (font);
+  HB_PTR_PARAM (glyph_outline_t, outline);
+  if (unlikely (!outline))
+    return false;
+
+  hb_outline_t hb_outline;
+  auto *funcs = hb_outline_recording_pen_get_funcs ();
+
+  hb_font_draw_glyph (font, glyph, funcs, &hb_outline);
+
+  if (unlikely (hb_outline.points.in_error () ||
+		hb_outline.contours.in_error ()))
+  {
+    outline->n_points = outline->n_contours = 0;
+    return false;
+  }
+
+  // TODO Check two buffers separately
+  if (hb_outline.points.length <= outline->n_points &&
+      hb_outline.contours.length <= outline->n_contours)
+  {
+    glyph_outline_point_t *points = HB_ARRAY_APP2NATIVE (glyph_outline_point_t, outline->points, hb_outline.points.length);
+    uint32_t *contours = HB_ARRAY_APP2NATIVE (uint32_t, outline->contours, hb_outline.contours.length);
+
+    if (unlikely (!points || !contours))
+    {
+      outline->n_points = outline->n_contours = 0;
+      return false;
+    }
+
+    hb_memcpy (points, hb_outline.points.arrayZ, hb_outline.points.get_size ());
+    hb_memcpy (contours, hb_outline.contours.arrayZ, hb_outline.contours.get_size ());
+
+    return true;
+  }
+
+  outline->n_points = hb_outline.points.length;
+  outline->points = wasm_runtime_module_dup_data (module_inst,
+						  (const char *) hb_outline.points.arrayZ,
+						  hb_outline.points.get_size ());
+  outline->n_contours = hb_outline.contours.length;
+  outline->contours = wasm_runtime_module_dup_data (module_inst,
+						    (const char *) hb_outline.contours.arrayZ,
+						    hb_outline.contours.get_size ());
+
+  if ((outline->n_points && !outline->points) ||
+      (!outline->n_contours && !outline->contours))
+  {
+    outline->n_points = outline->n_contours = 0;
+    return false;
+  }
+
+  return true;
+}
+
+HB_WASM_API (void, glyph_outline_free) (HB_WASM_EXEC_ENV
+					ptr_d(glyph_outline_t, outline))
+{
+  HB_PTR_PARAM (glyph_outline_t, outline);
+  if (unlikely (!outline))
+    return;
+
+  module_free (outline->points);
+  module_free (outline->contours);
+
+  outline->n_points = 0;
+  outline->points = nullref;
+  outline->n_contours = 0;
+  outline->contours = nullref;
+}
+
+HB_WASM_API (bool_t, font_copy_coords) (HB_WASM_EXEC_ENV
+					  ptr_d(font_t, font),
+					  ptr_d(coords_t, coords))
+{
+  HB_REF2OBJ (font);
+  HB_PTR_PARAM (coords_t, coords);
+  if (unlikely (!coords))
+    return false;
+
+  unsigned our_length;
+  const int* our_coords = hb_font_get_var_coords_normalized(font, &our_length);
+
+  if (our_length <= coords->length) {
+    int *their_coords = HB_ARRAY_APP2NATIVE (int, coords->coords, our_length);
+    if (unlikely(!their_coords)) {
+    	coords->length = 0;
+    	return false;
+    }
+		unsigned bytes = our_length * sizeof (int);
+    hb_memcpy (their_coords, our_coords, bytes);
+
+    return true;
+  }
+
+  module_free (coords->coords);
+  coords->length = our_length;
+	unsigned bytes = our_length * sizeof (int);
+  coords->coords = wasm_runtime_module_dup_data (module_inst, (const char *) our_coords, bytes);
+	if (our_length && !coords->coords)
+	  {
+    coords->length = 0;
+    return false;
+  }
+
+  return true;
+}
+
+HB_WASM_API (bool_t, font_set_coords) (HB_WASM_EXEC_ENV
+					  ptr_d(font_t, font),
+					  ptr_d(coords_t, coords))
+{
+  HB_REF2OBJ (font);
+  HB_PTR_PARAM (coords_t, coords);
+  if (unlikely (!coords))
+    return false;
+
+  unsigned length = coords->length;
+  unsigned bytes;
+  if (unlikely (hb_unsigned_mul_overflows (length, sizeof (int), &bytes)))
+    return false;
+
+  const int *our_coords = (const int *) (validate_app_addr (coords->coords, bytes) ? addr_app_to_native (coords->coords) : nullptr);
+  hb_font_set_var_coords_normalized(font, our_coords, length);
+  return true;
+}
+
+
+}}
+
+#endif /* HB_WASM_API_FONT_HH */

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-shape.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-shape.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-shape.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_SHAPE_HH
+#define HB_WASM_API_SHAPE_HH
+
+#include "hb-wasm-api.hh"
+
+namespace hb {
+namespace wasm {
+
+
+static_assert (sizeof (feature_t) == sizeof (hb_feature_t), "");
+
+HB_WASM_INTERFACE (bool_t, shape_with) (HB_WASM_EXEC_ENV
+				        ptr_d(font_t, font),
+				        ptr_d(buffer_t, buffer),
+				        ptr_d(const feature_t, features),
+				        uint32_t num_features,
+					const char *shaper)
+{
+  if (unlikely (0 == strcmp (shaper, "wasm")))
+    return false;
+
+  HB_REF2OBJ (font);
+  HB_REF2OBJ (buffer);
+
+  /* Pre-conditions that make hb_shape_full() crash should be checked here. */
+
+  if (unlikely (!buffer->ensure_unicode ()))
+    return false;
+
+  if (unlikely (!HB_DIRECTION_IS_VALID (buffer->props.direction)))
+    return false;
+
+  HB_ARRAY_PARAM (const feature_t, features, num_features);
+  if (unlikely (!features && num_features))
+    return false;
+
+  const char * shaper_list[] = {shaper, nullptr};
+  return hb_shape_full (font, buffer,
+			(hb_feature_t *) features, num_features,
+			shaper_list);
+}
+
+
+}}
+
+#endif /* HB_WASM_API_SHAPE_HH */

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  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.
+ */
+
+#include "hb.hh"
+
+#ifdef HAVE_WASM
+
+#include "hb-wasm-api.hh"
+
+#define module_inst wasm_runtime_get_module_inst (exec_env)
+
+
+#include "hb-wasm-api-blob.hh"
+#include "hb-wasm-api-buffer.hh"
+#include "hb-wasm-api-common.hh"
+#include "hb-wasm-api-face.hh"
+#include "hb-wasm-api-font.hh"
+#include "hb-wasm-api-shape.hh"
+
+
+#undef module_inst
+
+hb_user_data_key_t _hb_wasm_ref_type_key = {};
+
+#endif

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.h	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.h	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,319 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_H
+#define HB_WASM_API_H
+
+/*
+#include "hb.h"
+*/
+
+#include <stdint.h>
+
+
+#ifndef HB_WASM_BEGIN_DECLS
+# ifdef __cplusplus
+#  define HB_WASM_BEGIN_DECLS	extern "C" {
+#  define HB_WASM_END_DECLS	}
+# else /* !__cplusplus */
+#  define HB_WASM_BEGIN_DECLS
+#  define HB_WASM_END_DECLS
+# endif /* !__cplusplus */
+#endif
+
+
+HB_WASM_BEGIN_DECLS
+
+#ifndef HB_WASM_API
+#define HB_WASM_API(ret_t, name) ret_t name
+#endif
+#ifndef HB_WASM_API_COMPOUND /* compound return type */
+#define HB_WASM_API_COMPOUND(ret_t, name) HB_WASM_API(ret_t, name)
+#endif
+#ifndef HB_WASM_INTERFACE
+#define HB_WASM_INTERFACE(ret_t, name) ret_t name
+#endif
+#ifndef HB_WASM_EXEC_ENV
+#define HB_WASM_EXEC_ENV
+#endif
+#ifndef HB_WASM_EXEC_ENV_COMPOUND
+#define HB_WASM_EXEC_ENV_COMPOUND HB_WASM_EXEC_ENV
+#endif
+
+
+#ifndef bool_t
+#define bool_t uint32_t
+#endif
+#ifndef ptr_t
+#define ptr_t(type_t) type_t *
+#endif
+#ifndef ptr_d
+#define ptr_d(type_t, name) type_t *name
+#endif
+
+typedef uint32_t codepoint_t;
+typedef int32_t position_t;
+typedef uint32_t mask_t;
+typedef uint32_t tag_t;
+#define TAG(c1,c2,c3,c4) ((tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF)))
+
+typedef enum {
+  DIRECTION_INVALID = 0,
+  DIRECTION_LTR = 4,
+  DIRECTION_RTL,
+  DIRECTION_TTB,
+  DIRECTION_BTT
+} direction_t;
+#define DIRECTION_IS_VALID(dir)		((((unsigned int) (dir)) & ~3U) == 4)
+#define DIRECTION_IS_HORIZONTAL(dir)	((((unsigned int) (dir)) & ~1U) == 4)
+#define DIRECTION_IS_VERTICAL(dir)	((((unsigned int) (dir)) & ~1U) == 6)
+#define DIRECTION_IS_FORWARD(dir)	((((unsigned int) (dir)) & ~2U) == 4)
+#define DIRECTION_IS_BACKWARD(dir)	((((unsigned int) (dir)) & ~2U) == 5)
+#define DIRECTION_REVERSE(dir)		((direction_t) (((unsigned int) (dir)) ^ 1))
+
+typedef tag_t script_t; /* ISO 15924 representation of Unicode scripts. */
+
+
+/* common */
+
+HB_WASM_API (direction_t, script_get_horizontal_direction) (HB_WASM_EXEC_ENV
+							    script_t script);
+
+
+/* blob */
+
+typedef struct
+{
+  uint32_t length;
+  ptr_t(char) data;
+} blob_t;
+#define BLOB_INIT {0, 0}
+
+HB_WASM_API (void, blob_free) (HB_WASM_EXEC_ENV
+			       ptr_d(blob_t, blob));
+
+/* buffer */
+
+typedef struct
+{
+  uint32_t codepoint;
+  uint32_t mask;
+  uint32_t cluster;
+  uint32_t var1;
+  uint32_t var2;
+} glyph_info_t;
+
+typedef struct
+{
+  position_t x_advance;
+  position_t y_advance;
+  position_t x_offset;
+  position_t y_offset;
+  uint32_t var;
+} glyph_position_t;
+
+typedef struct
+{
+  uint32_t length;
+  ptr_t(glyph_info_t) info;
+  ptr_t(glyph_position_t) pos;
+} buffer_contents_t;
+#define BUFFER_CONTENTS_INIT {0, 0, 0}
+
+HB_WASM_API (bool_t, buffer_contents_realloc) (HB_WASM_EXEC_ENV
+					       ptr_d(buffer_contents_t, contents),
+					       uint32_t size);
+
+HB_WASM_API (void, buffer_contents_free) (HB_WASM_EXEC_ENV
+					  ptr_d(buffer_contents_t, contents));
+
+typedef struct buffer_t buffer_t;
+
+HB_WASM_API (bool_t, buffer_copy_contents) (HB_WASM_EXEC_ENV
+					    ptr_d(buffer_t, buffer),
+					    ptr_d(buffer_contents_t, contents));
+
+HB_WASM_API (bool_t, buffer_set_contents) (HB_WASM_EXEC_ENV
+					   ptr_d(buffer_t, buffer),
+					   ptr_d(const buffer_contents_t, contents));
+
+HB_WASM_API (direction_t, buffer_get_direction) (HB_WASM_EXEC_ENV
+						 ptr_d(buffer_t, buffer));
+
+HB_WASM_API (script_t, buffer_get_script) (HB_WASM_EXEC_ENV
+					   ptr_d(buffer_t, buffer));
+
+HB_WASM_API (void, buffer_reverse) (HB_WASM_EXEC_ENV
+				    ptr_d(buffer_t, buffer));
+
+HB_WASM_API (void, buffer_reverse_clusters) (HB_WASM_EXEC_ENV
+					     ptr_d(buffer_t, buffer));
+
+/* face */
+
+typedef struct face_t face_t;
+
+HB_WASM_API (ptr_t(face_t), face_create) (HB_WASM_EXEC_ENV
+					  ptr_d(blob_t, blob),
+					  unsigned int);
+
+HB_WASM_API (bool_t, face_copy_table) (HB_WASM_EXEC_ENV
+				       ptr_d(face_t, face),
+				       tag_t table_tag,
+				       ptr_d(blob_t, blob));
+
+HB_WASM_API (unsigned, face_get_upem) (HB_WASM_EXEC_ENV
+				       ptr_d(face_t, face));
+
+/* font */
+
+typedef struct font_t font_t;
+
+HB_WASM_API (ptr_t(font_t), font_create) (HB_WASM_EXEC_ENV
+					  ptr_d(face_t, face));
+
+HB_WASM_API (ptr_t(face_t), font_get_face) (HB_WASM_EXEC_ENV
+					    ptr_d(font_t, font));
+
+HB_WASM_API (void, font_get_scale) (HB_WASM_EXEC_ENV
+				    ptr_d(font_t, font),
+				    ptr_d(int32_t, x_scale),
+				    ptr_d(int32_t, y_scale));
+
+HB_WASM_API (codepoint_t, font_get_glyph) (HB_WASM_EXEC_ENV
+					      ptr_d(font_t, font),
+					      codepoint_t unicode,
+					      codepoint_t variation_selector);
+
+HB_WASM_API (position_t, font_get_glyph_h_advance) (HB_WASM_EXEC_ENV
+						    ptr_d(font_t, font),
+						    codepoint_t glyph);
+
+HB_WASM_API (position_t, font_get_glyph_v_advance) (HB_WASM_EXEC_ENV
+						    ptr_d(font_t, font),
+						    codepoint_t glyph);
+
+typedef struct
+{
+  position_t x_bearing;
+  position_t y_bearing;
+  position_t width;
+  position_t height;
+} glyph_extents_t;
+
+HB_WASM_API (bool_t, font_get_glyph_extents) (HB_WASM_EXEC_ENV
+					      ptr_d(font_t, font),
+					      codepoint_t glyph,
+					      ptr_d(glyph_extents_t, extents));
+
+HB_WASM_API (void, font_glyph_to_string) (HB_WASM_EXEC_ENV
+					  ptr_d(font_t, font),
+					  codepoint_t glyph,
+					  char *s, uint32_t size);
+
+
+typedef struct
+{
+  unsigned int length;
+  ptr_t(int) coords;
+} coords_t;
+
+HB_WASM_API (bool_t, font_copy_coords) (HB_WASM_EXEC_ENV
+					  ptr_d(font_t, font),
+					  ptr_d(coords_t, coords));
+
+HB_WASM_API (bool_t, font_set_coords) (HB_WASM_EXEC_ENV
+					  ptr_d(font_t, font),
+					  ptr_d(coords_t, coords));
+
+/* outline */
+
+enum glyph_outline_point_type_t
+{
+  MOVE_TO,
+  LINE_TO,
+  QUADRATIC_TO,
+  CUBIC_TO,
+};
+
+typedef struct
+{
+  float x;
+  float y;
+  uint32_t type;
+} glyph_outline_point_t;
+
+typedef struct
+{
+  uint32_t n_points;
+  ptr_t(glyph_outline_point_t) points;
+  uint32_t n_contours;
+  ptr_t(uint32_t) contours;
+} glyph_outline_t;
+#define GLYPH_OUTLINE_INIT {0, 0, 0, 0}
+
+HB_WASM_API (void, glyph_outline_free) (HB_WASM_EXEC_ENV
+					ptr_d(glyph_outline_t, outline));
+
+HB_WASM_API (bool_t, font_copy_glyph_outline) (HB_WASM_EXEC_ENV
+					       ptr_d(font_t, font),
+					       codepoint_t glyph,
+					       ptr_d(glyph_outline_t, outline));
+
+
+/* shape */
+
+typedef struct
+{
+  tag_t    tag;
+  uint32_t value;
+  uint32_t start;
+  uint32_t end;
+} feature_t;
+#define FEATURE_GLOBAL_START	0
+#define FEATURE_GLOBAL_END	((uint32_t) -1)
+
+HB_WASM_API (bool_t, shape_with) (HB_WASM_EXEC_ENV
+				  ptr_d(font_t, font),
+				  ptr_d(buffer_t, buffer),
+				  ptr_d(const feature_t, features),
+				  uint32_t num_features,
+				  const char *shaper);
+
+/* Implement these in your shaper. */
+
+HB_WASM_INTERFACE (ptr_t(void), shape_plan_create) (ptr_d(face_t, face));
+
+HB_WASM_INTERFACE (bool_t, shape) (ptr_d(void, shape_plan),
+				   ptr_d(font_t, font),
+				   ptr_d(buffer_t, buffer),
+				   ptr_d(const feature_t, features),
+				   uint32_t num_features);
+
+HB_WASM_INTERFACE (void, shape_plan_destroy) (ptr_d(void, shape_plan));
+
+
+HB_WASM_END_DECLS
+
+#endif /* HB_WASM_API_H */

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2023  Behdad Esfahbod
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_HH
+#define HB_WASM_API_HH
+
+#include "hb.hh"
+
+#include <wasm_export.h>
+
+#define HB_WASM_BEGIN_DECLS namespace hb { namespace wasm {
+#define HB_WASM_END_DECLS }}
+
+#define HB_WASM_API(ret_t, name) HB_INTERNAL ret_t name
+#define HB_WASM_API_COMPOUND(ret_t, name) HB_INTERNAL void name
+
+#define HB_WASM_EXEC_ENV wasm_exec_env_t exec_env,
+#define HB_WASM_EXEC_ENV_COMPOUND wasm_exec_env_t exec_env, ptr_t() retptr,
+
+#define ptr_t(type_t) uint32_t
+#define ptr_d(type_t, name) uint32_t name##ptr
+
+#include "hb-wasm-api.h"
+
+#undef HB_WASM_BEGIN_DECLS
+#undef HB_WASM_END_DECLS
+
+
+enum {
+  hb_wasm_ref_type_none,
+  hb_wasm_ref_type_face,
+  hb_wasm_ref_type_font,
+  hb_wasm_ref_type_buffer,
+};
+
+HB_INTERNAL extern hb_user_data_key_t _hb_wasm_ref_type_key;
+
+#define nullref 0
+
+#define HB_REF2OBJ(obj) \
+  hb_##obj##_t *obj = nullptr; \
+  HB_STMT_START { \
+    (void) wasm_externref_ref2obj (obj##ptr, (void **) &obj); \
+    /* Check object type. */ \
+    /* This works because all our objects have the same hb_object_t layout. */ \
+    if (unlikely (hb_##obj##_get_user_data (obj, &_hb_wasm_ref_type_key) != \
+		  (void *) hb_wasm_ref_type_##obj)) \
+      obj = hb_##obj##_get_empty (); \
+  } HB_STMT_END
+
+#define HB_OBJ2REF(obj) \
+  uint32_t obj##ref = nullref; \
+  HB_STMT_START { \
+    hb_##obj##_set_user_data (obj, &_hb_wasm_ref_type_key, \
+			      (void *) hb_wasm_ref_type_##obj, \
+			      nullptr, false); \
+    (void) wasm_externref_obj2ref (module_inst, obj, &obj##ref); \
+  } HB_STMT_END
+
+#define HB_RETURN_STRUCT(type, name) \
+  type *_name_ptr = nullptr; \
+  { \
+    if (likely (wasm_runtime_validate_app_addr (module_inst, \
+						retptr, sizeof (type)))) \
+    { \
+      _name_ptr = (type *) wasm_runtime_addr_app_to_native (module_inst, retptr); \
+      if (unlikely (!_name_ptr)) \
+	return; \
+    } \
+  } \
+  type &name = *_name_ptr
+
+#define HB_PTR_PARAM(type, name) \
+  type *name = nullptr; \
+  HB_STMT_START { \
+    if (likely (wasm_runtime_validate_app_addr (module_inst, \
+						name##ptr, sizeof (type)))) \
+      name = (type *) wasm_runtime_addr_app_to_native (module_inst, name##ptr); \
+  } HB_STMT_END
+
+#define HB_ARRAY_PARAM(type, name, length) \
+  type *name = nullptr; \
+  HB_STMT_START { \
+    if (likely (!hb_unsigned_mul_overflows (length, sizeof (type)) && \
+		wasm_runtime_validate_app_addr (module_inst, \
+						name##ptr, length * sizeof (type)))) \
+      name = (type *) wasm_runtime_addr_app_to_native (module_inst, name##ptr); \
+  } HB_STMT_END
+
+#define HB_ARRAY_APP2NATIVE(type, name, length) \
+    ((type *) (!hb_unsigned_mul_overflows (length, sizeof (type)) && \
+	       validate_app_addr (name, (length) * sizeof (type)) ? \
+	       addr_app_to_native (name) : nullptr))
+
+
+#endif /* HB_WASM_API_HH */

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,470 @@
+/*
+ * Copyright © 2011  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#undef HB_DEBUG_WASM
+#define HB_DEBUG_WASM 1
+
+#include "hb-shaper-impl.hh"
+
+#ifdef HAVE_WASM
+
+/* Compile wasm-micro-runtime with:
+ *
+ * $ cmake -DWAMR_BUILD_MULTI_MODULE=1 -DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_FAST_JIT=1
+ * $ make
+ *
+ * If you manage to build a wasm shared module successfully and want to use it,
+ * do the following:
+ *
+ *   - Add -DWAMR_BUILD_MULTI_MODULE=1 to your cmake build for wasm-micro-runtime,
+ *
+ *   - Remove the #define HB_WASM_NO_MODULES line below,
+ *
+ *   - Install your shared module with name ending in .wasm in
+ *     $(prefix)/$(libdir)/harfbuzz/wasm/
+ *
+ *   - Build your font's wasm code importing the shared modules with the desired
+ *     name. This can be done eg.: __attribute__((import_module("graphite2")))
+ *     before each symbol in the the shared-module's headers.
+ *
+ *   - Try shaping your font and hope for the best...
+ *
+ * I haven't been able to get this to work since emcc's support for shared libraries
+ * requires support from the host that seems to be missing from wasm-micro-runtime?
+ */
+
+#include "hb-wasm-api.hh"
+#include "hb-wasm-api-list.hh"
+
+#ifndef HB_WASM_NO_MODULES
+#define HB_WASM_NO_MODULES
+#endif
+
+
+#ifndef HB_WASM_NO_MODULES
+static bool HB_UNUSED
+_hb_wasm_module_reader (const char *module_name,
+		       uint8_t **p_buffer, uint32_t *p_size)
+{
+  char path[sizeof (HB_WASM_MODULE_DIR) + 64] = HB_WASM_MODULE_DIR "/";
+  strncat (path, module_name, sizeof (path) - sizeof (HB_WASM_MODULE_DIR) - 16);
+  strncat (path, ".wasm", 6);
+
+  auto *blob = hb_blob_create_from_file (path);
+
+  unsigned length;
+  auto *data = hb_blob_get_data (blob, &length);
+
+  *p_buffer = (uint8_t *) hb_malloc (length);
+
+  if (length && !p_buffer)
+    return false;
+
+  memcpy (*p_buffer, data, length);
+  *p_size = length;
+
+  hb_blob_destroy (blob);
+
+  return true;
+}
+
+static void HB_UNUSED
+_hb_wasm_module_destroyer (uint8_t *buffer, uint32_t size)
+{
+  hb_free (buffer);
+}
+#endif
+
+/*
+ * shaper face data
+ */
+
+#define HB_WASM_TAG_WASM HB_TAG('W','a','s','m')
+
+struct hb_wasm_shape_plan_t {
+  wasm_module_inst_t module_inst;
+  wasm_exec_env_t exec_env;
+  ptr_d(void, wasm_shape_plan);
+};
+
+struct hb_wasm_face_data_t {
+  hb_blob_t *wasm_blob;
+  wasm_module_t wasm_module;
+  mutable hb_atomic_ptr_t<hb_wasm_shape_plan_t> plan;
+};
+
+static bool
+_hb_wasm_init ()
+{
+  /* XXX
+   *
+   * Umm. Make this threadsafe. How?!
+   * It's clunky that we can't allocate a static mutex.
+   * So we have to first allocate one on the heap atomically...
+   *
+   * Do we also need to lock around module creation?
+   *
+   * Also, wasm-micro-runtime uses a singleton instance. So if
+   * another library or client uses it, all bets are off. :-(
+   * If nothing else, around HB_REF2OBJ().
+   */
+
+  static bool initialized;
+  if (initialized)
+    return true;
+
+  RuntimeInitArgs init_args;
+  hb_memset (&init_args, 0, sizeof (RuntimeInitArgs));
+
+  init_args.mem_alloc_type = Alloc_With_Allocator;
+  init_args.mem_alloc_option.allocator.malloc_func = (void *) hb_malloc;
+  init_args.mem_alloc_option.allocator.realloc_func = (void *) hb_realloc;
+  init_args.mem_alloc_option.allocator.free_func = (void *) hb_free;
+
+  // Native symbols need below registration phase
+  init_args.n_native_symbols = ARRAY_LENGTH (_hb_wasm_native_symbols);
+  init_args.native_module_name = "env";
+  init_args.native_symbols = _hb_wasm_native_symbols;
+
+  if (unlikely (!wasm_runtime_full_init (&init_args)))
+  {
+    DEBUG_MSG (WASM, nullptr, "Init runtime environment failed.");
+    return false;
+  }
+
+#ifndef HB_WASM_NO_MODULES
+  wasm_runtime_set_module_reader (_hb_wasm_module_reader,
+				  _hb_wasm_module_destroyer);
+#endif
+
+  initialized = true;
+  return true;
+}
+
+hb_wasm_face_data_t *
+_hb_wasm_shaper_face_data_create (hb_face_t *face)
+{
+  char error[128];
+  hb_wasm_face_data_t *data = nullptr;
+  hb_blob_t *wasm_blob = nullptr;
+  wasm_module_t wasm_module = nullptr;
+
+  wasm_blob = hb_face_reference_table (face, HB_WASM_TAG_WASM);
+  unsigned length = hb_blob_get_length (wasm_blob);
+  if (!length)
+    goto fail;
+
+  if (!_hb_wasm_init ())
+    goto fail;
+
+  wasm_module = wasm_runtime_load ((uint8_t *) hb_blob_get_data_writable (wasm_blob, nullptr),
+				   length, error, sizeof (error));
+  if (unlikely (!wasm_module))
+  {
+    DEBUG_MSG (WASM, nullptr, "Load wasm module failed: %s", error);
+    goto fail;
+  }
+
+  data = (hb_wasm_face_data_t *) hb_calloc (1, sizeof (hb_wasm_face_data_t));
+  if (unlikely (!data))
+    goto fail;
+
+  data->wasm_blob = wasm_blob;
+  data->wasm_module = wasm_module;
+
+  return data;
+
+fail:
+  if (wasm_module)
+      wasm_runtime_unload (wasm_module);
+  hb_blob_destroy (wasm_blob);
+  hb_free (data);
+  return nullptr;
+}
+
+static hb_wasm_shape_plan_t *
+acquire_shape_plan (hb_face_t *face,
+		    const hb_wasm_face_data_t *face_data)
+{
+  char error[128];
+
+  /* Fetch cached one if available. */
+  hb_wasm_shape_plan_t *plan = face_data->plan.get_acquire ();
+  if (likely (plan && face_data->plan.cmpexch (plan, nullptr)))
+    return plan;
+
+  plan = (hb_wasm_shape_plan_t *) hb_calloc (1, sizeof (hb_wasm_shape_plan_t));
+
+  wasm_module_inst_t module_inst = nullptr;
+  wasm_exec_env_t exec_env = nullptr;
+  wasm_function_inst_t func = nullptr;
+
+  constexpr uint32_t stack_size = 32 * 1024, heap_size = 2 * 1024 * 1024;
+
+  module_inst = plan->module_inst = wasm_runtime_instantiate (face_data->wasm_module,
+							      stack_size, heap_size,
+							      error, sizeof (error));
+  if (unlikely (!module_inst))
+  {
+    DEBUG_MSG (WASM, face_data, "Create wasm module instance failed: %s", error);
+    goto fail;
+  }
+
+  exec_env = plan->exec_env = wasm_runtime_create_exec_env (module_inst,
+							    stack_size);
+  if (unlikely (!exec_env)) {
+    DEBUG_MSG (WASM, face_data, "Create wasm execution environment failed.");
+    goto fail;
+  }
+
+  func = wasm_runtime_lookup_function (module_inst, "shape_plan_create", nullptr);
+  if (func)
+  {
+    wasm_val_t results[1];
+    wasm_val_t arguments[1];
+
+    HB_OBJ2REF (face);
+    if (unlikely (!faceref))
+    {
+      DEBUG_MSG (WASM, face_data, "Failed to register face object.");
+      goto fail;
+    }
+
+    results[0].kind = WASM_I32;
+    arguments[0].kind = WASM_I32;
+    arguments[0].of.i32 = faceref;
+    bool ret = wasm_runtime_call_wasm_a (exec_env, func,
+					 ARRAY_LENGTH (results), results,
+					 ARRAY_LENGTH (arguments), arguments);
+
+    if (unlikely (!ret))
+    {
+      DEBUG_MSG (WASM, module_inst, "Calling shape_plan_create() failed: %s",
+		 wasm_runtime_get_exception (module_inst));
+      goto fail;
+    }
+    plan->wasm_shape_planptr = results[0].of.i32;
+  }
+
+  return plan;
+
+fail:
+
+  if (exec_env)
+    wasm_runtime_destroy_exec_env (exec_env);
+  if (module_inst)
+    wasm_runtime_deinstantiate (module_inst);
+  hb_free (plan);
+  return nullptr;
+}
+
+static void
+release_shape_plan (const hb_wasm_face_data_t *face_data,
+		    hb_wasm_shape_plan_t *plan,
+		    bool cache = false)
+{
+  if (cache && face_data->plan.cmpexch (nullptr, plan))
+    return;
+
+  auto *module_inst = plan->module_inst;
+  auto *exec_env = plan->exec_env;
+
+  /* Is there even any point to having a shape_plan_destroy function
+   * and calling it? */
+  if (plan->wasm_shape_planptr)
+  {
+
+    auto *func = wasm_runtime_lookup_function (module_inst, "shape_plan_destroy", nullptr);
+    if (func)
+    {
+      wasm_val_t arguments[1];
+
+      arguments[0].kind = WASM_I32;
+      arguments[0].of.i32 = plan->wasm_shape_planptr;
+      bool ret = wasm_runtime_call_wasm_a (exec_env, func,
+					   0, nullptr,
+					   ARRAY_LENGTH (arguments), arguments);
+
+      if (unlikely (!ret))
+      {
+	DEBUG_MSG (WASM, module_inst, "Calling shape_plan_destroy() failed: %s",
+		   wasm_runtime_get_exception (module_inst));
+      }
+    }
+  }
+
+  wasm_runtime_destroy_exec_env (exec_env);
+  wasm_runtime_deinstantiate (module_inst);
+  hb_free (plan);
+}
+
+void
+_hb_wasm_shaper_face_data_destroy (hb_wasm_face_data_t *data)
+{
+  if (data->plan.get_relaxed ())
+    release_shape_plan (data, data->plan);
+  wasm_runtime_unload (data->wasm_module);
+  hb_blob_destroy (data->wasm_blob);
+  hb_free (data);
+}
+
+
+/*
+ * shaper font data
+ */
+
+struct hb_wasm_font_data_t {};
+
+hb_wasm_font_data_t *
+_hb_wasm_shaper_font_data_create (hb_font_t *font HB_UNUSED)
+{
+  return (hb_wasm_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+}
+
+void
+_hb_wasm_shaper_font_data_destroy (hb_wasm_font_data_t *data HB_UNUSED)
+{
+}
+
+
+/*
+ * shaper
+ */
+
+hb_bool_t
+_hb_wasm_shape (hb_shape_plan_t    *shape_plan,
+		hb_font_t          *font,
+		hb_buffer_t        *buffer,
+		const hb_feature_t *features,
+		unsigned int        num_features)
+{
+  if (unlikely (buffer->in_error ()))
+    return false;
+
+  bool ret = true;
+  hb_face_t *face = font->face;
+  const hb_wasm_face_data_t *face_data = face->data.wasm;
+
+  bool retried = false;
+  if (0)
+  {
+retry:
+    DEBUG_MSG (WASM, font, "Retrying...");
+  }
+
+  wasm_function_inst_t func = nullptr;
+
+  hb_wasm_shape_plan_t *plan = acquire_shape_plan (face, face_data);
+  if (unlikely (!plan))
+  {
+    DEBUG_MSG (WASM, face_data, "Acquiring shape-plan failed.");
+    return false;
+  }
+
+  auto *module_inst = plan->module_inst;
+  auto *exec_env = plan->exec_env;
+
+  HB_OBJ2REF (font);
+  HB_OBJ2REF (buffer);
+  if (unlikely (!fontref || !bufferref))
+  {
+    DEBUG_MSG (WASM, module_inst, "Failed to register objects.");
+    goto fail;
+  }
+
+  func = wasm_runtime_lookup_function (module_inst, "shape", nullptr);
+  if (unlikely (!func))
+  {
+    DEBUG_MSG (WASM, module_inst, "Shape function not found.");
+    goto fail;
+  }
+
+  wasm_val_t results[1];
+  wasm_val_t arguments[5];
+
+  results[0].kind = WASM_I32;
+  arguments[0].kind = WASM_I32;
+  arguments[0].of.i32 = plan->wasm_shape_planptr;
+  arguments[1].kind = WASM_I32;
+  arguments[1].of.i32 = fontref;
+  arguments[2].kind = WASM_I32;
+  arguments[2].of.i32 = bufferref;
+  arguments[3].kind = WASM_I32;
+  arguments[3].of.i32 = num_features ? wasm_runtime_module_dup_data (module_inst,
+								     (const char *) features,
+								     num_features * sizeof (features[0])) : 0;
+  arguments[4].kind = WASM_I32;
+  arguments[4].of.i32 = num_features;
+
+  ret = wasm_runtime_call_wasm_a (exec_env, func,
+				  ARRAY_LENGTH (results), results,
+				  ARRAY_LENGTH (arguments), arguments);
+
+  if (num_features)
+    wasm_runtime_module_free (module_inst, arguments[2].of.i32);
+
+  if (unlikely (!ret || !results[0].of.i32))
+  {
+    DEBUG_MSG (WASM, module_inst, "Calling shape() failed: %s",
+	       wasm_runtime_get_exception (module_inst));
+    if (!buffer->ensure_unicode ())
+    {
+      DEBUG_MSG (WASM, font, "Shape failed but buffer is not in Unicode; failing...");
+      goto fail;
+    }
+    if (retried)
+    {
+      DEBUG_MSG (WASM, font, "Giving up...");
+      goto fail;
+    }
+    buffer->successful = true;
+    retried = true;
+    release_shape_plan (face_data, plan);
+    plan = nullptr;
+    goto retry;
+  }
+
+  /* TODO Regularize clusters according to direction & cluster level,
+   * such that client doesn't crash with unmet expectations. */
+
+  if (!results[0].of.i32)
+  {
+fail:
+    ret = false;
+  }
+
+  release_shape_plan (face_data, plan, ret);
+
+  if (ret)
+  {
+    buffer->clear_glyph_flags ();
+    buffer->unsafe_to_break ();
+  }
+
+  return ret;
+}
+
+#endif

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh	2023-07-09 05:55:34 UTC (rev 67588)
@@ -315,6 +315,14 @@
 #define __restrict
 #endif
 
+#ifndef HB_ALWAYS_INLINE
+#if defined(_MSC_VER)
+#define HB_ALWAYS_INLINE __forceinline
+#else
+#define HB_ALWAYS_INLINE __attribute__((always_inline)) inline
+#endif
+#endif
+
 /*
  * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
  * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -245,7 +245,7 @@
 	  if (hb_color_get_alpha (color) != 255)
 	    fprintf (f, "fill-opacity=\"%.3f\"", (double) hb_color_get_alpha (color) / 255.);
 	  fprintf (f, "d=\"");
-	  hb_font_get_glyph_shape (font, layers[layer].glyph, funcs, &draw_data);
+	  hb_font_draw_glyph (font, layers[layer].glyph, funcs, &draw_data);
 	  fprintf (f, "\"/>\n");
 	}
 
@@ -284,7 +284,7 @@
     draw_data_t draw_data;
     draw_data.ascender = font_extents.ascender;
     draw_data.f = f;
-    hb_font_get_glyph_shape (font, gid, funcs, &draw_data);
+    hb_font_draw_glyph (font, gid, funcs, &draw_data);
     fprintf (f, "\"/></svg>");
     fclose (f);
   }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build	2023-07-09 05:55:34 UTC (rev 67588)
@@ -324,6 +324,19 @@
 hb_graphite2_sources = files('hb-graphite2.cc')
 hb_graphite2_headers = files('hb-graphite2.h')
 
+hb_wasm_sources = files(
+  'hb-wasm-api.cc',
+  'hb-wasm-api.hh',
+  'hb-wasm-api-blob.hh',
+  'hb-wasm-api-buffer.hh',
+  'hb-wasm-api-common.hh',
+  'hb-wasm-api-face.hh',
+  'hb-wasm-api-font.hh',
+  'hb-wasm-api-shape.hh',
+  'hb-wasm-shape.cc',
+)
+hb_wasm_headers = files()
+
 # System-dependent sources and headers
 
 hb_coretext_sources = files('hb-coretext.cc')
@@ -353,11 +366,10 @@
   'hb-subset-cff-common.cc',
   'hb-subset-cff-common.hh',
   'hb-subset-cff1.cc',
-  'hb-subset-cff1.hh',
   'hb-subset-cff2.cc',
-  'hb-subset-cff2.hh',
   'hb-subset-input.cc',
   'hb-subset-input.hh',
+  'hb-subset-instancer-solver.hh',
   'hb-subset-instancer-solver.cc',
   'hb-subset-plan.cc',
   'hb-subset-plan.hh',
@@ -417,7 +429,7 @@
   output: 'harfbuzz.cc',
   input: hb_base_sources + hb_glib_sources + hb_ft_sources +
          hb_graphite2_sources + hb_uniscribe_sources + hb_gdi_sources +
-         hb_directwrite_sources + hb_coretext_sources,
+         hb_directwrite_sources + hb_coretext_sources + hb_wasm_sources,
   command: [find_program('gen-harfbuzzcc.py'),
             '@OUTPUT@', meson.current_source_dir(), '@INPUT@'],
 )
@@ -460,6 +472,13 @@
   harfbuzz_deps += [graphite2_dep, graphite_dep]
 endif
 
+if conf.get('HAVE_WASM', 0) == 1
+  hb_sources += hb_wasm_sources
+  hb_headers += hb_wasm_headers
+  harfbuzz_deps += wasm_dep
+  #harfbuzz_deps += llvm_dep
+endif
+
 if conf.get('HAVE_UNISCRIBE', 0) == 1
   hb_sources += hb_uniscribe_sources
   hb_headers += hb_uniscribe_headers
@@ -497,6 +516,7 @@
   'GRAPHITE',
   'ICU',
   'UNISCRIBE',
+  'WASM',
 ]
 
 hb_enabled_features = configuration_data()
@@ -700,6 +720,8 @@
     'test-unicode-ranges': ['test-unicode-ranges.cc'],
     'test-vector': ['test-vector.cc', 'hb-static.cc'],
     'test-bimap': ['test-bimap.cc', 'hb-static.cc'],
+    'test-instancer-solver': ['test-subset-instancer-solver.cc', 'hb-subset-instancer-solver.cc', 'hb-static.cc'],
+    'test-tuple-varstore': ['test-tuple-varstore.cc', 'hb-subset-instancer-solver.cc', 'hb-static.cc'],
   }
   foreach name, source : compiled_tests
     if cpp.get_argument_syntax() == 'msvc' and source.contains('hb-static.cc')
@@ -846,7 +868,7 @@
 
   if build_gir
     conf.set('HAVE_INTROSPECTION', 1)
-    hb_gen_files_gir = gnome.generate_gir(libharfbuzz_gobject,
+    hb_gen_files_gir = gnome.generate_gir([libharfbuzz_gobject, libharfbuzz],
       sources: [gir_headers, gir_sources, gobject_enums_h],
       dependencies: libharfbuzz_dep,
       namespace: 'HarfBuzz',
@@ -854,7 +876,7 @@
       identifier_prefix: 'hb_',
       symbol_prefix: ['hb', 'hb_gobject'],
       includes: ['GObject-2.0', 'freetype2-2.0'],
-      export_packages: ['harfbuzz-gobject'],
+      export_packages: ['harfbuzz-gobject', 'harfbuzz'],
       header: 'hb-gobject.h',
       install: true,
       extra_args:  ['--cflags-begin',
@@ -910,7 +932,10 @@
   env.set('HBHEADERS', ' '.join(HBHEADERS))
 
   if cpp.get_argument_syntax() != 'msvc' and not meson.is_cross_build() # ensure the local tools are usable
-    dist_check_script += ['check-libstdc++', 'check-static-inits', 'check-symbols']
+    dist_check_script += ['check-static-inits', 'check-symbols']
+    if get_option('wasm').disabled()
+      dist_check_script += ['check-libstdc++']
+    endif
   endif
 
   foreach name : dist_check_script

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-get-alternates.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-get-alternates.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-get-alternates.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -65,7 +65,7 @@
   for (unsigned i = 0; i < count; i++)
   {
     unsigned alt_count = 0;
-    for (unsigned lookup_index = HB_SET_VALUE_INVALID;
+    for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID;
 	 hb_set_next (lookup_indexes, &lookup_index);)
       if ((alt_count = hb_ot_layout_lookup_get_glyph_alternates (face,
 								 lookup_index,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -79,7 +79,7 @@
     s.set (1, 2);
     s.set (3, 4);
 
-    hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> v (s);
+    hb_vector_t<hb_codepoint_pair_t> v (s);
     hb_map_t v0 (v);
     hb_map_t v1 (s);
     hb_map_t v2 (std::move (s));
@@ -112,7 +112,7 @@
 
   /* Test initializing from initializer list and swapping. */
   {
-    using pair_t = hb_pair_t<hb_codepoint_t, hb_codepoint_t>;
+    using pair_t = hb_codepoint_pair_t;
     hb_map_t v1 {pair_t{1,2}, pair_t{4,5}};
     hb_map_t v2 {pair_t{3,4}};
     hb_swap (v1, v2);
@@ -149,7 +149,7 @@
 
   /* Test hashing maps. */
   {
-    using pair = hb_pair_t<hb_codepoint_t, hb_codepoint_t>;
+    using pair = hb_codepoint_pair_t;
 
     hb_hashmap_t<hb_map_t, hb_map_t> m1;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -91,7 +91,7 @@
     s << 12;
 
     /* Sink a range. */
-    s << hb_pair_t<hb_codepoint_t, hb_codepoint_t> {1, 3};
+    s << hb_codepoint_pair_t {1, 3};
 
     hb_set_t v (hb_iter (s));
 

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,395 @@
+/*
+ * Copyright © 2023  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): Qunxin Liu
+ */
+
+#include "hb-subset-instancer-solver.hh"
+
+static inline bool approx (Triple a, Triple b)
+{
+  return fabsf (a.minimum - b.minimum) < 0.000001f &&
+         fabsf (a.middle - b.middle) < 0.000001f &&
+         fabsf (a.maximum - b.maximum) < 0.000001f;
+}
+
+static inline bool approx (float a, float b)
+{ return fabsf (a - b) < 0.000001f; }
+
+/* tests ported from
+ * https://github.com/fonttools/fonttools/blob/main/Tests/varLib/instancer/solver_test.py */
+int
+main (int argc, char **argv)
+{
+  /* Case 1 */
+  {
+    /* pin axis*/
+    Triple tent (0.f, 1.f, 1.f);
+    Triple axis_range (0.f, 0.f, 0.f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 0);
+  }
+
+  {
+    /* pin axis*/
+    Triple tent (0.f, 1.f, 1.f);
+    Triple axis_range (0.5f, 0.5f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 0.5f);
+    assert (out[0].second == Triple ());
+  }
+
+  {
+    /* tent falls outside the new axis range */
+    Triple tent (0.3f, 0.5f, 0.8f);
+    Triple axis_range (0.1f, 0.2f, 0.3f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 0);
+  }
+
+  /* Case 2 */
+  {
+    Triple tent (0.f, 1.f, 1.f);
+    Triple axis_range (-1.f, 0.f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 0.5f);
+    assert (out[0].second == Triple (0.f, 1.f, 1.f));
+  }
+
+  /* Case 2 */
+  {
+    Triple tent (0.f, 1.f, 1.f);
+    Triple axis_range (-1.f, 0.f, 0.75f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 0.75f);
+    assert (out[0].second == Triple (0.f, 1.f, 1.f));
+  }
+
+  /* Without gain: */
+  /* Case 3 */
+  {
+    Triple tent (0.f, 0.2f, 1.f);
+    Triple axis_range (-1.f, 0.f, 0.8f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple (0.f, 0.25f, 1.25f));
+  }
+
+  /* Case 3 boundary */
+  {
+    Triple tent (0.f, 0.4f, 1.f);
+    Triple axis_range (-1.f, 0.f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple (0.f, 0.8f, 32767/(float) (1 << 14)));
+  }
+
+  /* Case 4 */
+  {
+    Triple tent (0.f, 0.25f, 1.f);
+    Triple axis_range (-1.f, 0.f, 0.4f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 2);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple (0.f, 0.625f, 1.f));
+    assert (approx (out[1].first, 0.8f));
+    assert (out[1].second == Triple (0.625f, 1.f, 1.f));
+  }
+
+  /* Case 4 */
+  {
+    Triple tent (0.25f, 0.3f, 1.05f);
+    Triple axis_range (0.f, 0.2f, 0.4f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 2);
+    assert (out[0].first == 1.f);
+    assert (approx (out[0].second, Triple (0.25f, 0.5f, 1.f)));
+    assert (approx (out[1].first, 2.6f/3));
+    assert (approx (out[1].second, Triple (0.5f, 1.f, 1.f)));
+  }
+
+  /* Case 4 boundary */
+  {
+    Triple tent (0.25f, 0.5f, 1.f);
+    Triple axis_range (0.f, 0.25f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple (0.f, 1.f, 1.f));
+  }
+
+  /* With gain */
+  /* Case 3a/1neg */
+  {
+    Triple tent (0.f, 0.5f, 1.f);
+    Triple axis_range (0.f, 0.5f, 1.f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 3);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == -1.f);
+    assert (out[1].second == Triple (0.f, 1.f, 1.f));
+    assert (out[2].first == -1.f);
+    assert (out[2].second == Triple (-1.f, -1.f, 0.f));
+  }
+
+  {
+    Triple tent (0.f, 0.5f, 1.f);
+    Triple axis_range (0.f, 0.5f, 0.75f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 3);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == -0.5f);
+    assert (out[1].second == Triple (0.f, 1.f, 1.f));
+    assert (out[2].first == -1.f);
+    assert (out[2].second == Triple (-1.f, -1.f, 0.f));
+  }
+
+  {
+    Triple tent (0.f, 0.5f, 1.f);
+    Triple axis_range (0.f, 0.25f, 0.8f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 4);
+    assert (out[0].first == 0.5f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == 0.5f);
+    assert (approx (out[1].second, Triple (0.f, 0.454545f, 0.909091f)));
+    assert (approx (out[2].first, -0.1f));
+    assert (approx (out[2].second, Triple (0.909091f, 1.f, 1.f)));
+    assert (out[3].first == -0.5f);
+    assert (out[3].second == Triple (-1.f, -1.f, 0.f));
+  }
+
+  /* Case 3a/1neg */
+  {
+    Triple tent (0.f, 0.5f, 2.f);
+    Triple axis_range (0.2f, 0.5f, 0.8f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 3);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple ());
+    assert (approx (out[1].first, -0.2f));
+    assert (out[1].second == Triple (0.f, 1.f, 1.f));
+    assert (approx (out[2].first, -0.6f));
+    assert (out[2].second == Triple (-1.f, -1.f, 0.f));
+  }
+
+  /* Case 3a/1neg */
+  {
+    Triple tent (0.f, 0.5f, 2.f);
+    Triple axis_range (0.2f, 0.5f, 1.f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 3);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple ());
+    assert (approx (out[1].first, -1.f/3));
+    assert (out[1].second == Triple (0.f, 1.f, 1.f));
+    assert (approx (out[2].first, -0.6f));
+    assert (out[2].second == Triple (-1.f, -1.f, 0.f));
+  }
+
+  /* Case 3 */
+  {
+    Triple tent (0.f, 0.5f, 1.f);
+    Triple axis_range (0.25f, 0.25f, 0.75f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 2);
+    assert (out[0].first == 0.5f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == 0.5f);
+    assert (out[1].second == Triple (0.f, 0.5f, 1.0f));
+  }
+
+  /* Case 1neg */
+  {
+    Triple tent (0.f, 0.5f, 1.f);
+    Triple axis_range (0.f, 0.25f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 3);
+    assert (out[0].first == 0.5f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == 0.5f);
+    assert (out[1].second == Triple (0.f, 1.f, 1.f));
+    assert (out[2].first == -0.5f);
+    assert (out[2].second == Triple (-1.f, -1.f, 0.f));
+  }
+
+  /* Case 2neg */
+  {
+    Triple tent (0.05f, 0.55f, 1.f);
+    Triple axis_range (0.f, 0.25f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 4);
+    assert (approx (out[0].first, 0.4f));
+    assert (out[0].second == Triple ());
+    assert (approx (out[1].first, 0.5f));
+    assert (out[1].second == Triple (0.f, 1.f, 1.f));
+    assert (approx (out[2].first, -0.4f));
+    assert (out[2].second == Triple (-1.f, -0.8f, 0.f));
+    assert (approx (out[3].first, -0.4f));
+    assert (out[3].second == Triple (-1.f, -1.f, -0.8f));
+  }
+
+  /* Case 2neg, other side */
+  {
+    Triple tent (-1.f, -0.55f, -0.05f);
+    Triple axis_range (-0.5f, -0.25f, 0.f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 4);
+    assert (approx (out[0].first, 0.4f));
+    assert (out[0].second == Triple ());
+    assert (approx (out[1].first, 0.5f));
+    assert (out[1].second == Triple (-1.f, -1.f, 0.f));
+    assert (approx (out[2].first, -0.4f));
+    assert (out[2].second == Triple (0.f, 0.8f, 1.f));
+    assert (approx (out[3].first, -0.4f));
+    assert (out[3].second == Triple (0.8f, 1.f, 1.f));
+  }
+
+  /* Misc corner cases */
+  {
+    Triple tent (0.5f, 0.5f, 0.5f);
+    Triple axis_range (0.5f, 0.5f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple ());
+  }
+
+  {
+    Triple tent (0.3f, 0.5f, 0.7f);
+    Triple axis_range (0.1f, 0.5f, 0.9f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 5);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == -1.f);
+    assert (out[1].second == Triple (0.f, 0.5f, 1.f));
+    assert (out[2].first == -1.f);
+    assert (out[2].second == Triple (0.5f, 1.f, 1.f));
+    assert (out[3].first == -1.f);
+    assert (approx (out[3].second, Triple (-1.f, -0.5f, 0.f)));
+    assert (out[4].first == -1.f);
+    assert (approx (out[4].second, Triple (-1.f, -1.f, -0.5f)));
+  }
+
+  {
+    Triple tent (0.5f, 0.5f, 0.5f);
+    Triple axis_range (0.25f, 0.25f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple (1.f, 1.f, 1.f));
+  }
+
+  {
+    Triple tent (0.5f, 0.5f, 0.5f);
+    Triple axis_range (0.25f, 0.35f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple (1.f, 1.f, 1.f));
+  }
+
+  {
+    Triple tent (0.5f, 0.5f, 0.55f);
+    Triple axis_range (0.25f, 0.35f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple (1.f, 1.f, 1.f));
+  }
+
+  {
+    Triple tent (0.5f, 0.5f, 1.f);
+    Triple axis_range (0.5f, 0.5f, 1.f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 2);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == -1.f);
+    assert (out[1].second == Triple (0.f, 1.f, 1.f));
+  }
+
+  {
+    Triple tent (0.25f, 0.5f, 1.f);
+    Triple axis_range (0.5f, 0.5f, 1.f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 2);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == -1.f);
+    assert (out[1].second == Triple (0.f, 1.f, 1.f));
+  }
+
+  {
+    Triple tent (0.f, 0.2f, 1.f);
+    Triple axis_range (0.f, 0.f, 0.5f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 1);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple (0.f, 0.4f, 32767/(float) (1 << 14)));
+  }
+
+
+  {
+    Triple tent (0.f, 0.5f, 1.f);
+    Triple axis_range (-1.f, 0.25f, 1.f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 5);
+    assert (out[0].first == 0.5f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == 0.5f);
+    assert (out[1].second == Triple (0.f, 1.f/3, 2.f/3));
+    assert (out[2].first == -0.5f);
+    assert (out[2].second == Triple (2.f/3, 1.f, 1.f));
+    assert (out[3].first == -0.5f);
+    assert (out[3].second == Triple (-1.f, -0.2f, 0.f));
+    assert (out[4].first == -0.5f);
+    assert (out[4].second == Triple (-1.f, -1.f, -0.2f));
+  }
+
+  {
+    Triple tent (0.5f, 0.5f, 0.5f);
+    Triple axis_range (0.f, 0.5f, 1.f);
+    result_t out = rebase_tent (tent, axis_range);
+    assert (out.length == 5);
+    assert (out[0].first == 1.f);
+    assert (out[0].second == Triple ());
+    assert (out[1].first == -1.f);
+    assert (out[1].second == Triple (0.f, 2/(float) (1 << 14), 1.f));
+    assert (out[2].first == -1.f);
+    assert (out[2].second == Triple (2/(float) (1 << 14), 1.f, 1.f));
+    assert (out[3].first == -1.f);
+    assert (out[3].second == Triple (-1.f, -2/(float) (1 << 14), 0.f));
+    assert (out[4].first == -1.f);
+    assert (out[4].second == Triple (-1.f, -1.f, -2/(float) (1 << 14)));
+  }
+}
+

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ *
+ */
+#include "hb-ot-var-cvar-table.hh"
+
+// cvar table data from Multi-ABC.ttf
+const char cvar_data[] = "\x0\x1\x0\x0\x0\x2\x0\x14\x0\x51\xa0\x0\xc0\x0\x0\x54\xa0\x0\x40\x0\x2a\x29\x17\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\xd\xff\x0\xfd\x1\x0\xff\x0\xfd\x1\x0\xdb\xdb\xe6\xe6\x82\x0\xfd\x84\x6\xfd\x0\x2\xe3\xe3\xec\xec\x82\x4\x1\xe3\xe3\xec\xec\x82\x0\x1\x2a\x29\x17\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\xd\x1\x0\x5\xfd\x0\x1\x0\x5\xfd\x0\x61\x61\x44\x44\x82\x0\x5\x81\x9\x1\xff\x1\x7\xff\xfb\x49\x49\x35\x35\x82\x4\xff\x49\x49\x35\x35\x82\x0\xff";
+
+static void
+test_decompile_cvar ()
+{
+  const OT::cvar* cvar_table = reinterpret_cast<const OT::cvar*> (cvar_data);
+  unsigned point_count = 65;
+  unsigned axis_count = 1;
+
+  hb_tag_t axis_tag = HB_TAG ('w', 'g', 'h', 't');
+  hb_map_t axis_idx_tag_map;
+  axis_idx_tag_map.set (0, axis_tag);
+
+  OT::TupleVariationData::tuple_variations_t tuple_variations;
+  bool result = cvar_table->decompile_tuple_variations (axis_count, point_count, false, &axis_idx_tag_map, tuple_variations);
+  assert (result);
+  assert (tuple_variations.tuple_vars.length == 2);
+  for (unsigned i = 0; i < 2; i++)
+  {
+    assert (tuple_variations.tuple_vars[i].axis_tuples.get_population () == 1);
+    assert (!tuple_variations.tuple_vars[i].deltas_y);
+    assert (tuple_variations.tuple_vars[i].indices.length == 65);
+    assert (tuple_variations.tuple_vars[i].indices.length == tuple_variations.tuple_vars[i].deltas_x.length);
+  }
+  assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.f, -1.f, 0.f));
+  assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.f, 1.f, 1.f));
+  
+  hb_vector_t<float> deltas_1 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, -3.f, 1.f, 0.f, -1.f, 0.f, -3.f, 1.f, 0.f, -37.f, -37.f, -26.f, -26.f, 0.f, 0.f, 0.f, -3.f, 0.f, 0.f, 0.f, 0.f, 0.f, -3.f, 0.f, 2.f, -29.f, -29.f, -20.f, -20.f, 0.f, 0.f, 0.f, 1.f, -29.f, -29.f, -20.f, -20.f, 0.f, 0.f, 0.f, 1.f};
+  for (unsigned i = 0; i < 65; i++)
+  {
+    if (i < 23)
+      assert (tuple_variations.tuple_vars[0].indices[i] == 0);
+    else
+    {
+      assert (tuple_variations.tuple_vars[0].indices[i] == 1);
+      assert (tuple_variations.tuple_vars[0].deltas_x[i] == deltas_1[i]);
+    }
+  }
+
+  hb_vector_t<float> deltas_2 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 5.f, -3.f, 0.f, 1.f, 0.f, 5.f, -3.f, 0.f, 97.f, 97.f, 68.f, 68.f, 0.f, 0.f, 0.f, 5.f, 0.f, 0.f, 1.f, -1.f, 1.f, 7.f, -1.f, -5.f, 73.f, 73.f, 53.f, 53.f, 0.f, 0.f, 0.f, -1.f, 73.f, 73.f, 53.f, 53.f, 0.f, 0.f, 0.f, -1.f};
+  for (unsigned i = 0 ; i < 65; i++)
+  {
+    if (i < 23)
+      assert (tuple_variations.tuple_vars[1].indices[i] == 0);
+    else
+    {
+      assert (tuple_variations.tuple_vars[1].indices[i] == 1);
+      assert (tuple_variations.tuple_vars[1].deltas_x[i] == deltas_2[i]);
+    }
+  }
+
+  /* partial instancing wght=300:800 */
+  hb_hashmap_t<hb_tag_t, Triple> normalized_axes_location;
+  normalized_axes_location.set (axis_tag, Triple (-0.512817f, 0.f, 0.700012f));
+
+  tuple_variations.change_tuple_variations_axis_limits (&normalized_axes_location);
+  tuple_variations.merge_tuple_variations ();
+
+  assert (tuple_variations.tuple_vars[0].indices.length == 65);
+  assert (tuple_variations.tuple_vars[1].indices.length == 65);
+  assert (!tuple_variations.tuple_vars[0].deltas_y);
+  assert (!tuple_variations.tuple_vars[1].deltas_y);
+  assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.f, -1.f, 0.f));
+  assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.f, 1.f, 1.f));
+
+  hb_vector_t<float> rounded_deltas_1 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -1, 0.f, -2, 1, 0.f, -1, 0.f, -2, 1, 0.f, -19, -19, -13, -13, 0.f, 0.f, 0.f, -2, 0.f, 0.f, 0.f, 0.f, 0.f, -2, 0.f, 1, -15, -15, -10.f, -10.f, 0.f, 0.f, 0.f, 1, -15, -15, -10.f, -10.f, 0.f, 0.f, 0.f, 1};
+
+  hb_vector_t<float> rounded_deltas_2 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1, 0.f, 4, -2, 0.f, 1, 0.f, 4, -2, 0.f, 68, 68, 48, 48, 0.f, 0.f, 0.f, 4, 0.f, 0.f, 1, -1, 1, 5, -1, -4, 51, 51, 37, 37, 0.f, 0.f, 0.f, -1, 51, 51, 37, 37, 0.f, 0.f, 0.f, -1};
+
+  for (unsigned i = 0; i < 65; i++)
+  {
+    if (i < 23)
+    {
+      assert (tuple_variations.tuple_vars[0].indices[i] == 0);
+      assert (tuple_variations.tuple_vars[1].indices[i] == 0);
+    }
+    else
+    {
+      assert (tuple_variations.tuple_vars[0].indices[i] == 1);
+      assert (tuple_variations.tuple_vars[1].indices[i] == 1);
+      assert (roundf (tuple_variations.tuple_vars[0].deltas_x[i]) == rounded_deltas_1[i]);
+      assert (roundf (tuple_variations.tuple_vars[1].deltas_x[i]) == rounded_deltas_2[i]);
+    }
+  }
+
+  hb_map_t axes_index_map;
+  axes_index_map.set (0, 0);
+  bool res = tuple_variations.compile_bytes (axes_index_map, axis_idx_tag_map);
+  assert (res);
+  assert (tuple_variations.tuple_vars[0].compiled_tuple_header.length == 6);
+  const char tuple_var_header_1[] = "\x0\x51\xa0\x0\xc0\x0";
+  for (unsigned i = 0; i < 6; i++)
+    assert(tuple_variations.tuple_vars[0].compiled_tuple_header.arrayZ[i] == tuple_var_header_1[i]);
+
+  assert (tuple_variations.tuple_vars[1].compiled_tuple_header.length == 6);
+  const char tuple_var_header_2[] = "\x0\x54\xa0\x0\x40\x0";
+  for (unsigned i = 0; i < 6; i++)
+    assert(tuple_variations.tuple_vars[1].compiled_tuple_header.arrayZ[i] == tuple_var_header_2[i]);
+
+  assert (tuple_variations.tuple_vars[0].compiled_deltas.length == 37);
+  assert (tuple_variations.tuple_vars[1].compiled_deltas.length == 40);
+  const char compiled_deltas_1[] = "\x0d\xff\x00\xfe\x01\x00\xff\x00\xfe\x01\x00\xed\xed\xf3\xf3\x82\x00\xfe\x84\x06\xfe\x00\x01\xf1\xf1\xf6\xf6\x82\x04\x01\xf1\xf1\xf6\xf6\x82\x00\x01";
+  for (unsigned i = 0; i < 37; i++)
+    assert (tuple_variations.tuple_vars[0].compiled_deltas.arrayZ[i] == compiled_deltas_1[i]);
+
+  const char compiled_deltas_2[] = "\x0d\x01\x00\x04\xfe\x00\x01\x00\x04\xfe\x00\x44\x44\x30\x30\x82\x00\x04\x81\x09\x01\xff\x01\x05\xff\xfc\x33\x33\x25\x25\x82\x04\xff\x33\x33\x25\x25\x82\x00\xff";
+  for (unsigned i = 0; i < 40; i++)
+    assert (tuple_variations.tuple_vars[1].compiled_deltas.arrayZ[i] == compiled_deltas_2[i]);
+}
+
+int
+main (int argc, char **argv)
+{
+  test_decompile_cvar ();
+}

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc	2023-07-09 05:55:34 UTC (rev 67588)
@@ -181,6 +181,11 @@
     hb_map_t m;
     v.push (m);
   }
+  {
+    hb_vector_t<hb_map_t> v;
+    hb_map_t m;
+    v.push (m);
+  }
 
   return 0;
 }

Modified: trunk/Build/source/libs/harfbuzz/version.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/version.ac	2023-07-08 23:47:51 UTC (rev 67587)
+++ trunk/Build/source/libs/harfbuzz/version.ac	2023-07-09 05:55:34 UTC (rev 67588)
@@ -8,4 +8,4 @@
 dnl --------------------------------------------------------
 dnl
 dnl  m4-include this file to define the current harfbuzz version
-m4_define([harfbuzz_version], [7.3.0])
+m4_define([harfbuzz_version], [8.0.0])



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