texlive[64657] Build/source/libs: harfbuzz 5.3.0

commits+kakuto at tug.org commits+kakuto at tug.org
Sat Oct 8 23:59:08 CEST 2022


Revision: 64657
          http://tug.org/svn/texlive?view=revision&revision=64657
Author:   kakuto
Date:     2022-10-08 23:59:08 +0200 (Sat, 08 Oct 2022)
Log Message:
-----------
harfbuzz 5.3.0

Modified Paths:
--------------
    trunk/Build/source/libs/README
    trunk/Build/source/libs/harfbuzz/ChangeLog
    trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
    trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
    trunk/Build/source/libs/harfbuzz/configure
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
    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/src/OT/Layout/GPOS/GPOS.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/GSUB/GSUB.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/glyf.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/markbasepos-graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cplusplus.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
    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-shaper-use-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-vowel-constraints.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc
    trunk/Build/source/libs/harfbuzz/version.ac

Modified: trunk/Build/source/libs/README
===================================================================
--- trunk/Build/source/libs/README	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/README	2022-10-08 21:59:08 UTC (rev 64657)
@@ -25,8 +25,8 @@
   http://sourceforge.net/projects/silgraphite/files/graphite2/
   (requires C++11)
 
-harfbuzz 5.2.0 - checked 19sep22
-  https://github.com/harfbuzz/harfbuzz/releases/tag/5.2.0
+harfbuzz 5.3.0 - checked 09oct22
+  https://github.com/harfbuzz/harfbuzz/releases/tag/5.3.0
 
 icu 70.1 - checked 16jan22
   https://github.com/unicode-org/icu/releases/

Modified: trunk/Build/source/libs/harfbuzz/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/ChangeLog	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/ChangeLog	2022-10-08 21:59:08 UTC (rev 64657)
@@ -1,3 +1,8 @@
+2022-10-09  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
+
+	Import harfbuzz-5.3.0.
+	* version.ac: Adjusted.
+
 2022-09-19  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
 
 	Import harfbuzz-5.2.0.

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2022-10-08 21:59:08 UTC (rev 64657)
@@ -1,3 +1,8 @@
+2022-10-09  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
+
+	Imported harfbuzz-5.3.0 source tree from:
+	https://github.com/harfbuzz/harfbuzz/releases/download/5.3.0/
+
 2022-09-19  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
 
 	Imported harfbuzz-5.2.0 source tree from:

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2022-10-08 21:59:08 UTC (rev 64657)
@@ -1,5 +1,5 @@
-Changes applied to the harfbuzz-5.2.0/ tree as obtained from:
-	https://github.com/harfbuzz/harfbuzz/releases/download/5.2.0/
+Changes applied to the harfbuzz-5.3.0/ tree as obtained from:
+	https://github.com/harfbuzz/harfbuzz/releases/download/5.3.0/
 
 Removed:
 	COPYING

