texlive[76048] Build/source/libs: harfbuzz 11.4.1

commits+kakuto at tug.org commits+kakuto at tug.org
Thu Aug 14 00:39:52 CEST 2025


Revision: 76048
          https://tug.org/svn/texlive?view=revision&revision=76048
Author:   kakuto
Date:     2025-08-14 00:39:51 +0200 (Thu, 14 Aug 2025)
Log Message:
-----------
harfbuzz 11.4.1

Modified Paths:
--------------
    trunk/Build/source/libs/README
    trunk/Build/source/libs/harfbuzz/ChangeLog
    trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
    trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
    trunk/Build/source/libs/harfbuzz/configure
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/RELEASING.md
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CPAL/CPAL.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/LigatureArray.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/types.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/ligature-graph.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-subset.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-harfrust.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-std-str.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-macroman.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-khmer-machine.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-myanmar-machine.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-thai.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-string-array.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/Cargo.toml
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/meson.build
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/shape.rs
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-algs.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-array.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-bimap.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-cff.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-decycler.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gpos-size-params.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-would-substitute.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-item-varstore.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-multimap.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-number.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-glyphname.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-meta.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-name.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-serialize.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc
    trunk/Build/source/libs/harfbuzz/version.ac

Added Paths:
-----------
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/check-release-notes.py
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kbts.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-cff.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-color.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-layout.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-other.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-var.cc
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table.hh
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/.gitignore

Removed Paths:
-------------
    trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/Cargo.lock

Modified: trunk/Build/source/libs/README
===================================================================
--- trunk/Build/source/libs/README	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/README	2025-08-13 22:39:51 UTC (rev 76048)
@@ -28,7 +28,7 @@
   https://sourceforge.net/projects/silgraphite/files/graphite2/
   (requires C++11)
 
-harfbuzz 11.3.3 - checked 27jul25
+harfbuzz 11.4.1 - checked 14aug25
   https://github.com/harfbuzz/harfbuzz/releases/latest
 
 icu 76.1 - checked 27oct24 (requires C++17, e.g., g++13)

Modified: trunk/Build/source/libs/harfbuzz/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/ChangeLog	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/ChangeLog	2025-08-13 22:39:51 UTC (rev 76048)
@@ -1,3 +1,8 @@
+2025-08-14  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
+
+	Import harfbuzz-11.4.1.
+	* version.ac: Adjusted.
+
 2025-07-27  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
 
 	Import harfbuzz-11.3.3.

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog	2025-08-13 22:39:51 UTC (rev 76048)
@@ -1,3 +1,8 @@
+2025-08-14  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
+
+	Imported harfbuzz-11.4.1 source tree from:
+	https://github.com/harfbuzz/harfbuzz/releases/download/11.4.1/
+
 2025-07-27  Akira Kakuto  <kakuto at jcom.zaq.ne.jp>
 
 	Imported harfbuzz-11.3.3 source tree from:

Modified: trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes	2025-08-13 22:39:51 UTC (rev 76048)
@@ -1,5 +1,5 @@
-Changes applied to the harfbuzz-11.3.3/ tree as obtained from:
-	https://github.com/harfbuzz/harfbuzz/releases/download/11.3.3/
+Changes applied to the harfbuzz-11.4.1/ tree as obtained from:
+	https://github.com/harfbuzz/harfbuzz/releases/download/11.4.1/
 
 Removed:
 	.clang-format

Modified: trunk/Build/source/libs/harfbuzz/configure
===================================================================
--- trunk/Build/source/libs/harfbuzz/configure	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/configure	2025-08-13 22:39:51 UTC (rev 76048)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for harfbuzz (TeX Live) 11.3.3.
+# Generated by GNU Autoconf 2.72 for harfbuzz (TeX Live) 11.4.1.
 #
 # Report bugs to <tex-k at tug.org>.
 #
@@ -604,8 +604,8 @@
 # Identity of this package.
 PACKAGE_NAME='harfbuzz (TeX Live)'
 PACKAGE_TARNAME='harfbuzz--tex-live-'
-PACKAGE_VERSION='11.3.3'
-PACKAGE_STRING='harfbuzz (TeX Live) 11.3.3'
+PACKAGE_VERSION='11.4.1'
+PACKAGE_STRING='harfbuzz (TeX Live) 11.4.1'
 PACKAGE_BUGREPORT='tex-k at tug.org'
 PACKAGE_URL=''
 
@@ -1341,7 +1341,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) 11.3.3 to adapt to many kinds of systems.
+'configure' configures harfbuzz (TeX Live) 11.4.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1413,7 +1413,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of harfbuzz (TeX Live) 11.3.3:";;
+     short | recursive ) echo "Configuration of harfbuzz (TeX Live) 11.4.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1518,7 +1518,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-harfbuzz (TeX Live) configure 11.3.3
+harfbuzz (TeX Live) configure 11.4.1
 generated by GNU Autoconf 2.72
 
 Copyright (C) 2023 Free Software Foundation, Inc.
@@ -2075,7 +2075,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 11.3.3, which was
+It was created by harfbuzz (TeX Live) $as_me 11.4.1, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -5259,7 +5259,7 @@
 
 # Define the identity of the package.
  PACKAGE='harfbuzz--tex-live-'
- VERSION='11.3.3'
+ VERSION='11.4.1'
 
 
 # Some tools Automake needs.
@@ -5572,9 +5572,9 @@
 
 
 HB_VERSION_MAJOR=11
-HB_VERSION_MINOR=3
-HB_VERSION_MICRO=3
-HB_VERSION=11.3.3
+HB_VERSION_MINOR=4
+HB_VERSION_MICRO=1
+HB_VERSION=11.4.1
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -9426,7 +9426,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 11.3.3, which was
+This file was extended by harfbuzz (TeX Live) $as_me 11.4.1, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9494,7 +9494,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-harfbuzz (TeX Live) config.status 11.3.3
+harfbuzz (TeX Live) config.status 11.4.1
 configured by $0, generated by GNU Autoconf 2.72,
   with options \\"\$ac_cs_config\\"
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt	2025-08-13 22:39:51 UTC (rev 76048)
@@ -364,6 +364,7 @@
   add_definitions(-DHAVE_DIRECTWRITE)
   list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-directwrite.h)
   list(APPEND THIRD_PARTY_LIBS dwrite)
+  list(APPEND PC_LIBS_PRIV -ldwrite)
 endif ()
 
 if (HB_HAVE_CAIRO)

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS	2025-08-13 22:39:51 UTC (rev 76048)
@@ -1,3 +1,21 @@
+Overview of changes leading to 11.4.1
+Wednesday, August 13, 2025
+====================================
+- Fix clang compiler warnings.
+
+Overview of changes leading to 11.4.0
+Wednesday, August 13, 2025
+====================================
+- General shaping and subsetting speedups.
+- Fix in Graphite shaping backend when glyph advances became negative.
+- Subsetting improvements, pruning empty mark-attachment lookups.
+- Don't use the macro name `_S`, which is reserved by system liberaries.
+- Build fixes and speedup.
+- Add a `kbts` shaping backend that calls into the `kb_text_shape`
+  single-header shaping library. This is purely for testing and
+  performance evaluation and we do NOT recommend using it for any
+  other purposes.
+
 Overview of changes leading to 11.3.3
 Sunday, July 26, 2025
 ====================================

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md	2025-08-13 22:39:51 UTC (rev 76048)
@@ -78,7 +78,7 @@
 More presentations and papers are available on [behdad][11]'s website.
 In particular, the following _studies_ are relevant to HarfBuzz development:
 
-- 2025 - [Introducing HarfRust][22]
+- 2025 – [Introducing HarfRust][22]
 - 2025 – [Subsetting][21]
 - 2025 – [Caching][12]
 - 2025 – [`hb-decycler`][13]
@@ -119,10 +119,10 @@
 [2]: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html
 [3]: https://github.com/harfbuzz/harfbuzz/releases
 [4]: https://github.com/harfbuzz/harfbuzz
-[6]: http://behdad.org/text2024
+[6]: https://behdad.org/text2024
 [7]: https://docs.google.com/presentation/d/1x97pfbB1gbD53Yhz6-_yBUozQMVJ_5yMqqR_D-R7b7I/preview
 [8]: https://docs.google.com/presentation/d/1ySTZaXP5XKFg0OpmHZM00v5b17GSr3ojnzJekl4U8qI/preview
-[9]: http://behdad.org/download/Presentations/slippy/harfbuzz_slides.pdf
+[9]: https://behdad.org/doc/harfbuzz2009-slides.pdf
 [10]: https://docs.google.com/document/d/12jfNpQJzeVIAxoUSpk7KziyINAa1msbGliyXqguS86M/preview
 [11]: https://behdad.org/
 [12]: https://docs.google.com/document/d/1_VgObf6Je0J8byMLsi7HCQHnKo2emGnx_ib_sHo-bt4/preview

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/RELEASING.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/RELEASING.md	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/RELEASING.md	2025-08-13 22:39:51 UTC (rev 76048)
@@ -36,7 +36,6 @@
 
 - [ ] Push the commit and tag out: `git push --follow-tags`.
 
-- [ ] There should be a GitHub release automatically created,
-      but it takes a few minutes as a bot has to build it.
-      When it does, go to that release page and add description.
-      The description should be the NEWS file additions.
+- [ ] Wait a few minutes and the CI job will create a GitHub release automatically, and it will use the NEWS file additions for release description.
+      The new release will be in draft mode, check everything is fine, or make any needed edits, then publish the release.
+      The release should also automatically include Windows binaries, but they take a bit longer to build and upload.

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build	2025-08-13 22:39:51 UTC (rev 76048)
@@ -1,6 +1,6 @@
 project('harfbuzz', ['c', 'cpp'],
   meson_version: '>= 0.60.0',
-  version: '11.3.3',
+  version: '11.4.1',
   default_options: [
     'cpp_eh=none',          # Just to support msvc, we are passing -fno-exceptions also anyway
     # 'cpp_rtti=false',     # Do NOT enable, wraps inherit it and ICU needs RTTI
@@ -212,6 +212,11 @@
   harfrust_dep_found = true
 endif
 
+kbts_dep = null_dep
+if get_option('kbts').enabled()
+  kbts_dep = subproject('kbts').get_variable('kbts_dep')
+endif
+
 conf = configuration_data()
 incconfig = include_directories('.')
 
@@ -261,6 +266,10 @@
   conf.set('HAVE_HARFRUST', 1)
 endif
 
+if kbts_dep.found()
+  conf.set('HAVE_KBTS', 1)
+endif
+
 if wasm_dep.found()
   conf.set('HAVE_WASM', 1)
   conf.set('HB_WASM_MODULE_DIR', '"'+get_option('prefix')+'/'+get_option('libdir')+'/harfbuzz/wasm"')
@@ -488,11 +497,12 @@
     {'Graphite2': conf.get('HAVE_GRAPHITE2', 0) == 1,
      'WebAssembly (experimental)': conf.get('HAVE_WASM', 0) == 1,
     },
-  'Platform shapers (not normally needed)':
+  'Platform / other shapers (not normally needed)':
     {'CoreText': conf.get('HAVE_CORETEXT', 0) == 1,
      'DirectWrite': conf.get('HAVE_DIRECTWRITE', 0) == 1,
      'GDI/Uniscribe': (conf.get('HAVE_GDI', 0) == 1) and (conf.get('HAVE_UNISCRIBE', 0) == 1),
      'HarfRust': conf.get('HAVE_HARFRUST', 0) == 1,
+     'kbts': conf.get('HAVE_KBTS', 0) == 1,
     },
   'Other features':
     {'Utilities': not get_option('utilities').disabled(),

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt	2025-08-13 22:39:51 UTC (rev 76048)
@@ -25,6 +25,8 @@
   description: 'Enable CoreText shaper and font backend on Apple platforms')
 option('harfrust', type: 'feature', value: 'disabled',
   description: 'Enable HarfRust shaper backend')
+option('kbts', type: 'feature', value: 'disabled',
+  description: 'Enable kb_text_shape backend')
 option('wasm', type: 'feature', value: 'disabled',
   description: 'Enable WebAssembly shaper backend (experimental)')
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -178,7 +178,10 @@
   { glyphs->add (glyph_id); }
 
   void add_layer_indices (unsigned first_layer_index, unsigned num_of_layers)
-  { layer_indices->add_range (first_layer_index, first_layer_index + num_of_layers - 1); }
+  {
+    if (num_of_layers == 0) return;
+    layer_indices->add_range (first_layer_index, first_layer_index + num_of_layers - 1);
+  }
 
   void add_palette_index (unsigned palette_index)
   { palette_indices->add (palette_index); }
@@ -650,10 +653,10 @@
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (this);
     if (unlikely (!out)) return_trace (false);
-    return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers.get (firstLayerIndex),
+
+    uint32_t first_layer_index = numLayers ? c->plan->colrv1_layers.get (firstLayerIndex) : 0;
+    return_trace (c->serializer->check_assign (out->firstLayerIndex, first_layer_index,
                                                HB_SERIALIZE_ERROR_INT_OVERFLOW));
-
-    return_trace (true);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CPAL/CPAL.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CPAL/CPAL.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CPAL/CPAL.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -307,6 +307,7 @@
       if (first_color_to_layer_index.has (first_color_record_idx)) continue;
 
       first_color_index_for_layer.push (first_color_record_idx);
+      if (unlikely (!c->serializer->propagate_error (first_color_index_for_layer))) return_trace (false);
       first_color_to_layer_index.set (first_color_record_idx,
                                       first_color_index_for_layer.length - 1);
     }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -97,12 +97,17 @@
     }
   }
   unsigned int get_coverage (hb_codepoint_t glyph_id,
-			     hb_ot_lookup_cache_t *cache) const
+			     hb_ot_layout_mapping_cache_t *cache) const
   {
     unsigned coverage;
-    if (cache && cache->get (glyph_id, &coverage)) return coverage;
+    if (cache && cache->get (glyph_id, &coverage)) return coverage < cache->MAX_VALUE ? coverage : NOT_COVERED;
     coverage = get_coverage (glyph_id);
-    if (cache) cache->set (glyph_id, coverage);
+    if (cache) {
+      if (coverage == NOT_COVERED)
+	cache->set_unchecked (glyph_id, cache->MAX_VALUE);
+      else if (likely (coverage < cache->MAX_VALUE))
+	cache->set_unchecked (glyph_id, coverage);
+    }
     return coverage;
   }
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -977,7 +977,7 @@
       }
 
 #ifndef HB_NO_GDEF_CACHE
-      table->get_mark_glyph_sets ().collect_coverage (mark_glyph_set_digests);
+      table->get_mark_glyph_sets ().collect_coverage (mark_glyph_sets);
 #endif
     }
     ~accelerator_t () { table.destroy (); }
@@ -1006,14 +1006,16 @@
     {
       return
 #ifndef HB_NO_GDEF_CACHE
-	     mark_glyph_set_digests[set_index].may_have (glyph_id) &&
+	     mark_glyph_sets[set_index].may_have (glyph_id)
+#else
+	     table->mark_set_covers (set_index, glyph_id)
 #endif
-	     table->mark_set_covers (set_index, glyph_id);
+      ;
     }
 
     hb_blob_ptr_t<GDEF> table;
 #ifndef HB_NO_GDEF_CACHE
-    hb_vector_t<hb_set_digest_t> mark_glyph_set_digests;
+    hb_vector_t<hb_bit_set_t> mark_glyph_sets;
     mutable hb_cache_t<21, 3> glyph_props_cache;
     static_assert (sizeof (glyph_props_cache) == 512, "");
 #endif

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -77,6 +77,13 @@
 
     return_trace (true);
   }
+
+  bool offset_is_null (unsigned row, unsigned col, unsigned num_cols) const
+  {
+    if (unlikely (row >= rows || col >= num_cols)) return true;
+    auto &offset = matrixZ[row * num_cols + col];
+    return offset.is_null ();
+  }
 };
 
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/LigatureArray.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/LigatureArray.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/LigatureArray.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -19,10 +19,11 @@
   bool subset (hb_subset_context_t *c,
                Iterator             coverage,
                unsigned             class_count,
-               const hb_map_t      *klass_mapping) const
+               const hb_map_t      *klass_mapping,
+               hb_sorted_vector_t<hb_codepoint_t> &new_coverage /* OUT */) const
   {
     TRACE_SUBSET (this);
-    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+    const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
 
     auto *out = c->serializer->start_embed (this);
     if (unlikely (!c->serializer->extend_min (out)))  return_trace (false);
@@ -29,12 +30,19 @@
 
     bool ret = false;
     for (const auto _ : + hb_zip (coverage, *this)
-                  | hb_filter (glyphset, hb_first))
+                        | hb_filter (glyph_map, hb_first))
     {
+      const LigatureAttach& src = (this + _.second);
+      bool non_empty = + hb_range (src.rows * class_count)
+                       | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
+                       | hb_map ([&] (const unsigned index) { return !src.offset_is_null (index / class_count, index % class_count, class_count); })
+                       | hb_any;
+
+      if (!non_empty) continue;
+
       auto *matrix = out->serialize_append (c->serializer);
       if (unlikely (!matrix)) return_trace (false);
 
-      const LigatureAttach& src = (this + _.second);
       auto indexes =
           + hb_range (src.rows * class_count)
           | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
@@ -44,6 +52,9 @@
 				       this,
 				       src.rows,
 				       indexes);
+
+      hb_codepoint_t new_gid = glyph_map.get (_.first);
+      new_coverage.push (new_gid);
     }
     return_trace (ret);
   }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkBasePosFormat1.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkBasePosFormat1.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -209,19 +209,22 @@
     ;
 
     new_coverage.reset ();
-    + base_iter
-    | hb_map (hb_first)
-    | hb_map (glyph_map)
-    | hb_sink (new_coverage)
-    ;
+    hb_sorted_vector_t<unsigned> base_indexes;
+    auto &base_array = (this+baseArray);
+    for (const auto _ : + base_iter)
+    {
+      unsigned row = _.second;
+      bool non_empty = + hb_range ((unsigned) classCount)
+                       | hb_filter (klass_mapping)
+                       | hb_map ([&] (const unsigned col) { return !base_array.offset_is_null (row, col, (unsigned) classCount); })
+                       | hb_any
+                       ;
 
-    if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
-      return_trace (false);
+      if (!non_empty) continue;
+      
+      hb_codepoint_t new_g = glyph_map.get ( _.first);
+      new_coverage.push (new_g);
 
-    hb_sorted_vector_t<unsigned> base_indexes;
-    for (const unsigned row : + base_iter
-                              | hb_map (hb_second))
-    {
       + hb_range ((unsigned) classCount)
       | hb_filter (klass_mapping)
       | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
@@ -229,8 +232,12 @@
       ;
     }
 
+    if (!new_coverage) return_trace (false);
+    if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+      return_trace (false);
+
     return_trace (out->baseArray.serialize_subset (c, baseArray, this,
-						   base_iter.len (),
+						   new_coverage.length,
 						   base_indexes.iter ()));
   }
 };

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkLigPosFormat1.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkLigPosFormat1.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -200,19 +200,13 @@
 						    &klass_mapping)))
       return_trace (false);
 
-    auto new_ligature_coverage =
-    + hb_iter (this + ligatureCoverage)
-    | hb_take ((this + ligatureArray).len)
-    | hb_map_retains_sorting (glyph_map)
-    | hb_filter ([] (hb_codepoint_t glyph) { return glyph != HB_MAP_VALUE_INVALID; })
-    ;
-
-    if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
+    hb_sorted_vector_t<hb_codepoint_t> new_lig_coverage;
+    if (!out->ligatureArray.serialize_subset (c, ligatureArray, this,
+					      hb_iter (this+ligatureCoverage),
+					      classCount, &klass_mapping, new_lig_coverage))
       return_trace (false);
 
-    return_trace (out->ligatureArray.serialize_subset (c, ligatureArray, this,
-						       hb_iter (this+ligatureCoverage),
-						       classCount, &klass_mapping));
+    return_trace (out->ligatureCoverage.serialize_serialize (c->serializer, new_lig_coverage.iter ()));
   }
 
 };

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -196,19 +196,23 @@
     ;
 
     new_coverage.reset ();
-    + mark2_iter
-    | hb_map (hb_first)
-    | hb_map (glyph_map)
-    | hb_sink (new_coverage)
-    ;
+    hb_sorted_vector_t<unsigned> mark2_indexes;
+    auto &mark2_array = (this+mark2Array);
+    for (const auto _ : + mark2_iter)
+    {
+      unsigned row = _.second;
 
-    if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
-      return_trace (false);
+      bool non_empty = + hb_range ((unsigned) classCount)
+                       | hb_filter (klass_mapping)
+                       | hb_map ([&] (const unsigned col) { return !mark2_array.offset_is_null (row, col, (unsigned) classCount); })
+                       | hb_any
+                       ;
 
-    hb_sorted_vector_t<unsigned> mark2_indexes;
-    for (const unsigned row : + mark2_iter
-                              | hb_map (hb_second))
-    {
+      if (!non_empty) continue;
+
+      hb_codepoint_t new_g = glyph_map.get ( _.first);
+      new_coverage.push (new_g);
+
       + hb_range ((unsigned) classCount)
       | hb_filter (klass_mapping)
       | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
@@ -216,6 +220,10 @@
       ;
     }
 
+    if (!new_coverage) return_trace (false);
+    if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+      return_trace (false);
+
     return_trace (out->mark2Array.serialize_subset (c, mark2Array, this,
 						    mark2_iter.len (),
 						    mark2_indexes.iter ()));

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat1.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat1.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -103,28 +103,24 @@
 
   const Coverage &get_coverage () const { return this+coverage; }
 
-  unsigned cache_cost () const
+  static void * cache_func (void *p, hb_ot_subtable_cache_op_t op)
   {
-    return (this+coverage).cost ();
-  }
-  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
-  {
     switch (op)
     {
-      case hb_ot_lookup_cache_op_t::CREATE:
+      case hb_ot_subtable_cache_op_t::CREATE:
       {
-	hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
+	hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) hb_malloc (sizeof (hb_ot_layout_mapping_cache_t));
 	if (likely (cache))
 	  cache->clear ();
 	return cache;
       }
-      case hb_ot_lookup_cache_op_t::ENTER:
-	return (void *) true;
-      case hb_ot_lookup_cache_op_t::LEAVE:
+      case hb_ot_subtable_cache_op_t::ENTER:
 	return nullptr;
-      case hb_ot_lookup_cache_op_t::DESTROY:
+      case hb_ot_subtable_cache_op_t::LEAVE:
+	return nullptr;
+      case hb_ot_subtable_cache_op_t::DESTROY:
       {
-	hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
+	hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) p;
 	hb_free (cache);
 	return nullptr;
       }
@@ -132,9 +128,7 @@
     return nullptr;
   }
 
-  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
-  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
-  bool _apply (hb_ot_apply_context_t *c, bool cached) const
+  bool apply (hb_ot_apply_context_t *c, void *external_cache) const
   {
     TRACE_APPLY (this);
 
@@ -141,7 +135,7 @@
     hb_buffer_t *buffer = c->buffer;
 
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-    hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
+    hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) external_cache;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache);
 #else
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -125,20 +125,16 @@
 
   struct pair_pos_cache_t
   {
-    hb_ot_lookup_cache_t coverage;
-    hb_ot_lookup_cache_t first;
-    hb_ot_lookup_cache_t second;
+    hb_ot_layout_mapping_cache_t coverage;
+    hb_ot_layout_mapping_cache_t first;
+    hb_ot_layout_mapping_cache_t second;
   };
 
-  unsigned cache_cost () const
+  static void * cache_func (void *p, hb_ot_subtable_cache_op_t op)
   {
-    return (this+coverage).cost () + (this+classDef1).cost () + (this+classDef2).cost ();
-  }
-  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
-  {
     switch (op)
     {
-      case hb_ot_lookup_cache_op_t::CREATE:
+      case hb_ot_subtable_cache_op_t::CREATE:
       {
 	pair_pos_cache_t *cache = (pair_pos_cache_t *) hb_malloc (sizeof (pair_pos_cache_t));
 	if (likely (cache))
@@ -149,11 +145,11 @@
 	}
 	return cache;
       }
-      case hb_ot_lookup_cache_op_t::ENTER:
-	return (void *) true;
-      case hb_ot_lookup_cache_op_t::LEAVE:
+      case hb_ot_subtable_cache_op_t::ENTER:
 	return nullptr;
-      case hb_ot_lookup_cache_op_t::DESTROY:
+      case hb_ot_subtable_cache_op_t::LEAVE:
+	return nullptr;
+      case hb_ot_subtable_cache_op_t::DESTROY:
 	{
 	  pair_pos_cache_t *cache = (pair_pos_cache_t *) p;
 	  hb_free (cache);
@@ -163,9 +159,7 @@
     return nullptr;
   }
 
-  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
-  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
-  bool _apply (hb_ot_apply_context_t *c, bool cached) const
+  bool apply (hb_ot_apply_context_t *c, void *external_cache) const
   {
     TRACE_APPLY (this);
 
@@ -172,7 +166,7 @@
     hb_buffer_t *buffer = c->buffer;
 
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-    pair_pos_cache_t *cache = cached ? (pair_pos_cache_t *) c->lookup_accel->cache : nullptr;
+    pair_pos_cache_t *cache = (pair_pos_cache_t *) external_cache;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
 #else
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/LigatureSubstFormat1.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/LigatureSubstFormat1.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -78,28 +78,24 @@
     return lig_set.would_apply (c);
   }
 
-  unsigned cache_cost () const
+  static void * cache_func (void *p, hb_ot_subtable_cache_op_t op)
   {
-    return (this+coverage).cost ();
-  }
-  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
-  {
     switch (op)
     {
-      case hb_ot_lookup_cache_op_t::CREATE:
+      case hb_ot_subtable_cache_op_t::CREATE:
       {
-	hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
+	hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) hb_malloc (sizeof (hb_ot_layout_mapping_cache_t));
 	if (likely (cache))
 	  cache->clear ();
 	return cache;
       }
-      case hb_ot_lookup_cache_op_t::ENTER:
-	return (void *) true;
-      case hb_ot_lookup_cache_op_t::LEAVE:
+      case hb_ot_subtable_cache_op_t::ENTER:
 	return nullptr;
-      case hb_ot_lookup_cache_op_t::DESTROY:
+      case hb_ot_subtable_cache_op_t::LEAVE:
+	return nullptr;
+      case hb_ot_subtable_cache_op_t::DESTROY:
       {
-	hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
+	hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) p;
 	hb_free (cache);
 	return nullptr;
       }
@@ -107,15 +103,13 @@
     return nullptr;
   }
 
-  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
-  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
-  bool _apply (hb_ot_apply_context_t *c, bool cached) const
+  bool apply (hb_ot_apply_context_t *c, void *external_cache) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
 
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-    hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
+    hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) external_cache;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache);
 #else
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/types.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/types.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/types.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -29,8 +29,8 @@
 #ifndef OT_LAYOUT_TYPES_HH
 #define OT_LAYOUT_TYPES_HH
 
-using hb_ot_lookup_cache_t = hb_cache_t<15, 8, 7>;
-static_assert (sizeof (hb_ot_lookup_cache_t) == 256, "");
+using hb_ot_layout_mapping_cache_t = hb_cache_t<15, 8, 7>;
+static_assert (sizeof (hb_ot_layout_mapping_cache_t) == 256, "");
 
 namespace OT {
 namespace Layout {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -11,6 +11,8 @@
 //namespace Var {
 
 
+#ifndef HB_NO_DRAW
+
 struct hb_transforming_pen_context_t
 {
   hb_transform_t<> transform;
@@ -411,6 +413,8 @@
   return true;
 }
 
+#endif
+
 //} // namespace Var
 } // namespace OT
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -194,6 +194,7 @@
 		 hb_codepoint_t gid,
 		 hb_glyph_extents_t *extents) const
     {
+#ifndef HB_NO_DRAW
       if (!table->has_data ()) return false;
 
       hb_extents_t<> f_extents;
@@ -207,6 +208,9 @@
 	*extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0);
 
       return ret;
+#else
+      return false;
+#endif
     }
 
     private:

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	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -533,7 +533,11 @@
   bool get_extents_without_var_scaled (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator,
 				       hb_glyph_extents_t *extents) const
   {
-    if (type == EMPTY) return true; /* Empty glyph; zero extents. */
+    if (type == EMPTY)
+    {
+      *extents = {0, 0, 0, 0};
+      return true; /* Empty glyph; zero extents. */
+    }
     return header->get_extents_without_var_scaled (font, glyf_accelerator, gid, extents);
   }
 

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	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -445,8 +445,7 @@
     if (coords)
     {
       hb_glyf_scratch_t *scratch = acquire_scratch ();
-      if (unlikely (!scratch))
-        return false;
+      if (unlikely (!scratch)) return false;
       bool ret = get_points (font,
 			     gid,
 			     points_aggregator_t (font, extents, nullptr, true),
@@ -493,8 +492,7 @@
     if (!has_data ()) return false;
 
     hb_glyf_scratch_t *scratch = acquire_scratch ();
-    if (unlikely (!scratch))
-      return true;
+    if (unlikely (!scratch)) return true;
 
     bool ret = get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
 			   hb_array (font->coords,
@@ -523,6 +521,7 @@
 
   hb_glyf_scratch_t *acquire_scratch () const
   {
+    if (!has_data ()) return nullptr;
     hb_glyf_scratch_t *scratch = cached_scratch.get_acquire ();
     if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
     {
@@ -534,6 +533,8 @@
   }
   void release_scratch (hb_glyf_scratch_t *scratch) const
   {
+    if (!scratch)
+      return;
     if (!cached_scratch.cmpexch (nullptr, scratch))
     {
       scratch->~hb_glyf_scratch_t ();

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/check-release-notes.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/check-release-notes.py	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/check-release-notes.py	2025-08-13 22:39:51 UTC (rev 76048)
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+import sys
+
+
+news_path = sys.argv[1]
+release = sys.argv[2]
+
+with open(news_path, "r", encoding="utf-8") as news_file:
+    lines = news_file.readlines()
+
+start = None
+end = None
+for i, line in enumerate(lines):
+    line = line.rstrip()
+    if line.startswith("Overview of changes leading to"):
+        if start is not None:  # Start of next release
+            end = i
+            break
+        if line.endswith(release):  # Start of the release
+            start = i + 3  # Skip the header lines
+
+assert start and end and end > start
+
+print("".join(lines[start:end]))

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -965,9 +965,9 @@
    */
   template<typename O>
   unsigned move_child (unsigned old_parent_idx,
-                   const O* old_offset,
-                   unsigned new_parent_idx,
-                   const O* new_offset)
+                       const O* old_offset,
+                       unsigned new_parent_idx,
+                       const O* new_offset)
   {
     distance_invalid = true;
     positions_invalid = true;
@@ -993,6 +993,50 @@
   }
 
   /*
+   * Moves all outgoing links in old parent that have
+   * a link position between [old_post_start, old_pos_end)
+   * to the new parent. Links are placed serially in the new
+   * parent starting at new_pos_start.
+   */
+  template<typename O>
+  void move_children (unsigned old_parent_idx,
+                      unsigned old_pos_start,
+                      unsigned old_pos_end,
+                      unsigned new_parent_idx,
+                      unsigned new_pos_start)
+  {
+    distance_invalid = true;
+    positions_invalid = true;
+
+    auto& old_v = vertices_[old_parent_idx];
+    auto& new_v = vertices_[new_parent_idx];
+
+    hb_vector_t<hb_serialize_context_t::object_t::link_t> old_links;
+    for (const auto& l : old_v.obj.real_links)
+    {
+      if (l.position < old_pos_start || l.position >= old_pos_end)
+      {
+        old_links.push(l);
+        continue;
+      }
+
+      unsigned array_pos = l.position - old_pos_start;
+
+      unsigned child_id = l.objidx;
+      auto* new_link = new_v.obj.real_links.push ();
+      new_link->width = O::static_size;
+      new_link->objidx = child_id;
+      new_link->position = new_pos_start + array_pos;
+
+      auto& child = vertices_[child_id];
+      child.add_parent (new_parent_idx, false);
+      child.remove_parent (old_parent_idx);
+    }
+
+    old_v.obj.real_links = std::move (old_links);
+  }
+
+  /*
    * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
    * links. index_map is updated with mappings from old id to new id. If a duplication has already
    * been performed for a given index, then it will be skipped.

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/ligature-graph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/ligature-graph.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/ligature-graph.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -105,6 +105,23 @@
     return result;
   }
 
+  hb_vector_t<unsigned> ligature_index_to_object_id(const graph_t::vertex_and_table_t<LigatureSet>& liga_set) const {
+    hb_vector_t<unsigned> map;
+    map.resize_exact(liga_set.table->ligature.len);
+    if (map.in_error()) return map;
+
+    for (unsigned i = 0; i < map.length; i++) {
+      map[i] = (unsigned) -1;
+    }
+
+    for (const auto& l : liga_set.vertex->obj.real_links) {
+      if (l.position < 2) continue;
+      unsigned array_index = (l.position - 2) / 2;
+      map[array_index] = l.objidx;
+    }
+    return map;
+  }
+
   hb_vector_t<unsigned> compute_split_points(gsubgpos_graph_context_t& c,
                                              unsigned parent_index,
                                              unsigned this_index) const
@@ -128,9 +145,16 @@
         return hb_vector_t<unsigned> {};
       }
 
+      // Finding the object id associated with an array index is O(n)
+      // so to avoid O(n^2), precompute the mapping by scanning through
+      // all links
+      auto index_to_id = ligature_index_to_object_id(liga_set);
+      if (index_to_id.in_error()) return hb_vector_t<unsigned>();
+
       for (unsigned j = 0; j < liga_set.table->ligature.len; j++)
       {
-        const unsigned liga_id = c.graph.index_for_offset (liga_set.index, &liga_set.table->ligature[j]);
+        const unsigned liga_id = index_to_id[j];
+        if (liga_id == (unsigned) -1) continue; // no outgoing link, ignore
         const unsigned liga_size = c.graph.vertices_[liga_id].table_size ();
 
         accumulated += OT::HBUINT16::static_size; // for ligature offset
@@ -154,7 +178,6 @@
     return split_points;
   }
 
-
   struct split_context_t
   {
     gsubgpos_graph_context_t& c;
@@ -323,19 +346,19 @@
       {
         // This liga set partially overlaps [start, end). We'll need to create
         // a new liga set sub table and move the intersecting ligas to it.
-        unsigned liga_count = hb_min(end, current_end) - hb_max(start, current_start);
+        unsigned start_index = hb_max(start, current_start) - count;
+        unsigned end_index = hb_min(end, current_end) - count;
+        unsigned liga_count = end_index - start_index;
         auto result = new_liga_set(c, liga_count);
         liga_set_prime_id = result.first;
-        LigatureSet* prime = result.second;
         if (liga_set_prime_id == (unsigned) -1) return -1;
 
-        unsigned new_index = 0;
-        for (unsigned j = hb_max(start, current_start) - count; j < hb_min(end, current_end) - count; j++) {
-          c.graph.move_child<> (liga_set_index,
-                                &liga_set.table->ligature[j],
-                                liga_set_prime_id,
-                                &prime->ligature[new_index++]);
-        }
+        c.graph.move_children<OT::Offset16>(
+          liga_set_index,
+          2 + start_index * 2,
+          2 + end_index * 2,
+          liga_set_prime_id,
+          2);
 
         liga_set_end = i;
         if (i < liga_set_start) liga_set_start = i;
@@ -392,8 +415,12 @@
       // duplicated. Code later on will re-add the virtual links as needed (via retained_indices).
       clear_virtual_links(c, liga_set.index);
       retained_indices.add(liga_set.index);
-      for (const auto& liga_offset : liga_set.table->ligature) {
-        unsigned liga_index = c.graph.index_for_offset(liga_set.index, &liga_offset);
+
+      auto index_to_id = ligature_index_to_object_id(liga_set);
+      if (index_to_id.in_error()) return false;
+
+      for (unsigned i = 0; i < liga_set.table->ligature.len; i++) {
+        unsigned liga_index = index_to_id[i];
         if (liga_index != (unsigned) -1) {
           clear_virtual_links(c, liga_index);
           retained_indices.add(liga_index);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -38,7 +38,7 @@
   hb_serialize_context_t serializer(buffer, 100);
   OT::ClassDef_serialize (&serializer, glyph_and_class);
   serializer.end_serialize ();
-  assert(!serializer.in_error());
+  hb_always_assert(!serializer.in_error());
 
   hb_blob_t* blob = serializer.copy_blob();
   unsigned size = hb_blob_get_length(blob);
@@ -66,7 +66,7 @@
   hb_serialize_context_t serializer(buffer, 100);
   OT::Layout::Common::Coverage_serialize (&serializer, glyphs);
   serializer.end_serialize ();
-  assert(!serializer.in_error());
+  hb_always_assert(!serializer.in_error());
 
   hb_blob_t* blob = serializer.copy_blob();
   unsigned size = hb_blob_get_length(blob);
@@ -101,9 +101,9 @@
   return true;
 }
 
-static bool check_add_class_def_size(graph::class_def_size_estimator_t& estimator,
-                                     const gid_and_class_list_t& map,
-                                     unsigned klass, hb_vector_t<unsigned> klasses)
+static HB_UNUSED bool check_add_class_def_size(graph::class_def_size_estimator_t& estimator,
+					       const gid_and_class_list_t& map,
+					       unsigned klass, hb_vector_t<unsigned> klasses)
 {
   unsigned result = estimator.add_class_def_size(klass);
   unsigned expected = actual_class_def_size(map, klasses);
@@ -115,7 +115,7 @@
   return check_coverage_size(estimator, map, klasses);
 }
 
-static bool check_add_class_def_size (const gid_and_class_list_t& list, unsigned klass)
+static HB_UNUSED bool check_add_class_def_size (const gid_and_class_list_t& list, unsigned klass)
 {
   graph::class_def_size_estimator_t estimator (list.iter ());
 
@@ -149,13 +149,13 @@
 {
   gid_and_class_list_t empty = {
   };
-  assert (check_add_class_def_size (empty, 0));
-  assert (check_add_class_def_size (empty, 1));
+  hb_always_assert (check_add_class_def_size (empty, 0));
+  hb_always_assert (check_add_class_def_size (empty, 1));
 
   gid_and_class_list_t class_zero = {
     {5, 0},
   };
-  assert (check_add_class_def_size (class_zero, 0));
+  hb_always_assert (check_add_class_def_size (class_zero, 0));
 
   gid_and_class_list_t consecutive = {
     {4, 0},
@@ -169,9 +169,9 @@
     {10, 2},
     {11, 2},
   };
-  assert (check_add_class_def_size (consecutive, 0));
-  assert (check_add_class_def_size (consecutive, 1));
-  assert (check_add_class_def_size (consecutive, 2));
+  hb_always_assert (check_add_class_def_size (consecutive, 0));
+  hb_always_assert (check_add_class_def_size (consecutive, 1));
+  hb_always_assert (check_add_class_def_size (consecutive, 2));
 
   gid_and_class_list_t non_consecutive = {
     {4, 0},
@@ -185,9 +185,9 @@
     {11, 2},
     {13, 2},
   };
-  assert (check_add_class_def_size (non_consecutive, 0));
-  assert (check_add_class_def_size (non_consecutive, 1));
-  assert (check_add_class_def_size (non_consecutive, 2));
+  hb_always_assert (check_add_class_def_size (non_consecutive, 0));
+  hb_always_assert (check_add_class_def_size (non_consecutive, 1));
+  hb_always_assert (check_add_class_def_size (non_consecutive, 2));
 
   gid_and_class_list_t multiple_ranges = {
     {4, 0},
@@ -202,8 +202,8 @@
     {12, 1},
     {13, 1},
   };
-  assert (check_add_class_def_size (multiple_ranges, 0));
-  assert (check_add_class_def_size (multiple_ranges, 1));
+  hb_always_assert (check_add_class_def_size (multiple_ranges, 0));
+  hb_always_assert (check_add_class_def_size (multiple_ranges, 1));
 }
 
 static void test_running_class_and_coverage_size_estimates () {
@@ -229,14 +229,14 @@
   };
 
   graph::class_def_size_estimator_t estimator1(consecutive_map.iter());
-  assert(check_add_class_def_size(estimator1, consecutive_map, 1, {1}));
-  assert(check_add_class_def_size(estimator1, consecutive_map, 2, {1, 2}));
-  assert(check_add_class_def_size(estimator1, consecutive_map, 2, {1, 2})); // check that adding the same class again works
-  assert(check_add_class_def_size(estimator1, consecutive_map, 3, {1, 2, 3}));
+  hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 1, {1}));
+  hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 2, {1, 2}));
+  hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 2, {1, 2})); // check that adding the same class again works
+  hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 3, {1, 2, 3}));
 
   estimator1.reset();
-  assert(check_add_class_def_size(estimator1, consecutive_map, 2, {2}));
-  assert(check_add_class_def_size(estimator1, consecutive_map, 3, {2, 3}));
+  hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 2, {2}));
+  hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 3, {2, 3}));
 
   // #### With non-consecutive gids: always uses format 2 ###
   gid_and_class_list_t non_consecutive_map = {
@@ -261,13 +261,13 @@
   };
 
   graph::class_def_size_estimator_t estimator2(non_consecutive_map.iter());
-  assert(check_add_class_def_size(estimator2, non_consecutive_map, 1, {1}));
-  assert(check_add_class_def_size(estimator2, non_consecutive_map, 2, {1, 2}));
-  assert(check_add_class_def_size(estimator2, non_consecutive_map, 3, {1, 2, 3}));
+  hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 1, {1}));
+  hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 2, {1, 2}));
+  hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 3, {1, 2, 3}));
 
   estimator2.reset();
-  assert(check_add_class_def_size(estimator2, non_consecutive_map, 2, {2}));
-  assert(check_add_class_def_size(estimator2, non_consecutive_map, 3, {2, 3}));
+  hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 2, {2}));
+  hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 3, {2, 3}));
 }
 
 static void test_running_class_size_estimates_with_locally_consecutive_glyphs () {
@@ -278,13 +278,13 @@
   };
 
   graph::class_def_size_estimator_t estimator(map.iter());
-  assert(check_add_class_def_size(estimator, map, 1, {1}));
-  assert(check_add_class_def_size(estimator, map, 2, {1, 2}));
-  assert(check_add_class_def_size(estimator, map, 3, {1, 2, 3}));
+  hb_always_assert(check_add_class_def_size(estimator, map, 1, {1}));
+  hb_always_assert(check_add_class_def_size(estimator, map, 2, {1, 2}));
+  hb_always_assert(check_add_class_def_size(estimator, map, 3, {1, 2, 3}));
 
   estimator.reset();
-  assert(check_add_class_def_size(estimator, map, 2, {2}));
-  assert(check_add_class_def_size(estimator, map, 3, {2, 3}));
+  hb_always_assert(check_add_class_def_size(estimator, map, 2, {2}));
+  hb_always_assert(check_add_class_def_size(estimator, map, 3, {2, 3}));
 }
 
 int

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-subset.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-subset.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-subset.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -62,6 +62,11 @@
 #include "hb-subset-plan-var.cc"
 #include "hb-subset-plan.cc"
 #include "hb-subset-serialize.cc"
+#include "hb-subset-table-cff.cc"
+#include "hb-subset-table-color.cc"
+#include "hb-subset-table-layout.cc"
+#include "hb-subset-table-other.cc"
+#include "hb-subset-table-var.cc"
 #include "hb-subset.cc"
 #include "hb-ucd.cc"
 #include "hb-unicode.cc"

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -290,7 +290,7 @@
     unsigned int j = m & ELT_MASK;
 
     const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
-    for (const elt_t *p = &vv; i < len (); p = &v[++i])
+    for (const elt_t *p = &vv; i < len (); p = ((const elt_t *) &v[0]) + (++i))
       if (*p)
       {
 	*codepoint = i * ELT_BITS + elt_get_min (*p);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -32,7 +32,7 @@
 #include "hb.hh"
 
 
-#line 36 "hb-buffer-deserialize-text-unicode.hh"
+#line 33 "hb-buffer-deserialize-text-unicode.hh"
 static const unsigned char _deserialize_text_unicode_trans_keys[] = {
 	0u, 0u, 43u, 102u, 48u, 102u, 48u, 124u, 48u, 57u, 62u, 124u, 48u, 124u, 60u, 117u, 
 	85u, 117u, 85u, 117u, 0
@@ -150,12 +150,12 @@
   hb_glyph_info_t info = {0};
   const hb_glyph_position_t pos = {0};
   
-#line 154 "hb-buffer-deserialize-text-unicode.hh"
+#line 147 "hb-buffer-deserialize-text-unicode.hh"
 	{
 	cs = deserialize_text_unicode_start;
 	}
 
-#line 159 "hb-buffer-deserialize-text-unicode.hh"
+#line 150 "hb-buffer-deserialize-text-unicode.hh"
 	{
 	int _slen;
 	int _trans;
@@ -215,7 +215,7 @@
 	hb_memset (&info, 0, sizeof (info));
 }
 	break;
-#line 219 "hb-buffer-deserialize-text-unicode.hh"
+#line 203 "hb-buffer-deserialize-text-unicode.hh"
 	}
 
 _again:
@@ -238,7 +238,7 @@
 	*end_ptr = p;
 }
 	break;
-#line 242 "hb-buffer-deserialize-text-unicode.hh"
+#line 224 "hb-buffer-deserialize-text-unicode.hh"
 	}
 	}
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -75,6 +75,8 @@
   static_assert ((key_bits >= cache_bits), "");
   static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), "");
 
+  static constexpr unsigned MAX_VALUE = (1u << value_bits) - 1;
+
   hb_cache_t () { clear (); }
 
   void clear ()
@@ -100,6 +102,12 @@
   {
     if (unlikely ((key >> key_bits) || (value >> value_bits)))
       return; /* Overflows */
+    set_unchecked (key, value);
+  }
+
+  HB_HOT
+  void set_unchecked (unsigned int key, unsigned int value)
+  {
     unsigned int k = key & ((1u<<cache_bits)-1);
     unsigned int v = ((key>>cache_bits)<<value_bits) | value;
     values[k] = v;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -72,7 +72,7 @@
   cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
 			const int *coords_=nullptr, unsigned int num_coords_=0)
     : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs),
-      cached_scalars_vector (&acc.cached_scalars_vector)
+      region_count (0), cached_scalars_vector (&acc.cached_scalars_vector)
   {
     coords = coords_;
     num_coords = num_coords_;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -91,7 +91,10 @@
 #ifdef HB_MINI
 #define HB_NO_AAT
 #define HB_NO_LEGACY
-#define HB_NO_BORING_EXPANSION
+#define HB_NO_BEYOND_64K
+#define HB_NO_CUBIC_GLYF
+#define HB_NO_VAR_COMPOSITES
+#define HB_NO_VAR_HVF
 #endif
 
 #ifdef __OPTIMIZE_SIZE__
@@ -109,12 +112,6 @@
 
 /* Closure of options. */
 
-#ifdef HB_NO_BORING_EXPANSION
-#define HB_NO_BEYOND_64K
-#define HB_NO_CUBIC_GLYF
-#define HB_NO_VAR_COMPOSITES
-#endif
-
 #ifdef HB_NO_VAR
 #define HB_NO_VAR_COMPOSITES
 #endif

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -394,6 +394,10 @@
 #define HB_DEBUG_WASM (HB_DEBUG+0)
 #endif
 
+#ifndef HB_DEBUG_KBTS
+#define HB_DEBUG_KBTS (HB_DEBUG+0)
+#endif
+
 /*
  * With tracing.
  */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -84,8 +84,7 @@
 
   hb_sanitize_context_t c (blob);
 
-  const char *start = hb_blob_get_data (blob, nullptr);
-  auto *ot = reinterpret_cast<OT::OpenTypeFontFile *> (const_cast<char *> (start));
+  auto *ot = blob->as<OT::OpenTypeFontFile> ();
   if (unlikely (!ot->sanitize (&c)))
     return 0;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -266,7 +266,7 @@
   gr_segment *seg = nullptr;
   const gr_slot *is;
   unsigned int ci = 0, ic = 0;
-  unsigned int curradvx = 0, curradvy = 0;
+  int curradvx = 0, curradvy = 0;
 
   unsigned int scratch_size;
   hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-harfrust.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-harfrust.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-harfrust.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -30,6 +30,16 @@
 
 
 /*
+ * buffer
+ */
+extern "C" void *
+_hb_harfrust_buffer_create_rs (void);
+
+extern "C" void
+_hb_harfrust_buffer_destroy_rs (void *data);
+
+
+/*
  * shaper face data
  */
 
@@ -75,6 +85,7 @@
   _hb_harfrust_shaper_font_data_destroy_rs (data);
 }
 
+
 /*
  * shape plan
  */
@@ -98,12 +109,13 @@
 _hb_harfrust_shape_rs (const void         *font_data,
 		       const void         *face_data,
 		       const void         *rs_shape_plan,
+		       const void         *rs_buffer,
 		       hb_font_t          *font,
 		       hb_buffer_t        *buffer,
 		       const hb_feature_t *features,
 		       unsigned int        num_features);
 
-static hb_user_data_key_t hr_shape_plan_key = {0};
+static hb_user_data_key_t hb_object_key = {0};
 
 hb_bool_t
 _hb_harfrust_shape (hb_shape_plan_t    *shape_plan,
@@ -115,13 +127,31 @@
   const hb_harfrust_font_data_t *font_data = font->data.harfrust;
   const hb_harfrust_face_data_t *face_data = font->face->data.harfrust;
 
+retry_buffer:
+  void *hr_buffer = hb_buffer_get_user_data (buffer, &hb_object_key);
+  if (unlikely (!hr_buffer))
+  {
+    hr_buffer = _hb_harfrust_buffer_create_rs ();
+    if (unlikely (!hr_buffer))
+      return false;
+
+    if (!hb_buffer_set_user_data (buffer,
+				  &hb_object_key,
+				  hr_buffer,
+				  _hb_harfrust_buffer_destroy_rs,
+				  false))
+    {
+      _hb_harfrust_buffer_destroy_rs (hr_buffer);
+      goto retry_buffer;
+    }
+  }
+
   void *hr_shape_plan = nullptr;
 
   if (!num_features)
   {
-  retry:
-    hr_shape_plan = hb_shape_plan_get_user_data (shape_plan,
-						 &hr_shape_plan_key);
+  retry_shape_plan:
+    hr_shape_plan = hb_shape_plan_get_user_data (shape_plan, &hb_object_key);
     if (unlikely (!hr_shape_plan))
     {
       hr_shape_plan = _hb_harfrust_shape_plan_create_rs (font_data, face_data,
@@ -130,13 +160,13 @@
 							 shape_plan->key.props.direction);
       if (hr_shape_plan &&
 	  !hb_shape_plan_set_user_data (shape_plan,
-				       &hr_shape_plan_key,
+				       &hb_object_key,
 				       hr_shape_plan,
 				       _hb_harfrust_shape_plan_destroy_rs,
 				       false))
       {
         _hb_harfrust_shape_plan_destroy_rs (hr_shape_plan);
-	goto retry;
+	goto retry_shape_plan;
       }
     }
   }
@@ -144,6 +174,7 @@
   return _hb_harfrust_shape_rs (font_data,
 				face_data,
 				hr_shape_plan,
+				hr_buffer,
 				font,
 				buffer,
 				features,

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -972,7 +972,7 @@
 		    Proj&& f = hb_identity) const
   {
     for (auto it = hb_iter (c); it; ++it)
-      if (!hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it)))
+      if (!hb_match (p, hb_get (f, *it)))
 	return false;
     return true;
   }
@@ -989,7 +989,7 @@
 		    Proj&& f = hb_identity) const
   {
     for (auto it = hb_iter (c); it; ++it)
-      if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it)))
+      if (hb_match (p, hb_get (f, *it)))
 	return true;
     return false;
   }
@@ -1006,7 +1006,7 @@
 		    Proj&& f = hb_identity) const
   {
     for (auto it = hb_iter (c); it; ++it)
-      if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it)))
+      if (hb_match (p, hb_get (f, *it)))
 	return false;
     return true;
   }

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kbts.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kbts.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kbts.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -0,0 +1,259 @@
+/*
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author(s): Khaled Hosny
+ */
+
+#include "hb.hh"
+
+#if HAVE_KBTS
+
+#include "hb-shaper-impl.hh"
+
+#define KB_TEXT_SHAPE_IMPLEMENTATION
+#define KB_TEXT_SHAPE_STATIC
+#define KB_TEXT_SHAPE_NO_CRT
+#define KBTS_MEMSET hb_memset
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#include "kb_text_shape.h"
+#pragma GCC diagnostic pop
+
+
+hb_kbts_face_data_t *
+_hb_kbts_shaper_face_data_create (hb_face_t *face)
+{
+  hb_blob_t *blob = hb_face_reference_blob (face);
+
+  unsigned int blob_length;
+  const char *blob_data = hb_blob_get_data (blob, &blob_length);
+  if (unlikely (!blob_length))
+  {
+    DEBUG_MSG (KBTS, blob, "Empty blob");
+    hb_blob_destroy (blob);
+    return nullptr;
+  }
+
+  void *data = hb_malloc (blob_length);
+  if (likely (data))
+    hb_memcpy (data, blob_data, blob_length);
+
+  hb_blob_destroy (blob);
+  blob = nullptr;
+
+  if (unlikely (!data))
+  {
+    DEBUG_MSG (KBTS, face, "Failed to allocate memory for font data");
+    return nullptr;
+  }
+
+  kbts_font *kb_font = (kbts_font *) hb_calloc (1, sizeof (kbts_font));
+  if (unlikely (!kb_font))
+  {
+    hb_free (data);
+    return nullptr;
+  }
+
+  size_t memory_size;
+  {
+    unsigned scratch_size = kbts_ReadFontHeader (kb_font, data, blob_length);
+    void *scratch = hb_malloc (scratch_size);
+    memory_size = kbts_ReadFontData (kb_font, scratch, scratch_size);
+    hb_free (scratch);
+  }
+
+  void *memory = hb_malloc (memory_size);
+  if (unlikely (!kbts_PostReadFontInitialize (kb_font, memory, memory_size)))
+  {
+    DEBUG_MSG (KBTS, face, "kbts_PostReadFontInitialize failed");
+    hb_free (memory);
+    hb_free (data);
+    hb_free (kb_font);
+    return nullptr;
+  }
+
+  return (hb_kbts_face_data_t *) kb_font;
+}
+
+void
+_hb_kbts_shaper_face_data_destroy (hb_kbts_face_data_t *data)
+{
+  kbts_font *font = (kbts_font *) data;
+
+  assert (kbts_FontIsValid (font));
+
+  hb_free (font->FileBase);
+  hb_free (font->GlyphLookupMatrix);
+  hb_free (font);
+}
+
+hb_kbts_font_data_t *
+_hb_kbts_shaper_font_data_create (hb_font_t *font)
+{
+  return (hb_kbts_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+}
+
+void
+_hb_kbts_shaper_font_data_destroy (hb_kbts_font_data_t *data)
+{
+}
+
+hb_bool_t
+_hb_kbts_shape (hb_shape_plan_t    *shape_plan,
+		hb_font_t          *font,
+		hb_buffer_t        *buffer,
+		const hb_feature_t *features,
+		unsigned int        num_features)
+{
+  hb_face_t *face = font->face;
+  kbts_font *kb_font = (kbts_font *) (const void *) face->data.kbts;
+
+  kbts_direction kb_direction;
+  switch (buffer->props.direction)
+  {
+    case HB_DIRECTION_LTR: kb_direction = KBTS_DIRECTION_LTR; break;
+    case HB_DIRECTION_RTL: kb_direction = KBTS_DIRECTION_RTL; break;
+    case HB_DIRECTION_TTB:
+    case HB_DIRECTION_BTT:
+      DEBUG_MSG (KBTS, face, "Vertical direction is not supported");
+      return false;
+    default:
+    case HB_DIRECTION_INVALID:
+      DEBUG_MSG (KBTS, face, "Invalid direction");
+      return false;
+  }
+
+  kbts_script kb_script = KBTS_SCRIPT_DONT_KNOW;
+  kbts_language kb_language = KBTS_LANGUAGE_DEFAULT;
+  {
+    hb_tag_t scripts[HB_OT_MAX_TAGS_PER_SCRIPT];
+    hb_tag_t language;
+    unsigned int script_count = ARRAY_LENGTH (scripts);
+    unsigned int language_count = 1;
+
+    hb_ot_tags_from_script_and_language (buffer->props.script, buffer->props.language,
+					 &script_count, scripts,
+					 &language_count, &language);
+
+    for (unsigned int i = 0; i < script_count && scripts[i] != HB_TAG_NONE; ++i)
+    {
+      kb_script = kbts_ScriptTagToScript (hb_uint32_swap (scripts[i]));
+      if (kb_script != KBTS_SCRIPT_DONT_KNOW)
+        break;
+    }
+
+    if (language_count)
+      kb_language = (kbts_language) hb_uint32_swap (language);
+  }
+
+  hb_vector_t<kbts_glyph> kb_glyphs;
+  if (unlikely (!kb_glyphs.resize_exact (buffer->len, false)))
+    return false;
+
+  for (size_t i = 0; i < buffer->len; ++i)
+    kb_glyphs.arrayZ[i] = kbts_CodepointToGlyph (kb_font, buffer->info[i].codepoint);
+
+  if (num_features)
+  {
+    for (unsigned int i = 0; i < num_features; ++i)
+    {
+      hb_feature_t feature = features[i];
+      for (unsigned int j = 0; j < buffer->len; ++j)
+      {
+	kbts_glyph *kb_glyph = &kb_glyphs.arrayZ[j];
+	if (hb_in_range (j, feature.start, feature.end))
+	{
+	  if (!kb_glyph->Config)
+	    kb_glyph->Config = (kbts_glyph_config *) hb_calloc (1, sizeof (kbts_glyph_config));
+	  kbts_glyph_config *config = kb_glyph->Config;
+	  while (!kbts_GlyphConfigOverrideFeatureFromTag (config, hb_uint32_swap (feature.tag),
+	                                                  feature.value > 1, feature.value))
+	  {
+	    config->FeatureOverrides = (kbts_feature_override *) hb_realloc (config->FeatureOverrides,
+									     config->RequiredFeatureOverrideCapacity);
+	    config->FeatureOverrideCapacity += 1;
+	  }
+	}
+      }
+    }
+  }
+
+  kbts_shape_state *kb_shape_state;
+  {
+    size_t kb_shape_state_size = kbts_SizeOfShapeState (kb_font);
+    void *kb_shape_state_buffer = hb_malloc (kb_shape_state_size);
+    if (unlikely (!kb_shape_state_buffer))
+    {
+      DEBUG_MSG (KBTS, face, "Failed to allocate memory for shape state");
+      return false;
+    }
+    kb_shape_state = kbts_PlaceShapeState (kb_shape_state_buffer, kb_shape_state_size);
+  }
+  kbts_shape_config kb_shape_config = kbts_ShapeConfig (kb_font, kb_script, kb_language);
+  uint32_t glyph_count = buffer->len;
+  uint32_t glyph_capacity = kb_glyphs.length;
+  while (kbts_Shape (kb_shape_state, &kb_shape_config, KBTS_DIRECTION_LTR, kb_direction,
+		     kb_glyphs.arrayZ, &glyph_count, glyph_capacity))
+  {
+    glyph_capacity = kb_shape_state->RequiredGlyphCapacity;
+    /* kb increases capacity by a fixed number only. We increase it by 50% to
+     * avoid O(n^2) behavior in case of expanding text.
+     *
+     * https://github.com/JimmyLefevre/kb/issues/32
+     */
+    glyph_capacity += glyph_capacity / 2;
+    if (unlikely (!kb_glyphs.resize_exact (glyph_capacity, false)))
+      return false;
+  }
+
+  hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
+  hb_buffer_set_length (buffer, glyph_count);
+
+  hb_glyph_info_t *info = buffer->info;
+  hb_glyph_position_t *pos = buffer->pos;
+
+  buffer->clear_positions ();
+  for (size_t i = 0; i < glyph_count; ++i)
+  {
+    kbts_glyph kb_glyph = kb_glyphs.arrayZ[i];
+    info[i].codepoint = kb_glyph.Id;
+    info[i].cluster = 0; // FIXME
+    pos[i].x_advance = font->em_scalef_x (kb_glyph.AdvanceX);
+    pos[i].y_advance = font->em_scalef_y (kb_glyph.AdvanceY);
+    pos[i].x_offset = font->em_scalef_x (kb_glyph.OffsetX);
+    pos[i].y_offset = font->em_scalef_y (kb_glyph.OffsetY);
+
+    if (kb_glyph.Config)
+      hb_free (kb_glyph.Config->FeatureOverrides);
+  }
+
+  hb_free (kb_shape_state);
+
+  buffer->clear_glyph_flags ();
+  buffer->unsafe_to_break ();
+
+  return true;
+}
+
+#endif
\ No newline at end of file

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -70,11 +70,18 @@
  * Any extra arguments are forwarded to get_size, so for example
  * it can work with UnsizedArrayOf<> as well. */
 template <typename Type, typename TObject, typename ...Ts>
-static inline const Type& StructAfter(const TObject &X, Ts... args)
-{ return StructAtOffset<Type>(&X, X.get_size(args...)); }
+static inline auto StructAfter(const TObject &X, Ts... args) HB_AUTO_RETURN((
+  StructAtOffset<Type>(&X, X.get_size(std::forward<Ts> (args)...))
+))
+/* The is_const shenanigans is to avoid ambiguous overload with gcc-8.
+ * It disables this path when TObject is const.
+ * See: https://github.com/harfbuzz/harfbuzz/issues/5429 */
 template <typename Type, typename TObject, typename ...Ts>
-static inline Type& StructAfter(TObject &X, Ts... args)
-{ return StructAtOffset<Type>(&X, X.get_size(args...)); }
+static inline auto StructAfter(TObject &X, Ts... args) HB_AUTO_RETURN((
+  sizeof(int[std::is_const<TObject>::value ? -1 : +1]) > 0 ?
+  StructAtOffset<Type>(&X, X.get_size(std::forward<Ts> (args)...))
+  : *reinterpret_cast<Type*> (0)
+))
 
 
 /*

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -31,7 +31,7 @@
 #include "hb.hh"
 
 
-#line 35 "hb-number-parser.hh"
+#line 32 "hb-number-parser.hh"
 static const unsigned char _double_parser_trans_keys[] = {
 	0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u, 
 	46u, 101u, 0
@@ -135,12 +135,12 @@
 
   int cs;
   
-#line 139 "hb-number-parser.hh"
+#line 132 "hb-number-parser.hh"
 	{
 	cs = double_parser_start;
 	}
 
-#line 144 "hb-number-parser.hh"
+#line 135 "hb-number-parser.hh"
 	{
 	int _slen;
 	int _trans;
@@ -198,7 +198,7 @@
 	  exp_overflow = true;
 }
 	break;
-#line 202 "hb-number-parser.hh"
+#line 187 "hb-number-parser.hh"
 	}
 
 _again:

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -79,7 +79,7 @@
   {
     TRACE_SERIALIZE (this);
     for (unsigned int i = 0; i < dictval.get_count (); i++)
-      if (unlikely (!opszr.serialize (c, dictval[i], std::forward<Ts> (ds)...)))
+      if (unlikely (!opszr.serialize (c, dictval[i], ds...)))
 	return_trace (false);
 
     return_trace (true);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-std-str.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-std-str.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-std-str.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -30,396 +30,396 @@
 #include "hb.hh"
 #endif
 
-_S(".notdef")
-_S("space")
-_S("exclam")
-_S("quotedbl")
-_S("numbersign")
-_S("dollar")
-_S("percent")
-_S("ampersand")
-_S("quoteright")
-_S("parenleft")
-_S("parenright")
-_S("asterisk")
-_S("plus")
-_S("comma")
-_S("hyphen")
-_S("period")
-_S("slash")
-_S("zero")
-_S("one")
-_S("two")
-_S("three")
-_S("four")
-_S("five")
-_S("six")
-_S("seven")
-_S("eight")
-_S("nine")
-_S("colon")
-_S("semicolon")
-_S("less")
-_S("equal")
-_S("greater")
-_S("question")
-_S("at")
-_S("A")
-_S("B")
-_S("C")
-_S("D")
-_S("E")
-_S("F")
-_S("G")
-_S("H")
-_S("I")
-_S("J")
-_S("K")
-_S("L")
-_S("M")
-_S("N")
-_S("O")
-_S("P")
-_S("Q")
-_S("R")
-_S("S")
-_S("T")
-_S("U")
-_S("V")
-_S("W")
-_S("X")
-_S("Y")
-_S("Z")
-_S("bracketleft")
-_S("backslash")
-_S("bracketright")
-_S("asciicircum")
-_S("underscore")
-_S("quoteleft")
-_S("a")
-_S("b")
-_S("c")
-_S("d")
-_S("e")
-_S("f")
-_S("g")
-_S("h")
-_S("i")
-_S("j")
-_S("k")
-_S("l")
-_S("m")
-_S("n")
-_S("o")
-_S("p")
-_S("q")
-_S("r")
-_S("s")
-_S("t")
-_S("u")
-_S("v")
-_S("w")
-_S("x")
-_S("y")
-_S("z")
-_S("braceleft")
-_S("bar")
-_S("braceright")
-_S("asciitilde")
-_S("exclamdown")
-_S("cent")
-_S("sterling")
-_S("fraction")
-_S("yen")
-_S("florin")
-_S("section")
-_S("currency")
-_S("quotesingle")
-_S("quotedblleft")
-_S("guillemotleft")
-_S("guilsinglleft")
-_S("guilsinglright")
-_S("fi")
-_S("fl")
-_S("endash")
-_S("dagger")
-_S("daggerdbl")
-_S("periodcentered")
-_S("paragraph")
-_S("bullet")
-_S("quotesinglbase")
-_S("quotedblbase")
-_S("quotedblright")
-_S("guillemotright")
-_S("ellipsis")
-_S("perthousand")
-_S("questiondown")
-_S("grave")
-_S("acute")
-_S("circumflex")
-_S("tilde")
-_S("macron")
-_S("breve")
-_S("dotaccent")
-_S("dieresis")
-_S("ring")
-_S("cedilla")
-_S("hungarumlaut")
-_S("ogonek")
-_S("caron")
-_S("emdash")
-_S("AE")
-_S("ordfeminine")
-_S("Lslash")
-_S("Oslash")
-_S("OE")
-_S("ordmasculine")
-_S("ae")
-_S("dotlessi")
-_S("lslash")
-_S("oslash")
-_S("oe")
-_S("germandbls")
-_S("onesuperior")
-_S("logicalnot")
-_S("mu")
-_S("trademark")
-_S("Eth")
-_S("onehalf")
-_S("plusminus")
-_S("Thorn")
-_S("onequarter")
-_S("divide")
-_S("brokenbar")
-_S("degree")
-_S("thorn")
-_S("threequarters")
-_S("twosuperior")
-_S("registered")
-_S("minus")
-_S("eth")
-_S("multiply")
-_S("threesuperior")
-_S("copyright")
-_S("Aacute")
-_S("Acircumflex")
-_S("Adieresis")
-_S("Agrave")
-_S("Aring")
-_S("Atilde")
-_S("Ccedilla")
-_S("Eacute")
-_S("Ecircumflex")
-_S("Edieresis")
-_S("Egrave")
-_S("Iacute")
-_S("Icircumflex")
-_S("Idieresis")
-_S("Igrave")
-_S("Ntilde")
-_S("Oacute")
-_S("Ocircumflex")
-_S("Odieresis")
-_S("Ograve")
-_S("Otilde")
-_S("Scaron")
-_S("Uacute")
-_S("Ucircumflex")
-_S("Udieresis")
-_S("Ugrave")
-_S("Yacute")
-_S("Ydieresis")
-_S("Zcaron")
-_S("aacute")
-_S("acircumflex")
-_S("adieresis")
-_S("agrave")
-_S("aring")
-_S("atilde")
-_S("ccedilla")
-_S("eacute")
-_S("ecircumflex")
-_S("edieresis")
-_S("egrave")
-_S("iacute")
-_S("icircumflex")
-_S("idieresis")
-_S("igrave")
-_S("ntilde")
-_S("oacute")
-_S("ocircumflex")
-_S("odieresis")
-_S("ograve")
-_S("otilde")
-_S("scaron")
-_S("uacute")
-_S("ucircumflex")
-_S("udieresis")
-_S("ugrave")
-_S("yacute")
-_S("ydieresis")
-_S("zcaron")
-_S("exclamsmall")
-_S("Hungarumlautsmall")
-_S("dollaroldstyle")
-_S("dollarsuperior")
-_S("ampersandsmall")
-_S("Acutesmall")
-_S("parenleftsuperior")
-_S("parenrightsuperior")
-_S("twodotenleader")
-_S("onedotenleader")
-_S("zerooldstyle")
-_S("oneoldstyle")
-_S("twooldstyle")
-_S("threeoldstyle")
-_S("fouroldstyle")
-_S("fiveoldstyle")
-_S("sixoldstyle")
-_S("sevenoldstyle")
-_S("eightoldstyle")
-_S("nineoldstyle")
-_S("commasuperior")
-_S("threequartersemdash")
-_S("periodsuperior")
-_S("questionsmall")
-_S("asuperior")
-_S("bsuperior")
-_S("centsuperior")
-_S("dsuperior")
-_S("esuperior")
-_S("isuperior")
-_S("lsuperior")
-_S("msuperior")
-_S("nsuperior")
-_S("osuperior")
-_S("rsuperior")
-_S("ssuperior")
-_S("tsuperior")
-_S("ff")
-_S("ffi")
-_S("ffl")
-_S("parenleftinferior")
-_S("parenrightinferior")
-_S("Circumflexsmall")
-_S("hyphensuperior")
-_S("Gravesmall")
-_S("Asmall")
-_S("Bsmall")
-_S("Csmall")
-_S("Dsmall")
-_S("Esmall")
-_S("Fsmall")
-_S("Gsmall")
-_S("Hsmall")
-_S("Ismall")
-_S("Jsmall")
-_S("Ksmall")
-_S("Lsmall")
-_S("Msmall")
-_S("Nsmall")
-_S("Osmall")
-_S("Psmall")
-_S("Qsmall")
-_S("Rsmall")
-_S("Ssmall")
-_S("Tsmall")
-_S("Usmall")
-_S("Vsmall")
-_S("Wsmall")
-_S("Xsmall")
-_S("Ysmall")
-_S("Zsmall")
-_S("colonmonetary")
-_S("onefitted")
-_S("rupiah")
-_S("Tildesmall")
-_S("exclamdownsmall")
-_S("centoldstyle")
-_S("Lslashsmall")
-_S("Scaronsmall")
-_S("Zcaronsmall")
-_S("Dieresissmall")
-_S("Brevesmall")
-_S("Caronsmall")
-_S("Dotaccentsmall")
-_S("Macronsmall")
-_S("figuredash")
-_S("hypheninferior")
-_S("Ogoneksmall")
-_S("Ringsmall")
-_S("Cedillasmall")
-_S("questiondownsmall")
-_S("oneeighth")
-_S("threeeighths")
-_S("fiveeighths")
-_S("seveneighths")
-_S("onethird")
-_S("twothirds")
-_S("zerosuperior")
-_S("foursuperior")
-_S("fivesuperior")
-_S("sixsuperior")
-_S("sevensuperior")
-_S("eightsuperior")
-_S("ninesuperior")
-_S("zeroinferior")
-_S("oneinferior")
-_S("twoinferior")
-_S("threeinferior")
-_S("fourinferior")
-_S("fiveinferior")
-_S("sixinferior")
-_S("seveninferior")
-_S("eightinferior")
-_S("nineinferior")
-_S("centinferior")
-_S("dollarinferior")
-_S("periodinferior")
-_S("commainferior")
-_S("Agravesmall")
-_S("Aacutesmall")
-_S("Acircumflexsmall")
-_S("Atildesmall")
-_S("Adieresissmall")
-_S("Aringsmall")
-_S("AEsmall")
-_S("Ccedillasmall")
-_S("Egravesmall")
-_S("Eacutesmall")
-_S("Ecircumflexsmall")
-_S("Edieresissmall")
-_S("Igravesmall")
-_S("Iacutesmall")
-_S("Icircumflexsmall")
-_S("Idieresissmall")
-_S("Ethsmall")
-_S("Ntildesmall")
-_S("Ogravesmall")
-_S("Oacutesmall")
-_S("Ocircumflexsmall")
-_S("Otildesmall")
-_S("Odieresissmall")
-_S("OEsmall")
-_S("Oslashsmall")
-_S("Ugravesmall")
-_S("Uacutesmall")
-_S("Ucircumflexsmall")
-_S("Udieresissmall")
-_S("Yacutesmall")
-_S("Thornsmall")
-_S("Ydieresissmall")
-_S("001.000")
-_S("001.001")
-_S("001.002")
-_S("001.003")
-_S("Black")
-_S("Bold")
-_S("Book")
-_S("Light")
-_S("Medium")
-_S("Regular")
-_S("Roman")
-_S("Semibold")
+HB_STR(".notdef")
+HB_STR("space")
+HB_STR("exclam")
+HB_STR("quotedbl")
+HB_STR("numbersign")
+HB_STR("dollar")
+HB_STR("percent")
+HB_STR("ampersand")
+HB_STR("quoteright")
+HB_STR("parenleft")
+HB_STR("parenright")
+HB_STR("asterisk")
+HB_STR("plus")
+HB_STR("comma")
+HB_STR("hyphen")
+HB_STR("period")
+HB_STR("slash")
+HB_STR("zero")
+HB_STR("one")
+HB_STR("two")
+HB_STR("three")
+HB_STR("four")
+HB_STR("five")
+HB_STR("six")
+HB_STR("seven")
+HB_STR("eight")
+HB_STR("nine")
+HB_STR("colon")
+HB_STR("semicolon")
+HB_STR("less")
+HB_STR("equal")
+HB_STR("greater")
+HB_STR("question")
+HB_STR("at")
+HB_STR("A")
+HB_STR("B")
+HB_STR("C")
+HB_STR("D")
+HB_STR("E")
+HB_STR("F")
+HB_STR("G")
+HB_STR("H")
+HB_STR("I")
+HB_STR("J")
+HB_STR("K")
+HB_STR("L")
+HB_STR("M")
+HB_STR("N")
+HB_STR("O")
+HB_STR("P")
+HB_STR("Q")
+HB_STR("R")
+HB_STR("S")
+HB_STR("T")
+HB_STR("U")
+HB_STR("V")
+HB_STR("W")
+HB_STR("X")
+HB_STR("Y")
+HB_STR("Z")
+HB_STR("bracketleft")
+HB_STR("backslash")
+HB_STR("bracketright")
+HB_STR("asciicircum")
+HB_STR("underscore")
+HB_STR("quoteleft")
+HB_STR("a")
+HB_STR("b")
+HB_STR("c")
+HB_STR("d")
+HB_STR("e")
+HB_STR("f")
+HB_STR("g")
+HB_STR("h")
+HB_STR("i")
+HB_STR("j")
+HB_STR("k")
+HB_STR("l")
+HB_STR("m")
+HB_STR("n")
+HB_STR("o")
+HB_STR("p")
+HB_STR("q")
+HB_STR("r")
+HB_STR("s")
+HB_STR("t")
+HB_STR("u")
+HB_STR("v")
+HB_STR("w")
+HB_STR("x")
+HB_STR("y")
+HB_STR("z")
+HB_STR("braceleft")
+HB_STR("bar")
+HB_STR("braceright")
+HB_STR("asciitilde")
+HB_STR("exclamdown")
+HB_STR("cent")
+HB_STR("sterling")
+HB_STR("fraction")
+HB_STR("yen")
+HB_STR("florin")
+HB_STR("section")
+HB_STR("currency")
+HB_STR("quotesingle")
+HB_STR("quotedblleft")
+HB_STR("guillemotleft")
+HB_STR("guilsinglleft")
+HB_STR("guilsinglright")
+HB_STR("fi")
+HB_STR("fl")
+HB_STR("endash")
+HB_STR("dagger")
+HB_STR("daggerdbl")
+HB_STR("periodcentered")
+HB_STR("paragraph")
+HB_STR("bullet")
+HB_STR("quotesinglbase")
+HB_STR("quotedblbase")
+HB_STR("quotedblright")
+HB_STR("guillemotright")
+HB_STR("ellipsis")
+HB_STR("perthousand")
+HB_STR("questiondown")
+HB_STR("grave")
+HB_STR("acute")
+HB_STR("circumflex")
+HB_STR("tilde")
+HB_STR("macron")
+HB_STR("breve")
+HB_STR("dotaccent")
+HB_STR("dieresis")
+HB_STR("ring")
+HB_STR("cedilla")
+HB_STR("hungarumlaut")
+HB_STR("ogonek")
+HB_STR("caron")
+HB_STR("emdash")
+HB_STR("AE")
+HB_STR("ordfeminine")
+HB_STR("Lslash")
+HB_STR("Oslash")
+HB_STR("OE")
+HB_STR("ordmasculine")
+HB_STR("ae")
+HB_STR("dotlessi")
+HB_STR("lslash")
+HB_STR("oslash")
+HB_STR("oe")
+HB_STR("germandbls")
+HB_STR("onesuperior")
+HB_STR("logicalnot")
+HB_STR("mu")
+HB_STR("trademark")
+HB_STR("Eth")
+HB_STR("onehalf")
+HB_STR("plusminus")
+HB_STR("Thorn")
+HB_STR("onequarter")
+HB_STR("divide")
+HB_STR("brokenbar")
+HB_STR("degree")
+HB_STR("thorn")
+HB_STR("threequarters")
+HB_STR("twosuperior")
+HB_STR("registered")
+HB_STR("minus")
+HB_STR("eth")
+HB_STR("multiply")
+HB_STR("threesuperior")
+HB_STR("copyright")
+HB_STR("Aacute")
+HB_STR("Acircumflex")
+HB_STR("Adieresis")
+HB_STR("Agrave")
+HB_STR("Aring")
+HB_STR("Atilde")
+HB_STR("Ccedilla")
+HB_STR("Eacute")
+HB_STR("Ecircumflex")
+HB_STR("Edieresis")
+HB_STR("Egrave")
+HB_STR("Iacute")
+HB_STR("Icircumflex")
+HB_STR("Idieresis")
+HB_STR("Igrave")
+HB_STR("Ntilde")
+HB_STR("Oacute")
+HB_STR("Ocircumflex")
+HB_STR("Odieresis")
+HB_STR("Ograve")
+HB_STR("Otilde")
+HB_STR("Scaron")
+HB_STR("Uacute")
+HB_STR("Ucircumflex")
+HB_STR("Udieresis")
+HB_STR("Ugrave")
+HB_STR("Yacute")
+HB_STR("Ydieresis")
+HB_STR("Zcaron")
+HB_STR("aacute")
+HB_STR("acircumflex")
+HB_STR("adieresis")
+HB_STR("agrave")
+HB_STR("aring")
+HB_STR("atilde")
+HB_STR("ccedilla")
+HB_STR("eacute")
+HB_STR("ecircumflex")
+HB_STR("edieresis")
+HB_STR("egrave")
+HB_STR("iacute")
+HB_STR("icircumflex")
+HB_STR("idieresis")
+HB_STR("igrave")
+HB_STR("ntilde")
+HB_STR("oacute")
+HB_STR("ocircumflex")
+HB_STR("odieresis")
+HB_STR("ograve")
+HB_STR("otilde")
+HB_STR("scaron")
+HB_STR("uacute")
+HB_STR("ucircumflex")
+HB_STR("udieresis")
+HB_STR("ugrave")
+HB_STR("yacute")
+HB_STR("ydieresis")
+HB_STR("zcaron")
+HB_STR("exclamsmall")
+HB_STR("Hungarumlautsmall")
+HB_STR("dollaroldstyle")
+HB_STR("dollarsuperior")
+HB_STR("ampersandsmall")
+HB_STR("Acutesmall")
+HB_STR("parenleftsuperior")
+HB_STR("parenrightsuperior")
+HB_STR("twodotenleader")
+HB_STR("onedotenleader")
+HB_STR("zerooldstyle")
+HB_STR("oneoldstyle")
+HB_STR("twooldstyle")
+HB_STR("threeoldstyle")
+HB_STR("fouroldstyle")
+HB_STR("fiveoldstyle")
+HB_STR("sixoldstyle")
+HB_STR("sevenoldstyle")
+HB_STR("eightoldstyle")
+HB_STR("nineoldstyle")
+HB_STR("commasuperior")
+HB_STR("threequartersemdash")
+HB_STR("periodsuperior")
+HB_STR("questionsmall")
+HB_STR("asuperior")
+HB_STR("bsuperior")
+HB_STR("centsuperior")
+HB_STR("dsuperior")
+HB_STR("esuperior")
+HB_STR("isuperior")
+HB_STR("lsuperior")
+HB_STR("msuperior")
+HB_STR("nsuperior")
+HB_STR("osuperior")
+HB_STR("rsuperior")
+HB_STR("ssuperior")
+HB_STR("tsuperior")
+HB_STR("ff")
+HB_STR("ffi")
+HB_STR("ffl")
+HB_STR("parenleftinferior")
+HB_STR("parenrightinferior")
+HB_STR("Circumflexsmall")
+HB_STR("hyphensuperior")
+HB_STR("Gravesmall")
+HB_STR("Asmall")
+HB_STR("Bsmall")
+HB_STR("Csmall")
+HB_STR("Dsmall")
+HB_STR("Esmall")
+HB_STR("Fsmall")
+HB_STR("Gsmall")
+HB_STR("Hsmall")
+HB_STR("Ismall")
+HB_STR("Jsmall")
+HB_STR("Ksmall")
+HB_STR("Lsmall")
+HB_STR("Msmall")
+HB_STR("Nsmall")
+HB_STR("Osmall")
+HB_STR("Psmall")
+HB_STR("Qsmall")
+HB_STR("Rsmall")
+HB_STR("Ssmall")
+HB_STR("Tsmall")
+HB_STR("Usmall")
+HB_STR("Vsmall")
+HB_STR("Wsmall")
+HB_STR("Xsmall")
+HB_STR("Ysmall")
+HB_STR("Zsmall")
+HB_STR("colonmonetary")
+HB_STR("onefitted")
+HB_STR("rupiah")
+HB_STR("Tildesmall")
+HB_STR("exclamdownsmall")
+HB_STR("centoldstyle")
+HB_STR("Lslashsmall")
+HB_STR("Scaronsmall")
+HB_STR("Zcaronsmall")
+HB_STR("Dieresissmall")
+HB_STR("Brevesmall")
+HB_STR("Caronsmall")
+HB_STR("Dotaccentsmall")
+HB_STR("Macronsmall")
+HB_STR("figuredash")
+HB_STR("hypheninferior")
+HB_STR("Ogoneksmall")
+HB_STR("Ringsmall")
+HB_STR("Cedillasmall")
+HB_STR("questiondownsmall")
+HB_STR("oneeighth")
+HB_STR("threeeighths")
+HB_STR("fiveeighths")
+HB_STR("seveneighths")
+HB_STR("onethird")
+HB_STR("twothirds")
+HB_STR("zerosuperior")
+HB_STR("foursuperior")
+HB_STR("fivesuperior")
+HB_STR("sixsuperior")
+HB_STR("sevensuperior")
+HB_STR("eightsuperior")
+HB_STR("ninesuperior")
+HB_STR("zeroinferior")
+HB_STR("oneinferior")
+HB_STR("twoinferior")
+HB_STR("threeinferior")
+HB_STR("fourinferior")
+HB_STR("fiveinferior")
+HB_STR("sixinferior")
+HB_STR("seveninferior")
+HB_STR("eightinferior")
+HB_STR("nineinferior")
+HB_STR("centinferior")
+HB_STR("dollarinferior")
+HB_STR("periodinferior")
+HB_STR("commainferior")
+HB_STR("Agravesmall")
+HB_STR("Aacutesmall")
+HB_STR("Acircumflexsmall")
+HB_STR("Atildesmall")
+HB_STR("Adieresissmall")
+HB_STR("Aringsmall")
+HB_STR("AEsmall")
+HB_STR("Ccedillasmall")
+HB_STR("Egravesmall")
+HB_STR("Eacutesmall")
+HB_STR("Ecircumflexsmall")
+HB_STR("Edieresissmall")
+HB_STR("Igravesmall")
+HB_STR("Iacutesmall")
+HB_STR("Icircumflexsmall")
+HB_STR("Idieresissmall")
+HB_STR("Ethsmall")
+HB_STR("Ntildesmall")
+HB_STR("Ogravesmall")
+HB_STR("Oacutesmall")
+HB_STR("Ocircumflexsmall")
+HB_STR("Otildesmall")
+HB_STR("Odieresissmall")
+HB_STR("OEsmall")
+HB_STR("Oslashsmall")
+HB_STR("Ugravesmall")
+HB_STR("Uacutesmall")
+HB_STR("Ucircumflexsmall")
+HB_STR("Udieresissmall")
+HB_STR("Yacutesmall")
+HB_STR("Thornsmall")
+HB_STR("Ydieresissmall")
+HB_STR("001.000")
+HB_STR("001.001")
+HB_STR("001.002")
+HB_STR("001.003")
+HB_STR("Black")
+HB_STR("Bold")
+HB_STR("Book")
+HB_STR("Light")
+HB_STR("Medium")
+HB_STR("Regular")
+HB_STR("Roman")
+HB_STR("Semibold")
 
 #endif /* HB_OT_CFF1_STD_STR_HH */

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	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -466,6 +466,11 @@
   {
     const auto &glyf = *ot_face->glyf;
     auto *scratch = glyf.acquire_scratch ();
+    if (unlikely (!scratch))
+    {
+      ot_font->h.release_advance_cache (advance_cache);
+      goto fallback;
+    }
     OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
 
     for (unsigned int i = 0; i < count; i++)
@@ -586,6 +591,11 @@
   {
     const auto &glyf = *ot_face->glyf;
     auto *scratch = glyf.acquire_scratch ();
+    if (unlikely (!scratch))
+    {
+      ot_font->v.release_advance_cache (advance_cache);
+      goto fallback;
+    }
     OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
 
     for (unsigned int i = 0; i < count; i++)
@@ -664,7 +674,7 @@
 	hb_position_t origin;
 	unsigned cv;
 	if (origin_cache->get (*first_glyph, &cv))
-	  origin = font->y_scale < 0 ? -cv : cv;
+	  origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
 	else
 	{
 	  origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph));
@@ -688,7 +698,7 @@
 	hb_position_t origin;
 	unsigned cv;
 	if (origin_cache->get (*first_glyph, &cv))
-	  origin = font->y_scale < 0 ? -cv : cv;
+	  origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
 	else
 	{
 	  origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph) +
@@ -717,6 +727,11 @@
   if (origin_cache && vmtx.has_data() && glyf.has_data ())
   {
     auto *scratch = glyf.acquire_scratch ();
+    if (unlikely (!scratch))
+    {
+      ot_font->v_origin.release_origin_cache (origin_cache);
+      return false;
+    }
     OT::hb_scalar_cache_t *gvar_cache = font->has_nonzero_coords ?
 					ot_font->draw.acquire_gvar_cache (*ot_face->gvar) :
 					nullptr;
@@ -726,7 +741,7 @@
       hb_position_t origin;
       unsigned cv;
       if (origin_cache->get (*first_glyph, &cv))
-	origin = font->y_scale < 0 ? -cv : cv;
+	origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
       else
       {
 	origin = font->em_scalef_y (glyf.get_v_origin_with_var_unscaled (*first_glyph, font, *scratch, gvar_cache));
@@ -760,7 +775,7 @@
       unsigned cv;
 
       if (origin_cache->get (*first_glyph, &cv))
-	origin = font->y_scale < 0 ? -cv : cv;
+	origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv);
       else
       {
 	hb_glyph_extents_t extents = {0};

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -371,9 +371,9 @@
 					    hb_scalar_cache_t *store_cache = nullptr) const
     {
       unsigned int advance = get_advance_without_var_unscaled (glyph);
-      return advance + roundf (var_table->get_advance_delta_unscaled (glyph,
+      return hb_max(0.0f, advance + roundf (var_table->get_advance_delta_unscaled (glyph,
 								      font->coords, font->num_coords,
-								      store_cache));
+								      store_cache)));
     }
 #endif
 

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	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -1337,7 +1337,7 @@
     TRACE_DISPATCH (this, lookup_type);
     unsigned int count = get_subtable_count ();
     for (unsigned int i = 0; i < count; i++) {
-      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, std::forward<Ts> (ds)...);
+      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, ds...);
       if (c->stop_sublookup_iteration (r))
 	return_trace (r);
     }
@@ -2078,7 +2078,7 @@
     }
   }
   unsigned int get_class (hb_codepoint_t glyph_id,
-			  hb_ot_lookup_cache_t *cache) const
+			  hb_ot_layout_mapping_cache_t *cache) const
   {
     unsigned klass;
     if (cache && cache->get (glyph_id, &klass)) return klass;
@@ -2575,7 +2575,7 @@
       return scratch_cache;
     }
 