Modified: trunk/Build/source/libs/harfbuzz/configure
===================================================================
--- trunk/Build/source/libs/harfbuzz/configure	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/configure	2022-10-08 21:59:08 UTC (rev 64657)
@@ -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) 5.2.0.
+# Generated by GNU Autoconf 2.71 for harfbuzz (TeX Live) 5.3.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='5.2.0'
-PACKAGE_STRING='harfbuzz (TeX Live) 5.2.0'
+PACKAGE_VERSION='5.3.0'
+PACKAGE_STRING='harfbuzz (TeX Live) 5.3.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) 5.2.0 to adapt to many kinds of systems.
+\`configure' configures harfbuzz (TeX Live) 5.3.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) 5.2.0:";;
+     short | recursive ) echo "Configuration of harfbuzz (TeX Live) 5.3.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 5.2.0
+harfbuzz (TeX Live) configure 5.3.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 5.2.0, which was
+It was created by harfbuzz (TeX Live) $as_me 5.3.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='5.2.0'
+ VERSION='5.3.0'
 
 
 # Some tools Automake needs.
@@ -5034,9 +5034,9 @@
 
 
 HB_VERSION_MAJOR=5
-HB_VERSION_MINOR=2
+HB_VERSION_MINOR=3
 HB_VERSION_MICRO=0
-HB_VERSION=5.2.0
+HB_VERSION=5.3.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 5.2.0, which was
+This file was extended by harfbuzz (TeX Live) $as_me 5.3.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 5.2.0
+harfbuzz (TeX Live) config.status 5.3.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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog	2022-10-08 21:59:08 UTC (rev 64657)
@@ -1,3 +1,347 @@
+commit 3ce4b8f5c94fe351165243b209ccb9759917f5cb
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sat Oct 8 19:10:07 2022 +0200
+
+    5.3.0
+
+ NEWS                   | 17 +++++++++++++++++
+ configure.ac           |  2 +-
+ docs/harfbuzz-docs.xml |  1 +
+ meson.build            |  2 +-
+ src/hb-face.cc         |  2 +-
+ src/hb-ot-layout.cc    |  2 +-
+ src/hb-version.h       |  4 ++--
+ 7 files changed, 24 insertions(+), 6 deletions(-)
+
+commit 90eee512a07819c50d32b44e6e660fecd05828b0
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sat Oct 8 19:02:28 2022 +0200
+
+    [doc] Add symbols to harfbuzz-sections.txt
+
+ docs/harfbuzz-sections.txt | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 9a28df411e75a39c2e4973a589ad0db99f2c5306
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Sat Oct 8 18:22:13 2022 +0200
+
+    [ci] Mark automatic releases as draft
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/2780
+
+ .ci/publish_release_artifact.sh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 99f4668e1969a0a688044433803b3e7797391688
+Author: Garret Rieger <grieger at google.com>
+Date:   Thu Sep 29 19:39:59 2022 +0000
+
+    [repacker] use mutable copies of Coverage/ClassDef in MarkBasePos shrink operation.
+    
+    Also make mutable copies (when needed) of the top level subtables during a split operation.
+
+ src/graph/graph.hh             | 25 ++++++++++++++--
+ src/graph/gsubgpos-graph.hh    |  9 ++++--
+ src/graph/markbasepos-graph.hh | 23 ++++++++-------
+ src/graph/pairpos-graph.hh     | 66 ++++++++++++++++++++----------------------
+ src/hb-repacker.hh             |  2 +-
+ 5 files changed, 73 insertions(+), 52 deletions(-)
+
+commit 8f1bf23cc9a8912c452f7571e2a3f35a192a8120
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Sep 27 22:50:54 2022 +0000
+
+    [subset] optimize glyf subsetting w/ retain gids.
+    
+    When retain gids is enabled the subset plan may require the output of many empty glyphs. This change optimizes the glyf subsetting code when the number of retained glyphs << number of output glyphs. Unnessecary lookups to the glyph map are reduced by iterating through the glyph map instead of the output glyph set.
+
+ src/OT/glyf/Glyph.hh       | 14 +++++++++----
+ src/OT/glyf/SubsetGlyph.hh |  1 -
+ src/OT/glyf/glyf.hh        | 52 +++++++++++++++++++++-------------------------
+ 3 files changed, 34 insertions(+), 33 deletions(-)
+
+commit e94fe2adf379b1a802e1ecdd393858474a02970b
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Tue Sep 20 13:14:26 2022 -0700
+
+    [instance] minor optimizations to glyf instancing
+
+ src/OT/glyf/Glyph.hh       | 13 +++++++++----
+ src/OT/glyf/SimpleGlyph.hh | 26 ++++++++++++--------------
+ src/OT/glyf/glyf.hh        | 22 +++++++++++++++++-----
+ 3 files changed, 38 insertions(+), 23 deletions(-)
+
+commit d5fc4a73c08c218b16513464a2e880f65531313b
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Wed Sep 14 14:43:20 2022 -0700
+
+    [instance] add tests for featureVariations
+    
+    Also updated the script that is used to generate tests.With fonttools,
+    we now do instancing first and then subsetting.
+    
+    With different order of subsetting and instancing operations on the same
+    VF file, fonttools seems to generate 2 different font files with different
+    glyph set.
+    1. do subsetting and then instancing: this seems result in a larger glyph
+       set in the font file. Lookups are collected from both retained features
+       and all possible alternate featurevariations, this leads to a larger
+       glyph set after glyph closurei. And instancer doesn't redo glyph
+       closure, it does lookups pruning only.
+    
+    2. do instancing and then subsetting: lookups are collected from
+       features that are replaced already and possible alternate feature
+       variations
+
+ ...fault.retain-all-codepoint.wght=150,wdth=80.ttf | Bin 114200 -> 114200 bytes
+ ...fault.retain-all-codepoint.wght=300,wdth=90.ttf | Bin 114300 -> 114300 bytes
+ ...iable.default.retain-all-codepoint.wght=400.ttf | Bin 0 -> 1660624 bytes
+ ...otdef-outline.retain-all-codepoint.wght=400.ttf | Bin 0 -> 1660668 bytes
+ test/subset/data/fonts/Roboto-Variable.ttf         | Bin 0 -> 477420 bytes
+ .../data/tests/instance_feature_variations.tests   |  12 +++++++++++
+ test/subset/generate-expected-outputs.py           |  23 +++++++++++----------
+ test/subset/meson.build                            |   1 +
+ 8 files changed, 25 insertions(+), 11 deletions(-)
+
+commit b90ce34a25538b1377f69be2bae8b2cf8230ac06
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Wed Sep 14 11:26:32 2022 -0700
+
+    [instance] fix for non-empty .notdef glyph metrics update
+    
+    we need pass in source glyph's outline data to calculate boundaries, and
+    then drop the outline data if notdef-outline is specified.
+    
+    Also disable shifting points for instancing in get_points () API
+
+ src/OT/glyf/Glyph.hh | 31 ++++++++++++++++++++-----------
+ src/OT/glyf/glyf.hh  |  5 +++--
+ 2 files changed, 23 insertions(+), 13 deletions(-)
+
+commit b706c6f77eaeb4fc17e03c0c8c6cee2fe5dc85fc
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Sep 12 13:58:55 2022 -0700
+
+    [instance] update FeatureList with variations
+
+ src/hb-ot-layout-common.hh | 234 ++++++++++++++++++++++++++++-----------------
+ 1 file changed, 144 insertions(+), 90 deletions(-)
+
+commit 8f3a7017c38a713759a324f755f4042b3e533ac2
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Fri Sep 9 15:00:37 2022 -0700
+
+    [instance] support FeatureVariations table
+
+ src/OT/Layout/GPOS/GPOS.hh |  2 +-
+ src/OT/Layout/GSUB/GSUB.hh |  2 +-
+ src/hb-ot-layout-common.hh | 72 +++++++++++++++++++++++++++++++++++-----------
+ 3 files changed, 58 insertions(+), 18 deletions(-)
+
+commit f4813e3b7f3bd15ab0ba94bbf8176b6ec2a9ecea
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Fri Sep 9 10:34:09 2022 -0700
+
+    [instance] update collect_lookups/prune_features()/closure_features() with variations
+    
+    Some features will be substituted with variations, so we do not collect
+    lookups from the original feature tables.
+
+ src/hb-ot-layout-common.hh   | 23 ++++++++++++---
+ src/hb-ot-layout-gsubgpos.hh | 17 +++++++----
+ src/hb-ot-layout.cc          |  2 +-
+ src/hb-subset-plan.cc        | 69 +++++++++++++++++++++++++++++++++-----------
+ src/hb-subset-plan.hh        |  4 +--
+ 5 files changed, 86 insertions(+), 29 deletions(-)
+
+commit 64e2f2fc581c7a301919265b9bf6a6519e9c8586
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Fri Sep 9 09:36:19 2022 -0700
+
+    [instance] store active featurevariation record/condition idxes in the plan
+
+ src/hb-ot-layout-common.hh   | 140 +++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout-gsubgpos.hh |   5 ++
+ src/hb-subset-plan.cc        |  19 +++++-
+ src/hb-subset-plan.hh        |  17 ++++++
+ 4 files changed, 178 insertions(+), 3 deletions(-)
+
+commit 0a6c16a313443eb4130aca4e39e2a9a792f8ba03
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Aug 8 13:47:39 2022 -0700
+
+    [instance] instantiate fvar table
+    
+    Added an old->new axes_indices mapping in the subset plan
+
+ src/hb-ot-var-fvar-table.hh | 80 +++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-subset-input.cc      |  1 -
+ src/hb-subset-plan.cc       | 14 +++++---
+ src/hb-subset-plan.hh       |  6 ++++
+ src/hb-subset.cc            |  4 +++
+ 5 files changed, 100 insertions(+), 5 deletions(-)
+
+commit 486fc2271a804f8143f44476d55237f8a7755955
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Sep 28 15:11:23 2022 -0600
+
+    [cplusplus] Add missing const
+
+ src/hb-cplusplus.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit c335bf469f5f1103d5ddf76716f356d026cc30c0
+Author: Qunxin Liu <qxliu at google.com>
+Date:   Mon Sep 26 13:01:20 2022 -0700
+
+    support dereferencing shared_ptrs and unique_ptrs
+
+ src/hb-meta.hh  | 12 ++++++++++++
+ src/test-map.cc | 17 +++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+commit d5829b3ce2a3a989f7f69e5184b7802e71402cf8
+Author: Garret Rieger <grieger at google.com>
+Date:   Fri Sep 23 20:06:57 2022 +0000
+
+    [repacker] update the repacker doc to reflect the current state.
+
+ docs/repacker.md | 97 ++++++++++++++++++++++++++++++++++++--------------------
+ 1 file changed, 63 insertions(+), 34 deletions(-)
+
+commit 8cd7d1c3fe4e632a205b538b5ba46c2abe861a56
+Author: Garret Rieger <grieger at google.com>
+Date:   Tue Sep 20 22:04:39 2022 +0000
+
+    [subset] Allow table ordering on the face builder to be overriden.
+
+ docs/harfbuzz-sections.txt |  1 +
+ src/hb-face.cc             | 76 +++++++++++++++++++++++++++++++++++++---------
+ src/hb-face.h              |  4 +++
+ 3 files changed, 67 insertions(+), 14 deletions(-)
+
+commit b70032eddadb5488514d60c54f6254834f3d750d
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Sep 22 15:59:16 2022 -0600
+
+    [layout] Fix typo in docs
+
+ src/hb-ot-layout.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d2966d39197090a29c35b635831496e6e5a64cf3
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Thu Sep 22 23:30:50 2022 +0200
+
+    [ot-font] Try CBDT extents before outline tables
+    
+    Like we do for sbix table.
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/3827
+
+ src/hb-ot-font.cc | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 1fdf04642773251bb7899df1e2d6b50ec9a6acff
+Merge: 3ca5fbda7 752060a49
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Sep 22 12:03:17 2022 -0600
+
+    Merge pull request #3799 from harfbuzz/optical-bounds
+    
+    Optical bounds
+
+commit 3ca5fbda76098cf74a9ba0c55feea611e48b0b5c
+Author: David Corbett <corbett.dav at northeastern.edu>
+Date:   Wed Sep 21 18:13:17 2022 -0400
+
+    [USE] Update the data files
+    
+    This uses the data files from
+    <https://github.com/microsoft/font-tools/tree/3254c94606d1d6737370deedae0ee3e08d1e100d/USE>
+    and closes #3817.
+
+ src/gen-use-table.py                              |  23 +--
+ src/hb-ot-shaper-use-table.hh                     | 120 ++++++-------
+ src/hb-ot-shaper-vowel-constraints.cc             |  34 ++++
+ src/ms-use/IndicPositionalCategory-Additional.txt |  15 +-
+ src/ms-use/IndicShapingInvalidCluster.txt         | 198 +++++++++++-----------
+ src/ms-use/IndicSyllabicCategory-Additional.txt   |  91 +++++++---
+ 6 files changed, 284 insertions(+), 197 deletions(-)
+
+commit b78d4b1e58a6c358b4c5034549deba7dea59934c
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Sep 21 13:27:12 2022 -0600
+
+    [color] Fix documentation re UPEM vs PPEM
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/3826
+
+ src/hb-ot-color.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 56c467093598ec559a7148b61e112e9de52b7076
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Tue Sep 20 17:39:54 2022 -0600
+
+    [subset] Fix compiler warning
+    
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/3823
+
+ src/graph/graph.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit c02a1a4adc3d3c02b3573a13d47e8381e3534c22
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Sat Sep 10 10:44:16 2022 -0600
+
+    [ot-font] Remove unused include
+
+ src/hb-ot-font.cc | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit d7cc82ad48981b5d321e848a26618443e28f1b2b
+Author: David Corbett <corbett.dav at northeastern.edu>
+Date:   Tue Sep 20 11:22:54 2022 -0400
+
+    Update the language system tag registry URL
+
+ src/update-unicode-tables.make | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 21b0e594141a386a616f0497c171339f4f47552f
+Author: Jonathan Kew <jfkthame at gmail.com>
+Date:   Tue Sep 20 12:03:08 2022 +0100
+
+    [aat] Add test for rlig-to-aat feature mapping in Geeza Pro.
+
+ test/shape/data/in-house/tests/macos.tests | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit f54d2b3e2c7a51586011f15e439f203a5295fc4e
+Author: Jonathan Kew <jfkthame at gmail.com>
+Date:   Tue Sep 20 11:42:00 2022 +0100
+
+    [aat] Map 'rlig' to AAT required-ligatures setting.
+    
+    Fixes #3819.
+
+ src/hb-aat-layout.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit d827a5ee4031d7db1a0cd3265764140a1210fb12
+Author: Khaled Hosny <khaled at aliftype.com>
+Date:   Mon Sep 19 10:40:49 2022 +0200
+
+    [subset] Skip glyph closure for any dropped table
+    
+    If COLR or MATH tables are being dropped, there is no point in closing
+    glyphs over them, just like it is done for GSUB.
+
+ src/hb-subset-plan.cc | 29 +++++++++++++++--------------
+ 1 file changed, 15 insertions(+), 14 deletions(-)
+
 commit 4a1d891c6317d2c83e5f3c2607ec5f5ccedffcde
 Author: Khaled Hosny <khaled at aliftype.com>
 Date:   Sat Sep 17 03:15:51 2022 +0200
@@ -91,6 +435,71 @@
  util/helper-cairo.hh | 6 ++++++
  1 file changed, 6 insertions(+)
 
+commit 752060a49c533c84249707d5a2f026a5b5a4ea33
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Sep 1 13:47:12 2022 -0600
+
+    [layout] Document hb_ot_layout_lookup_get_optical_bound()
+
+ src/hb-ot-layout.cc | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+commit 71c6cba097852831bfb296702e8727e88d14d04a
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Sep 1 13:43:19 2022 -0600
+
+    [layout] Rename API:
+    
+    -hb_ot_layout_get_optical_bound()
+    +hb_ot_layout_lookup_get_optical_bound()
+
+ src/hb-config.hh    |  2 +-
+ src/hb-ot-layout.cc | 10 +++++-----
+ src/hb-ot-layout.h  | 13 +++++++++----
+ 3 files changed, 15 insertions(+), 10 deletions(-)
+
+commit 3892128a1fe1d04365cb91b71babd01b331c1893
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Sep 1 13:40:53 2022 -0600
+
+    [layout] Add HB_NO_LAYOUT_RARELY_USED
+
+ src/hb-config.hh    | 1 +
+ src/hb-ot-layout.cc | 2 ++
+ 2 files changed, 3 insertions(+)
+
+commit 8e88653f05daa3f78462ba4949b6713115b26aa9
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Thu Sep 1 13:39:26 2022 -0600
+
+    [layout] Move code around
+
+ src/hb-ot-layout.cc | 104 ++++++++++++++++++++++++++--------------------------
+ 1 file changed, 53 insertions(+), 51 deletions(-)
+
+commit 4bf9621113441a509565697c146492eee872c6fa
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Aug 31 09:18:18 2022 -0600
+
+    [optical-bounds] Optimize
+
+ src/OT/Layout/GPOS/SinglePosFormat1.hh | 15 +++++++++++----
+ src/OT/Layout/GPOS/SinglePosFormat2.hh | 15 +++++++++++----
+ src/hb-ot-layout.cc                    |  6 +-----
+ 3 files changed, 23 insertions(+), 13 deletions(-)
+
+commit 5d6f1a88e48b57cd28f529643c2c0ff7809e3eea
+Author: Behdad Esfahbod <behdad at behdad.org>
+Date:   Wed Aug 31 08:31:24 2022 -0600
+
+    [layout] Add hb_ot_layout_get_optical_bound()
+
+ src/OT/Layout/GPOS/SinglePosFormat1.hh | 11 +++++++
+ src/OT/Layout/GPOS/SinglePosFormat2.hh | 17 +++++++++-
+ src/hb-ot-layout.cc                    | 57 ++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout.h                     |  6 ++++
+ 4 files changed, 90 insertions(+), 1 deletion(-)
+
 commit 238e7dd2b646b061ffb5c748e280c1e805d6fd00
 Author: Behdad Esfahbod <behdad at behdad.org>
 Date:   Thu Sep 1 13:24:01 2022 -0600

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2022-10-08 21:59:08 UTC (rev 64657)
@@ -1,3 +1,20 @@
+Overview of changes leading to 5.3.0
+Saturday, October 8, 2022
+"Women, Life, Freedom" #MahsaAmini
+====================================
+- Don’t add glyphs from dropped MATH or COLR tables to the subset glyphs.
+  (Khaled Hosny)
+- Map “rlig” to appropriate AAT feature selectors. (Jonathan Kew)
+- Update USE data files to latest version. (David Corbett)
+- Check “CBDT” extents first before outline tables, to help with fonts that
+  also include an empty “glyf” table. (Khaled Hosny)
+- More work towards variable font instancing in the subsetter. (Qunxin Liu)
+- Subsetter repacker improvements. (Garret Rieger)
+- New API:
++hb_ot_layout_lookup_get_optical_bound()
++hb_face_builder_sort_tables()
+
+
 Overview of changes leading to 5.2.0
 Saturday, September 17, 2022
 ====================================

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac	2022-10-08 21:59:08 UTC (rev 64657)
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [5.2.0],
+        [5.3.0],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build	2022-10-08 21:59:08 UTC (rev 64657)
@@ -1,6 +1,6 @@
 project('harfbuzz', 'c', 'cpp',
   meson_version: '>= 0.55.0',
-  version: '5.2.0',
+  version: '5.3.0',
   default_options: [
     'cpp_rtti=false',       # Just to support msvc, we are passing -fno-exceptions also anyway
     'cpp_std=c++11',

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/GPOS.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/GPOS.hh	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/GPOS.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -39,7 +39,7 @@
 
   bool subset (hb_subset_context_t *c) const
   {
-    hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
+    hb_subset_layout_context_t l (c, tableTag);
     return GSUBGPOS::subset<PosLookup> (&l);
   }
 

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -80,6 +80,24 @@
     return_trace (true);
   }
 
+  bool
+  position_single (hb_font_t           *font,
+		   hb_direction_t       direction,
+		   hb_codepoint_t       gid,
+		   hb_glyph_position_t &pos) const
+  {
+    unsigned int index = (this+coverage).get_coverage  (gid);
+    if (likely (index == NOT_COVERED)) return false;
+
+    /* This is ugly... */
+    hb_buffer_t buffer;
+    buffer.props.direction = direction;
+    OT::hb_ot_apply_context_t c (1, font, &buffer);
+
+    valueFormat.apply_value (&c, this, values, pos);
+    return true;
+  }
+
   template<typename Iterator,
       typename SrcLookup,
       hb_requires (hb_is_iterator (Iterator))>

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -68,7 +68,7 @@
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    if (likely (index >= valueCount)) return_trace (false);
+    if (unlikely (index >= valueCount)) return_trace (false);
 
     if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     {
@@ -92,6 +92,28 @@
     return_trace (true);
   }
 
+  bool
+  position_single (hb_font_t           *font,
+		   hb_direction_t       direction,
+		   hb_codepoint_t       gid,
+		   hb_glyph_position_t &pos) const
+  {
+    unsigned int index = (this+coverage).get_coverage  (gid);
+    if (likely (index == NOT_COVERED)) return false;
+    if (unlikely (index >= valueCount)) return false;
+
+    /* This is ugly... */
+    hb_buffer_t buffer;
+    buffer.props.direction = direction;
+    OT::hb_ot_apply_context_t c (1, font, &buffer);
+
+    valueFormat.apply_value (&c, this,
+                             &values[index * valueFormat.get_len ()],
+                             pos);
+    return true;
+  }
+
+
   template<typename Iterator,
       typename SrcLookup,
       hb_requires (hb_is_iterator (Iterator))>

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/GSUB.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/GSUB.hh	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/GSUB.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -27,7 +27,7 @@
 
   bool subset (hb_subset_context_t *c) const
   {
-    hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
+    hb_subset_layout_context_t l (c, tableTag);
     return GSUBGPOS::subset<SubstLookup> (&l);
   }
 

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -102,18 +102,20 @@
                              hb_bytes_t &dest_bytes /* OUT */) const
   {
     GlyphHeader *glyph_header = nullptr;
-    if (all_points.length > 4)
+    if (type != EMPTY && all_points.length > 4)
     {
       glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
       if (unlikely (!glyph_header)) return false;
     }
 
-    int xMin, xMax;
-    xMin = xMax = roundf (all_points[0].x);
+    int xMin = 0, xMax = 0;
+    int yMin = 0, yMax = 0;
+    if (all_points.length > 4)
+    {
+      xMin = xMax = roundf (all_points[0].x);
+      yMin = yMax = roundf (all_points[0].y);
+    }
 
-    int yMin, yMax;
-    yMin = yMax = roundf (all_points[0].y);
-
     for (unsigned i = 1; i < all_points.length - 4; i++)
     {
       float rounded_x = roundf (all_points[i].x);
@@ -128,7 +130,7 @@
 
     /*for empty glyphs: all_points only include phantom points.
      *just update metrics and then return */
-    if (all_points.length == 4)
+    if (!glyph_header)
       return true;
 
     glyph_header->numberOfContours = header->numberOfContours;
@@ -145,11 +147,18 @@
                                   hb_font_t *font,
                                   const glyf_accelerator_t &glyf,
                                   hb_bytes_t &dest_start,  /* IN/OUT */
-                                  hb_bytes_t &dest_end /* OUT */) const
+                                  hb_bytes_t &dest_end /* OUT */)
   {
     contour_point_vector_t all_points, deltas;
-    get_points (font, glyf, all_points, &deltas, false);
+    if (!get_points (font, glyf, all_points, &deltas, false, false))
+      return false;
 
+    // .notdef, set type to empty so we only update metrics and don't compile bytes for
+    // it
+    if (gid == 0 &&
+        !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+      type = EMPTY;
+
     switch (type) {
     case COMPOSITE:
       if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
@@ -171,7 +180,12 @@
       break;
     }
 
-    return compile_header_bytes (plan, all_points, dest_start);
+    if (!compile_header_bytes (plan, all_points, dest_start))
+    {
+      dest_end.fini ();
+      return false;
+    }
+    return true;
   }
 
 
@@ -182,6 +196,7 @@
   bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
 		   contour_point_vector_t &all_points /* OUT */,
 		   contour_point_vector_t *deltas = nullptr, /* OUT */
+		   bool shift_points_hori = true,
 		   bool use_my_metrics = true,
 		   bool phantom_only = false,
 		   unsigned int depth = 0) const
@@ -238,8 +253,7 @@
     if (deltas != nullptr && depth == 0 && type == COMPOSITE)
     {
       if (unlikely (!deltas->resize (points.length))) return false;
-      for (unsigned i = 0 ; i < points.length; i++)
-        deltas->arrayZ[i] = points.arrayZ[i];
+      deltas->copy_vector (points);
     }
 
 #ifndef HB_NO_VAR
@@ -271,7 +285,7 @@
         comp_points.reset ();
 	if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
 				       .get_points (font, glyf_accelerator, comp_points,
-						    deltas, use_my_metrics, phantom_only, depth + 1)))
+						    deltas, shift_points_hori, use_my_metrics, phantom_only, depth + 1)))
 	  return false;
 
 	/* Copy phantom points from component if USE_MY_METRICS flag set */
@@ -310,7 +324,7 @@
       all_points.extend (phantoms);
     }
 
-    if (depth == 0) /* Apply at top level */
+    if (depth == 0 && shift_points_hori) /* Apply at top level */
     {
       /* Undocumented rasterizer behavior:
        * Shift points horizontally by the updated left side bearing
@@ -332,10 +346,16 @@
 
   hb_bytes_t get_bytes () const { return bytes; }
 
-  Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
-	 hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_),
-						      header (bytes.as<GlyphHeader> ()),
-						      gid (gid_)
+  Glyph () : bytes (),
+             header (bytes.as<GlyphHeader> ()),
+             gid (-1),
+             type(EMPTY)
+  {}
+
+  Glyph (hb_bytes_t bytes_,
+	 hb_codepoint_t gid_ = (unsigned) -1) : bytes (bytes_),
+                                                header (bytes.as<GlyphHeader> ()),
+                                                gid (gid_)
   {
     int num_contours = header->numberOfContours;
     if (unlikely (num_contours == 0)) type = EMPTY;

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -271,31 +271,29 @@
     }
     //convert absolute values to relative values
     unsigned num_points = all_points.length - 4;
-    hb_vector_t<hb_pair_t<int, int>> deltas;
-    deltas.resize (num_points);
 
-    for (unsigned i = 0; i < num_points; i++)
-    {
-      deltas[i].first = i == 0 ? roundf (all_points[i].x) : roundf (all_points[i].x) - roundf (all_points[i-1].x);
-      deltas[i].second = i == 0 ? roundf (all_points[i].y) : roundf (all_points[i].y) - roundf (all_points[i-1].y);
-    }
-
     hb_vector_t<uint8_t> flags, x_coords, y_coords;
-    flags.alloc (num_points);
-    x_coords.alloc (2*num_points);
-    y_coords.alloc (2*num_points);
+    if (unlikely (!flags.alloc (num_points))) return false;
+    if (unlikely (!x_coords.alloc (2*num_points))) return false;
+    if (unlikely (!y_coords.alloc (2*num_points))) return false;
 
     uint8_t lastflag = 0, repeat = 0;
-
+    int prev_x = 0.f, prev_y = 0.f;
+    
     for (unsigned i = 0; i < num_points; i++)
     {
       uint8_t flag = all_points[i].flag;
       flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
 
-      encode_coord (deltas[i].first, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
-      encode_coord (deltas[i].second, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
+      float cur_x = roundf (all_points[i].x);
+      float cur_y = roundf (all_points[i].y);
+      encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
+      encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
       if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point
       encode_flag (flag, repeat, lastflag, flags);
+
+      prev_x = cur_x;
+      prev_y = cur_y;
     }
 
     unsigned len_before_instrs = 2 * header.numberOfContours + 2;

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SubsetGlyph.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -14,7 +14,6 @@
 
 struct SubsetGlyph
 {
-  hb_codepoint_t new_gid;
   hb_codepoint_t old_gid;
   Glyph source_glyph;
   hb_bytes_t dest_start;  /* region of source_glyph to copy first */

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -72,10 +72,13 @@
     if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
 
     hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
-    _populate_subset_glyphs (c->plan, &glyphs);
+    _populate_subset_glyphs (c->plan, glyphs);
 
     if (!c->plan->pinned_at_default)
-      _compile_subset_glyphs_with_deltas (c->plan, &glyphs);
+    {
+      if (!_compile_subset_glyphs_with_deltas (c->plan, &glyphs))
+        return_trace (false);
+    }
 
     auto padded_offsets =
     + hb_iter (glyphs)
@@ -105,9 +108,9 @@
 
   void
   _populate_subset_glyphs (const hb_subset_plan_t   *plan,
-			   hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
-  
-  void
+			   hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
+
+  bool
   _compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
                                       hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
 
@@ -180,7 +183,7 @@
     contour_point_vector_t all_points;
 
     bool phantom_only = !consumer.is_consuming_contour_points ();
-    if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, phantom_only)))
+    if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, true, phantom_only)))
       return false;
 
     if (consumer.is_consuming_contour_points ())
@@ -374,44 +377,43 @@
 
 inline void
 glyf::_populate_subset_glyphs (const hb_subset_plan_t   *plan,
-			       hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
+			       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;
 
-  + hb_range (plan->num_output_glyphs ())
-  | hb_map ([&] (hb_codepoint_t new_gid)
-	{
-	  glyf_impl::SubsetGlyph subset_glyph = {0};
-	  subset_glyph.new_gid = new_gid;
+  for (auto p : plan->glyph_map->iter ())
+  {
+    unsigned new_gid = p.second;
+    glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid];
+    subset_glyph.old_gid = p.first;
 
-	  /* should never fail: all old gids should be mapped */
-	  if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
-	    return subset_glyph;
+    if (unlikely (new_gid == 0 &&
+                  !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
+                  plan->pinned_at_default)
+      subset_glyph.source_glyph = glyf_impl::Glyph ();
+    else
+      subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
 
-	  if (new_gid == 0 &&
-	      !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
-	    subset_glyph.source_glyph = glyf_impl::Glyph ();
-	  else
-	    subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
-	  if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
-	    subset_glyph.drop_hints_bytes ();
-	  else
-	    subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
-	  return subset_glyph;
-	})
-  | hb_sink (glyphs)
-  ;
+    if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+      subset_glyph.drop_hints_bytes ();
+    else
+      subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
+  }
 }
 
-inline void
+inline bool
 glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
                                           hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
 {
   OT::glyf_accelerator_t glyf (plan->source);
   hb_font_t *font = hb_font_create (plan->source);
+  if (unlikely (!font)) return false;
 
   hb_vector_t<hb_variation_t> vars;
-  vars.alloc (plan->user_axes_location->get_population ());
+  if (unlikely (!vars.alloc (plan->user_axes_location->get_population ())))
+    return false;
 
   for (auto _ : *plan->user_axes_location)
   {
@@ -423,9 +425,16 @@
 
   hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
   for (auto& subset_glyph : *glyphs)
-    const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf);
+  {
+    if (!const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf))
+    {
+      hb_font_destroy (font);
+      return false;
+    }
+  }
 
   hb_font_destroy (font);
+  return true;
 }
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py	2022-10-08 21:59:08 UTC (rev 64657)
@@ -134,6 +134,7 @@
 	'Number_Joiner',
 	'Number',
 	'Brahmi_Joining_Number',
+	'Symbol_Modifier',
 	'Hieroglyph',
 	'Hieroglyph_Joiner',
 	'Hieroglyph_Segment_Begin',
@@ -214,8 +215,7 @@
 	return (UISC == Consonant_Medial and UGC != Lo or
 		UISC == Consonant_Initial_Postfixed)
 def is_CONS_MOD(U, UISC, UDI, UGC, AJT):
-	return (UISC in [Nukta, Gemination_Mark, Consonant_Killer] and
-		not is_SYM_MOD(U, UISC, UDI, UGC, AJT))
+	return UISC in [Nukta, Gemination_Mark, Consonant_Killer]
 def is_CONS_SUB(U, UISC, UDI, UGC, AJT):
 	return UISC == Consonant_Subjoined and UGC != Lo
 def is_CONS_WITH_STACKER(U, UISC, UDI, UGC, AJT):
@@ -257,7 +257,7 @@
 	# Split off of HALANT
 	return U == 0x1A60
 def is_SYM_MOD(U, UISC, UDI, UGC, AJT):
-	return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
+	return UISC == Symbol_Modifier
 def is_VOWEL(U, UISC, UDI, UGC, AJT):
 	return (UISC == Pure_Killer or
 		UGC != Lo and UISC in [Vowel, Vowel_Dependent])
@@ -359,9 +359,6 @@
 		# TODO: These don't have UISC assigned in Unicode 13.0.0, but have UIPC
 		if 0x0F18 <= U <= 0x0F19 or 0x0F3E <= U <= 0x0F3F: UISC = Vowel_Dependent
 
-		# TODO: https://github.com/harfbuzz/harfbuzz/pull/627
-		if 0x1BF2 <= U <= 0x1BF3: UISC = Nukta; UIPC = Bottom
-
 		# TODO: U+1CED should only be allowed after some of
 		# the nasalization marks, maybe only for U+1CE9..U+1CF1.
 		if U == 0x1CED: UISC = Tone_Mark
@@ -372,24 +369,10 @@
 
 		# Resolve Indic_Positional_Category
 
-		# TODO: These should die, but have UIPC in Unicode 13.0.0
-		if U in [0x953, 0x954]: UIPC = Not_Applicable
-
-		# TODO: These are not in USE's override list that we have, nor are they in Unicode 13.0.0
-		if 0xA926 <= U <= 0xA92A: UIPC = Top
 		# TODO: https://github.com/harfbuzz/harfbuzz/pull/1037
 		#  and https://github.com/harfbuzz/harfbuzz/issues/1631
 		if U in [0x11302, 0x11303, 0x114C1]: UIPC = Top
-		if 0x1CF8 <= U <= 0x1CF9: UIPC = Top
 
-		# TODO: https://github.com/harfbuzz/harfbuzz/issues/3550
-		if U == 0x10A38: UIPC = Bottom
-
-		# TODO: https://github.com/harfbuzz/harfbuzz/pull/982
-		# also  https://github.com/harfbuzz/harfbuzz/issues/1012
-		if 0x1112A <= U <= 0x1112B: UIPC = Top
-		if 0x11131 <= U <= 0x11132: UIPC = Top
-
 		assert (UIPC in [Not_Applicable, Visual_Order_Left] or U == 0x0F7F or
 			USE in use_positions), "%s %s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UDI, UGC, AJT)
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -70,8 +70,8 @@
       {
         DEBUG_MSG (SUBSET_REPACK, nullptr,
                    "vertex [%lu] bytes != [%lu] bytes, depth = %u",
-                   table_size (),
-                   other.table_size (),
+                   (unsigned long) table_size (),
+                   (unsigned long) other.table_size (),
                    depth);
 
         auto a = as_bytes ();
@@ -496,6 +496,12 @@
   }
 
   template <typename T, typename ...Ts>
+  vertex_and_table_t<T> as_mutable_table (unsigned parent, const void* offset, Ts... ds)
+  {
+    return as_table_from_index<T> (mutable_index_for_offset (parent, offset), std::forward<Ts>(ds)...);
+  }
+
+  template <typename T, typename ...Ts>
   vertex_and_table_t<T> as_table_from_index (unsigned index, Ts... ds)
   {
     if (index >= vertices_.length)
@@ -833,8 +839,21 @@
    * parent to the clone. The copy is a shallow copy, objects
    * linked from child are not duplicated.
    */
-  bool duplicate (unsigned parent_idx, unsigned child_idx)
+  unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx)
   {
+    unsigned new_idx = duplicate (parent_idx, child_idx);
+    if (new_idx == (unsigned) -1) return child_idx;
+    return new_idx;
+  }
+
+
+  /*
+   * Creates a copy of child and re-assigns the link from
+   * parent to the clone. The copy is a shallow copy, objects
+   * linked from child are not duplicated.
+   */
+  unsigned duplicate (unsigned parent_idx, unsigned child_idx)
+  {
     update_parents ();
 
     unsigned links_to_child = 0;
@@ -849,7 +868,7 @@
       // to child are from parent.
       DEBUG_MSG (SUBSET_REPACK, nullptr, "  Not duplicating %d => %d",
                  parent_idx, child_idx);
-      return false;
+      return -1;
     }
 
     DEBUG_MSG (SUBSET_REPACK, nullptr, "  Duplicating %d => %d",
@@ -869,7 +888,7 @@
       reassign_link (l, parent_idx, clone_idx);
     }
 
-    return true;
+    return clone_idx;
   }
 
 

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -131,8 +131,10 @@
     for (unsigned i = 0; i < subTable.len; i++)
     {
       unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
+      unsigned parent_index = this_index;
       if (is_ext) {
         unsigned ext_subtable_index = subtable_index;
+        parent_index = ext_subtable_index;
         ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
             (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
             c.graph.object (ext_subtable_index).head;
@@ -150,9 +152,9 @@
       switch (type)
       {
       case 2:
-        new_sub_tables = split_subtable<PairPos> (c, subtable_index); break;
+        new_sub_tables = split_subtable<PairPos> (c, parent_index, subtable_index); break;
       case 4:
-        new_sub_tables = split_subtable<MarkBasePos> (c, subtable_index); break;
+        new_sub_tables = split_subtable<MarkBasePos> (c, parent_index, subtable_index); break;
       default:
         break;
       }
@@ -172,6 +174,7 @@
 
   template<typename T>
   hb_vector_t<unsigned> split_subtable (gsubgpos_graph_context_t& c,
+                                        unsigned parent_idx,
                                         unsigned objidx)
   {
     T* sub_table = (T*) c.graph.object (objidx).head;
@@ -178,7 +181,7 @@
     if (!sub_table || !sub_table->sanitize (c.graph.vertices_[objidx]))
       return hb_vector_t<unsigned> ();
 
-    return sub_table->split_subtables (c, objidx);
+    return sub_table->split_subtables (c, parent_idx, objidx);
   }
 
   void add_sub_tables (gsubgpos_graph_context_t& c,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/markbasepos-graph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/markbasepos-graph.hh	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/markbasepos-graph.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -209,7 +209,9 @@
     return vertex_len >= MarkBasePosFormat1::static_size;
   }
 
-  hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+  hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+                                         unsigned parent_index,
+                                         unsigned this_index)
   {
     hb_set_t visited;
 
@@ -261,7 +263,7 @@
     split_context_t split_context {
       c,
       this,
-      this_index,
+      c.graph.duplicate_if_shared (parent_index, this_index),
       std::move (class_to_info),
       c.graph.vertices_[mark_array_id].position_to_index_map (),
     };
@@ -365,8 +367,8 @@
 
     classCount = count;
 
-    auto mark_coverage = sc.c.graph.as_table<Coverage> (this_index,
-                                                        &markCoverage);
+    auto mark_coverage = sc.c.graph.as_mutable_table<Coverage> (this_index,
+                                                                &markCoverage);
     if (!mark_coverage) return false;
     hb_set_t marks = sc.marks_for (0, count);
     auto new_coverage =
@@ -380,9 +382,9 @@
       return false;
 
 
-    auto base_array = sc.c.graph.as_table<AnchorMatrix> (this_index,
-                                                         &baseArray,
-                                                         old_count);
+    auto base_array = sc.c.graph.as_mutable_table<AnchorMatrix> (this_index,
+                                                                 &baseArray,
+                                                                 old_count);
     if (!base_array || !base_array.table->shrink (sc.c,
                                                   base_array.index,
                                                   old_count,
@@ -389,8 +391,8 @@
                                                   count))
       return false;
 
-    auto mark_array = sc.c.graph.as_table<MarkArray> (this_index,
-                                                      &markArray);
+    auto mark_array = sc.c.graph.as_mutable_table<MarkArray> (this_index,
+                                                              &markArray);
     if (!mark_array || !mark_array.table->shrink (sc.c,
                                                   sc.mark_array_links,
                                                   mark_array.index,
@@ -469,11 +471,12 @@
 struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
 {
   hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+                                         unsigned parent_index,
                                          unsigned this_index)
   {
     switch (u.format) {
     case 1:
-      return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, this_index);
+      return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
 #ifndef HB_NO_BORING_EXPANSION
     case 2: HB_FALLTHROUGH;
       // Don't split 24bit PairPos's.

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -47,7 +47,9 @@
         min_size + pairSet.get_size () - pairSet.len.get_size();
   }
 
-  hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+  hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+                                         unsigned parent_index,
+                                         unsigned this_index)
   {
     hb_set_t visited;
 
@@ -81,7 +83,7 @@
     split_context_t split_context {
       c,
       this,
-      this_index,
+      c.graph.duplicate_if_shared (parent_index, this_index),
     };
 
     return actuate_subtable_split<split_context_t> (split_context, split_points);
@@ -125,16 +127,12 @@
     pairSet.len = count;
     c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
 
-    unsigned coverage_id = c.graph.mutable_index_for_offset (this_index, &coverage);
-    unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
-    auto& coverage_v = c.graph.vertices_[coverage_id];
+    auto coverage = c.graph.as_mutable_table<Coverage> (this_index, &this->coverage);
+    if (!coverage) return false;
 
-    Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
-    if (!coverage_table || !coverage_table->sanitize (coverage_v))
-      return false;
-
+    unsigned coverage_size = coverage.vertex->table_size ();
     auto new_coverage =
-        + hb_zip (coverage_table->iter (), hb_range ())
+        + hb_zip (coverage.table->iter (), hb_range ())
         | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
           return p.second < count;
         })
@@ -141,7 +139,7 @@
         | hb_map_retains_sorting (hb_first)
         ;
 
-    return Coverage::make_coverage (c, new_coverage, coverage_id, coverage_size);
+    return Coverage::make_coverage (c, new_coverage, coverage.index, coverage_size);
   }
 
   // Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
@@ -206,7 +204,9 @@
         min_size + class1_count * get_class1_record_size ();
   }
 
-  hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+  hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+                                         unsigned parent_index,
+                                         unsigned this_index)
   {
     const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size;
     const unsigned class_def_2_size = size_of (c, this_index, &classDef2);
@@ -287,7 +287,7 @@
     split_context_t split_context {
       c,
       this,
-      this_index,
+      c.graph.duplicate_if_shared (parent_index, this_index),
       class1_record_size,
       total_value_len,
       value_1_len,
@@ -508,24 +508,18 @@
     graph.vertices_[split_context.this_index].obj.tail -=
         (old_count - count) * split_context.class1_record_size;
 
-    unsigned coverage_id =
-        graph.mutable_index_for_offset (split_context.this_index, &coverage);
-    unsigned class_def_1_id =
-        graph.mutable_index_for_offset (split_context.this_index, &classDef1);
-    auto& coverage_v = graph.vertices_[coverage_id];
-    auto& class_def_1_v = graph.vertices_[class_def_1_id];
-    Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
-    ClassDef* class_def_1_table = (ClassDef*) class_def_1_v.obj.head;
-    if (!coverage_table
-        || !coverage_table->sanitize (coverage_v)
-        || !class_def_1_table
-        || !class_def_1_table->sanitize (class_def_1_v))
-      return false;
+    auto coverage =
+        graph.as_mutable_table<Coverage> (split_context.this_index, &this->coverage);
+    if (!coverage) return false;
 
+    auto class_def_1 =
+        graph.as_mutable_table<ClassDef> (split_context.this_index, &classDef1);
+    if (!class_def_1) return false;
+
     auto klass_map =
-    + coverage_table->iter ()
+    + 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_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1.table->get_class (gid));
     })
     | hb_filter ([&] (hb_codepoint_t klass) {
       return klass < count;
@@ -534,14 +528,14 @@
 
     if (!Coverage::make_coverage (split_context.c,
                                   + klass_map | hb_map_retains_sorting (hb_first),
-                                  coverage_id,
-                                  coverage_v.table_size ()))
+                                  coverage.index,
+                                  coverage.vertex->table_size ()))
       return false;
 
     return ClassDef::make_class_def (split_context.c,
                                      + klass_map,
-                                     class_def_1_id,
-                                     class_def_1_v.table_size ());
+                                     class_def_1.index,
+                                     class_def_1.vertex->table_size ());
   }
 
   hb_hashmap_t<unsigned, unsigned>
@@ -605,13 +599,15 @@
 
 struct PairPos : public OT::Layout::GPOS_impl::PairPos
 {
-  hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+  hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+                                         unsigned parent_index,
+                                         unsigned this_index)
   {
     switch (u.format) {
     case 1:
-      return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index);
+      return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
     case 2:
-      return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index);
+      return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index);
 #ifndef HB_NO_BORING_EXPANSION
     case 3: HB_FALLTHROUGH;
     case 4: HB_FALLTHROUGH;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -131,6 +131,7 @@
   {HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING,          HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS,           (hb_aat_layout_feature_selector_t) 4},
   {HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT,              (hb_aat_layout_feature_selector_t) 7},
   {HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT,             (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('r','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF},
   {HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA,               HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON,                   HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF},
   {HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS,           HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
   {HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS,          HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -71,6 +71,7 @@
 #define HB_NO_LANGUAGE_PRIVATE_SUBTAG
 #define HB_NO_LAYOUT_FEATURE_PARAMS
 #define HB_NO_LAYOUT_COLLECT_GLYPHS
+#define HB_NO_LAYOUT_RARELY_USED
 #define HB_NO_LAYOUT_UNUSED
 #define HB_NO_MATH
 #define HB_NO_META

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cplusplus.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cplusplus.hh	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cplusplus.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -69,9 +69,9 @@
   operator T * () const { return p; }
   T& operator * () const { return *get (); }
   T* operator -> () const { return get (); }
-  operator bool () { return p; }
-  bool operator == (const shared_ptr &o) { return p == o.p; }
-  bool operator != (const shared_ptr &o) { return p != o.p; }
+  operator bool () const { return p; }
+  bool operator == (const shared_ptr &o) const { return p == o.p; }
+  bool operator != (const shared_ptr &o) const { return p != o.p; }
 
   static T* get_empty() { return v::get_empty (); }
   T* reference() { return v::reference (p); }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -633,21 +633,30 @@
  * face-builder: A face that has add_table().
  */
 
+struct face_table_info_t
+{
+  hb_blob_t* data;
+  unsigned order;
+};
+
 struct hb_face_builder_data_t
 {
-  hb_hashmap_t<hb_tag_t, hb_blob_t *> tables;
+  hb_hashmap_t<hb_tag_t, face_table_info_t> tables;
 };
 
 static int compare_entries (const void* pa, const void* pb)
 {
-  const auto& a = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pa;
-  const auto& b = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pb;
+  const auto& a = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pa;
+  const auto& b = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pb;
 
   /* Order by blob size first (smallest to largest) and then table tag */
 
-  if (a.second->length != b.second->length)
-    return a.second->length < b.second->length ? -1 : +1;
+  if (a.second.order != b.second.order)
+    return a.second.order < b.second.order ? -1 : +1;
 
+  if (a.second.data->length != b.second.data->length)
+    return a.second.data->length < b.second.data->length ? -1 : +1;
+
   return a.first < b.first ? -1 : a.first == b.first ? 0 : +1;
 }
 
@@ -668,8 +677,8 @@
 {
   hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
 
-  for (hb_blob_t* b : data->tables.values())
-    hb_blob_destroy (b);
+  for (auto info : data->tables.values())
+    hb_blob_destroy (info.data);
 
   data->tables.fini ();
 
@@ -683,8 +692,8 @@
   unsigned int table_count = data->tables.get_population ();
   unsigned int face_length = table_count * 16 + 12;
 
-  for (hb_blob_t* b : data->tables.values())
-    face_length += hb_ceil_to_4 (hb_blob_get_length (b));
+  for (auto info : data->tables.values())
+    face_length += hb_ceil_to_4 (hb_blob_get_length (info.data));
 
   char *buf = (char *) hb_malloc (face_length);
   if (unlikely (!buf))
@@ -699,7 +708,7 @@
   hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
 
   // Sort the tags so that produced face is deterministic.
-  hb_vector_t<hb_pair_t <hb_tag_t, hb_blob_t*>> sorted_entries;
+  hb_vector_t<hb_pair_t <hb_tag_t, face_table_info_t>> sorted_entries;
   data->tables.iter () | hb_sink (sorted_entries);
   if (unlikely (sorted_entries.in_error ()))
   {
@@ -708,8 +717,14 @@
   }
 
   sorted_entries.qsort (compare_entries);
-  bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter());
 
+  bool ret = f->serialize_single (&c,
+                                  sfnt_tag,
+                                  + sorted_entries.iter()
+                                  | hb_map ([&] (hb_pair_t<hb_tag_t, face_table_info_t> _) {
+                                    return hb_pair_t<hb_tag_t, hb_blob_t*> (_.first, _.second.data);
+                                  }));
+
   c.end_serialize ();
 
   if (unlikely (!ret))
@@ -729,7 +744,7 @@
   if (!tag)
     return _hb_face_builder_data_reference_blob (data);
 
-  return hb_blob_reference (data->tables[tag]);
+  return hb_blob_reference (data->tables[tag].data);
 }
 
 
@@ -777,8 +792,8 @@
 
   hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
 
-  hb_blob_t* previous = data->tables.get (tag);
-  if (!data->tables.set (tag, hb_blob_reference (blob)))
+  hb_blob_t* previous = data->tables.get (tag).data;
+  if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), 0}))
   {
     hb_blob_destroy (blob);
     return false;
@@ -787,3 +802,36 @@
   hb_blob_destroy (previous);
   return true;
 }
+
+/**
+ * hb_face_builder_sort_tables:
+ * @face: A face object created with hb_face_builder_create()
+ * @tags: (array zero-terminated=1) ordered list of table tags terminated by
+ *   %HB_TAG_NONE
+ *
+ * Set the ordering of tables for serialization. Any tables not
+ * specified in the tags list will be ordered after the tables in
+ * tags, ordered by the default sort ordering.
+ *
+ * Since: 5.3.0
+ **/
+void
+hb_face_builder_sort_tables (hb_face_t *face,
+                             const hb_tag_t  *tags)
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
+
+  // Sort all unspecified tables after any specified tables.
+  for (auto& info : data->tables.values_ref())
+    info.order = -1;
+
+  unsigned order = 0;
+  for (const hb_tag_t* tag = tags;
+       *tag;
+       tag++)
+  {
+    face_table_info_t* info;
+    if (!data->tables.has (*tag, &info)) continue;
+    info->order = order++;
+  }
+}

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h	2022-10-08 21:59:08 UTC (rev 64657)
@@ -171,7 +171,11 @@
 			   hb_tag_t   tag,
 			   hb_blob_t *blob);
 
+HB_EXTERN void
+hb_face_builder_sort_tables (hb_face_t *face,
+                             const hb_tag_t  *tags);
 
+
 HB_END_DECLS
 
 #endif /* HB_FACE_H */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -133,6 +133,18 @@
 
   template <typename T> constexpr auto
   operator () (T *v) const HB_AUTO_RETURN (*v)
+
+  template <typename T> constexpr auto
+  operator () (const hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v)
+
+  template <typename T> constexpr auto
+  operator () (hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v)
+  
+  template <typename T> constexpr auto
+  operator () (const hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v)
+
+  template <typename T> constexpr auto
+  operator () (hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v)
 }
 HB_FUNCOBJ (hb_deref);
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -295,8 +295,8 @@
  * @glyph: a glyph index
  *
  * Fetches the PNG image for a glyph. This function takes a font object, not a face object,
- * as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font
- * object. If UPEM is unset, the blob returned will be the largest PNG available.
+ * as input. To get an optimally sized PNG blob, the PPEM values must be set on the @font
+ * object. If PPEM is unset, the blob returned will be the largest PNG available.
  *
  * If the glyph has no PNG image, the singleton empty blob is returned.
  *

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -40,7 +40,6 @@
 #include "hb-ot-cff1-table.hh"
 #include "hb-ot-cff2-table.hh"
 #include "hb-ot-hmtx-table.hh"
-#include "hb-ot-os2-table.hh"
 #include "hb-ot-post-table.hh"
 #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-ot-vorg-table.hh"
@@ -349,6 +348,7 @@
 
 #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
   if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
+  if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
 #endif
   if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
 #ifndef HB_NO_OT_FONT_CFF
@@ -355,9 +355,6 @@
   if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
   if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
 #endif
-#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
-  if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
-#endif
 
   // TODO Hook up side-bearings variations.
   return false;

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -94,7 +94,20 @@
     hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_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;
+  hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map;
+  hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
 
+  // not stored in subset_plan
+  hb_set_t *feature_indices;
+  bool apply;
+  unsigned cur_record_idx;
+  hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map;
+};
+
 struct hb_prune_langsys_context_t
 {
   hb_prune_langsys_context_t (const void         *table_,
@@ -160,24 +173,40 @@
   const hb_map_t *lookup_index_map;
   const hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
   const hb_map_t *feature_index_map;
+  const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
+  hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map;
+
   unsigned cur_script_index;
+  unsigned cur_feature_var_record_idx;
 
   hb_subset_layout_context_t (hb_subset_context_t *c_,
-			      hb_tag_t tag_,
-			      hb_map_t *lookup_map_,
-			      hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
-			      hb_map_t *feature_index_map_) :
+			      hb_tag_t tag_) :
 				subset_context (c_),
 				table_tag (tag_),
-				lookup_index_map (lookup_map_),
-				script_langsys_map (script_langsys_map_),
-				feature_index_map (feature_index_map_),
 				cur_script_index (0xFFFFu),
+				cur_feature_var_record_idx (0u),
 				script_count (0),
 				langsys_count (0),
 				feature_index_count (0),
 				lookup_index_count (0)
-  {}
+  {
+    if (tag_ == HB_OT_TAG_GSUB)
+    {
+      lookup_index_map = c_->plan->gsub_lookups;
+      script_langsys_map = c_->plan->gsub_langsys;
+      feature_index_map = c_->plan->gsub_features;
+      feature_substitutes_map = c_->plan->gsub_feature_substitutes_map;
+      feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gsub_feature_record_cond_idx_map;
+    }
+    else
+    {
+      lookup_index_map = c_->plan->gpos_lookups;
+      script_langsys_map = c_->plan->gpos_langsys;
+      feature_index_map = c_->plan->gpos_features;
+      feature_substitutes_map = c_->plan->gpos_feature_substitutes_map;
+      feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gpos_feature_record_cond_idx_map;
+    }
+  }
 
   private:
   unsigned script_count;
@@ -324,6 +353,31 @@
   const void *base;
 };
 
+template<typename OutputArray, typename Arg>
+struct subset_record_array_arg_t
+{
+  subset_record_array_arg_t (hb_subset_layout_context_t *c_, OutputArray* out_,
+			     const void *base_,
+			     Arg &&arg_) : subset_layout_context (c_),
+					   out (out_), base (base_), arg (arg_) {}
+
+  template <typename T>
+  void
+  operator () (T&& record)
+  {
+    auto snap = subset_layout_context->subset_context->serializer->snapshot ();
+    bool ret = record.subset (subset_layout_context, base, arg);
+    if (!ret) subset_layout_context->subset_context->serializer->revert (snap);
+    else out->len++;
+  }
+
+  private:
+  hb_subset_layout_context_t *subset_layout_context;
+  OutputArray *out;
+  const void *base;
+  Arg &&arg;
+};
+
 /*
  * Helper to subset a RecordList/record array. Subsets each Record in the array and
  * discards the record if the subset operation returns false.
@@ -335,6 +389,13 @@
   operator () (hb_subset_layout_context_t *c, OutputArray* out,
 	       const void *base) const
   { return subset_record_array_t<OutputArray> (c, out, base); }
+
+  /* Variant with one extra argument passed to subset */
+  template<typename OutputArray, typename Arg>
+  subset_record_array_arg_t<OutputArray, Arg>
+  operator () (hb_subset_layout_context_t *c, OutputArray* out,
+               const void *base, Arg &&arg) const
+  { return subset_record_array_arg_t<OutputArray, Arg> (c, out, base, arg); }
 }
 HB_FUNCOBJ (subset_record_array);
 
@@ -431,94 +492,6 @@
 };
 
 
-struct Record_sanitize_closure_t {
-  hb_tag_t tag;
-  const void *list_base;
-};
-
-template <typename Type>
-struct Record
-{
-  int cmp (hb_tag_t a) const { return tag.cmp (a); }
-
-  bool subset (hb_subset_layout_context_t *c, const void *base) const
-  {
-    TRACE_SUBSET (this);
-    auto *out = c->subset_context->serializer->embed (this);
-    if (unlikely (!out)) return_trace (false);
-    bool ret = out->offset.serialize_subset (c->subset_context, offset, base, c, &tag);
-    return_trace (ret);
-  }
-
-  bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    const Record_sanitize_closure_t closure = {tag, base};
-    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
-  }
-
-  Tag		tag;		/* 4-byte Tag identifier */
-  Offset16To<Type>
-		offset;		/* Offset from beginning of object holding
-				 * the Record */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-template <typename Type>
-struct RecordArrayOf : SortedArray16Of<Record<Type>>
-{
-  const Offset16To<Type>& get_offset (unsigned int i) const
-  { return (*this)[i].offset; }
-  Offset16To<Type>& get_offset (unsigned int i)
-  { return (*this)[i].offset; }
-  const Tag& get_tag (unsigned int i) const
-  { return (*this)[i].tag; }
-  unsigned int get_tags (unsigned int start_offset,
-			 unsigned int *record_count /* IN/OUT */,
-			 hb_tag_t     *record_tags /* OUT */) const
-  {
-    if (record_count)
-    {
-      + this->sub_array (start_offset, record_count)
-      | hb_map (&Record<Type>::tag)
-      | hb_sink (hb_array (record_tags, *record_count))
-      ;
-    }
-    return this->len;
-  }
-  bool find_index (hb_tag_t tag, unsigned int *index) const
-  {
-    return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
-  }
-};
-
-template <typename Type>
-struct RecordListOf : RecordArrayOf<Type>
-{
-  const Type& operator [] (unsigned int i) const
-  { return this+this->get_offset (i); }
-
-  bool subset (hb_subset_context_t *c,
-	       hb_subset_layout_context_t *l) const
-  {
-    TRACE_SUBSET (this);
-    auto *out = c->serializer->start_embed (*this);
-    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
-    + this->iter ()
-    | hb_apply (subset_record_array (l, out, this))
-    ;
-    return_trace (true);
-  }
-
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (RecordArrayOf<Type>::sanitize (c, this));
-  }
-};
-
 /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
 struct FeatureParamsSize
 {
@@ -801,6 +774,10 @@
   DEFINE_SIZE_MIN (0);
 };
 
+struct Record_sanitize_closure_t {
+  hb_tag_t tag;
+  const void *list_base;
+};
 
 struct Feature
 {
@@ -897,6 +874,103 @@
   DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
 };
 
+template <typename Type>
+struct Record
+{
+  int cmp (hb_tag_t a) const { return tag.cmp (a); }
+
+  bool subset (hb_subset_layout_context_t *c, const void *base, const void *f_sub = nullptr) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->subset_context->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    if (!f_sub)
+      return_trace (out->offset.serialize_subset (c->subset_context, offset, base, c, &tag));
+
+    const Feature& f = *reinterpret_cast<const Feature *> (f_sub);
+    auto *s = c->subset_context->serializer;
+    s->push ();
+
+    out->offset = 0;
+    bool ret = f.subset (c->subset_context, c, &tag);
+    if (ret)
+      s->add_link (out->offset, s->pop_pack ());
+    else
+      s->pop_discard ();
+
+    return_trace (ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    const Record_sanitize_closure_t closure = {tag, base};
+    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
+  }
+
+  Tag           tag;            /* 4-byte Tag identifier */
+  Offset16To<Type>
+                offset;         /* Offset from beginning of object holding
+                                 * the Record */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <typename Type>
+struct RecordArrayOf : SortedArray16Of<Record<Type>>
+{
+  const Offset16To<Type>& get_offset (unsigned int i) const
+  { return (*this)[i].offset; }
+  Offset16To<Type>& get_offset (unsigned int i)
+  { return (*this)[i].offset; }
+  const Tag& get_tag (unsigned int i) const
+  { return (*this)[i].tag; }
+  unsigned int get_tags (unsigned int start_offset,
+                         unsigned int *record_count /* IN/OUT */,
+                         hb_tag_t     *record_tags /* OUT */) const
+  {
+    if (record_count)
+    {
+      + this->sub_array (start_offset, record_count)
+      | hb_map (&Record<Type>::tag)
+      | hb_sink (hb_array (record_tags, *record_count))
+      ;
+    }
+    return this->len;
+  }
+  bool find_index (hb_tag_t tag, unsigned int *index) const
+  {
+    return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+  }
+};
+
+template <typename Type>
+struct RecordListOf : RecordArrayOf<Type>
+{
+  const Type& operator [] (unsigned int i) const
+  { return this+this->get_offset (i); }
+
+  bool subset (hb_subset_context_t *c,
+               hb_subset_layout_context_t *l) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+    + this->iter ()
+    | hb_apply (subset_record_array (l, out, this))
+    ;
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (RecordArrayOf<Type>::sanitize (c, this));
+  }
+};
+
 struct RecordListOfFeature : RecordListOf<Feature>
 {
   bool subset (hb_subset_context_t *c,
@@ -907,11 +981,20 @@
     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
 
     unsigned count = this->len;
+
     + hb_zip (*this, hb_range (count))
     | hb_filter (l->feature_index_map, hb_second)
-    | hb_map (hb_first)
-    | hb_apply (subset_record_array (l, out, this))
+    | hb_apply ([l, out, this] (const hb_pair_t<const Record<Feature>&, unsigned>& _)
+                {
+                  const Feature *f_sub = nullptr;
+                  const Feature **f = nullptr;
+                  if (l->feature_substitutes_map->has (_.second, &f))
+                    f_sub = *f;
+
+                  subset_record_array (l, out, this, f_sub) (_.first);
+                })
     ;
+
     return_trace (true);
   }
 };
@@ -2692,6 +2775,13 @@
 /*
  * Feature Variations
  */
+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,
+};
 
 struct ConditionFormat1
 {
@@ -2702,10 +2792,52 @@
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (this);
     if (unlikely (!out)) return_trace (false);
-    return_trace (true);
+
+    const hb_map_t *index_map = c->plan->axes_index_map;
+    if (index_map->is_empty ()) return_trace (true);
+
+    if (!index_map->has (axisIndex))
+      return_trace (false);
+
+    return_trace (c->serializer->check_assign (out->axisIndex, index_map->get (axisIndex),
+                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
   }
 
   private:
+  Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
+                                             hb_map_t *condition_map /* OUT */) const
+  {
+    //invalid axis index, drop the entire record
+    if (!c->axes_index_tag_map->has (axisIndex))
+      return DROP_RECORD_WITH_VAR;
+
+    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))
+    {
+      // add axisIndex->value into the hashmap so we can check if the record is
+      // unique with variations
+      int16_t min_val = filterRangeMinValue;
+      int16_t max_val = filterRangeMaxValue;
+      hb_codepoint_t val = (max_val << 16) + 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 || v > filterRangeMaxValue)
+      return DROP_RECORD_WITH_VAR;
+
+    //axis pinned and condition met, drop the condition
+    return DROP_COND_WITH_VAR;
+  }
+
   bool evaluate (const int *coords, unsigned int coord_len) const
   {
     int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
@@ -2737,6 +2869,15 @@
     }
   }
 
+  Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
+                                             hb_map_t *condition_map /* OUT */) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.keep_with_variations (c, condition_map);
+    default:return KEEP_COND_WITH_VAR;
+    }
+  }
+
   template <typename context_t, typename ...Ts>
   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
@@ -2778,16 +2919,66 @@
     return true;
   }
 
-  bool subset (hb_subset_context_t *c) const
+  Cond_with_Var_flag_t 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;
+    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;
+    hb::shared_ptr<hb_set_t> s {cond_set};
+
+    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
+      if (ret == DROP_RECORD_WITH_VAR)
+        return DROP_RECORD_WITH_VAR;
+
+      // axis not pinned, keep this condition
+      if (ret == KEEP_COND_WITH_VAR)
+      {
+        cond_set->add (cond_idx);
+        num_kept_cond++;
+      }
+      cond_idx++;
+    }
+
+    // all conditions met
+    if (num_kept_cond == 0) return DROP_COND_WITH_VAR;
+ 
+    //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;
+
+    c->conditionset_map->set (p, 1);
+    c->record_cond_idx_map->set (c->cur_record_idx, s);
+
+    return KEEP_COND_WITH_VAR;
+  }
+
+  bool subset (hb_subset_context_t *c,
+               hb_subset_layout_context_t *l) const
+  {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (this);
     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
 
-    + conditions.iter ()
-    | hb_apply (subset_offset_array (c, out->conditions, this))
-    ;
+    hb_set_t *retained_cond_set = nullptr;
+    if (l->feature_record_cond_idx_map != nullptr)
+      retained_cond_set = l->feature_record_cond_idx_map->get (l->cur_feature_var_record_idx);
 
+    unsigned int count = conditions.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (retained_cond_set != nullptr && !retained_cond_set->has (i))
+        continue;
+      subset_offset_array (c, out->conditions, this) (conditions[i]);
+    }
+
     return_trace (bool (out->conditions));
   }
 
@@ -2820,10 +3011,19 @@
       feature_indexes->add (featureIndex);
   }
 
+  void collect_feature_substitutes_with_variations (hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
+                                                    const hb_set_t *feature_indices,
+                                                    const void *base) const
+  {
+    if (feature_indices->has (featureIndex))
+      feature_substitutes_map->set (featureIndex, &(base+feature));
+  }
+
   bool subset (hb_subset_layout_context_t *c, const void *base) const
   {
     TRACE_SUBSET (this);
-    if (!c->feature_index_map->has (featureIndex)) {
+    if (!c->feature_index_map->has (featureIndex) ||
+        c->feature_substitutes_map->has (featureIndex)) {
       // Feature that is being substituted is not being retained, so we don't
       // need this.
       return_trace (false);
@@ -2865,10 +3065,16 @@
   }
 
   void collect_lookups (const hb_set_t *feature_indexes,
+			const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
 			hb_set_t       *lookup_indexes /* OUT */) const
   {
     + hb_iter (substitutions)
     | hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
+    | hb_filter ([feature_substitutes_map] (const FeatureTableSubstitutionRecord& record)
+                 {
+                   if (feature_substitutes_map == nullptr) return true;
+                   return !feature_substitutes_map->has (record.featureIndex);
+                 })
     | hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
 		{ r.collect_lookups (this, lookup_indexes); })
     ;
@@ -2890,6 +3096,12 @@
     return false;
   }
 
+  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+  {
+    for (const FeatureTableSubstitutionRecord& record : substitutions)
+      record.collect_feature_substitutes_with_variations (c->feature_substitutes_map, c->feature_indices, this);
+  }
+
   bool subset (hb_subset_context_t        *c,
 	       hb_subset_layout_context_t *l) const
   {
@@ -2929,9 +3141,10 @@
 
   void collect_lookups (const void     *base,
 			const hb_set_t *feature_indexes,
+			const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
 			hb_set_t       *lookup_indexes /* OUT */) const
   {
-    return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
+    return (base+substitutions).collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
   }
 
   void closure_features (const void     *base,
@@ -2946,6 +3159,18 @@
     return (base+substitutions).intersects_features (feature_index_map);
   }
 
+  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+substitutions).collect_feature_substitutes_with_variations (c);
+      c->apply = false; // set variations only once
+    }
+  }
+
   bool subset (hb_subset_layout_context_t *c, const void *base) const
   {
     TRACE_SUBSET (this);
@@ -2952,7 +3177,7 @@
     auto *out = c->subset_context->serializer->embed (this);
     if (unlikely (!out)) return_trace (false);
 
-    out->conditions.serialize_subset (c->subset_context, conditions, base);
+    out->conditions.serialize_subset (c->subset_context, conditions, base, c);
     out->substitutions.serialize_subset (c->subset_context, substitutions, base, c);
 
     return_trace (true);
@@ -3002,6 +3227,16 @@
     return (this+record.substitutions).find_substitute (feature_index);
   }
 
+  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+  {
+    unsigned int count = varRecords.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      c->cur_record_idx = i;
+      varRecords[i].collect_feature_substitutes_with_variations (c, this);
+    }
+  }
+
   FeatureVariations* copy (hb_serialize_context_t *c) const
   {
     TRACE_SERIALIZE (this);
@@ -3009,17 +3244,25 @@
   }
 
   void collect_lookups (const hb_set_t *feature_indexes,
+			const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
 			hb_set_t       *lookup_indexes /* OUT */) const
   {
     for (const FeatureVariationRecord& r : varRecords)
-      r.collect_lookups (this, feature_indexes, lookup_indexes);
+      r.collect_lookups (this, feature_indexes, feature_substitutes_map, lookup_indexes);
   }
 
   void closure_features (const hb_map_t *lookup_indexes,
+			 const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
 			 hb_set_t       *feature_indexes /* OUT */) const
   {
-    for (const FeatureVariationRecord& record : varRecords)
-      record.closure_features (this, lookup_indexes, feature_indexes);
+    unsigned int count = varRecords.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (feature_record_cond_idx_map != nullptr &&
+          !feature_record_cond_idx_map->has (i))
+        continue;
+      varRecords[i].closure_features (this, lookup_indexes, feature_indexes);
+    }
   }
 
   bool subset (hb_subset_context_t *c,
@@ -3041,7 +3284,13 @@
     }
 
     unsigned count = (unsigned) (keep_up_to + 1);
-    for (unsigned i = 0; i < count; i++) {
+    for (unsigned i = 0; i < count; i++)
+    {
+      if (l->feature_record_cond_idx_map != nullptr &&
+          !l->feature_record_cond_idx_map->has (i))
+        continue;
+
+      l->cur_feature_var_record_idx = i;
       subset_record_array (l, &(out->varRecords), this) (varRecords[i]);
     }
     return_trace (bool (out->varRecords));

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -4236,13 +4236,19 @@
   }
 
   void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
+					  const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
 					  hb_set_t       *lookup_indexes /* OUT */) const
   {
 #ifndef HB_NO_VAR
-    get_feature_variations ().collect_lookups (feature_indexes, lookup_indexes);
+    get_feature_variations ().collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
 #endif
   }
 
+#ifndef HB_NO_VAR
+  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+  { get_feature_variations ().collect_feature_substitutes_with_variations (c); }
+#endif
+
   template <typename TLookup>
   void closure_lookups (hb_face_t      *face,
 			const hb_set_t *glyphs,
@@ -4278,6 +4284,8 @@
   }
 
   void prune_features (const hb_map_t *lookup_indices, /* IN */
+		       const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* IN */
+		       const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, /* IN */
 		       hb_set_t       *feature_indices /* IN/OUT */) const
   {
 #ifndef HB_NO_VAR
@@ -4285,7 +4293,7 @@
     // if the FeatureVariation's table and the alternate version(s) intersect the
     // set of lookup indices.
     hb_set_t alternate_feature_indices;
-    get_feature_variations ().closure_features (lookup_indices, &alternate_feature_indices);
+    get_feature_variations ().closure_features (lookup_indices, feature_record_cond_idx_map, &alternate_feature_indices);
     if (unlikely (alternate_feature_indices.in_error()))
     {
       feature_indices->err ();
@@ -4295,7 +4303,6 @@
 
     for (unsigned i : feature_indices->iter())
     {
-      const Feature& f = get_feature (i);
       hb_tag_t tag =  get_feature_tag (i);
       if (tag == HB_TAG ('p', 'r', 'e', 'f'))
         // Note: Never ever drop feature 'pref', even if it's empty.
@@ -4305,11 +4312,16 @@
         continue;
 
 
-      if (!f.featureParams.is_null () &&
+      const Feature *f = &(get_feature (i));
+      const Feature** p = nullptr;
+      if (feature_substitutes_map->has (i, &p))
+        f = *p;
+
+      if (!f->featureParams.is_null () &&
           tag == HB_TAG ('s', 'i', 'z', 'e'))
         continue;
 
-      if (!f.intersects_lookup_indexes (lookup_indices)
+      if (!f->intersects_lookup_indexes (lookup_indices)
 #ifndef HB_NO_VAR
           && !alternate_feature_indices.has (i)
 #endif

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -1271,7 +1271,7 @@
        hb_set_next (&feature_indexes, &feature_index);)
     g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
 
-  g.feature_variation_collect_lookups (&feature_indexes, lookup_indexes);
+  g.feature_variation_collect_lookups (&feature_indexes, nullptr, lookup_indexes);
 }
 
 
@@ -1709,6 +1709,8 @@
 
   return false;
 }
+
+
 /**
  * hb_ot_layout_feature_get_name_ids:
  * @face: #hb_face_t to work upon
@@ -2341,6 +2343,7 @@
   ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
 };
 
+#ifndef HB_NO_LAYOUT_RARELY_USED
 /**
  * hb_ot_layout_lookup_get_glyph_alternates:
  * @face: a face.
@@ -2373,4 +2376,72 @@
   return ret;
 }
 
+
+struct hb_position_single_dispatch_t :
+       hb_dispatch_context_t<hb_position_single_dispatch_t, bool>
+{
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  private:
+  template <typename T, typename ...Ts> auto
+  _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
+  ( obj.position_single (std::forward<Ts> (ds)...) )
+  template <typename T, typename ...Ts> auto
+  _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
+  ( default_return_value () )
+  public:
+  template <typename T, typename ...Ts> auto
+  dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
+  ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
+};
+
+/**
+ * hb_ot_layout_lookup_get_optical_bound:
+ * @font: a font.
+ * @lookup_index: index of the feature lookup to query.
+ * @direction: edge of the glyph to query.
+ * @glyph: a glyph id.
+ *
+ * Fetches the optical bound of a glyph positioned at the margin of text.
+ * The direction identifies which edge of the glyph to query.
+ *
+ * Return value: Adjustment value. Negative values mean the glyph will stick out of the margin.
+ *
+ * Since: 5.3.0
+ **/
+hb_position_t
+hb_ot_layout_lookup_get_optical_bound (hb_font_t      *font,
+				       unsigned        lookup_index,
+				       hb_direction_t  direction,
+				       hb_codepoint_t  glyph)
+{
+  const OT::PosLookup &lookup = font->face->table.GPOS->table->get_lookup (lookup_index);
+  hb_glyph_position_t pos = {0};
+  hb_position_single_dispatch_t c;
+  lookup.dispatch (&c, font, direction, glyph, pos);
+  hb_position_t ret = 0;
+  switch (direction)
+  {
+    case HB_DIRECTION_LTR:
+      ret = pos.x_offset;
+      break;
+    case HB_DIRECTION_RTL:
+      ret = pos.x_advance - pos.x_offset;
+      break;
+    case HB_DIRECTION_TTB:
+      ret = pos.y_offset;
+      break;
+    case HB_DIRECTION_BTT:
+      ret = pos.y_advance - pos.y_offset;
+      break;
+    case HB_DIRECTION_INVALID:
+    default:
+      break;
+  }
+  return ret;
+}
 #endif
+
+
+#endif

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h	2022-10-08 21:59:08 UTC (rev 64657)
@@ -403,7 +403,17 @@
 			      unsigned int    *range_start,       /* OUT.  May be NULL */
 			      unsigned int    *range_end          /* OUT.  May be NULL */);
 
+HB_EXTERN hb_position_t
+hb_ot_layout_lookup_get_optical_bound (hb_font_t      *font,
+				       unsigned        lookup_index,
+				       hb_direction_t  direction,
+				       hb_codepoint_t  glyph);
 
+
+/*
+ * GSUB/GPOS
+ */
+
 HB_EXTERN hb_bool_t
 hb_ot_layout_feature_get_name_ids (hb_face_t       *face,
 				   hb_tag_t         table_tag,
@@ -423,6 +433,7 @@
 				     unsigned int   *char_count    /* IN/OUT.  May be NULL */,
 				     hb_codepoint_t *characters    /* OUT.     May be NULL */);
 
+
 /*
  * BASE
  */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-table.hh	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-table.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -25,6 +25,7 @@
  * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
  * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
  * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
+ * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
  * # Override values For Indic_Positional_Category
  * # Not derivable
  * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
@@ -34,6 +35,7 @@
  * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
  * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
  * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
+ * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
  * UnicodeData.txt does not have a header.
  */
 
@@ -90,7 +92,7 @@
 #pragma GCC diagnostic pop
 
 static const uint8_t
-hb_use_u8[3115] =
+hb_use_u8[3141] =
 {
      16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   51,   57,   58,  179,  195,   61,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
@@ -125,11 +127,11 @@
       2,    2,    2,    2,    2,    2,    2,    2,    2,   88,   89,    2,    2,    2,    2,    2,
       2,    2,    2,   90,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-      2,    2,    2,   91,    2,    2,   92,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-      2,    2,    2,   93,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-      2,   94,   94,   95,   96,   94,   94,   94,   94,   94,   94,   94,   94,   94,   94,   94,
-     94,   94,   94,   94,   94,   94,   94,   94,   94,   94,   94,   94,   94,   94,   94,   94,
-     94,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,
+      2,    2,    2,   91,    2,    2,   92,    2,    2,    2,   93,    2,    2,    2,    2,    2,
+      2,    2,    2,   94,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+      2,   95,   95,   96,   97,   95,   95,   95,   95,   95,   95,   95,   95,   95,   95,   95,
+     95,   95,   95,   95,   95,   95,   95,   95,   95,   95,   95,   95,   95,   95,   95,   95,
+     95,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,
       0,    2,    2,    2,    2,    2,    0,    0,    0,    3,    0,    0,    0,    0,    0,    4,
       0,    0,    5,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,
       0,    0,    0,    0,    0,    0,    0,    0,    6,    7,    0,    0,    0,    0,    0,    0,
@@ -226,70 +228,72 @@
       0,    9,   47,    2,    2,    2,    2,    2,    2,    2,    2,    2,  125,   18,   20,  151,
      20,   19,  152,  153,    2,    2,    2,    2,    2,    0,    0,   63,  154,    0,    0,    0,
       0,    2,   11,    0,    0,    0,    0,    0,    0,    2,   63,   23,   18,   18,   18,   20,
-     20,  106,  155,    0,    0,  156,  157,   29,  158,   28,    2,    2,    2,    2,    2,    2,
-      2,    2,    2,    2,    2,    2,    2,   21,   17,   20,   20,  159,   42,    0,    0,    0,
+     20,  106,  155,    0,    0,   54,  156,   29,  157,   28,    2,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,    2,    2,   21,   17,   20,   20,  158,   42,    0,    0,    0,
      47,  125,    0,    0,    0,    0,    0,    0,    0,    2,    2,    2,    7,    7,    2,    2,
      28,    2,    2,    2,    2,    2,    2,    2,   28,    2,    2,    2,    2,    2,    2,    2,
-      8,   16,   17,   19,   20,  160,   29,    0,    0,    9,    9,   28,    2,    2,    2,    7,
+      8,   16,   17,   19,   20,  159,   29,    0,    0,    9,    9,   28,    2,    2,    2,    7,
      28,    7,    2,   28,    2,    2,   56,   15,   21,   14,   21,   45,   30,   31,   30,   32,
       0,    0,    0,    0,   33,    0,    0,    0,    2,    2,   21,    0,    9,    9,    9,   44,
       0,    9,    9,   44,    0,    0,    0,    0,    0,    2,    2,   63,   23,   18,   18,   18,
      20,   21,  123,   13,   15,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,    0,
-    161,  162,    0,    0,    0,    0,    0,    0,    0,   16,   17,   18,   18,   64,   97,   23,
-    158,    9,  163,    7,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,    2,
-     63,   23,   18,   18,    0,   46,   46,    9,  164,   35,    0,    0,    0,    0,    0,    0,
+    160,  161,    0,    0,    0,    0,    0,    0,    0,   16,   17,   18,   18,   64,   97,   23,
+    157,    9,  162,    7,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,    2,
+     63,   23,   18,   18,    0,   46,   46,    9,  163,   35,    0,    0,    0,    0,    0,    0,
       0,    0,    0,    0,    0,    2,    2,   18,    0,   21,   17,   18,   18,   19,   14,   80,
-    164,   36,    0,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    8,  165,
-     23,   18,   20,   20,  163,    7,    0,    0,    0,    2,    2,    2,    2,    2,    7,   41,
+    163,   36,    0,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    8,  164,
+     23,   18,   20,   20,  162,    7,    0,    0,    0,    2,    2,    2,    2,    2,    7,   41,
     133,   21,   20,   18,   74,   19,   20,    0,    0,    2,    2,    2,    7,    0,    0,    0,
-      0,    2,    2,    2,    2,    2,    2,   16,   17,   18,   19,   20,  103,  164,   35,    0,
+      0,    2,    2,    2,    2,    2,    2,   16,   17,   18,   19,   20,  103,  163,   35,    0,
       0,    2,    2,    2,    7,   28,    0,    2,    2,    2,    2,   28,    7,    2,    2,    2,
-      2,   21,   21,   16,   30,   31,   10,  166,  167,  168,  169,    0,    0,    0,    0,    0,
+      2,   21,   21,   16,   30,   31,   10,  165,  166,  167,  168,    0,    0,    0,    0,    0,
       0,    2,    2,    2,    2,    0,    2,    2,    2,   63,   23,   18,   18,    0,   20,   21,
      27,  106,    0,   31,    0,    0,    0,    0,    0,   50,   18,   20,   20,   20,  137,    2,
-      2,    2,  170,  171,    9,   13,  172,   70,  173,    0,    0,    1,  144,    0,    0,    0,
-      0,   50,   18,   20,   14,   17,   18,    2,    2,    2,    2,  155,  155,  155,  174,  174,
-    174,  174,  174,  174,   13,  175,    0,   28,    0,   20,   18,   18,   29,   20,   20,    9,
-    164,    0,   59,   59,   59,   59,   59,   59,   59,   64,   19,   80,   44,    0,    0,    0,
+      2,    2,  169,  170,    9,   13,  171,   70,  172,    0,    0,    1,  144,    0,    0,    0,
+      0,   50,   18,   20,   14,   17,   18,    2,    2,    2,    2,  155,  155,  155,  173,  173,
+    173,  173,  173,  173,   13,  174,    0,   28,    0,   20,   18,   18,   29,   20,   20,    9,
+    163,    0,   59,   59,   59,   59,   59,   59,   59,   64,   19,   80,   44,    0,    0,    0,
       0,    2,    2,    2,    7,    2,   28,    2,    2,   50,   20,   20,   29,    0,   36,   20,
-     25,    9,  157,  176,  172,    0,    0,    0,    0,    2,    2,    2,   28,    7,    2,    2,
+     25,    9,  156,  175,  171,    0,    0,    0,    0,    2,    2,    2,   28,    7,    2,    2,
       2,    2,    2,    2,    2,    2,   21,   21,   45,   20,   33,   80,   66,    0,    0,    0,
-      0,    2,  177,   64,   45,    0,    0,    0,    0,    9,  178,    2,    2,    2,    2,    2,
+      0,    2,  176,   64,   45,    0,    0,    0,    0,    9,  177,    2,    2,    2,    2,    2,
       2,    2,    2,   21,   20,   18,   29,    0,   46,   14,  140,    0,    0,    0,    0,    0,
-      0,  179,  179,  179,  106,    7,    0,    0,    0,    9,    9,    9,   44,    0,    0,    0,
-      0,    2,    2,    2,    2,    2,    7,    0,   56,  180,   18,   18,   18,   18,   18,   18,
+      0,  178,  178,  178,  106,  179,  178,    0,    0,  145,    2,    2,  180,  114,  114,  114,
+    114,  114,  114,  114,    0,    0,    0,    0,    0,    9,    9,    9,   44,    0,    0,    0,
+      0,    2,    2,    2,    2,    2,    7,    0,   56,  181,   18,   18,   18,   18,   18,   18,
      18,   18,   18,   18,   18,   18,   18,   18,   18,   18,   18,   18,   18,    0,    0,    0,
      38,  114,   24,    0,    0,    0,    0,    0,    0,    0,    0,    7,    0,    0,    0,    0,
       0,    2,    2,    2,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,   56,
      35,    0,    4,  118,  118,  118,  119,    0,    0,    9,    9,    9,   47,    2,    2,    2,
       0,    2,    2,    2,    2,    2,    0,    0,    2,    2,    2,    2,    2,    2,    2,    2,
-     44,    2,    2,    2,    2,    2,    2,    9,    9,    2,    2,   42,   42,   42,   90,    0,
-      0,    O,    O,    O,   GB,    B,    B,   GB,    O,    O,   WJ,FMPst,FMPst,    O,  CGJ,    B,
-      O,    B,VMAbv,VMAbv,VMAbv,    O,VMAbv,    B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,
-      B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst,    H, VPre,
-   VPst,VMBlw,    O,    O, VAbv,   GB,VMAbv,VMPst,VMPst,    O,    B, VBlw,    O,    O, VPre, VPre,
-      O, VPre,    H,    O, VPst,FMAbv,    O,CMBlw,    O, VAbv,    O, VAbv,    H,    O,VMBlw,VMAbv,
-  CMAbv,   GB,   GB,    O, MBlw,CMAbv,CMAbv, VPst, VAbv,VMAbv,    O, VPst,    O, VPre, VPre,VMAbv,
-      B,    O,   CS,   CS,VMPst,    B, VAbv, VAbv,    B,    R,    O,  HVM,    O,    O, FBlw,    O,
-  CMAbv,    O,CMBlw, VAbv, VBlw,    B,  SUB,  SUB,  SUB,    O,  SUB,  SUB,    O, FBlw,    O,    B,
-   VPst, VBlw, VPre,VMAbv,VMBlw,VMPst,   IS, VAbv, MPst, MPre, MBlw, MBlw,    B, MBlw, MBlw, VPst,
-  VMPst,VMPst,    B, MBlw, VPst, VPre, VAbv, VAbv,VMPst,VMPst,VMBlw,    B,VMPst, VBlw, VPst,  CGJ,
-    CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv,   IS,FMAbv,    B,FMAbv,    B,
-    CGJ,   WJ,  CGJ,   GB,CMAbv,CMAbv,    B,   GB,    B, VAbv,  SUB, FPst, FPst,VMBlw, FPst, FPst,
-   FBlw,VMAbv,FMBlw, VAbv, VPre,    B, MPre, MBlw,  SUB, FAbv, FAbv, MAbv,  SUB,   Sk, VPst, VAbv,
-  VMAbv,VMAbv, FAbv,CMAbv, VPst,    H,    B,    O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst,   IS, VBlw,
-   FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,   CS,    O,FMAbv, ZWNJ,  CGJ,   WJ,   WJ,   WJ,
-      O,FMPst,    O,    O,    H, MPst, VPst,    H,VMAbv, VAbv,VMBlw,    B, VBlw, FPst, VPst, FAbv,
-  VMPst,    B,CMAbv, VAbv, MBlw, MPst, MBlw,    H,    O, VBlw, MPst, MPre, MAbv, MBlw,    O,    B,
-   FAbv, FAbv, FPst, VBlw,    B,    B, VPre,    O,VMPst,   IS,    O,VMPst, VBlw, VPst,VMBlw,VMBlw,
-  VMAbv,    O,   IS,VMBlw,    B,VMPst,VMAbv,VMPst,   CS,   CS,    B,    N,    N,    O,   HN, VPre,
-   VBlw, VAbv,   IS,CMAbv,    O, VPst,    B,    R,    R,    O,FMBlw,CMBlw, VAbv, VPre,VMAbv,VMAbv,
-      H, VAbv,CMBlw,FMAbv,    B,   CS,   CS,    H,CMBlw,VMPst,    H,VMPst, VAbv,VMAbv, VPst,   IS,
-      R, MPst,    R, MPst,CMBlw,    B,FMBlw, VBlw,VMAbv,    R, MBlw, MBlw,   GB, FBlw, FBlw,CMAbv,
-     IS, VBlw,   IS,   GB, VAbv,    R,VMPst,    H,    H,    O, VBlw,
+     44,    2,    2,    2,    2,    2,    2,    9,    9,    2,    2,    2,    2,    2,    2,   20,
+     20,    2,    2,   42,   42,   42,   90,    0,    0,    O,    O,    O,   GB,    B,    B,   GB,
+      O,    O,   WJ,FMPst,FMPst,    O,  CGJ,    B,    O,    B,VMAbv,VMAbv,VMAbv,    O,VMAbv,    B,
+  CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,    B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw,
+   VAbv, VAbv, VAbv, VPst, VPst, VPst,    H, VPre, VPst,VMBlw,    O,    O, VAbv,   GB,VMAbv,VMPst,
+  VMPst,    O,    B, VBlw,    O,    O, VPre, VPre,    O, VPre,    H,    O, VPst,FMAbv,    O,CMBlw,
+      O, VAbv,    O, VAbv,    H,    O,VMBlw,VMAbv,CMAbv,   GB,   GB,    O, MBlw,CMAbv,CMAbv, VPst,
+   VAbv,VMAbv,    O, VPst,    O, VPre, VPre,VMAbv,    B,    O,   CS,   CS,VMPst,    B, VAbv, VAbv,
+      B,    R,    O,  HVM,    O,    O,FMBlw,    O,CMAbv,    O,CMBlw, VAbv, VBlw,    B,  SUB,  SUB,
+    SUB,    O,  SUB,  SUB,    O,FMBlw,    O,    B, VPst, VBlw, VPre,VMAbv,VMBlw,VMPst,   IS, VAbv,
+   MPst, MPre, MBlw, MBlw,    B, MBlw, MBlw, VPst,VMPst,VMPst,    B, MBlw, VPst, VPre, VAbv, VAbv,
+  VMPst,VMPst,VMBlw,    B,VMPst, VBlw, VPst,  CGJ,  CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,
+  VMAbv,FMAbv, VAbv,   IS,FMAbv,    B,FMAbv,    B,  CGJ,   WJ,  CGJ,   GB,CMAbv,CMAbv,    B,   GB,
+      B, VAbv,  SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre,    B, MPre, MBlw,
+    SUB, FAbv, FAbv, MAbv,  SUB,   Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst,    H,    B,    O,
+  SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst,   IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,
+     CS,    O,FMAbv, ZWNJ,  CGJ,   WJ,   WJ,   WJ,    O,FMPst,    O,    O,    H, MPst, VPst,    H,
+  VMAbv, VAbv,VMBlw,    B, VBlw, FPst, VPst, FAbv,VMPst,    B,CMAbv, VAbv, MBlw, MPst, MBlw,    H,
+      O, VBlw, MPst, MPre, MAbv, MBlw,    O,    B, FAbv, FAbv, FPst, VBlw,    B,    B, VPre,    O,
+  VMPst,   IS,    O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv,    O,   IS,VMBlw,    B,VMPst,VMAbv,VMPst,
+     CS,   CS,    B,    N,    N,    O,   HN, VPre, VBlw, VAbv,   IS,CMAbv,    O, VPst,    B,    R,
+      R,CMBlw, VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,FMAbv,    B,   CS,   CS,    H,CMBlw,VMPst,
+      H,VMPst, VAbv,VMAbv, VPst,   IS,    R, MPst,    R, MPst,CMBlw,    B,FMBlw, VBlw,VMAbv,    R,
+   MBlw, MBlw,   GB, FBlw, FBlw,CMAbv,   IS, VBlw,   IS,   GB, VAbv,    R,VMPst,    H,    H,    B,
+      H,    B,VMBlw,    O, VBlw,
 };
 static const uint16_t
-hb_use_u16[776] =
+hb_use_u16[784] =
 {
     0,  0,  1,  2,  0,  0,  0,  0,  0,  0,  3,  4,  0,  5,  0,  0,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,
@@ -332,14 +336,14 @@
     9,242, 73,243,  0,  0,  0,  0,244,  9,  9,245,246,  2,247,  9,
   248,249,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,250,
   251, 48,  9,252,253,  2,  0,  0,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9, 98,254,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,
-    9,  9,  9,255,  0,  0,  0,  0,  9,  9,  9,  9,256,257,258,258,
-  259,260,  0,  0,  0,  0,261,  0,  9,  9,  9,  9,  9,262,  0,  0,
-    9,  9,  9,  9,  9,  9,105, 70, 94,263,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,264,  9,  9, 70,265,266,  0,  0,  0,
-    0,  9,267,  0,  9,  9,268,  2,  9,  9,  9,  9,269,  2,  0,  0,
-  129,129,129,129,129,129,129,129,160,160,160,160,160,160,160,160,
-  160,160,160,160,160,160,160,129,
+    9,  9,  9,254,255,256,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,
+    9,  9,  9,257,  0,  0,  0,  0,  9,  9,  9,  9,258,259,260,260,
+  261,262,  0,  0,  0,  0,263,  0,  9,  9,  9,  9,  9,264,  0,  0,
+    9,  9,  9,  9,  9,  9,105, 70, 94,265,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,266,  9,  9, 70,267,268,  0,  0,  0,
+    0,  9,269,  0,  9,  9,270,  2,  0,  0,  0,  0,  0,  9,271,  2,
+    9,  9,  9,  9,272,  2,  0,  0,129,129,129,129,129,129,129,129,
+  160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,129,
 };
 
 static inline unsigned
@@ -350,7 +354,7 @@
 static inline uint_fast8_t
 hb_use_get_category (unsigned u)
 {
-  return u<921600u?hb_use_u8[2753+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+  return u<921600u?hb_use_u8[2777+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
 }
 
 #undef B

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-vowel-constraints.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-vowel-constraints.cc	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-vowel-constraints.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -342,6 +342,40 @@
       }
       break;
 
+    case HB_SCRIPT_KHOJKI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+	bool matched = false;
+	switch (buffer->cur ().codepoint)
+	{
+	  case 0x11200u:
+	    switch (buffer->cur (1).codepoint)
+	    {
+	      case 0x1122Cu: case 0x11231u: case 0x11233u:
+		matched = true;
+		break;
+	    }
+	    break;
+	  case 0x11206u:
+	    matched = 0x1122Cu == buffer->cur (1).codepoint;
+	    break;
+	  case 0x1122Cu:
+	    switch (buffer->cur (1).codepoint)
+	    {
+	      case 0x11230u: case 0x11231u:
+		matched = true;
+		break;
+	    }
+	    break;
+	  case 0x11240u:
+	    matched = 0x1122Eu == buffer->cur (1).codepoint;
+	    break;
+	}
+	(void) buffer->next_glyph ();
+	if (matched) _output_with_dotted_circle (buffer);
+      }
+      break;
+
     case HB_SCRIPT_KHUDAWADI:
       for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
       {

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -47,6 +47,44 @@
   hb_array_t<const HBFixed> get_coordinates (unsigned int axis_count) const
   { return coordinatesZ.as_array (axis_count); }
 
+  bool subset (hb_subset_context_t *c,
+               unsigned axis_count,
+               bool has_postscript_nameid) const
+  {
+    TRACE_SUBSET (this);
+    if (unlikely (!c->serializer->embed (subfamilyNameID))) return_trace (false);
+    if (unlikely (!c->serializer->embed (flags))) return_trace (false);
+
+    const hb_array_t<const HBFixed> coords = get_coordinates (axis_count);
+    const hb_hashmap_t<hb_tag_t, float> *axes_location = c->plan->user_axes_location;
+    for (unsigned i = 0 ; i < axis_count; i++)
+    {
+      unsigned *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) &&
+          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);
+    }
+
+    if (has_postscript_nameid)
+    {
+      NameID name_id;
+      name_id = StructAfter<NameID> (coords);
+      if (!c->serializer->embed (name_id))
+        return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
   bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
   {
     TRACE_SANITIZE (this);
@@ -321,6 +359,48 @@
     }
   }
 
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    unsigned retained_axis_count = c->plan->axes_index_map->get_population ();
+    if (!retained_axis_count) //all axes are pinned
+      return_trace (false);
+
+    fvar *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    if (!c->serializer->check_assign (out->axisCount, retained_axis_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+      return_trace (false);
+
+    bool has_postscript_nameid = false;
+    if (instanceSize >= axisCount * 4 + 6)
+      has_postscript_nameid = true;
+
+    if (!c->serializer->check_assign (out->instanceSize, retained_axis_count * 4 + (has_postscript_nameid ? 6 : 4),
+                                      HB_SERIALIZE_ERROR_INT_OVERFLOW))
+      return_trace (false);
+
+    auto axes_records = get_axes ();
+    for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
+    {
+      if (!c->plan->axes_index_map->has (i)) continue;
+      if (unlikely (!c->serializer->embed (axes_records[i])))
+        return_trace (false);
+    }
+
+    if (!c->serializer->check_assign (out->firstAxis, get_size (), HB_SERIALIZE_ERROR_INT_OVERFLOW))
+      return_trace (false);
+
+    for (unsigned i = 0 ; i < (unsigned)instanceCount; i++)
+    {
+      const InstanceRecord *instance = get_instance (i);
+      auto snap = c->serializer->snapshot ();
+      if (!instance->subset (c, axisCount, has_postscript_nameid))
+        c->serializer->revert (snap);
+    }
+    return_trace (true);
+  }
+
   public:
   hb_array_t<const AxisRecord> get_axes () const
   { return hb_array (&(this+firstAxis), axisCount); }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -244,7 +244,7 @@
     {
       // The child object is shared, we may be able to eliminate the overflow
       // by duplicating it.
-      if (!sorted_graph.duplicate (r.parent, r.child)) continue;
+      if (sorted_graph.duplicate (r.parent, r.child) == (unsigned) -1) continue;
       return true;
     }
 

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -89,7 +89,6 @@
 
   hb_tag_t default_no_subset_tables[] = {
     HB_TAG ('a', 'v', 'a', 'r'),
-    HB_TAG ('f', 'v', 'a', 'r'),
     HB_TAG ('g', 'a', 's', 'p'),
     HB_TAG ('c', 'v', 't', ' '),
     HB_TAG ('f', 'p', 'g', 'm'),

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -129,7 +129,9 @@
 static void _collect_layout_indices (hb_subset_plan_t     *plan,
                                      const T&              table,
                                      hb_set_t		  *lookup_indices, /* OUT */
-                                     hb_set_t		  *feature_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 */)
 {
   unsigned num_features = table.get_feature_count ();
   hb_vector_t<hb_tag_t> features;
@@ -154,16 +156,37 @@
                                  retain_all_features ? nullptr : features.arrayZ,
                                  feature_indices);
 
+#ifndef HB_NO_VAR
+  // collect feature substitutes with variations
+  if (!plan->user_axes_location->is_empty ())
+  {
+    hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> conditionset_map;
+    OT::hb_collect_feature_substitutes_with_var_context_t c =
+    {
+      plan->axes_old_index_tag_map,
+      plan->axes_location,
+      feature_record_cond_idx_map,
+      feature_substitutes_map,
+      feature_indices,
+      true,
+      0,
+      &conditionset_map
+    };
+    table.collect_feature_substitutes_with_variations (&c);
+  }
+#endif
+
   for (unsigned feature_index : *feature_indices)
   {
-    //TODO: replace HB_OT_LAYOUT_NO_VARIATIONS_INDEX with variation_index for
-    //instancing
-    const OT::Feature &f = table.get_feature_variation (feature_index, HB_OT_LAYOUT_NO_VARIATIONS_INDEX);
-    f.add_lookup_indexes_to (lookup_indices);
+    const OT::Feature* f = &(table.get_feature (feature_index));
+    const OT::Feature **p = nullptr;
+    if (feature_substitutes_map->has (feature_index, &p))
+      f = *p;
+
+    f->add_lookup_indexes_to (lookup_indices);
   }
 
-  //TODO: update for instancing: only collect lookups from feature_indexes that have no variations
-  table.feature_variation_collect_lookups (feature_indices, lookup_indices);
+  table.feature_variation_collect_lookups (feature_indices, feature_substitutes_map, lookup_indices);
 }
 
 
@@ -171,6 +194,7 @@
 _GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
 				   const hb_map_t *lookup_indices,
 				   const hb_set_t *feature_indices,
+				   const hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
 				   hb_map_t *duplicate_feature_map /* OUT */)
 {
   if (feature_indices->is_empty ()) return;
@@ -195,16 +219,22 @@
     hb_set_t* same_tag_features = unique_features.get (t);
     for (unsigned other_f_index : same_tag_features->iter ())
     {
-      const OT::Feature& f = g.get_feature (i);
-      const OT::Feature& other_f = g.get_feature (other_f_index);
+      const OT::Feature* f = &(g.get_feature (i));
+      const OT::Feature **p = nullptr;
+      if (feature_substitutes_map->has (i, &p))
+        f = *p;
 
+      const OT::Feature* other_f = &(g.get_feature (other_f_index));
+      if (feature_substitutes_map->has (other_f_index, &p))
+        f = *p;
+
       auto f_iter =
-      + hb_iter (f.lookupIndex)
+      + hb_iter (f->lookupIndex)
       | hb_filter (lookup_indices)
       ;
 
       auto other_f_iter =
-      + hb_iter (other_f.lookupIndex)
+      + hb_iter (other_f->lookupIndex)
       | hb_filter (lookup_indices)
       ;
 
@@ -237,7 +267,9 @@
 				  hb_set_t	     *gids_to_retain,
 				  hb_map_t	     *lookups,
 				  hb_map_t	     *features,
-				  script_langsys_map *langsys_map)
+				  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_blob_ptr_t<T> table = plan->source_table<T> ();
   hb_tag_t table_tag = table->tableTag;
@@ -245,7 +277,9 @@
   _collect_layout_indices<T> (plan,
                               *table,
                               &lookup_indices,
-                              &feature_indices);
+                              &feature_indices,
+                              feature_record_cond_idx_map,
+                              feature_substitutes_map);
 
   if (table_tag == HB_OT_TAG_GSUB)
     hb_ot_layout_lookups_substitute_closure (plan->source,
@@ -257,9 +291,12 @@
   _remap_indexes (&lookup_indices, lookups);
 
   // prune features
-  table->prune_features (lookups, &feature_indices);
+  table->prune_features (lookups,
+                         plan->user_axes_location->is_empty () ? nullptr : feature_record_cond_idx_map,
+                         feature_substitutes_map,
+                         &feature_indices);
   hb_map_t duplicate_feature_map;
-  _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, &duplicate_feature_map);
+  _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map);
 
   feature_indices.clear ();
   table->prune_langsys (&duplicate_feature_map, plan->layout_scripts, langsys_map, &feature_indices);
@@ -509,9 +546,7 @@
 
 static void
 _populate_gids_to_retain (hb_subset_plan_t* plan,
-			  bool close_over_gsub,
-			  bool close_over_gpos,
-			  bool close_over_gdef)
+		          hb_set_t* drop_tables)
 {
   OT::glyf_accelerator_t glyf (plan->source);
 #ifndef HB_NO_SUBSET_CFF
@@ -523,7 +558,7 @@
   _cmap_closure (plan->source, plan->unicodes, plan->_glyphset_gsub);
 
 #ifndef HB_NO_SUBSET_LAYOUT
-  if (close_over_gsub)
+  if (!drop_tables->has (HB_OT_TAG_GSUB))
     // closure all glyphs/lookups/features needed for GSUB substitutions.
     _closure_glyphs_lookups_features<GSUB> (
         plan,
@@ -530,25 +565,35 @@
         plan->_glyphset_gsub,
         plan->gsub_lookups,
         plan->gsub_features,
-        plan->gsub_langsys);
+        plan->gsub_langsys,
+        plan->gsub_feature_record_cond_idx_map,
+        plan->gsub_feature_substitutes_map);
 
-  if (close_over_gpos)
+  if (!drop_tables->has (HB_OT_TAG_GPOS))
     _closure_glyphs_lookups_features<GPOS> (
         plan,
         plan->_glyphset_gsub,
         plan->gpos_lookups,
         plan->gpos_features,
-        plan->gpos_langsys);
+        plan->gpos_langsys,
+        plan->gpos_feature_record_cond_idx_map,
+        plan->gpos_feature_substitutes_map);
 #endif
   _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
 
   hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
-  _math_closure (plan, plan->_glyphset_mathed);
-  _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
+  if (!drop_tables->has (HB_OT_TAG_MATH))
+  {
+    _math_closure (plan, plan->_glyphset_mathed);
+    _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
+  }
 
   hb_set_t cur_glyphset = *plan->_glyphset_mathed;
-  _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
-  _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
+  if (!drop_tables->has (HB_OT_TAG_COLR))
+  {
+    _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
+    _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
+  }
 
   hb_set_set (plan->_glyphset_colred, &cur_glyphset);
 
@@ -570,7 +615,7 @@
 
 
 #ifndef HB_NO_VAR
-  if (close_over_gdef)
+  if (!drop_tables->has (HB_OT_TAG_GDEF))
     _collect_layout_variation_indices (plan);
 #endif
 }
@@ -659,18 +704,22 @@
     seg_maps = face->table.avar->get_segment_maps ();
 
   bool axis_not_pinned = false;
-  unsigned axis_count = 0;
+  unsigned old_axis_idx = 0, new_axis_idx = 0;
   for (const auto& axis : axes)
   {
     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))
     {
       axis_not_pinned = true;
+      plan->axes_index_map->set (old_axis_idx, new_axis_idx);
+      new_axis_idx++;
     }
     else
     {
       int normalized_v = axis.normalize_axis_value (plan->user_axes_location->get (axis_tag));
-      if (has_avar && axis_count < face->table.avar->get_axis_count ())
+      if (has_avar && old_axis_idx < face->table.avar->get_axis_count ())
       {
         normalized_v = seg_maps->map (normalized_v);
       }
@@ -680,8 +729,8 @@
     }
     if (has_avar)
       seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
-
-    axis_count++;
+    
+    old_axis_idx++;
   }
   plan->all_axes_pinned = !axis_not_pinned;
 }
@@ -741,6 +790,13 @@
 
   plan->gsub_features = hb_map_create ();
   plan->gpos_features = hb_map_create ();
+
+  plan->check_success (plan->gsub_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ());
+  plan->check_success (plan->gpos_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ());
+
+  plan->check_success (plan->gsub_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
+  plan->check_success (plan->gpos_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
+
   plan->colrv1_layers = hb_map_create ();
   plan->colr_palettes = hb_map_create ();
   plan->check_success (plan->layout_variation_idx_delta_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
@@ -751,6 +807,8 @@
   plan->check_success (plan->user_axes_location = hb_hashmap_create<hb_tag_t, float> ());
   if (plan->user_axes_location && input->axes_location)
       *plan->user_axes_location = *input->axes_location;
+  plan->check_success (plan->axes_index_map = hb_map_create ());
+  plan->check_success (plan->axes_old_index_tag_map = hb_map_create ());
   plan->all_axes_pinned = false;
   plan->pinned_at_default = true;
 
@@ -768,10 +826,7 @@
 
   _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
 
-  _populate_gids_to_retain (plan,
-			    !input->sets.drop_tables->has (HB_OT_TAG_GSUB),
-			    !input->sets.drop_tables->has (HB_OT_TAG_GPOS),
-			    !input->sets.drop_tables->has (HB_OT_TAG_GDEF));
+  _populate_gids_to_retain (plan, input->sets.drop_tables);
 
   _create_old_gid_to_new_gid_map (face,
                                   input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,

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	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh	2022-10-08 21:59:08 UTC (rev 64657)
@@ -36,6 +36,10 @@
 #include "hb-bimap.hh"
 #include "hb-set.hh"
 
+namespace OT {
+struct Feature;
+}
+
 struct hb_subset_plan_t
 {
   hb_subset_plan_t ()
@@ -67,9 +71,15 @@
     hb_map_destroy (gpos_features);
     hb_map_destroy (colrv1_layers);
     hb_map_destroy (colr_palettes);
+    hb_map_destroy (axes_index_map);
+    hb_map_destroy (axes_old_index_tag_map);
 
     hb_hashmap_destroy (gsub_langsys);
     hb_hashmap_destroy (gpos_langsys);
+    hb_hashmap_destroy (gsub_feature_record_cond_idx_map);
+    hb_hashmap_destroy (gpos_feature_record_cond_idx_map);
+    hb_hashmap_destroy (gsub_feature_substitutes_map);
+    hb_hashmap_destroy (gpos_feature_substitutes_map);
     hb_hashmap_destroy (axes_location);
     hb_hashmap_destroy (sanitized_table_cache);
     hb_hashmap_destroy (hmtx_map);
@@ -143,6 +153,15 @@
   hb_map_t *gsub_features;
   hb_map_t *gpos_features;
 
+  //active feature variation records/condition index with variations
+  hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gsub_feature_record_cond_idx_map;
+  hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gpos_feature_record_cond_idx_map;
+
+  //feature index-> address of substituation feature table mapping with
+  //variations
+  hb_hashmap_t<unsigned, const OT::Feature*> *gsub_feature_substitutes_map;
+  hb_hashmap_t<unsigned, const OT::Feature*> *gpos_feature_substitutes_map;
+
   //active layers/palettes we'd like to retain
   hb_map_t *colrv1_layers;
   hb_map_t *colr_palettes;
@@ -158,6 +177,10 @@
   hb_hashmap_t<hb_tag_t, int> *axes_location;
   //user specified axes location map
   hb_hashmap_t<hb_tag_t, float> *user_axes_location;
+  //retained old axis index -> new axis index mapping in fvar axis array
+  hb_map_t *axes_index_map;
+  //axis_index->axis_tag mapping in fvar axis array
+  hb_map_t *axes_old_index_tag_map;
   bool all_axes_pinned;
   bool pinned_at_default;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -50,6 +50,7 @@
 #include "hb-ot-color-cbdt-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-var-fvar-table.hh"
 #include "hb-ot-var-gvar-table.hh"
 #include "hb-ot-var-hvar-table.hh"
 #include "hb-ot-math-table.hh"
@@ -475,6 +476,9 @@
   case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf);
   case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf);
 #endif
+  case HB_OT_TAG_fvar:
+    if (plan->user_axes_location->is_empty ()) return _passthrough (plan, tag);
+    return _subset<const OT::fvar> (plan, buf);
   case HB_OT_TAG_STAT:
     /*TODO(qxliu): change the condition as we support more complex
      * instancing operation*/

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc	2022-10-08 21:59:08 UTC (rev 64657)
@@ -222,6 +222,23 @@
     hb::unique_ptr<hb_hashmap_t<int, int>> *v2;
     m.has (0, &v2);
   }
+  /* Test hashmap with complex shared_ptrs as keys. */
+  {
+    hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> m;
 
+    hb_map_t *m1 = hb_map_create ();
+    hb_map_t *m2 = hb_map_create ();
+    m1->set (1,3);
+    m2->set (1,3);
+
+    hb::shared_ptr<hb_map_t> p1 {m1};
+    hb::shared_ptr<hb_map_t> p2 {m2};
+    m.set (p1,1);
+    
+    assert (m.has (p2));
+
+    m1->set (2,4);
+    assert (!m.has (p2));
+  }
   return 0;
 }

Modified: trunk/Build/source/libs/harfbuzz/version.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/version.ac	2022-10-08 20:06:42 UTC (rev 64656)
+++ trunk/Build/source/libs/harfbuzz/version.ac	2022-10-08 21:59:08 UTC (rev 64657)
@@ -8,4 +8,4 @@
 dnl --------------------------------------------------------
 dnl
 dnl  m4-include this file to define the current harfbuzz version
-m4_define([harfbuzz_version], [5.2.0])
+m4_define([harfbuzz_version], [5.3.0])



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