-    auto *cache = (hb_scalar_cache_t *) hb_malloc (sizeof (hb_scalar_cache_t) - sizeof (values) + sizeof (values[0]) * count);
+    auto *cache = (hb_scalar_cache_t *) hb_malloc (sizeof (hb_scalar_cache_t) - sizeof (static_values) + sizeof (static_values[0]) * count);
     if (unlikely (!cache)) return (hb_scalar_cache_t *) &Null(hb_scalar_cache_t);
 
     cache->length = count;
@@ -2593,6 +2593,7 @@
 
   void clear ()
   {
+    auto *values = &static_values[0];
     for (unsigned i = 0; i < length; i++)
       values[i] = INVALID;
   }
@@ -2605,6 +2606,7 @@
       *value = 0.f;
       return true;
     }
+    auto *values = &static_values[0];
     auto *cached_value = &values[i];
     if (*cached_value != INVALID)
     {
@@ -2618,6 +2620,7 @@
   void set (unsigned i, float value)
   {
     if (unlikely (i >= length)) return;
+    auto *values = &static_values[0];
     auto *cached_value = &values[i];
     *cached_value = roundf(value * MULTIPLIER);
   }
@@ -2624,7 +2627,7 @@
 
   private:
   unsigned length;
-  mutable hb_atomic_t<int> values[STATIC_LENGTH];
+  mutable hb_atomic_t<int> static_values[STATIC_LENGTH];
 };
 
 struct VarRegionList
@@ -3439,7 +3442,7 @@
     for (unsigned i = 0; i < count; i++)
     {
       hb_inc_bimap_t *map = inner_maps.push ();
-      if (!c->propagate_error(inner_maps))
+      if (unlikely (!c->propagate_error(inner_maps)))
         return_trace(nullptr);
       auto &data = this+dataSets[i];
 

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	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -455,7 +455,7 @@
   HB_ALWAYS_INLINE
 #endif
   may_skip_t may_skip (const context_t *c,
-		       const hb_glyph_info_t       &info) const
+		       const hb_glyph_info_t &info) const
   {
     if (!c->check_glyph_property (&info, lookup_props))
       return SKIP_YES;
@@ -470,7 +470,7 @@
   }
 
   public:
-  unsigned int lookup_props = 0;
+  unsigned int lookup_props = (unsigned) -1;
   hb_mask_t mask = -1;
   bool ignore_zwnj = false;
   bool ignore_zwj = false;
@@ -670,8 +670,14 @@
 {
   const char *get_name () { return "APPLY"; }
   typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
+
   template <typename T>
-  return_t dispatch (const T &obj) { return obj.apply (this); }
+  static inline auto apply_ (const T &obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (return_t, obj.apply (c, nullptr) )
+  template <typename T>
+  static inline auto apply_ (const T &obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (return_t, obj.apply (c) )
+  template <typename T>
+  return_t dispatch (const T &obj) { return apply_(obj, this, hb_prioritize); }
+
   static return_t default_return_value () { return false; }
   bool stop_sublookup_iteration (return_t r) const { return r; }
   return_t recurse (unsigned int sub_lookup_index)
@@ -706,7 +712,8 @@
   hb_direction_t direction;
   hb_mask_t lookup_mask = 1;
   unsigned int lookup_index = (unsigned) -1;
-  unsigned int lookup_props = 0;
+  unsigned int lookup_props = (unsigned) -1;
+  unsigned int cached_props = (unsigned) -1; /* Cached glyph properties for the current lookup. */
   unsigned int nesting_level_left = HB_MAX_NESTING_LEVEL;
 
   bool has_glyph_classes;
@@ -772,15 +779,22 @@
     return buffer->random_state;
   }
 
-  bool match_properties_mark (hb_codepoint_t  glyph,
+  HB_ALWAYS_INLINE
+  HB_HOT
+  bool match_properties_mark (const hb_glyph_info_t *info,
 			      unsigned int    glyph_props,
-			      unsigned int    match_props) const
+			      unsigned int    match_props,
+			      bool            cached) const
   {
     /* If using mark filtering sets, the high short of
      * match_props has the set index.
      */
     if (match_props & LookupFlag::UseMarkFilteringSet)
-      return gdef_accel.mark_set_covers (match_props >> 16, glyph);
+    {
+      if (cached && match_props == cached_props)
+	return _hb_glyph_info_matches (info);
+      return gdef_accel.mark_set_covers (match_props >> 16, info->codepoint);
+    }
 
     /* The second byte of match_props has the meaning
      * "ignore marks of attachment type different than
@@ -796,7 +810,8 @@
   HB_ALWAYS_INLINE
 #endif
   bool check_glyph_property (const hb_glyph_info_t *info,
-			     unsigned int  match_props) const
+			     unsigned match_props,
+			     bool cached = true) const
   {
     unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
 
@@ -807,7 +822,7 @@
       return false;
 
     if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
-      return match_properties_mark (info->codepoint, glyph_props, match_props);
+      return match_properties_mark (info, glyph_props, match_props, cached);
 
     return true;
   }
@@ -849,6 +864,10 @@
     }
     else
       _hb_glyph_info_set_glyph_props (&buffer->cur(), props);
+
+    if (cached_props != (unsigned) -1)
+      _hb_glyph_info_set_match (&buffer->cur(),
+				check_glyph_property (&buffer->cur(), cached_props, false));
   }
 
   void replace_glyph (hb_codepoint_t glyph_index)
@@ -875,7 +894,7 @@
   }
 };
 
-enum class hb_ot_lookup_cache_op_t
+enum class hb_ot_subtable_cache_op_t
 {
   CREATE,
   ENTER,
@@ -886,43 +905,49 @@
 struct hb_accelerate_subtables_context_t :
        hb_dispatch_context_t<hb_accelerate_subtables_context_t>
 {
-  template <typename Type>
-  static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c)
+  template <typename T>
+  static inline auto apply_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<1>) HB_RETURN (bool, obj->apply (c, external_cache) )
+  template <typename T>
+  static inline auto apply_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
+  template <typename T>
+  static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c, void *external_cache)
   {
-    const Type *typed_obj = (const Type *) obj;
-    return typed_obj->apply (c);
+    const T *typed_obj = (const T *) obj;
+    return apply_ (typed_obj, c, external_cache, hb_prioritize);
   }
 
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
   template <typename T>
-  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply_cached (c) )
+  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<2>) HB_RETURN (bool, obj->apply_cached (c, external_cache) )
   template <typename T>
-  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
-  template <typename Type>
-  static inline bool apply_cached_to (const void *obj, hb_ot_apply_context_t *c)
+  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<1>) HB_RETURN (bool, obj->apply (c, external_cache) )
+  template <typename T>
+  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
+  template <typename T>
+  static inline bool apply_cached_to (const void *obj, hb_ot_apply_context_t *c, void *external_cache)
   {
-    const Type *typed_obj = (const Type *) obj;
-    return apply_cached_ (typed_obj, c, hb_prioritize);
+    const T *typed_obj = (const T *) obj;
+    return apply_cached_ (typed_obj, c, external_cache, hb_prioritize);
   }
 
   template <typename T>
   static inline auto cache_func_ (void *p,
-				  hb_ot_lookup_cache_op_t op,
+				  hb_ot_subtable_cache_op_t op,
 				  hb_priority<1>) HB_RETURN (void *, T::cache_func (p, op) )
   template <typename T=void>
   static inline void * cache_func_ (void *p,
-				    hb_ot_lookup_cache_op_t op HB_UNUSED,
-				    hb_priority<0>) { return (void *) false; }
+				    hb_ot_subtable_cache_op_t op HB_UNUSED,
+				    hb_priority<0>) { return nullptr; }
   template <typename Type>
   static inline void * cache_func_to (void *p,
-				      hb_ot_lookup_cache_op_t op)
+				      hb_ot_subtable_cache_op_t op)
   {
     return cache_func_<Type> (p, op, hb_prioritize);
   }
 #endif
 
-  typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c);
-  typedef void * (*hb_cache_func_t) (void *p, hb_ot_lookup_cache_op_t op);
+  typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c, void *external_cache);
+  typedef void * (*hb_cache_func_t) (void *p, hb_ot_subtable_cache_op_t op);
 
   struct hb_applicable_t
   {
@@ -943,27 +968,37 @@
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
       apply_cached_func = apply_cached_func_;
       cache_func = cache_func_;
+      external_cache = cache_create ();
 #endif
       digest.init ();
       obj_.get_coverage ().collect_coverage (&digest);
     }
 
+#ifdef HB_NO_OT_LAYOUT_LOOKUP_CACHE
     bool apply (hb_ot_apply_context_t *c) const
     {
-      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
+      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c, nullptr);
     }
-#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+#else
+    bool apply (hb_ot_apply_context_t *c) const
+    {
+      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c, external_cache);
+    }
     bool apply_cached (hb_ot_apply_context_t *c) const
     {
-      return digest.may_have (c->buffer->cur().codepoint) &&  apply_cached_func (obj, c);
+      return digest.may_have (c->buffer->cur().codepoint) &&  apply_cached_func (obj, c, external_cache);
     }
+    void *cache_create () const
+    {
+	return cache_func (nullptr, hb_ot_subtable_cache_op_t::CREATE);
+    }
     bool cache_enter (hb_ot_apply_context_t *c) const
     {
-      return (bool) cache_func (c, hb_ot_lookup_cache_op_t::ENTER);
+      return (bool) cache_func (c, hb_ot_subtable_cache_op_t::ENTER);
     }
     void cache_leave (hb_ot_apply_context_t *c) const
     {
-      cache_func (c, hb_ot_lookup_cache_op_t::LEAVE);
+      cache_func (c, hb_ot_subtable_cache_op_t::LEAVE);
     }
 #endif
 
@@ -973,6 +1008,7 @@
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
     hb_apply_func_t apply_cached_func;
     hb_cache_func_t cache_func;
+    void *external_cache;
 #endif
     hb_set_digest_t digest;
   };
@@ -1008,10 +1044,10 @@
      * and we allocate the cache opportunity to the costliest subtable.
      */
     unsigned cost = cache_cost (obj, hb_prioritize);
-    if (cost > cache_user_cost)
+    if (cost > subtable_cache_user_cost)
     {
-      cache_user_idx = i - 1;
-      cache_user_cost = cost;
+      subtable_cache_user_idx = i - 1;
+      subtable_cache_user_cost = cost;
     }
 #endif
 
@@ -1026,8 +1062,8 @@
   unsigned i = 0;
 
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-  unsigned cache_user_idx = (unsigned) -1;
-  unsigned cache_user_cost = 0;
+  unsigned subtable_cache_user_idx = (unsigned) -1;
+  unsigned subtable_cache_user_cost = 0;
 #endif
 };
 
@@ -1176,39 +1212,51 @@
   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   return class_def.get_class (info.codepoint) == value;
 }
-static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, const void *data)
+static inline unsigned get_class_cached (const ClassDef &class_def, hb_glyph_info_t &info)
 {
   unsigned klass = info.syllable();
   if (klass < 255)
-    return klass == value;
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+    return klass;
   klass = class_def.get_class (info.codepoint);
   if (likely (klass < 255))
     info.syllable() = klass;
-  return klass == value;
+  return klass;
 }
-static inline bool match_class_cached1 (hb_glyph_info_t &info, unsigned value, const void *data)
+static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, const void *data)
 {
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  return get_class_cached (class_def, info) == value;
+}
+static inline unsigned get_class_cached1 (const ClassDef &class_def, hb_glyph_info_t &info)
+{
   unsigned klass = info.syllable() & 0x0F;
   if (klass < 15)
-    return klass == value;
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+    return klass;
   klass = class_def.get_class (info.codepoint);
   if (likely (klass < 15))
     info.syllable() = (info.syllable() & 0xF0) | klass;
-  return klass == value;
+  return klass;
 }
-static inline bool match_class_cached2 (hb_glyph_info_t &info, unsigned value, const void *data)
+static inline bool match_class_cached1 (hb_glyph_info_t &info, unsigned value, const void *data)
 {
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  return get_class_cached1 (class_def, info) == value;
+}
+static inline unsigned get_class_cached2 (const ClassDef &class_def, hb_glyph_info_t &info)
+{
   unsigned klass = (info.syllable() & 0xF0) >> 4;
   if (klass < 15)
-    return klass == value;
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+    return klass;
   klass = class_def.get_class (info.codepoint);
   if (likely (klass < 15))
     info.syllable() = (info.syllable() & 0x0F) | (klass << 4);
-  return klass == value;
+  return klass;
 }
+static inline bool match_class_cached2 (hb_glyph_info_t &info, unsigned value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  return get_class_cached2 (class_def, info) == value;
+}
 static inline bool match_coverage (hb_glyph_info_t &info, unsigned value, const void *data)
 {
   Offset16To<Coverage> coverage;
@@ -1321,7 +1369,7 @@
 	if (ligbase == LIGBASE_NOT_CHECKED)
 	{
 	  bool found = false;
-	  const auto *out = buffer->out_info;
+	  auto *out = buffer->out_info;
 	  unsigned int j = buffer->out_len;
 	  while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
 	  {
@@ -1979,6 +2027,37 @@
   return ret;
 }
 
+static inline void * context_cache_func (void *p, hb_ot_subtable_cache_op_t op)
+{
+  switch (op)
+  {
+    case hb_ot_subtable_cache_op_t::CREATE:
+      return nullptr;
+    case hb_ot_subtable_cache_op_t::ENTER:
+    {
+      hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
+      if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+	return (void *) false;
+      auto &info = c->buffer->info;
+      unsigned count = c->buffer->len;
+      for (unsigned i = 0; i < count; i++)
+	info[i].syllable() = 255;
+      c->new_syllables = 255;
+      return (void *) true;
+    }
+    case hb_ot_subtable_cache_op_t::LEAVE:
+    {
+      hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
+      c->new_syllables = (unsigned) -1;
+      HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+      return nullptr;
+    }
+    case hb_ot_subtable_cache_op_t::DESTROY:
+      return nullptr;
+  }
+  return nullptr;
+}
+
 template <typename Types>
 struct Rule
 {
@@ -2607,41 +2686,14 @@
 
   unsigned cache_cost () const
   {
-    unsigned c = (this+classDef).cost () * ruleSet.len;
-    return c >= 4 ? c : 0;
+    return (this+classDef).cost ();
   }
-  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
+  static void * cache_func (void *p, hb_ot_subtable_cache_op_t op)
   {
-    switch (op)
-    {
-      case hb_ot_lookup_cache_op_t::CREATE:
-	return (void *) true;
-      case hb_ot_lookup_cache_op_t::ENTER:
-      {
-	hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
-	if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
-	  return (void *) false;
-	auto &info = c->buffer->info;
-	unsigned count = c->buffer->len;
-	for (unsigned i = 0; i < count; i++)
-	  info[i].syllable() = 255;
-	c->new_syllables = 255;
-	return (void *) true;
-      }
-      case hb_ot_lookup_cache_op_t::LEAVE:
-      {
-	hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
-	c->new_syllables = (unsigned) -1;
-	HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
-	return nullptr;
-      }
-      case hb_ot_lookup_cache_op_t::DESTROY:
-        return nullptr;
-    }
-    return nullptr;
+    return context_cache_func (p, op);
   }
 
-  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
+  bool apply_cached (hb_ot_apply_context_t *c, void *external_cache HB_UNUSED) const { return _apply (c, true); }
   bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
   bool _apply (hb_ot_apply_context_t *c, bool cached) const
   {
@@ -2656,10 +2708,7 @@
       &class_def
     };
 
-    if (cached && c->buffer->cur().syllable() < 255)
-      index = c->buffer->cur().syllable ();
-    else
-      index = class_def.get_class (c->buffer->cur().codepoint);
+    index = cached ? get_class_cached (class_def, c->buffer->cur()) : class_def.get_class (c->buffer->cur().codepoint);
     const RuleSet &rule_set = this+ruleSet[index];
     return_trace (rule_set.apply (c, lookup_context));
   }
@@ -3858,40 +3907,14 @@
 
   unsigned cache_cost () const
   {
-    return (this+lookaheadClassDef).cost () * ruleSet.len;
+    return (this+inputClassDef).cost () + (this+lookaheadClassDef).cost ();
   }
-  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
+  static void * cache_func (void *p, hb_ot_subtable_cache_op_t op)
   {
-    switch (op)
-    {
-      case hb_ot_lookup_cache_op_t::CREATE:
-	return (void *) true;
-      case hb_ot_lookup_cache_op_t::ENTER:
-      {
-	hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
-	if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
-	  return (void *) false;
-	auto &info = c->buffer->info;
-	unsigned count = c->buffer->len;
-	for (unsigned i = 0; i < count; i++)
-	  info[i].syllable() = 255;
-	c->new_syllables = 255;
-	return (void *) true;
-      }
-      case hb_ot_lookup_cache_op_t::LEAVE:
-      {
-	hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
-	c->new_syllables = (unsigned) -1;
-	HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
-	return nullptr;
-      }
-      case hb_ot_lookup_cache_op_t::DESTROY:
-        return nullptr;
-    }
-    return nullptr;
+    return context_cache_func (p, op);
   }
 
-  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
+  bool apply_cached (hb_ot_apply_context_t *c, void *external_cache HB_UNUSED) const { return _apply (c, true); }
   bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
   bool _apply (hb_ot_apply_context_t *c, bool cached) const
   {
@@ -3914,11 +3937,9 @@
        &lookahead_class_def}
     };
 
-    // Note: Corresponds to match_class_cached2
-    if (cached && ((c->buffer->cur().syllable() & 0xF0) >> 4) < 15)
-      index = (c->buffer->cur().syllable () & 0xF0) >> 4;
-    else
-      index = input_class_def.get_class (c->buffer->cur().codepoint);
+    index = cached
+         ? get_class_cached2 (input_class_def, c->buffer->cur())
+          : input_class_def.get_class (c->buffer->cur().codepoint);
     const ChainRuleSet &rule_set = this+ruleSet[index];
     return_trace (rule_set.apply (c, lookup_context));
   }
@@ -4414,21 +4435,12 @@
       thiz->digest.union_ (subtable.digest);
 
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-    if (c_accelerate_subtables.cache_user_cost < 4)
-      c_accelerate_subtables.cache_user_idx = (unsigned) -1;
+    thiz->count = count;
+    thiz->subtable_cache_user_idx = c_accelerate_subtables.subtable_cache_user_idx;
 
-    thiz->cache_user_idx = c_accelerate_subtables.cache_user_idx;
-
-    if (thiz->cache_user_idx != (unsigned) -1)
-    {
-      thiz->cache = thiz->subtables[thiz->cache_user_idx].cache_func (nullptr, hb_ot_lookup_cache_op_t::CREATE);
-      if (!thiz->cache)
-	thiz->cache_user_idx = (unsigned) -1;
-    }
-
     for (unsigned i = 0; i < count; i++)
-      if (i != thiz->cache_user_idx)
-	thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
+      if (i != thiz->subtable_cache_user_idx)
+       thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
 #endif
 
     return thiz;
@@ -4437,11 +4449,9 @@
   void fini ()
   {
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-    if (cache)
-    {
-      assert (cache_user_idx != (unsigned) -1);
-      subtables[cache_user_idx].cache_func (cache, hb_ot_lookup_cache_op_t::DESTROY);
-    }
+    for (unsigned i = 0; i < count; i++)
+      if (subtables[i].external_cache)
+	subtables[i].cache_func (subtables[i].external_cache, hb_ot_subtable_cache_op_t::DESTROY);
 #endif
   }
 
@@ -4478,8 +4488,8 @@
   bool cache_enter (hb_ot_apply_context_t *c) const
   {
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-    return cache_user_idx != (unsigned) -1 &&
-	   subtables[cache_user_idx].cache_enter (c);
+    return subtable_cache_user_idx != (unsigned) -1 &&
+	   subtables[subtable_cache_user_idx].cache_enter (c);
 #else
     return false;
 #endif
@@ -4487,7 +4497,7 @@
   void cache_leave (hb_ot_apply_context_t *c) const
   {
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-    subtables[cache_user_idx].cache_leave (c);
+    subtables[subtable_cache_user_idx].cache_leave (c);
 #endif
   }
 
@@ -4494,10 +4504,9 @@
 
   hb_set_digest_t digest;
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
-  public:
-  void *cache = nullptr;
   private:
-  unsigned cache_user_idx = (unsigned) -1;
+  unsigned count = 0; /* Number of subtables in the array. */
+  unsigned subtable_cache_user_idx = (unsigned) -1;
 #endif
   private:
   hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];

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	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -1918,7 +1918,7 @@
 	       const OT::hb_ot_layout_lookup_accelerator_t &accel,
 	       unsigned subtable_count)
 {
-  bool use_cache = accel.cache_enter (c);
+  bool use_hot_subtable_cache = accel.cache_enter (c);
 
   bool ret = false;
   hb_buffer_t *buffer = c->buffer;
@@ -1930,7 +1930,7 @@
 	(cur.mask & c->lookup_mask) &&
 	c->check_glyph_property (&cur, c->lookup_props))
      {
-       applied = accel.apply (c, subtable_count, use_cache);
+       applied = accel.apply (c, subtable_count, use_hot_subtable_cache);
      }
 
     if (applied)
@@ -1939,7 +1939,7 @@
       (void) buffer->next_glyph ();
   }
 
-  if (use_cache)
+  if (use_hot_subtable_cache)
     accel.cache_leave (c);
 
   return ret;
@@ -1982,7 +1982,22 @@
 
   bool ret = false;
 
-  c->set_lookup_props (lookup.get_props ());
+  unsigned lookup_props = lookup.get_props ();
+  if (lookup_props != c->cached_props)
+  {
+    bool cache_it = subtable_count > 1 && (lookup_props & OT::LookupFlag::UseMarkFilteringSet);
+    if (cache_it)
+    {
+      auto &info = buffer->info;
+      for (unsigned int i = 0; i < buffer->len; i++)
+	_hb_glyph_info_set_match (&info[i],
+				  c->check_glyph_property (&info[i], lookup_props, false));
+      c->cached_props = lookup_props;
+    }
+    else
+      c->cached_props = (unsigned) -1;
+  }
+  c->set_lookup_props (lookup_props);
 
   if (likely (!lookup.is_reverse ()))
   {

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -81,9 +81,10 @@
   HB_OT_LAYOUT_GLYPH_PROPS_MARK		= 0x08u,
 
   /* The following are used internally; not derived from GDEF. */
-  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED	= 0x10u,
-  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED	= 0x20u,
-  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED	= 0x40u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MATCHES      = 0x10u,
+  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED	= 0x20u,
+  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED	= 0x40u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED	= 0x80u,
 
   HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
 					  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
@@ -610,7 +611,21 @@
   return false;
 }
 
+static inline bool
+_hb_glyph_info_matches (const hb_glyph_info_t *info)
+{
+  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MATCHES;
+}
+static inline void
+_hb_glyph_info_set_match (hb_glyph_info_t *info, bool match)
+{
+  if (match)
+    info->glyph_props() |= HB_OT_LAYOUT_GLYPH_PROPS_MATCHES;
+  else
+    info->glyph_props() &= ~HB_OT_LAYOUT_GLYPH_PROPS_MATCHES;
+}
 
+
 /* Allocation / deallocation. */
 
 static inline void

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-macroman.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-macroman.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-macroman.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -31,264 +31,264 @@
 #endif
 
 
-_S(".notdef")
-_S(".null")
-_S("nonmarkingreturn")
-_S("space")
-_S("exclam")
-_S("quotedbl")
-_S("numbersign")
-_S("dollar")
-_S("percent")
-_S("ampersand")
-_S("quotesingle")
-_S("parenleft")
-_S("parenright")
-_S("asterisk")
-_S("plus")
-_S("comma")
-_S("hyphen")
-_S("period")
-_S("slash")
-_S("zero")
-_S("one")
-_S("two")
-_S("three")
-_S("four")
-_S("five")
-_S("six")
-_S("seven")
-_S("eight")
-_S("nine")
-_S("colon")
-_S("semicolon")
-_S("less")
-_S("equal")
-_S("greater")
-_S("question")
-_S("at")
-_S("A")
-_S("B")
-_S("C")
-_S("D")
-_S("E")
-_S("F")
-_S("G")
-_S("H")
-_S("I")
-_S("J")
-_S("K")
-_S("L")
-_S("M")
-_S("N")
-_S("O")
-_S("P")
-_S("Q")
-_S("R")
-_S("S")
-_S("T")
-_S("U")
-_S("V")
-_S("W")
-_S("X")
-_S("Y")
-_S("Z")
-_S("bracketleft")
-_S("backslash")
-_S("bracketright")
-_S("asciicircum")
-_S("underscore")
-_S("grave")
-_S("a")
-_S("b")
-_S("c")
-_S("d")
-_S("e")
-_S("f")
-_S("g")
-_S("h")
-_S("i")
-_S("j")
-_S("k")
-_S("l")
-_S("m")
-_S("n")
-_S("o")
-_S("p")
-_S("q")
-_S("r")
-_S("s")
-_S("t")
-_S("u")
-_S("v")
-_S("w")
-_S("x")
-_S("y")
-_S("z")
-_S("braceleft")
-_S("bar")
-_S("braceright")
-_S("asciitilde")
-_S("Adieresis")
-_S("Aring")
-_S("Ccedilla")
-_S("Eacute")
-_S("Ntilde")
-_S("Odieresis")
-_S("Udieresis")
-_S("aacute")
-_S("agrave")
-_S("acircumflex")
-_S("adieresis")
-_S("atilde")
-_S("aring")
-_S("ccedilla")
-_S("eacute")
-_S("egrave")
-_S("ecircumflex")
-_S("edieresis")
-_S("iacute")
-_S("igrave")
-_S("icircumflex")
-_S("idieresis")
-_S("ntilde")
-_S("oacute")
-_S("ograve")
-_S("ocircumflex")
-_S("odieresis")
-_S("otilde")
-_S("uacute")
-_S("ugrave")
-_S("ucircumflex")
-_S("udieresis")
-_S("dagger")
-_S("degree")
-_S("cent")
-_S("sterling")
-_S("section")
-_S("bullet")
-_S("paragraph")
-_S("germandbls")
-_S("registered")
-_S("copyright")
-_S("trademark")
-_S("acute")
-_S("dieresis")
-_S("notequal")
-_S("AE")
-_S("Oslash")
-_S("infinity")
-_S("plusminus")
-_S("lessequal")
-_S("greaterequal")
-_S("yen")
-_S("mu")
-_S("partialdiff")
-_S("summation")
-_S("product")
-_S("pi")
-_S("integral")
-_S("ordfeminine")
-_S("ordmasculine")
-_S("Omega")
-_S("ae")
-_S("oslash")
-_S("questiondown")
-_S("exclamdown")
-_S("logicalnot")
-_S("radical")
-_S("florin")
-_S("approxequal")
-_S("Delta")
-_S("guillemotleft")
-_S("guillemotright")
-_S("ellipsis")
-_S("nonbreakingspace")
-_S("Agrave")
-_S("Atilde")
-_S("Otilde")
-_S("OE")
-_S("oe")
-_S("endash")
-_S("emdash")
-_S("quotedblleft")
-_S("quotedblright")
-_S("quoteleft")
-_S("quoteright")
-_S("divide")
-_S("lozenge")
-_S("ydieresis")
-_S("Ydieresis")
-_S("fraction")
-_S("currency")
-_S("guilsinglleft")
-_S("guilsinglright")
-_S("fi")
-_S("fl")
-_S("daggerdbl")
-_S("periodcentered")
-_S("quotesinglbase")
-_S("quotedblbase")
-_S("perthousand")
-_S("Acircumflex")
-_S("Ecircumflex")
-_S("Aacute")
-_S("Edieresis")
-_S("Egrave")
-_S("Iacute")
-_S("Icircumflex")
-_S("Idieresis")
-_S("Igrave")
-_S("Oacute")
-_S("Ocircumflex")
-_S("apple")
-_S("Ograve")
-_S("Uacute")
-_S("Ucircumflex")
-_S("Ugrave")
-_S("dotlessi")
-_S("circumflex")
-_S("tilde")
-_S("macron")
-_S("breve")
-_S("dotaccent")
-_S("ring")
-_S("cedilla")
-_S("hungarumlaut")
-_S("ogonek")
-_S("caron")
-_S("Lslash")
-_S("lslash")
-_S("Scaron")
-_S("scaron")
-_S("Zcaron")
-_S("zcaron")
-_S("brokenbar")
-_S("Eth")
-_S("eth")
-_S("Yacute")
-_S("yacute")
-_S("Thorn")
-_S("thorn")
-_S("minus")
-_S("multiply")
-_S("onesuperior")
-_S("twosuperior")
-_S("threesuperior")
-_S("onehalf")
-_S("onequarter")
-_S("threequarters")
-_S("franc")
-_S("Gbreve")
-_S("gbreve")
-_S("Idotaccent")
-_S("Scedilla")
-_S("scedilla")
-_S("Cacute")
-_S("cacute")
-_S("Ccaron")
-_S("ccaron")
-_S("dcroat")
+HB_STR(".notdef")
+HB_STR(".null")
+HB_STR("nonmarkingreturn")
+HB_STR("space")
+HB_STR("exclam")
+HB_STR("quotedbl")
+HB_STR("numbersign")
+HB_STR("dollar")
+HB_STR("percent")
+HB_STR("ampersand")
+HB_STR("quotesingle")
+HB_STR("parenleft")
+HB_STR("parenright")
+HB_STR("asterisk")
+HB_STR("plus")
+HB_STR("comma")
+HB_STR("hyphen")
+HB_STR("period")
+HB_STR("slash")
+HB_STR("zero")
+HB_STR("one")
+HB_STR("two")
+HB_STR("three")
+HB_STR("four")
+HB_STR("five")
+HB_STR("six")
+HB_STR("seven")
+HB_STR("eight")
+HB_STR("nine")
+HB_STR("colon")
+HB_STR("semicolon")
+HB_STR("less")
+HB_STR("equal")
+HB_STR("greater")
+HB_STR("question")
+HB_STR("at")
+HB_STR("A")
+HB_STR("B")
+HB_STR("C")
+HB_STR("D")
+HB_STR("E")
+HB_STR("F")
+HB_STR("G")
+HB_STR("H")
+HB_STR("I")
+HB_STR("J")
+HB_STR("K")
+HB_STR("L")
+HB_STR("M")
+HB_STR("N")
+HB_STR("O")
+HB_STR("P")
+HB_STR("Q")
+HB_STR("R")
+HB_STR("S")
+HB_STR("T")
+HB_STR("U")
+HB_STR("V")
+HB_STR("W")
+HB_STR("X")
+HB_STR("Y")
+HB_STR("Z")
+HB_STR("bracketleft")
+HB_STR("backslash")
+HB_STR("bracketright")
+HB_STR("asciicircum")
+HB_STR("underscore")
+HB_STR("grave")
+HB_STR("a")
+HB_STR("b")
+HB_STR("c")
+HB_STR("d")
+HB_STR("e")
+HB_STR("f")
+HB_STR("g")
+HB_STR("h")
+HB_STR("i")
+HB_STR("j")
+HB_STR("k")
+HB_STR("l")
+HB_STR("m")
+HB_STR("n")
+HB_STR("o")
+HB_STR("p")
+HB_STR("q")
+HB_STR("r")
+HB_STR("s")
+HB_STR("t")
+HB_STR("u")
+HB_STR("v")
+HB_STR("w")
+HB_STR("x")
+HB_STR("y")
+HB_STR("z")
+HB_STR("braceleft")
+HB_STR("bar")
+HB_STR("braceright")
+HB_STR("asciitilde")
+HB_STR("Adieresis")
+HB_STR("Aring")
+HB_STR("Ccedilla")
+HB_STR("Eacute")
+HB_STR("Ntilde")
+HB_STR("Odieresis")
+HB_STR("Udieresis")
+HB_STR("aacute")
+HB_STR("agrave")
+HB_STR("acircumflex")
+HB_STR("adieresis")
+HB_STR("atilde")
+HB_STR("aring")
+HB_STR("ccedilla")
+HB_STR("eacute")
+HB_STR("egrave")
+HB_STR("ecircumflex")
+HB_STR("edieresis")
+HB_STR("iacute")
+HB_STR("igrave")
+HB_STR("icircumflex")
+HB_STR("idieresis")
+HB_STR("ntilde")
+HB_STR("oacute")
+HB_STR("ograve")
+HB_STR("ocircumflex")
+HB_STR("odieresis")
+HB_STR("otilde")
+HB_STR("uacute")
+HB_STR("ugrave")
+HB_STR("ucircumflex")
+HB_STR("udieresis")
+HB_STR("dagger")
+HB_STR("degree")
+HB_STR("cent")
+HB_STR("sterling")
+HB_STR("section")
+HB_STR("bullet")
+HB_STR("paragraph")
+HB_STR("germandbls")
+HB_STR("registered")
+HB_STR("copyright")
+HB_STR("trademark")
+HB_STR("acute")
+HB_STR("dieresis")
+HB_STR("notequal")
+HB_STR("AE")
+HB_STR("Oslash")
+HB_STR("infinity")
+HB_STR("plusminus")
+HB_STR("lessequal")
+HB_STR("greaterequal")
+HB_STR("yen")
+HB_STR("mu")
+HB_STR("partialdiff")
+HB_STR("summation")
+HB_STR("product")
+HB_STR("pi")
+HB_STR("integral")
+HB_STR("ordfeminine")
+HB_STR("ordmasculine")
+HB_STR("Omega")
+HB_STR("ae")
+HB_STR("oslash")
+HB_STR("questiondown")
+HB_STR("exclamdown")
+HB_STR("logicalnot")
+HB_STR("radical")
+HB_STR("florin")
+HB_STR("approxequal")
+HB_STR("Delta")
+HB_STR("guillemotleft")
+HB_STR("guillemotright")
+HB_STR("ellipsis")
+HB_STR("nonbreakingspace")
+HB_STR("Agrave")
+HB_STR("Atilde")
+HB_STR("Otilde")
+HB_STR("OE")
+HB_STR("oe")
+HB_STR("endash")
+HB_STR("emdash")
+HB_STR("quotedblleft")
+HB_STR("quotedblright")
+HB_STR("quoteleft")
+HB_STR("quoteright")
+HB_STR("divide")
+HB_STR("lozenge")
+HB_STR("ydieresis")
+HB_STR("Ydieresis")
+HB_STR("fraction")
+HB_STR("currency")
+HB_STR("guilsinglleft")
+HB_STR("guilsinglright")
+HB_STR("fi")
+HB_STR("fl")
+HB_STR("daggerdbl")
+HB_STR("periodcentered")
+HB_STR("quotesinglbase")
+HB_STR("quotedblbase")
+HB_STR("perthousand")
+HB_STR("Acircumflex")
+HB_STR("Ecircumflex")
+HB_STR("Aacute")
+HB_STR("Edieresis")
+HB_STR("Egrave")
+HB_STR("Iacute")
+HB_STR("Icircumflex")
+HB_STR("Idieresis")
+HB_STR("Igrave")
+HB_STR("Oacute")
+HB_STR("Ocircumflex")
+HB_STR("apple")
+HB_STR("Ograve")
+HB_STR("Uacute")
+HB_STR("Ucircumflex")
+HB_STR("Ugrave")
+HB_STR("dotlessi")
+HB_STR("circumflex")
+HB_STR("tilde")
+HB_STR("macron")
+HB_STR("breve")
+HB_STR("dotaccent")
+HB_STR("ring")
+HB_STR("cedilla")
+HB_STR("hungarumlaut")
+HB_STR("ogonek")
+HB_STR("caron")
+HB_STR("Lslash")
+HB_STR("lslash")
+HB_STR("Scaron")
+HB_STR("scaron")
+HB_STR("Zcaron")
+HB_STR("zcaron")
+HB_STR("brokenbar")
+HB_STR("Eth")
+HB_STR("eth")
+HB_STR("Yacute")
+HB_STR("yacute")
+HB_STR("Thorn")
+HB_STR("thorn")
+HB_STR("minus")
+HB_STR("multiply")
+HB_STR("onesuperior")
+HB_STR("twosuperior")
+HB_STR("threesuperior")
+HB_STR("onehalf")
+HB_STR("onequarter")
+HB_STR("threequarters")
+HB_STR("franc")
+HB_STR("Gbreve")
+HB_STR("gbreve")
+HB_STR("Idotaccent")
+HB_STR("Scedilla")
+HB_STR("scedilla")
+HB_STR("Cacute")
+HB_STR("cacute")
+HB_STR("Ccaron")
+HB_STR("ccaron")
+HB_STR("dcroat")
 
 
 #endif /* HB_OT_POST_MACROMAN_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -78,7 +78,7 @@
 static inline void
 set_glyph (hb_glyph_info_t &info, hb_font_t *font)
 {
-  (void) font->get_nominal_glyph (info.codepoint, &info.glyph_index());
+  (void) font->get_nominal_glyph (info.codepoint, &info.normalizer_glyph_index());
 }
 
 static inline void
@@ -85,7 +85,7 @@
 output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
 {
   /* This is very confusing indeed. */
-  buffer->cur().glyph_index() = glyph;
+  buffer->cur().normalizer_glyph_index() = glyph;
   (void) buffer->output_glyph (unichar);
   _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer);
 }
@@ -93,7 +93,7 @@
 static inline void
 next_char (hb_buffer_t *buffer, hb_codepoint_t glyph)
 {
-  buffer->cur().glyph_index() = glyph;
+  buffer->cur().normalizer_glyph_index() = glyph;
   (void) buffer->next_glyph ();
 }
 
@@ -210,7 +210,7 @@
   hb_font_t * const font = c->font;
   for (; buffer->idx < end - 1 && buffer->successful;) {
     if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
-      if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
+      if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().normalizer_glyph_index()))
       {
 	hb_codepoint_t unicode = buffer->cur().codepoint;
 	(void) buffer->replace_glyphs (2, 1, &unicode);
@@ -342,7 +342,7 @@
 	unsigned int done = font->get_nominal_glyphs (end - buffer->idx,
 						      &buffer->cur().codepoint,
 						      sizeof (buffer->info[0]),
-						      &buffer->cur().glyph_index(),
+						      &buffer->cur().normalizer_glyph_index(),
 						      sizeof (buffer->info[0]));
 	if (unlikely (!buffer->next_glyphs (done))) break;
       }
@@ -456,7 +456,7 @@
 	  buffer->out_len--; /* Remove the second composable. */
 	  /* Modify starter and carry on. */
 	  buffer->out_info[starter].codepoint = composed;
-	  buffer->out_info[starter].glyph_index() = glyph;
+	  buffer->out_info[starter].normalizer_glyph_index() = glyph;
 	  _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
 
 	  continue;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -32,7 +32,7 @@
 
 
 /* buffer var allocations, used during the normalization process */
-#define glyph_index()	var1.u32
+#define normalizer_glyph_index()	var1.u32
 
 struct hb_ot_shape_plan_t;
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -614,14 +614,14 @@
     for (unsigned i = 0; i < count; i++)
     {
       auto gc = _hb_glyph_info_get_general_category (&info[i]);
-      if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
-	found_number = true;
-      else if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc))
+      if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc))
       {
 	found_letter = true;
 	break;
       }
-      else if (_hb_codepoint_is_regional_indicator (info[i].codepoint))
+      else if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
+	found_number = true;
+      else if (unlikely (_hb_codepoint_is_regional_indicator (info[i].codepoint)))
 	found_ri = true;
     }
     if ((found_number || found_ri) && !found_letter)
@@ -843,11 +843,11 @@
 static inline void
 hb_ot_map_glyphs_fast (hb_buffer_t  *buffer)
 {
-  /* Normalization process sets up glyph_index(), we just copy it. */
+  /* Normalization process sets up normalizer_glyph_index(), we just copy it. */
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
-    info[i].codepoint = info[i].glyph_index();
+    info[i].codepoint = info[i].normalizer_glyph_index();
 
   buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
 }
@@ -885,7 +885,7 @@
 
   hb_ot_rotate_chars (c);
 
-  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
+  HB_BUFFER_ALLOCATE_VAR (buffer, normalizer_glyph_index);
 
   _hb_ot_shape_normalize (c->plan, buffer, c->font);
 
@@ -897,7 +897,7 @@
 
   hb_ot_map_glyphs_fast (buffer);
 
-  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index);
+  HB_BUFFER_DEALLOCATE_VAR (buffer, normalizer_glyph_index);
 }
 
 static inline void

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -53,7 +53,7 @@
 };
 
 
-#line 57 "hb-ot-shaper-indic-machine.hh"
+#line 54 "hb-ot-shaper-indic-machine.hh"
 #define indic_syllable_machine_ex_A 9u
 #define indic_syllable_machine_ex_C 1u
 #define indic_syllable_machine_ex_CM 16u
@@ -77,7 +77,7 @@
 #define indic_syllable_machine_ex_ZWNJ 5u
 
 
-#line 81 "hb-ot-shaper-indic-machine.hh"
+#line 76 "hb-ot-shaper-indic-machine.hh"
 static const unsigned char _indic_syllable_machine_trans_keys[] = {
 	8u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u, 
 	8u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u, 4u, 57u, 
@@ -1126,7 +1126,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 1130 "hb-ot-shaper-indic-machine.hh"
+#line 1119 "hb-ot-shaper-indic-machine.hh"
 	{
 	cs = indic_syllable_machine_start;
 	ts = 0;
@@ -1142,7 +1142,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 1146 "hb-ot-shaper-indic-machine.hh"
+#line 1131 "hb-ot-shaper-indic-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -1156,7 +1156,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 1160 "hb-ot-shaper-indic-machine.hh"
+#line 1143 "hb-ot-shaper-indic-machine.hh"
 	}
 
 	_keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -1268,7 +1268,7 @@
 #line 117 "hb-ot-shaper-indic-machine.rl"
 	{act = 7;}
 	break;
-#line 1272 "hb-ot-shaper-indic-machine.hh"
+#line 1232 "hb-ot-shaper-indic-machine.hh"
 	}
 
 _again:
@@ -1277,7 +1277,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 1281 "hb-ot-shaper-indic-machine.hh"
+#line 1239 "hb-ot-shaper-indic-machine.hh"
 	}
 
 	if ( ++p != pe )

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-khmer-machine.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-khmer-machine.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-khmer-machine.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -48,7 +48,7 @@
 };
 
 
-#line 52 "hb-ot-shaper-khmer-machine.hh"
+#line 49 "hb-ot-shaper-khmer-machine.hh"
 #define khmer_syllable_machine_ex_C 1u
 #define khmer_syllable_machine_ex_DOTTEDCIRCLE 11u
 #define khmer_syllable_machine_ex_H 4u
@@ -66,7 +66,7 @@
 #define khmer_syllable_machine_ex_ZWNJ 5u
 
 
-#line 70 "hb-ot-shaper-khmer-machine.hh"
+#line 65 "hb-ot-shaper-khmer-machine.hh"
 static const unsigned char _khmer_syllable_machine_trans_keys[] = {
 	5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 
 	5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 
@@ -294,7 +294,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 298 "hb-ot-shaper-khmer-machine.hh"
+#line 287 "hb-ot-shaper-khmer-machine.hh"
 	{
 	cs = khmer_syllable_machine_start;
 	ts = 0;
@@ -310,7 +310,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 314 "hb-ot-shaper-khmer-machine.hh"
+#line 299 "hb-ot-shaper-khmer-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -324,7 +324,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 328 "hb-ot-shaper-khmer-machine.hh"
+#line 311 "hb-ot-shaper-khmer-machine.hh"
 	}
 
 	_keys = _khmer_syllable_machine_trans_keys + (cs<<1);
@@ -394,7 +394,7 @@
 #line 98 "hb-ot-shaper-khmer-machine.rl"
 	{act = 3;}
 	break;
-#line 398 "hb-ot-shaper-khmer-machine.hh"
+#line 368 "hb-ot-shaper-khmer-machine.hh"
 	}
 
 _again:
@@ -403,7 +403,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 407 "hb-ot-shaper-khmer-machine.hh"
+#line 375 "hb-ot-shaper-khmer-machine.hh"
 	}
 
 	if ( ++p != pe )

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-myanmar-machine.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-myanmar-machine.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-myanmar-machine.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -50,7 +50,7 @@
 };
 
 
-#line 54 "hb-ot-shaper-myanmar-machine.hh"
+#line 51 "hb-ot-shaper-myanmar-machine.hh"
 #define myanmar_syllable_machine_ex_A 9u
 #define myanmar_syllable_machine_ex_As 32u
 #define myanmar_syllable_machine_ex_C 1u
@@ -78,7 +78,7 @@
 #define myanmar_syllable_machine_ex_ZWNJ 5u
 
 
-#line 82 "hb-ot-shaper-myanmar-machine.hh"
+#line 77 "hb-ot-shaper-myanmar-machine.hh"
 static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
 	1u, 57u, 3u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u, 
 	3u, 57u, 3u, 57u, 3u, 57u, 5u, 57u, 1u, 15u, 3u, 57u, 3u, 57u, 3u, 57u, 
@@ -549,7 +549,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 553 "hb-ot-shaper-myanmar-machine.hh"
+#line 542 "hb-ot-shaper-myanmar-machine.hh"
 	{
 	cs = myanmar_syllable_machine_start;
 	ts = 0;
@@ -565,7 +565,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 569 "hb-ot-shaper-myanmar-machine.hh"
+#line 554 "hb-ot-shaper-myanmar-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -579,7 +579,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 583 "hb-ot-shaper-myanmar-machine.hh"
+#line 566 "hb-ot-shaper-myanmar-machine.hh"
 	}
 
 	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -649,7 +649,7 @@
 #line 113 "hb-ot-shaper-myanmar-machine.rl"
 	{act = 3;}
 	break;
-#line 653 "hb-ot-shaper-myanmar-machine.hh"
+#line 623 "hb-ot-shaper-myanmar-machine.hh"
 	}
 
 _again:
@@ -658,7 +658,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 662 "hb-ot-shaper-myanmar-machine.hh"
+#line 630 "hb-ot-shaper-myanmar-machine.hh"
 	}
 
 	if ( ++p != pe )

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-thai.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-thai.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-thai.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -191,7 +191,7 @@
 };
 
 
-static enum thai_below_state_t
+static const enum thai_below_state_t
 {
   B0, /* No descender */
   B1, /* Removable descender */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -53,7 +53,7 @@
 };
 
 
-#line 57 "hb-ot-shaper-use-machine.hh"
+#line 54 "hb-ot-shaper-use-machine.hh"
 #define use_syllable_machine_ex_B 1u
 #define use_syllable_machine_ex_CGJ 6u
 #define use_syllable_machine_ex_CMAbv 31u
@@ -100,7 +100,7 @@
 #define use_syllable_machine_ex_ZWNJ 14u
 
 
-#line 104 "hb-ot-shaper-use-machine.hh"
+#line 99 "hb-ot-shaper-use-machine.hh"
 static const unsigned char _use_syllable_machine_trans_keys[] = {
 	49u, 51u, 0u, 56u, 11u, 56u, 11u, 56u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 
 	14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 
@@ -929,7 +929,7 @@
   unsigned int act HB_UNUSED;
   int cs;
   
-#line 933 "hb-ot-shaper-use-machine.hh"
+#line 922 "hb-ot-shaper-use-machine.hh"
 	{
 	cs = use_syllable_machine_start;
 	ts = 0;
@@ -942,7 +942,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 946 "hb-ot-shaper-use-machine.hh"
+#line 931 "hb-ot-shaper-use-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -956,7 +956,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 960 "hb-ot-shaper-use-machine.hh"
+#line 943 "hb-ot-shaper-use-machine.hh"
 	}
 
 	_keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -1078,7 +1078,7 @@
 #line 181 "hb-ot-shaper-use-machine.rl"
 	{act = 9;}
 	break;
-#line 1082 "hb-ot-shaper-use-machine.hh"
+#line 1039 "hb-ot-shaper-use-machine.hh"
 	}
 
 _again:
@@ -1087,7 +1087,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 1091 "hb-ot-shaper-use-machine.hh"
+#line 1046 "hb-ot-shaper-use-machine.hh"
 	}
 
 	if ( ++p != pe )

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -724,7 +724,7 @@
 	   hb_requires (hb_is_iterator (Iterator)),
 	   typename ...Ts>
   void copy_all (Iterator it, Ts&&... ds)
-  { for (decltype (*it) _ : it) copy (_, std::forward<Ts> (ds)...); }
+  { for (decltype (*it) _ : it) copy (_, ds...); }
 
   template <typename Type>
   hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -199,6 +199,7 @@
 
 
 #ifdef HB_EXPERIMENTAL_API
+#ifndef HB_NO_VAR
 
 static float
 buffer_advance (hb_buffer_t *buffer)
@@ -440,8 +441,8 @@
 
   return true;
 }
-
 #endif
+#endif
 
 
 #endif

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -61,6 +61,10 @@
 HB_SHAPER_IMPLEMENT (harfrust)
 #endif
 
+#ifdef HAVE_KBTS
+HB_SHAPER_IMPLEMENT (kbts)
+#endif
+
 #ifndef HB_NO_FALLBACK_SHAPE
 HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
 #endif

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-string-array.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-string-array.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-string-array.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -45,9 +45,9 @@
  * but C++ does not allow that.
  * https://stackoverflow.com/q/28433862
  */
-#define _S(s) char HB_PASTE (str, __LINE__)[sizeof (s)];
+#define HB_STR(s) char HB_PASTE (str, __LINE__)[sizeof (s)];
 #include HB_STRING_ARRAY_LIST
-#undef _S
+#undef HB_STR
   } st;
   char str[HB_VAR_ARRAY];
 }
@@ -54,16 +54,16 @@
 HB_STRING_ARRAY_POOL_NAME =
 {
   {
-#define _S(s) s,
+#define HB_STR(s) s,
 #include HB_STRING_ARRAY_LIST
-#undef _S
+#undef HB_STR
   }
 };
 static const unsigned int HB_STRING_ARRAY_OFFS_NAME[] =
 {
-#define _S(s) offsetof (union HB_STRING_ARRAY_TYPE_NAME, st.HB_PASTE(str, __LINE__)),
+#define HB_STR(s) offsetof (union HB_STRING_ARRAY_TYPE_NAME, st.HB_PASTE(str, __LINE__)),
 #include HB_STRING_ARRAY_LIST
-#undef _S
+#undef HB_STR
   sizeof (HB_STRING_ARRAY_TYPE_NAME)
 };
 

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	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -300,6 +300,7 @@
 // compile times more reasonable:
 // - hb-subset-plan.cc
 // - hb-subset-plan-layout.cc
+// - hb-subset-plan-var.cc
 //
 // The functions below are those needed to connect the split files
 // above together.

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-cff.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-cff.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-cff.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -0,0 +1,143 @@
+#include "hb-subset-table.hh"
+
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-ot-vorg-table.hh"
+
+
+#ifndef HB_NO_SUBSET_CFF
+template<>
+struct hb_subset_plan_t::source_table_loader<const OT::cff1>
+{
+  auto operator () (hb_subset_plan_t *plan)
+  HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff1_accel :
+		  plan->inprogress_accelerator ? plan->inprogress_accelerator->cff1_accel :
+		  plan->cff1_accel)
+};
+template<>
+struct hb_subset_plan_t::source_table_loader<const OT::cff2>
+{
+  auto operator () (hb_subset_plan_t *plan)
+  HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff2_accel :
+		  plan->inprogress_accelerator ? plan->inprogress_accelerator->cff2_accel :
+		  plan->cff2_accel)
+};
+#endif
+
+
+bool _hb_subset_table_cff		(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success)
+{
+#ifndef HB_NO_SUBSET_CFF
+  switch (tag)
+  {
+  case HB_TAG('C','F','F',' '): *success = _hb_subset_table<const OT::cff1> (plan, buf); return true;
+  case HB_TAG('C','F','F','2'): *success = _hb_subset_table<const OT::cff2> (plan, buf); return true;
+  case HB_TAG('V','O','R','G'): *success = _hb_subset_table<const OT::VORG> (plan, buf); return true;
+  }
+#endif
+  return false;
+}
+
+
+#ifdef HB_EXPERIMENTAL_API
+#ifndef HB_NO_CFF
+
+template<typename accel_t>
+static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_index) {
+  if (!accel.is_valid()) {
+    return hb_blob_get_empty ();
+  }
+
+  hb_ubytes_t bytes = (*accel.charStrings)[glyph_index];
+  if (!bytes) {
+    return hb_blob_get_empty ();
+  }
+
+  hb_blob_t* cff_blob = accel.get_blob();
+  uint32_t length;
+  const char* cff_data = hb_blob_get_data(cff_blob, &length) ;
+
+  long int offset = (const char*) bytes.arrayZ - cff_data;
+  if (offset < 0 || offset > INT32_MAX) {
+    return hb_blob_get_empty ();
+  }
+
+  return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, bytes.length);
+}
+
+template<typename accel_t>
+static hb_blob_t* get_charstrings_index(accel_t& accel) {
+  if (!accel.is_valid()) {
+    return hb_blob_get_empty ();
+  }
+
+  const char* charstrings_start = (const char*) accel.charStrings;
+  unsigned charstrings_length = accel.charStrings->get_size();
+
+  hb_blob_t* cff_blob = accel.get_blob();
+  uint32_t length;
+  const char* cff_data = hb_blob_get_data(cff_blob, &length) ;
+
+  long int offset = charstrings_start - cff_data;
+  if (offset < 0 || offset > INT32_MAX) {
+    return hb_blob_get_empty ();
+  }
+
+  return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, charstrings_length);
+}
+
+/**
+ * hb_subset_cff_get_charstring_data:
+ * @face: A face object
+ * @glyph_index: Glyph index to get data for.
+ *
+ * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index.
+ *
+ * XSince: EXPERIMENTAL
+ **/
+HB_EXTERN hb_blob_t*
+hb_subset_cff_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) {
+  return get_charstrings_data(*face->table.cff1, glyph_index);
+}
+
+/**
+ * hb_subset_cff_get_charstrings_index:
+ * @face: A face object
+ *
+ * Returns the raw CFF CharStrings INDEX from the CFF table.
+ *
+ * XSince: EXPERIMENTAL
+ **/
+HB_EXTERN hb_blob_t*
+hb_subset_cff_get_charstrings_index (hb_face_t* face) {
+  return get_charstrings_index (*face->table.cff1);
+}
+
+/**
+ * hb_subset_cff2_get_charstring_data:
+ * @face: A face object
+ * @glyph_index: Glyph index to get data for.
+ *
+ * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index.
+ *
+ * XSince: EXPERIMENTAL
+ **/
+HB_EXTERN hb_blob_t*
+hb_subset_cff2_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) {
+  return get_charstrings_data(*face->table.cff2, glyph_index);
+}
+
+/**
+ * hb_subset_cff2_get_charstrings_index:
+ * @face: A face object
+ *
+ * Returns the raw CFF2 CharStrings INDEX from the CFF2 table.
+ *
+ * XSince: EXPERIMENTAL
+ **/
+HB_EXTERN hb_blob_t*
+hb_subset_cff2_get_charstrings_index (hb_face_t* face) {
+  return get_charstrings_index (*face->table.cff2);
+}
+#endif
+#endif

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-color.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-color.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-color.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -0,0 +1,21 @@
+#include "hb-subset-table.hh"
+
+#include "OT/Color/sbix/sbix.hh"
+#include "OT/Color/CPAL/CPAL.hh"
+#include "OT/Color/COLR/COLR.hh"
+#include "OT/Color/CBDT/CBDT.hh"
+
+bool _hb_subset_table_color		(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success)
+{
+#ifndef HB_NO_COLOR
+  switch (tag)
+  {
+  case HB_TAG('s','b','i','x'): *success = _hb_subset_table<const OT::sbix> (plan, buf); return true;
+  case HB_TAG('C','O','L','R'): *success = _hb_subset_table<const OT::COLR> (plan, buf); return true;
+  case HB_TAG('C','P','A','L'): *success = _hb_subset_table<const OT::CPAL> (plan, buf); return true;
+  case HB_TAG('C','B','L','C'): *success = _hb_subset_table<const OT::CBLC> (plan, buf); return true;
+  case HB_TAG('C','B','D','T'): *success = true; return true; /* skip CBDT, handled by CBLC */
+  }
+#endif
+  return false;
+}

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-layout.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-layout.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-layout.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -0,0 +1,22 @@
+#include "hb-subset-table.hh"
+
+#include "hb-ot-layout-gdef-table.hh"
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-layout-base-table.hh"
+#include "hb-ot-math-table.hh"
+
+bool _hb_subset_table_layout		(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success)
+{
+#ifndef HB_NO_SUBSET_LAYOUT
+  switch (tag)
+  {
+  case HB_TAG('G','D','E','F'): *success = _hb_subset_table<const OT::GDEF> (plan, buf); return true;
+  case HB_TAG('G','S','U','B'): *success = _hb_subset_table<const OT::Layout::GSUB> (plan, buf); return true;
+  case HB_TAG('G','P','O','S'): *success = _hb_subset_table<const OT::Layout::GPOS> (plan, buf); return true;
+  case HB_TAG('B','A','S','E'): *success = _hb_subset_table<const OT::BASE> (plan, buf); return true;
+  case HB_TAG('M','A','T','H'): *success = _hb_subset_table<const OT::MATH> (plan, buf); return true;
+  }
+#endif
+  return false;
+}

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-other.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-other.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-other.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -0,0 +1,31 @@
+#include "hb-subset-table.hh"
+
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-hdmx-table.hh"
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-hmtx-table.hh"
+#include "hb-ot-maxp-table.hh"
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-name-table.hh"
+#include "hb-ot-post-table.hh"
+
+bool _hb_subset_table_other		(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success)
+{
+  switch (tag)
+  {
+  case HB_TAG('g','l','y','f'): *success = _hb_subset_table<const OT::glyf> (plan, buf); return true;
+  case HB_TAG('h','d','m','x'): *success = _hb_subset_table<const OT::hdmx> (plan, buf); return true;
+  case HB_TAG('n','a','m','e'): *success = _hb_subset_table<const OT::name> (plan, buf); return true;
+  case HB_TAG('h','h','e','a'): *success = true; return true; /* skip hhea, handled by hmtx */
+  case HB_TAG('h','m','t','x'): *success = _hb_subset_table<const OT::hmtx> (plan, buf); return true;
+  case HB_TAG('v','h','e','a'): *success = true; return true; /* skip vhea, handled by vmtx */
+  case HB_TAG('v','m','t','x'): *success = _hb_subset_table<const OT::vmtx> (plan, buf); return true;
+  case HB_TAG('m','a','x','p'): *success = _hb_subset_table<const OT::maxp> (plan, buf); return true;
+  case HB_TAG('l','o','c','a'): *success = true; return true; /* skip loca, handled by glyf */
+  case HB_TAG('c','m','a','p'): *success = _hb_subset_table<const OT::cmap> (plan, buf); return true;
+  case HB_TAG('O','S','/','2'): *success = _hb_subset_table<const OT::OS2 > (plan, buf); return true;
+  case HB_TAG('p','o','s','t'): *success = _hb_subset_table<const OT::post> (plan, buf); return true;
+  }
+  return false;
+}

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-var.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-var.cc	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table-var.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -0,0 +1,45 @@
+#include "hb-subset-table.hh"
+
+#include "hb-ot-var-hvar-table.hh"
+#include "hb-ot-var-gvar-table.hh"
+#include "hb-ot-var-fvar-table.hh"
+#include "hb-ot-var-avar-table.hh"
+#include "hb-ot-var-cvar-table.hh"
+#include "hb-ot-var-mvar-table.hh"
+
+bool _hb_subset_table_var		(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success)
+{
+#ifndef HB_NO_VAR
+  switch (tag)
+  {
+  case HB_TAG('H','V','A','R'): *success = _hb_subset_table<const OT::HVAR> (plan, buf); return true;
+  case HB_TAG('V','V','A','R'): *success = _hb_subset_table<const OT::VVAR> (plan, buf); return true;
+  case HB_TAG('g','v','a','r'): *success = _hb_subset_table<const OT::gvar> (plan, buf); return true;
+  case HB_TAG('f','v','a','r'):
+    if (plan->user_axes_location.is_empty ())
+      *success = _hb_subset_table_passthrough (plan, tag);
+    else
+      *success = _hb_subset_table<const OT::fvar> (plan, buf);
+    return true;
+  case HB_TAG('a','v','a','r'):
+    if (plan->user_axes_location.is_empty ())
+      *success = _hb_subset_table_passthrough (plan, tag);
+    else
+      *success = _hb_subset_table<const OT::avar> (plan, buf);
+    return true;
+  case HB_TAG('c','v','a','r'):
+    if (plan->user_axes_location.is_empty ())
+      *success = _hb_subset_table_passthrough (plan, tag);
+    else
+      *success = _hb_subset_table<const OT::cvar> (plan, buf);
+    return true;
+  case HB_TAG('M','V','A','R'):
+    if (plan->user_axes_location.is_empty ())
+      *success = _hb_subset_table_passthrough (plan, tag);
+    else
+      *success = _hb_subset_table<const OT::MVAR> (plan, buf);
+    return true;
+  }
+#endif
+  return false;
+}

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table.hh	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-table.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -0,0 +1,217 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Roderick Sheeter
+ */
+
+#ifndef HB_SUBSET_TABLE_HH
+#define HB_SUBSET_TABLE_HH
+
+
+#include "hb.hh"
+
+#include "hb-subset.hh"
+#include "hb-repacker.hh"
+
+
+template<typename TableType>
+static bool
+_hb_subset_table_try (const TableType *table,
+		      hb_vector_t<char>* buf,
+		      hb_subset_context_t* c /* OUT */)
+{
+  c->serializer->start_serialize ();
+  if (c->serializer->in_error ()) return false;
+
+  bool needed = table->subset (c);
+  if (!c->serializer->ran_out_of_room ())
+  {
+    c->serializer->end_serialize ();
+    return needed;
+  }
+
+  unsigned buf_size = buf->allocated;
+  buf_size = buf_size * 2 + 16;
+
+
+
+
+  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
+             HB_UNTAG (c->table_tag), buf_size);
+
+  if (unlikely (buf_size > c->source_blob->length * 256 ||
+		!buf->alloc_exact (buf_size)))
+  {
+    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
+               HB_UNTAG (c->table_tag), buf_size);
+    return needed;
+  }
+
+  c->serializer->reset (buf->arrayZ, buf->allocated);
+  return _hb_subset_table_try (table, buf, c);
+}
+
+static HB_UNUSED unsigned
+_hb_subset_estimate_table_size (hb_subset_plan_t *plan,
+				unsigned table_len,
+				hb_tag_t table_tag)
+{
+  unsigned src_glyphs = plan->source->get_num_glyphs ();
+  unsigned dst_glyphs = plan->glyphset ()->get_population ();
+
+  unsigned bulk = 8192;
+  /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's
+   * because those are expensive to subset, so giving them more room is fine. */
+  bool same_size = table_tag == HB_TAG('G','S','U','B') ||
+		   table_tag == HB_TAG('G','P','O','S') ||
+		   table_tag == HB_TAG('G','D','E','F') ||
+		   table_tag == HB_TAG('n','a','m','e');
+
+  if (plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS)
+  {
+    if (table_tag == HB_TAG('C','F','F',' '))
+    {
+      /* Add some extra room for the CFF charset. */
+      bulk += src_glyphs * 16;
+    }
+    else if (table_tag == HB_TAG('C','F','F','2'))
+    {
+      /* Just extra CharString offsets. */
+      bulk += src_glyphs * 4;
+    }
+  }
+
+  if (unlikely (!src_glyphs) || same_size)
+    return bulk + table_len;
+
+  return bulk + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
+}
+
+/*
+ * Repack the serialization buffer if any offset overflows exist.
+ */
+static HB_UNUSED hb_blob_t*
+_hb_subset_repack (hb_tag_t tag, const hb_serialize_context_t& c)
+{
+  if (!c.offset_overflow ())
+    return c.copy_blob ();
+
+  hb_blob_t* result = hb_resolve_overflows (c.object_graph (), tag);
+
+  if (unlikely (!result))
+  {
+    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c offset overflow resolution failed.",
+               HB_UNTAG (tag));
+    return nullptr;
+  }
+
+  return result;
+}
+
+template <typename T>
+static HB_UNUSED auto _hb_do_destroy (T &t, hb_priority<1>) HB_RETURN (void, t.destroy ())
+
+template <typename T>
+static HB_UNUSED void _hb_do_destroy (T &t, hb_priority<0>) {}
+
+template<typename TableType>
+static bool
+_hb_subset_table (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
+{
+  auto &&source_blob = plan->source_table<TableType> ();
+  auto *table = source_blob.get ();
+
+  hb_tag_t tag = TableType::tableTag;
+  hb_blob_t *blob = source_blob.get_blob();
+  if (unlikely (!blob || !blob->data))
+  {
+    DEBUG_MSG (SUBSET, nullptr,
+               "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
+    _hb_do_destroy (source_blob, hb_prioritize);
+    return false;
+  }
+
+  unsigned buf_size = _hb_subset_estimate_table_size (plan, blob->length, TableType::tableTag);
+  DEBUG_MSG (SUBSET, nullptr,
+             "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
+  if (unlikely (!buf.alloc (buf_size)))
+  {
+    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
+    _hb_do_destroy (source_blob, hb_prioritize);
+    return false;
+  }
+
+  bool needed = false;
+  hb_serialize_context_t serializer (buf.arrayZ, buf.allocated);
+  {
+    hb_subset_context_t c (blob, plan, &serializer, tag);
+    needed = _hb_subset_table_try (table, &buf, &c);
+  }
+  _hb_do_destroy (source_blob, hb_prioritize);
+
+  if (serializer.in_error () && !serializer.only_offset_overflow ())
+  {
+    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset FAILED!", HB_UNTAG (tag));
+    return false;
+  }
+
+  if (!needed)
+  {
+    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
+    return true;
+  }
+
+  bool result = false;
+  hb_blob_t *dest_blob = _hb_subset_repack (tag, serializer);
+  if (dest_blob)
+  {
+    DEBUG_MSG (SUBSET, nullptr,
+               "OT::%c%c%c%c final subset table size: %u bytes.",
+               HB_UNTAG (tag), dest_blob->length);
+    result = plan->add_table (tag, dest_blob);
+    hb_blob_destroy (dest_blob);
+  }
+
+  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s",
+             HB_UNTAG (tag), result ? "success" : "FAILED!");
+  return result;
+}
+
+static HB_UNUSED bool
+_hb_subset_table_passthrough (hb_subset_plan_t *plan, hb_tag_t tag)
+{
+  hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
+  bool result = plan->add_table (tag, source_table);
+  hb_blob_destroy (source_table);
+  return result;
+}
+
+
+HB_INTERNAL bool _hb_subset_table_layout	(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success);
+HB_INTERNAL bool _hb_subset_table_var		(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success);
+HB_INTERNAL bool _hb_subset_table_cff		(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success);
+HB_INTERNAL bool _hb_subset_table_color		(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success);
+HB_INTERNAL bool _hb_subset_table_other		(hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success);
+
+
+#endif /* HB_SUBSET_TABLE_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -25,67 +25,21 @@
  */
 
 #include "hb.hh"
+
 #include "hb-open-type.hh"
+#include "hb-open-file.hh"
 
 #include "hb-subset.hh"
+#include "hb-subset-table.hh"
+#include "hb-subset-accelerator.hh"
 
-#include "hb-open-file.hh"
 #include "hb-ot-cmap-table.hh"
-#include "hb-ot-glyf-table.hh"
-#include "hb-ot-hdmx-table.hh"
+#include "hb-ot-var-cvar-table.hh"
 #include "hb-ot-head-table.hh"
-#include "hb-ot-hhea-table.hh"
-#include "hb-ot-hmtx-table.hh"
-#include "hb-ot-maxp-table.hh"
-#include "OT/Color/CBDT/CBDT.hh"
-#include "OT/Color/COLR/COLR.hh"
-#include "OT/Color/CPAL/CPAL.hh"
-#include "OT/Color/sbix/sbix.hh"
-#include "hb-ot-os2-table.hh"
-#include "hb-ot-post-table.hh"
+#include "hb-ot-stat-table.hh"
 #include "hb-ot-post-table-v2subset.hh"
-#include "hb-ot-cff1-table.hh"
-#include "hb-ot-cff2-table.hh"
-#include "hb-ot-vorg-table.hh"
-#include "hb-ot-name-table.hh"
-#include "hb-ot-layout-base-table.hh"
-#include "hb-ot-layout-gsub-table.hh"
-#include "hb-ot-layout-gpos-table.hh"
-#include "hb-ot-var-avar-table.hh"
-#include "hb-ot-var-cvar-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-var-mvar-table.hh"
-#include "hb-ot-math-table.hh"
-#include "hb-ot-stat-table.hh"
-#include "hb-repacker.hh"
-#include "hb-subset-accelerator.hh"
 
-using OT::Layout::GSUB;
-using OT::Layout::GPOS;
 
-
-#ifndef HB_NO_SUBSET_CFF
-template<>
-struct hb_subset_plan_t::source_table_loader<const OT::cff1>
-{
-  auto operator () (hb_subset_plan_t *plan)
-  HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff1_accel :
-		  plan->inprogress_accelerator ? plan->inprogress_accelerator->cff1_accel :
-		  plan->cff1_accel)
-};
-template<>
-struct hb_subset_plan_t::source_table_loader<const OT::cff2>
-{
-  auto operator () (hb_subset_plan_t *plan)
-  HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff2_accel :
-		  plan->inprogress_accelerator ? plan->inprogress_accelerator->cff2_accel :
-		  plan->cff2_accel)
-};
-#endif
-
-
 /**
  * SECTION:hb-subset
  * @title: hb-subset
@@ -116,56 +70,56 @@
  * if we are unable to list the tables in a face.
  */
 static hb_tag_t known_tables[] {
-  HB_TAG ('a', 'v', 'a', 'r'),
-  HB_OT_TAG_BASE,
-  HB_OT_TAG_CBDT,
-  HB_OT_TAG_CBLC,
-  HB_OT_TAG_CFF1,
-  HB_OT_TAG_CFF2,
-  HB_OT_TAG_cmap,
-  HB_OT_TAG_COLR,
-  HB_OT_TAG_CPAL,
-  HB_TAG ('c', 'v', 'a', 'r'),
-  HB_TAG ('c', 'v', 't', ' '),
-  HB_TAG ('D', 'S', 'I', 'G'),
-  HB_TAG ('E', 'B', 'D', 'T'),
-  HB_TAG ('E', 'B', 'L', 'C'),
-  HB_TAG ('E', 'B', 'S', 'C'),
-  HB_TAG ('f', 'p', 'g', 'm'),
-  HB_TAG ('f', 'v', 'a', 'r'),
-  HB_TAG ('g', 'a', 's', 'p'),
-  HB_OT_TAG_GDEF,
-  HB_OT_TAG_glyf,
-  HB_OT_TAG_GPOS,
-  HB_OT_TAG_GSUB,
-  HB_OT_TAG_gvar,
-  HB_OT_TAG_hdmx,
-  HB_OT_TAG_head,
-  HB_OT_TAG_hhea,
-  HB_OT_TAG_hmtx,
-  HB_OT_TAG_HVAR,
-  HB_OT_TAG_JSTF,
-  HB_TAG ('k', 'e', 'r', 'n'),
-  HB_OT_TAG_loca,
-  HB_TAG ('L', 'T', 'S', 'H'),
-  HB_OT_TAG_MATH,
-  HB_OT_TAG_maxp,
-  HB_TAG ('M', 'E', 'R', 'G'),
-  HB_TAG ('m', 'e', 't', 'a'),
-  HB_TAG ('M', 'V', 'A', 'R'),
-  HB_TAG ('P', 'C', 'L', 'T'),
-  HB_OT_TAG_post,
-  HB_TAG ('p', 'r', 'e', 'p'),
-  HB_OT_TAG_sbix,
-  HB_TAG ('S', 'T', 'A', 'T'),
-  HB_TAG ('S', 'V', 'G', ' '),
-  HB_TAG ('V', 'D', 'M', 'X'),
-  HB_OT_TAG_vhea,
-  HB_OT_TAG_vmtx,
-  HB_OT_TAG_VORG,
-  HB_OT_TAG_VVAR,
-  HB_OT_TAG_name,
-  HB_OT_TAG_OS2
+  HB_TAG('a','v','a','r'),
+  HB_TAG('B','A','S','E'),
+  HB_TAG('C','B','D','T'),
+  HB_TAG('C','B','L','C'),
+  HB_TAG('C','F','F',' '),
+  HB_TAG('C','F','F','2'),
+  HB_TAG('c','m','a','p'),
+  HB_TAG('C','O','L','R'),
+  HB_TAG('C','P','A','L'),
+  HB_TAG('c','v','a','r'),
+  HB_TAG('c','v','t',' '),
+  HB_TAG('D','S','I','G'),
+  HB_TAG('E','B','D','T'),
+  HB_TAG('E','B','L','C'),
+  HB_TAG('E','B','S','C'),
+  HB_TAG('f','p','g','m'),
+  HB_TAG('f','v','a','r'),
+  HB_TAG('g','a','s','p'),
+  HB_TAG('G','D','E','F'),
+  HB_TAG('g','l','y','f'),
+  HB_TAG('G','P','O','S'),
+  HB_TAG('G','S','U','B'),
+  HB_TAG('g','v','a','r'),
+  HB_TAG('h','d','m','x'),
+  HB_TAG('h','e','a','d'),
+  HB_TAG('h','h','e','a'),
+  HB_TAG('h','m','t','x'),
+  HB_TAG('H','V','A','R'),
+  HB_TAG('J','S','T','F'),
+  HB_TAG('k','e','r','n'),
+  HB_TAG('l','o','c','a'),
+  HB_TAG('L','T','S','H'),
+  HB_TAG('M','A','T','H'),
+  HB_TAG('m','a','x','p'),
+  HB_TAG('M','E','R','G'),
+  HB_TAG('m','e','t','a'),
+  HB_TAG('M','V','A','R'),
+  HB_TAG('P','C','L','T'),
+  HB_TAG('p','o','s','t'),
+  HB_TAG('p','r','e','p'),
+  HB_TAG('s','b','i','x'),
+  HB_TAG('S','T','A','T'),
+  HB_TAG('S','V','G',' '),
+  HB_TAG('V','D','M','X'),
+  HB_TAG('v','h','e','a'),
+  HB_TAG('v','m','t','x'),
+  HB_TAG('V','O','R','G'),
+  HB_TAG('V','V','A','R'),
+  HB_TAG('n','a','m','e'),
+  HB_TAG('O','S','/','2')
 };
 
 static bool _table_is_empty (const hb_face_t *face, hb_tag_t tag)
@@ -213,170 +167,7 @@
 }
 
 
-static unsigned
-_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
-				  unsigned table_len,
-				  hb_tag_t table_tag)
-{
-  unsigned src_glyphs = plan->source->get_num_glyphs ();
-  unsigned dst_glyphs = plan->glyphset ()->get_population ();
-
-  unsigned bulk = 8192;
-  /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's
-   * because those are expensive to subset, so giving them more room is fine. */
-  bool same_size = table_tag == HB_OT_TAG_GSUB ||
-		   table_tag == HB_OT_TAG_GPOS ||
-		   table_tag == HB_OT_TAG_name;
-
-  if (plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS)
-  {
-    if (table_tag == HB_OT_TAG_CFF1)
-    {
-      /* Add some extra room for the CFF charset. */
-      bulk += src_glyphs * 16;
-    }
-    else if (table_tag == HB_OT_TAG_CFF2)
-    {
-      /* Just extra CharString offsets. */
-      bulk += src_glyphs * 4;
-    }
-  }
-
-  if (unlikely (!src_glyphs) || same_size)
-    return bulk + table_len;
-
-  return bulk + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
-}
-
-/*
- * Repack the serialization buffer if any offset overflows exist.
- */
-static hb_blob_t*
-_repack (hb_tag_t tag, const hb_serialize_context_t& c)
-{
-  if (!c.offset_overflow ())
-    return c.copy_blob ();
-
-  hb_blob_t* result = hb_resolve_overflows (c.object_graph (), tag);
-
-  if (unlikely (!result))
-  {
-    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c offset overflow resolution failed.",
-               HB_UNTAG (tag));
-    return nullptr;
-  }
-
-  return result;
-}
-
-template<typename TableType>
-static
-bool
-_try_subset (const TableType *table,
-             hb_vector_t<char>* buf,
-             hb_subset_context_t* c /* OUT */)
-{
-  c->serializer->start_serialize ();
-  if (c->serializer->in_error ()) return false;
-
-  bool needed = table->subset (c);
-  if (!c->serializer->ran_out_of_room ())
-  {
-    c->serializer->end_serialize ();
-    return needed;
-  }
-
-  unsigned buf_size = buf->allocated;
-  buf_size = buf_size * 2 + 16;
-
-
-
-
-  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
-             HB_UNTAG (c->table_tag), buf_size);
-
-  if (unlikely (buf_size > c->source_blob->length * 256 ||
-		!buf->alloc_exact (buf_size)))
-  {
-    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
-               HB_UNTAG (c->table_tag), buf_size);
-    return needed;
-  }
-
-  c->serializer->reset (buf->arrayZ, buf->allocated);
-  return _try_subset (table, buf, c);
-}
-
-template <typename T>
-static auto _do_destroy (T &t, hb_priority<1>) HB_RETURN (void, t.destroy ())
-
-template <typename T>
-static void _do_destroy (T &t, hb_priority<0>) {}
-
-template<typename TableType>
 static bool
-_subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
-{
-  auto &&source_blob = plan->source_table<TableType> ();
-  auto *table = source_blob.get ();
-
-  hb_tag_t tag = TableType::tableTag;
-  hb_blob_t *blob = source_blob.get_blob();
-  if (unlikely (!blob || !blob->data))
-  {
-    DEBUG_MSG (SUBSET, nullptr,
-               "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
-    _do_destroy (source_blob, hb_prioritize);
-    return false;
-  }
-
-  unsigned buf_size = _plan_estimate_subset_table_size (plan, blob->length, TableType::tableTag);
-  DEBUG_MSG (SUBSET, nullptr,
-             "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
-  if (unlikely (!buf.alloc (buf_size)))
-  {
-    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
-    _do_destroy (source_blob, hb_prioritize);
-    return false;
-  }
-
-  bool needed = false;
-  hb_serialize_context_t serializer (buf.arrayZ, buf.allocated);
-  {
-    hb_subset_context_t c (blob, plan, &serializer, tag);
-    needed = _try_subset (table, &buf, &c);
-  }
-  _do_destroy (source_blob, hb_prioritize);
-
-  if (serializer.in_error () && !serializer.only_offset_overflow ())
-  {
-    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset FAILED!", HB_UNTAG (tag));
-    return false;
-  }
-
-  if (!needed)
-  {
-    DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
-    return true;
-  }
-
-  bool result = false;
-  hb_blob_t *dest_blob = _repack (tag, serializer);
-  if (dest_blob)
-  {
-    DEBUG_MSG (SUBSET, nullptr,
-               "OT::%c%c%c%c final subset table size: %u bytes.",
-               HB_UNTAG (tag), dest_blob->length);
-    result = plan->add_table (tag, dest_blob);
-    hb_blob_destroy (dest_blob);
-  }
-
-  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s",
-             HB_UNTAG (tag), result ? "success" : "FAILED!");
-  return result;
-}
-
-static bool
 _is_table_present (hb_face_t *source, hb_tag_t tag)
 {
 
@@ -407,34 +198,34 @@
 
   switch (tag)
   {
-  case HB_TAG ('c','v','a','r'): /* hint table, fallthrough */
+  case HB_TAG('c','v','a','r'): /* hint table, fallthrough */
     return plan->all_axes_pinned || (plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
 
-  case HB_TAG ('c','v','t',' '): /* hint table, fallthrough */
-  case HB_TAG ('f','p','g','m'): /* hint table, fallthrough */
-  case HB_TAG ('p','r','e','p'): /* hint table, fallthrough */
-  case HB_TAG ('h','d','m','x'): /* hint table, fallthrough */
-  case HB_TAG ('V','D','M','X'): /* hint table, fallthrough */
+  case HB_TAG('c','v','t',' '): /* hint table, fallthrough */
+  case HB_TAG('f','p','g','m'): /* hint table, fallthrough */
+  case HB_TAG('p','r','e','p'): /* hint table, fallthrough */
+  case HB_TAG('h','d','m','x'): /* hint table, fallthrough */
+  case HB_TAG('V','D','M','X'): /* hint table, fallthrough */
     return plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
 
 #ifdef HB_NO_SUBSET_LAYOUT
     // Drop Layout Tables if requested.
-  case HB_OT_TAG_GDEF:
-  case HB_OT_TAG_GPOS:
-  case HB_OT_TAG_GSUB:
-  case HB_TAG ('m','o','r','x'):
-  case HB_TAG ('m','o','r','t'):
-  case HB_TAG ('k','e','r','x'):
-  case HB_TAG ('k','e','r','n'):
+  case HB_TAG('G','D','E','F'):
+  case HB_TAG('G','P','O','S'):
+  case HB_TAG('G','S','U','B'):
+  case HB_TAG('m','o','r','x'):
+  case HB_TAG('m','o','r','t'):
+  case HB_TAG('k','e','r','x'):
+  case HB_TAG('k','e','r','n'):
     return true;
 #endif
 
-  case HB_TAG ('a','v','a','r'):
-  case HB_TAG ('f','v','a','r'):
-  case HB_TAG ('g','v','a','r'):
-  case HB_OT_TAG_HVAR:
-  case HB_OT_TAG_VVAR:
-  case HB_TAG ('M','V','A','R'):
+  case HB_TAG('a','v','a','r'):
+  case HB_TAG('f','v','a','r'):
+  case HB_TAG('g','v','a','r'):
+  case HB_TAG('H','V','A','R'):
+  case HB_TAG('V','V','A','R'):
+  case HB_TAG('M','V','A','R'):
     return plan->all_axes_pinned;
 
   default:
@@ -443,15 +234,6 @@
 }
 
 static bool
-_passthrough (hb_subset_plan_t *plan, hb_tag_t tag)
-{
-  hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
-  bool result = plan->add_table (tag, source_table);
-  hb_blob_destroy (source_table);
-  return result;
-}
-
-static bool
 _dependencies_satisfied (hb_subset_plan_t *plan, hb_tag_t tag,
                          const hb_set_t &subsetted_tags,
                          const hb_set_t &pending_subset_tags)
@@ -458,13 +240,13 @@
 {
   switch (tag)
   {
-  case HB_OT_TAG_hmtx:
-  case HB_OT_TAG_vmtx:
-  case HB_OT_TAG_maxp:
-  case HB_OT_TAG_OS2:
-    return !plan->normalized_coords || !pending_subset_tags.has (HB_OT_TAG_glyf);
-  case HB_OT_TAG_GPOS:
-    return plan->all_axes_pinned || !pending_subset_tags.has (HB_OT_TAG_GDEF);
+  case HB_TAG('h','m','t','x'):
+  case HB_TAG('v','m','t','x'):
+  case HB_TAG('m','a','x','p'):
+  case HB_TAG('O','S','/','2'):
+    return !plan->normalized_coords || !pending_subset_tags.has (HB_TAG('g','l','y','f'));
+  case HB_TAG('G','P','O','S'):
+    return plan->all_axes_pinned || !pending_subset_tags.has (HB_TAG('G','D','E','F'));
   default:
     return true;
   }
@@ -476,73 +258,34 @@
 	       hb_tag_t tag)
 {
   if (plan->no_subset_tables.has (tag)) {
-    return _passthrough (plan, tag);
+    return _hb_subset_table_passthrough (plan, tag);
   }
 
   DEBUG_MSG (SUBSET, nullptr, "subset %c%c%c%c", HB_UNTAG (tag));
+
+  bool success;
+  if (_hb_subset_table_layout (plan, buf, tag, &success) ||
+      _hb_subset_table_var (plan, buf, tag, &success) ||
+      _hb_subset_table_cff (plan, buf, tag, &success) ||
+      _hb_subset_table_color (plan, buf, tag, &success) ||
+      _hb_subset_table_other (plan, buf, tag, &success))
+    return success;
+
+
   switch (tag)
   {
-  case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan, buf);
-  case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan, buf);
-  case HB_OT_TAG_name: return _subset<const OT::name> (plan, buf);
-  case HB_OT_TAG_head:
-    if (_is_table_present (plan->source, HB_OT_TAG_glyf) && !_should_drop_table (plan, HB_OT_TAG_glyf))
+  case HB_TAG('h','e','a','d'):
+    if (_is_table_present (plan->source, HB_TAG('g','l','y','f')) && !_should_drop_table (plan, HB_TAG('g','l','y','f')))
       return true; /* skip head, handled by glyf */
-    return _subset<const OT::head> (plan, buf);
-  case HB_OT_TAG_hhea: return true; /* skip hhea, handled by hmtx */
-  case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan, buf);
-  case HB_OT_TAG_vhea: return true; /* skip vhea, handled by vmtx */
-  case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan, buf);
-  case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan, buf);
-  case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan, buf);
-  case HB_OT_TAG_loca: return true; /* skip loca, handled by glyf */
-  case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan, buf);
-  case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan, buf);
-  case HB_OT_TAG_post: return _subset<const OT::post> (plan, buf);
-  case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan, buf);
-  case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan, buf);
-  case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan, buf);
-  case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
-  case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan, buf);
-  case HB_OT_TAG_BASE: return _subset<const OT::BASE> (plan, buf);
+    return _hb_subset_table<const OT::head> (plan, buf);
 
-#ifndef HB_NO_SUBSET_CFF
-  case HB_OT_TAG_CFF1: return _subset<const OT::cff1> (plan, buf);
-  case HB_OT_TAG_CFF2: return _subset<const OT::cff2> (plan, buf);
-  case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan, buf);
-#endif
+  case HB_TAG('S','T','A','T'):
+    if (!plan->user_axes_location.is_empty ()) return _hb_subset_table<const OT::STAT> (plan, buf);
+    else return _hb_subset_table_passthrough (plan, tag);
 
-#ifndef HB_NO_SUBSET_LAYOUT
-  case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan, buf);
-  case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan, buf);
-  case HB_OT_TAG_GPOS: return _subset<const GPOS> (plan, buf);
-  case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan, buf);
-  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_TAG('c','v','t',' '):
 #ifndef HB_NO_VAR
-  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_avar:
-    if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
-    return _subset<const OT::avar> (plan, buf);
-  case HB_OT_TAG_cvar:
-    if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
-    return _subset<const OT::cvar> (plan, buf);
-  case HB_OT_TAG_MVAR:
-    if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
-    return _subset<const OT::MVAR> (plan, buf);
-#endif
-
-  case HB_OT_TAG_STAT:
-    if (!plan->user_axes_location.is_empty ()) return _subset<const OT::STAT> (plan, buf);
-    else return _passthrough (plan, tag);
-
-  case HB_TAG ('c', 'v', 't', ' '):
-#ifndef HB_NO_VAR
-    if (_is_table_present (plan->source, HB_OT_TAG_cvar) &&
+    if (_is_table_present (plan->source, HB_TAG('c','v','a','r')) &&
         plan->normalized_coords && !plan->pinned_at_default)
     {
       auto &cvar = *plan->source->table.cvar;
@@ -549,15 +292,14 @@
       return OT::cvar::add_cvt_and_apply_deltas (plan, cvar.get_tuple_var_data (), &cvar);
     }
 #endif
-    return _passthrough (plan, tag);
+    return _hb_subset_table_passthrough (plan, tag);
+  }
 
-  default:
-    if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED)
-      return _passthrough (plan, tag);
+  if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED)
+    return _hb_subset_table_passthrough (plan, tag);
 
-    // Drop table
-    return true;
-  }
+  // Drop table
+  return true;
 }
 
 static void _attach_accelerator_data (hb_subset_plan_t* plan,
@@ -707,108 +449,4 @@
 
 end:
   return success ? hb_face_reference (plan->dest) : nullptr;
-}
-
-
-#ifdef HB_EXPERIMENTAL_API
-
-#include "hb-ot-cff1-table.hh"
-
-template<typename accel_t>
-static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_index) {
-  if (!accel.is_valid()) {
-    return hb_blob_get_empty ();
-  }
-
-  hb_ubytes_t bytes = (*accel.charStrings)[glyph_index];
-  if (!bytes) {
-    return hb_blob_get_empty ();
-  }
-
-  hb_blob_t* cff_blob = accel.get_blob();
-  uint32_t length;
-  const char* cff_data = hb_blob_get_data(cff_blob, &length) ;
-
-  long int offset = (const char*) bytes.arrayZ - cff_data;
-  if (offset < 0 || offset > INT32_MAX) {
-    return hb_blob_get_empty ();
-  }
-
-  return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, bytes.length);
-}
-
-template<typename accel_t>
-static hb_blob_t* get_charstrings_index(accel_t& accel) {
-  if (!accel.is_valid()) {
-    return hb_blob_get_empty ();
-  }
-
-  const char* charstrings_start = (const char*) accel.charStrings;
-  unsigned charstrings_length = accel.charStrings->get_size();
-
-  hb_blob_t* cff_blob = accel.get_blob();
-  uint32_t length;
-  const char* cff_data = hb_blob_get_data(cff_blob, &length) ;
-
-  long int offset = charstrings_start - cff_data;
-  if (offset < 0 || offset > INT32_MAX) {
-    return hb_blob_get_empty ();
-  }
-
-  return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, charstrings_length);
-}
-
-/**
- * hb_subset_cff_get_charstring_data:
- * @face: A face object
- * @glyph_index: Glyph index to get data for.
- *
- * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index.
- *
- * XSince: EXPERIMENTAL
- **/
-HB_EXTERN hb_blob_t*
-hb_subset_cff_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) {
-  return get_charstrings_data(*face->table.cff1, glyph_index);
-}
-
-/**
- * hb_subset_cff_get_charstrings_index:
- * @face: A face object
- *
- * Returns the raw CFF CharStrings INDEX from the CFF table.
- *
- * XSince: EXPERIMENTAL
- **/
-HB_EXTERN hb_blob_t*
-hb_subset_cff_get_charstrings_index (hb_face_t* face) {
-  return get_charstrings_index (*face->table.cff1);
-}
- 
-/**
- * hb_subset_cff2_get_charstring_data:
- * @face: A face object
- * @glyph_index: Glyph index to get data for.
- *
- * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index.
- *
- * XSince: EXPERIMENTAL
- **/
-HB_EXTERN hb_blob_t*
-hb_subset_cff2_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) {
-  return get_charstrings_data(*face->table.cff2, glyph_index);
-}
-
-/**
- * hb_subset_cff2_get_charstrings_index:
- * @face: A face object
- *
- * Returns the raw CFF2 CharStrings INDEX from the CFF2 table.
- *
- * XSince: EXPERIMENTAL
- **/
-HB_EXTERN hb_blob_t*
-hb_subset_cff2_get_charstrings_index (hb_face_t* face) {
-  return get_charstrings_index (*face->table.cff2);
-}
-#endif
\ No newline at end of file
+}
\ No newline at end of file

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -70,5 +70,4 @@
 			table_tag (table_tag_) {}
 };
 
-
 #endif /* HB_SUBSET_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh	2025-08-13 22:39:51 UTC (rev 76048)
@@ -136,6 +136,7 @@
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
 #pragma GCC diagnostic ignored "-Wformat-zero-length"
 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#pragma GCC diagnostic ignored "-Wold-style-cast"
 #pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang
 #pragma GCC diagnostic ignored "-Wrange-loop-analysis" // https://github.com/harfbuzz/harfbuzz/issues/2834
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
@@ -239,6 +240,8 @@
 // clang defines it so no need.
 #ifdef __has_builtin
 #define hb_has_builtin __has_builtin
+#elif defined(_MSC_VER)
+#define hb_has_builtin(x) 0
 #else
 #define hb_has_builtin(x) ((defined(__GNUC__) && __GNUC__ >= 5))
 #endif
@@ -557,4 +560,13 @@
 #include "hb-vector.hh"	// Requires: hb-array hb-null
 #include "hb-object.hh"	// Requires: hb-atomic hb-mutex hb-vector
 
+
+/* Our src/test-*.cc use hb_assert(), such that it's not compiled out under NDEBUG.
+ * https://github.com/harfbuzz/harfbuzz/issues/5418 */
+#define hb_always_assert(x) \
+	HB_STMT_START { \
+	  if (!(x)) { fprintf(stderr, "Assertion failed: %s, at %s:%d\n", #x, __FILE__, __LINE__); abort(); } \
+	} HB_STMT_END
+
+
 #endif /* HB_HH */

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build	2025-08-13 22:39:51 UTC (rev 76048)
@@ -341,6 +341,9 @@
 hb_harfrust_sources = files('hb-harfrust.cc')
 hb_harfrust_headers = files()
 
+hb_kbts_sources = files('hb-kbts.cc')
+hb_kbts_headers = files()
+
 hb_glib_sources = files('hb-glib.cc')
 hb_glib_headers = files('hb-glib.h')
 
@@ -403,6 +406,12 @@
   'hb-subset-plan.hh',
   'hb-subset-plan-member-list.hh',
   'hb-subset-serialize.cc',
+  'hb-subset-table.hh',
+  'hb-subset-table-layout.cc',
+  'hb-subset-table-var.cc',
+  'hb-subset-table-cff.cc',
+  'hb-subset-table-color.cc',
+  'hb-subset-table-other.cc',
   'graph/gsubgpos-context.cc',
   'graph/gsubgpos-context.hh',
   'graph/gsubgpos-graph.hh',
@@ -549,6 +558,12 @@
   hb_headers += hb_harfrust_headers
 endif
 
+if conf.get('HAVE_KBTS', 0) == 1
+  hb_sources += hb_kbts_sources
+  hb_headers += hb_kbts_headers
+  harfbuzz_deps += [kbts_dep]
+endif
+
 have_icu = conf.get('HAVE_ICU', 0) == 1
 have_icu_builtin = conf.get('HAVE_ICU_BUILTIN', 0) == 1
 if have_icu and have_icu_builtin
@@ -750,7 +765,6 @@
     foreach name, source : noinst_programs
       executable(name, source,
         include_directories: incconfig,
-        cpp_args: cpp_args + ['-UNDEBUG'],
         dependencies: libharfbuzz_dep,
         install: false,
       )
@@ -1085,6 +1099,14 @@
       suite: ['src'],
     )
   endforeach
+
+  test('check-release-notes',
+    find_program('check-release-notes.py'),
+    args: [
+      meson.current_source_dir() / '..' / 'NEWS',
+      meson.project_version()
+    ],
+  )
 endif
 
 install_headers(hb_headers + hb_subset_headers, subdir: meson.project_name())

Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/.gitignore
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/.gitignore	                        (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/.gitignore	2025-08-13 22:39:51 UTC (rev 76048)
@@ -0,0 +1 @@
+Cargo.lock

Deleted: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/Cargo.lock
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/Cargo.lock	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/Cargo.lock	2025-08-13 22:39:51 UTC (rev 76048)
@@ -1,135 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "bitflags"
-version = "2.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
-
-[[package]]
-name = "bytemuck"
-version = "1.23.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422"
-dependencies = [
- "bytemuck_derive",
-]
-
-[[package]]
-name = "bytemuck_derive"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "441473f2b4b0459a68628c744bc61d23e730fb00128b841d30fa4bb3972257e4"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "core_maths"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"
-dependencies = [
- "libm",
-]
-
-[[package]]
-name = "font-types"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02a596f5713680923a2080d86de50fe472fb290693cf0f701187a1c8b36996b7"
-dependencies = [
- "bytemuck",
-]
-
-[[package]]
-name = "harfbuzz_rust"
-version = "0.0.0"
-dependencies = [
- "harfrust",
- "skrifa",
-]
-
-[[package]]
-name = "harfrust"
-version = "0.1.0"
-source = "git+https://github.com/harfbuzz/harfrust#77fb262c8e99a2556b84b8c6ddead5980d2b3ccd"
-dependencies = [
- "bitflags",
- "bytemuck",
- "core_maths",
- "read-fonts",
- "smallvec",
-]
-
-[[package]]
-name = "libm"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.95"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "read-fonts"
-version = "0.30.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "192735ef611aac958468e670cb98432c925426f3cb71521fda202130f7388d91"
-dependencies = [
- "bytemuck",
- "core_maths",
- "font-types",
-]
-
-[[package]]
-name = "skrifa"
-version = "0.32.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6d632b5a73f566303dbeabd344dc3e716fd4ddc9a70d6fc8ea8e6f06617da97"
-dependencies = [
- "bytemuck",
- "read-fonts",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
-
-[[package]]
-name = "syn"
-version = "2.0.104"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/Cargo.toml
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/Cargo.toml	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/Cargo.toml	2025-08-13 22:39:51 UTC (rev 76048)
@@ -5,7 +5,7 @@
 
 [dependencies]
 skrifa = { version = "0.*", optional = true }
-harfrust = { git = "https://github.com/harfbuzz/harfrust", optional = true }
+harfrust = { version = "0.1.*", optional = true }
 
 [lib]
 name = "harfbuzz_rust"

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/meson.build	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/meson.build	2025-08-13 22:39:51 UTC (rev 76048)
@@ -52,7 +52,7 @@
 
 harfbuzz_rust = custom_target(
   'harfbuzz_rust',
-  input: sources + ['Cargo.toml', 'Cargo.lock'],
+  input: sources + ['Cargo.toml'],
   output: ['libharfbuzz_rust.a'],
   depends: [hb_rs],
   env: ['OUT_DIR=' + meson.current_build_dir(),

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/shape.rs
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/shape.rs	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/rust/shape.rs	2025-08-13 22:39:51 UTC (rev 76048)
@@ -99,6 +99,18 @@
 }
 
 #[no_mangle]
+pub unsafe extern "C" fn _hb_harfrust_buffer_create_rs() -> *mut c_void {
+    let hr_buffer = Box::new(harfrust::UnicodeBuffer::new());
+    Box::into_raw(hr_buffer) as *mut c_void
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn _hb_harfrust_buffer_destroy_rs(data: *mut c_void) {
+    let data = data as *mut harfrust::UnicodeBuffer;
+    let _hr_buffer = Box::from_raw(data);
+}
+
+#[no_mangle]
 pub unsafe extern "C" fn _hb_harfrust_shape_plan_create_rs(
     font_data: *const c_void,
     face_data: *const c_void,
@@ -144,6 +156,7 @@
     font_data: *const c_void,
     face_data: *const c_void,
     shape_plan: *const c_void,
+    hr_buffer_box: *const c_void,
     font: *mut hb_font_t,
     buffer: *mut hb_buffer_t,
     features: *const hb_feature_t,
@@ -154,7 +167,9 @@
 
     let font_ref = &(*face_data).font_ref;
 
-    let mut hr_buffer = harfrust::UnicodeBuffer::new();
+    let hr_buffer_box = hr_buffer_box as *mut harfrust::UnicodeBuffer;
+    let mut hr_buffer_box = Box::from_raw(hr_buffer_box);
+    let mut hr_buffer = *hr_buffer_box;
 
     // Set buffer properties
     let cluster_level = hb_buffer_get_cluster_level(buffer);
@@ -299,5 +314,9 @@
         pos.y_offset = (hr_pos.y_offset as f32 * y_scale + 0.5).floor() as hb_position_t;
     }
 
+    let hr_buffer = glyphs.clear();
+    *hr_buffer_box = hr_buffer; // Move the buffer back into the box
+    let _ = Box::into_raw(hr_buffer_box); // Prevent double free
+
     true as hb_bool_t
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-algs.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-algs.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-algs.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -47,16 +47,16 @@
   auto p = hb_pair (1, i);
 
   p.second = 2;
-  assert (i == 2);
+  hb_always_assert (i == 2);
 
   const int c = 3;
   auto pc = hb_pair (1, c);
-  assert (pc.second == 3);
+  hb_always_assert (pc.second == 3);
 
   auto q = p;
-  assert (&q != &p);
+  hb_always_assert (&q != &p);
   q.second = 4;
-  assert (i == 4);
+  hb_always_assert (i == 4);
 
   hb_invoke (test_func, 0, nullptr);
 
@@ -63,8 +63,8 @@
   A a;
   hb_invoke (&A::a, a);
 
-  assert (1 == hb_min (8, 1));
-  assert (8 == hb_max (8, 1));
+  hb_always_assert (1 == hb_min (8, 1));
+  hb_always_assert (8 == hb_max (8, 1));
 
   int x = 1, y = 2;
   hb_min (x, 3);
@@ -72,39 +72,39 @@
   hb_min (x, 4 + 3);
   int &z = hb_min (x, y);
   z = 3;
-  assert (x == 3);
+  hb_always_assert (x == 3);
 
   hb_pair_t<const int*, int> xp = hb_pair_t<int *, long> (nullptr, 0);
   xp = hb_pair_t<int *, double> (nullptr, 1);
   xp = hb_pair_t<const int*, int> (nullptr, 1);
 
-  assert (3 == hb_partial (hb_min, 3) (4));
-  assert (3 == hb_partial<1> (hb_min, 4) (3));
+  hb_always_assert (3 == hb_partial (hb_min, 3) (4));
+  hb_always_assert (3 == hb_partial<1> (hb_min, 4) (3));
 
   auto M0 = hb_partial<2> (hb_max, 0);
-  assert (M0 (-2) == 0);
-  assert (M0 (+2) == 2);
+  hb_always_assert (M0 (-2) == 0);
+  hb_always_assert (M0 (+2) == 2);
 
-  assert (hb_add (2) (5) == 7);
-  assert (hb_add (5) (2) == 7);
+  hb_always_assert (hb_add (2) (5) == 7);
+  hb_always_assert (hb_add (5) (2) == 7);
 
   x = 1;
-  assert (++hb_inc (x) == 3);
-  assert (x == 3);
+  hb_always_assert (++hb_inc (x) == 3);
+  hb_always_assert (x == 3);
 
   hb_set_t set1 {1};
   hb_set_t set2 {2};
 
-  assert (hb_hash (set1) != hb_hash (set2));
-  assert (hb_hash (set1) == hb_hash (hb_set_t {1}));
-  assert (hb_hash (set1) != hb_hash (hb_set_t {}));
-  assert (hb_hash (set1) != hb_hash (hb_set_t {2}));
-  assert (hb_hash (set2) == hb_hash (hb_set_t {2}));
+  hb_always_assert (hb_hash (set1) != hb_hash (set2));
+  hb_always_assert (hb_hash (set1) == hb_hash (hb_set_t {1}));
+  hb_always_assert (hb_hash (set1) != hb_hash (hb_set_t {}));
+  hb_always_assert (hb_hash (set1) != hb_hash (hb_set_t {2}));
+  hb_always_assert (hb_hash (set2) == hb_hash (hb_set_t {2}));
 
   /* hb_hash, unlike std::hash, dereferences pointers. */
-  assert (hb_hash (set1) == hb_hash (&set1));
-  assert (hb_hash (set1) == hb_hash (hb::shared_ptr<hb_set_t> {hb_set_reference (&set1)}));
-  assert (hb_hash (set1) == hb_hash (hb::unique_ptr<hb_set_t> {hb_set_reference (&set1)}));
+  hb_always_assert (hb_hash (set1) == hb_hash (&set1));
+  hb_always_assert (hb_hash (set1) == hb_hash (hb::shared_ptr<hb_set_t> {hb_set_reference (&set1)}));
+  hb_always_assert (hb_hash (set1) == hb_hash (hb::unique_ptr<hb_set_t> {hb_set_reference (&set1)}));
 
   return 0;
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-array.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-array.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-array.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -36,7 +36,7 @@
 
   int expected_values[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};
   hb_array_t<int> expected (expected_values, 9);
-  assert (a == expected);
+  hb_always_assert (a == expected);
 }
 
 static void
@@ -48,7 +48,7 @@
 
   int expected_values[] = {1, 2, 6, 5, 4, 3, 7, 8, 9};
   hb_array_t<int> expected (expected_values, 9);
-  assert (a == expected);
+  hb_always_assert (a == expected);
 }
 
 static void
@@ -64,7 +64,7 @@
 
   int expected_values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
   hb_array_t<int> expected (expected_values, 9);
-  assert (a == expected);
+  hb_always_assert (a == expected);
 }
 
 int
@@ -71,7 +71,7 @@
 main (int argc, char **argv)
 {
   /* The following fails on MSVC. */
-  // assert (sizeof (hb_array_t<int>) == sizeof (hb_sorted_array_t<int>));
+  // hb_always_assert (sizeof (hb_array_t<int>) == sizeof (hb_sorted_array_t<int>));
 
   test_reverse ();
   test_reverse_range ();

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-bimap.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-bimap.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-bimap.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -32,45 +32,45 @@
 {
   hb_bimap_t	bm;
 
-  assert (bm.is_empty () == true);
+  hb_always_assert (bm.is_empty () == true);
   bm.set (1, 4);
   bm.set (2, 5);
   bm.set (3, 6);
-  assert (bm.get_population () == 3);
-  assert (bm.has (1) == true);
-  assert (bm.has (4) == false);
-  assert (bm[2] == 5);
-  assert (bm.backward (6) == 3);
+  hb_always_assert (bm.get_population () == 3);
+  hb_always_assert (bm.has (1) == true);
+  hb_always_assert (bm.has (4) == false);
+  hb_always_assert (bm[2] == 5);
+  hb_always_assert (bm.backward (6) == 3);
   bm.del (1);
-  assert (bm.has (1) == false);
-  assert (bm.has (3) == true);
+  hb_always_assert (bm.has (1) == false);
+  hb_always_assert (bm.has (3) == true);
   bm.clear ();
-  assert (bm.get_population () == 0);
+  hb_always_assert (bm.get_population () == 0);
 
   hb_inc_bimap_t  ibm;
 
-  assert (ibm.add (13) == 0);
-  assert (ibm.add (8) == 1);
-  assert (ibm.add (10) == 2);
-  assert (ibm.add (8) == 1);
-  assert (ibm.add (7) == 3);
-  assert (ibm.get_population () == 4);
-  assert (ibm[7] == 3);
+  hb_always_assert (ibm.add (13) == 0);
+  hb_always_assert (ibm.add (8) == 1);
+  hb_always_assert (ibm.add (10) == 2);
+  hb_always_assert (ibm.add (8) == 1);
+  hb_always_assert (ibm.add (7) == 3);
+  hb_always_assert (ibm.get_population () == 4);
+  hb_always_assert (ibm[7] == 3);
 
   ibm.sort ();
-  assert (ibm.get_population () == 4);
-  assert (ibm[7] == 0);
-  assert (ibm[13] == 3);
+  hb_always_assert (ibm.get_population () == 4);
+  hb_always_assert (ibm[7] == 0);
+  hb_always_assert (ibm[13] == 3);
 
   ibm.identity (3);
-  assert (ibm.get_population () == 3);
-  assert (ibm[0] == 0);
-  assert (ibm[1] == 1);
-  assert (ibm[2] == 2);
-  assert (ibm.backward (0) == 0);
-  assert (ibm.backward (1) == 1);
-  assert (ibm.backward (2) == 2);
-  assert (ibm.has (4) == false);
+  hb_always_assert (ibm.get_population () == 3);
+  hb_always_assert (ibm[0] == 0);
+  hb_always_assert (ibm[1] == 1);
+  hb_always_assert (ibm[2] == 2);
+  hb_always_assert (ibm.backward (0) == 0);
+  hb_always_assert (ibm.backward (1) == 1);
+  hb_always_assert (ibm.backward (2) == 2);
+  hb_always_assert (ibm.has (4) == false);
 
   return 0;
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -64,7 +64,7 @@
     argv[1] = (char *) "/dev/null";
 
   hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
-  assert (blob);
+  hb_always_assert (blob);
   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
   hb_blob_destroy (blob);
   blob = nullptr;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-cff.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-cff.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-cff.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -64,9 +64,9 @@
       struct num_tp_test num_tp_test = num_tp_tests[t];
       number.set_real (num_tp_test.input);
       encoder.encode_num_tp (number);
-      assert (buff.length == num_tp_test.length);
+      hb_always_assert (buff.length == num_tp_test.length);
       for (unsigned i = 0; i < buff.length; i++)
-	assert (buff[i] == num_tp_test.output[i]);
+	hb_always_assert (buff[i] == num_tp_test.output[i]);
       encoder.reset ();
     }
   }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-decycler.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-decycler.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-decycler.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -38,7 +38,7 @@
   hb_decycler_node_t node (decycler);
 
   bool ret = node.visit (value);
-  assert (ret);
+  hb_always_assert (ret);
 
   tree_recurse_binary (value * 2 + 1, max_value, decycler);
   tree_recurse_binary (value * 2 + 2, max_value, decycler);
@@ -63,7 +63,7 @@
   for (unsigned i = 1; i <= 3; i++)
   {
     bool ret = node.visit (value + i);
-    assert (ret);
+    hb_always_assert (ret);
 
     tree_recurse_tertiary (value + i, max_value, decycler);
   }
@@ -82,7 +82,7 @@
 	       signed cycle_length,
 	       hb_decycler_t &decycler)
 {
-  assert (cycle_length > 0);
+  hb_always_assert (cycle_length > 0);
 
   hb_decycler_node_t node (decycler);
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gpos-size-params.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gpos-size-params.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gpos-size-params.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -43,7 +43,7 @@
 
   /* Create the face */
   hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
-  assert (blob);
+  hb_always_assert (blob);
   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
   hb_blob_destroy (blob);
   blob = nullptr;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-would-substitute.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-would-substitute.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-would-substitute.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -47,7 +47,7 @@
 
   /* Create the face */
   hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
-  assert (blob);
+  hb_always_assert (blob);
   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
   hb_blob_destroy (blob);
   blob = nullptr;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-item-varstore.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-item-varstore.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-item-varstore.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -43,7 +43,7 @@
   const OT::ItemVariationStore& src_var_store = hvar_table+(hvar_table->varStore);
   bool result = item_vars.create_from_item_varstore (src_var_store, axis_idx_tag_map);
       
-  assert (result);
+  hb_always_assert (result);
 
   /* partial instancing wght=300:800 */
   hb_hashmap_t<hb_tag_t, Triple> normalized_axes_location;
@@ -53,10 +53,10 @@
   axes_triple_distances.set (axis_tag, TripleDistances (200.0, 500.0));
 
   result = item_vars.instantiate_tuple_vars (normalized_axes_location, axes_triple_distances);
-  assert (result);
+  hb_always_assert (result);
   result = item_vars.as_item_varstore (false);
-  assert (result);
-  assert (item_vars.get_region_list().length == 8);
+  hb_always_assert (result);
+  hb_always_assert (item_vars.get_region_list().length == 8);
 }
 
 int

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -84,7 +84,7 @@
   it = it + 10;
   it = 10 + it;
 
-  assert (*it == it[0]);
+  hb_always_assert (*it == it[0]);
 
   static_assert (true || it.is_random_access_iterator, "");
   static_assert (true || it.is_sorted_iterator, "");
@@ -96,7 +96,7 @@
 test_iterator (Iter it)
 {
   Iter default_constructed;
-  assert (!default_constructed);
+  hb_always_assert (!default_constructed);
 
   test_iterator_non_default_constructable (it);
 }
@@ -118,7 +118,7 @@
 {
   int i = 1;
   for (int v : +it) {
-    assert (v == i++);
+    hb_always_assert (v == i++);
   }
 }
 
@@ -131,16 +131,16 @@
   hb_vector_t<int> d = {1, 2, 3, 4, 5};
 
   auto it1 = hb_concat (a, b);
-  assert (it1.len () == 5);
-  assert (it1.is_random_access_iterator);
+  hb_always_assert (it1.len () == 5);
+  hb_always_assert (it1.is_random_access_iterator);
   auto it2 = hb_concat (c, d);
-  assert (it2.len () == 5);
+  hb_always_assert (it2.len () == 5);
   auto it3 = hb_concat (d, c);
-  assert (it3.len () == 5);
+  hb_always_assert (it3.len () == 5);
   for (int i = 0; i < 5; i++) {
-    assert(it1[i] == i + 1);
-    assert(it2[i] == i + 1);
-    assert(it3[i] == i + 1);
+    hb_always_assert(it1[i] == i + 1);
+    hb_always_assert(it2[i] == i + 1);
+    hb_always_assert(it3[i] == i + 1);
   }
 
   check_sequential (it1);
@@ -149,40 +149,40 @@
 
   auto it4 = +it1;
   it4 += 0;
-  assert (*it4 == 1);
+  hb_always_assert (*it4 == 1);
 
   it4 += 2;
-  assert (*it4 == 3);
-  assert (it4);
-  assert (it4.len () == 3);
+  hb_always_assert (*it4 == 3);
+  hb_always_assert (it4);
+  hb_always_assert (it4.len () == 3);
 
   it4 += 2;
-  assert (*it4 == 5);
-  assert (it4);
-  assert (it4.len () == 1);
+  hb_always_assert (*it4 == 5);
+  hb_always_assert (it4);
+  hb_always_assert (it4.len () == 1);
 
   it4++;
-  assert (!it4);
-  assert (it4.len () == 0);
+  hb_always_assert (!it4);
+  hb_always_assert (it4.len () == 0);
 
   auto it5 = +it1;
   it5 += 3;
-  assert (*it5 == 4);
+  hb_always_assert (*it5 == 4);
 
   hb_set_t s_a = {1, 2, 3};
   hb_set_t s_b = {4, 5};
   auto it6 = hb_concat (s_a, s_b);
-  assert (!it6.is_random_access_iterator);
+  hb_always_assert (!it6.is_random_access_iterator);
   check_sequential (it6);
-  assert (it6.len () == 5);
+  hb_always_assert (it6.len () == 5);
 
   it6 += 0;
-  assert (*it6 == 1);
+  hb_always_assert (*it6 == 1);
 
   it6 += 3;
-  assert (*it6 == 4);
-  assert (it6);
-  assert (it6.len () == 2);
+  hb_always_assert (*it6 == 4);
+  hb_always_assert (it6);
+  hb_always_assert (it6.len () == 2);
 }
 
 int
@@ -235,16 +235,16 @@
   test_iterator_non_default_constructable (hb_iter (st) | hb_filter ());
   test_iterator_non_default_constructable (hb_iter (st) | hb_map (hb_lidentity));
 
-  assert (true == hb_all (st));
-  assert (false == hb_all (st, 42u));
-  assert (true == hb_any (st));
-  assert (false == hb_any (st, 14u));
-  assert (true == hb_any (st, 14u, [] (unsigned _) { return _ - 1u; }));
-  assert (true == hb_any (st, [] (unsigned _) { return _ == 15u; }));
-  assert (true == hb_any (st, 15u));
-  assert (false == hb_none (st));
-  assert (false == hb_none (st, 15u));
-  assert (true == hb_none (st, 17u));
+  hb_always_assert (true == hb_all (st));
+  hb_always_assert (false == hb_all (st, 42u));
+  hb_always_assert (true == hb_any (st));
+  hb_always_assert (false == hb_any (st, 14u));
+  hb_always_assert (true == hb_any (st, 14u, [] (unsigned _) { return _ - 1u; }));
+  hb_always_assert (true == hb_any (st, [] (unsigned _) { return _ == 15u; }));
+  hb_always_assert (true == hb_any (st, 15u));
+  hb_always_assert (false == hb_none (st));
+  hb_always_assert (false == hb_none (st, 15u));
+  hb_always_assert (true == hb_none (st, 17u));
 
   hb_array_t<hb_vector_t<int>> pa;
   pa->as_array ();
@@ -318,7 +318,7 @@
 	       }, hb_map_create ())
   ;
   /* The result should be something like 0->10, 1->11, ..., 9->19 */
-  assert (hb_map_get (result, 9) == 19);
+  hb_always_assert (hb_map_get (result, 9) == 19);
   hb_map_destroy (result);
 
   /* Like above, but passing hb_set_t instead of hb_set_t * */
@@ -341,7 +341,7 @@
 	       }, hb_map_create ())
   ;
   /* The result should be something like 0->10, 1->11, ..., 9->19 */
-  assert (hb_map_get (result, 9) == 19);
+  hb_always_assert (hb_map_get (result, 9) == 19);
   hb_map_destroy (result);
 
   unsigned int temp3 = 0;
@@ -361,20 +361,20 @@
   hb_iota ();
   hb_iota (3);
   hb_iota (3, 2);
-  assert ((&vl) + 1 == *++hb_iota (&vl, hb_inc));
+  hb_always_assert ((&vl) + 1 == *++hb_iota (&vl, hb_inc));
   hb_range ();
   hb_repeat (7u);
   hb_repeat (nullptr);
   hb_repeat (vl) | hb_chop (3);
-  assert (hb_len (hb_range (10) | hb_take (3)) == 3);
-  assert (hb_range (9).len () == 9);
-  assert (hb_range (2, 9).len () == 7);
-  assert (hb_range (2, 9, 3).len () == 3);
-  assert (hb_range (2, 8, 3).len () == 2);
-  assert (hb_range (2, 7, 3).len () == 2);
-  assert (hb_range (-2, -9, -3).len () == 3);
-  assert (hb_range (-2, -8, -3).len () == 2);
-  assert (hb_range (-2, -7, -3).len () == 2);
+  hb_always_assert (hb_len (hb_range (10) | hb_take (3)) == 3);
+  hb_always_assert (hb_range (9).len () == 9);
+  hb_always_assert (hb_range (2, 9).len () == 7);
+  hb_always_assert (hb_range (2, 9, 3).len () == 3);
+  hb_always_assert (hb_range (2, 8, 3).len () == 2);
+  hb_always_assert (hb_range (2, 7, 3).len () == 2);
+  hb_always_assert (hb_range (-2, -9, -3).len () == 3);
+  hb_always_assert (hb_range (-2, -8, -3).len () == 2);
+  hb_always_assert (hb_range (-2, -7, -3).len () == 2);
 
   test_concat ();
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -36,10 +36,10 @@
     hb_map_t v1;
     v1.set (1, 2);
     hb_map_t v2 {v1};
-    assert (v1.get_population () == 1);
-    assert (v2.get_population () == 1);
-    assert (v1[1] == 2);
-    assert (v2[1] == 2);
+    hb_always_assert (v1.get_population () == 1);
+    hb_always_assert (v2.get_population () == 1);
+    hb_always_assert (v1[1] == 2);
+    hb_always_assert (v2[1] == 2);
   }
 
   /* Test copy assignment. */
@@ -47,10 +47,10 @@
     hb_map_t v1;
     v1.set (1, 2);
     hb_map_t v2 = v1;
-    assert (v1.get_population () == 1);
-    assert (v2.get_population () == 1);
-    assert (v1[1] == 2);
-    assert (v2[1] == 2);
+    hb_always_assert (v1.get_population () == 1);
+    hb_always_assert (v2.get_population () == 1);
+    hb_always_assert (v1[1] == 2);
+    hb_always_assert (v2[1] == 2);
   }
 
   /* Test move constructor. */
@@ -58,8 +58,8 @@
     hb_map_t s {};
     s.set (1, 2);
     hb_map_t v (std::move (s));
-    assert (s.get_population () == 0);
-    assert (v.get_population () == 1);
+    hb_always_assert (s.get_population () == 0);
+    hb_always_assert (v.get_population () == 1);
   }
 
   /* Test move assignment. */
@@ -68,8 +68,8 @@
     s.set (1, 2);
     hb_map_t v;
     v = std::move (s);
-    assert (s.get_population () == 0);
-    assert (v.get_population () == 1);
+    hb_always_assert (s.get_population () == 0);
+    hb_always_assert (v.get_population () == 1);
   }
 
   /* Test initializing from iterable. */
@@ -84,10 +84,10 @@
     hb_map_t v1 (s);
     hb_map_t v2 (std::move (s));
 
-    assert (s.get_population () == 0);
-    assert (v0.get_population () == 2);
-    assert (v1.get_population () == 2);
-    assert (v2.get_population () == 2);
+    hb_always_assert (s.get_population () == 0);
+    hb_always_assert (v0.get_population () == 2);
+    hb_always_assert (v1.get_population () == 2);
+    hb_always_assert (v2.get_population () == 2);
   }
 
   /* Test call fini() twice. */
@@ -107,7 +107,7 @@
 
     hb_map_t v (hb_iter (s));
 
-    assert (v.get_population () == 2);
+    hb_always_assert (v.get_population () == 2);
   }
 
   /* Test initializing from initializer list and swapping. */
@@ -116,8 +116,8 @@
     hb_map_t v1 {pair_t{1,2}, pair_t{4,5}};
     hb_map_t v2 {pair_t{3,4}};
     hb_swap (v1, v2);
-    assert (v1.get_population () == 1);
-    assert (v2.get_population () == 2);
+    hb_always_assert (v1.get_population () == 1);
+    hb_always_assert (v2.get_population () == 2);
   }
 
   /* Test class key / value types. */
@@ -125,9 +125,9 @@
     hb_hashmap_t<hb_bytes_t, int> m1;
     hb_hashmap_t<int, hb_bytes_t> m2;
     hb_hashmap_t<hb_bytes_t, hb_bytes_t> m3;
-    assert (m1.get_population () == 0);
-    assert (m2.get_population () == 0);
-    assert (m3.get_population () == 0);
+    hb_always_assert (m1.get_population () == 0);
+    hb_always_assert (m2.get_population () == 0);
+    hb_always_assert (m3.get_population () == 0);
   }
 
   {
@@ -157,8 +157,8 @@
     m1.set (hb_map_t (), hb_map_t {pair (1u, 2u)});
     m1.set (hb_map_t {pair (1u, 2u)}, hb_map_t {pair (2u, 3u)});
 
-    assert (m1.get (hb_map_t ()) == hb_map_t {pair (1u, 2u)});
-    assert (m1.get (hb_map_t {pair (1u, 2u)}) == hb_map_t {pair (2u, 3u)});
+    hb_always_assert (m1.get (hb_map_t ()) == hb_map_t {pair (1u, 2u)});
+    hb_always_assert (m1.get (hb_map_t {pair (1u, 2u)}) == hb_map_t {pair (2u, 3u)});
   }
 
   /* Test hashing sets. */
@@ -169,8 +169,8 @@
     m1.set (hb_set_t (), hb_set_t {1});
     m1.set (hb_set_t {1, 1000}, hb_set_t {2});
 
-    assert (m1.get (hb_set_t ()) == hb_set_t {1});
-    assert (m1.get (hb_set_t {1000, 1}) == hb_set_t {2});
+    hb_always_assert (m1.get (hb_set_t ()) == hb_set_t {1});
+    hb_always_assert (m1.get (hb_set_t {1000, 1}) == hb_set_t {2});
   }
 
   /* Test hashing vectors. */
@@ -184,8 +184,8 @@
 
     m1 << hb_pair_t<vector_t, vector_t> {vector_t {2}, vector_t ()};
 
-    assert (m1.get (vector_t ()) == vector_t {1});
-    assert (m1.get (vector_t {1}) == vector_t {2});
+    hb_always_assert (m1.get (vector_t ()) == vector_t {1});
+    hb_always_assert (m1.get (vector_t {1}) == vector_t {2});
   }
 
   /* Test moving values */
@@ -194,11 +194,11 @@
 
     hb_hashmap_t<vector_t, vector_t> m1;
     vector_t v {3};
-    assert (v.length == 1);
+    hb_always_assert (v.length == 1);
     m1 << hb_pair_t<vector_t, vector_t> {vector_t {3}, v};
-    assert (v.length == 1);
+    hb_always_assert (v.length == 1);
     m1 << hb_pair_t<vector_t, vector_t&&> {vector_t {4}, std::move (v)};
-    assert (v.length == 0);
+    hb_always_assert (v.length == 0);
     m1 << hb_pair_t<vector_t&&, vector_t> {vector_t {4}, vector_t {5}};
     m1 << hb_pair_t<vector_t&&, vector_t&&> {vector_t {4}, vector_t {5}};
 
@@ -205,9 +205,9 @@
     hb_hashmap_t<vector_t, vector_t> m2;
     vector_t v2 {3};
     m2.set (vector_t {4}, v2);
-    assert (v2.length == 1);
+    hb_always_assert (v2.length == 1);
     m2.set (vector_t {5}, std::move (v2));
-    assert (v2.length == 0);
+    hb_always_assert (v2.length == 0);
   }
 
   /* Test hb::shared_ptr. */
@@ -250,10 +250,10 @@
     hb::shared_ptr<hb_map_t> p2 {m2};
     m.set (p1,1);
 
-    assert (m.has (p2));
+    hb_always_assert (m.has (p2));
 
     m1->set (2,4);
-    assert (!m.has (p2));
+    hb_always_assert (!m.has (p2));
   }
   /* Test value type with hb_bytes_t. */
   {
@@ -262,8 +262,8 @@
     hb_bytes_t bytes (c_str);
 
     m.set (1, bytes);
-    assert (m.has (1));
-    assert (m.get (1) == hb_bytes_t {"Test"});
+    hb_always_assert (m.has (1));
+    hb_always_assert (m.get (1) == hb_bytes_t {"Test"});
   }
   /* Test operators. */
   {
@@ -275,16 +275,16 @@
     m3.set (1, 3);
     m3.set (3, 5);
 
-    assert (m1 == m2);
-    assert (m1 != m3);
-    assert (!(m2 == m3));
+    hb_always_assert (m1 == m2);
+    hb_always_assert (m1 != m3);
+    hb_always_assert (!(m2 == m3));
 
     m2 = m3;
-    assert (m2.has (1));
-    assert (!m2.has (2));
-    assert (m2.has (3));
+    hb_always_assert (m2.has (1));
+    hb_always_assert (!m2.has (2));
+    hb_always_assert (m2.has (3));
 
-    assert (m3.has (3));
+    hb_always_assert (m3.has (3));
   }
   /* Test reset. */
   {
@@ -309,15 +309,15 @@
 	 m.next (&i, &k, &v);)
     {
       pop++;
-           if (k == 1) assert (v == 1);
-      else if (k == 2) assert (v == 1);
-      else if (k == 3) assert (v == 2);
-      else if (k == 4) assert (v == 3);
-      else if (k == 5) assert (v == 5);
-      else if (k == 6) assert (v == 8);
-      else assert (false);
+           if (k == 1) hb_always_assert (v == 1);
+      else if (k == 2) hb_always_assert (v == 1);
+      else if (k == 3) hb_always_assert (v == 2);
+      else if (k == 4) hb_always_assert (v == 3);
+      else if (k == 5) hb_always_assert (v == 5);
+      else if (k == 6) hb_always_assert (v == 8);
+      else hb_always_assert (false);
     }
-    assert (pop == m.get_population ());
+    hb_always_assert (pop == m.get_population ());
   }
   /* Test update */
   {
@@ -327,9 +327,9 @@
     m2.set (1, 3);
 
     m1.update (m2);
-    assert (m1.get_population () == 2);
-    assert (m1[1] == 3);
-    assert (m1[2] == 4);
+    hb_always_assert (m1.get_population () == 2);
+    hb_always_assert (m1[1] == 3);
+    hb_always_assert (m1[2] == 4);
   }
   /* Test keys / values */
   {
@@ -347,11 +347,11 @@
     hb_copy (m.keys (), keys);
     hb_copy (m.values (), values);
 
-    assert (keys.is_equal (hb_set_t ({1, 2, 3, 4, 5, 6})));
-    assert (values.is_equal (hb_set_t ({1, 1, 2, 3, 5, 8})));
+    hb_always_assert (keys.is_equal (hb_set_t ({1, 2, 3, 4, 5, 6})));
+    hb_always_assert (values.is_equal (hb_set_t ({1, 1, 2, 3, 5, 8})));
 
-    assert (keys.is_equal (hb_set_t (m.keys ())));
-    assert (values.is_equal (hb_set_t (m.values ())));
+    hb_always_assert (keys.is_equal (hb_set_t (m.keys ())));
+    hb_always_assert (values.is_equal (hb_set_t (m.values ())));
   }
 
   return 0;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-multimap.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-multimap.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-multimap.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -30,30 +30,30 @@
 {
   hb_multimap_t m;
 
-  assert (m.get (10).length == 0);
+  hb_always_assert (m.get (10).length == 0);
 
   m.add (10, 11);
-  assert (m.get (10).length == 1);
+  hb_always_assert (m.get (10).length == 1);
 
   m.add (10, 12);
-  assert (m.get (10).length == 2);
+  hb_always_assert (m.get (10).length == 2);
 
   m.add (10, 13);
-  assert (m.get (10).length == 3);
-  assert (m.get (10)[0] == 11);
-  assert (m.get (10)[1] == 12);
-  assert (m.get (10)[2] == 13);
+  hb_always_assert (m.get (10).length == 3);
+  hb_always_assert (m.get (10)[0] == 11);
+  hb_always_assert (m.get (10)[1] == 12);
+  hb_always_assert (m.get (10)[2] == 13);
 
-  assert (m.get (11).length == 0);
+  hb_always_assert (m.get (11).length == 0);
   m.add (11, 14);
-  assert (m.get (10).length == 3);
-  assert (m.get (11).length == 1);
-  assert (m.get (12).length == 0);
-  assert (m.get (10)[0] == 11);
-  assert (m.get (10)[1] == 12);
-  assert (m.get (10)[2] == 13);
-  assert (m.get (11)[0] == 14);
-  assert (m.get (12)[0] == 0); // Array fallback value
+  hb_always_assert (m.get (10).length == 3);
+  hb_always_assert (m.get (11).length == 1);
+  hb_always_assert (m.get (12).length == 0);
+  hb_always_assert (m.get (10)[0] == 11);
+  hb_always_assert (m.get (10)[1] == 12);
+  hb_always_assert (m.get (10)[2] == 13);
+  hb_always_assert (m.get (11)[0] == 14);
+  hb_always_assert (m.get (12)[0] == 0); // Array fallback value
 
   return 0;
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-number.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-number.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-number.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -36,11 +36,11 @@
     const char *end = str + 3;
 
     int pv;
-    assert (hb_parse_int (&pp, end, &pv));
-    assert (pv == 123);
-    assert (pp - str == 3);
-    assert (end - pp == 0);
-    assert (!*end);
+    hb_always_assert (hb_parse_int (&pp, end, &pv));
+    hb_always_assert (pv == 123);
+    hb_always_assert (pp - str == 3);
+    hb_always_assert (end - pp == 0);
+    hb_always_assert (!*end);
   }
 
   {
@@ -49,11 +49,11 @@
     const char *end = str + strlen (str);
 
     unsigned int pv;
-    assert (hb_parse_uint (&pp, end, &pv));
-    assert (pv == 123);
-    assert (pp - str == 3);
-    assert (end - pp == 0);
-    assert (!*end);
+    hb_always_assert (hb_parse_uint (&pp, end, &pv));
+    hb_always_assert (pv == 123);
+    hb_always_assert (pp - str == 3);
+    hb_always_assert (end - pp == 0);
+    hb_always_assert (!*end);
   }
 
   {
@@ -62,11 +62,11 @@
     const char *end = str + 3;
 
     unsigned int pv;
-    assert (hb_parse_uint (&pp, end, &pv, true, 16));
-    assert (pv == 0x12F);
-    assert (pp - str == 3);
-    assert (end - pp == 0);
-    assert (!*end);
+    hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
+    hb_always_assert (pv == 0x12F);
+    hb_always_assert (pp - str == 3);
+    hb_always_assert (end - pp == 0);
+    hb_always_assert (!*end);
   }
 
   {
@@ -75,12 +75,12 @@
     const char *end = str + 4;
 
     unsigned int pv;
-    assert (!hb_parse_uint (&pp, end, &pv, true, 16));
-    assert (hb_parse_uint (&pp, end, &pv, false, 16));
-    assert (pv == 0x12F);
-    assert (pp - str == 3);
-    assert (end - pp == 1);
-    assert (!*end);
+    hb_always_assert (!hb_parse_uint (&pp, end, &pv, true, 16));
+    hb_always_assert (hb_parse_uint (&pp, end, &pv, false, 16));
+    hb_always_assert (pv == 0x12F);
+    hb_always_assert (pp - str == 3);
+    hb_always_assert (end - pp == 1);
+    hb_always_assert (!*end);
   }
 
   {
@@ -89,50 +89,50 @@
     const char *end = str + 4;
 
     int pv;
-    assert (hb_parse_int (&pp, end, &pv));
-    assert (pv == -123);
-    assert (pp - str == 4);
-    assert (end - pp == 0);
-    assert (!*end);
+    hb_always_assert (hb_parse_int (&pp, end, &pv));
+    hb_always_assert (pv == -123);
+    hb_always_assert (pp - str == 4);
+    hb_always_assert (end - pp == 0);
+    hb_always_assert (!*end);
   }
 
   {
     const char str[] = "123";
     const char *pp = str;
-    assert (ARRAY_LENGTH (str) == 4);
+    hb_always_assert (ARRAY_LENGTH (str) == 4);
     const char *end = str + ARRAY_LENGTH (str);
 
     unsigned int pv;
-    assert (hb_parse_uint (&pp, end, &pv));
-    assert (pv == 123);
-    assert (pp - str == 3);
-    assert (end - pp == 1);
+    hb_always_assert (hb_parse_uint (&pp, end, &pv));
+    hb_always_assert (pv == 123);
+    hb_always_assert (pp - str == 3);
+    hb_always_assert (end - pp == 1);
   }
 
   {
     const char str[] = "123\0";
     const char *pp = str;
-    assert (ARRAY_LENGTH (str) == 5);
+    hb_always_assert (ARRAY_LENGTH (str) == 5);
     const char *end = str + ARRAY_LENGTH (str);
 
     unsigned int pv;
-    assert (hb_parse_uint (&pp, end, &pv));
-    assert (pv == 123);
-    assert (pp - str == 3);
-    assert (end - pp == 2);
+    hb_always_assert (hb_parse_uint (&pp, end, &pv));
+    hb_always_assert (pv == 123);
+    hb_always_assert (pp - str == 3);
+    hb_always_assert (end - pp == 2);
   }
 
   {
     const char str[] = "123V";
     const char *pp = str;
-    assert (ARRAY_LENGTH (str) == 5);
+    hb_always_assert (ARRAY_LENGTH (str) == 5);
     const char *end = str + ARRAY_LENGTH (str);
 
     unsigned int pv;
-    assert (hb_parse_uint (&pp, end, &pv));
-    assert (pv == 123);
-    assert (pp - str == 3);
-    assert (end - pp == 2);
+    hb_always_assert (hb_parse_uint (&pp, end, &pv));
+    hb_always_assert (pv == 123);
+    hb_always_assert (pp - str == 3);
+    hb_always_assert (end - pp == 2);
   }
 
   {
@@ -141,10 +141,10 @@
     const char *end = str + ARRAY_LENGTH (str);
 
     double pv;
-    assert (hb_parse_double (&pp, end, &pv));
-    assert ((int) roundf (pv * 1000.) == 123);
-    assert (pp - str == 4);
-    assert (end - pp == 1);
+    hb_always_assert (hb_parse_double (&pp, end, &pv));
+    hb_always_assert ((int) roundf (pv * 1000.) == 123);
+    hb_always_assert (pp - str == 4);
+    hb_always_assert (end - pp == 1);
   }
 
   {
@@ -153,10 +153,10 @@
     const char *end = str + ARRAY_LENGTH (str) - 1;
 
     double pv;
-    assert (hb_parse_double (&pp, end, &pv));
-    assert ((int) roundf (pv * 1000.) == 123);
-    assert (pp - str == 5);
-    assert (end - pp == 0);
+    hb_always_assert (hb_parse_double (&pp, end, &pv));
+    hb_always_assert ((int) roundf (pv * 1000.) == 123);
+    hb_always_assert (pp - str == 5);
+    hb_always_assert (end - pp == 0);
   }
 
   {
@@ -165,10 +165,10 @@
     const char *end = str + ARRAY_LENGTH (str) - 1;
 
     double pv;
-    assert (hb_parse_double (&pp, end, &pv));
-    assert ((int) roundf (pv * 1000.) == 123);
-    assert (pp - str == 7);
-    assert (end - pp == 0);
+    hb_always_assert (hb_parse_double (&pp, end, &pv));
+    hb_always_assert ((int) roundf (pv * 1000.) == 123);
+    hb_always_assert (pp - str == 7);
+    hb_always_assert (end - pp == 0);
   }
 
   {
@@ -177,10 +177,10 @@
     const char *end = str + ARRAY_LENGTH (str) - 1;
 
     double pv;
-    assert (hb_parse_double (&pp, end, &pv));
-    assert ((int) roundf (pv * 1000.) == 123);
-    assert (pp - str == 6);
-    assert (end - pp == 0);
+    hb_always_assert (hb_parse_double (&pp, end, &pv));
+    hb_always_assert ((int) roundf (pv * 1000.) == 123);
+    hb_always_assert (pp - str == 6);
+    hb_always_assert (end - pp == 0);
   }
 
   {
@@ -189,10 +189,10 @@
     const char *end = str + ARRAY_LENGTH (str) - 1;
 
     double pv;
-    assert (hb_parse_double (&pp, end, &pv));
-    assert ((int) roundf (pv * 1000.) == 123);
-    assert (pp - str == 10);
-    assert (end - pp == 0);
+    hb_always_assert (hb_parse_double (&pp, end, &pv));
+    hb_always_assert ((int) roundf (pv * 1000.) == 123);
+    hb_always_assert (pp - str == 10);
+    hb_always_assert (end - pp == 0);
   }
 
   {
@@ -201,10 +201,10 @@
     const char *end = str + ARRAY_LENGTH (str) - 1;
 
     double pv;
-    assert (hb_parse_double (&pp, end, &pv));
-    assert ((int) roundf (pv * 1000.) == -123);
-    assert (pp - str == 13);
-    assert (end - pp == 0);
+    hb_always_assert (hb_parse_double (&pp, end, &pv));
+    hb_always_assert ((int) roundf (pv * 1000.) == -123);
+    hb_always_assert (pp - str == 13);
+    hb_always_assert (end - pp == 0);
 
   }
 
@@ -214,10 +214,10 @@
     const char *end = str + ARRAY_LENGTH (str) - 1;
 
     double pv;
-    assert (hb_parse_double (&pp, end, &pv));
-    assert ((int) roundf (pv * 1000.) == -123);
-    assert (pp - str == 8);
-    assert (end - pp == 0);
+    hb_always_assert (hb_parse_double (&pp, end, &pv));
+    hb_always_assert ((int) roundf (pv * 1000.) == -123);
+    hb_always_assert (pp - str == 8);
+    hb_always_assert (end - pp == 0);
   }
 
   return 0;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-glyphname.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-glyphname.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-glyphname.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -40,7 +40,7 @@
   }
 
   hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
-  assert (blob);
+  hb_always_assert (blob);
   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
   hb_font_t *font = hb_font_create (face);
   hb_blob_destroy (blob);

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-meta.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-meta.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-meta.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -38,7 +38,7 @@
   }
 
   hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
-  assert (blob);
+  hb_always_assert (blob);
   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
   hb_blob_destroy (blob);
   blob = nullptr;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-name.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-name.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-name.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -40,7 +40,7 @@
   }
 
   hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
-  assert (blob);
+  hb_always_assert (blob);
   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
   hb_blob_destroy (blob);
   blob = nullptr;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -31,23 +31,23 @@
 test_insert ()
 {
   hb_priority_queue_t<int64_t> queue;
-  assert (queue.is_empty ());
+  hb_always_assert (queue.is_empty ());
 
   queue.insert (10, 0);
-  assert (!queue.is_empty ());
-  assert (queue.minimum () == hb_pair (10, 0));
+  hb_always_assert (!queue.is_empty ());
+  hb_always_assert (queue.minimum () == hb_pair (10, 0));
 
   queue.insert (20, 1);
-  assert (queue.minimum () == hb_pair (10, 0));
+  hb_always_assert (queue.minimum () == hb_pair (10, 0));
 
   queue.insert (5, 2);
-  assert (queue.minimum () == hb_pair (5, 2));
+  hb_always_assert (queue.minimum () == hb_pair (5, 2));
 
   queue.insert (15, 3);
-  assert (queue.minimum () == hb_pair (5, 2));
+  hb_always_assert (queue.minimum () == hb_pair (5, 2));
 
   queue.insert (1, 4);
-  assert (queue.minimum () == hb_pair (1, 4));
+  hb_always_assert (queue.minimum () == hb_pair (1, 4));
 }
 
 static void
@@ -65,12 +65,12 @@
 
   for (int i = 0; i < 8; i++)
   {
-    assert (!queue.is_empty ());
-    assert (queue.minimum () == hb_pair (i * 10, i));
-    assert (queue.pop_minimum () == hb_pair (i * 10, i));
+    hb_always_assert (!queue.is_empty ());
+    hb_always_assert (queue.minimum () == hb_pair (i * 10, i));
+    hb_always_assert (queue.pop_minimum () == hb_pair (i * 10, i));
   }
 
-  assert (queue.is_empty ());
+  hb_always_assert (queue.is_empty ());
 }
 
 int

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -488,7 +488,7 @@
   {
     if (check_binary_equivalence) {
       printf("when binary equivalence checking is enabled, the expected graph cannot overflow.");
-      assert(!check_binary_equivalence);
+      hb_always_assert(!check_binary_equivalence);
     }
     expected_graph.assign_spaces ();
     expected_graph.sort_shortest_distance ();
@@ -495,8 +495,8 @@
   }
 
   // Check that overflow resolution succeeds
-  assert (overflowing.offset_overflow ());
-  assert (hb_resolve_graph_overflows (tag,
+  hb_always_assert (overflowing.offset_overflow ());
+  hb_always_assert (hb_resolve_graph_overflows (tag,
                                       num_iterations,
                                       recalculate_extensions,
                                       graph));
@@ -503,9 +503,9 @@
 
   // Check the graphs can be serialized.
   hb_blob_t* out1 = graph::serialize (graph);
-  assert (out1);
+  hb_always_assert (out1);
   hb_blob_t* out2 = graph::serialize (expected_graph);
-  assert (out2);
+  hb_always_assert (out2);
   if (check_binary_equivalence) {
     unsigned l1, l2;
     const char* d1 = hb_blob_get_data(out1, &l1);
@@ -517,7 +517,7 @@
       graph.print();
       printf("## Expected:\n");
       expected_graph.print();
-      assert(match);
+      hb_always_assert(match);
     }
   }
 
@@ -533,7 +533,7 @@
     printf("## Result:\n");
     graph.print();
   }
-  assert (graph == expected_graph);
+  hb_always_assert (graph == expected_graph);
 }
 
 static void add_virtual_offset (unsigned id,
@@ -888,7 +888,7 @@
   unsigned obj_d = c->pop_pack(false);
 
   add_offset(obj_d, c);
-  assert(c->last_added_child_index() == obj_d);
+  hb_always_assert(c->last_added_child_index() == obj_d);
 
   if (!with_overflow) {
     obj_e_1 = add_object("a", 1, c);
@@ -1804,27 +1804,27 @@
 
   graph_t graph (c.object_graph ());
   graph.sort_shortest_distance ();
-  assert (!graph.in_error ());
+  hb_always_assert (!graph.in_error ());
 
-  assert(strncmp (graph.object (4).head, "abc", 3) == 0);
-  assert(graph.object (4).real_links.length == 3);
-  assert(graph.object (4).real_links[0].objidx == 2);
-  assert(graph.object (4).real_links[1].objidx == 0);
-  assert(graph.object (4).real_links[2].objidx == 3);
+  hb_always_assert(strncmp (graph.object (4).head, "abc", 3) == 0);
+  hb_always_assert(graph.object (4).real_links.length == 3);
+  hb_always_assert(graph.object (4).real_links[0].objidx == 2);
+  hb_always_assert(graph.object (4).real_links[1].objidx == 0);
+  hb_always_assert(graph.object (4).real_links[2].objidx == 3);
 
-  assert(strncmp (graph.object (3).head, "mn", 2) == 0);
-  assert(graph.object (3).real_links.length == 0);
+  hb_always_assert(strncmp (graph.object (3).head, "mn", 2) == 0);
+  hb_always_assert(graph.object (3).real_links.length == 0);
 
-  assert(strncmp (graph.object (2).head, "def", 3) == 0);
-  assert(graph.object (2).real_links.length == 1);
-  assert(graph.object (2).real_links[0].objidx == 1);
+  hb_always_assert(strncmp (graph.object (2).head, "def", 3) == 0);
+  hb_always_assert(graph.object (2).real_links.length == 1);
+  hb_always_assert(graph.object (2).real_links[0].objidx == 1);
 
-  assert(strncmp (graph.object (1).head, "ghi", 3) == 0);
-  assert(graph.object (1).real_links.length == 1);
-  assert(graph.object (1).real_links[0].objidx == 0);
+  hb_always_assert(strncmp (graph.object (1).head, "ghi", 3) == 0);
+  hb_always_assert(graph.object (1).real_links.length == 1);
+  hb_always_assert(graph.object (1).real_links[0].objidx == 0);
 
-  assert(strncmp (graph.object (0).head, "jkl", 3) == 0);
-  assert(graph.object (0).real_links.length == 0);
+  hb_always_assert(strncmp (graph.object (0).head, "jkl", 3) == 0);
+  hb_always_assert(graph.object (0).real_links.length == 0);
 
   free (buffer);
 }
@@ -1839,28 +1839,28 @@
   graph_t graph (c.object_graph ());
   graph.duplicate (4, 1);
 
-  assert(strncmp (graph.object (5).head, "abc", 3) == 0);
-  assert(graph.object (5).real_links.length == 3);
-  assert(graph.object (5).real_links[0].objidx == 3);
-  assert(graph.object (5).real_links[1].objidx == 4);
-  assert(graph.object (5).real_links[2].objidx == 0);
+  hb_always_assert(strncmp (graph.object (5).head, "abc", 3) == 0);
+  hb_always_assert(graph.object (5).real_links.length == 3);
+  hb_always_assert(graph.object (5).real_links[0].objidx == 3);
+  hb_always_assert(graph.object (5).real_links[1].objidx == 4);
+  hb_always_assert(graph.object (5).real_links[2].objidx == 0);
 
-  assert(strncmp (graph.object (4).head, "jkl", 3) == 0);
-  assert(graph.object (4).real_links.length == 0);
+  hb_always_assert(strncmp (graph.object (4).head, "jkl", 3) == 0);
+  hb_always_assert(graph.object (4).real_links.length == 0);
 
-  assert(strncmp (graph.object (3).head, "def", 3) == 0);
-  assert(graph.object (3).real_links.length == 1);
-  assert(graph.object (3).real_links[0].objidx == 2);
+  hb_always_assert(strncmp (graph.object (3).head, "def", 3) == 0);
+  hb_always_assert(graph.object (3).real_links.length == 1);
+  hb_always_assert(graph.object (3).real_links[0].objidx == 2);
 
-  assert(strncmp (graph.object (2).head, "ghi", 3) == 0);
-  assert(graph.object (2).real_links.length == 1);
-  assert(graph.object (2).real_links[0].objidx == 1);
+  hb_always_assert(strncmp (graph.object (2).head, "ghi", 3) == 0);
+  hb_always_assert(graph.object (2).real_links.length == 1);
+  hb_always_assert(graph.object (2).real_links[0].objidx == 1);
 
-  assert(strncmp (graph.object (1).head, "jkl", 3) == 0);
-  assert(graph.object (1).real_links.length == 0);
+  hb_always_assert(strncmp (graph.object (1).head, "jkl", 3) == 0);
+  hb_always_assert(graph.object (1).real_links.length == 0);
 
-  assert(strncmp (graph.object (0).head, "mn", 2) == 0);
-  assert(graph.object (0).real_links.length == 0);
+  hb_always_assert(strncmp (graph.object (0).head, "mn", 2) == 0);
+  hb_always_assert(graph.object (0).real_links.length == 0);
 
   free (buffer);
 }
@@ -1875,33 +1875,33 @@
   graph_t graph (c.object_graph ());
   graph.duplicate (3, 2);
 
-  assert(strncmp (graph.object (6).head, "abc", 3) == 0);
-  assert(graph.object (6).real_links.length == 3);
-  assert(graph.object (6).real_links[0].objidx == 4);
-  assert(graph.object (6).real_links[1].objidx == 2);
-  assert(graph.object (6).real_links[2].objidx == 1);
+  hb_always_assert(strncmp (graph.object (6).head, "abc", 3) == 0);
+  hb_always_assert(graph.object (6).real_links.length == 3);
+  hb_always_assert(graph.object (6).real_links[0].objidx == 4);
+  hb_always_assert(graph.object (6).real_links[1].objidx == 2);
+  hb_always_assert(graph.object (6).real_links[2].objidx == 1);
 
-  assert(strncmp (graph.object (5).head, "jkl", 3) == 0);
-  assert(graph.object (5).real_links.length == 1);
-  assert(graph.object (5).real_links[0].objidx == 0);
+  hb_always_assert(strncmp (graph.object (5).head, "jkl", 3) == 0);
+  hb_always_assert(graph.object (5).real_links.length == 1);
+  hb_always_assert(graph.object (5).real_links[0].objidx == 0);
 
-  assert(strncmp (graph.object (4).head, "def", 3) == 0);
-  assert(graph.object (4).real_links.length == 1);
-  assert(graph.object (4).real_links[0].objidx == 3);
+  hb_always_assert(strncmp (graph.object (4).head, "def", 3) == 0);
+  hb_always_assert(graph.object (4).real_links.length == 1);
+  hb_always_assert(graph.object (4).real_links[0].objidx == 3);
 
-  assert(strncmp (graph.object (3).head, "ghi", 3) == 0);
-  assert(graph.object (3).real_links.length == 1);
-  assert(graph.object (3).real_links[0].objidx == 5);
+  hb_always_assert(strncmp (graph.object (3).head, "ghi", 3) == 0);
+  hb_always_assert(graph.object (3).real_links.length == 1);
+  hb_always_assert(graph.object (3).real_links[0].objidx == 5);
 
-  assert(strncmp (graph.object (2).head, "jkl", 3) == 0);
-  assert(graph.object (2).real_links.length == 1);
-  assert(graph.object (2).real_links[0].objidx == 0);
+  hb_always_assert(strncmp (graph.object (2).head, "jkl", 3) == 0);
+  hb_always_assert(graph.object (2).real_links.length == 1);
+  hb_always_assert(graph.object (2).real_links[0].objidx == 0);
 
-  assert(strncmp (graph.object (1).head, "mn", 2) == 0);
-  assert(graph.object (1).real_links.length == 0);
+  hb_always_assert(strncmp (graph.object (1).head, "mn", 2) == 0);
+  hb_always_assert(graph.object (1).real_links.length == 0);
 
-  assert(strncmp (graph.object (0).head, "opqrst", 6) == 0);
-  assert(graph.object (0).real_links.length == 0);
+  hb_always_assert(strncmp (graph.object (0).head, "opqrst", 6) == 0);
+  hb_always_assert(graph.object (0).real_links.length == 0);
 
   free (buffer);
 }
@@ -1920,7 +1920,7 @@
   free (buffer_1);
 
   hb_bytes_t actual = out->as_bytes ();
-  assert (actual == expected);
+  hb_always_assert (actual == expected);
   expected.fini ();
   hb_blob_destroy (out);
 }
@@ -1933,7 +1933,7 @@
   populate_serializer_complex_2 (&c);
   graph_t graph (c.object_graph ());
 
-  assert (!graph::will_overflow (graph, nullptr));
+  hb_always_assert (!graph::will_overflow (graph, nullptr));
 
   free (buffer);
 }
@@ -1946,7 +1946,7 @@
   populate_serializer_with_overflow (&c);
   graph_t graph (c.object_graph ());
 
-  assert (graph::will_overflow (graph, nullptr));
+  hb_always_assert (graph::will_overflow (graph, nullptr));
 
   free (buffer);
 }
@@ -1959,7 +1959,7 @@
   populate_serializer_with_dedup_overflow (&c);
   graph_t graph (c.object_graph ());
 
-  assert (graph::will_overflow (graph, nullptr));
+  hb_always_assert (graph::will_overflow (graph, nullptr));
 
   free (buffer);
 }
@@ -1973,9 +1973,9 @@
   graph_t graph (c.object_graph ());
 
   hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE);
-  assert (out);
+  hb_always_assert (out);
   hb_bytes_t result = out->as_bytes ();
-  assert (result.length == (80000 + 3 + 3 * 2));
+  hb_always_assert (result.length == (80000 + 3 + 3 * 2));
 
   free (buffer);
   hb_blob_destroy (out);
@@ -1990,9 +1990,9 @@
   graph_t graph (c.object_graph ());
 
   hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE);
-  assert (out);
+  hb_always_assert (out);
   hb_bytes_t result = out->as_bytes ();
-  assert (result.length == (10000 + 2 * 2 + 60000 + 2 + 3 * 2));
+  hb_always_assert (result.length == (10000 + 2 * 2 + 60000 + 2 + 3 * 2));
 
   free (buffer);
   hb_blob_destroy (out);
@@ -2007,7 +2007,7 @@
   graph_t graph (c.object_graph ());
 
   hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE, 5);
-  assert (out);
+  hb_always_assert (out);
 
   free (buffer);
   hb_blob_destroy (out);
@@ -2040,11 +2040,11 @@
   populate_serializer_with_isolation_overflow (&c);
   graph_t graph (c.object_graph ());
 
-  assert (c.offset_overflow ());
+  hb_always_assert (c.offset_overflow ());
   hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0);
-  assert (out);
+  hb_always_assert (out);
   hb_bytes_t result = out->as_bytes ();
-  assert (result.length == (1 + 10000 + 60000 + 1 + 1
+  hb_always_assert (result.length == (1 + 10000 + 60000 + 1 + 1
                             + 4 + 3 * 2));
 
   free (buffer);
@@ -2115,14 +2115,14 @@
   populate_serializer_with_isolation_overflow_spaces (&c);
   graph_t graph (c.object_graph ());
 
-  assert (c.offset_overflow ());
+  hb_always_assert (c.offset_overflow ());
   hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0);
-  assert (out);
+  hb_always_assert (out);
   hb_bytes_t result = out->as_bytes ();
 
   unsigned expected_length = 3 + 2 * 60000; // objects
   expected_length += 2 * 4 + 2 * 2; // links
-  assert (result.length == expected_length);
+  hb_always_assert (result.length == expected_length);
 
   free (buffer);
   hb_blob_destroy (out);
@@ -2136,9 +2136,9 @@
   populate_serializer_with_24_and_32_bit_offsets (&c);
   graph_t graph (c.object_graph ());
 
-  assert (c.offset_overflow ());
+  hb_always_assert (c.offset_overflow ());
   hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0);
-  assert (out);
+  hb_always_assert (out);
   hb_bytes_t result = out->as_bytes ();
 
   unsigned expected_length =
@@ -2152,7 +2152,7 @@
       4 * 3 +  // 24
       4 * 2;   // 16
 
-  assert (result.length == expected_length);
+  hb_always_assert (result.length == expected_length);
 
   free (buffer);
   hb_blob_destroy (out);
@@ -2162,12 +2162,12 @@
 {
   size_t buffer_size = 200000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_extension_promotion (&c);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_extension_promotion (&e, 3);
 
@@ -2184,12 +2184,12 @@
 {
   size_t buffer_size = 200000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_extension_promotion (&c, 0, true);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_extension_promotion (&e, 3, true);
 
@@ -2206,12 +2206,12 @@
 {
   size_t buffer_size = 200000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_large_pair_pos_1 <1, 4>(&c);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_large_pair_pos_1 <2, 2>(&e, true);
 
@@ -2229,12 +2229,12 @@
 {
   size_t buffer_size = 200000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_large_pair_pos_1 <1, 4>(&c, true);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_large_pair_pos_1 <2, 2>(&e, true);
 
@@ -2252,12 +2252,12 @@
 {
   size_t buffer_size = 300000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_large_pair_pos_2 <1, 4, 3000>(&c);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_large_pair_pos_2 <2, 2, 3000>(&e, true);
 
@@ -2275,12 +2275,12 @@
 {
   size_t buffer_size = 300000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_large_pair_pos_2 <1, 1636, 10>(&c, true, false, false);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_large_pair_pos_2 <2, 818, 10>(&e, true, false, false);
 
@@ -2298,12 +2298,12 @@
 {
   size_t buffer_size = 300000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_large_pair_pos_2 <1, 4, 2000>(&c, false, true);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_large_pair_pos_2 <2, 2, 2000>(&e, true, true);
 
@@ -2321,12 +2321,12 @@
 {
   size_t buffer_size = 200000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_large_mark_base_pos_1 <40, 10, 110, 1>(&c);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_large_mark_base_pos_1 <40, 10, 110, 2>(&e);
 
@@ -2344,12 +2344,12 @@
 {
   size_t buffer_size = 200000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_large_liga<1, 1, 2, 40000>(&c, false);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_large_liga<2, 1, 1, 40000>(&e, false);
 
@@ -2367,12 +2367,12 @@
 {
   size_t buffer_size = 400000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_large_liga<1, 6, 2, 16000>(&c, true);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_large_liga<3, 2, 2, 16000>(&e, true);
 
@@ -2390,12 +2390,12 @@
 {
   size_t buffer_size = 400000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_large_liga<1, 2, 3, 30000>(&c, true);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_large_liga_overlapping_clone_result(&e);
 
@@ -2477,15 +2477,15 @@
   populate_serializer_virtual_link (&c);
 
   hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE);
-  assert (out);
+  hb_always_assert (out);
 
   hb_bytes_t result = out->as_bytes ();
-  assert (result.length == 5 + 4 * 2);
-  assert (result[0]  == 'a');
-  assert (result[5]  == 'c');
-  assert (result[8]  == 'e');
-  assert (result[9]  == 'b');
-  assert (result[12] == 'd');
+  hb_always_assert (result.length == 5 + 4 * 2);
+  hb_always_assert (result[0]  == 'a');
+  hb_always_assert (result[5]  == 'c');
+  hb_always_assert (result[8]  == 'e');
+  hb_always_assert (result[9]  == 'b');
+  hb_always_assert (result[12] == 'd');
 
   free (buffer);
   hb_blob_destroy (out);
@@ -2511,7 +2511,7 @@
   add_virtual_offset (obj_c, &c);
   unsigned obj_d_2 = c.pop_pack ();
 
-  assert (obj_d_1 == obj_d_2);
+  hb_always_assert (obj_d_1 == obj_d_2);
 
   start_object ("a", 1, &c);
   add_offset (obj_b, &c);
@@ -2521,9 +2521,9 @@
   c.pop_pack ();
   c.end_serialize ();
 
-  assert(c.object_graph() [obj_d_1]->virtual_links.length == 2);
-  assert(c.object_graph() [obj_d_1]->virtual_links[0].objidx == obj_b);
-  assert(c.object_graph() [obj_d_1]->virtual_links[1].objidx == obj_c);
+  hb_always_assert(c.object_graph() [obj_d_1]->virtual_links.length == 2);
+  hb_always_assert(c.object_graph() [obj_d_1]->virtual_links[0].objidx == obj_b);
+  hb_always_assert(c.object_graph() [obj_d_1]->virtual_links[1].objidx == obj_c);
   free(buffer);
 }
 
@@ -2532,12 +2532,12 @@
 {
   size_t buffer_size = 200000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_with_repack_last (&c, true);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_with_repack_last (&e, false);
 
@@ -2558,12 +2558,12 @@
 {
   size_t buffer_size = 200000;
   void* buffer = malloc (buffer_size);
-  assert (buffer);
+  hb_always_assert (buffer);
   hb_serialize_context_t c (buffer, buffer_size);
   populate_serializer_virtual (&c, true);
 
   void* expected_buffer = malloc (buffer_size);
-  assert (expected_buffer);
+  hb_always_assert (expected_buffer);
   hb_serialize_context_t e (expected_buffer, buffer_size);
   populate_serializer_virtual (&e, false);
 

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-serialize.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-serialize.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-serialize.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -45,7 +45,7 @@
   s.end_serialize ();
 
   hb_bytes_t bytes = s.copy_bytes ();
-  assert (bytes.length == 10);
+  hb_always_assert (bytes.length == 10);
   bytes.fini ();
 
   return 0;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -33,9 +33,9 @@
   {
     hb_set_t v1 {1, 2};
     hb_set_t v2 {v1};
-    assert (v1.get_population () == 2);
-    assert (hb_len (hb_iter (v1)) == 2);
-    assert (v2.get_population () == 2);
+    hb_always_assert (v1.get_population () == 2);
+    hb_always_assert (hb_len (hb_iter (v1)) == 2);
+    hb_always_assert (v2.get_population () == 2);
   }
 
   /* Test copy assignment. */
@@ -43,8 +43,8 @@
     hb_set_t v1 {1, 2};
     hb_set_t v2;
     v2 = v1;
-    assert (v1.get_population () == 2);
-    assert (v2.get_population () == 2);
+    hb_always_assert (v1.get_population () == 2);
+    hb_always_assert (v2.get_population () == 2);
   }
 
   /* Test move constructor. */
@@ -51,9 +51,9 @@
   {
     hb_set_t s {1, 2};
     hb_set_t v (std::move (s));
-    assert (s.get_population () == 0);
-    assert (hb_len (hb_iter (s)) == 0);
-    assert (v.get_population () == 2);
+    hb_always_assert (s.get_population () == 0);
+    hb_always_assert (hb_len (hb_iter (s)) == 0);
+    hb_always_assert (v.get_population () == 2);
   }
 
   /* Test move assignment. */
@@ -61,8 +61,8 @@
     hb_set_t s = hb_set_t {1, 2};
     hb_set_t v;
     v = std::move (s);
-    assert (s.get_population () == 0);
-    assert (v.get_population () == 2);
+    hb_always_assert (s.get_population () == 0);
+    hb_always_assert (v.get_population () == 2);
   }
 
   /* Test initializing from iterable. */
@@ -77,10 +77,10 @@
     hb_set_t v1 (s);
     hb_set_t v2 (std::move (s));
 
-    assert (s.get_population () == 0);
-    assert (v0.get_population () == 2);
-    assert (v1.get_population () == 2);
-    assert (v2.get_population () == 2);
+    hb_always_assert (s.get_population () == 0);
+    hb_always_assert (v0.get_population () == 2);
+    hb_always_assert (v1.get_population () == 2);
+    hb_always_assert (v2.get_population () == 2);
   }
 
   /* Test initializing from iterator. */
@@ -95,7 +95,7 @@
 
     hb_set_t v (hb_iter (s));
 
-    assert (v.get_population () == 5);
+    hb_always_assert (v.get_population () == 5);
   }
 
   /* Test initializing from initializer list and swapping. */
@@ -103,8 +103,8 @@
     hb_set_t v1 {1, 2, 3};
     hb_set_t v2 {4, 5};
     hb_swap (v1, v2);
-    assert (v1.get_population () == 2);
-    assert (v2.get_population () == 3);
+    hb_always_assert (v1.get_population () == 2);
+    hb_always_assert (v2.get_population () == 3);
   }
 
   /* Test inverted sets. */
@@ -114,27 +114,27 @@
     s.del (5);
 
     hb_codepoint_t start = HB_SET_VALUE_INVALID, last = HB_SET_VALUE_INVALID;
-    assert (s.next_range (&start, &last));
-    assert (start == 0);
-    assert (last == 4);
-    assert (s.next_range (&start, &last));
-    assert (start == 6);
-    assert (last == HB_SET_VALUE_INVALID - 1);
-    assert (!s.next_range (&start, &last));
+    hb_always_assert (s.next_range (&start, &last));
+    hb_always_assert (start == 0);
+    hb_always_assert (last == 4);
+    hb_always_assert (s.next_range (&start, &last));
+    hb_always_assert (start == 6);
+    hb_always_assert (last == HB_SET_VALUE_INVALID - 1);
+    hb_always_assert (!s.next_range (&start, &last));
 
     start = HB_SET_VALUE_INVALID;
     last = HB_SET_VALUE_INVALID;
-    assert (s.previous_range (&start, &last));
-    assert (start == 6);
-    assert (last == HB_SET_VALUE_INVALID - 1);
-    assert (s.previous_range (&start, &last));
-    assert (start == 0);
-    assert (last == 4);
-    assert (!s.previous_range (&start, &last));
+    hb_always_assert (s.previous_range (&start, &last));
+    hb_always_assert (start == 6);
+    hb_always_assert (last == HB_SET_VALUE_INVALID - 1);
+    hb_always_assert (s.previous_range (&start, &last));
+    hb_always_assert (start == 0);
+    hb_always_assert (last == 4);
+    hb_always_assert (!s.previous_range (&start, &last));
 
-    assert (s.is_inverted ());
+    hb_always_assert (s.is_inverted ());
     /* Inverted set returns true for invalid value; oh well. */
-    assert (s.has (HB_SET_VALUE_INVALID));
+    hb_always_assert (s.has (HB_SET_VALUE_INVALID));
   }
 
   /* Adding HB_SET_VALUE_INVALID */
@@ -142,23 +142,23 @@
     hb_set_t s;
 
     s.add(HB_SET_VALUE_INVALID);
-    assert(!s.has(HB_SET_VALUE_INVALID));
+    hb_always_assert(!s.has(HB_SET_VALUE_INVALID));
 
     s.clear();
-    assert(!s.add_range(HB_SET_VALUE_INVALID - 2, HB_SET_VALUE_INVALID));
-    assert(!s.has(HB_SET_VALUE_INVALID));
+    hb_always_assert(!s.add_range(HB_SET_VALUE_INVALID - 2, HB_SET_VALUE_INVALID));
+    hb_always_assert(!s.has(HB_SET_VALUE_INVALID));
 
     hb_codepoint_t array[] = {(unsigned) HB_SET_VALUE_INVALID, 0, 2};
     s.clear();
     s.add_array(array, 3);
-    assert(!s.has(HB_SET_VALUE_INVALID));
-    assert(s.has(2));
+    hb_always_assert(!s.has(HB_SET_VALUE_INVALID));
+    hb_always_assert(s.has(2));
 
     hb_codepoint_t sorted_array[] = {0, 2, (unsigned) HB_SET_VALUE_INVALID};
     s.clear();
     s.add_sorted_array(sorted_array, 3);
-    assert(!s.has(HB_SET_VALUE_INVALID));
-    assert(s.has(2));
+    hb_always_assert(!s.has(HB_SET_VALUE_INVALID));
+    hb_always_assert(s.has(2));
   }
 
   return 0;

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -49,7 +49,7 @@
     Triple tent (0.0, 1.0, 1.0);
     Triple axis_range (0.0, 0.0, 0.0);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 0);
+    hb_always_assert (out.length == 0);
   }
 
   {
@@ -57,9 +57,9 @@
     Triple tent (0.0, 1.0, 1.0);
     Triple axis_range (0.5, 0.5, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 0.5);
-    assert (out[0].second == Triple ());
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 0.5);
+    hb_always_assert (out[0].second == Triple ());
   }
 
   {
@@ -67,7 +67,7 @@
     Triple tent (0.3, 0.5, 0.8);
     Triple axis_range (0.1, 0.2, 0.3);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 0);
+    hb_always_assert (out.length == 0);
   }
 
   /* Case 2 */
@@ -75,9 +75,9 @@
     Triple tent (0.0, 1.0, 1.0);
     Triple axis_range (-1.0, 0.0, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 0.5);
-    assert (out[0].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 0.5);
+    hb_always_assert (out[0].second == Triple (0.0, 1.0, 1.0));
   }
 
   /* Case 2 */
@@ -85,9 +85,9 @@
     Triple tent (0.0, 1.0, 1.0);
     Triple axis_range (-1.0, 0.0, 0.75);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 0.75);
-    assert (out[0].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 0.75);
+    hb_always_assert (out[0].second == Triple (0.0, 1.0, 1.0));
   }
 
   /* Without gain: */
@@ -96,11 +96,11 @@
     Triple tent (0.0, 0.2, 1.0);
     Triple axis_range (-1.0, 0.0, 0.8);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 2);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (0.0, 0.25, 1.0));
-    assert (approx (out[1].first, 0.250));
-    assert (out[1].second == Triple (0.25, 1.0, 1.0));
+    hb_always_assert (out.length == 2);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (0.0, 0.25, 1.0));
+    hb_always_assert (approx (out[1].first, 0.250));
+    hb_always_assert (out[1].second == Triple (0.25, 1.0, 1.0));
   }
 
   /* Case 3 boundary */
@@ -108,11 +108,11 @@
     Triple tent (0.0, 0.4, 1.0);
     Triple axis_range (-1.0, 0.0, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 2);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (0.0, 0.8, 1.0));
-    assert (approx (out[1].first, 2.5/3));
-    assert (out[1].second == Triple (0.8, 1.0, 1.0));
+    hb_always_assert (out.length == 2);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (0.0, 0.8, 1.0));
+    hb_always_assert (approx (out[1].first, 2.5/3));
+    hb_always_assert (out[1].second == Triple (0.8, 1.0, 1.0));
   }
 
   /* Case 4 */
@@ -120,11 +120,11 @@
     Triple tent (0.0, 0.25, 1.0);
     Triple axis_range (-1.0, 0.0, 0.4);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 2);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (0.0, 0.625, 1.0));
-    assert (approx (out[1].first, 0.80));
-    assert (out[1].second == Triple (0.625, 1.0, 1.0));
+    hb_always_assert (out.length == 2);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (0.0, 0.625, 1.0));
+    hb_always_assert (approx (out[1].first, 0.80));
+    hb_always_assert (out[1].second == Triple (0.625, 1.0, 1.0));
   }
 
   /* Case 4 */
@@ -132,11 +132,11 @@
     Triple tent (0.25, 0.3, 1.05);
     Triple axis_range (0.0, 0.2, 0.4);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 2);
-    assert (out[0].first == 1.0);
-    assert (approx (out[0].second, Triple (0.25, 0.5, 1.0)));
-    assert (approx (out[1].first, 2.6 / 3));
-    assert (approx (out[1].second, Triple (0.5, 1.0, 1.0)));
+    hb_always_assert (out.length == 2);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (approx (out[0].second, Triple (0.25, 0.5, 1.0)));
+    hb_always_assert (approx (out[1].first, 2.6 / 3));
+    hb_always_assert (approx (out[1].second, Triple (0.5, 1.0, 1.0)));
   }
 
   /* Case 4 boundary */
@@ -144,9 +144,9 @@
     Triple tent (0.25, 0.5, 1.0);
     Triple axis_range (0.0, 0.25, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (0.0, 1.0, 1.0));
   }
 
   /* With gain */
@@ -155,13 +155,13 @@
     Triple tent (0.0, 0.5, 1.0);
     Triple axis_range (0.0, 0.5, 1.0);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 3);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == -1.0);
-    assert (out[1].second == Triple (0.0, 1.0, 1.0));
-    assert (out[2].first == -1.0);
-    assert (out[2].second == Triple (-1.0, -1.0, 0.0));
+    hb_always_assert (out.length == 3);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == -1.0);
+    hb_always_assert (out[1].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (out[2].first == -1.0);
+    hb_always_assert (out[2].second == Triple (-1.0, -1.0, 0.0));
   }
 
   {
@@ -168,13 +168,13 @@
     Triple tent (0.0, 0.5, 1.0);
     Triple axis_range (0.0, 0.5, 0.75);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 3);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == -0.5);
-    assert (out[1].second == Triple (0.0, 1.0, 1.0));
-    assert (out[2].first == -1.0);
-    assert (out[2].second == Triple (-1.0, -1.0, 0.0));
+    hb_always_assert (out.length == 3);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == -0.5);
+    hb_always_assert (out[1].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (out[2].first == -1.0);
+    hb_always_assert (out[2].second == Triple (-1.0, -1.0, 0.0));
   }
 
   {
@@ -181,15 +181,15 @@
     Triple tent (0.0, 0.50, 1.0);
     Triple axis_range (0.0, 0.25, 0.8);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 4);
-    assert (out[0].first == 0.5);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == 0.5);
-    assert (approx (out[1].second, Triple (0.0, 0.454545, 0.909091)));
-    assert (approx (out[2].first, -0.1));
-    assert (approx (out[2].second, Triple (0.909091, 1.0, 1.0)));
-    assert (out[3].first == -0.5);
-    assert (out[3].second == Triple (-1.0, -1.0, 0.0));
+    hb_always_assert (out.length == 4);
+    hb_always_assert (out[0].first == 0.5);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == 0.5);
+    hb_always_assert (approx (out[1].second, Triple (0.0, 0.454545, 0.909091)));
+    hb_always_assert (approx (out[2].first, -0.1));
+    hb_always_assert (approx (out[2].second, Triple (0.909091, 1.0, 1.0)));
+    hb_always_assert (out[3].first == -0.5);
+    hb_always_assert (out[3].second == Triple (-1.0, -1.0, 0.0));
   }
 
   /* Case 3a/1neg */
@@ -197,13 +197,13 @@
     Triple tent (0.0, 0.5, 2.0);
     Triple axis_range (0.2, 0.5, 0.8);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 3);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple ());
-    assert (approx (out[1].first, -0.2));
-    assert (out[1].second == Triple (0.0, 1.0, 1.0));
-    assert (approx (out[2].first, -0.6));
-    assert (out[2].second == Triple (-1.0, -1.0, 0.0));
+    hb_always_assert (out.length == 3);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (approx (out[1].first, -0.2));
+    hb_always_assert (out[1].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (approx (out[2].first, -0.6));
+    hb_always_assert (out[2].second == Triple (-1.0, -1.0, 0.0));
   }
 
   /* Case 3a/1neg */
@@ -211,13 +211,13 @@
     Triple tent (0.0, 0.5, 2.0);
     Triple axis_range (0.2, 0.5, 1.0);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 3);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple ());
-    assert (approx (out[1].first, -1.0/3));
-    assert (out[1].second == Triple (0.0, 1.0, 1.0));
-    assert (approx (out[2].first, -0.6));
-    assert (out[2].second == Triple (-1.0, -1.0, 0.0));
+    hb_always_assert (out.length == 3);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (approx (out[1].first, -1.0/3));
+    hb_always_assert (out[1].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (approx (out[2].first, -0.6));
+    hb_always_assert (out[2].second == Triple (-1.0, -1.0, 0.0));
   }
 
   /* Case 3 */
@@ -225,11 +225,11 @@
     Triple tent (0.0, 0.5, 1.0);
     Triple axis_range (0.25, 0.25, 0.75);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 2);
-    assert (out[0].first == 0.5);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == 0.5);
-    assert (out[1].second == Triple (0.0, 0.5, 1.0));
+    hb_always_assert (out.length == 2);
+    hb_always_assert (out[0].first == 0.5);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == 0.5);
+    hb_always_assert (out[1].second == Triple (0.0, 0.5, 1.0));
   }
 
   /* Case 1neg */
@@ -237,13 +237,13 @@
     Triple tent (0.0, 0.5, 1.0);
     Triple axis_range (0.0, 0.25, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 3);
-    assert (out[0].first == 0.5);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == 0.5);
-    assert (out[1].second == Triple (0.0, 1.0, 1.0));
-    assert (out[2].first == -0.5);
-    assert (out[2].second == Triple (-1.0, -1.0, 0.0));
+    hb_always_assert (out.length == 3);
+    hb_always_assert (out[0].first == 0.5);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == 0.5);
+    hb_always_assert (out[1].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (out[2].first == -0.5);
+    hb_always_assert (out[2].second == Triple (-1.0, -1.0, 0.0));
   }
 
   /* Case 2neg */
@@ -251,15 +251,15 @@
     Triple tent (0.05, 0.55, 1.0);
     Triple axis_range (0.0, 0.25, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 4);
-    assert (approx (out[0].first, 0.4));
-    assert (out[0].second == Triple ());
-    assert (approx (out[1].first, 0.5));
-    assert (out[1].second == Triple (0.0, 1.0, 1.0));
-    assert (approx (out[2].first, -0.4));
-    assert (out[2].second == Triple (-1.0, -0.8, 0.0));
-    assert (approx (out[3].first, -0.4));
-    assert (out[3].second == Triple (-1.0, -1.0, -0.8));
+    hb_always_assert (out.length == 4);
+    hb_always_assert (approx (out[0].first, 0.4));
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (approx (out[1].first, 0.5));
+    hb_always_assert (out[1].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (approx (out[2].first, -0.4));
+    hb_always_assert (out[2].second == Triple (-1.0, -0.8, 0.0));
+    hb_always_assert (approx (out[3].first, -0.4));
+    hb_always_assert (out[3].second == Triple (-1.0, -1.0, -0.8));
   }
 
   /* Case 2neg, other side */
@@ -267,15 +267,15 @@
     Triple tent (-1.0, -0.55, -0.05);
     Triple axis_range (-0.5, -0.25, 0.0);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 4);
-    assert (approx (out[0].first, 0.4));
-    assert (out[0].second == Triple ());
-    assert (approx (out[1].first, 0.5));
-    assert (out[1].second == Triple (-1.0, -1.0, 0.0));
-    assert (approx (out[2].first, -0.4));
-    assert (out[2].second == Triple (0.0, 0.8, 1.0));
-    assert (approx (out[3].first, -0.4));
-    assert (out[3].second == Triple (0.8, 1.0, 1.0));
+    hb_always_assert (out.length == 4);
+    hb_always_assert (approx (out[0].first, 0.4));
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (approx (out[1].first, 0.5));
+    hb_always_assert (out[1].second == Triple (-1.0, -1.0, 0.0));
+    hb_always_assert (approx (out[2].first, -0.4));
+    hb_always_assert (out[2].second == Triple (0.0, 0.8, 1.0));
+    hb_always_assert (approx (out[3].first, -0.4));
+    hb_always_assert (out[3].second == Triple (0.8, 1.0, 1.0));
   }
 
   /* Misc corner cases */
@@ -283,9 +283,9 @@
     Triple tent (0.5, 0.5, 0.5);
     Triple axis_range (0.5, 0.5, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple ());
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple ());
   }
 
   {
@@ -292,17 +292,17 @@
     Triple tent (0.3, 0.5, 0.7);
     Triple axis_range (0.1, 0.5, 0.9);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 5);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == -1.0);
-    assert (approx(out[1].second, Triple (0.0, 0.5, 1.0)));
-    assert (out[2].first == -1.0);
-    assert (approx(out[2].second, Triple (0.5, 1.0, 1.0)));
-    assert (out[3].first == -1.0);
-    assert (approx (out[3].second, Triple (-1.0, -0.5, 0.0)));
-    assert (out[4].first == -1.0);
-    assert (approx (out[4].second, Triple (-1.0, -1.0, -0.5)));
+    hb_always_assert (out.length == 5);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == -1.0);
+    hb_always_assert (approx(out[1].second, Triple (0.0, 0.5, 1.0)));
+    hb_always_assert (out[2].first == -1.0);
+    hb_always_assert (approx(out[2].second, Triple (0.5, 1.0, 1.0)));
+    hb_always_assert (out[3].first == -1.0);
+    hb_always_assert (approx (out[3].second, Triple (-1.0, -0.5, 0.0)));
+    hb_always_assert (out[4].first == -1.0);
+    hb_always_assert (approx (out[4].second, Triple (-1.0, -1.0, -0.5)));
   }
 
   {
@@ -309,9 +309,9 @@
     Triple tent (0.5, 0.5, 0.5);
     Triple axis_range (0.25, 0.25, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (1.0, 1.0, 1.0));
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (1.0, 1.0, 1.0));
   }
 
   {
@@ -318,9 +318,9 @@
     Triple tent (0.5, 0.5, 0.5);
     Triple axis_range (0.25, 0.35, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (1.0, 1.0, 1.0));
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (1.0, 1.0, 1.0));
   }
 
   {
@@ -327,9 +327,9 @@
     Triple tent (0.5, 0.5, 0.55);
     Triple axis_range (0.25, 0.35, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (1.0, 1.0, 1.0));
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (1.0, 1.0, 1.0));
   }
 
   {
@@ -336,11 +336,11 @@
     Triple tent (0.5, 0.5, 1.0);
     Triple axis_range (0.5, 0.5, 1.0);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 2);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == -1.0);
-    assert (out[1].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (out.length == 2);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == -1.0);
+    hb_always_assert (out[1].second == Triple (0.0, 1.0, 1.0));
   }
 
   {
@@ -347,11 +347,11 @@
     Triple tent (0.25, 0.5, 1.0);
     Triple axis_range (0.5, 0.5, 1.0);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 2);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == -1.0);
-    assert (out[1].second == Triple (0.0, 1.0, 1.0));
+    hb_always_assert (out.length == 2);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == -1.0);
+    hb_always_assert (out[1].second == Triple (0.0, 1.0, 1.0));
   }
 
   {
@@ -358,11 +358,11 @@
     Triple tent (0.0, 0.2, 1.0);
     Triple axis_range (0.0, 0.0, 0.5);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 2);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (0.0, 0.4, 1.0));
-    assert (out[1].first == 0.625);
-    assert (out[1].second == Triple (0.4, 1.0, 1.0));
+    hb_always_assert (out.length == 2);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (0.0, 0.4, 1.0));
+    hb_always_assert (out[1].first == 0.625);
+    hb_always_assert (out[1].second == Triple (0.4, 1.0, 1.0));
   }
 
 
@@ -370,17 +370,17 @@
     Triple tent (0.0, 0.5, 1.0);
     Triple axis_range (-1.0, 0.25, 1.0);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 5);
-    assert (out[0].first == 0.5);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == 0.5);
-    assert (out[1].second == Triple (0.0, 1.0/3, 2.0/3));
-    assert (out[2].first == -0.5);
-    assert (out[2].second == Triple (2.0/3, 1.0, 1.0));
-    assert (out[3].first == -0.5);
-    assert (out[3].second == Triple (-1.0, -0.2, 0.0));
-    assert (out[4].first == -0.5);
-    assert (out[4].second == Triple (-1.0, -1.0, -0.2));
+    hb_always_assert (out.length == 5);
+    hb_always_assert (out[0].first == 0.5);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == 0.5);
+    hb_always_assert (out[1].second == Triple (0.0, 1.0/3, 2.0/3));
+    hb_always_assert (out[2].first == -0.5);
+    hb_always_assert (out[2].second == Triple (2.0/3, 1.0, 1.0));
+    hb_always_assert (out[3].first == -0.5);
+    hb_always_assert (out[3].second == Triple (-1.0, -0.2, 0.0));
+    hb_always_assert (out[4].first == -0.5);
+    hb_always_assert (out[4].second == Triple (-1.0, -1.0, -0.2));
   }
 
   {
@@ -387,17 +387,17 @@
     Triple tent (0.5, 0.5, 0.5);
     Triple axis_range (0.0, 0.5, 1.0);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 5);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple ());
-    assert (out[1].first == -1.0);
-    assert (out[1].second == Triple (0.0, 2/(double) (1 << 14), 1.0));
-    assert (out[2].first == -1.0);
-    assert (out[2].second == Triple (2/(double) (1 << 14), 1.0, 1.0));
-    assert (out[3].first == -1.0);
-    assert (out[3].second == Triple (-1.0, -2/(double) (1 << 14), 0.0));
-    assert (out[4].first == -1.0);
-    assert (out[4].second == Triple (-1.0, -1.0, -2/(double) (1 << 14)));
+    hb_always_assert (out.length == 5);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple ());
+    hb_always_assert (out[1].first == -1.0);
+    hb_always_assert (out[1].second == Triple (0.0, 2/(double) (1 << 14), 1.0));
+    hb_always_assert (out[2].first == -1.0);
+    hb_always_assert (out[2].second == Triple (2/(double) (1 << 14), 1.0, 1.0));
+    hb_always_assert (out[3].first == -1.0);
+    hb_always_assert (out[3].second == Triple (-1.0, -2/(double) (1 << 14), 0.0));
+    hb_always_assert (out[4].first == -1.0);
+    hb_always_assert (out[4].second == Triple (-1.0, -1.0, -2/(double) (1 << 14)));
   }
 
   {
@@ -404,9 +404,9 @@
     Triple tent (0.0, 1.0, 1.0);
     Triple axis_range (-1.0, -0.5, 1.0);
     rebase_tent_result_t out = rebase_tent (tent, axis_range, default_axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (1.0/3, 1.0, 1.0));
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (1.0/3, 1.0, 1.0));
   }
 
   {
@@ -414,9 +414,9 @@
     Triple axis_range (-1.0, -0.5, 1.0);
     TripleDistances axis_distances{2.0, 1.0};
     rebase_tent_result_t out = rebase_tent (tent, axis_range, axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 1.0);
-    assert (out[0].second == Triple (0.5, 1.0, 1.0));
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (out[0].second == Triple (0.5, 1.0, 1.0));
   }
 
   {
@@ -424,8 +424,8 @@
     Triple axis_range (-1.0, 0.2, 1.0);
     TripleDistances axis_distances{1.0, 1.0};
     rebase_tent_result_t out = rebase_tent (tent, axis_range, axis_distances);
-    assert (out.length == 1);
-    assert (out[0].first == 1.0);
-    assert (approx (out[0].second, Triple (0.5, 0.625, 0.75)));
+    hb_always_assert (out.length == 1);
+    hb_always_assert (out[0].first == 1.0);
+    hb_always_assert (approx (out[0].second, Triple (0.5, 0.625, 0.75)));
   }
 }

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -48,33 +48,33 @@
   hb_bytes_t var_data_bytes{(const char* ) cvar_data + 4, len - 4};
   bool result = OT::TupleVariationData<>::get_tuple_iterator (var_data_bytes, axis_count, cvar_table,
                                                             shared_indices, &iterator);
-  assert (result);
+  hb_always_assert (result);
 
   result = tuple_var_data->decompile_tuple_variations (point_count, false, iterator, &axis_idx_tag_map,
                                                        shared_indices, hb_array<const OT::F2DOT14> (),
                                                        tuple_variations);
 
-  assert (result);
-  assert (tuple_variations.tuple_vars.length == 2);
+  hb_always_assert (result);
+  hb_always_assert (tuple_variations.tuple_vars.length == 2);
   for (unsigned i = 0; i < 2; i++)
   {
-    assert (tuple_variations.tuple_vars[i].axis_tuples.get_population () == 1);
-    assert (!tuple_variations.tuple_vars[i].deltas_y);
-    assert (tuple_variations.tuple_vars[i].indices.length == 65);
-    assert (tuple_variations.tuple_vars[i].indices.length == tuple_variations.tuple_vars[i].deltas_x.length);
+    hb_always_assert (tuple_variations.tuple_vars[i].axis_tuples.get_population () == 1);
+    hb_always_assert (!tuple_variations.tuple_vars[i].deltas_y);
+    hb_always_assert (tuple_variations.tuple_vars[i].indices.length == 65);
+    hb_always_assert (tuple_variations.tuple_vars[i].indices.length == tuple_variations.tuple_vars[i].deltas_x.length);
   }
-  assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.0, -1.0, 0.0));
-  assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.0, 1.0, 1.0));
+  hb_always_assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.0, -1.0, 0.0));
+  hb_always_assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.0, 1.0, 1.0));
 
   hb_vector_t<float> deltas_1 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -3.0, 1.0, 0.0, -1.0, 0.0, -3.0, 1.0, 0.0, -37.0, -37.0, -26.0, -26.0, 0.0, 0.0, 0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 0.0, -3.0, 0.0, 2.0, -29.0, -29.0, -20.0, -20.0, 0.0, 0.0, 0.0, 1.0, -29.0, -29.0, -20.0, -20.0, 0.0, 0.0, 0.0, 1.0};
   for (unsigned i = 0; i < 65; i++)
   {
     if (i < 23)
-      assert (tuple_variations.tuple_vars[0].indices[i] == 0);
+      hb_always_assert (tuple_variations.tuple_vars[0].indices[i] == 0);
     else
     {
-      assert (tuple_variations.tuple_vars[0].indices[i] == 1);
-      assert (tuple_variations.tuple_vars[0].deltas_x[i] == deltas_1[i]);
+      hb_always_assert (tuple_variations.tuple_vars[0].indices[i] == 1);
+      hb_always_assert (tuple_variations.tuple_vars[0].deltas_x[i] == deltas_1[i]);
     }
   }
 
@@ -82,11 +82,11 @@
   for (unsigned i = 0 ; i < 65; i++)
   {
     if (i < 23)
-      assert (tuple_variations.tuple_vars[1].indices[i] == 0);
+      hb_always_assert (tuple_variations.tuple_vars[1].indices[i] == 0);
     else
     {
-      assert (tuple_variations.tuple_vars[1].indices[i] == 1);
-      assert (tuple_variations.tuple_vars[1].deltas_x[i] == deltas_2[i]);
+      hb_always_assert (tuple_variations.tuple_vars[1].indices[i] == 1);
+      hb_always_assert (tuple_variations.tuple_vars[1].deltas_x[i] == deltas_2[i]);
     }
   }
 
@@ -99,12 +99,12 @@
 
   tuple_variations.instantiate (normalized_axes_location, axes_triple_distances);
 
-  assert (tuple_variations.tuple_vars[0].indices.length == 65);
-  assert (tuple_variations.tuple_vars[1].indices.length == 65);
-  assert (!tuple_variations.tuple_vars[0].deltas_y);
-  assert (!tuple_variations.tuple_vars[1].deltas_y);
-  assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.0, -1.0, 0.0));
-  assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.0, 1.0, 1.0));
+  hb_always_assert (tuple_variations.tuple_vars[0].indices.length == 65);
+  hb_always_assert (tuple_variations.tuple_vars[1].indices.length == 65);
+  hb_always_assert (!tuple_variations.tuple_vars[0].deltas_y);
+  hb_always_assert (!tuple_variations.tuple_vars[1].deltas_y);
+  hb_always_assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.0, -1.0, 0.0));
+  hb_always_assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.0, 1.0, 1.0));
 
   hb_vector_t<float> rounded_deltas_1 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1, 0.0, -2, 1, 0.0, -1, 0.0, -2, 1, 0.0, -19, -19, -13, -13, 0.0, 0.0, 0.0, -2, 0.0, 0.0, 0.0, 0.0, 0.0, -2, 0.0, 1, -15, -15, -10.0, -10.0, 0.0, 0.0, 0.0, 1, -15, -15, -10.0, -10.0, 0.0, 0.0, 0.0, 1};
 
@@ -114,15 +114,15 @@
   {
     if (i < 23)
     {
-      assert (tuple_variations.tuple_vars[0].indices[i] == 0);
-      assert (tuple_variations.tuple_vars[1].indices[i] == 0);
+      hb_always_assert (tuple_variations.tuple_vars[0].indices[i] == 0);
+      hb_always_assert (tuple_variations.tuple_vars[1].indices[i] == 0);
     }
     else
     {
-      assert (tuple_variations.tuple_vars[0].indices[i] == 1);
-      assert (tuple_variations.tuple_vars[1].indices[i] == 1);
-      assert (roundf (tuple_variations.tuple_vars[0].deltas_x[i]) == rounded_deltas_1[i]);
-      assert (roundf (tuple_variations.tuple_vars[1].deltas_x[i]) == rounded_deltas_2[i]);
+      hb_always_assert (tuple_variations.tuple_vars[0].indices[i] == 1);
+      hb_always_assert (tuple_variations.tuple_vars[1].indices[i] == 1);
+      hb_always_assert (roundf (tuple_variations.tuple_vars[0].deltas_x[i]) == rounded_deltas_1[i]);
+      hb_always_assert (roundf (tuple_variations.tuple_vars[1].deltas_x[i]) == rounded_deltas_2[i]);
     }
   }
 
@@ -129,26 +129,26 @@
   hb_map_t axes_index_map;
   axes_index_map.set (0, 0);
   bool res = tuple_variations.compile_bytes (axes_index_map, axis_idx_tag_map, false);
-  assert (res);
-  assert (tuple_variations.tuple_vars[0].compiled_tuple_header.length == 6);
+  hb_always_assert (res);
+  hb_always_assert (tuple_variations.tuple_vars[0].compiled_tuple_header.length == 6);
   const unsigned char tuple_var_header_1[] = "\x0\x51\xa0\x0\xc0\x0";
   for (unsigned i = 0; i < 6; i++)
-    assert(tuple_variations.tuple_vars[0].compiled_tuple_header.arrayZ[i] == tuple_var_header_1[i]);
+    hb_always_assert(tuple_variations.tuple_vars[0].compiled_tuple_header.arrayZ[i] == tuple_var_header_1[i]);
 
-  assert (tuple_variations.tuple_vars[1].compiled_tuple_header.length == 6);
+  hb_always_assert (tuple_variations.tuple_vars[1].compiled_tuple_header.length == 6);
   const unsigned char tuple_var_header_2[] = "\x0\x54\xa0\x0\x40\x0";
   for (unsigned i = 0; i < 6; i++)
-    assert(tuple_variations.tuple_vars[1].compiled_tuple_header.arrayZ[i] == tuple_var_header_2[i]);
+    hb_always_assert(tuple_variations.tuple_vars[1].compiled_tuple_header.arrayZ[i] == tuple_var_header_2[i]);
 
-  assert (tuple_variations.tuple_vars[0].compiled_deltas.length == 37);
-  assert (tuple_variations.tuple_vars[1].compiled_deltas.length == 40);
+  hb_always_assert (tuple_variations.tuple_vars[0].compiled_deltas.length == 37);
+  hb_always_assert (tuple_variations.tuple_vars[1].compiled_deltas.length == 40);
   const unsigned char compiled_deltas_1[] = "\x0d\xff\x00\xfe\x01\x00\xff\x00\xfe\x01\x00\xed\xed\xf3\xf3\x82\x00\xfe\x84\x06\xfe\x00\x01\xf1\xf1\xf6\xf6\x82\x04\x01\xf1\xf1\xf6\xf6\x82\x00\x01";
   for (unsigned i = 0; i < 37; i++)
-    assert (tuple_variations.tuple_vars[0].compiled_deltas.arrayZ[i] == compiled_deltas_1[i]);
+    hb_always_assert (tuple_variations.tuple_vars[0].compiled_deltas.arrayZ[i] == compiled_deltas_1[i]);
 
   const unsigned char compiled_deltas_2[] = "\x0d\x01\x00\x04\xfe\x00\x01\x00\x04\xfe\x00\x44\x44\x30\x30\x82\x00\x04\x81\x09\x01\xff\x01\x05\xff\xfc\x33\x33\x25\x25\x82\x04\xff\x33\x33\x25\x25\x82\x00\xff";
   for (unsigned i = 0; i < 40; i++)
-    assert (tuple_variations.tuple_vars[1].compiled_deltas.arrayZ[i] == compiled_deltas_2[i]);
+    hb_always_assert (tuple_variations.tuple_vars[1].compiled_deltas.arrayZ[i] == compiled_deltas_2[i]);
 }
 
 int

Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc	2025-08-13 22:39:51 UTC (rev 76048)
@@ -33,7 +33,7 @@
 int
 main (int argc, char **argv)
 {
-  assert (sizeof (hb_vector_t<int>) == sizeof (hb_sorted_vector_t<int>));
+  hb_always_assert (sizeof (hb_vector_t<int>) == sizeof (hb_sorted_vector_t<int>));
 
   /* Test copy constructor. */
   {
@@ -40,12 +40,12 @@
     hb_vector_t<int> v1 {1, 2};
     hb_vector_t<int> v2 {v1};
     hb_vector_t<int> V2 {v1};
-    assert (v1.length == 2);
-    assert (v1[0] == 1);
-    assert (v1[1] == 2);
-    assert (v2.length == 2);
-    assert (v2[0] == 1);
-    assert (v2[1] == 2);
+    hb_always_assert (v1.length == 2);
+    hb_always_assert (v1[0] == 1);
+    hb_always_assert (v1[1] == 2);
+    hb_always_assert (v2.length == 2);
+    hb_always_assert (v2[0] == 1);
+    hb_always_assert (v2[1] == 2);
   }
 
   /* Test copy assignment. */
@@ -53,12 +53,12 @@
     hb_vector_t<int> v1 {1, 2};
     hb_vector_t<int> v2 = v1;
     hb_vector_t<int> V2 = v1;
-    assert (v1.length == 2);
-    assert (v1[0] == 1);
-    assert (v1[1] == 2);
-    assert (v2.length == 2);
-    assert (v2[0] == 1);
-    assert (v2[1] == 2);
+    hb_always_assert (v1.length == 2);
+    hb_always_assert (v1[0] == 1);
+    hb_always_assert (v1[1] == 2);
+    hb_always_assert (v2.length == 2);
+    hb_always_assert (v2[0] == 1);
+    hb_always_assert (v2[1] == 2);
   }
 
   /* Test move constructor. */
@@ -67,11 +67,11 @@
     hb_sorted_vector_t<int> S {1, 2};
     hb_vector_t<int> v (std::move (s));
     hb_sorted_vector_t<int> V (std::move (S));
-    assert (s.length == 0);
-    assert (S.length == 0);
-    assert (v.length == 2);
-    assert (v[0] == 1);
-    assert (v[1] == 2);
+    hb_always_assert (s.length == 0);
+    hb_always_assert (S.length == 0);
+    hb_always_assert (v.length == 2);
+    hb_always_assert (v[0] == 1);
+    hb_always_assert (v[1] == 2);
   }
 
   /* Test move assignment. */
@@ -82,12 +82,12 @@
     hb_sorted_vector_t<int> V;
     v = std::move (s);
     V = std::move (S);
-    assert (s.length == 0);
-    assert (S.length == 0);
-    assert (v.length == 2);
-    assert (V.length == 2);
-    assert (v[0] == 1);
-    assert (v[1] == 2);
+    hb_always_assert (s.length == 0);
+    hb_always_assert (S.length == 0);
+    hb_always_assert (v.length == 2);
+    hb_always_assert (V.length == 2);
+    hb_always_assert (v[0] == 1);
+    hb_always_assert (v[1] == 2);
   }
 
   /* Test initializing from iterable. */
@@ -100,12 +100,12 @@
     hb_vector_t<int> v (s);
     hb_sorted_vector_t<int> V (s);
 
-    assert (v.length == 2);
-    assert (V.length == 2);
-    assert (v[0] == 12);
-    assert (V[0] == 12);
-    assert (v[1] == 18);
-    assert (V[1] == 18);
+    hb_always_assert (v.length == 2);
+    hb_always_assert (V.length == 2);
+    hb_always_assert (v[0] == 12);
+    hb_always_assert (V[0] == 12);
+    hb_always_assert (v[1] == 18);
+    hb_always_assert (V[1] == 18);
   }
 
   /* Test initializing from iterator. */
@@ -118,12 +118,12 @@
     hb_vector_t<int> v (hb_iter (s));
     hb_vector_t<int> V (hb_iter (s));
 
-    assert (v.length == 2);
-    assert (V.length == 2);
-    assert (v[0] == 12);
-    assert (V[0] == 12);
-    assert (v[1] == 18);
-    assert (V[1] == 18);
+    hb_always_assert (v.length == 2);
+    hb_always_assert (V.length == 2);
+    hb_always_assert (v[0] == 12);
+    hb_always_assert (V[0] == 12);
+    hb_always_assert (v[1] == 18);
+    hb_always_assert (V[1] == 18);
   }
 
   /* Test initializing from initializer list and swapping. */
@@ -131,10 +131,10 @@
     hb_vector_t<int> v1 {1, 2, 3};
     hb_vector_t<int> v2 {4, 5};
     hb_swap (v1, v2);
-    assert (v1.length == 2);
-    assert (v1[0] == 4);
-    assert (v2.length == 3);
-    assert (v2[2] == 3);
+    hb_always_assert (v1.length == 2);
+    hb_always_assert (v1[0] == 4);
+    hb_always_assert (v2.length == 3);
+    hb_always_assert (v2[2] == 3);
   }
 
   /* Test initializing sorted-vector from initializer list and swapping. */
@@ -142,10 +142,10 @@
     hb_sorted_vector_t<int> v1 {1, 2, 3};
     hb_sorted_vector_t<int> v2 {4, 5};
     hb_swap (v1, v2);
-    assert (v1.length == 2);
-    assert (v1[0] == 4);
-    assert (v2.length == 3);
-    assert (v2[2] == 3);
+    hb_always_assert (v1.length == 2);
+    hb_always_assert (v1[0] == 4);
+    hb_always_assert (v2.length == 3);
+    hb_always_assert (v2[2] == 3);
   }
 
   {
@@ -171,9 +171,9 @@
     hb_set_t s {1, 5, 7};
     v.push (s);
     v << s;
-    assert (s.get_population () == 3);
+    hb_always_assert (s.get_population () == 3);
     v << std::move (s);
-    assert (s.get_population () == 0);
+    hb_always_assert (s.get_population () == 0);
   }
 
   {

Modified: trunk/Build/source/libs/harfbuzz/version.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/version.ac	2025-08-13 20:02:02 UTC (rev 76047)
+++ trunk/Build/source/libs/harfbuzz/version.ac	2025-08-13 22:39:51 UTC (rev 76048)
@@ -8,4 +8,4 @@
 dnl --------------------------------------------------------
 dnl
 dnl  m4-include this file to define the current harfbuzz version
-m4_define([harfbuzz_version], [11.3.3])
+m4_define([harfbuzz_version], [11.4.1])



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