texlive[74540] Build/source/libs: harfbuzz 10.4.0
commits+kakuto at tug.org
commits+kakuto at tug.org
Sat Mar 8 23:22:06 CET 2025
Revision: 74540
https://tug.org/svn/texlive?view=revision&revision=74540
Author: kakuto
Date: 2025-03-08 23:22:06 +0100 (Sat, 08 Mar 2025)
Log Message:
-----------
harfbuzz 10.4.0
Modified Paths:
--------------
trunk/Build/source/libs/README
trunk/Build/source/libs/harfbuzz/ChangeLog
trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
trunk/Build/source/libs/harfbuzz/configure
trunk/Build/source/libs/harfbuzz/harfbuzz-src/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/meson.build
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/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/Common/CoverageFormat1.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/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/GPOS/SinglePosFormat1.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/SingleSubstFormat1.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/SingleSubstFormat2.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/Var/VARC/coord-setter.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.rl
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-font.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-shape.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft-colr.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-geometry.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-vowel-constraints.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc
trunk/Build/source/libs/harfbuzz/version.ac
Added Paths:
-----------
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-decycler.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-decycler.cc
Modified: trunk/Build/source/libs/README
===================================================================
--- trunk/Build/source/libs/README 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/README 2025-03-08 22:22:06 UTC (rev 74540)
@@ -28,7 +28,7 @@
https://sourceforge.net/projects/silgraphite/files/graphite2/
(requires C++11)
-harfbuzz 10.2.0 - checked 12jan25
+harfbuzz 10.4.0 - checked 09mar25
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/ChangeLog 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1,3 +1,8 @@
+2025-03-09 Akira Kakuto <kakuto at jcom.zaq.ne.jp>
+
+ Import harfbuzz-10.4.0.
+ * version.ac: Adjusted.
+
2025-01-12 Akira Kakuto <kakuto at jcom.zaq.ne.jp>
Import harfbuzz-10.2.0.
Modified: trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1,3 +1,8 @@
+2025-03-09 Akira Kakuto <kakuto at jcom.zaq.ne.jp>
+
+ Imported harfbuzz-10.4.0 source tree from:
+ https://github.com/harfbuzz/harfbuzz/releases/download/10.4.0/
+
2025-01-12 Akira Kakuto <kakuto at jcom.zaq.ne.jp>
Imported harfbuzz-10.2.0 source tree from:
Modified: trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1,5 +1,5 @@
-Changes applied to the harfbuzz-10.2.0/ tree as obtained from:
- https://github.com/harfbuzz/harfbuzz/releases/download/10.2.0/
+Changes applied to the harfbuzz-10.4.0/ tree as obtained from:
+ https://github.com/harfbuzz/harfbuzz/releases/download/10.4.0/
Removed:
.clang-format
Modified: trunk/Build/source/libs/harfbuzz/configure
===================================================================
--- trunk/Build/source/libs/harfbuzz/configure 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/configure 2025-03-08 22:22:06 UTC (rev 74540)
@@ -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) 10.2.0.
+# Generated by GNU Autoconf 2.72 for harfbuzz (TeX Live) 10.4.0.
#
# 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='10.2.0'
-PACKAGE_STRING='harfbuzz (TeX Live) 10.2.0'
+PACKAGE_VERSION='10.4.0'
+PACKAGE_STRING='harfbuzz (TeX Live) 10.4.0'
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) 10.2.0 to adapt to many kinds of systems.
+'configure' configures harfbuzz (TeX Live) 10.4.0 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) 10.2.0:";;
+ short | recursive ) echo "Configuration of harfbuzz (TeX Live) 10.4.0:";;
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 10.2.0
+harfbuzz (TeX Live) configure 10.4.0
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 10.2.0, which was
+It was created by harfbuzz (TeX Live) $as_me 10.4.0, which was
generated by GNU Autoconf 2.72. Invocation command line was
$ $0$ac_configure_args_raw
@@ -5252,7 +5252,7 @@
# Define the identity of the package.
PACKAGE='harfbuzz--tex-live-'
- VERSION='10.2.0'
+ VERSION='10.4.0'
# Some tools Automake needs.
@@ -5441,9 +5441,9 @@
HB_VERSION_MAJOR=10
-HB_VERSION_MINOR=2
+HB_VERSION_MINOR=4
HB_VERSION_MICRO=0
-HB_VERSION=10.2.0
+HB_VERSION=10.4.0
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -9292,7 +9292,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 10.2.0, which was
+This file was extended by harfbuzz (TeX Live) $as_me 10.4.0, which was
generated by GNU Autoconf 2.72. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -9360,7 +9360,7 @@
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
-harfbuzz (TeX Live) config.status 10.2.0
+harfbuzz (TeX Live) config.status 10.4.0
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt 2025-03-08 22:22:06 UTC (rev 74540)
@@ -334,15 +334,15 @@
if (WIN32 AND HB_HAVE_GDI)
add_definitions(-DHAVE_GDI)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-gdi.h)
- list(APPEND THIRD_PARTY_LIBS gdi32)
- list(APPEND PC_LIBS_PRIV -lgdi32)
+ list(APPEND THIRD_PARTY_LIBS gdi32 user32)
+ list(APPEND PC_LIBS_PRIV -lgdi32 -luser32)
endif ()
if (WIN32 AND HB_HAVE_UNISCRIBE)
add_definitions(-DHAVE_UNISCRIBE)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h)
- list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4)
- list(APPEND PC_LIBS_PRIV -lusp10 -lgdi32 -lrpcrt4)
+ list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4 user32)
+ list(APPEND PC_LIBS_PRIV -lusp10 -lgdi32 -lrpcrt4 -luser32)
endif ()
if (WIN32 AND HB_HAVE_DIRECTWRITE)
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1,3 +1,65 @@
+Overview of changes leading to 10.4.0
+Saturday, March 1, 2025
+====================================
+- Drawing glyphs using hb-draw API now avoids any “malloc” calls, which
+ improves drawing performance by 10+%.
+- Add support new “GVAR” table fonts with more than 65535 glyphs. Support is
+ currently behind a compilation flag and is disabled by default.
+- Some hb-directwrite and hb-ft APIs got renamed with more clear names and the
+ old names are deprecated.
+- Various build and fuzzing fixes.
+
+- New API:
++hb_directwrite_face_get_dw_font_face()
++hb_ft_font_get_ft_face()
+
+- Deprecated API:
++hb_directwrite_face_get_font_face()
++hb_ft_font_get_face()
+
+
+Overview of changes leading to 10.3.0
+Thursday, February 11, 2025
+====================================
+- Vastly improved “AAT” shaping performance. LucidaGrande benchmark-shape
+ before: 14.6ms after: 5.9ms.
+- Improved OpenType shaping performance (kerning / ligature), at the expense of
+ ~1kb per face allocated cache memory. Roboto-Regular benchmark-shape before:
+ 10.3ms after: 9.4ms.
+- Improved “COLRv1” benchmark-font paint performance. Before: 7.85ms after
+ 4.85ms.
+- Don’t apply glyph substitutions in “morx” table of a font with known broken
+ “morx” table (AALMAGHRIBI.ttf font).
+- Update IANA and OT language registries.
+- Various documentation updates.
+- Various build improvements, and test speed-ups.
+- The “hb_face_reference_blob()” API now works for faces created with
+ “hb_face_create_for_tables()” if the face sets “get_table_tags” callback.
+ This constructs a new face blob from individual table blobs.
+- Various fixes to how “trak” table is handled to bring it closer to Core Text
+ behaviour. Particularly, the tracking values for sizes not explicitly set in
+ the table are now properly interpolated, and the tracking is applied to glyph
+ advances when they are returned by ot-font functions, instead of applying
+ them during shaping. The “trak” pseudo OpenType feature that could be used to
+ disable “trak” table application have been dropped.
+- Core Text font functions now support non-BMP code points.
+- The drawing algorithm used by hb-draw for “glyf” table now match the
+ algorithm used by FreeType and Core Text.
+- The “hb_coretext_font_create()” API now copy font variations from Core Text
+ font to the created HarfBuzz font.
+- Add an API to get the feature tags enabled on a given shape-plan after
+ executing it, which can be used to applications to show in the UI what
+ features are applied by default (which can vary based on the font, the
+ script, the language, and the direction set on the buffer).
+- Add APIs to created HarfBuzz font from DirectWrite font, and copy the font
+ variations.
+
+- New API:
++hb_directwrite_font_create()
++hb_directwrite_font_get_dw_font()
++hb_ot_shape_plan_get_feature_tags()
+
+
Overview of changes leading to 10.2.0
Saturday, January 11, 2025
====================================
@@ -183,10 +245,10 @@
tools. Old option is kept as an alias.
- New API:
-HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION
++HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION
- Deprecated API:
-HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION
++HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION
Overview of changes leading to 8.2.2
Wednesday, October 18, 2023
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1,9 +1,9 @@
-[](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)
+[](https://github.com/harfbuzz/harfbuzz/actions/workflows/linux-ci.yml)
+[](https://github.com/harfbuzz/harfbuzz/actions/workflows/macos-ci.yml)
+[](https://github.com/harfbuzz/harfbuzz/actions/workflows/msvc-ci.yml)
[](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main)
[](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
[](https://scan.coverity.com/projects/harfbuzz)
-[](https://app.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
-[](https://codecov.io/gh/harfbuzz/harfbuzz)
[](https://repology.org/project/harfbuzz/versions)
[](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz)
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1,6 +1,6 @@
project('harfbuzz', 'c', 'cpp',
meson_version: '>= 0.55.0',
- version: '10.2.0',
+ version: '10.4.0',
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
@@ -321,7 +321,7 @@
endif
gdi_deps_found = true
- foreach usplib : ['usp10', 'gdi32', 'rpcrt4']
+ foreach usplib : ['usp10', 'gdi32', 'rpcrt4', 'user32']
dep = cpp.find_library(usplib, required: get_option('gdi'))
gdi_deps_found = gdi_deps_found and dep.found()
gdi_uniscribe_deps += dep
@@ -464,6 +464,13 @@
alias_target('lib', libharfbuzz)
alias_target('libs', libharfbuzz, libharfbuzz_subset)
+if meson.version().version_compare('>=0.57.0')
+ # Re glib, see https://github.com/harfbuzz/harfbuzz/issues/4153#issuecomment-2646347531
+ add_test_setup('default',
+ exclude_suites: ['google-benchmark'],
+ is_default: glib_dep.type_name() != 'internal' and not meson.is_subproject())
+endif
+
build_summary = {
'Directories':
{'prefix': get_option('prefix'),
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -941,10 +941,12 @@
}
}
- bool has_data () const { return cbdt.get_length (); }
+ bool has_data () const { return cbdt->version.major; }
bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
{
+ if (!has_data ()) return false;
+
hb_glyph_extents_t extents;
hb_glyph_extents_t pixel_extents;
hb_blob_t *blob = reference_png (font, glyph);
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -29,11 +29,14 @@
#define OT_COLOR_COLR_COLR_HH
#include "../../../hb.hh"
+#include "../../../hb-decycler.hh"
#include "../../../hb-open-type.hh"
#include "../../../hb-ot-var-common.hh"
#include "../../../hb-paint.hh"
#include "../../../hb-paint-extents.hh"
+#include "../CPAL/CPAL.hh"
+
/*
* COLR -- Color
* https://docs.microsoft.com/en-us/typography/opentype/spec/colr
@@ -66,11 +69,11 @@
hb_paint_funcs_t *funcs;
void *data;
hb_font_t *font;
- unsigned int palette_index;
+ hb_array_t<const BGRAColor> palette;
hb_color_t foreground;
ItemVarStoreInstancer &instancer;
- hb_map_t current_glyphs;
- hb_map_t current_layers;
+ hb_decycler_t glyphs_decycler;
+ hb_decycler_t layers_decycler;
int depth_left = HB_MAX_NESTING_LEVEL;
int edge_count = HB_MAX_GRAPH_EDGE_COUNT;
@@ -85,7 +88,11 @@
funcs (funcs_),
data (data_),
font (font_),
- palette_index (palette_),
+ palette (
+#ifndef HB_NO_COLOR
+ font->face->table.CPAL->get_palette_colors (palette_)
+#endif
+ ),
foreground (foreground_),
instancer (instancer_)
{ }
@@ -99,13 +106,8 @@
if (color_index != 0xffff)
{
if (!funcs->custom_palette_color (data, color_index, &color))
- {
- unsigned int clen = 1;
- hb_face_t *face = hb_font_get_face (font);
+ color = palette[color_index];
- hb_ot_color_palette_get_colors (face, palette_index, color_index, &clen, &color);
- }
-
*is_foreground = false;
}
@@ -2134,6 +2136,8 @@
const ItemVariationStore &get_var_store () const
{ return colr->get_var_store (); }
+ const ItemVariationStore *get_var_store_ptr () const
+ { return colr->get_var_store_ptr (); }
bool has_delta_set_index_map () const
{ return colr->has_delta_set_index_map (); }
@@ -2140,6 +2144,8 @@
const DeltaSetIndexMap &get_delta_set_index_map () const
{ return colr->get_delta_set_index_map (); }
+ const DeltaSetIndexMap *get_delta_set_index_map_ptr () const
+ { return colr->get_delta_set_index_map_ptr (); }
private:
hb_blob_ptr_t<COLR> colr;
@@ -2232,9 +2238,13 @@
const DeltaSetIndexMap &get_delta_set_index_map () const
{ return has_delta_set_index_map () && hb_barrier () ? this+varIdxMap : Null (DeltaSetIndexMap); }
+ const DeltaSetIndexMap *get_delta_set_index_map_ptr () const
+ { return has_delta_set_index_map () && hb_barrier () ? &(this+varIdxMap) : nullptr; }
const ItemVariationStore &get_var_store () const
{ return has_var_store () && hb_barrier () ? this+varStore : Null (ItemVariationStore); }
+ const ItemVariationStore *get_var_store_ptr () const
+ { return has_var_store () && hb_barrier () ? &(this+varStore) : nullptr; }
const ClipList &get_clip_list () const
{ return has_clip_list () && hb_barrier () ? this+clipList : Null (ClipList); }
@@ -2482,9 +2492,9 @@
* after instancing */
if (!subset_varstore (c, colr_prime)) return_trace (false);
- ItemVarStoreInstancer instancer (&(get_var_store ()),
- &(get_delta_set_index_map ()),
- c->plan->normalized_coords.as_array ());
+ ItemVarStoreInstancer instancer (get_var_store_ptr (),
+ get_delta_set_index_map_ptr (),
+ c->plan->normalized_coords.as_array ());
if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this, instancer))
return_trace (false);
@@ -2513,8 +2523,8 @@
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
{
- ItemVarStoreInstancer instancer (&(get_var_store ()),
- &(get_delta_set_index_map ()),
+ ItemVarStoreInstancer instancer (get_var_store_ptr (),
+ get_delta_set_index_map_ptr (),
hb_array (font->coords, font->num_coords));
if (get_clip (glyph, extents, instancer))
@@ -2575,12 +2585,14 @@
bool
paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const
{
- ItemVarStoreInstancer instancer (&(get_var_store ()),
- &(get_delta_set_index_map ()),
- hb_array (font->coords, font->num_coords));
+ ItemVarStoreInstancer instancer (get_var_store_ptr (),
+ get_delta_set_index_map_ptr (),
+ hb_array (font->coords, font->num_coords));
hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
- c.current_glyphs.add (glyph);
+ hb_decycler_node_t node (c.glyphs_decycler);
+ node.visit (glyph);
+
if (version >= 1)
{
hb_barrier ();
@@ -2695,19 +2707,16 @@
{
TRACE_PAINT (this);
const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
+ hb_decycler_node_t node (c->layers_decycler);
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
{
- if (unlikely (c->current_layers.has (i)))
- continue;
+ if (unlikely (!node.visit (i)))
+ return;
- c->current_layers.add (i);
-
const Paint &paint = paint_offset_lists.get_paint (i);
c->funcs->push_group (c->data);
c->recurse (paint);
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
-
- c->current_layers.del (i);
}
}
@@ -2715,16 +2724,14 @@
{
TRACE_PAINT (this);
- if (unlikely (c->current_glyphs.has (gid)))
+ hb_decycler_node_t node (c->glyphs_decycler);
+ if (unlikely (!node.visit (gid)))
return;
- c->current_glyphs.add (gid);
-
c->funcs->push_inverse_root_transform (c->data, c->font);
if (c->funcs->color_glyph (c->data, gid, c->font))
{
c->funcs->pop_transform (c->data);
- c->current_glyphs.del (gid);
return;
}
c->funcs->pop_transform (c->data);
@@ -2747,8 +2754,6 @@
if (has_clip_box)
c->funcs->pop_clip (c->data);
-
- c->current_glyphs.del (gid);
}
} /* namespace OT */
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CPAL/CPAL.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -187,6 +187,14 @@
hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
{ return v1 ().get_color_name_id (this, color_index, numColors); }
+ hb_array_t<const BGRAColor> get_palette_colors (unsigned int palette_index) const
+ {
+ if (unlikely (palette_index >= numPalettes))
+ return hb_array_t<const BGRAColor> ();
+ unsigned int start_index = colorRecordIndicesZ[palette_index];
+ hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
+ return all_colors.sub_array (start_index, numColors);
+ }
unsigned int get_palette_colors (unsigned int palette_index,
unsigned int start_offset,
unsigned int *color_count, /* IN/OUT. May be NULL. */
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -96,6 +96,15 @@
default:return NOT_COVERED;
}
}
+ unsigned int get_coverage (hb_codepoint_t glyph_id,
+ hb_ot_lookup_cache_t *cache) const
+ {
+ unsigned coverage;
+ if (cache && cache->get (glyph_id, &coverage)) return coverage;
+ coverage = get_coverage (glyph_id);
+ if (cache) cache->set (glyph_id, coverage);
+ return coverage;
+ }
unsigned get_population () const
{
@@ -201,6 +210,19 @@
}
}
+ unsigned cost () const
+ {
+ switch (u.format) {
+ case 1: hb_barrier (); return u.format1.cost ();
+ case 2: hb_barrier (); return u.format2.cost ();
+#ifndef HB_NO_BEYOND_64K
+ case 3: hb_barrier (); return u.format3.cost ();
+ case 4: hb_barrier (); return u.format4.cost ();
+#endif
+ default:return 0u;
+ }
+ }
+
/* Might return false if array looks unsorted.
* Used for faster rejection of corrupt data. */
template <typename set_t>
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -103,6 +103,8 @@
intersect_glyphs << glyphArray[i];
}
+ unsigned cost () const { return hb_bit_storage ((unsigned) glyphArray.len); /* bsearch cost */ }
+
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{ return glyphs->add_sorted_array (glyphArray.as_array ()); }
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -157,6 +157,8 @@
}
}
+ unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
+
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat1.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -103,12 +103,50 @@
const Coverage &get_coverage () const { return this+coverage; }
- bool apply (hb_ot_apply_context_t *c) const
+ unsigned cache_cost () const
{
+ 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:
+ {
+ hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_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:
+ return nullptr;
+ case hb_ot_lookup_cache_op_t::DESTROY:
+ {
+ hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
+ hb_free (cache);
+ return nullptr;
+ }
+ }
+ 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
+ {
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;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache);
+#else
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+#endif
+ if (index == NOT_COVERED) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx);
@@ -156,7 +194,7 @@
strip = true;
newFormats = compute_effective_value_formats (glyphset, strip, true);
}
-
+
out->valueFormat[0] = newFormats.first;
out->valueFormat[1] = newFormats.second;
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -123,12 +123,61 @@
const Coverage &get_coverage () const { return this+coverage; }
- bool apply (hb_ot_apply_context_t *c) const
+ struct pair_pos_cache_t
{
+ hb_ot_lookup_cache_t coverage;
+ hb_ot_lookup_cache_t first;
+ hb_ot_lookup_cache_t second;
+ };
+
+ unsigned cache_cost () const
+ {
+ 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:
+ {
+ pair_pos_cache_t *cache = (pair_pos_cache_t *) hb_malloc (sizeof (pair_pos_cache_t));
+ if (likely (cache))
+ {
+ cache->coverage.clear ();
+ cache->first.clear ();
+ cache->second.clear ();
+ }
+ return cache;
+ }
+ case hb_ot_lookup_cache_op_t::ENTER:
+ return (void *) true;
+ case hb_ot_lookup_cache_op_t::LEAVE:
+ return nullptr;
+ case hb_ot_lookup_cache_op_t::DESTROY:
+ {
+ pair_pos_cache_t *cache = (pair_pos_cache_t *) p;
+ hb_free (cache);
+ return nullptr;
+ }
+ }
+ 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
+ {
TRACE_APPLY (this);
+
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;
+ 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);
- if (likely (index == NOT_COVERED)) return_trace (false);
+#endif
+ if (index == NOT_COVERED) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx);
@@ -139,8 +188,13 @@
return_trace (false);
}
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint, cache ? &cache->first : nullptr);
+ unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint, cache ? &cache->second : nullptr);
+#else
unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
+#endif
if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
{
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -67,7 +67,7 @@
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -66,7 +66,7 @@
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
if (unlikely (index >= valueCount)) return_trace (false);
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/AlternateSubstFormat1.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/AlternateSubstFormat1.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -74,7 +74,7 @@
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
return_trace ((this+alternateSet[index]).apply (c));
}
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/LigatureSubstFormat1.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -78,12 +78,49 @@
return lig_set.would_apply (c);
}
- bool apply (hb_ot_apply_context_t *c) const
+ unsigned cache_cost () const
{
+ 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:
+ {
+ hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_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:
+ return nullptr;
+ case hb_ot_lookup_cache_op_t::DESTROY:
+ {
+ hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
+ hb_free (cache);
+ return nullptr;
+ }
+ }
+ 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
+ {
TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache);
+#else
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+#endif
+ if (index == NOT_COVERED) return_trace (false);
const auto &lig_set = this+ligatureSet[index];
return_trace (lig_set.apply (c));
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/MultipleSubstFormat1.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/MultipleSubstFormat1.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -66,7 +66,7 @@
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
return_trace ((this+sequence[index]).apply (c));
}
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -112,7 +112,7 @@
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
return_trace (false); /* No chaining to this type */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/SingleSubstFormat1.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/SingleSubstFormat1.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/SingleSubstFormat1.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -128,7 +128,7 @@
TRACE_APPLY (this);
hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
unsigned int index = (this+coverage).get_coverage (glyph_id);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
hb_codepoint_t d = deltaGlyphID;
hb_codepoint_t mask = get_mask ();
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/SingleSubstFormat2.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/SingleSubstFormat2.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/SingleSubstFormat2.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -104,7 +104,7 @@
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
if (unlikely (index >= substitute.len)) return_trace (false);
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/types.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -29,6 +29,9 @@
#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, "");
+
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -3,7 +3,6 @@
#ifndef HB_NO_VAR_COMPOSITES
#include "../../../hb-draw.hh"
-#include "../../../hb-geometry.hh"
#include "../../../hb-ot-layout-common.hh"
#include "../../../hb-ot-layout-gdef-table.hh"
@@ -133,18 +132,19 @@
hb_codepoint_t parent_gid,
hb_draw_session_t &draw_session,
hb_array_t<const int> coords,
+ hb_transform_t total_transform,
hb_ubytes_t total_record,
- hb_set_t *visited,
+ hb_decycler_t *decycler,
signed *edges_left,
signed depth_left,
+ hb_glyf_scratch_t &scratch,
VarRegionList::cache_t *cache) const
{
const unsigned char *end = total_record.arrayZ + total_record.length;
const unsigned char *record = total_record.arrayZ;
- auto &VARC = *font->face->table.VARC;
+ auto &VARC = *font->face->table.VARC->table;
auto &varStore = &VARC+VARC.varStore;
- auto instancer = MultiItemVarStoreInstancer(&varStore, nullptr, coords, cache);
#define READ_UINT32VAR(name) \
HB_STMT_START { \
@@ -187,22 +187,25 @@
unsigned conditionIndex;
READ_UINT32VAR (conditionIndex);
const auto &condition = (&VARC+VARC.conditionList)[conditionIndex];
+ auto instancer = MultiItemVarStoreInstancer(&varStore, nullptr, coords, cache);
show = condition.evaluate (coords.arrayZ, coords.length, &instancer);
}
// Axis values
- hb_vector_t<unsigned> axisIndices;
- hb_vector_t<float> axisValues;
+ auto &axisIndices = scratch.axisIndices;
+ axisIndices.clear ();
+ auto &axisValues = scratch.axisValues;
+ axisValues.clear ();
if (flags & (unsigned) flags_t::HAVE_AXES)
{
unsigned axisIndicesIndex;
READ_UINT32VAR (axisIndicesIndex);
- axisIndices = (&VARC+VARC.axisIndicesList)[axisIndicesIndex];
+ axisIndices.extend ((&VARC+VARC.axisIndicesList)[axisIndicesIndex]);
axisValues.resize (axisIndices.length);
const HBUINT8 *p = (const HBUINT8 *) record;
TupleValues::decompile (p, axisValues, (const HBUINT8 *) end);
- record += (const unsigned char *) p - record;
+ record = (const unsigned char *) p;
}
// Apply variations if any
@@ -312,32 +315,87 @@
if (!(flags & (unsigned) flags_t::HAVE_SCALE_Y))
transform.scaleY = transform.scaleX;
- // Scale the transform by the font's scale
- float x_scale = font->x_multf;
- float y_scale = font->y_multf;
- transform.translateX *= x_scale;
- transform.translateY *= y_scale;
- transform.tCenterX *= x_scale;
- transform.tCenterY *= y_scale;
+ total_transform.transform (transform.to_transform ());
+ total_transform.scale (font->x_mult ? 1.f / font->x_multf : 0.f,
+ font->y_mult ? 1.f / font->y_multf : 0.f);
+ VARC.get_path_at (font, gid,
+ draw_session, component_coords, total_transform,
+ parent_gid,
+ decycler, edges_left, depth_left - 1,
+ scratch);
+ }
+
+#undef PROCESS_TRANSFORM_COMPONENTS
+#undef READ_UINT32VAR
+
+ return hb_ubytes_t (record, end - record);
+}
+
+bool
+VARC::get_path_at (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_session_t &draw_session,
+ hb_array_t<const int> coords,
+ hb_transform_t transform,
+ hb_codepoint_t parent_glyph,
+ hb_decycler_t *decycler,
+ signed *edges_left,
+ signed depth_left,
+ hb_glyf_scratch_t &scratch) const
+{
+ // Don't recurse on the same glyph.
+ unsigned idx = glyph == parent_glyph ?
+ NOT_COVERED :
+ (this+coverage).get_coverage (glyph);
+ if (idx == NOT_COVERED)
+ {
// Build a transforming pen to apply the transform.
hb_draw_funcs_t *transformer_funcs = hb_transforming_pen_get_funcs ();
- hb_transforming_pen_context_t context {transform.to_transform (),
+ hb_transforming_pen_context_t context {transform,
draw_session.funcs,
draw_session.draw_data,
&draw_session.st};
hb_draw_session_t transformer_session {transformer_funcs, &context};
+ hb_draw_session_t &shape_draw_session = transform.is_identity () ? draw_session : transformer_session;
- VARC.get_path_at (font, gid,
- transformer_session, component_coords,
- parent_gid,
- visited, edges_left, depth_left - 1);
+ if (!font->face->table.glyf->get_path_at (font, glyph, shape_draw_session, coords, scratch))
+#ifndef HB_NO_CFF
+ if (!font->face->table.cff2->get_path_at (font, glyph, shape_draw_session, coords))
+ if (!font->face->table.cff1->get_path (font, glyph, shape_draw_session)) // Doesn't have variations
+#endif
+ return false;
+ return true;
}
-#undef PROCESS_TRANSFORM_COMPONENTS
-#undef READ_UINT32VAR
+ if (depth_left <= 0)
+ return true;
- return hb_ubytes_t (record, end - record);
+ if (*edges_left <= 0)
+ return true;
+ (*edges_left)--;
+
+ hb_decycler_node_t node (*decycler);
+ if (unlikely (!node.visit (glyph)))
+ return true;
+
+ hb_ubytes_t record = (this+glyphRecords)[idx];
+
+ float static_cache[sizeof (void *) * 16];
+ VarRegionList::cache_t *cache = (this+varStore).create_cache (hb_array (static_cache));
+
+ transform.scale (font->x_multf, font->y_multf);
+
+ VarCompositeGlyph::get_path_at (font, glyph,
+ draw_session, coords, transform,
+ record,
+ decycler, edges_left, depth_left,
+ scratch,
+ cache);
+
+ (this+varStore).destroy_cache (cache, hb_array (static_cache));
+
+ return true;
}
//} // namespace Var
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1,6 +1,8 @@
#ifndef OT_VAR_VARC_VARC_HH
#define OT_VAR_VARC_VARC_HH
+#include "../../../hb-decycler.hh"
+#include "../../../hb-geometry.hh"
#include "../../../hb-ot-layout-common.hh"
#include "../../../hb-ot-glyf-table.hh"
#include "../../../hb-ot-cff2-table.hh"
@@ -46,10 +48,12 @@
hb_codepoint_t parent_gid,
hb_draw_session_t &draw_session,
hb_array_t<const int> coords,
+ hb_transform_t transform,
hb_ubytes_t record,
- hb_set_t *visited,
+ hb_decycler_t *decycler,
signed *edges_left,
signed depth_left,
+ hb_glyf_scratch_t &scratch,
VarRegionList::cache_t *cache = nullptr) const;
};
@@ -60,10 +64,12 @@
hb_codepoint_t glyph,
hb_draw_session_t &draw_session,
hb_array_t<const int> coords,
+ hb_transform_t transform,
hb_ubytes_t record,
- hb_set_t *visited,
+ hb_decycler_t *decycler,
signed *edges_left,
signed depth_left,
+ hb_glyf_scratch_t &scratch,
VarRegionList::cache_t *cache = nullptr)
{
while (record)
@@ -70,9 +76,9 @@
{
const VarComponent &comp = * (const VarComponent *) (record.arrayZ);
record = comp.get_path_at (font, glyph,
- draw_session, coords,
+ draw_session, coords, transform,
record,
- visited, edges_left, depth_left, cache);
+ decycler, edges_left, depth_left, scratch, cache);
}
}
};
@@ -85,79 +91,37 @@
static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C');
- bool
+ HB_INTERNAL bool
get_path_at (hb_font_t *font,
hb_codepoint_t glyph,
hb_draw_session_t &draw_session,
hb_array_t<const int> coords,
- hb_codepoint_t parent_glyph = HB_CODEPOINT_INVALID,
- hb_set_t *visited = nullptr,
- signed *edges_left = nullptr,
- signed depth_left = HB_MAX_NESTING_LEVEL) const
- {
- hb_set_t stack_set;
- if (visited == nullptr)
- visited = &stack_set;
- signed stack_edges = HB_MAX_GRAPH_EDGE_COUNT;
- if (edges_left == nullptr)
- edges_left = &stack_edges;
+ hb_transform_t transform,
+ hb_codepoint_t parent_glyph,
+ hb_decycler_t *decycler,
+ signed *edges_left,
+ signed depth_left,
+ hb_glyf_scratch_t &scratch) const;
- // Don't recurse on the same glyph.
- unsigned idx = glyph == parent_glyph ?
- NOT_COVERED :
- (this+coverage).get_coverage (glyph);
- if (idx == NOT_COVERED)
- {
- if (!font->face->table.glyf->get_path_at (font, glyph, draw_session, coords))
-#ifndef HB_NO_CFF
- if (!font->face->table.cff2->get_path_at (font, glyph, draw_session, coords))
- if (!font->face->table.cff1->get_path (font, glyph, draw_session)) // Doesn't have variations
-#endif
- return false;
- return true;
- }
-
- if (depth_left <= 0)
- return true;
-
- if (*edges_left <= 0)
- return true;
- (*edges_left)--;
-
- if (visited->has (glyph) || visited->in_error ())
- return true;
- visited->add (glyph);
-
- hb_ubytes_t record = (this+glyphRecords)[idx];
-
- VarRegionList::cache_t *cache = record.length >= 64 ? // Heuristic
- (this+varStore).create_cache ()
- : nullptr;
-
- VarCompositeGlyph::get_path_at (font, glyph,
- draw_session, coords,
- record,
- visited, edges_left, depth_left,
- cache);
-
- (this+varStore).destroy_cache (cache);
-
- visited->del (glyph);
-
- return true;
- }
-
bool
- get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
- { return get_path_at (font, gid, draw_session, hb_array (font->coords, font->num_coords)); }
-
- bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
+ get_path (hb_font_t *font,
+ hb_codepoint_t gid,
+ hb_draw_session_t &draw_session,
+ hb_glyf_scratch_t &scratch) const
{
- funcs->push_clip_glyph (data, gid, font);
- funcs->color (data, true, foreground);
- funcs->pop_clip (data);
+ hb_decycler_t decycler;
+ signed edges = HB_MAX_GRAPH_EDGE_COUNT;
- return true;
+ return get_path_at (font,
+ gid,
+ draw_session,
+ hb_array (font->coords, font->num_coords),
+ HB_TRANSFORM_IDENTITY,
+ HB_CODEPOINT_INVALID,
+ &decycler,
+ &edges,
+ HB_MAX_NESTING_LEVEL,
+ scratch);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -173,6 +137,63 @@
glyphRecords.sanitize (c, this));
}
+ struct accelerator_t
+ {
+ friend struct VarComponent;
+
+ accelerator_t (hb_face_t *face)
+ {
+ table = hb_sanitize_context_t ().reference_table<VARC> (face);
+ }
+ ~accelerator_t ()
+ {
+ auto *scratch = cached_scratch.get_relaxed ();
+ if (scratch)
+ {
+ scratch->~hb_glyf_scratch_t ();
+ hb_free (scratch);
+ }
+
+ table.destroy ();
+ }
+
+ bool
+ get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
+ {
+ if (!table->has_data ()) return false;
+
+ hb_glyf_scratch_t *scratch;
+
+ // Borrow the cached strach buffer.
+ {
+ scratch = cached_scratch.get_acquire ();
+ if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
+ {
+ scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t));
+ if (unlikely (!scratch))
+ return true;
+ }
+ }
+
+ bool ret = table->get_path (font, gid, draw_session, *scratch);
+
+ // Put it back.
+ if (!cached_scratch.cmpexch (nullptr, scratch))
+ {
+ scratch->~hb_glyf_scratch_t ();
+ hb_free (scratch);
+ }
+
+ return ret;
+ }
+
+ private:
+ hb_blob_ptr_t<VARC> table;
+ hb_atomic_ptr_t<hb_glyf_scratch_t> cached_scratch;
+ };
+
+ bool has_data () const { return version.major != 0; }
+
protected:
FixedVersion<> version; /* Version identifier */
Offset32To<Coverage> coverage;
@@ -184,6 +205,10 @@
DEFINE_SIZE_STATIC (24);
};
+struct VARC_accelerator_t : VARC::accelerator_t {
+ VARC_accelerator_t (hb_face_t *face) : VARC::accelerator_t (face) {}
+};
+
#endif
//}
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/coord-setter.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/coord-setter.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/coord-setter.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -11,22 +11,48 @@
struct coord_setter_t
{
- coord_setter_t (hb_array_t<const int> coords) :
- coords (coords) {}
+ coord_setter_t (hb_array_t<const int> coords_)
+ {
+ length = coords_.length;
+ if (length <= ARRAY_LENGTH (static_coords))
+ hb_memcpy (static_coords, coords_.arrayZ, length * sizeof (int));
+ else
+ dynamic_coords.extend (coords_);
+ }
int& operator [] (unsigned idx)
{
if (unlikely (idx >= HB_VAR_COMPOSITE_MAX_AXES))
return Crap(int);
- if (coords.length < idx + 1)
- coords.resize (idx + 1);
- return coords[idx];
+
+ if (length <= ARRAY_LENGTH (static_coords))
+ {
+ if (idx < ARRAY_LENGTH (static_coords))
+ {
+ while (length <= idx)
+ static_coords[length++] = 0;
+ return static_coords[idx];
+ }
+ else
+ dynamic_coords.extend (hb_array (static_coords, length));
+ }
+
+ if (dynamic_coords.length <= idx)
+ {
+ if (unlikely (!dynamic_coords.resize (idx + 1)))
+ return Crap(int);
+ length = idx + 1;
+ }
+ return dynamic_coords.arrayZ[idx];
}
hb_array_t<int> get_coords ()
- { return coords.as_array (); }
+ { return length <= ARRAY_LENGTH (static_coords) ? hb_array (static_coords, length) : dynamic_coords.as_array (); }
- hb_vector_t<int> coords;
+ private:
+ hb_vector_t<int> dynamic_coords;
+ unsigned length;
+ int static_coords[sizeof (void *) * 8];
};
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -143,7 +143,7 @@
float matrix[4];
contour_point_t trans;
get_transformation (matrix, trans);
- if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points
+ if (unlikely (!points.alloc (points.length + 1 + 4))) return false; // For phantom points
points.push (trans);
return true;
}
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -251,7 +251,8 @@
composite_contours_p = nullptr;
}
- if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
+ hb_glyf_scratch_t scratch;
+ if (!get_points (font, glyf, all_points, scratch, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
return false;
// .notdef, set type to empty so we only update metrics and don't compile bytes for
@@ -305,6 +306,7 @@
template <typename accelerator_t>
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
contour_point_vector_t &all_points /* OUT */,
+ hb_glyf_scratch_t &scratch,
contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
unsigned *composite_contours = nullptr, /* OUT */
@@ -312,7 +314,6 @@
bool use_my_metrics = true,
bool phantom_only = false,
hb_array_t<const int> coords = hb_array_t<const int> (),
- hb_map_t *current_glyphs = nullptr,
unsigned int depth = 0,
unsigned *edge_count = nullptr) const
{
@@ -322,10 +323,6 @@
if (unlikely (*edge_count > HB_MAX_GRAPH_EDGE_COUNT)) return false;
(*edge_count)++;
- hb_map_t current_glyphs_stack;
- if (current_glyphs == nullptr)
- current_glyphs = ¤t_glyphs_stack;
-
if (head_maxp_info)
{
head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
@@ -334,8 +331,7 @@
if (!coords)
coords = hb_array (font->coords, font->num_coords);
- contour_point_vector_t stack_points;
- contour_point_vector_t &points = type == SIMPLE ? all_points : stack_points;
+ contour_point_vector_t &points = type == SIMPLE ? all_points : scratch.comp_points;
unsigned old_length = points.length;
switch (type) {
@@ -388,37 +384,54 @@
#ifndef HB_NO_VAR
if (coords)
- glyf_accelerator.gvar->apply_deltas_to_points (gid,
- coords,
- points.as_array ().sub_array (old_length),
- phantom_only && type == SIMPLE);
+ {
+#ifndef HB_NO_BEYOND_64K
+ if (glyf_accelerator.GVAR->has_data ())
+ glyf_accelerator.GVAR->apply_deltas_to_points (gid,
+ coords,
+ points.as_array ().sub_array (old_length),
+ scratch,
+ phantom_only && type == SIMPLE);
+ else
#endif
+ glyf_accelerator.gvar->apply_deltas_to_points (gid,
+ coords,
+ points.as_array ().sub_array (old_length),
+ scratch,
+ phantom_only && type == SIMPLE);
+ }
+#endif
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
// with child glyphs' points
if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
{
- if (unlikely (!points_with_deltas->resize (points.length))) return false;
+ assert (old_length == 0);
*points_with_deltas = points;
}
+ float shift = 0;
switch (type) {
case SIMPLE:
if (depth == 0 && head_maxp_info)
head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, all_points.length - old_length - 4);
+ shift = phantoms[PHANTOM_LEFT].x;
break;
case COMPOSITE:
{
+ hb_decycler_node_t decycler_node (scratch.decycler);
+
unsigned int comp_index = 0;
for (auto &item : get_composite_iterator ())
{
hb_codepoint_t item_gid = item.get_gid ();
- if (unlikely (current_glyphs->has (item_gid)))
+ if (unlikely (!decycler_node.visit (item_gid)))
+ {
+ comp_index++;
continue;
+ }
- current_glyphs->add (item_gid);
-
unsigned old_count = all_points.length;
if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) &&
@@ -426,6 +439,7 @@
.get_points (font,
glyf_accelerator,
all_points,
+ scratch,
points_with_deltas,
head_maxp_info,
composite_contours,
@@ -433,14 +447,16 @@
use_my_metrics,
phantom_only,
coords,
- current_glyphs,
depth + 1,
edge_count)))
{
- current_glyphs->del (item_gid);
+ points.resize (old_length);
return false;
}
+ // points might have been reallocated. Relocate phantoms.
+ phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
+
auto comp_points = all_points.as_array ().sub_array (old_count);
/* Copy phantom points from component if USE_MY_METRICS flag set */
@@ -455,7 +471,7 @@
item.get_transformation (matrix, default_trans);
/* Apply component transformation & translation (with deltas applied) */
- item.transform_points (comp_points, matrix, points[comp_index]);
+ item.transform_points (comp_points, matrix, points[old_length + comp_index]);
}
if (item.is_anchored () && !phantom_only)
@@ -476,12 +492,11 @@
if (all_points.length > HB_GLYF_MAX_POINTS)
{
- current_glyphs->del (item_gid);
+ points.resize (old_length);
return false;
}
comp_index++;
- current_glyphs->del (item_gid);
}
if (head_maxp_info && depth == 0)
@@ -492,9 +507,13 @@
head_maxp_info->maxComponentElements = hb_max (head_maxp_info->maxComponentElements, comp_index);
}
all_points.extend (phantoms);
+ shift = phantoms[PHANTOM_LEFT].x;
+ points.resize (old_length);
} break;
case EMPTY:
all_points.extend (phantoms);
+ shift = phantoms[PHANTOM_LEFT].x;
+ points.resize (old_length);
break;
}
@@ -503,10 +522,9 @@
/* Undocumented rasterizer behavior:
* Shift points horizontally by the updated left side bearing
*/
- float v = -phantoms[PHANTOM_LEFT].x;
- if (v)
+ if (shift)
for (auto &point : all_points)
- point.x += v;
+ point.x -= shift;
}
return !all_points.in_error ();
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -127,12 +127,13 @@
hb_array_t<contour_point_t> points_ /* IN/OUT */,
const HBUINT8 *end)
{
+ auto *points = points_.arrayZ;
unsigned count = points_.length;
for (unsigned int i = 0; i < count;)
{
if (unlikely (p + 1 > end)) return false;
uint8_t flag = *p++;
- points_.arrayZ[i++].flag = flag;
+ points[i++].flag = flag;
if (flag & FLAG_REPEAT)
{
if (unlikely (p + 1 > end)) return false;
@@ -139,7 +140,7 @@
unsigned int repeat_count = *p++;
unsigned stop = hb_min (i + repeat_count, count);
for (; i < stop; i++)
- points_.arrayZ[i].flag = flag;
+ points[i].flag = flag;
}
}
return true;
@@ -160,10 +161,7 @@
if (flag & short_flag)
{
if (unlikely (p + 1 > end)) return false;
- if (flag & same_flag)
- v += *p++;
- else
- v -= *p++;
+ v += (bool(flag & same_flag) * 2 - 1) * *p++;
}
else
{
@@ -190,7 +188,7 @@
unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
unsigned old_length = points.length;
- points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy
+ points.alloc (points.length + num_points + 4); // Allocate for phantom points, to avoid a possible copy
if (unlikely (!points.resize (points.length + num_points, false))) return false;
auto points_ = points.as_array ().sub_array (old_length);
if (!phantom_only)
@@ -281,9 +279,9 @@
unsigned num_points = all_points.length - 4;
hb_vector_t<uint8_t> flags, x_coords, y_coords;
- if (unlikely (!flags.alloc (num_points, true))) return false;
- if (unlikely (!x_coords.alloc (2*num_points, true))) return false;
- if (unlikely (!y_coords.alloc (2*num_points, true))) return false;
+ if (unlikely (!flags.alloc_exact (num_points))) return false;
+ if (unlikely (!x_coords.alloc_exact (2*num_points))) return false;
+ if (unlikely (!y_coords.alloc_exact (2*num_points))) return false;
unsigned lastflag = 255, repeat = 0;
int prev_x = 0, prev_y = 0;
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -94,7 +94,7 @@
}
hb_vector_t<unsigned> padded_offsets;
- if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true)))
+ if (unlikely (!padded_offsets.alloc_exact (c->plan->new_to_old_gid_list.length)))
return_trace (false);
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
@@ -172,7 +172,10 @@
glyf_table = nullptr;
#ifndef HB_NO_VAR
gvar = nullptr;
+#ifndef HB_NO_BEYOND_64K
+ GVAR = nullptr;
#endif
+#endif
hmtx = nullptr;
#ifndef HB_NO_VERTICAL
vmtx = nullptr;
@@ -187,7 +190,10 @@
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
#ifndef HB_NO_VAR
gvar = face->table.gvar;
+#ifndef HB_NO_BEYOND_64K
+ GVAR = face->table.GVAR;
#endif
+#endif
hmtx = face->table.hmtx;
#ifndef HB_NO_VERTICAL
vmtx = face->table.vmtx;
@@ -198,6 +204,13 @@
}
~glyf_accelerator_t ()
{
+ auto *scratch = cached_scratch.get_relaxed ();
+ if (scratch)
+ {
+ scratch->~hb_glyf_scratch_t ();
+ hb_free (scratch);
+ }
+
glyf_table.destroy ();
}
@@ -206,21 +219,16 @@
protected:
template<typename T>
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer,
- hb_array_t<const int> coords = hb_array_t<const int> ()) const
+ hb_array_t<const int> coords,
+ hb_glyf_scratch_t &scratch) const
{
- if (!coords)
- coords = hb_array (font->coords, font->num_coords);
-
if (gid >= num_glyphs) return false;
- /* Making this allocfree is not that easy
- https://github.com/harfbuzz/harfbuzz/issues/2095
- mostly because of gvar handling in VF fonts,
- perhaps a separate path for non-VF fonts can be considered */
- contour_point_vector_t all_points;
+ auto &all_points = scratch.all_points;
+ all_points.resize (0);
bool phantom_only = !consumer.is_consuming_contour_points ();
- if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only, coords)))
+ if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, scratch, nullptr, nullptr, nullptr, true, true, phantom_only, coords)))
return false;
unsigned count = all_points.length;
@@ -229,8 +237,61 @@
if (consumer.is_consuming_contour_points ())
{
- for (auto &point : all_points.as_array ().sub_array (0, count))
- consumer.consume_point (point);
+ auto *points = all_points.arrayZ;
+
+ if (false)
+ {
+ /* Our path-builder was designed to work with this simple loop.
+ * But FreeType and CoreText do it differently, so we match those
+ * with the other, more complicated, code branch below. */
+ for (unsigned i = 0; i < count; i++)
+ {
+ consumer.consume_point (points[i]);
+ if (points[i].is_end_point)
+ consumer.contour_end ();
+ }
+ }
+ else
+ {
+ for (unsigned i = 0; i < count; i++)
+ {
+ // Start of a contour.
+ if (points[i].flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE)
+ {
+ // First point is on-curve. Draw the contour.
+ for (; i < count; i++)
+ {
+ consumer.consume_point (points[i]);
+ if (points[i].is_end_point)
+ {
+ consumer.contour_end ();
+ break;
+ }
+ }
+ }
+ else
+ {
+ unsigned start = i;
+
+ // Find end of the contour.
+ for (; i < count; i++)
+ if (points[i].is_end_point)
+ break;
+
+ unsigned end = i;
+
+ // Enough to start from the end. Our path-builder takes care of the rest.
+ if (likely (end < count)) // Can only fail in case of alloc failure *maybe*.
+ consumer.consume_point (points[end]);
+
+ for (i = start; i < end; i++)
+ consumer.consume_point (points[i]);
+
+ consumer.contour_end ();
+ }
+ }
+ }
+
consumer.points_end ();
}
@@ -303,6 +364,7 @@
HB_ALWAYS_INLINE
void consume_point (const contour_point_t &point) { bounds.add (point); }
+ void contour_end () {}
void points_end () { bounds.get_extents (font, extents, scaled); }
bool is_consuming_contour_points () { return extents; }
@@ -318,7 +380,12 @@
contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
if (font->num_coords)
- success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false));
+ {
+ hb_glyf_scratch_t scratch;
+ success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false),
+ hb_array (font->coords, font->num_coords),
+ scratch);
+ }
if (unlikely (!success))
return
@@ -338,9 +405,11 @@
if (unlikely (gid >= num_glyphs)) return false;
hb_glyph_extents_t extents;
-
+ hb_glyf_scratch_t scratch;
contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
- if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false))))
+ if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false),
+ hb_array (font->coords, font->num_coords),
+ scratch)))
return false;
*lsb = is_vertical
@@ -366,20 +435,16 @@
#ifndef HB_NO_VAR
if (font->num_coords)
- return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true));
+ {
+ hb_glyf_scratch_t scratch;
+ return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true),
+ hb_array (font->coords, font->num_coords),
+ scratch);
+ }
#endif
return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
}
- bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
- {
- funcs->push_clip_glyph (data, gid, font);
- funcs->color (data, true, foreground);
- funcs->pop_clip (data);
-
- return true;
- }
-
const glyf_impl::Glyph
glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
{
@@ -410,16 +475,53 @@
bool
get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
- { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); }
+ {
+ if (!has_data ()) return false;
+ hb_glyf_scratch_t *scratch;
+
+ // Borrow the cached strach buffer.
+ {
+ scratch = cached_scratch.get_acquire ();
+ if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
+ {
+ scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t));
+ if (unlikely (!scratch))
+ return true;
+ }
+ }
+
+ bool ret = get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
+ hb_array (font->coords, font->num_coords),
+ *scratch);
+
+ // Put it back.
+ if (!cached_scratch.cmpexch (nullptr, scratch))
+ {
+ scratch->~hb_glyf_scratch_t ();
+ hb_free (scratch);
+ }
+
+ return ret;
+ }
+
bool
get_path_at (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session,
- hb_array_t<const int> coords) const
- { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session), coords); }
+ hb_array_t<const int> coords,
+ hb_glyf_scratch_t &scratch) const
+ {
+ if (!has_data ()) return false;
+ return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
+ coords,
+ scratch);
+ }
#ifndef HB_NO_VAR
const gvar_accelerator_t *gvar;
+#ifndef HB_NO_BEYOND_64K
+ const GVAR_accelerator_t *GVAR;
#endif
+#endif
const hmtx_accelerator_t *hmtx;
#ifndef HB_NO_VERTICAL
const vmtx_accelerator_t *vmtx;
@@ -430,6 +532,7 @@
unsigned int num_glyphs;
hb_blob_ptr_t<loca> loca_table;
hb_blob_ptr_t<glyf> glyf_table;
+ hb_atomic_ptr_t<hb_glyf_scratch_t> cached_scratch;
};
@@ -439,7 +542,7 @@
hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
{
OT::glyf_accelerator_t glyf (plan->source);
- if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false;
+ if (!glyphs.alloc_exact (plan->new_to_old_gid_list.length)) return false;
for (const auto &pair : plan->new_to_old_gid_list)
{
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -42,7 +42,7 @@
{
bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
#ifdef HB_NO_CUBIC_GLYF
- bool is_cubic = false;
+ constexpr bool is_cubic = false;
#else
bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
#endif
@@ -124,58 +124,60 @@
}
}
- if (unlikely (point.is_end_point))
+ }
+
+ void contour_end ()
+ {
+ if (first_offcurve && last_offcurve)
{
- if (first_offcurve && last_offcurve)
- {
- optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
- first_offcurve2 :
- first_offcurve);
- if (last_offcurve2)
- draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
- last_offcurve.x, last_offcurve.y,
- mid.x, mid.y);
- else
- draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
- mid.x, mid.y);
- last_offcurve = optional_point_t ();
- }
- /* now check the rest */
+ optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
+ first_offcurve2 :
+ first_offcurve);
+ if (last_offcurve2)
+ draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+ last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ else
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve = optional_point_t ();
+ }
+ /* now check the rest */
- if (first_offcurve && first_oncurve)
- {
- if (first_offcurve2)
- draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
- first_offcurve.x, first_offcurve.y,
- first_oncurve.x, first_oncurve.y);
- else
- draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
- first_oncurve.x, first_oncurve.y);
- }
- else if (last_offcurve && first_oncurve)
- {
- if (last_offcurve2)
- draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
- last_offcurve.x, last_offcurve.y,
- first_oncurve.x, first_oncurve.y);
- else
- draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
- first_oncurve.x, first_oncurve.y);
- }
- else if (first_oncurve)
- draw_session->line_to (first_oncurve.x, first_oncurve.y);
- else if (first_offcurve)
- {
- float x = first_offcurve.x, y = first_offcurve.y;
- draw_session->move_to (x, y);
- draw_session->quadratic_to (x, y, x, y);
- }
+ if (first_offcurve && first_oncurve)
+ {
+ if (first_offcurve2)
+ draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
+ first_offcurve.x, first_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else
+ draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ }
+ else if (last_offcurve && first_oncurve)
+ {
+ if (last_offcurve2)
+ draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+ last_offcurve.x, last_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ }
+ else if (first_oncurve)
+ draw_session->line_to (first_oncurve.x, first_oncurve.y);
+ else if (first_offcurve)
+ {
+ float x = first_offcurve.x, y = first_offcurve.y;
+ draw_session->move_to (x, y);
+ draw_session->quadratic_to (x, y, x, y);
+ }
- /* Getting ready for the next contour */
- first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
- draw_session->close_path ();
- }
+ /* Getting ready for the next contour */
+ first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
+ draw_session->close_path ();
}
+
void points_end () {}
bool is_consuming_contour_points () { return true; }
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -163,7 +163,7 @@
if (platformID != 1)
{
unsigned text_size = hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, nullptr, nullptr);
-
+
text_size++; // needs to consider NULL terminator for use in hb_ot_name_convert_utf()
unsigned byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
name_str_utf16_be = (char *) hb_calloc (byte_len, 1);
@@ -174,7 +174,7 @@
}
hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, &text_size,
(hb_utf16_be_t::codepoint_t *) name_str_utf16_be);
-
+
unsigned encoded_byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
if (!encoded_byte_len || !c->check_assign (out->length, encoded_byte_len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
c->revert (snap);
@@ -181,7 +181,7 @@
hb_free (name_str_utf16_be);
return_trace (nullptr);
}
-
+
encoded_bytes = hb_bytes_t (name_str_utf16_be, encoded_byte_len);
}
else
@@ -392,7 +392,7 @@
const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides =
&c->plan->name_table_overrides;
#endif
-
+
auto it =
+ nameRecordZ.as_array (count)
| hb_filter (c->plan->name_ids, &NameRecord::nameID)
@@ -485,7 +485,7 @@
const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
this->table->count);
- this->names.alloc (all_names.length, true);
+ this->names.alloc_exact (all_names.length);
for (unsigned int i = 0; i < all_names.length; i++)
{
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py 2025-03-08 22:22:06 UTC (rev 74540)
@@ -172,7 +172,7 @@
print ('_output_dotted_circle (hb_buffer_t *buffer)')
print ('{')
print (' (void) buffer->output_glyph (0x25CCu);')
-print (' _hb_glyph_info_reset_continuation (&buffer->prev());')
+print (' _hb_glyph_info_clear_continuation (&buffer->prev());')
print ('}')
print ()
print ('static void')
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -30,7 +30,11 @@
#include "hb-aat-layout.hh"
#include "hb-aat-map.hh"
#include "hb-open-type.hh"
+#include "hb-cache.hh"
+#include "hb-bit-set.hh"
+#include "hb-bit-page.hh"
+
namespace OT {
struct GDEF;
};
@@ -39,10 +43,11 @@
using namespace OT;
-#define HB_AAT_BUFFER_DIGEST_THRESHOLD 32
-
struct ankr;
+using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>;
+static_assert (sizeof (hb_aat_class_cache_t) == 256, "");
+
struct hb_aat_apply_context_t :
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
{
@@ -61,10 +66,12 @@
const ankr *ankr_table;
const OT::GDEF *gdef_table;
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
- hb_set_digest_t buffer_digest = hb_set_digest_t::full ();
- hb_set_digest_t machine_glyph_set = hb_set_digest_t::full ();
- hb_set_digest_t left_set = hb_set_digest_t::full ();
- hb_set_digest_t right_set = hb_set_digest_t::full ();
+ bool using_buffer_glyph_set = false;
+ hb_bit_set_t buffer_glyph_set;
+ const hb_bit_set_t *left_set = nullptr;
+ const hb_bit_set_t *right_set = nullptr;
+ const hb_bit_set_t *machine_glyph_set = nullptr;
+ hb_aat_class_cache_t *machine_class_cache = nullptr;
hb_mask_t subtable_flags = 0;
/* Unused. For debug tracing only. */
@@ -80,6 +87,25 @@
HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
void set_lookup_index (unsigned int i) { lookup_index = i; }
+
+ void setup_buffer_glyph_set ()
+ {
+ using_buffer_glyph_set = buffer->len >= 4;
+
+ if (using_buffer_glyph_set)
+ buffer->collect_codepoints (buffer_glyph_set);
+ }
+ bool buffer_intersects_machine () const
+ {
+ if (using_buffer_glyph_set)
+ return buffer_glyph_set.intersects (*machine_glyph_set);
+
+ // Faster for shorter buffers.
+ for (unsigned i = 0; i < buffer->len; i++)
+ if (machine_glyph_set->has (buffer->info[i].codepoint))
+ return true;
+ return false;
+ }
};
@@ -108,6 +134,13 @@
{
glyphs.add_range (0, num_glyphs - 1);
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
+ {
+ for (unsigned i = 0; i < num_glyphs; i++)
+ if (filter (arrayZ[i]))
+ glyphs.add (i);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -140,10 +173,15 @@
template <typename set_t>
void collect_glyphs (set_t &glyphs) const
{
- if (first == DELETED_GLYPH)
- return;
+ if (first == DELETED_GLYPH) return;
glyphs.add_range (first, last);
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+ {
+ if (!filter (value)) return;
+ glyphs.add_range (first, last);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -182,6 +220,13 @@
for (unsigned int i = 0; i < count; i++)
segments[i].collect_glyphs (glyphs);
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+ {
+ unsigned count = segments.get_length ();
+ for (unsigned int i = 0; i < count; i++)
+ segments[i].collect_glyphs_filtered (glyphs, filter);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -217,10 +262,17 @@
template <typename set_t>
void collect_glyphs (set_t &glyphs) const
{
- if (first == DELETED_GLYPH)
- return;
+ if (first == DELETED_GLYPH) return;
glyphs.add_range (first, last);
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const
+ {
+ const auto &values = base+valuesZ;
+ for (hb_codepoint_t i = first; i <= last; i++)
+ if (filter (values[i - first]))
+ glyphs.add (i);
+ }
int cmp (hb_codepoint_t g) const
{ return g < first ? -1 : g <= last ? 0 : +1; }
@@ -271,6 +323,13 @@
for (unsigned i = 0; i < count; i++)
segments[i].collect_glyphs (glyphs);
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+ {
+ unsigned count = segments.get_length ();
+ for (unsigned i = 0; i < count; i++)
+ segments[i].collect_glyphs_filtered (glyphs, this, filter);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -303,10 +362,15 @@
template <typename set_t>
void collect_glyphs (set_t &glyphs) const
{
- if (glyph == DELETED_GLYPH)
- return;
+ if (glyph == DELETED_GLYPH) return;
glyphs.add (glyph);
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+ {
+ if (!filter (value)) return;
+ glyphs.add (glyph);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -344,6 +408,13 @@
for (unsigned i = 0; i < count; i++)
entries[i].collect_glyphs (glyphs);
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+ {
+ unsigned count = entries.get_length ();
+ for (unsigned i = 0; i < count; i++)
+ entries[i].collect_glyphs_filtered (glyphs, filter);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -379,12 +450,20 @@
template <typename set_t>
void collect_glyphs (set_t &glyphs) const
{
- if (unlikely (!glyphCount))
- return;
- if (firstGlyph == DELETED_GLYPH)
- return;
+ if (unlikely (!glyphCount)) return;
+ if (firstGlyph == DELETED_GLYPH) return;
glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+ {
+ if (unlikely (!glyphCount)) return;
+ if (firstGlyph == DELETED_GLYPH) return;
+ const T *p = valueArrayZ.arrayZ;
+ for (unsigned i = 0; i < glyphCount; i++)
+ if (filter (p[i]))
+ glyphs.add (firstGlyph + i);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -433,10 +512,8 @@
template <typename set_t>
void collect_glyphs (set_t &glyphs) const
{
- if (unlikely (!glyphCount))
- return;
- if (firstGlyph == DELETED_GLYPH)
- return;
+ if (unlikely (!glyphCount)) return;
+ if (firstGlyph == DELETED_GLYPH) return;
glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
}
@@ -501,6 +578,18 @@
default:return;
}
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
+ {
+ switch (u.format) {
+ case 0: hb_barrier (); u.format0.collect_glyphs_filtered (glyphs, num_glyphs, filter); return;
+ case 2: hb_barrier (); u.format2.collect_glyphs_filtered (glyphs, filter); return;
+ case 4: hb_barrier (); u.format4.collect_glyphs_filtered (glyphs, filter); return;
+ case 6: hb_barrier (); u.format6.collect_glyphs_filtered (glyphs, filter); return;
+ case 8: hb_barrier (); u.format8.collect_glyphs_filtered (glyphs, filter); return;
+ default:return;
+ }
+ }
typename T::type get_class (hb_codepoint_t glyph_id,
unsigned int num_glyphs,
@@ -563,7 +652,7 @@
template <typename T>
struct Entry
{
- // This does seem like it's ever called.
+ // This doesn't seem like it's ever called.
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -632,18 +721,47 @@
{
(this+classTable).collect_glyphs (glyphs, num_glyphs);
}
+ template <typename set_t, typename table_t>
+ void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs, const table_t &table) const
+ {
+ unsigned num_classes = nClasses;
+ if (unlikely (num_classes > hb_bit_page_t::BITS))
+ {
+ (this+classTable).collect_glyphs (glyphs, num_glyphs);
+ return;
+ }
+
+ // Collect all classes going out from the start state.
+ hb_bit_page_t filter;
+
+ for (unsigned i = 0; i < num_classes; i++)
+ {
+ const auto &entry = get_entry (STATE_START_OF_TEXT, i);
+ if (new_state (entry.newState) == STATE_START_OF_TEXT &&
+ !table.is_action_initiable (entry) && !table.is_actionable (entry))
+ continue;
+
+ filter.add (i);
+ }
+
+ // And glyphs in those classes.
+ (this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter);
+ }
+
int new_state (unsigned int newState) const
{ return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
- template <typename set_t>
unsigned int get_class (hb_codepoint_t glyph_id,
unsigned int num_glyphs,
- const set_t &glyphs) const
+ hb_aat_class_cache_t *cache = nullptr) const
{
+ unsigned klass;
+ if (cache && cache->get (glyph_id, &klass)) return klass;
if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
- if (!glyphs[glyph_id]) return CLASS_OUT_OF_BOUNDS;
- return (this+classTable).get_class (glyph_id, num_glyphs, CLASS_OUT_OF_BOUNDS);
+ klass = (this+classTable).get_class (glyph_id, num_glyphs, CLASS_OUT_OF_BOUNDS);
+ if (cache) cache->set (glyph_id, klass);
+ return klass;
}
const Entry<Extra> *get_entries () const
@@ -651,13 +769,14 @@
const Entry<Extra> &get_entry (int state, unsigned int klass) const
{
- if (unlikely (klass >= nClasses))
+ unsigned n_classes = nClasses;
+ if (unlikely (klass >= n_classes))
klass = CLASS_OUT_OF_BOUNDS;
const HBUSHORT *states = (this+stateArrayTable).arrayZ;
const Entry<Extra> *entries = (this+entryTable).arrayZ;
- unsigned int entry = states[state * nClasses + klass];
+ unsigned int entry = states[state * n_classes + klass];
DEBUG_MSG (APPLY, nullptr, "e%u", entry);
return entries[entry];
@@ -803,6 +922,13 @@
if (classArray.arrayZ[i] != CLASS_OUT_OF_BOUNDS)
glyphs.add (firstGlyph + i);
}
+ template <typename set_t, typename filter_t>
+ void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
+ {
+ for (unsigned i = 0; i < classArray.len; i++)
+ if (filter (classArray.arrayZ[i]))
+ glyphs.add (firstGlyph + i);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -918,7 +1044,7 @@
}
};
-template <typename Types, typename EntryData>
+template <typename Types, typename EntryData, typename Flags>
struct StateTableDriver
{
using StateTableT = StateTable<Types, EntryData>;
@@ -930,14 +1056,6 @@
num_glyphs (face_->get_num_glyphs ()) {}
template <typename context_t>
- bool is_idempotent_on_all_out_of_bounds (context_t *c, hb_aat_apply_context_t *ac)
- {
- const auto entry = machine.get_entry (StateTableT::STATE_START_OF_TEXT, CLASS_OUT_OF_BOUNDS);
- return !c->is_actionable (ac->buffer, this, entry) &&
- machine.new_state (entry.newState) == StateTableT::STATE_START_OF_TEXT;
- }
-
- template <typename context_t>
void drive (context_t *c, hb_aat_apply_context_t *ac)
{
hb_buffer_t *buffer = ac->buffer;
@@ -977,7 +1095,7 @@
}
unsigned int klass = likely (buffer->idx < buffer->len) ?
- machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_glyph_set) :
+ machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_class_cache) :
(unsigned) CLASS_END_OF_TEXT;
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
const EntryT &entry = machine.get_entry (state, klass);
@@ -1011,41 +1129,36 @@
*
* https://github.com/harfbuzz/harfbuzz/issues/2860
*/
-
- const auto is_safe_to_break_extra = [&]()
- {
- /* 2c. */
- const auto &wouldbe_entry = machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass);
-
- /* 2c'. */
- if (c->is_actionable (buffer, this, wouldbe_entry))
- return false;
-
- /* 2c". */
- return next_state == machine.new_state(wouldbe_entry.newState)
- && (entry.flags & context_t::DontAdvance) == (wouldbe_entry.flags & context_t::DontAdvance);
- };
-
- const auto is_safe_to_break = [&]()
- {
+ const EntryT *wouldbe_entry;
+ bool is_safe_to_break =
+ (
/* 1. */
- if (c->is_actionable (buffer, this, entry))
- return false;
+ !c->table->is_actionable (entry) &&
/* 2. */
// This one is meh, I know...
- const auto ok =
+ (
state == StateTableT::STATE_START_OF_TEXT
- || ((entry.flags & context_t::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT)
- || is_safe_to_break_extra();
- if (!ok)
- return false;
+ || ((entry.flags & Flags::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT)
+ || (
+ /* 2c. */
+ wouldbe_entry = &machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass)
+ ,
+ /* 2c'. */
+ !c->table->is_actionable (*wouldbe_entry) &&
+ /* 2c". */
+ (
+ next_state == machine.new_state(wouldbe_entry->newState) &&
+ (entry.flags & Flags::DontAdvance) == (wouldbe_entry->flags & Flags::DontAdvance)
+ )
+ )
+ ) &&
/* 3. */
- return !c->is_actionable (buffer, this, machine.get_entry (state, CLASS_END_OF_TEXT));
- };
+ !c->table->is_actionable (machine.get_entry (state, CLASS_END_OF_TEXT))
+ );
- if (!is_safe_to_break () && buffer->backtrack_len () && buffer->idx < buffer->len)
+ if (!is_safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
c->transition (buffer, this, entry);
@@ -1056,7 +1169,7 @@
if (buffer->idx == buffer->len || unlikely (!buffer->successful))
break;
- if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
+ if (!(entry.flags & Flags::DontAdvance) || buffer->max_ops-- <= 0)
(void) buffer->next_glyph ();
}
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -112,10 +112,6 @@
if (header.coverage & header.Backwards)
return_trace (false);
- if (!(c->buffer_digest.may_have (c->left_set) &&
- c->buffer_digest.may_have (c->right_set)))
- return_trace (false);
-
accelerator_t accel (*this, c);
hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
machine.kern (c->font, c->buffer, c->plan->kern_mask);
@@ -144,7 +140,7 @@
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{
- if (!c->left_set[left] || !c->right_set[right]) return 0;
+ if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
return table.get_kerning (left, right, c);
}
};
@@ -211,6 +207,9 @@
typedef void EntryData;
+ static bool initiateAction (const Entry<EntryData> &entry)
+ { return entry.flags & Push; }
+
static bool performAction (const Entry<EntryData> &entry)
{ return entry.flags & Offset; }
@@ -227,13 +226,23 @@
typedef Format1Entry<Types::extended> Format1EntryT;
typedef typename Format1EntryT::EntryData EntryData;
+ enum Flags
+ {
+ DontAdvance = Format1EntryT::DontAdvance,
+ };
+
+ bool is_action_initiable (const Entry<EntryData> &entry) const
+ {
+ return Format1EntryT::initiateAction (entry);
+ }
+ bool is_actionable (const Entry<EntryData> &entry) const
+ {
+ return Format1EntryT::performAction (entry);
+ }
+
struct driver_context_t
{
static constexpr bool in_place = true;
- enum
- {
- DontAdvance = Format1EntryT::DontAdvance,
- };
driver_context_t (const KerxSubTableFormat1 *table_,
hb_aat_apply_context_t *c_) :
@@ -246,12 +255,8 @@
depth (0),
crossStream (table->header.coverage & table->header.CrossStream) {}
- bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
- StateTableDriver<Types, EntryData> *driver HB_UNUSED,
- const Entry<EntryData> &entry)
- { return Format1EntryT::performAction (entry); }
void transition (hb_buffer_t *buffer,
- StateTableDriver<Types, EntryData> *driver,
+ StateTableDriver<Types, EntryData, Flags> *driver,
const Entry<EntryData> &entry)
{
unsigned int flags = entry.flags;
@@ -351,9 +356,10 @@
}
}
- private:
+ public:
hb_aat_apply_context_t *c;
const KerxSubTableFormat1 *table;
+ private:
const UnsizedArrayOf<FWORD> &kernAction;
unsigned int stack[8];
unsigned int depth;
@@ -370,13 +376,8 @@
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->font->face);
+ StateTableDriver<Types, EntryData, Flags> driver (machine, c->font->face);
- if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
- !(c->buffer_digest.may_have (c->left_set) &&
- c->buffer_digest.may_have (c->right_set)))
- return_trace (false);
-
driver.drive (&dc, c);
return_trace (true);
@@ -440,10 +441,6 @@
if (header.coverage & header.Backwards)
return_trace (false);
- if (!(c->buffer_digest.may_have (c->left_set) &&
- c->buffer_digest.may_have (c->right_set)))
- return_trace (false);
-
accelerator_t accel (*this, c);
hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
machine.kern (c->font, c->buffer, c->plan->kern_mask);
@@ -469,7 +466,7 @@
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{
- if (!c->left_set[left] || !c->right_set[right]) return 0;
+ if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
return table.get_kerning (left, right, c);
}
};
@@ -513,17 +510,26 @@
DEFINE_SIZE_STATIC (2);
};
+ enum Flags
+ {
+ Mark = 0x8000, /* If set, remember this glyph as the marked glyph. */
+ DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
+ * going to the new state. */
+ Reserved = 0x3FFF, /* Not used; set to 0. */
+ };
+
+ bool is_action_initiable (const Entry<EntryData> &entry) const
+ {
+ return (entry.flags & Mark);
+ }
+ bool is_actionable (const Entry<EntryData> &entry) const
+ {
+ return entry.data.ankrActionIndex != 0xFFFF;
+ }
+
struct driver_context_t
{
static constexpr bool in_place = true;
- enum Flags
- {
- Mark = 0x8000, /* If set, remember this glyph as the marked glyph. */
- DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
- * going to the new state. */
- Reserved = 0x3FFF, /* Not used; set to 0. */
- };
-
enum SubTableFlags
{
ActionType = 0xC0000000, /* A two-bit field containing the action type. */
@@ -533,20 +539,17 @@
* point table. */
};
- driver_context_t (const KerxSubTableFormat4 *table,
+ driver_context_t (const KerxSubTableFormat4 *table_,
hb_aat_apply_context_t *c_) :
c (c_),
+ table (table_),
action_type ((table->flags & ActionType) >> 30),
ankrData ((HBUINT16 *) ((const char *) &table->machine + (table->flags & Offset))),
mark_set (false),
mark (0) {}
- bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
- StateTableDriver<Types, EntryData> *driver HB_UNUSED,
- const Entry<EntryData> &entry)
- { return entry.data.ankrActionIndex != 0xFFFF; }
void transition (hb_buffer_t *buffer,
- StateTableDriver<Types, EntryData> *driver,
+ StateTableDriver<Types, EntryData, Flags> *driver,
const Entry<EntryData> &entry)
{
if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
@@ -634,8 +637,10 @@
}
}
+ public:
+ hb_aat_apply_context_t *c;
+ const KerxSubTableFormat4 *table;
private:
- hb_aat_apply_context_t *c;
unsigned int action_type;
const HBUINT16 *ankrData;
bool mark_set;
@@ -648,13 +653,8 @@
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->font->face);
+ StateTableDriver<Types, EntryData, Flags> driver (machine, c->font->face);
- if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
- !(c->buffer_digest.may_have (c->left_set) &&
- c->buffer_digest.may_have (c->right_set)))
- return_trace (false);
-
driver.drive (&dc, c);
return_trace (true);
@@ -735,10 +735,6 @@
if (header.coverage & header.Backwards)
return_trace (false);
- if (!(c->buffer_digest.may_have (c->left_set) &&
- c->buffer_digest.may_have (c->right_set)))
- return_trace (false);
-
accelerator_t accel (*this, c);
hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
machine.kern (c->font, c->buffer, c->plan->kern_mask);
@@ -793,7 +789,7 @@
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{
- if (!c->left_set[left] || !c->right_set[right]) return 0;
+ if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
return table.get_kerning (left, right, c);
}
};
@@ -925,7 +921,7 @@
* The 'kerx' Table
*/
-using kern_accelerator_data_t = hb_vector_t<hb_pair_t<hb_set_digest_t, hb_set_digest_t>>;
+using kern_accelerator_data_t = hb_vector_t<hb_pair_t<hb_bit_set_t, hb_bit_set_t>>;
template <typename T>
struct KerxTable
@@ -985,15 +981,10 @@
}
bool apply (AAT::hb_aat_apply_context_t *c,
- const kern_accelerator_data_t *accel_data = nullptr) const
+ const kern_accelerator_data_t &accel_data) const
{
c->buffer->unsafe_to_concat ();
- if (c->buffer->len < HB_AAT_BUFFER_DIGEST_THRESHOLD)
- c->buffer_digest = c->buffer->digest ();
- else
- c->buffer_digest = hb_set_digest_t::full ();
-
typedef typename T::SubTable SubTable;
bool ret = false;
@@ -1037,15 +1028,8 @@
if (reverse)
c->buffer->reverse ();
- if (accel_data)
- {
- c->left_set = (*accel_data)[i].first;
- c->right_set = (*accel_data)[i].second;
- }
- else
- {
- c->left_set = c->right_set = hb_set_digest_t::full ();
- }
+ c->left_set = &accel_data[i].first;
+ c->right_set = &accel_data[i].second;
{
/* See comment in sanitize() for conditional here. */
@@ -1122,7 +1106,7 @@
unsigned int count = thiz()->tableCount;
for (unsigned int i = 0; i < count; i++)
{
- hb_set_digest_t left_set, right_set;
+ hb_bit_set_t left_set, right_set;
st->collect_glyphs (left_set, right_set, num_glyphs);
accel_data.push (hb_pair (left_set, right_set));
st = &StructAfter<SubTable> (*st);
@@ -1148,7 +1132,7 @@
bool apply (AAT::hb_aat_apply_context_t *c) const
{
- return table->apply (c, &accel_data);
+ return table->apply (c, accel_data);
}
hb_blob_ptr_t<T> table;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -29,6 +29,7 @@
#include "hb-open-type.hh"
#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-layout-gdef-table.hh"
#include "hb-aat-map.hh"
@@ -53,35 +54,40 @@
typedef void EntryData;
- struct driver_context_t
+ enum Flags
{
- static constexpr bool in_place = true;
- enum Flags
- {
- MarkFirst = 0x8000, /* If set, make the current glyph the first
+ MarkFirst = 0x8000, /* If set, make the current glyph the first
* glyph to be rearranged. */
- DontAdvance = 0x4000, /* If set, don't advance to the next glyph
+ DontAdvance = 0x4000, /* If set, don't advance to the next glyph
* before going to the new state. This means
* that the glyph index doesn't change, even
* if the glyph at that index has changed. */
- MarkLast = 0x2000, /* If set, make the current glyph the last
+ MarkLast = 0x2000, /* If set, make the current glyph the last
* glyph to be rearranged. */
- Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */
- Verb = 0x000F, /* The type of rearrangement specified. */
- };
+ Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */
+ Verb = 0x000F, /* The type of rearrangement specified. */
+ };
- driver_context_t (const RearrangementSubtable *table HB_UNUSED) :
+ bool is_action_initiable (const Entry<EntryData> &entry) const
+ {
+ return (entry.flags & MarkFirst);
+ }
+ bool is_actionable (const Entry<EntryData> &entry) const
+ {
+ return (entry.flags & Verb);
+ }
+
+ struct driver_context_t
+ {
+ static constexpr bool in_place = true;
+
+ driver_context_t (const RearrangementSubtable *table_) :
ret (false),
+ table (table_),
start (0), end (0) {}
- bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
- StateTableDriver<Types, EntryData> *driver HB_UNUSED,
- const Entry<EntryData> &entry) const
- {
- return (entry.flags & Verb) && start < end;
- }
void transition (hb_buffer_t *buffer,
- StateTableDriver<Types, EntryData> *driver,
+ StateTableDriver<Types, EntryData, Flags> *driver,
const Entry<EntryData> &entry)
{
unsigned int flags = entry.flags;
@@ -158,6 +164,7 @@
public:
bool ret;
+ const RearrangementSubtable *table;
private:
unsigned int start;
unsigned int end;
@@ -169,11 +176,13 @@
driver_context_t dc (this);
- StateTableDriver<Types, EntryData> driver (machine, c->face);
+ StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
- if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
- !c->buffer_digest.may_have (c->machine_glyph_set))
+ if (!c->buffer_intersects_machine ())
+ {
+ (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
return_trace (false);
+ }
driver.drive (&dc, c);
@@ -207,39 +216,40 @@
DEFINE_SIZE_STATIC (4);
};
+ enum Flags
+ {
+ SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
+ DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
+ * going to the new state. */
+ Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */
+ };
+
+ bool is_action_initiable (const Entry<EntryData> &entry) const
+ {
+ return (entry.flags & SetMark);
+ }
+ bool is_actionable (const Entry<EntryData> &entry) const
+ {
+ return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
+ }
+
struct driver_context_t
{
static constexpr bool in_place = true;
- enum Flags
- {
- SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
- DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
- * going to the new state. */
- Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */
- };
driver_context_t (const ContextualSubtable *table_,
hb_aat_apply_context_t *c_) :
ret (false),
c (c_),
+ table (table_),
gdef (*c->gdef_table),
mark_set (false),
has_glyph_classes (gdef.has_glyph_classes ()),
mark (0),
- table (table_),
subs (table+table->substitutionTables) {}
- bool is_actionable (hb_buffer_t *buffer,
- StateTableDriver<Types, EntryData> *driver,
- const Entry<EntryData> &entry) const
- {
- if (buffer->idx == buffer->len && !mark_set)
- return false;
-
- return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
- }
void transition (hb_buffer_t *buffer,
- StateTableDriver<Types, EntryData> *driver,
+ StateTableDriver<Types, EntryData, Flags> *driver,
const Entry<EntryData> &entry)
{
/* Looks like CoreText applies neither mark nor current substitution for
@@ -271,8 +281,9 @@
if (replacement)
{
buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
- buffer->info[mark].codepoint = *replacement;
- c->buffer_digest.add (*replacement);
+ hb_codepoint_t glyph = *replacement;
+ buffer->info[mark].codepoint = glyph;
+ c->buffer_glyph_set.add (glyph);
if (has_glyph_classes)
_hb_glyph_info_set_glyph_props (&buffer->info[mark],
gdef.get_glyph_props (*replacement));
@@ -301,8 +312,9 @@
}
if (replacement)
{
- buffer->info[idx].codepoint = *replacement;
- c->buffer_digest.add (*replacement);
+ hb_codepoint_t glyph = *replacement;
+ buffer->info[idx].codepoint = glyph;
+ c->buffer_glyph_set.add (glyph);
if (has_glyph_classes)
_hb_glyph_info_set_glyph_props (&buffer->info[idx],
gdef.get_glyph_props (*replacement));
@@ -318,13 +330,13 @@
public:
bool ret;
+ hb_aat_apply_context_t *c;
+ const ContextualSubtable *table;
private:
- hb_aat_apply_context_t *c;
const OT::GDEF &gdef;
bool mark_set;
bool has_glyph_classes;
unsigned int mark;
- const ContextualSubtable *table;
const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false> &subs;
};
@@ -334,11 +346,13 @@
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->face);
+ StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
- if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
- !c->buffer_digest.may_have (c->machine_glyph_set))
+ if (!c->buffer_intersects_machine ())
+ {
+ (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
return_trace (false);
+ }
driver.drive (&dc, c);
@@ -389,6 +403,16 @@
template <>
struct LigatureEntry<true>
{
+
+ struct EntryData
+ {
+ HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry
+ * for processing this group, if indicated
+ * by the flags. */
+ public:
+ DEFINE_SIZE_STATIC (2);
+ };
+
enum Flags
{
SetComponent = 0x8000, /* Push this glyph onto the component stack for
@@ -400,14 +424,8 @@
Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */
};
- struct EntryData
- {
- HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry
- * for processing this group, if indicated
- * by the flags. */
- public:
- DEFINE_SIZE_STATIC (2);
- };
+ static bool initiateAction (const Entry<EntryData> &entry)
+ { return entry.flags & SetComponent; }
static bool performAction (const Entry<EntryData> &entry)
{ return entry.flags & PerformAction; }
@@ -418,6 +436,8 @@
template <>
struct LigatureEntry<false>
{
+ typedef void EntryData;
+
enum Flags
{
SetComponent = 0x8000, /* Push this glyph onto the component stack for
@@ -429,7 +449,8 @@
* multiple of 4. */
};
- typedef void EntryData;
+ static bool initiateAction (const Entry<EntryData> &entry)
+ { return entry.flags & SetComponent; }
static bool performAction (const Entry<EntryData> &entry)
{ return entry.flags & Offset; }
@@ -447,13 +468,23 @@
typedef LigatureEntry<Types::extended> LigatureEntryT;
typedef typename LigatureEntryT::EntryData EntryData;
+ enum Flags
+ {
+ DontAdvance = LigatureEntryT::DontAdvance,
+ };
+
+ bool is_action_initiable (const Entry<EntryData> &entry) const
+ {
+ return LigatureEntryT::initiateAction (entry);
+ }
+ bool is_actionable (const Entry<EntryData> &entry) const
+ {
+ return LigatureEntryT::performAction (entry);
+ }
+
struct driver_context_t
{
static constexpr bool in_place = false;
- enum
- {
- DontAdvance = LigatureEntryT::DontAdvance,
- };
enum LigActionFlags
{
LigActionLast = 0x80000000, /* This is the last action in the list. This also
@@ -476,14 +507,8 @@
ligature (table+table->ligature),
match_length (0) {}
- bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
- StateTableDriver<Types, EntryData> *driver HB_UNUSED,
- const Entry<EntryData> &entry) const
- {
- return LigatureEntryT::performAction (entry);
- }
void transition (hb_buffer_t *buffer,
- StateTableDriver<Types, EntryData> *driver,
+ StateTableDriver<Types, EntryData, Flags> *driver,
const Entry<EntryData> &entry)
{
DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
@@ -564,7 +589,7 @@
{
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return;
- buffer->cur().unicode_props() |= UPROPS_MASK_IGNORABLE;
+ _hb_glyph_info_set_default_ignorable (&buffer->cur());
if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return;
}
@@ -581,9 +606,9 @@
public:
bool ret;
- private:
hb_aat_apply_context_t *c;
const LigatureSubtable *table;
+ private:
const UnsizedArrayOf<HBUINT32> &ligAction;
const UnsizedArrayOf<HBUINT16> &component;
const UnsizedArrayOf<HBGlyphID16> &ligature;
@@ -597,11 +622,13 @@
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->face);
+ StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
- if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
- !c->buffer_digest.may_have (c->machine_glyph_set))
+ if (!c->buffer_intersects_machine ())
+ {
+ (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
return_trace (false);
+ }
driver.drive (&dc, c);
@@ -638,6 +665,12 @@
{
TRACE_APPLY (this);
+ if (!c->buffer_intersects_machine ())
+ {
+ (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
+ return_trace (false);
+ }
+
const OT::GDEF &gdef (*c->gdef_table);
bool has_glyph_classes = gdef.has_glyph_classes ();
@@ -670,8 +703,9 @@
const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
if (replacement)
{
- info[i].codepoint = *replacement;
- c->buffer_digest.add (*replacement);
+ hb_codepoint_t glyph = *replacement;
+ info[i].codepoint = glyph;
+ c->buffer_glyph_set.add (glyph);
if (has_glyph_classes)
_hb_glyph_info_set_glyph_props (&info[i],
gdef.get_glyph_props (*replacement));
@@ -682,6 +716,12 @@
return_trace (ret);
}
+ template <typename set_t>
+ void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs) const
+ {
+ substitute.collect_glyphs (glyphs, num_glyphs);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -715,73 +755,78 @@
DEFINE_SIZE_STATIC (4);
};
+ enum Flags
+ {
+ SetMark = 0x8000, /* If set, mark the current glyph. */
+ DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
+ * going to the new state. This does not mean
+ * that the glyph pointed to is the same one as
+ * before. If you've made insertions immediately
+ * downstream of the current glyph, the next glyph
+ * processed would in fact be the first one
+ * inserted. */
+ CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero,
+ * then the specified glyph list will be inserted
+ * as a kashida-like insertion, either before or
+ * after the current glyph (depending on the state
+ * of the currentInsertBefore flag). If clear, and
+ * the currentInsertList is nonzero, then the
+ * specified glyph list will be inserted as a
+ * split-vowel-like insertion, either before or
+ * after the current glyph (depending on the state
+ * of the currentInsertBefore flag). */
+ MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero,
+ * then the specified glyph list will be inserted
+ * as a kashida-like insertion, either before or
+ * after the marked glyph (depending on the state
+ * of the markedInsertBefore flag). If clear, and
+ * the markedInsertList is nonzero, then the
+ * specified glyph list will be inserted as a
+ * split-vowel-like insertion, either before or
+ * after the marked glyph (depending on the state
+ * of the markedInsertBefore flag). */
+ CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made
+ * to the left of the current glyph. If clear,
+ * they're made to the right of the current glyph. */
+ MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be
+ * made to the left of the marked glyph. If clear,
+ * they're made to the right of the marked glyph. */
+ CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the
+ * number of glyphs to insert at the current
+ * position. Since zero means no insertions, the
+ * largest number of insertions at any given
+ * current location is 31 glyphs. */
+ MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the
+ * number of glyphs to insert at the marked
+ * position. Since zero means no insertions, the
+ * largest number of insertions at any given
+ * marked location is 31 glyphs. */
+ };
+
+ bool is_action_initiable (const Entry<EntryData> &entry) const
+ {
+ return (entry.flags & SetMark);
+ }
+ bool is_actionable (const Entry<EntryData> &entry) const
+ {
+ return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
+ (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
+ }
+
struct driver_context_t
{
static constexpr bool in_place = false;
- enum Flags
- {
- SetMark = 0x8000, /* If set, mark the current glyph. */
- DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
- * going to the new state. This does not mean
- * that the glyph pointed to is the same one as
- * before. If you've made insertions immediately
- * downstream of the current glyph, the next glyph
- * processed would in fact be the first one
- * inserted. */
- CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero,
- * then the specified glyph list will be inserted
- * as a kashida-like insertion, either before or
- * after the current glyph (depending on the state
- * of the currentInsertBefore flag). If clear, and
- * the currentInsertList is nonzero, then the
- * specified glyph list will be inserted as a
- * split-vowel-like insertion, either before or
- * after the current glyph (depending on the state
- * of the currentInsertBefore flag). */
- MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero,
- * then the specified glyph list will be inserted
- * as a kashida-like insertion, either before or
- * after the marked glyph (depending on the state
- * of the markedInsertBefore flag). If clear, and
- * the markedInsertList is nonzero, then the
- * specified glyph list will be inserted as a
- * split-vowel-like insertion, either before or
- * after the marked glyph (depending on the state
- * of the markedInsertBefore flag). */
- CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made
- * to the left of the current glyph. If clear,
- * they're made to the right of the current glyph. */
- MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be
- * made to the left of the marked glyph. If clear,
- * they're made to the right of the marked glyph. */
- CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the
- * number of glyphs to insert at the current
- * position. Since zero means no insertions, the
- * largest number of insertions at any given
- * current location is 31 glyphs. */
- MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the
- * number of glyphs to insert at the marked
- * position. Since zero means no insertions, the
- * largest number of insertions at any given
- * marked location is 31 glyphs. */
- };
- driver_context_t (const InsertionSubtable *table,
+ driver_context_t (const InsertionSubtable *table_,
hb_aat_apply_context_t *c_) :
ret (false),
c (c_),
+ table (table_),
mark (0),
insertionAction (table+table->insertionAction) {}
- bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
- StateTableDriver<Types, EntryData> *driver HB_UNUSED,
- const Entry<EntryData> &entry) const
- {
- return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
- (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
- }
void transition (hb_buffer_t *buffer,
- StateTableDriver<Types, EntryData> *driver,
+ StateTableDriver<Types, EntryData, Flags> *driver,
const Entry<EntryData> &entry)
{
unsigned int flags = entry.flags;
@@ -807,7 +852,7 @@
/* TODO We ignore KashidaLike setting. */
if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
for (unsigned int i = 0; i < count; i++)
- c->buffer_digest.add (glyphs[i]);
+ c->buffer_glyph_set.add (glyphs[i]);
ret = true;
if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();
@@ -861,8 +906,9 @@
public:
bool ret;
+ hb_aat_apply_context_t *c;
+ const InsertionSubtable *table;
private:
- hb_aat_apply_context_t *c;
unsigned int mark;
const UnsizedArrayOf<HBGlyphID16> &insertionAction;
};
@@ -873,11 +919,13 @@
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->face);
+ StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
- if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
- !c->buffer_digest.may_have (c->machine_glyph_set))
+ if (!c->buffer_intersects_machine ())
+ {
+ (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
return_trace (false);
+ }
driver.drive (&dc, c);
@@ -935,25 +983,34 @@
friend struct hb_aat_layout_lookup_accelerator_t;
public:
- hb_set_digest_t digest;
+ hb_bit_set_t glyph_set;
+ mutable hb_aat_class_cache_t class_cache;
template <typename T>
auto init_ (const T &obj_, unsigned num_glyphs, hb_priority<1>) HB_AUTO_RETURN
(
- obj_.machine.collect_glyphs (this->digest, num_glyphs)
+ obj_.machine.collect_initial_glyphs (glyph_set, num_glyphs, obj_)
)
template <typename T>
void init_ (const T &obj_, unsigned num_glyphs, hb_priority<0>)
{
- digest = digest.full ();
+ obj_.collect_initial_glyphs (glyph_set, num_glyphs);
}
template <typename T>
void init (const T &obj_, unsigned num_glyphs)
{
+ glyph_set.init ();
init_ (obj_, num_glyphs, hb_prioritize);
+ class_cache.clear ();
}
+
+ void
+ fini ()
+ {
+ glyph_set.fini ();
+ }
};
/* Dispatch interface. */
@@ -999,6 +1056,8 @@
if (unlikely (!thiz))
return nullptr;
+ thiz->count = count;
+
hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables, num_glyphs);
chain.dispatch (&c_accelerate_subtables);
@@ -1005,6 +1064,13 @@
return thiz;
}
+ void destroy ()
+ {
+ for (unsigned i = 0; i < count; i++)
+ subtables[i].fini ();
+ }
+
+ unsigned count;
hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
};
@@ -1152,15 +1218,19 @@
{
bool reverse;
+ auto coverage = subtable->get_coverage ();
+
+ hb_mask_t subtable_flags = subtable->subFeatureFlags;
if (hb_none (hb_iter (c->range_flags) |
- hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); })))
+ hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); })))
goto skip;
- c->subtable_flags = subtable->subFeatureFlags;
- c->machine_glyph_set = accel ? accel->subtables[i].digest : hb_set_digest_t::full ();
+ c->subtable_flags = subtable_flags;
+ c->machine_glyph_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_bit_set_t);
+ c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr;
- if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
+ if (!(coverage & ChainSubtable<Types>::AllDirections) &&
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
- bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical))
+ bool (coverage & ChainSubtable<Types>::Vertical))
goto skip;
/* Buffer contents is always in logical direction. Determine if
@@ -1190,9 +1260,9 @@
(the order opposite that of the characters, which
may be right-to-left or left-to-right).
*/
- reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ?
- bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) :
- bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) !=
+ reverse = coverage & ChainSubtable<Types>::Logical ?
+ bool (coverage & ChainSubtable<Types>::Backwards) :
+ bool (coverage & ChainSubtable<Types>::Backwards) !=
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index))
@@ -1298,6 +1368,12 @@
hb_sanitize_context_t sc;
this->table = sc.reference_table<T> (face);
+ if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
+ {
+ hb_blob_destroy (this->table.get_blob ());
+ this->table = hb_blob_get_empty ();
+ }
+
this->chain_count = table->get_chain_count ();
this->accels = (hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *) hb_calloc (this->chain_count, sizeof (*accels));
@@ -1311,7 +1387,11 @@
~accelerator_t ()
{
for (unsigned int i = 0; i < this->chain_count; i++)
+ {
+ if (this->accels[i])
+ this->accels[i]->destroy ();
hb_free (this->accels[i]);
+ }
hb_free (this->accels);
this->table.destroy ();
}
@@ -1365,9 +1445,8 @@
unsigned get_chain_count () const
{
- return chainCount;
+ return chainCount;
}
-
void apply (hb_aat_apply_context_t *c,
const hb_aat_map_t &map,
const accelerator_t &accel) const
@@ -1376,10 +1455,7 @@
c->buffer->unsafe_to_concat ();
- if (c->buffer->len < HB_AAT_BUFFER_DIGEST_THRESHOLD)
- c->buffer_digest = c->buffer->digest ();
- else
- c->buffer_digest = hb_set_digest_t::full ();
+ c->setup_buffer_glyph_set ();
c->set_lookup_index (0);
const Chain<Types> *chain = &firstChain;
@@ -1428,9 +1504,18 @@
DEFINE_SIZE_MIN (8);
};
-struct morx : mortmorx<morx, ExtendedTypes, HB_AAT_TAG_morx> {};
-struct mort : mortmorx<mort, ObsoleteTypes, HB_AAT_TAG_mort> {};
+struct morx : mortmorx<morx, ExtendedTypes, HB_AAT_TAG_morx>
+{
+ HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+};
+struct mort : mortmorx<mort, ObsoleteTypes, HB_AAT_TAG_mort>
+{
+ HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+};
+
struct morx_accelerator_t : morx::accelerator_t {
morx_accelerator_t (hb_face_t *face) : morx::accelerator_t (face) {}
};
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -48,17 +48,69 @@
float get_track_value () const { return track.to_float (); }
- int get_value (const void *base, unsigned int index,
- unsigned int table_size) const
- { return (base+valuesZ).as_array (table_size)[index]; }
+ float interpolate_at (unsigned int idx,
+ float ptem,
+ const void *base,
+ hb_array_t<const F16DOT16> size_table) const
+ {
+ const FWORD *values = (base+valuesZ).arrayZ;
+ float s0 = size_table[idx].to_float ();
+ float s1 = size_table[idx + 1].to_float ();
+ int v0 = values[idx];
+ int v1 = values[idx + 1];
+
+ // Deal with font bugs.
+ if (unlikely (s1 < s0))
+ { hb_swap (s0, s1); hb_swap (v0, v1); }
+ if (unlikely (ptem < s0)) return v0;
+ if (unlikely (ptem > s1)) return v1;
+ if (unlikely (s0 == s1)) return (v0 + v1) * 0.5f;
+
+ float t = (ptem - s0) / (s1 - s0);
+ return v0 + t * (v1 - v0);
+ }
+
+ float get_value (float ptem,
+ const void *base,
+ hb_array_t<const F16DOT16> size_table) const
+ {
+ const FWORD *values = (base+valuesZ).arrayZ;
+
+ unsigned int n_sizes = size_table.length;
+
+ /*
+ * Choose size.
+ */
+ if (!n_sizes) return 0.f;
+ if (n_sizes == 1) return values[0];
+
+ // At least two entries.
+
+ unsigned i;
+ for (i = 0; i < n_sizes; i++)
+ if (size_table[i].to_float () >= ptem)
+ break;
+
+ // Boundary conditions.
+ if (i == 0) return values[0];
+ if (i == n_sizes) return values[n_sizes - 1];
+
+ // Exact match.
+ if (size_table[i].to_float () == ptem) return values[i];
+
+ // Interpolate.
+ return interpolate_at (i - 1, ptem, base, size_table);
+ }
+
public:
- bool sanitize (hb_sanitize_context_t *c, const void *base,
- unsigned int table_size) const
+ bool sanitize (hb_sanitize_context_t *c,
+ const void *base,
+ unsigned int n_sizes) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
- (valuesZ.sanitize (c, base, table_size))));
+ (valuesZ.sanitize (c, base, n_sizes))));
}
protected:
@@ -76,58 +128,38 @@
struct TrackData
{
- float interpolate_at (unsigned int idx,
- float target_size,
- const TrackTableEntry &trackTableEntry,
- const void *base) const
+ float get_tracking (const void *base, float ptem, float track = 0.f) const
{
- unsigned int sizes = nSizes;
- hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
+ unsigned count = nTracks;
+ hb_array_t<const F16DOT16> size_table = (base+sizeTable).as_array (nSizes);
- float s0 = size_table[idx].to_float ();
- float s1 = size_table[idx + 1].to_float ();
- float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0);
- return t * trackTableEntry.get_value (base, idx + 1, sizes) +
- (1.f - t) * trackTableEntry.get_value (base, idx, sizes);
- }
+ if (!count) return 0.f;
+ if (count == 1) return trackTable[0].get_value (ptem, base, size_table);
- int get_tracking (const void *base, float ptem) const
- {
- /*
- * Choose track.
- */
- const TrackTableEntry *trackTableEntry = nullptr;
- unsigned int count = nTracks;
- for (unsigned int i = 0; i < count; i++)
- {
- /* Note: Seems like the track entries are sorted by values. But the
- * spec doesn't explicitly say that. It just mentions it in the example. */
+ // At least two entries.
- /* For now we only seek for track entries with zero tracking value */
+ unsigned i = 0;
+ unsigned j = count - 1;
- if (trackTable[i].get_track_value () == 0.f)
- {
- trackTableEntry = &trackTable[i];
- break;
- }
- }
- if (!trackTableEntry) return 0;
+ // Find the two entries that track is between.
+ while (i + 1 < count && trackTable[i + 1].get_track_value () < track)
+ i++;
+ while (j > 0 && trackTable[j - 1].get_track_value () > track)
+ j--;
- /*
- * Choose size.
- */
- unsigned int sizes = nSizes;
- if (!sizes) return 0;
- if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
+ // Exact match.
+ if (i == j) return trackTable[i].get_value (ptem, base, size_table);
- hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
- unsigned int size_index;
- for (size_index = 0; size_index < sizes - 1; size_index++)
- if (size_table[size_index].to_float () >= ptem)
- break;
+ // Interpolate.
- return roundf (interpolate_at (size_index ? size_index - 1 : 0, ptem,
- *trackTableEntry, base));
+ float t0 = trackTable[i].get_track_value ();
+ float t1 = trackTable[j].get_track_value ();
+
+ float t = (track - t0) / (t1 - t0);
+
+ float a = trackTable[i].get_value (ptem, base, size_table);
+ float b = trackTable[j].get_value (ptem, base, size_table);
+ return a + t * (b - a);
}
bool sanitize (hb_sanitize_context_t *c, const void *base) const
@@ -158,46 +190,16 @@
bool has_data () const { return version.to_int (); }
- bool apply (hb_aat_apply_context_t *c) const
+ hb_position_t get_h_tracking (hb_font_t *font, float track = 0.f) const
{
- TRACE_APPLY (this);
-
- hb_mask_t trak_mask = c->plan->trak_mask;
-
- const float ptem = c->font->ptem;
- if (unlikely (ptem <= 0.f))
- return_trace (false);
-
- hb_buffer_t *buffer = c->buffer;
- if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
- {
- const TrackData &trackData = this+horizData;
- int tracking = trackData.get_tracking (this, ptem);
- hb_position_t offset_to_add = c->font->em_scalef_x (tracking / 2);
- hb_position_t advance_to_add = c->font->em_scalef_x (tracking);
- foreach_grapheme (buffer, start, end)
- {
- if (!(buffer->info[start].mask & trak_mask)) continue;
- buffer->pos[start].x_advance += advance_to_add;
- buffer->pos[start].x_offset += offset_to_add;
- }
- }
- else
- {
- const TrackData &trackData = this+vertData;
- int tracking = trackData.get_tracking (this, ptem);
- hb_position_t offset_to_add = c->font->em_scalef_y (tracking / 2);
- hb_position_t advance_to_add = c->font->em_scalef_y (tracking);
- foreach_grapheme (buffer, start, end)
- {
- if (!(buffer->info[start].mask & trak_mask)) continue;
- buffer->pos[start].y_advance += advance_to_add;
- buffer->pos[start].y_offset += offset_to_add;
- }
- }
-
- return_trace (true);
+ float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE;
+ return font->em_scalef_x ((this+horizData).get_tracking (this, ptem, track));
}
+ hb_position_t get_v_tracking (hb_font_t *font, float track = 0.f) const
+ {
+ float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE;
+ return font->em_scalef_y ((this+vertData).get_tracking (this, ptem, track));
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -34,10 +34,13 @@
#include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise.
#include "hb-aat-layout-kerx-table.hh"
#include "hb-aat-layout-morx-table.hh"
-#include "hb-aat-layout-trak-table.hh"
+#include "hb-aat-layout-trak-table.hh" // Just so we compile it; unused otherwise.
#include "hb-aat-ltag-table.hh"
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gdef-table.hh"
+
/*
* hb_aat_apply_context_t
*/
@@ -207,6 +210,36 @@
*/
+bool
+AAT::morx::is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const
+{
+#ifdef HB_NO_AAT_LAYOUT_BLOCKLIST
+ return false;
+#endif
+
+ switch HB_CODEPOINT_ENCODE3 (blob->length,
+ face->table.GSUB->table.get_length (),
+ face->table.GDEF->table.get_length ())
+ {
+ /* https://github.com/harfbuzz/harfbuzz/issues/4108
+ sha1sum:a71ca6813b7e56a772cffff7c24a5166b087197c AALMAGHRIBI.ttf */
+ case HB_CODEPOINT_ENCODE3 (19892, 2794, 340):
+ return true;
+ }
+ return false;
+}
+
+bool
+AAT::mort::is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const
+{
+#ifdef HB_NO_AAT_LAYOUT_BLOCKLIST
+ return false;
+#endif
+ return false;
+}
+
void
hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
hb_aat_map_t *map)
@@ -361,17 +394,6 @@
return face->table.trak->has_data ();
}
-void
-hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- const AAT::trak& trak = *font->face->table.trak;
-
- AAT::hb_aat_apply_context_t c (plan, font, buffer);
- trak.apply (&c);
-}
-
/**
* hb_aat_layout_get_feature_types:
* @face: #hb_face_t to work upon
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -32,6 +32,9 @@
#include "hb-ot-shape.hh"
#include "hb-aat-ltag-table.hh"
+/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
+#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
+
struct hb_aat_feature_mapping_t
{
hb_tag_t otFeatureTag;
@@ -68,10 +71,5 @@
hb_font_t *font,
hb_buffer_t *buffer);
-HB_INTERNAL void
-hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-
#endif /* HB_AAT_LAYOUT_HH */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -88,22 +88,23 @@
/* Sort features by start/end events. */
hb_vector_t<feature_event_t> feature_events;
+ feature_events.alloc_exact (features.length * 2 + 1);
for (unsigned int i = 0; i < features.length; i++)
{
- auto &feature = features[i];
+ auto &feature = features.arrayZ[i];
- if (features[i].start == features[i].end)
+ if (feature.start == feature.end)
continue;
feature_event_t *event;
event = feature_events.push ();
- event->index = features[i].start;
+ event->index = feature.start;
event->start = true;
event->feature = feature.info;
event = feature_events.push ();
- event->index = features[i].end;
+ event->index = feature.end;
event->start = false;
event->feature = feature.info;
}
@@ -139,12 +140,12 @@
current_features.qsort ();
unsigned int j = 0;
for (unsigned int i = 1; i < current_features.length; i++)
- if (current_features[i].type != current_features[j].type ||
+ if (current_features.arrayZ[i].type != current_features.arrayZ[j].type ||
/* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
* respectively, so we mask out the low-order bit when checking for "duplicates"
* (selectors referring to the same feature setting) here. */
- (!current_features[i].is_exclusive && ((current_features[i].setting & ~1) != (current_features[j].setting & ~1))))
- current_features[++j] = current_features[i];
+ (!current_features.arrayZ[i].is_exclusive && ((current_features.arrayZ[i].setting & ~1) != (current_features.arrayZ[j].setting & ~1))))
+ current_features.arrayZ[++j] = current_features.arrayZ[i];
current_features.shrink (j + 1);
}
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -286,7 +286,7 @@
// Compression function for Merkle-Damgard construction.
// This function is generated using the framework provided.
-#define mix(h) ( \
+#define fasthash_mix(h) ( \
(void) ((h) ^= (h) >> 23), \
(void) ((h) *= 0x2127599bf4325c37ULL), \
(h) ^= (h) >> 47)
@@ -310,7 +310,7 @@
#pragma GCC diagnostic ignored "-Wcast-align"
v = * (const uint64_t *) (pos++);
#pragma GCC diagnostic pop
- h ^= mix(v);
+ h ^= fasthash_mix(v);
h *= m;
}
}
@@ -320,7 +320,7 @@
while (pos != end)
{
v = pos++->v;
- h ^= mix(v);
+ h ^= fasthash_mix(v);
h *= m;
}
}
@@ -336,11 +336,11 @@
case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH;
case 2: v ^= (uint64_t)pos2[1] << 8; HB_FALLTHROUGH;
case 1: v ^= (uint64_t)pos2[0];
- h ^= mix(v);
+ h ^= fasthash_mix(v);
h *= m;
}
- return mix(h);
+ return fasthash_mix(h);
}
static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -251,7 +251,8 @@
if (end < start + 2)
return;
- for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--)
+ unsigned stop = start + (end - start) / 2;
+ for (unsigned lhs = start, rhs = end - 1; lhs < stop; lhs++, rhs--)
hb_swap (arrayZ[rhs], arrayZ[lhs]);
}
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -212,6 +212,7 @@
T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
+ operator bool () const { return get_acquire () != nullptr; }
T * operator -> () const { return get_acquire (); }
template <typename C> operator C * () const { return get_acquire (); }
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -78,6 +78,28 @@
hb_vector_size_t operator ~ () const
{ return process (hb_bitwise_neg); }
+ operator bool () const
+ {
+ for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+ if (v[i])
+ return true;
+ return false;
+ }
+ operator unsigned int () const
+ {
+ unsigned int r = 0;
+ for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+ r += hb_popcount (v[i]);
+ return r;
+ }
+ bool operator == (const hb_vector_size_t &o) const
+ {
+ for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+ if (v[i] != o.v[i])
+ return false;
+ return true;
+ }
+
hb_array_t<const elt_t> iter () const
{ return hb_array (v); }
@@ -89,6 +111,8 @@
struct hb_bit_page_t
{
+ hb_bit_page_t () { init0 (); }
+
void init0 () { v.init0 (); population = 0; }
void init1 () { v.init1 (); population = PAGE_BITS; }
@@ -101,10 +125,9 @@
bool is_empty () const
{
if (has_population ()) return !population;
- return
- + hb_iter (v)
- | hb_none
- ;
+ bool empty = !v;
+ if (empty) population = 0;
+ return empty;
}
uint32_t hash () const
{
@@ -115,7 +138,11 @@
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); dirty (); }
void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
+ bool may_have (hb_codepoint_t g) const { return get (g); }
+ bool operator [] (hb_codepoint_t g) const { return get (g); }
+ bool operator () (hb_codepoint_t g) const { return get (g); }
+
void add_range (hb_codepoint_t a, hb_codepoint_t b)
{
elt_t *la = &elt (a);
@@ -220,13 +247,17 @@
}
bool operator == (const hb_bit_page_t &other) const { return is_equal (other); }
- bool is_equal (const hb_bit_page_t &other) const
+ bool is_equal (const hb_bit_page_t &other) const { return v == other.v; }
+ bool intersects (const hb_bit_page_t &other) const
{
for (unsigned i = 0; i < len (); i++)
- if (v[i] != other.v[i])
- return false;
- return true;
+ if (v[i] & other.v[i])
+ return true;
+ return false;
}
+ bool may_intersect (const hb_bit_page_t &other) const
+ { return intersects (other); }
+
bool operator <= (const hb_bit_page_t &larger_page) const { return is_subset (larger_page); }
bool is_subset (const hb_bit_page_t &larger_page) const
{
@@ -241,14 +272,10 @@
}
bool has_population () const { return population != UINT_MAX; }
- unsigned int get_population () const
+ unsigned get_population () const
{
if (has_population ()) return population;
- population =
- + hb_iter (v)
- | hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u)
- ;
- return population;
+ return population = v;
}
bool next (hb_codepoint_t *codepoint) const
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -126,6 +126,7 @@
{ unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); }
bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
+ bool may_have (hb_codepoint_t g) const { return get (g); }
/* Has interface. */
bool operator [] (hb_codepoint_t k) const { return get (k); }
@@ -139,6 +140,9 @@
hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range)
{ add_range (range.first, range.second); return *this; }
+ bool may_intersect (const hb_bit_set_invertible_t &other) const
+ { return inverted || other.inverted || s.intersects (other.s); }
+
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
{
hb_codepoint_t c = first - 1;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -88,10 +88,11 @@
{
if (unlikely (!successful)) return false;
- if (pages.length == 0 && count == 1)
+ if (pages.length < count && count <= 2)
exact_size = true; // Most sets are small and local
- if (unlikely (!pages.resize (count, clear, exact_size) || !page_map.resize (count, clear, exact_size)))
+ if (unlikely (!pages.resize (count, clear, exact_size) ||
+ !page_map.resize (count, clear)))
{
pages.resize (page_map.length, clear, exact_size);
successful = false;
@@ -297,9 +298,9 @@
unsigned int write_index = 0;
for (unsigned int i = 0; i < page_map.length; i++)
{
- int m = (int) page_map[i].major;
+ int m = (int) page_map.arrayZ[i].major;
if (m < ds || de < m)
- page_map[write_index++] = page_map[i];
+ page_map.arrayZ[write_index++] = page_map.arrayZ[i];
}
compact (compact_workspace, write_index);
resize (write_index);
@@ -345,6 +346,7 @@
return false;
return page->get (g);
}
+ bool may_have (hb_codepoint_t g) const { return get (g); }
/* Has interface. */
bool operator [] (hb_codepoint_t k) const { return get (k); }
@@ -358,6 +360,31 @@
hb_bit_set_t& operator << (const hb_codepoint_pair_t& range)
{ add_range (range.first, range.second); return *this; }
+ bool intersects (const hb_bit_set_t &other) const
+ {
+ unsigned int na = pages.length;
+ unsigned int nb = other.pages.length;
+
+ unsigned int a = 0, b = 0;
+ for (; a < na && b < nb; )
+ {
+ if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major)
+ {
+ if (page_at (a).intersects (other.page_at (b)))
+ return true;
+ a++;
+ b++;
+ }
+ else if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
+ a++;
+ else
+ b++;
+ }
+ return false;
+ }
+ bool may_intersect (const hb_bit_set_t &other) const
+ { return intersects (other); }
+
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
{
hb_codepoint_t c = first - 1;
@@ -389,7 +416,7 @@
{
if (page_at (a).is_empty ()) { a++; continue; }
if (other.page_at (b).is_empty ()) { b++; continue; }
- if (page_map[a].major != other.page_map[b].major ||
+ if (page_map.arrayZ[a].major != other.page_map.arrayZ[b].major ||
!page_at (a).is_equal (other.page_at (b)))
return false;
a++;
@@ -412,8 +439,8 @@
uint32_t spi = 0;
for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++)
{
- uint32_t spm = page_map[spi].major;
- uint32_t lpm = larger_set.page_map[lpi].major;
+ uint32_t spm = page_map.arrayZ[spi].major;
+ uint32_t lpm = larger_set.page_map.arrayZ[lpi].major;
auto sp = page_at (spi);
if (spm < lpm && !sp.is_empty ())
@@ -503,7 +530,7 @@
for (; a < na && b < nb; )
{
- if (page_map[a].major == other.page_map[b].major)
+ if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major)
{
if (!passthru_left)
{
@@ -512,7 +539,7 @@
// passthru_left is set since no left side pages will be removed
// in that case.
if (write_index < a)
- page_map[write_index] = page_map[a];
+ page_map.arrayZ[write_index] = page_map.arrayZ[a];
write_index++;
}
@@ -520,7 +547,7 @@
a++;
b++;
}
- else if (page_map[a].major < other.page_map[b].major)
+ else if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
{
if (passthru_left)
count++;
@@ -765,8 +792,8 @@
unsigned int initial_size = size;
for (unsigned int i = start_page; i < page_map.length && size; i++)
{
- uint32_t base = major_start (page_map[i].major);
- unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size);
+ uint32_t base = major_start (page_map.arrayZ[i].major);
+ unsigned int n = pages[page_map.arrayZ[i].index].write (base, start_page_value, out, size);
out += n;
size -= n;
start_page_value = 0;
@@ -814,8 +841,8 @@
hb_codepoint_t next_value = codepoint + 1;
for (unsigned int i=start_page; i<page_map.length && size; i++)
{
- uint32_t base = major_start (page_map[i].major);
- unsigned int n = pages[page_map[i].index].write_inverted (base, start_page_value, out, size, &next_value);
+ uint32_t base = major_start (page_map.arrayZ[i].major);
+ unsigned int n = pages[page_map.arrayZ[i].index].write_inverted (base, start_page_value, out, size, &next_value);
out += n;
size -= n;
start_page_value = 0;
@@ -846,8 +873,8 @@
unsigned count = pages.length;
for (unsigned i = 0; i < count; i++)
{
- const auto& map = page_map[i];
- const auto& page = pages[map.index];
+ const auto& map = page_map.arrayZ[i];
+ const auto& page = pages.arrayZ[map.index];
if (!page.is_empty ())
return map.major * page_t::PAGE_BITS + page.get_min ();
@@ -859,8 +886,8 @@
unsigned count = pages.length;
for (signed i = count - 1; i >= 0; i--)
{
- const auto& map = page_map[(unsigned) i];
- const auto& page = pages[map.index];
+ const auto& map = page_map.arrayZ[(unsigned) i];
+ const auto& page = pages.arrayZ[map.index];
if (!page.is_empty ())
return map.major * page_t::PAGE_BITS + page.get_max ();
@@ -961,7 +988,7 @@
return nullptr;
last_page_lookup = i;
- return &pages.arrayZ[page_map[i].index];
+ return &pages.arrayZ[page_map.arrayZ[i].index];
}
page_t &page_at (unsigned int i)
{
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -34,36 +34,36 @@
#line 36 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = {
- 0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
- 48u, 57u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
+ 0u, 0u, 9u, 123u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u,
+ 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u,
9u, 125u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u,
34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u,
9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u,
9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u,
- 9u, 123u, 0u, 0u, 0
+ 9u, 93u, 9u, 123u, 0u, 0u, 0
};
static const char _deserialize_json_key_spans[] = {
- 0, 115, 26, 21, 2, 1, 50, 49,
- 10, 117, 117, 85, 117, 1, 50, 49,
+ 0, 115, 115, 26, 21, 2, 1, 50,
+ 49, 10, 117, 117, 117, 1, 50, 49,
10, 117, 117, 1, 1, 50, 49, 117,
117, 2, 1, 50, 49, 10, 117, 117,
1, 50, 49, 10, 117, 117, 1, 1,
50, 49, 117, 117, 1, 50, 49, 59,
117, 59, 117, 117, 1, 50, 49, 117,
- 115, 0
+ 85, 115, 0
};
static const short _deserialize_json_index_offsets[] = {
- 0, 0, 116, 143, 165, 168, 170, 221,
- 271, 282, 400, 518, 604, 722, 724, 775,
- 825, 836, 954, 1072, 1074, 1076, 1127, 1177,
- 1295, 1413, 1416, 1418, 1469, 1519, 1530, 1648,
- 1766, 1768, 1819, 1869, 1880, 1998, 2116, 2118,
- 2120, 2171, 2221, 2339, 2457, 2459, 2510, 2560,
- 2620, 2738, 2798, 2916, 3034, 3036, 3087, 3137,
- 3255, 3371
+ 0, 0, 116, 232, 259, 281, 284, 286,
+ 337, 387, 398, 516, 634, 752, 754, 805,
+ 855, 866, 984, 1102, 1104, 1106, 1157, 1207,
+ 1325, 1443, 1446, 1448, 1499, 1549, 1560, 1678,
+ 1796, 1798, 1849, 1899, 1910, 2028, 2146, 2148,
+ 2150, 2201, 2251, 2369, 2487, 2489, 2540, 2590,
+ 2650, 2768, 2828, 2946, 3064, 3066, 3117, 3167,
+ 3285, 3371, 3487
};
static const char _deserialize_json_indicies[] = {
@@ -77,37 +77,51 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 3, 1, 2, 2, 2,
+ 2, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 1, 3, 3, 3,
- 3, 3, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 3, 1, 4, 1,
- 5, 1, 6, 7, 1, 8, 9, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 10, 1, 11, 12,
- 1, 13, 1, 13, 13, 13, 13, 13,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 13, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 14, 1, 14, 14,
- 14, 14, 14, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 14, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 15, 1, 1, 16, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 1,
- 18, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 1, 20, 20, 20, 20, 20,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 20, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3,
+ 1, 4, 4, 4, 4, 4, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 4, 1, 5, 1, 6, 1, 7, 8,
+ 1, 9, 10, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 11, 1, 12, 13, 1, 14, 1, 14,
+ 14, 14, 14, 14, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 14, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 15, 1, 15, 15, 15, 15, 15, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 15, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 16, 1,
+ 1, 17, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 1, 19, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 1, 21,
+ 21, 21, 21, 21, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 21, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 22, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -116,13 +130,13 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 22,
- 1, 23, 23, 23, 23, 23, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 23, 1, 24, 24, 24,
+ 24, 24, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 23, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 3, 1, 1, 1,
+ 1, 1, 1, 1, 24, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 4, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -131,94 +145,101 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 24, 1, 25,
- 25, 25, 25, 25, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 25, 1,
+ 1, 25, 1, 21, 21, 21, 21, 21,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 26, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 21, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 22, 1,
+ 1, 1, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 27, 1, 20, 20, 20,
- 20, 20, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 20, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 21, 1, 1, 1, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 23,
+ 1, 26, 1, 26, 26, 26, 26, 26,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 26, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 27, 1, 27, 27,
+ 27, 27, 27, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 27, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 28, 1, 1, 29, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 1,
+ 31, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 1, 33, 33, 33, 33, 33,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 22, 1, 28, 1, 28, 28, 28,
- 28, 28, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 28, 1, 1, 1,
+ 1, 1, 33, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 34, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 29, 1,
- 29, 29, 29, 29, 29, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 29,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 30, 1, 1, 31,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 35,
+ 1, 33, 33, 33, 33, 33, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 33, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 34, 1, 1, 1,
32, 32, 32, 32, 32, 32, 32, 32,
- 32, 1, 33, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 1, 35, 35, 35,
- 35, 35, 1, 1, 1, 1, 1, 1,
+ 32, 32, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 35, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 36, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 35, 1, 36,
+ 1, 37, 1, 37, 37, 37, 37, 37,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 37, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 37, 1, 35, 35, 35, 35, 35,
+ 1, 1, 1, 1, 38, 1, 38, 38,
+ 38, 38, 38, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 38, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 35, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 36, 1,
- 1, 1, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 39, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 1,
+ 41, 41, 41, 41, 41, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 41,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 42, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 37,
- 1, 38, 1, 39, 1, 39, 39, 39,
- 39, 39, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 39, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 40, 1,
- 40, 40, 40, 40, 40, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 40,
+ 1, 1, 1, 1, 43, 1, 41, 41,
+ 41, 41, 41, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 41,
- 42, 42, 42, 42, 42, 42, 42, 42,
- 42, 1, 43, 43, 43, 43, 43, 1,
+ 1, 1, 1, 1, 1, 41, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 42, 1, 1, 1, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 43, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 44, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -226,43 +247,42 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 43, 1, 45, 46, 1, 47,
+ 1, 47, 47, 47, 47, 47, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 45, 1,
- 43, 43, 43, 43, 43, 1, 1, 1,
+ 47, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 43,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 44, 1, 1, 1, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 48, 1, 48, 48, 48, 48,
+ 48, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 48, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 49, 1, 1, 50, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 1, 52, 53,
+ 53, 53, 53, 53, 53, 53, 53, 53,
+ 1, 54, 54, 54, 54, 54, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 54, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 55, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 45, 1, 47, 48,
- 1, 49, 1, 49, 49, 49, 49, 49,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 49, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 50, 1, 50, 50,
- 50, 50, 50, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 50, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 51, 1, 1, 52, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 1,
- 54, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 1, 56, 56, 56, 56, 56,
+ 1, 1, 1, 1, 1, 56, 1, 54,
+ 54, 54, 54, 54, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 54, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 56, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 57, 1,
+ 1, 1, 55, 1, 1, 1, 53, 53,
+ 53, 53, 53, 53, 53, 53, 53, 53,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -271,43 +291,42 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 56, 1, 57, 1, 57,
+ 57, 57, 57, 57, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 58,
- 1, 56, 56, 56, 56, 56, 1, 1,
+ 1, 1, 1, 1, 1, 1, 57, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 56, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 57, 1, 1, 1,
- 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 58, 1, 58, 58, 58, 58, 58, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 58, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 59, 1,
+ 1, 60, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 1, 62, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 1, 64,
+ 64, 64, 64, 64, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 64, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 65, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 58, 1, 59,
- 1, 59, 59, 59, 59, 59, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 59, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 60, 1, 60, 60, 60, 60,
- 60, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 60, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 61, 1, 1, 62, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 1, 64, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 1, 66, 66, 66, 66, 66, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 66, 1, 64, 64, 64,
+ 64, 64, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 66, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 67, 1, 1, 1,
+ 1, 1, 1, 1, 64, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 65, 1, 1, 1, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -316,42 +335,41 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 68, 1, 66,
- 66, 66, 66, 66, 1, 1, 1, 1,
+ 1, 66, 1, 67, 1, 68, 1, 68,
+ 68, 68, 68, 68, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 66, 1,
+ 1, 1, 1, 1, 1, 1, 68, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 67, 1, 1, 1, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 69, 1, 69, 69, 69, 69, 69, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 69, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 70, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 1, 72, 72, 72, 72,
+ 72, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 72, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 73,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 68, 1, 69, 1, 70,
- 1, 70, 70, 70, 70, 70, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 70, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 71, 1, 71, 71, 71, 71,
- 71, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 71, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 72, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 1, 74, 74,
- 74, 74, 74, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 74, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 75, 1, 1, 1, 1, 1, 1,
+ 74, 1, 72, 72, 72, 72, 72, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 72, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 73, 1, 1,
+ 1, 75, 75, 75, 75, 75, 75, 75,
+ 75, 75, 75, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -359,49 +377,43 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 76, 1, 74, 74, 74, 74,
- 74, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 74, 1,
+ 76, 1, 76, 76, 76, 76, 76, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 74, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 75,
- 1, 1, 1, 77, 77, 77, 77, 77,
- 77, 77, 77, 77, 77, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 76, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 77, 1, 77, 77, 77,
+ 77, 77, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 77, 1, 78, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 79, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 1, 82,
+ 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 83, 81, 84, 84, 84, 84, 84,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 84, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 85, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 76, 1, 78, 1, 78, 78, 78, 78,
- 78, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 78, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 79, 1, 79,
- 79, 79, 79, 79, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 79, 1,
- 80, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 81, 82,
- 82, 82, 82, 82, 82, 82, 82, 82,
- 1, 84, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 85, 83, 86, 86, 86,
- 86, 86, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 86, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 87, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 86,
+ 1, 81, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -408,75 +420,78 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 81, 1, 87, 87, 87,
+ 87, 87, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 88, 1, 83, 1, 1, 1, 1,
+ 1, 1, 1, 1, 87, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 88, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 83, 1, 89,
- 89, 89, 89, 89, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 89, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 90, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 89, 1, 87, 87, 87, 87, 87,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 87, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 88, 1,
+ 1, 1, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 91, 1, 89, 89, 89,
- 89, 89, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 89, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 90, 1, 1, 1, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 89,
+ 1, 91, 1, 91, 91, 91, 91, 91,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 91, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 92, 1, 92, 92,
+ 92, 92, 92, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 92, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 93, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 1,
+ 87, 87, 87, 87, 87, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 87,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 91, 1, 93, 1, 93, 93, 93,
- 93, 93, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 88, 1, 1, 1, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 93, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 94, 1,
- 94, 94, 94, 94, 94, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 94,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 95,
- 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 1, 89, 89, 89, 89, 89, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 89, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 90, 1, 1,
- 1, 97, 97, 97, 97, 97, 97, 97,
- 97, 97, 97, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 89, 1, 96, 96,
+ 96, 96, 96, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 96, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 97, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 91, 1,
- 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 98, 1, 2, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0,
+ 1, 1, 1, 2, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -487,40 +502,40 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 2, 1, 1, 0
+ 1, 1, 1, 1, 1, 1, 3, 1,
+ 1, 0
};
static const char _deserialize_json_trans_targs[] = {
- 1, 0, 2, 2, 3, 4, 19, 25,
- 38, 44, 52, 5, 13, 6, 7, 8,
- 9, 12, 9, 12, 10, 2, 11, 10,
- 11, 11, 56, 57, 14, 15, 16, 17,
- 18, 17, 18, 10, 2, 11, 20, 21,
- 22, 23, 24, 10, 2, 11, 24, 26,
- 32, 27, 28, 29, 30, 31, 30, 31,
- 10, 2, 11, 33, 34, 35, 36, 37,
- 36, 37, 10, 2, 11, 39, 40, 41,
- 42, 43, 10, 2, 11, 43, 45, 46,
- 47, 50, 51, 47, 48, 49, 10, 2,
- 11, 10, 2, 11, 51, 53, 54, 50,
- 55, 55
+ 1, 0, 2, 3, 3, 4, 5, 19,
+ 25, 38, 44, 52, 6, 13, 7, 8,
+ 9, 10, 12, 10, 12, 11, 3, 56,
+ 11, 56, 14, 15, 16, 17, 18, 17,
+ 18, 11, 3, 56, 20, 21, 22, 23,
+ 24, 11, 3, 56, 24, 26, 32, 27,
+ 28, 29, 30, 31, 30, 31, 11, 3,
+ 56, 33, 34, 35, 36, 37, 36, 37,
+ 11, 3, 56, 39, 40, 41, 42, 43,
+ 11, 3, 56, 43, 45, 46, 47, 50,
+ 51, 47, 48, 49, 11, 3, 56, 11,
+ 3, 56, 51, 53, 54, 50, 55, 55,
+ 56, 57, 58
};
static const char _deserialize_json_trans_actions[] = {
- 0, 0, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 2,
- 2, 2, 0, 0, 3, 3, 4, 0,
- 5, 0, 0, 0, 0, 0, 2, 2,
- 2, 0, 0, 6, 6, 7, 0, 0,
- 0, 2, 2, 8, 8, 9, 0, 0,
- 0, 0, 0, 2, 2, 2, 0, 0,
- 10, 10, 11, 0, 0, 2, 2, 2,
- 0, 0, 12, 12, 13, 0, 0, 0,
- 2, 2, 14, 14, 15, 0, 0, 0,
- 2, 16, 16, 0, 17, 0, 18, 18,
- 19, 20, 20, 21, 17, 0, 0, 22,
- 22, 23
+ 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 0, 0, 3, 3, 4,
+ 0, 5, 0, 0, 2, 2, 2, 0,
+ 0, 6, 6, 7, 0, 0, 0, 2,
+ 2, 8, 8, 9, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 0, 10, 10,
+ 11, 0, 0, 2, 2, 2, 0, 0,
+ 12, 12, 13, 0, 0, 0, 2, 2,
+ 14, 14, 15, 0, 0, 0, 2, 16,
+ 16, 0, 17, 0, 18, 18, 19, 20,
+ 20, 21, 17, 0, 0, 22, 22, 23,
+ 0, 0, 0
};
static const int deserialize_json_start = 1;
@@ -545,22 +560,17 @@
/* Ensure we have positions. */
(void) hb_buffer_get_glyph_positions (buffer, nullptr);
- while (p < pe && ISSPACE (*p))
- p++;
- if (p < pe && *p == (buffer->len ? ',' : '['))
- *end_ptr = ++p;
-
const char *tok = nullptr;
int cs;
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 559 "hb-buffer-deserialize-json.hh"
+#line 569 "hb-buffer-deserialize-json.hh"
{
cs = deserialize_json_start;
}
-#line 564 "hb-buffer-deserialize-json.hh"
+#line 574 "hb-buffer-deserialize-json.hh"
{
int _slen;
int _trans;
@@ -772,7 +782,7 @@
*end_ptr = p;
}
break;
-#line 776 "hb-buffer-deserialize-json.hh"
+#line 786 "hb-buffer-deserialize-json.hh"
}
_again:
@@ -784,7 +794,7 @@
_out: {}
}
-#line 137 "hb-buffer-deserialize-json.rl"
+#line 132 "hb-buffer-deserialize-json.rl"
*end_ptr = p;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.rl
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.rl 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.rl 2025-03-08 22:22:06 UTC (rev 74540)
@@ -106,7 +106,7 @@
@add_item
;
-main := space* item (comma item)* space* (','|']');
+main := space* '['? space* item (comma item)* space* (','|']')?;
}%%
@@ -122,11 +122,6 @@
/* Ensure we have positions. */
(void) hb_buffer_get_glyph_positions (buffer, nullptr);
- while (p < pe && ISSPACE (*p))
- p++;
- if (p < pe && *p == (buffer->len ? ',' : '['))
- *end_ptr = ++p;
-
const char *tok = nullptr;
int cs;
hb_glyph_info_t info = {0};
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -860,7 +860,7 @@
* @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
- * Attaches a user-data key/data pair to the specified buffer.
+ * Attaches a user-data key/data pair to the specified buffer.
*
* Return value: `true` if success, `false` otherwise
*
@@ -1209,7 +1209,7 @@
* @cluster_level: The cluster level to set on the buffer
*
* Sets the cluster level of a buffer. The #hb_buffer_cluster_level_t
- * dictates one aspect of how HarfBuzz will treat non-base characters
+ * dictates one aspect of how HarfBuzz will treat non-base characters
* during shaping.
*
* Since: 0.9.42
@@ -1229,7 +1229,7 @@
* @buffer: An #hb_buffer_t
*
* Fetches the cluster level of a buffer. The #hb_buffer_cluster_level_t
- * dictates one aspect of how HarfBuzz will treat non-base characters
+ * dictates one aspect of how HarfBuzz will treat non-base characters
* during shaping.
*
* Return value: The cluster level of @buffer
@@ -1983,7 +1983,7 @@
* @buffer: An #hb_buffer_t
* @source: source #hb_buffer_t
* @start: start index into source buffer to copy. Use 0 to copy from start of buffer.
- * @end: end index into source buffer to copy. Use @HB_FEATURE_GLOBAL_END to copy to end of buffer.
+ * @end: end index into source buffer to copy. Use @UINT_MAX (or ((unsigned int) -1)) to copy to end of buffer.
*
* Append (part of) contents of another buffer to this buffer.
*
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -32,7 +32,6 @@
#include "hb.hh"
#include "hb-unicode.hh"
-#include "hb-set-digest.hh"
static_assert ((sizeof (hb_glyph_info_t) == 20), "");
@@ -182,22 +181,24 @@
allocated_var_bits = 0;
}
+ HB_ALWAYS_INLINE
hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
+ HB_ALWAYS_INLINE
hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
+ HB_ALWAYS_INLINE
hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
+ HB_ALWAYS_INLINE
hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
+ HB_ALWAYS_INLINE
hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; }
+ HB_ALWAYS_INLINE
hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
- hb_set_digest_t digest () const
- {
- hb_set_digest_t d;
- d.init ();
- d.add_array (&info[0].codepoint, len, sizeof (info[0]));
- return d;
- }
+ template <typename set_t>
+ void collect_codepoints (set_t &d) const
+ { d.clear (); d.add_array (&info[0].codepoint, len, sizeof (info[0])); }
HB_INTERNAL void similar (const hb_buffer_t &src);
HB_INTERNAL void reset ();
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -522,7 +522,7 @@
void alloc (unsigned n)
{
- values.alloc (n, true);
+ values.alloc_exact (n);
}
void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t (), const VAL &v = VAL ())
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -157,6 +157,7 @@
#define HB_NO_FALLBACK_SHAPE
#define HB_NO_OT_KERN
#define HB_NO_OT_LAYOUT_BLOCKLIST
+#define HB_NO_AAT_LAYOUT_BLOCKLIST
#define HB_NO_OT_SHAPE_FALLBACK
#endif
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-font.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-font.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-font.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -60,11 +60,25 @@
void *user_data HB_UNUSED)
{
CTFontRef ct_font = (CTFontRef) font_data;
- UniChar ch = unicode;
- CGGlyph cg_glyph;
- if (CTFontGetGlyphsForCharacters (ct_font, &ch, &cg_glyph, 1))
+ UniChar ch[2];
+ CGGlyph cg_glyph[2];
+ unsigned count = 0;
+
+ if (unicode <= 0xFFFF)
{
- *glyph = cg_glyph;
+ ch[count++] = unicode;
+ }
+ else if (unicode <= 0x10FFFF)
+ {
+ ch[count++] = (unicode >> 10) + 0xD7C0;
+ ch[count++] = (unicode & 0x3FF) + 0xDC00;
+ }
+ else
+ ch[count++] = 0xFFFD;
+
+ if (CTFontGetGlyphsForCharacters (ct_font, ch, cg_glyph, count))
+ {
+ *glyph = cg_glyph[0];
return true;
}
return false;
@@ -80,6 +94,31 @@
unsigned int glyph_stride,
void *user_data HB_UNUSED)
{
+ // If any non-BMP codepoint is requested, use the slow path.
+ bool slow_path = false;
+ auto *unicode = first_unicode;
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (*unicode > 0xFFFF)
+ {
+ slow_path = true;
+ break;
+ }
+ unicode = &StructAtOffset<const hb_codepoint_t> (unicode, unicode_stride);
+ }
+
+ if (unlikely (slow_path))
+ {
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (!hb_coretext_get_nominal_glyph (font, font_data, *first_unicode, first_glyph, nullptr))
+ return i;
+ first_unicode = &StructAtOffset<const hb_codepoint_t> (first_unicode, unicode_stride);
+ first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
+ }
+ return count;
+ }
+
CTFontRef ct_font = (CTFontRef) font_data;
UniChar ch[MAX_GLYPHS];
@@ -92,7 +131,16 @@
ch[j] = *first_unicode;
first_unicode = &StructAtOffset<const hb_codepoint_t> (first_unicode, unicode_stride);
}
- CTFontGetGlyphsForCharacters (ct_font, ch, cg_glyph, c);
+ if (unlikely (!CTFontGetGlyphsForCharacters (ct_font, ch, cg_glyph, c)))
+ {
+ // Use slow path partially and return at first failure.
+ for (unsigned j = 0; j < c; j++)
+ {
+ if (!hb_coretext_get_nominal_glyph (font, font_data, ch[j], first_glyph, nullptr))
+ return i + j;
+ first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
+ }
+ }
for (unsigned j = 0; j < c; j++)
{
*first_glyph = cg_glyph[j];
@@ -113,14 +161,39 @@
{
CTFontRef ct_font = (CTFontRef) font_data;
- UniChar ch[2] = { unicode, variation_selector };
- CGGlyph cg_glyph[2];
+ UniChar ch[4];
+ CGGlyph cg_glyph[4];
+ unsigned count = 0;
- CTFontGetGlyphsForCharacters (ct_font, ch, cg_glyph, 2);
+ // Add Unicode, then variation selector. Ugly, but works.
+ //
+ if (unicode <= 0xFFFF)
+ ch[count++] = unicode;
+ else if (unicode <= 0x10FFFF)
+ {
+ ch[count++] = (unicode >> 10) + 0xD7C0;
+ ch[count++] = (unicode & 0x3FF) + 0xDC00;
+ }
+ else
+ ch[count++] = 0xFFFD;
- if (cg_glyph[1])
- return false;
+ if (variation_selector <= 0xFFFF)
+ ch[count++] = variation_selector;
+ else if (variation_selector <= 0x10FFFF)
+ {
+ ch[count++] = (variation_selector >> 10) + 0xD7C0;
+ ch[count++] = (variation_selector & 0x3FF) + 0xDC00;
+ }
+ else
+ ch[count++] = 0xFFFD;
+ CTFontGetGlyphsForCharacters (ct_font, ch, cg_glyph, count);
+
+ // All except for first should be zero if we succeeded
+ for (unsigned i = 1; i < count; i++)
+ if (cg_glyph[i])
+ return false;
+
*glyph = cg_glyph[0];
return true;
}
@@ -438,10 +511,6 @@
* created with hb_face_create(), and therefore was not
* initially configured to use CoreText font functions.
*
- * An #hb_font_t object created with hb_coretext_font_create()
- * is preconfigured for CoreText font functions and does not
- * require this function to be used.
- *
* <note>Note: Internally, this function creates a CTFont.
* </note>
*
@@ -452,7 +521,12 @@
{
CTFontRef ct_font = hb_coretext_font_get_ct_font (font);
if (unlikely (!ct_font))
+ {
+ hb_font_set_funcs (font,
+ hb_font_funcs_get_empty (),
+ nullptr, nullptr);
return;
+ }
hb_font_set_funcs (font,
_hb_coretext_get_font_funcs (),
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-shape.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-shape.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -45,9 +45,6 @@
* Functions for using HarfBuzz with the CoreText fonts.
**/
-/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
-#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
-
static CTFontRef create_ct_font (CGFontRef cg_font, CGFloat font_size);
static void
@@ -384,9 +381,9 @@
(CTFontDescriptorRef) CFArrayGetValueAtIndex (ct_font_desc_array, index) : nullptr;
if (unlikely (!ct_font_desc))
{
- CFRelease (ct_font_desc_array);
- CFRelease (url);
- return nullptr;
+ CFRelease (ct_font_desc_array);
+ CFRelease (url);
+ return nullptr;
}
CFRelease (url);
auto ct_font = ct_font_desc ? CTFontCreateWithFontDescriptor (ct_font_desc, 0, nullptr) : nullptr;
@@ -400,6 +397,7 @@
return nullptr;
hb_face_t *face = hb_coretext_face_create (cg_font);
+ CFRelease (cg_font);
if (unlikely (hb_face_is_immutable (face)))
return nullptr;
@@ -432,7 +430,7 @@
if (unlikely (!face_data)) return nullptr;
CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
- CGFloat font_size = (CGFloat) (font->ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : font->ptem);
+ CGFloat font_size = (CGFloat) (font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE);
CTFontRef ct_font = create_ct_font (cg_font, font_size);
if (unlikely (!ct_font))
@@ -451,11 +449,11 @@
for (unsigned i = 0; i < font->num_coords; i++)
{
- if (font->coords[i] == 0.) continue;
-
hb_ot_var_axis_info_t info;
unsigned int c = 1;
hb_ot_var_get_axis_infos (font->face, i, &c, &info);
+ if (font->design_coords[i] == info.default_value)
+ continue;
float v = hb_clamp (font->design_coords[i], info.min_value, info.max_value);
CFNumberRef tag_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag);
@@ -499,7 +497,7 @@
* CTFontRef.
*
* The created font uses the default font functions implemented
- * navitely by HarfBuzz. If you want to use the CoreText font functions
+ * natively by HarfBuzz. If you want to use the CoreText font functions
* instead (rarely needed), you can do so by calling
* by hb_coretext_font_set_funcs().
*
@@ -521,6 +519,36 @@
hb_font_set_ptem (font, CTFontGetSize (ct_font));
+ /* Copy font variations */
+ CFDictionaryRef variations = CTFontCopyVariation (ct_font);
+ if (variations)
+ {
+ hb_vector_t<hb_variation_t> vars;
+ hb_vector_t<CFTypeRef> keys;
+ hb_vector_t<CFTypeRef> values;
+
+ CFIndex count = CFDictionaryGetCount (variations);
+ if (unlikely (!vars.alloc_exact (count) || !keys.resize_exact (count) || !values.resize_exact (count)))
+ goto done;
+
+ // Fetch them one by one and collect in a vector of our own.
+ CFDictionaryGetKeysAndValues (variations, keys.arrayZ, values.arrayZ);
+ for (CFIndex i = 0; i < count; i++)
+ {
+ int tag;
+ float value;
+ CFNumberGetValue ((CFNumberRef) keys.arrayZ[i], kCFNumberIntType, &tag);
+ CFNumberGetValue ((CFNumberRef) values.arrayZ[i], kCFNumberFloatType, &value);
+
+ hb_variation_t var = {tag, value};
+ vars.push (var);
+ }
+ hb_font_set_variations (font, vars.arrayZ, vars.length);
+
+done:
+ CFRelease (variations);
+ }
+
/* Let there be dragons here... */
font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font));
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-decycler.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-decycler.hh (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-decycler.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2025 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_DECYCLER_HH
+#define HB_DECYCLER_HH
+
+#include "hb.hh"
+
+/*
+ * hb_decycler_t is an efficient cycle detector for graph traversal.
+ * It's a simple tortoise-and-hare algorithm with a twist: it's
+ * designed to detect cycles while traversing a graph in a DFS manner,
+ * instead of just a linked list.
+ *
+ * For Floyd's tortoise and hare algorithm, see:
+ * https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_tortoise_and_hare
+ *
+ * hb_decycler_t is O(n) in the number of nodes in the DFS traversal
+ * if there are no cycles. Unlike Floyd's algorithm, hb_decycler_t
+ * can be used in a DFS traversal, where the graph is not a simple
+ * linked list, but a tree with possible cycles. Like Floyd's algorithm,
+ * it is constant-memory (~three pointers).
+ *
+ * The decycler works by creating an implicit linked-list on the stack,
+ * of the path from the root to the current node, and apply Floyd's
+ * algorithm on that list as it goes.
+ *
+ * The decycler is malloc-free, and as such, much faster to use than a
+ * hb_set_t or hb_map_t equivalent.
+ *
+ * The decycler detects cycles in the graph *eventually*, not *immediately*.
+ * That is, it may not detect a cycle until the cycle is fully traversed,
+ * even multiple times. See Floyd's algorithm analysis for details.
+ *
+ * The implementation saves a pointer storage on the stack by combining
+ * this->u.decycler and this->u.next into a union. This is possible because
+ * at any point we only need one of those values. The invariant is that
+ * after construction, and before destruction, of a node, the u.decycler
+ * field is always valid. The u.next field is only valid when the node is
+ * in the traversal path, parent to another node.
+ *
+ * There are three method's:
+ *
+ * - hb_decycler_node_t() constructor: Creates a new node in the traversal.
+ * The constructor takes a reference to the decycler object and inserts
+ * itself as the latest node in the traversal path, by advancing the hare
+ * pointer, and for every other descent, advancing the tortoise pointer.
+ *
+ * - ~hb_decycler_node_t() destructor: Restores the decycler object to its
+ * previous state by removing the node from the traversal path.
+ *
+ * - bool visit(uintptr_t value): Called on every node in the graph. Returns
+ * true if the node is not part of a cycle, and false if it is. The value
+ * parameter is used to detect cycles. It's the caller's responsibility
+ * to ensure that the value is unique for each node in the graph.
+ * The cycle detection is as simple as comparing the value to the value
+ * held by the tortoise pointer, which is the Floyd's algorithm.
+ *
+ * For usage examples see test-decycler.cc.
+ */
+
+struct hb_decycler_node_t;
+
+struct hb_decycler_t
+{
+ friend struct hb_decycler_node_t;
+
+ private:
+ bool tortoise_awake = false;
+ hb_decycler_node_t *tortoise = nullptr;
+ hb_decycler_node_t *hare = nullptr;
+};
+
+struct hb_decycler_node_t
+{
+ hb_decycler_node_t (hb_decycler_t &decycler)
+ {
+ u.decycler = &decycler;
+
+ decycler.tortoise_awake = !decycler.tortoise_awake;
+
+ if (!decycler.tortoise)
+ {
+ // First node.
+ assert (decycler.tortoise_awake);
+ assert (!decycler.hare);
+ decycler.tortoise = decycler.hare = this;
+ return;
+ }
+
+ if (decycler.tortoise_awake)
+ decycler.tortoise = decycler.tortoise->u.next; // Time to move.
+
+ this->prev = decycler.hare;
+ decycler.hare->u.next = this;
+ decycler.hare = this;
+ }
+
+ ~hb_decycler_node_t ()
+ {
+ hb_decycler_t &decycler = *u.decycler;
+
+ // Inverse of the constructor.
+
+ assert (decycler.hare == this);
+ decycler.hare = prev;
+ if (prev)
+ prev->u.decycler = &decycler;
+
+ assert (decycler.tortoise);
+ if (decycler.tortoise_awake)
+ decycler.tortoise = decycler.tortoise->prev;
+
+ decycler.tortoise_awake = !decycler.tortoise_awake;
+ }
+
+ bool visit (uintptr_t value_)
+ {
+ value = value_;
+
+ hb_decycler_t &decycler = *u.decycler;
+
+ if (decycler.tortoise == this)
+ return true; // First node; not a cycle.
+
+ if (decycler.tortoise->value == value)
+ return false; // Cycle detected.
+
+ return true;
+ }
+
+ private:
+ union {
+ hb_decycler_t *decycler;
+ hb_decycler_node_t *next;
+ } u = {nullptr};
+ hb_decycler_node_t *prev = nullptr;
+ uintptr_t value = 0;
+};
+
+#endif /* HB_DECYCLER_HH */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -29,6 +29,7 @@
#include "hb-shaper-impl.hh"
#include <dwrite_1.h>
+#include <dwrite_3.h>
#include "hb-directwrite.h"
@@ -275,6 +276,8 @@
void
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
{
+ if (data != HB_SHAPER_DATA_SUCCEEDED)
+ ((IDWriteFont *) (const void *) data)->Release();
}
@@ -839,7 +842,7 @@
}
static void
-_hb_directwrite_font_release (void *data)
+_hb_directwrite_face_release (void *data)
{
if (data)
((IDWriteFontFace *) data)->Release ();
@@ -847,7 +850,7 @@
/**
* hb_directwrite_face_create:
- * @font_face: a DirectWrite IDWriteFontFace object.
+ * @dw_face: a DirectWrite IDWriteFontFace object.
*
* Constructs a new face object from the specified DirectWrite IDWriteFontFace.
*
@@ -856,15 +859,33 @@
* Since: 2.4.0
**/
hb_face_t *
-hb_directwrite_face_create (IDWriteFontFace *font_face)
+hb_directwrite_face_create (IDWriteFontFace *dw_face)
{
- if (font_face)
- font_face->AddRef ();
- return hb_face_create_for_tables (_hb_directwrite_reference_table, font_face,
- _hb_directwrite_font_release);
+ if (dw_face)
+ dw_face->AddRef ();
+ return hb_face_create_for_tables (_hb_directwrite_reference_table, dw_face,
+ _hb_directwrite_face_release);
}
/**
+* hb_directwrite_face_get_dw_font_face:
+* @face: a #hb_face_t object
+*
+* Gets the DirectWrite IDWriteFontFace associated with @face.
+*
+* Return value: DirectWrite IDWriteFontFace object corresponding to the given input
+*
+* Since: 10.4.0
+**/
+IDWriteFontFace *
+hb_directwrite_face_get_dw_font_face (hb_face_t *face)
+{
+ return face->data.directwrite->fontFace;
+}
+
+#ifndef HB_DISABLE_DEPRECATED
+
+/**
* hb_directwrite_face_get_font_face:
* @face: a #hb_face_t object
*
@@ -873,12 +894,90 @@
* Return value: DirectWrite IDWriteFontFace object corresponding to the given input
*
* Since: 2.5.0
+* Deprecated: 10.4.0: Use hb_directwrite_face_get_dw_font_face() instead
**/
IDWriteFontFace *
hb_directwrite_face_get_font_face (hb_face_t *face)
{
- return face->data.directwrite->fontFace;
+ return hb_directwrite_face_get_dw_font_face (face);
}
+#endif
+/**
+ * hb_directwrite_font_create:
+ * @dw_font: a DirectWrite IDWriteFont object.
+ *
+ * Constructs a new font object from the specified DirectWrite IDWriteFont.
+ *
+ * Return value: #hb_font_t object corresponding to the given input
+ *
+ * Since: 10.3.0
+ **/
+hb_font_t *
+hb_directwrite_font_create (IDWriteFont *dw_font)
+{
+ IDWriteFontFace *dw_face = nullptr;
+ IDWriteFontFace5 *dw_face5 = nullptr;
+
+ if (FAILED (dw_font->CreateFontFace (&dw_face)))
+ return hb_font_get_empty ();
+
+ hb_face_t *face = hb_directwrite_face_create (dw_face);
+ hb_font_t *font = hb_font_create (face);
+ hb_face_destroy (face);
+
+ if (unlikely (hb_object_is_immutable (font)))
+ goto done;
+
+ /* Copy font variations */
+ if (SUCCEEDED (dw_face->QueryInterface (__uuidof (IDWriteFontFace5), (void**) &dw_face5)))
+ {
+ if (dw_face5->HasVariations ())
+ {
+ hb_vector_t<DWRITE_FONT_AXIS_VALUE> values;
+ uint32_t count = dw_face5->GetFontAxisValueCount ();
+ if (likely (values.resize_exact (count)) &&
+ SUCCEEDED (dw_face5->GetFontAxisValues (values.arrayZ, count)))
+ {
+ hb_vector_t<hb_variation_t> vars;
+ if (likely (vars.resize_exact (count)))
+ {
+ for (uint32_t i = 0; i < count; ++i)
+ {
+ hb_tag_t tag = values[i].axisTag;
+ float value = values[i].value;
+ vars[i] = {tag, value};
+ }
+ hb_font_set_variations (font, vars.arrayZ, vars.length);
+ }
+ }
+ }
+ dw_face5->Release ();
+ }
+
+ dw_font->AddRef ();
+ font->data.directwrite.cmpexch (nullptr, (hb_directwrite_font_data_t *) dw_font);
+
+done:
+ dw_face->Release ();
+ return font;
+}
+
+/**
+* hb_directwrite_font_get_dw_font:
+* @font: a #hb_font_t object
+*
+* Gets the DirectWrite IDWriteFont associated with @font.
+*
+* Return value: DirectWrite IDWriteFont object corresponding to the given input
+*
+* Since: 10.3.0
+**/
+IDWriteFont *
+hb_directwrite_font_get_dw_font (hb_font_t *font)
+{
+ return (IDWriteFont *) (const void *) font->data.directwrite;
+}
+
#endif
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h 2025-03-08 22:22:06 UTC (rev 74540)
@@ -30,11 +30,25 @@
HB_BEGIN_DECLS
HB_EXTERN hb_face_t *
-hb_directwrite_face_create (IDWriteFontFace *font_face);
+hb_directwrite_face_create (IDWriteFontFace *dw_face);
HB_EXTERN IDWriteFontFace *
+hb_directwrite_face_get_dw_font_face (hb_face_t *face);
+
+HB_EXTERN hb_font_t *
+hb_directwrite_font_create (IDWriteFont *dw_font);
+
+HB_EXTERN IDWriteFont *
+hb_directwrite_font_get_dw_font (hb_font_t *font);
+
+#ifndef HB_DISABLE_DEPRECATED
+
+HB_DEPRECATED_FOR (hb_directwrite_face_get_dw_font_face)
+HB_EXTERN IDWriteFontFace *
hb_directwrite_face_get_font_face (hb_face_t *face);
+#endif
+
HB_END_DECLS
#endif /* HB_DIRECTWRITE_H */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -291,6 +291,7 @@
return face;
}
+#ifndef HB_NO_OPEN
/**
* hb_face_create_from_file_or_fail:
* @file_name: A font filename
@@ -317,6 +318,7 @@
return face;
}
+#endif
/**
* hb_face_get_empty:
@@ -491,9 +493,10 @@
* hb_face_reference_blob:
* @face: A face object
*
- * Fetches a pointer to the binary blob that contains the
- * specified face. Returns an empty blob if referencing face data is not
- * possible.
+ * Fetches a pointer to the binary blob that contains the specified face.
+ * If referencing the face data is not possible, this function creates a blob
+ * out of individual table blobs if hb_face_get_table_tags() works with this
+ * face, otherwise it returns an empty blob.
*
* Return value: (transfer full): A pointer to the blob for @face
*
@@ -502,7 +505,41 @@
hb_blob_t *
hb_face_reference_blob (hb_face_t *face)
{
- return face->reference_table (HB_TAG_NONE);
+ hb_blob_t *blob = face->reference_table (HB_TAG_NONE);
+
+ if (blob == hb_blob_get_empty ())
+ {
+ // If referencing the face blob is not possible (e.g. not implemented by the
+ // font functions), use face builder to create a blob out of individual
+ // table blobs.
+ unsigned total_count = hb_face_get_table_tags (face, 0, nullptr, nullptr);
+ if (total_count)
+ {
+ hb_tag_t tags[64];
+ unsigned count = ARRAY_LENGTH (tags);
+ hb_face_t* builder = hb_face_builder_create ();
+
+ for (unsigned offset = 0; offset < total_count; offset += count)
+ {
+ hb_face_get_table_tags (face, offset, &count, tags);
+ if (unlikely (!count))
+ break; // Allocation error
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (unlikely (!tags[i]))
+ continue;
+ hb_blob_t *table = hb_face_reference_table (face, tags[i]);
+ hb_face_builder_add_table (builder, tags[i], table);
+ hb_blob_destroy (table);
+ }
+ }
+
+ blob = hb_face_reference_blob (builder);
+ hb_face_destroy (builder);
+ }
+ }
+
+ return blob;
}
/**
@@ -644,6 +681,7 @@
{
if (destroy)
destroy (user_data);
+ return;
}
if (face->get_table_tags_destroy)
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h 2025-03-08 22:22:06 UTC (rev 74540)
@@ -73,9 +73,14 @@
* @tag: the tag of the table to reference
* @user_data: User data pointer passed by the caller
*
- * Callback function for hb_face_create_for_tables().
+ * Callback function for hb_face_create_for_tables(). The @tag is the tag of the
+ * table to reference, and the special tag #HB_TAG_NONE is used to reference the
+ * blob of the face itself. If referencing the face blob is not possible, it is
+ * recommended to set hb_get_table_tags_func_t on the @face to allow
+ * hb_face_reference_blob() to create a face blob out of individual table blobs.
*
- * Return value: (transfer full): A pointer to the @tag table within @face
+ * Return value: (transfer full): A pointer to the @tag table within @face or
+ * `NULL` if the table is not found or cannot be referenced.
*
* Since: 0.9.2
*/
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft-colr.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft-colr.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft-colr.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -27,6 +27,7 @@
#include "hb.hh"
+#include "hb-decycler.hh"
#include "hb-paint-extents.hh"
#include FT_COLOR_H
@@ -105,8 +106,8 @@
FT_Color *palette;
unsigned palette_index;
hb_color_t foreground;
- hb_map_t current_glyphs;
- hb_map_t current_layers;
+ hb_decycler_t glyphs_decycler;
+ hb_decycler_t layers_decycler;
int depth_left = HB_MAX_NESTING_LEVEL;
int edge_count = HB_MAX_GRAPH_EDGE_COUNT;
};
@@ -218,22 +219,19 @@
case FT_COLR_PAINTFORMAT_COLR_LAYERS:
{
FT_OpaquePaint other_paint = {0};
+ hb_decycler_node_t node (c->layers_decycler);
while (FT_Get_Paint_Layers (ft_face,
&paint.u.colr_layers.layer_iterator,
&other_paint))
{
- unsigned i = paint.u.colr_layers.layer_iterator.layer;
-
- if (unlikely (c->current_layers.has (i)))
+ // FreeType doesn't provide a way to get the layer index, so we use the pointer
+ // for cycle detection.
+ if (unlikely (!node.visit ((uintptr_t) other_paint.p)))
continue;
- c->current_layers.add (i);
-
c->funcs->push_group (c->data);
c->recurse (other_paint);
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
-
- c->current_layers.del (i);
}
}
break;
@@ -333,11 +331,10 @@
{
hb_codepoint_t gid = paint.u.colr_glyph.glyphID;
- if (unlikely (c->current_glyphs.has (gid)))
+ hb_decycler_node_t node (c->glyphs_decycler);
+ if (unlikely (!node.visit (gid)))
return;
- c->current_glyphs.add (gid);
-
c->funcs->push_inverse_root_transform (c->data, c->font);
c->ft_font->lock.unlock ();
if (c->funcs->color_glyph (c->data, gid, c->font))
@@ -344,7 +341,6 @@
{
c->ft_font->lock.lock ();
c->funcs->pop_transform (c->data);
- c->current_glyphs.del (gid);
return;
}
c->ft_font->lock.lock ();
@@ -380,8 +376,6 @@
if (has_clip_box)
c->funcs->pop_clip (c->data);
-
- c->current_glyphs.del (gid);
}
}
break;
@@ -506,7 +500,8 @@
hb_ft_paint_context_t c (ft_font, font,
paint_funcs, paint_data,
palette, palette_index, foreground);
- c.current_glyphs.add (gid);
+ hb_decycler_node_t node (c.glyphs_decycler);
+ node.visit (gid);
bool is_bounded = true;
FT_ClipBox clip_box;
@@ -530,7 +525,8 @@
hb_ft_paint_context_t ce (ft_font, font,
extents_funcs, &extents_data,
palette, palette_index, foreground);
- ce.current_glyphs.add (gid);
+ hb_decycler_node_t node2 (ce.glyphs_decycler);
+ node2.visit (gid);
ce.funcs->push_root_transform (ce.data, font);
ce.recurse (paint);
ce.funcs->pop_transform (ce.data);
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -37,7 +37,11 @@
#include "hb-draw.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
+#ifndef HB_NO_AAT
+#include "hb-aat-layout-trak-table.hh"
+#endif
#include "hb-ot-os2-table.hh"
+#include "hb-ot-stat-table.hh"
#include "hb-ot-shaper-arabic-pua.hh"
#include "hb-paint.hh"
@@ -275,7 +279,7 @@
}
/**
- * hb_ft_font_get_face: (skip)
+ * hb_ft_font_get_ft_face: (skip)
* @font: #hb_font_t to work upon
*
* Fetches the FT_Face associated with the specified #hb_font_t
@@ -286,10 +290,10 @@
*
* Return value: (nullable): the FT_Face found or `NULL`
*
- * Since: 0.9.2
+ * Since: 10.4.0
**/
FT_Face
-hb_ft_font_get_face (hb_font_t *font)
+hb_ft_font_get_ft_face (hb_font_t *font)
{
if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
return nullptr;
@@ -299,7 +303,32 @@
return ft_font->ft_face;
}
+#ifndef HB_DISABLE_DEPRECATED
+
/**
+ * hb_ft_font_get_face: (skip)
+ * @font: #hb_font_t to work upon
+ *
+ * Fetches the FT_Face associated with the specified #hb_font_t
+ * font object.
+ *
+ * This function works with #hb_font_t objects created by
+ * hb_ft_font_create() or hb_ft_font_create_referenced().
+ *
+ * Return value: (nullable): the FT_Face found or `NULL`
+ *
+ * Since: 0.9.2
+ * Deprecated: 10.4.0: Use hb_ft_font_get_ft_face() instead.
+ **/
+FT_Face
+hb_ft_font_get_face (hb_font_t *font)
+{
+ return hb_ft_font_get_ft_face (font);
+}
+
+#endif
+
+/**
* hb_ft_font_lock_face: (skip)
* @font: #hb_font_t to work upon
*
@@ -502,6 +531,26 @@
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
}
+
+#ifndef HB_NO_AAT
+ /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
+#ifndef HB_NO_STYLE
+ bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
+#else
+ bool apply_trak = false;
+#endif
+ if (apply_trak)
+ {
+ hb_position_t tracking = font->face->table.trak->get_h_tracking (font);
+ first_advance = orig_first_advance;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance += tracking;
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
+#endif
}
#ifndef HB_NO_VERTICAL
@@ -538,7 +587,20 @@
* have a Y growing upward. Hence the extra negation. */
hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
- return ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength);
+ v = ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength);
+
+#ifndef HB_NO_AAT
+ /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
+#ifndef HB_NO_STYLE
+ bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
+#else
+ bool apply_trak = false;
+#endif
+ if (apply_trak)
+ v += font->face->table.trak->get_v_tracking (font);
+#endif
+
+ return v;
}
#endif
@@ -1290,7 +1352,7 @@
*
* If you know you have valid reasons not to use hb_ft_font_create_referenced(),
* then it is the client program's responsibility to destroy @ft_face
- * after the #hb_font_t font object has been destroyed.
+ * only after the #hb_font_t font object has been destroyed.
*
* HarfBuzz will use the @destroy callback on the #hb_font_t font object
* if it is supplied when you use this function. However, even if @destroy
@@ -1598,6 +1660,11 @@
void
hb_ft_font_set_funcs (hb_font_t *font)
{
+ // In case of failure...
+ hb_font_set_funcs (font,
+ hb_font_funcs_get_empty (),
+ nullptr, nullptr);
+
hb_blob_t *blob = hb_face_reference_blob (font->face);
unsigned int blob_length;
const char *blob_data = hb_blob_get_data (blob, &blob_length);
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h 2025-03-08 22:22:06 UTC (rev 74540)
@@ -111,7 +111,7 @@
hb_ft_font_create_referenced (FT_Face ft_face);
HB_EXTERN FT_Face
-hb_ft_font_get_face (hb_font_t *font);
+hb_ft_font_get_ft_face (hb_font_t *font);
HB_EXTERN FT_Face
hb_ft_font_lock_face (hb_font_t *font);
@@ -142,7 +142,14 @@
HB_EXTERN void
hb_ft_font_set_funcs (hb_font_t *font);
+#ifndef HB_DISABLE_DEPRECATED
+HB_DEPRECATED_FOR (hb_ft_font_get_ft_face)
+HB_EXTERN FT_Face
+hb_ft_font_get_face (hb_font_t *font);
+
+#endif
+
HB_END_DECLS
#endif /* HB_FT_H */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-geometry.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-geometry.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-geometry.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -83,6 +83,13 @@
float x0, float y0) :
xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {}
+ bool is_identity () const
+ {
+ return xx == 1.f && yx == 0.f &&
+ xy == 0.f && yy == 1.f &&
+ x0 == 0.f && y0 == 0.f;
+ }
+
void multiply (const hb_transform_t &o)
{
/* Copied from cairo, with "o" being "a" there and "this" being "b" there. */
@@ -201,6 +208,8 @@
float y0 = 0.f;
};
+#define HB_TRANSFORM_IDENTITY hb_transform_t{1.f, 0.f, 0.f, 1.f, 0.f, 0.f}
+
struct hb_bounds_t
{
enum status_t {
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -87,20 +87,11 @@
return pb->cmp (*pa);
}
template <typename Type2,
- hb_enable_if (std::is_integral<Type2>::value &&
- sizeof (Type2) < sizeof (int) &&
- sizeof (Type) < sizeof (int))>
- int cmp (Type2 a) const
- {
- Type b = v;
- return (int) a - (int) b;
- }
- template <typename Type2,
hb_enable_if (hb_is_convertible (Type2, Type))>
int cmp (Type2 a) const
{
Type b = v;
- return a < b ? -1 : a == b ? 0 : +1;
+ return (a > b) - (a < b);
}
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -299,11 +290,6 @@
struct VarIdx : HBUINT32 {
static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu;
static_assert (NO_VARIATION == HB_OT_LAYOUT_NO_VARIATIONS_INDEX, "");
- static uint32_t add (uint32_t i, unsigned short v)
- {
- if (i == NO_VARIATION) return i;
- return i + v;
- }
VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
};
DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx);
@@ -1747,6 +1733,19 @@
else if ((control & VALUES_SIZE_MASK) == VALUES_ARE_WORDS)
{
if (unlikely (p + run_count * HBINT16::static_size > end)) return false;
+#ifndef HB_OPTIMIZE_SIZE
+ for (; i + 3 < stop; i += 4)
+ {
+ values.arrayZ[i] = * (const HBINT16 *) p;
+ p += HBINT16::static_size;
+ values.arrayZ[i + 1] = * (const HBINT16 *) p;
+ p += HBINT16::static_size;
+ values.arrayZ[i + 2] = * (const HBINT16 *) p;
+ p += HBINT16::static_size;
+ values.arrayZ[i + 3] = * (const HBINT16 *) p;
+ p += HBINT16::static_size;
+ }
+#endif
for (; i < stop; i++)
{
values.arrayZ[i] = * (const HBINT16 *) p;
@@ -1765,10 +1764,17 @@
else if ((control & VALUES_SIZE_MASK) == VALUES_ARE_BYTES)
{
if (unlikely (p + run_count > end)) return false;
+#ifndef HB_OPTIMIZE_SIZE
+ for (; i + 3 < stop; i += 4)
+ {
+ values.arrayZ[i] = * (const HBINT8 *) p++;
+ values.arrayZ[i + 1] = * (const HBINT8 *) p++;
+ values.arrayZ[i + 2] = * (const HBINT8 *) p++;
+ values.arrayZ[i + 3] = * (const HBINT8 *) p++;
+ }
+#endif
for (; i < stop; i++)
- {
values.arrayZ[i] = * (const HBINT8 *) p++;
- }
}
}
return true;
@@ -1777,12 +1783,12 @@
struct iter_t : hb_iter_with_fallback_t<iter_t, int>
{
iter_t (const unsigned char *p_, unsigned len_)
- : p (p_), end (p_ + len_)
+ : p (p_), endp (p_ + len_)
{ if (ensure_run ()) read_value (); }
private:
const unsigned char *p;
- const unsigned char * const end;
+ const unsigned char * const endp;
int current_value = 0;
signed run_count = 0;
unsigned width = 0;
@@ -1791,7 +1797,7 @@
{
if (likely (run_count > 0)) return true;
- if (unlikely (p >= end))
+ if (unlikely (p >= endp))
{
run_count = 0;
current_value = 0;
@@ -1810,7 +1816,7 @@
default: assert (false);
}
- if (unlikely (p + run_count * width > end))
+ if (unlikely (p + run_count * width > endp))
{
run_count = 0;
current_value = 0;
@@ -1837,7 +1843,7 @@
__item_t__ __item__ () const
{ return current_value; }
- bool __more__ () const { return run_count || p < end; }
+ bool __more__ () const { return run_count || p < endp; }
void __next__ ()
{
run_count--;
@@ -1864,10 +1870,146 @@
{ return p != o.p || run_count != o.run_count; }
iter_t __end__ () const
{
- iter_t it (end, 0);
+ iter_t it (endp, 0);
return it;
}
};
+
+ struct fetcher_t
+ {
+ fetcher_t (const unsigned char *p_, unsigned len_)
+ : p (p_), end (p_ + len_) {}
+
+ private:
+ const unsigned char *p;
+ const unsigned char * const end;
+ signed run_count = 0;
+ unsigned width = 0;
+
+ bool ensure_run ()
+ {
+ if (likely (run_count > 0)) return true;
+
+ if (unlikely (p >= end))
+ {
+ run_count = 0;
+ return false;
+ }
+
+ unsigned control = *p++;
+ run_count = (control & VALUE_RUN_COUNT_MASK) + 1;
+ width = control & VALUES_SIZE_MASK;
+ switch (width)
+ {
+ case VALUES_ARE_ZEROS: width = 0; break;
+ case VALUES_ARE_BYTES: width = HBINT8::static_size; break;
+ case VALUES_ARE_WORDS: width = HBINT16::static_size; break;
+ case VALUES_ARE_LONGS: width = HBINT32::static_size; break;
+ default: assert (false);
+ }
+
+ if (unlikely (p + run_count * width > end))
+ {
+ run_count = 0;
+ return false;
+ }
+
+ return true;
+ }
+
+ void skip (unsigned n)
+ {
+ while (n)
+ {
+ if (unlikely (!ensure_run ()))
+ return;
+ unsigned i = hb_min (n, (unsigned) run_count);
+ run_count -= i;
+ n -= i;
+ p += i * width;
+ }
+ }
+
+ template <bool scaled>
+ void _add_to (hb_array_t<float> out, float scale = 1.0f)
+ {
+ unsigned n = out.length;
+ float *arrayZ = out.arrayZ;
+
+ for (unsigned i = 0; i < n;)
+ {
+ if (unlikely (!ensure_run ()))
+ break;
+ unsigned count = hb_min (n - i, (unsigned) run_count);
+ switch (width)
+ {
+ case 1:
+ {
+ const auto *pp = (const HBINT8 *) p;
+ unsigned j = 0;
+#ifndef HB_OPTIMIZE_SIZE
+ for (; j + 3 < count; j += 4)
+ {
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ }
+#endif
+ for (; j < count; j++)
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ }
+ break;
+ case 2:
+ {
+ const auto *pp = (const HBINT16 *) p;
+ unsigned j = 0;
+#ifndef HB_OPTIMIZE_SIZE
+ for (; j + 3 < count; j += 4)
+ {
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ }
+#endif
+ for (; j < count; j++)
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ }
+ break;
+ case 4:
+ {
+ const auto *pp = (const HBINT32 *) p;
+ for (unsigned j = 0; j < count; j++)
+ *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+ }
+ break;
+ }
+ p += count * width;
+ run_count -= count;
+ i += count;
+ }
+ }
+
+ public:
+ void add_to (hb_array_t<float> out, float scale = 1.0f)
+ {
+ unsigned n = out.length;
+
+ if (scale == 0.0f)
+ {
+ skip (n);
+ return;
+ }
+
+#ifndef HB_OPTIMIZE_SIZE
+ if (scale == 1.0f)
+ _add_to<false> (out);
+ else
+#endif
+ _add_to<true> (out, scale);
+ }
+ };
};
struct TupleList : CFF2Index
@@ -1877,6 +2019,12 @@
auto bytes = CFF2Index::operator [] (i);
return TupleValues::iter_t (bytes.arrayZ, bytes.length);
}
+
+ TupleValues::fetcher_t fetcher (unsigned i) const
+ {
+ auto bytes = CFF2Index::operator [] (i);
+ return TupleValues::fetcher_t (bytes.arrayZ, bytes.length);
+ }
};
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -553,15 +553,6 @@
return true;
}
-bool OT::cff1::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
-{
- funcs->push_clip_glyph (data, glyph, font);
- funcs->color (data, true, foreground);
- funcs->pop_clip (data);
-
- return true;
-}
-
bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
#ifdef HB_NO_OT_FONT_CFF
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1462,7 +1462,6 @@
}
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
- HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
private:
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -143,15 +143,6 @@
return true;
}
-bool OT::cff2::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
-{
- funcs->push_clip_glyph (data, glyph, font);
- funcs->color (data, true, foreground);
- funcs->pop_clip (data);
-
- return true;
-}
-
struct cff2_path_param_t
{
cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -518,7 +518,6 @@
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
- HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t<const int> coords) const;
};
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -95,9 +95,12 @@
HB_OT_CORE_TABLE (OT, avar)
HB_OT_CORE_TABLE (OT, cvar)
HB_OT_ACCELERATOR (OT, gvar)
+#ifndef HB_NO_BEYOND_64K
+HB_OT_ACCELERATOR (OT, GVAR)
+#endif
HB_OT_CORE_TABLE (OT, MVAR)
#ifndef HB_NO_VAR_COMPOSITES
-HB_OT_CORE_TABLE (OT, VARC)
+HB_OT_ACCELERATOR (OT, VARC)
#endif
#endif
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -41,6 +41,7 @@
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-var-varc-table.hh"
#include "hb-aat-layout-kerx-table.hh"
#include "hb-aat-layout-morx-table.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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -36,6 +36,9 @@
#include "hb-ot-face.hh"
#include "hb-outline.hh"
+#ifndef HB_NO_AAT
+#include "hb-aat-layout-trak-table.hh"
+#endif
#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-cff2-table.hh"
@@ -42,7 +45,7 @@
#include "hb-ot-cff1-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-post-table.hh"
-#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-stat-table.hh"
#include "hb-ot-var-varc-table.hh"
#include "hb-ot-vorg-table.hh"
#include "OT/Color/CBDT/CBDT.hh"
@@ -73,6 +76,10 @@
{
const hb_ot_face_t *ot_face;
+#ifndef HB_NO_AAT
+ bool apply_trak;
+#endif
+
#ifndef HB_NO_OT_FONT_CMAP_CACHE
hb_ot_font_cmap_cache_t *cmap_cache;
#endif
@@ -91,6 +98,15 @@
ot_font->ot_face = &font->face->table;
+#ifndef HB_NO_AAT
+ /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
+#ifndef HB_NO_STYLE
+ ot_font->apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
+#else
+ ot_font->apply_trak = false;
+#endif
+#endif
+
#ifndef HB_NO_OT_FONT_CMAP_CACHE
// retry:
auto *cmap_cache = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face,
@@ -200,7 +216,6 @@
unsigned advance_stride,
void *user_data HB_UNUSED)
{
-
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
@@ -292,6 +307,20 @@
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
}
+
+#ifndef HB_NO_AAT
+ if (ot_font->apply_trak)
+ {
+ hb_position_t tracking = font->face->table.trak->get_h_tracking (font);
+ first_advance = orig_first_advance;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance += tracking;
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
+#endif
}
#ifndef HB_NO_VERTICAL
@@ -356,6 +385,20 @@
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
}
+
+#ifndef HB_NO_AAT
+ if (ot_font->apply_trak)
+ {
+ hb_position_t tracking = font->face->table.trak->get_v_tracking (font);
+ first_advance = orig_first_advance;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance += tracking;
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
+#endif
}
#endif
@@ -568,14 +611,11 @@
if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
#endif
#endif
-#ifndef HB_NO_VAR_COMPOSITES
- if (font->face->table.VARC->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
-#endif
- if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
-#ifndef HB_NO_CFF
- if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
- if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
-#endif
+
+ // Outline glyph
+ paint_funcs->push_clip_glyph (paint_data, glyph, font);
+ paint_funcs->color (paint_data, true, foreground);
+ paint_funcs->pop_clip (paint_data);
}
#endif
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -95,7 +95,7 @@
bool serialize (hb_serialize_context_t *c,
unsigned version,
Iterator it,
- const hb_vector_t<hb_codepoint_pair_t> &new_to_old_gid_list,
+ hb_array_t<const hb_codepoint_pair_t> new_to_old_gid_list,
unsigned num_glyphs)
{
TRACE_SERIALIZE (this);
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -182,7 +182,7 @@
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
- const hb_vector_t<hb_codepoint_pair_t> new_to_old_gid_list,
+ hb_array_t<const hb_codepoint_pair_t> new_to_old_gid_list,
unsigned num_long_metrics,
unsigned total_num_metrics)
{
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -342,7 +342,7 @@
}
bool apply (AAT::hb_aat_apply_context_t *c,
- const AAT::kern_accelerator_data_t *accel_data = nullptr) const
+ const AAT::kern_accelerator_data_t &accel_data) const
{ return dispatch (c, accel_data); }
template <typename context_t, typename ...Ts>
@@ -395,7 +395,7 @@
bool apply (AAT::hb_aat_apply_context_t *c) const
{
- return table->apply (c, &accel_data);
+ return table->apply (c, accel_data);
}
hb_blob_ptr_t<kern> table;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -460,7 +460,7 @@
{ return (this+baseValues).get_base_coord (baseline_tag_index); }
bool has_values () const { return baseValues; }
- bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ }
+ bool has_min_max () const { return defaultMinMax || baseLangSysRecords; }
void collect_variation_indices (const hb_subset_plan_t* plan,
hb_set_t& varidx_set /* OUT */) const
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -34,6 +34,7 @@
#include "hb-open-type.hh"
#include "hb-set.hh"
#include "hb-bimap.hh"
+#include "hb-cache.hh"
#include "OT/Layout/Common/Coverage.hh"
#include "OT/Layout/types.hh"
@@ -2076,6 +2077,15 @@
default:return 0;
}
}
+ unsigned int get_class (hb_codepoint_t glyph_id,
+ hb_ot_lookup_cache_t *cache) const
+ {
+ unsigned klass;
+ if (cache && cache->get (glyph_id, &klass)) return klass;
+ klass = get_class (glyph_id);
+ if (cache) cache->set (glyph_id, klass);
+ return klass;
+ }
unsigned get_population () const
{
@@ -3137,23 +3147,14 @@
{
auto &deltaSets = StructAfter<decltype (deltaSetsX)> (regionIndices);
- auto values_iter = deltaSets[inner];
-
+ auto values_iter = deltaSets.fetcher (inner);
unsigned regionCount = regionIndices.len;
- unsigned count = out.length;
for (unsigned regionIndex = 0; regionIndex < regionCount; regionIndex++)
{
float scalar = regions.evaluate (regionIndices.arrayZ[regionIndex],
coords, coord_count,
cache);
- if (scalar == 1.f)
- for (unsigned i = 0; i < count; i++)
- out.arrayZ[i] += *values_iter++;
- else if (scalar)
- for (unsigned i = 0; i < count; i++)
- out.arrayZ[i] += *values_iter++ * scalar;
- else
- values_iter += count;
+ values_iter.add_to (out, scalar);
}
}
@@ -3439,7 +3440,7 @@
{
using cache_t = SparseVarRegionList::cache_t;
- cache_t *create_cache () const
+ cache_t *create_cache (hb_array_t<float> static_cache = hb_array_t<float> ()) const
{
#ifdef HB_NO_VAR
return nullptr;
@@ -3447,8 +3448,14 @@
auto &r = this+regions;
unsigned count = r.regions.len;
- float *cache = (float *) hb_malloc (sizeof (float) * count);
- if (unlikely (!cache)) return nullptr;
+ float *cache;
+ if (count <= static_cache.length)
+ cache = static_cache.arrayZ;
+ else
+ {
+ cache = (float *) hb_malloc (sizeof (float) * count);
+ if (unlikely (!cache)) return nullptr;
+ }
for (unsigned i = 0; i < count; i++)
cache[i] = REGION_CACHE_ITEM_CACHE_INVALID;
@@ -3456,7 +3463,12 @@
return cache;
}
- static void destroy_cache (cache_t *cache) { hb_free (cache); }
+ static void destroy_cache (cache_t *cache,
+ hb_array_t<float> static_cache = hb_array_t<float> ())
+ {
+ if (cache != static_cache.arrayZ)
+ hb_free (cache);
+ }
private:
void get_delta (unsigned int outer, unsigned int inner,
@@ -3731,11 +3743,13 @@
float operator() (uint32_t varIdx, unsigned short offset = 0) const
{
+ if (!coords || varIdx == VarIdx::NO_VARIATION)
+ return 0.f;
+
+ varIdx += offset;
if (varIdxMap)
- varIdx = varIdxMap->map (VarIdx::add (varIdx, offset));
- else
- varIdx += offset;
- return coords ? varStore->get_delta (varIdx, coords, cache) : 0.f;
+ varIdx = varIdxMap->map (varIdx);
+ return varStore->get_delta (varIdx, coords, cache);
}
const ItemVariationStore *varStore;
@@ -3767,12 +3781,11 @@
void operator() (hb_array_t<float> out, uint32_t varIdx, unsigned short offset = 0) const
{
- if (coords)
+ if (coords && varIdx != VarIdx::NO_VARIATION)
{
+ varIdx += offset;
if (varIdxMap)
- varIdx = varIdxMap->map (VarIdx::add (varIdx, offset));
- else
- varIdx += offset;
+ varIdx = varIdxMap->map (varIdx);
varStore->get_delta (varIdx, coords, out, cache);
}
else
@@ -3890,8 +3903,8 @@
{
// add axisIndex->value into the hashmap so we can check if the record is
// unique with variations
- int16_t int_filter_max_val = filterRangeMaxValue.to_int ();
- int16_t int_filter_min_val = filterRangeMinValue.to_int ();
+ uint16_t int_filter_max_val = (uint16_t) filterRangeMaxValue.to_int ();
+ uint16_t int_filter_min_val = (uint16_t) filterRangeMinValue.to_int ();
hb_codepoint_t val = (int_filter_max_val << 16) + int_filter_min_val;
condition_map->set (axisIndex, val);
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -713,6 +713,7 @@
recurse_func_t recurse_func = nullptr;
const GDEF &gdef;
const GDEF::accelerator_t &gdef_accel;
+ const hb_ot_layout_lookup_accelerator_t *lookup_accel = nullptr;
const ItemVariationStore &var_store;
ItemVariationStore::cache_t *var_store_cache;
hb_set_digest_t digest;
@@ -762,10 +763,12 @@
nullptr
#endif
),
- digest (buffer_->digest ()),
direction (buffer_->props.direction),
has_glyph_classes (gdef.has_glyph_classes ())
- { init_iters (); }
+ {
+ init_iters ();
+ buffer->collect_codepoints (digest);
+ }
~hb_ot_apply_context_t ()
{
@@ -899,6 +902,13 @@
}
};
+enum class hb_ot_lookup_cache_op_t
+{
+ CREATE,
+ ENTER,
+ LEAVE,
+ DESTROY,
+};
struct hb_accelerate_subtables_context_t :
hb_dispatch_context_t<hb_accelerate_subtables_context_t>
@@ -923,19 +933,23 @@
}
template <typename T>
- static inline auto cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) )
- template <typename T>
- static inline bool cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; }
+ static inline auto cache_func_ (void *p,
+ hb_ot_lookup_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; }
template <typename Type>
- static inline bool cache_func_to (const void *obj, hb_ot_apply_context_t *c, bool enter)
+ static inline void * cache_func_to (void *p,
+ hb_ot_lookup_cache_op_t op)
{
- const Type *typed_obj = (const Type *) obj;
- return cache_func_ (typed_obj, c, enter, hb_prioritize);
+ 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 bool (*hb_cache_func_t) (const void *obj, hb_ot_apply_context_t *c, bool enter);
+ typedef void * (*hb_cache_func_t) (void *p, hb_ot_lookup_cache_op_t op);
struct hb_applicable_t
{
@@ -972,11 +986,11 @@
}
bool cache_enter (hb_ot_apply_context_t *c) const
{
- return cache_func (obj, c, true);
+ return (bool) cache_func (c, hb_ot_lookup_cache_op_t::ENTER);
}
void cache_leave (hb_ot_apply_context_t *c) const
{
- cache_func (obj, c, false);
+ cache_func (c, hb_ot_lookup_cache_op_t::LEAVE);
}
#endif
@@ -2623,25 +2637,35 @@
unsigned c = (this+classDef).cost () * ruleSet.len;
return c >= 4 ? c : 0;
}
- bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+ static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
{
- if (enter)
+ switch (op)
{
- if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
- return 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 true;
+ 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;
}
- else
- {
- c->new_syllables = (unsigned) -1;
- HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
- return true;
- }
+ return nullptr;
}
bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
@@ -2650,7 +2674,7 @@
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
const ClassDef &class_def = this+classDef;
@@ -2836,7 +2860,7 @@
{
TRACE_APPLY (this);
unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
struct ContextApplyLookupContext lookup_context = {
@@ -3650,7 +3674,7 @@
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextApplyLookupContext lookup_context = {
@@ -3861,28 +3885,37 @@
unsigned cache_cost () const
{
- unsigned c = (this+lookaheadClassDef).cost () * ruleSet.len;
- return c >= 4 ? c : 0;
+ return (this+lookaheadClassDef).cost () * ruleSet.len;
}
- bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+ static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
{
- if (enter)
+ switch (op)
{
- if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
- return 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 true;
+ 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;
}
- else
- {
- c->new_syllables = (unsigned) -1;
- HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
- return true;
- }
+ return nullptr;
}
bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
@@ -3891,7 +3924,7 @@
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
const ClassDef &backtrack_class_def = this+backtrackClassDef;
const ClassDef &input_class_def = this+inputClassDef;
@@ -4137,7 +4170,7 @@
const auto &input = StructAfter<decltype (inputX)> (backtrack);
unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
+ if (index == NOT_COVERED) return_trace (false);
const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
@@ -4408,7 +4441,18 @@
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->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;
@@ -4417,6 +4461,17 @@
return thiz;
}
+ 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);
+ }
+#endif
+ }
+
bool may_have (hb_codepoint_t g) const
{ return digest.may_have (g); }
@@ -4425,6 +4480,7 @@
#endif
bool apply (hb_ot_apply_context_t *c, unsigned subtables_count, bool use_cache) const
{
+ c->lookup_accel = this;
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
if (use_cache)
{
@@ -4464,10 +4520,13 @@
hb_set_digest_t digest;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ public:
+ void *cache = nullptr;
private:
-#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
unsigned cache_user_idx = (unsigned) -1;
#endif
+ private:
hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
};
@@ -4852,7 +4911,12 @@
~accelerator_t ()
{
for (unsigned int i = 0; i < this->lookup_count; i++)
- hb_free (this->accels[i]);
+ {
+ auto *accel = this->accels[i].get_relaxed ();
+ if (accel)
+ accel->fini ();
+ hb_free (accel);
+ }
hb_free (this->accels);
this->table.destroy ();
}
@@ -4873,6 +4937,7 @@
if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
{
+ accel->fini ();
hb_free (accel);
goto retry;
}
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1923,9 +1923,10 @@
while (buffer->idx < buffer->len && buffer->successful)
{
bool applied = false;
- if (accel.digest.may_have (buffer->cur().codepoint) &&
- (buffer->cur().mask & c->lookup_mask) &&
- c->check_glyph_property (&buffer->cur(), c->lookup_props))
+ auto &cur = buffer->cur();
+ if (accel.digest.may_have (cur.codepoint) &&
+ (cur.mask & c->lookup_mask) &&
+ c->check_glyph_property (&cur, c->lookup_props))
{
applied = accel.apply (c, subtable_count, use_cache);
}
@@ -1951,9 +1952,10 @@
hb_buffer_t *buffer = c->buffer;
do
{
- if (accel.digest.may_have (buffer->cur().codepoint) &&
- (buffer->cur().mask & c->lookup_mask) &&
- c->check_glyph_property (&buffer->cur(), c->lookup_props))
+ auto &cur = buffer->cur();
+ if (accel.digest.may_have (cur.codepoint) &&
+ (cur.mask & c->lookup_mask) &&
+ c->check_glyph_property (&cur, c->lookup_props))
ret |= accel.apply (c, subtable_count, false);
/* The reverse lookup doesn't "advance" cursor (for good reason). */
@@ -2033,7 +2035,7 @@
* (plus some past glyphs).
*
* Only try applying the lookup if there is any overlap. */
- if (accel->digest.may_have (c.digest))
+ if (accel->digest.may_intersect (c.digest))
{
c.set_lookup_index (lookup_index);
c.set_lookup_mask (lookup.mask, false);
@@ -2059,7 +2061,7 @@
if (stage->pause_func (plan, font, buffer))
{
/* Refresh working buffer digest since buffer changed. */
- c.digest = buffer->digest ();
+ buffer->collect_codepoints (c.digest);
}
}
}
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -339,6 +339,11 @@
!_hb_glyph_info_substituted (info);
}
static inline void
+_hb_glyph_info_set_default_ignorable (hb_glyph_info_t *info)
+{
+ info->unicode_props() |= UPROPS_MASK_IGNORABLE;
+}
+static inline void
_hb_glyph_info_clear_default_ignorable (hb_glyph_info_t *info)
{
info->unicode_props() &= ~ UPROPS_MASK_IGNORABLE;
@@ -360,7 +365,7 @@
info->unicode_props() |= UPROPS_MASK_CONTINUATION;
}
static inline void
-_hb_glyph_info_reset_continuation (hb_glyph_info_t *info)
+_hb_glyph_info_clear_continuation (hb_glyph_info_t *info)
{
info->unicode_props() &= ~ UPROPS_MASK_CONTINUATION;
}
@@ -633,8 +638,7 @@
}
/* Make sure no one directly touches our props... */
-#undef unicode_props0
-#undef unicode_props1
+#undef unicode_props
#undef lig_props
#undef glyph_props
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -390,5 +390,19 @@
}
}
+unsigned int hb_ot_map_t::get_feature_tags (unsigned int start_offset, unsigned int *tag_count, hb_tag_t *tags) const
+{
+ if (tag_count)
+ {
+ auto sub_features = features.as_array ().sub_array (start_offset, tag_count);
+ if (tags)
+ {
+ for (unsigned int i = 0; i < sub_features.length; i++)
+ tags[i] = sub_features[i].tag;
+ }
+ }
+ return features.length;
+}
+
#endif
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -166,6 +166,9 @@
const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+ HB_INTERNAL unsigned int get_feature_tags (unsigned int start_offset,
+ unsigned int *tag_count, /* IN/OUT */
+ hb_tag_t *tags /* OUT */) const;
public:
hb_tag_t chosen_script[2];
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -46,7 +46,9 @@
#include "hb-set.hh"
#include "hb-aat-layout.hh"
+#include "hb-ot-stat-table.hh"
+
static inline bool
_hb_codepoint_is_regional_indicator (hb_codepoint_t u)
{ return hb_in_range<hb_codepoint_t> (u, 0x1F1E6u, 0x1F1FFu); }
@@ -121,10 +123,6 @@
plan.kern_mask = plan.map.get_mask (kern_tag);
plan.requested_kerning = !!plan.kern_mask;
#endif
-#ifndef HB_NO_AAT_SHAPE
- plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
- plan.requested_tracking = !!plan.trak_mask;
-#endif
bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
bool disable_gpos = plan.shaper->gpos_tag &&
@@ -207,9 +205,6 @@
https://github.com/harfbuzz/harfbuzz/issues/2967. */
if (plan.apply_morx)
plan.adjust_mark_positioning_when_zeroing = false;
-
- /* Currently we always apply trak. */
- plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
#endif
}
@@ -274,11 +269,6 @@
#endif
else if (this->apply_fallback_kern)
_hb_ot_shape_fallback_kern (this, font, buffer);
-
-#ifndef HB_NO_AAT_SHAPE
- if (this->apply_trak)
- hb_aat_layout_track (this, font, buffer);
-#endif
}
@@ -346,13 +336,6 @@
/* Random! */
map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
-#ifndef HB_NO_AAT_SHAPE
- /* Tracking. We enable dummy feature here just to allow disabling
- * AAT 'trak' table using features.
- * https://github.com/harfbuzz/harfbuzz/issues/1303 */
- map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
-#endif
-
map->enable_feature (HB_TAG ('H','a','r','f')); /* Considered required. */
map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */
@@ -1277,6 +1260,36 @@
}
+/**
+ * hb_ot_shape_plan_get_feature_tags:
+ * @shape_plan: A shaping plan
+ * @start_offset: The index of first feature to retrieve
+ * @tag_count: (inout): Input = the maximum number of features to return;
+ * Output = the actual number of features returned (may be zero)
+ * @tags: (out) (array length=tag_count): The array of enabled feature
+ *
+ * Fetches the list of OpenType feature tags enabled for a shaping plan, if possible.
+ *
+ * Return value: Total number of feature tagss.
+ *
+ * Since: 10.3.0
+ */
+unsigned int
+hb_ot_shape_plan_get_feature_tags (hb_shape_plan_t *shape_plan,
+ unsigned int start_offset,
+ unsigned int *tag_count, /* IN/OUT */
+ hb_tag_t *tags /* OUT */)
+{
+#ifndef HB_NO_OT_SHAPE
+ return shape_plan->ot.map.get_feature_tags (start_offset, tag_count, tags);
+#else
+ if (tag_count)
+ *tag_count = 0;
+ return 0;
+#endif
+}
+
+
/* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
static void
add_char (hb_font_t *font,
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.h 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.h 2025-03-08 22:22:06 UTC (rev 74540)
@@ -48,6 +48,12 @@
hb_tag_t table_tag,
hb_set_t *lookup_indexes /* OUT */);
+HB_EXTERN unsigned int
+hb_ot_shape_plan_get_feature_tags (hb_shape_plan_t *shape_plan,
+ unsigned int start_offset,
+ unsigned int *tag_count, /* IN/OUT */
+ hb_tag_t *tags /* OUT */);
+
HB_END_DECLS
#endif /* HB_OT_SHAPE_H */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -51,7 +51,8 @@
bool equal (const hb_ot_shape_plan_key_t *other)
{
- return 0 == hb_memcmp (this, other, sizeof (*this));
+ return variations_index[0] == other->variations_index[0] &&
+ variations_index[1] == other->variations_index[1];
}
};
@@ -79,11 +80,6 @@
#else
static constexpr hb_mask_t kern_mask = 0;
#endif
-#ifndef HB_NO_AAT_SHAPE
- hb_mask_t trak_mask;
-#else
- static constexpr hb_mask_t trak_mask = 0;
-#endif
#ifndef HB_NO_OT_KERN
bool requested_kerning : 1;
@@ -90,11 +86,6 @@
#else
static constexpr bool requested_kerning = false;
#endif
-#ifndef HB_NO_AAT_SHAPE
- bool requested_tracking : 1;
-#else
- static constexpr bool requested_tracking = false;
-#endif
#ifndef HB_NO_OT_SHAPE_FRACTIONS
bool has_frac : 1;
#else
@@ -117,11 +108,9 @@
#ifndef HB_NO_AAT_SHAPE
bool apply_kerx : 1;
bool apply_morx : 1;
- bool apply_trak : 1;
#else
static constexpr bool apply_kerx = false;
static constexpr bool apply_morx = false;
- static constexpr bool apply_trak = false;
#endif
void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -355,6 +355,8 @@
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
if (fallback_plan->lookup_array[i])
{
+ if (fallback_plan->accel_array[i])
+ fallback_plan->accel_array[i]->fini ();
hb_free (fallback_plan->accel_array[i]);
if (fallback_plan->free_lookups)
hb_free (fallback_plan->lookup_array[i]);
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-vowel-constraints.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-vowel-constraints.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-vowel-constraints.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -24,7 +24,7 @@
_output_dotted_circle (hb_buffer_t *buffer)
{
(void) buffer->output_glyph (0x25CCu);
- _hb_glyph_info_reset_continuation (&buffer->prev());
+ _hb_glyph_info_clear_continuation (&buffer->prev());
}
static void
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -6,8 +6,8 @@
*
* on files with these headers:
*
- * <meta name="updated_at" content="2024-12-05 07:13 PM" />
- * File-Date: 2024-11-19
+ * <meta name="updated_at" content="2024-12-06 06:35 AM" />
+ * File-Date: 2025-01-21
*/
#ifndef HB_OT_TAG_TABLE_HH
@@ -745,6 +745,7 @@
/*{HB_TAG('h','n','d',' '), HB_TAG('H','N','D',' ')},*/ /* Southern Hindko -> Hindko */
{HB_TAG('h','n','e',' '), HB_TAG('C','H','H',' ')}, /* Chhattisgarhi -> Chattisgarhi */
{HB_TAG('h','n','j',' '), HB_TAG('H','M','N',' ')}, /* Hmong Njua -> Hmong */
+ {HB_TAG('h','n','m',' '), HB_TAG('Z','H','S',' ')}, /* Hainanese -> Chinese, Simplified */
{HB_TAG('h','n','o',' '), HB_TAG('H','N','D',' ')}, /* Northern Hindko -> Hindko */
{HB_TAG('h','o','c',' '), HB_TAG('H','O',' ',' ')}, /* Ho */
{HB_TAG('h','o','i',' '), HB_TAG('A','T','H',' ')}, /* Holikachuk -> Athapaskan */
@@ -981,9 +982,11 @@
{HB_TAG('l','t','o',' '), HB_TAG('L','U','H',' ')}, /* Tsotso -> Luyia */
{HB_TAG('l','t','s',' '), HB_TAG('L','U','H',' ')}, /* Tachoni -> Luyia */
/*{HB_TAG('l','u','a',' '), HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */
+ {HB_TAG('l','u','h',' '), HB_TAG('Z','H','S',' ')}, /* Leizhou Chinese -> Chinese, Simplified */
/*{HB_TAG('l','u','o',' '), HB_TAG('L','U','O',' ')},*/ /* Luo (Kenya and Tanzania) */
{HB_TAG('l','u','s',' '), HB_TAG('M','I','Z',' ')}, /* Lushai -> Mizo */
{HB_TAG('l','u','s',' '), HB_TAG('Q','I','N',' ')}, /* Lushai -> Chin */
+/*{HB_TAG('l','u','t',' '), HB_TAG('L','U','T',' ')},*/ /* Lushootseed */
{HB_TAG('l','u','y',' '), HB_TAG('L','U','H',' ')}, /* Luyia [macrolanguage] */
{HB_TAG('l','u','z',' '), HB_TAG('L','R','C',' ')}, /* Southern Luri -> Luri */
{HB_TAG('l','v','i',' '), HB_TAG_NONE }, /* Lavi != Latvian */
@@ -1404,6 +1407,7 @@
{HB_TAG('s','i','g',' '), HB_TAG_NONE }, /* Paasaal != Silte Gurage */
{HB_TAG('s','i','z',' '), HB_TAG('B','B','R',' ')}, /* Siwi -> Berber */
/*{HB_TAG('s','j','a',' '), HB_TAG('S','J','A',' ')},*/ /* Epena */
+ {HB_TAG('s','j','c',' '), HB_TAG('Z','H','S',' ')}, /* Shaojiang Chinese -> Chinese, Simplified */
{HB_TAG('s','j','d',' '), HB_TAG('K','S','M',' ')}, /* Kildin Sami */
/*{HB_TAG('s','j','e',' '), HB_TAG('S','J','E',' ')},*/ /* Pite Sami */
{HB_TAG('s','j','o',' '), HB_TAG('S','I','B',' ')}, /* Xibe -> Sibe */
@@ -2386,6 +2390,26 @@
*count = i;
return true;
}
+ if (lang_matches (&lang_str[1], limit, "nm-hant-hk", 10))
+ {
+ /* Hainanese; Han (Traditional variant); Hong Kong */
+ tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
+ *count = 1;
+ return true;
+ }
+ if (lang_matches (&lang_str[1], limit, "nm-hant-mo", 10))
+ {
+ /* Hainanese; Han (Traditional variant); Macao */
+ unsigned int i;
+ hb_tag_t possible_tags[] = {
+ HB_TAG('Z','H','T','M'), /* Chinese, Traditional, Macao SAR */
+ HB_TAG('Z','H','H',' '), /* Chinese, Traditional, Hong Kong SAR */
+ };
+ for (i = 0; i < 2 && i < *count; i++)
+ tags[i] = possible_tags[i];
+ *count = i;
+ return true;
+ }
if (lang_matches (&lang_str[1], limit, "sn-hant-hk", 10))
{
/* Xiang Chinese; Han (Traditional variant); Hong Kong */
@@ -2420,6 +2444,20 @@
*count = 1;
return true;
}
+ if (lang_matches (&lang_str[1], limit, "nm-hans", 7))
+ {
+ /* Hainanese; Han (Simplified variant) */
+ tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
+ *count = 1;
+ return true;
+ }
+ if (lang_matches (&lang_str[1], limit, "nm-hant", 7))
+ {
+ /* Hainanese; Han (Traditional variant) */
+ tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
+ *count = 1;
+ return true;
+ }
if (lang_matches (&lang_str[1], limit, "sn-hans", 7))
{
/* Xiang Chinese; Han (Simplified variant) */
@@ -2464,6 +2502,36 @@
*count = 1;
return true;
}
+ if (0 == strncmp (&lang_str[1], "nm-", 3)
+ && subtag_matches (lang_str, limit, "-hk", 3))
+ {
+ /* Hainanese; Hong Kong */
+ tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
+ *count = 1;
+ return true;
+ }
+ if (0 == strncmp (&lang_str[1], "nm-", 3)
+ && subtag_matches (lang_str, limit, "-mo", 3))
+ {
+ /* Hainanese; Macao */
+ unsigned int i;
+ hb_tag_t possible_tags[] = {
+ HB_TAG('Z','H','T','M'), /* Chinese, Traditional, Macao SAR */
+ HB_TAG('Z','H','H',' '), /* Chinese, Traditional, Hong Kong SAR */
+ };
+ for (i = 0; i < 2 && i < *count; i++)
+ tags[i] = possible_tags[i];
+ *count = i;
+ return true;
+ }
+ if (0 == strncmp (&lang_str[1], "nm-", 3)
+ && subtag_matches (lang_str, limit, "-tw", 3))
+ {
+ /* Hainanese; Taiwan, Province of China */
+ tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
+ *count = 1;
+ return true;
+ }
if (0 == strncmp (&lang_str[1], "sn-", 3)
&& subtag_matches (lang_str, limit, "-hk", 3))
{
@@ -2525,6 +2593,40 @@
}
break;
case 'l':
+ if (lang_matches (&lang_str[1], limit, "uh-hant-hk", 10))
+ {
+ /* Leizhou Chinese; Han (Traditional variant); Hong Kong */
+ tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
+ *count = 1;
+ return true;
+ }
+ if (lang_matches (&lang_str[1], limit, "uh-hant-mo", 10))
+ {
+ /* Leizhou Chinese; Han (Traditional variant); Macao */
+ unsigned int i;
+ hb_tag_t possible_tags[] = {
+ HB_TAG('Z','H','T','M'), /* Chinese, Traditional, Macao SAR */
+ HB_TAG('Z','H','H',' '), /* Chinese, Traditional, Hong Kong SAR */
+ };
+ for (i = 0; i < 2 && i < *count; i++)
+ tags[i] = possible_tags[i];
+ *count = i;
+ return true;
+ }
+ if (lang_matches (&lang_str[1], limit, "uh-hans", 7))
+ {
+ /* Leizhou Chinese; Han (Simplified variant) */
+ tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
+ *count = 1;
+ return true;
+ }
+ if (lang_matches (&lang_str[1], limit, "uh-hant", 7))
+ {
+ /* Leizhou Chinese; Han (Traditional variant) */
+ tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
+ *count = 1;
+ return true;
+ }
if (lang_matches (&lang_str[1], limit, "zh-hans", 7))
{
/* Literary Chinese; Han (Simplified variant) */
@@ -2532,6 +2634,36 @@
*count = 1;
return true;
}
+ if (0 == strncmp (&lang_str[1], "uh-", 3)
+ && subtag_matches (lang_str, limit, "-hk", 3))
+ {
+ /* Leizhou Chinese; Hong Kong */
+ tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
+ *count = 1;
+ return true;
+ }
+ if (0 == strncmp (&lang_str[1], "uh-", 3)
+ && subtag_matches (lang_str, limit, "-mo", 3))
+ {
+ /* Leizhou Chinese; Macao */
+ unsigned int i;
+ hb_tag_t possible_tags[] = {
+ HB_TAG('Z','H','T','M'), /* Chinese, Traditional, Macao SAR */
+ HB_TAG('Z','H','H',' '), /* Chinese, Traditional, Hong Kong SAR */
+ };
+ for (i = 0; i < 2 && i < *count; i++)
+ tags[i] = possible_tags[i];
+ *count = i;
+ return true;
+ }
+ if (0 == strncmp (&lang_str[1], "uh-", 3)
+ && subtag_matches (lang_str, limit, "-tw", 3))
+ {
+ /* Leizhou Chinese; Taiwan, Province of China */
+ tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
+ *count = 1;
+ return true;
+ }
break;
case 'm':
if (lang_matches (&lang_str[1], limit, "np-hant-hk", 10))
@@ -2703,6 +2835,72 @@
return true;
}
break;
+ case 's':
+ if (lang_matches (&lang_str[1], limit, "jc-hant-hk", 10))
+ {
+ /* Shaojiang Chinese; Han (Traditional variant); Hong Kong */
+ tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
+ *count = 1;
+ return true;
+ }
+ if (lang_matches (&lang_str[1], limit, "jc-hant-mo", 10))
+ {
+ /* Shaojiang Chinese; Han (Traditional variant); Macao */
+ unsigned int i;
+ hb_tag_t possible_tags[] = {
+ HB_TAG('Z','H','T','M'), /* Chinese, Traditional, Macao SAR */
+ HB_TAG('Z','H','H',' '), /* Chinese, Traditional, Hong Kong SAR */
+ };
+ for (i = 0; i < 2 && i < *count; i++)
+ tags[i] = possible_tags[i];
+ *count = i;
+ return true;
+ }
+ if (lang_matches (&lang_str[1], limit, "jc-hans", 7))
+ {
+ /* Shaojiang Chinese; Han (Simplified variant) */
+ tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
+ *count = 1;
+ return true;
+ }
+ if (lang_matches (&lang_str[1], limit, "jc-hant", 7))
+ {
+ /* Shaojiang Chinese; Han (Traditional variant) */
+ tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
+ *count = 1;
+ return true;
+ }
+ if (0 == strncmp (&lang_str[1], "jc-", 3)
+ && subtag_matches (lang_str, limit, "-hk", 3))
+ {
+ /* Shaojiang Chinese; Hong Kong */
+ tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
+ *count = 1;
+ return true;
+ }
+ if (0 == strncmp (&lang_str[1], "jc-", 3)
+ && subtag_matches (lang_str, limit, "-mo", 3))
+ {
+ /* Shaojiang Chinese; Macao */
+ unsigned int i;
+ hb_tag_t possible_tags[] = {
+ HB_TAG('Z','H','T','M'), /* Chinese, Traditional, Macao SAR */
+ HB_TAG('Z','H','H',' '), /* Chinese, Traditional, Hong Kong SAR */
+ };
+ for (i = 0; i < 2 && i < *count; i++)
+ tags[i] = possible_tags[i];
+ *count = i;
+ return true;
+ }
+ if (0 == strncmp (&lang_str[1], "jc-", 3)
+ && subtag_matches (lang_str, limit, "-tw", 3))
+ {
+ /* Shaojiang Chinese; Taiwan, Province of China */
+ tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
+ *count = 1;
+ return true;
+ }
+ break;
case 'w':
if (lang_matches (&lang_str[1], limit, "uu-hant-hk", 10))
{
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -231,9 +231,9 @@
/* indices_length = point_count, indice[i] = 1 means point i is referenced */
hb_vector_t<bool> indices;
- hb_vector_t<double> deltas_x;
+ hb_vector_t<float> deltas_x;
/* empty for cvar tuples */
- hb_vector_t<double> deltas_y;
+ hb_vector_t<float> deltas_y;
/* compiled data: header and deltas
* compiled point data is saved in a hashmap within tuple_variations_t cause
@@ -299,9 +299,9 @@
return *this;
}
- tuple_delta_t& operator *= (double scalar)
+ tuple_delta_t& operator *= (float scalar)
{
- if (scalar == 1.0)
+ if (scalar == 1.0f)
return *this;
unsigned num = indices.length;
@@ -514,9 +514,9 @@
bool compile_deltas ()
{ return compile_deltas (indices, deltas_x, deltas_y, compiled_deltas); }
- static bool compile_deltas (const hb_vector_t<bool> &point_indices,
- const hb_vector_t<double> &x_deltas,
- const hb_vector_t<double> &y_deltas,
+ static bool compile_deltas (hb_array_t<const bool> point_indices,
+ hb_array_t<const float> x_deltas,
+ hb_array_t<const float> y_deltas,
hb_vector_t<unsigned char> &compiled_deltas /* OUT */)
{
hb_vector_t<int> rounded_deltas;
@@ -629,11 +629,11 @@
deltas_x.arrayZ[i] = infer_delta ((double) orig_points.arrayZ[i].x,
(double) orig_points.arrayZ[prev].x,
(double) orig_points.arrayZ[next].x,
- deltas_x.arrayZ[prev], deltas_x.arrayZ[next]);
+ (double) deltas_x.arrayZ[prev], (double) deltas_x.arrayZ[next]);
deltas_y.arrayZ[i] = infer_delta ((double) orig_points.arrayZ[i].y,
(double) orig_points.arrayZ[prev].y,
(double) orig_points.arrayZ[next].y,
- deltas_y.arrayZ[prev], deltas_y.arrayZ[next]);
+ (double) deltas_y.arrayZ[prev], (double) deltas_y.arrayZ[next]);
inferred_idxes.add (i);
if (--unref_count == 0) goto no_more_gaps;
}
@@ -692,7 +692,7 @@
if (ref_count == count) return true;
- hb_vector_t<double> opt_deltas_x, opt_deltas_y;
+ hb_vector_t<float> opt_deltas_x, opt_deltas_y;
bool is_comp_glyph_wo_deltas = (is_composite && ref_count == 0);
if (is_comp_glyph_wo_deltas)
{
@@ -841,6 +841,7 @@
{ return (i >= end) ? start : (i + 1); }
};
+template <typename OffType = HBUINT16>
struct TupleVariationData
{
bool sanitize (hb_sanitize_context_t *c) const
@@ -875,7 +876,7 @@
private:
/* referenced point set->compiled point data map */
- hb_hashmap_t<const hb_vector_t<bool>*, hb_vector_t<char>> point_data_map;
+ hb_hashmap_t<const hb_vector_t<bool>*, hb_vector_t<unsigned char>> point_data_map;
/* referenced point set-> count map, used in finding shared points */
hb_hashmap_t<const hb_vector_t<bool>*, unsigned> point_set_count_map;
@@ -883,7 +884,7 @@
* shared_points_bytes is a pointer to some value in the point_data_map,
* which will be freed during map destruction. Save it for serialization, so
* no need to do find_shared_points () again */
- hb_vector_t<char> *shared_points_bytes = nullptr;
+ hb_vector_t<unsigned char> *shared_points_bytes = nullptr;
/* total compiled byte size as TupleVariationData format, initialized to 0 */
unsigned compiled_byte_size = 0;
@@ -1244,7 +1245,7 @@
for (auto& tuple: tuple_vars)
{
const hb_vector_t<bool>* points_set = &(tuple.indices);
- hb_vector_t<char> *points_data;
+ hb_vector_t<unsigned char> *points_data;
if (unlikely (!point_data_map.has (points_set, &points_data)))
return false;
@@ -1289,7 +1290,7 @@
TRACE_SERIALIZE (this);
if (is_gvar && shared_points_bytes)
{
- hb_bytes_t s (shared_points_bytes->arrayZ, shared_points_bytes->length);
+ hb_ubytes_t s (shared_points_bytes->arrayZ, shared_points_bytes->length);
s.copy (c);
}
@@ -1296,13 +1297,13 @@
for (const auto& tuple: tuple_vars)
{
const hb_vector_t<bool>* points_set = &(tuple.indices);
- hb_vector_t<char> *point_data;
+ hb_vector_t<unsigned char> *point_data;
if (!point_data_map.has (points_set, &point_data))
return_trace (false);
if (!is_gvar || point_data != shared_points_bytes)
{
- hb_bytes_t s (point_data->arrayZ, point_data->length);
+ hb_ubytes_t s (point_data->arrayZ, point_data->length);
s.copy (c);
}
@@ -1521,15 +1522,16 @@
* low 12 bits are the number of tuple variation tables
* for this glyph. The number of tuple variation tables
* can be any number between 1 and 4095. */
- Offset16To<HBUINT8>
+ OffsetTo<HBUINT8, OffType>
data; /* Offset from the start of the base table
* to the serialized data. */
/* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
public:
- DEFINE_SIZE_MIN (4);
+ DEFINE_SIZE_MIN (2 + OffType::static_size);
};
-using tuple_variations_t = TupleVariationData::tuple_variations_t;
+// TODO: Move tuple_variations_t to outside of TupleVariationData
+using tuple_variations_t = TupleVariationData<HBUINT16>::tuple_variations_t;
struct item_variations_t
{
using region_t = const hb_hashmap_t<hb_tag_t, Triple>*;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -50,7 +50,7 @@
tupleVariationData.sanitize (c));
}
- const TupleVariationData* get_tuple_var_data (void) const
+ const TupleVariationData<>* get_tuple_var_data (void) const
{ return &tupleVariationData; }
bool decompile_tuple_variations (unsigned axis_count,
@@ -58,12 +58,12 @@
hb_blob_t *blob,
bool is_gvar,
const hb_map_t *axes_old_index_tag_map,
- TupleVariationData::tuple_variations_t& tuple_variations /* OUT */) const
+ TupleVariationData<>::tuple_variations_t& tuple_variations /* OUT */) const
{
hb_vector_t<unsigned> shared_indices;
- TupleVariationData::tuple_iterator_t iterator;
+ TupleVariationData<>::tuple_iterator_t iterator;
hb_bytes_t var_data_bytes = blob->as_bytes ().sub_array (4);
- if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, this,
+ if (!TupleVariationData<>::get_tuple_iterator (var_data_bytes, axis_count, this,
shared_indices, &iterator))
return false;
@@ -77,16 +77,16 @@
static bool calculate_cvt_deltas (unsigned axis_count,
hb_array_t<int> coords,
unsigned num_cvt_item,
- const TupleVariationData *tuple_var_data,
+ const TupleVariationData<> *tuple_var_data,
const void *base,
hb_vector_t<float>& cvt_deltas /* OUT */)
{
if (!coords) return true;
hb_vector_t<unsigned> shared_indices;
- TupleVariationData::tuple_iterator_t iterator;
+ TupleVariationData<>::tuple_iterator_t iterator;
unsigned var_data_length = tuple_var_data->get_size (axis_count);
hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast<const char*> (tuple_var_data), var_data_length);
- if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, base,
+ if (!TupleVariationData<>::get_tuple_iterator (var_data_bytes, axis_count, base,
shared_indices, &iterator))
return true; /* isn't applied at all */
@@ -107,7 +107,7 @@
bool has_private_points = iterator.current_tuple->has_private_points ();
if (has_private_points &&
- !TupleVariationData::decompile_points (p, private_indices, end))
+ !TupleVariationData<>::decompile_points (p, private_indices, end))
return false;
const hb_vector_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
@@ -114,7 +114,7 @@
bool apply_to_all = (indices.length == 0);
unsigned num_deltas = apply_to_all ? num_cvt_item : indices.length;
if (unlikely (!unpacked_deltas.resize (num_deltas, false))) return false;
- if (unlikely (!TupleVariationData::decompile_deltas (p, unpacked_deltas, end))) return false;
+ if (unlikely (!TupleVariationData<>::decompile_deltas (p, unpacked_deltas, end))) return false;
for (unsigned int i = 0; i < num_deltas; i++)
{
@@ -129,7 +129,7 @@
}
bool serialize (hb_serialize_context_t *c,
- TupleVariationData::tuple_variations_t& tuple_variations) const
+ TupleVariationData<>::tuple_variations_t& tuple_variations) const
{
TRACE_SERIALIZE (this);
if (!tuple_variations) return_trace (false);
@@ -144,7 +144,7 @@
if (c->plan->all_axes_pinned)
return_trace (false);
- OT::TupleVariationData::tuple_variations_t tuple_variations;
+ OT::TupleVariationData<>::tuple_variations_t tuple_variations;
unsigned axis_count = c->plan->axes_old_index_tag_map.get_population ();
const hb_tag_t cvt = HB_TAG('c','v','t',' ');
@@ -169,7 +169,7 @@
}
static bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan,
- const TupleVariationData *tuple_var_data,
+ const TupleVariationData<> *tuple_var_data,
const void *base)
{
const hb_tag_t cvt = HB_TAG('c','v','t',' ');
@@ -209,7 +209,7 @@
protected:
FixedVersion<>version; /* Version of the CVT variation table
* initially set to 0x00010000u */
- TupleVariationData tupleVariationData; /* TupleVariationDate for cvar table */
+ TupleVariationData<> tupleVariationData; /* TupleVariationDate for cvar table */
public:
DEFINE_SIZE_MIN (8);
};
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -28,6 +28,7 @@
#ifndef HB_OT_VAR_GVAR_TABLE_HH
#define HB_OT_VAR_GVAR_TABLE_HH
+#include "hb-decycler.hh"
#include "hb-open-type.hh"
#include "hb-ot-var-common.hh"
@@ -36,15 +37,37 @@
* https://docs.microsoft.com/en-us/typography/opentype/spec/gvar
*/
#define HB_OT_TAG_gvar HB_TAG('g','v','a','r')
+#define HB_OT_TAG_GVAR HB_TAG('G','V','A','R')
+struct hb_glyf_scratch_t
+{
+ // glyf
+ contour_point_vector_t all_points;
+ contour_point_vector_t comp_points;
+ hb_decycler_t decycler;
+
+ // gvar
+ contour_point_vector_t orig_points;
+ hb_vector_t<int> x_deltas;
+ hb_vector_t<int> y_deltas;
+ contour_point_vector_t deltas;
+ hb_vector_t<unsigned int> shared_indices;
+ hb_vector_t<unsigned int> private_indices;
+
+ // VARC
+ hb_vector_t<unsigned> axisIndices;
+ hb_vector_t<float> axisValues;
+};
+
namespace OT {
-struct GlyphVariationData : TupleVariationData
-{};
-
+template <typename OffsetType>
struct glyph_variations_t
{
- using tuple_variations_t = TupleVariationData::tuple_variations_t;
+ // TODO: Move tuple_variations_t to outside of TupleVariationData
+ using tuple_variations_t = typename TupleVariationData<OffsetType>::tuple_variations_t;
+ using GlyphVariationData = TupleVariationData<OffsetType>;
+
hb_vector_t<tuple_variations_t> glyph_variations;
hb_vector_t<char> compiled_shared_tuples;
@@ -72,7 +95,7 @@
const hb_subset_plan_t *plan,
const hb_hashmap_t<hb_codepoint_t, hb_bytes_t>& new_gid_var_data_map)
{
- if (unlikely (!glyph_variations.alloc (plan->new_to_old_gid_list.length, true)))
+ if (unlikely (!glyph_variations.alloc_exact (plan->new_to_old_gid_list.length)))
return false;
auto it = hb_iter (plan->new_to_old_gid_list);
@@ -86,10 +109,11 @@
hb_bytes_t var_data = new_gid_var_data_map.get (new_gid);
const GlyphVariationData* p = reinterpret_cast<const GlyphVariationData*> (var_data.arrayZ);
- hb_vector_t<unsigned> shared_indices;
- GlyphVariationData::tuple_iterator_t iterator;
+ typename GlyphVariationData::tuple_iterator_t iterator;
tuple_variations_t tuple_vars;
+ hb_vector_t<unsigned> shared_indices;
+
/* in case variation data is empty, push an empty struct into the vector,
* keep the vector in sync with the new_to_old_gid_list */
if (!var_data || ! p->has_data () || !all_contour_points->length ||
@@ -259,7 +283,7 @@
hb_codepoint_t last_gid = 0;
unsigned idx = 0;
- TupleVariationData* cur_glyph = c->start_embed<TupleVariationData> ();
+ GlyphVariationData* cur_glyph = c->start_embed<GlyphVariationData> ();
if (!cur_glyph) return_trace (false);
for (auto &_ : it)
{
@@ -273,7 +297,7 @@
if (idx >= glyph_variations.length) return_trace (false);
if (!cur_glyph->serialize (c, true, glyph_variations[idx])) return_trace (false);
- TupleVariationData* next_glyph = c->start_embed<TupleVariationData> ();
+ GlyphVariationData* next_glyph = c->start_embed<GlyphVariationData> ();
glyph_offset += (char *) next_glyph - (char *) cur_glyph;
if (long_offset)
@@ -296,10 +320,15 @@
}
};
-struct gvar
+template <typename GidOffsetType, unsigned TableTag>
+struct gvar_GVAR
{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_gvar;
+ static constexpr hb_tag_t tableTag = TableTag;
+ using GlyphVariationData = TupleVariationData<GidOffsetType>;
+
+ bool has_data () const { return version.to_int () != 0; }
+
bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -317,7 +346,7 @@
{ return sanitize_shallow (c); }
bool decompile_glyph_variations (hb_subset_context_t *c,
- glyph_variations_t& glyph_vars /* OUT */) const
+ glyph_variations_t<GidOffsetType>& glyph_vars /* OUT */) const
{
hb_hashmap_t<hb_codepoint_t, hb_bytes_t> new_gid_var_data_map;
auto it = hb_iter (c->plan->new_to_old_gid_list);
@@ -344,7 +373,7 @@
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool serialize (hb_serialize_context_t *c,
- const glyph_variations_t& glyph_vars,
+ const glyph_variations_t<GidOffsetType>& glyph_vars,
Iterator it,
unsigned axis_count,
unsigned num_glyphs,
@@ -351,7 +380,7 @@
bool force_long_offsets) const
{
TRACE_SERIALIZE (this);
- gvar *out = c->allocate_min<gvar> ();
+ gvar_GVAR *out = c->allocate_min<gvar_GVAR> ();
if (unlikely (!out)) return_trace (false);
out->version.major = 1;
@@ -393,7 +422,7 @@
bool instantiate (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- glyph_variations_t glyph_vars;
+ glyph_variations_t<GidOffsetType> glyph_vars;
if (!decompile_glyph_variations (c, glyph_vars))
return_trace (false);
@@ -423,7 +452,7 @@
unsigned glyph_count = version.to_int () ? c->plan->source->get_num_glyphs () : 0;
- gvar *out = c->serializer->allocate_min<gvar> ();
+ gvar_GVAR *out = c->serializer->allocate_min<gvar_GVAR> ();
if (unlikely (!out)) return_trace (false);
out->version.major = 1;
@@ -557,9 +586,11 @@
public:
struct accelerator_t
{
+ bool has_data () const { return table->has_data (); }
+
accelerator_t (hb_face_t *face)
{
- table = hb_sanitize_context_t ().reference_table<gvar> (face);
+ table = hb_sanitize_context_t ().reference_table<gvar_GVAR> (face);
/* If sanitize failed, set glyphCount to 0. */
glyphCount = table->version.to_int () ? face->get_num_glyphs () : 0;
@@ -627,6 +658,7 @@
bool apply_deltas_to_points (hb_codepoint_t glyph,
hb_array_t<const int> coords,
const hb_array_t<contour_point_t> points,
+ hb_glyf_scratch_t &scratch,
bool phantom_only = false) const
{
if (unlikely (glyph >= glyphCount)) return true;
@@ -633,8 +665,11 @@
hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyphCount, glyph);
if (!var_data_bytes.as<GlyphVariationData> ()->has_data ()) return true;
- hb_vector_t<unsigned int> shared_indices;
- GlyphVariationData::tuple_iterator_t iterator;
+
+ auto &shared_indices = scratch.shared_indices;
+ shared_indices.clear ();
+
+ typename GlyphVariationData::tuple_iterator_t iterator;
if (!GlyphVariationData::get_tuple_iterator (var_data_bytes, table->axisCount,
var_data_bytes.arrayZ,
shared_indices, &iterator))
@@ -641,21 +676,22 @@
return true; /* so isn't applied at all */
/* Save original points for inferred delta calculation */
- contour_point_vector_t orig_points_vec; // Populated lazily
+ auto &orig_points_vec = scratch.orig_points;
+ orig_points_vec.clear (); // Populated lazily
auto orig_points = orig_points_vec.as_array ();
/* flag is used to indicate referenced point */
- contour_point_vector_t deltas_vec; // Populated lazily
+ auto &deltas_vec = scratch.deltas;
+ deltas_vec.clear (); // Populated lazily
auto deltas = deltas_vec.as_array ();
- hb_vector_t<unsigned> end_points; // Populated lazily
-
unsigned num_coords = table->axisCount;
hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * num_coords);
- hb_vector_t<unsigned int> private_indices;
- hb_vector_t<int> x_deltas;
- hb_vector_t<int> y_deltas;
+ auto &private_indices = scratch.private_indices;
+ auto &x_deltas = scratch.x_deltas;
+ auto &y_deltas = scratch.y_deltas;
+
unsigned count = points.length;
bool flush = false;
do
@@ -726,8 +762,8 @@
if (phantom_only && pt_index < count - 4) continue;
auto &delta = deltas.arrayZ[pt_index];
delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
- delta.x += x_deltas.arrayZ[i] * scalar;
- delta.y += y_deltas.arrayZ[i] * scalar;
+ delta.add_delta (x_deltas.arrayZ[i] * scalar,
+ y_deltas.arrayZ[i] * scalar);
}
}
else
@@ -738,10 +774,9 @@
if (apply_to_all)
for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
{
- unsigned int pt_index = i;
- auto &delta = deltas.arrayZ[pt_index];
- delta.x += x_deltas.arrayZ[i] * scalar;
- delta.y += y_deltas.arrayZ[i] * scalar;
+ auto &delta = deltas.arrayZ[i];
+ delta.add_delta (x_deltas.arrayZ[i] * scalar,
+ y_deltas.arrayZ[i] * scalar);
}
else
for (unsigned int i = 0; i < num_deltas; i++)
@@ -751,8 +786,8 @@
if (phantom_only && pt_index < count - 4) continue;
auto &delta = deltas.arrayZ[pt_index];
delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
- delta.x += x_deltas.arrayZ[i] * scalar;
- delta.y += y_deltas.arrayZ[i] * scalar;
+ delta.add_delta (x_deltas.arrayZ[i] * scalar,
+ y_deltas.arrayZ[i] * scalar);
}
}
else
@@ -760,10 +795,9 @@
if (apply_to_all)
for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
{
- unsigned int pt_index = i;
- auto &delta = deltas.arrayZ[pt_index];
- delta.x += x_deltas.arrayZ[i];
- delta.y += y_deltas.arrayZ[i];
+ auto &delta = deltas.arrayZ[i];
+ delta.add_delta (x_deltas.arrayZ[i],
+ y_deltas.arrayZ[i]);
}
else
for (unsigned int i = 0; i < num_deltas; i++)
@@ -773,8 +807,8 @@
if (phantom_only && pt_index < count - 4) continue;
auto &delta = deltas.arrayZ[pt_index];
delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
- delta.x += x_deltas.arrayZ[i];
- delta.y += y_deltas.arrayZ[i];
+ delta.add_delta (x_deltas.arrayZ[i],
+ y_deltas.arrayZ[i]);
}
}
}
@@ -782,17 +816,14 @@
/* infer deltas for unreferenced points */
if (!apply_to_all && !phantom_only)
{
- if (!end_points)
+ unsigned start_point = 0;
+ unsigned end_point = 0;
+ while (true)
{
- for (unsigned i = 0; i < count; ++i)
- if (points.arrayZ[i].is_end_point)
- end_points.push (i);
- if (unlikely (end_points.in_error ())) return false;
- }
+ while (end_point < count && !points.arrayZ[end_point].is_end_point)
+ end_point++;
+ if (unlikely (end_point == count)) break;
- unsigned start_point = 0;
- for (unsigned end_point : end_points)
- {
/* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
unsigned unref_count = 0;
for (unsigned i = start_point; i < end_point + 1; i++)
@@ -835,7 +866,7 @@
}
}
no_more_gaps:
- start_point = end_point + 1;
+ start_point = end_point = end_point + 1;
}
}
@@ -855,7 +886,7 @@
unsigned int get_axis_count () const { return table->axisCount; }
private:
- hb_blob_ptr_t<gvar> table;
+ hb_blob_ptr_t<gvar_GVAR> table;
unsigned glyphCount;
hb_vector_t<hb_pair_t<int, int>> shared_tuple_active_idx;
};
@@ -873,7 +904,7 @@
NNOffset32To<UnsizedArrayOf<F2DOT14>>
sharedTuples; /* Offset from the start of this table to the shared tuple records.
* Array of tuple records shared across all glyph variation data tables. */
- HBUINT16 glyphCountX; /* The number of glyphs in this font. This must match the number of
+ GidOffsetType glyphCountX; /* The number of glyphs in this font. This must match the number of
* glyphs stored elsewhere in the font. */
HBUINT16 flags; /* Bit-field that gives the format of the offset array that follows.
* If bit 0 is clear, the offsets are uint16; if bit 0 is set, the
@@ -888,9 +919,15 @@
DEFINE_SIZE_ARRAY (20, offsetZ);
};
+using gvar = gvar_GVAR<HBUINT16, HB_OT_TAG_gvar>;
+using GVAR = gvar_GVAR<HBUINT24, HB_OT_TAG_GVAR>;
+
struct gvar_accelerator_t : gvar::accelerator_t {
gvar_accelerator_t (hb_face_t *face) : gvar::accelerator_t (face) {}
};
+struct GVAR_accelerator_t : GVAR::accelerator_t {
+ GVAR_accelerator_t (hb_face_t *face) : GVAR::accelerator_t (face) {}
+};
} /* namespace OT */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -78,11 +78,11 @@
head = o.head;
tail = o.tail;
next = nullptr;
- real_links.alloc (o.num_real_links, true);
+ real_links.alloc_exact (o.num_real_links);
for (unsigned i = 0 ; i < o.num_real_links; i++)
real_links.push (o.real_links[i]);
- virtual_links.alloc (o.num_virtual_links, true);
+ virtual_links.alloc_exact (o.num_virtual_links);
for (unsigned i = 0; i < o.num_virtual_links; i++)
virtual_links.push (o.virtual_links[i]);
}
@@ -172,7 +172,7 @@
auto all_links () const HB_AUTO_RETURN
(( hb_concat (real_links, virtual_links) ));
auto all_links_writer () HB_AUTO_RETURN
- (( hb_concat (real_links.writer (), virtual_links.writer ()) ));
+ (( hb_concat (real_links.writer (), virtual_links.writer ()) ));
};
struct snapshot_t
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -56,7 +56,7 @@
* - For each glyph, if it doesn't match the subtable digest,
* skip it.
*
- * The main filter we use is a combination of three bits-pattern
+ * The main filter we use is a combination of four bits-pattern
* filters. A bits-pattern filter checks a number of bits (5 or 6)
* of the input number (glyph-id in this case) and checks whether
* its pattern is amongst the patterns of any of the accepted values.
@@ -64,45 +64,60 @@
* check is done using four bitwise operations only.
*/
-template <typename mask_t, unsigned int shift>
-struct hb_set_digest_bits_pattern_t
+static constexpr unsigned hb_set_digest_shifts[] = {4, 0, 6};
+
+struct hb_set_digest_t
{
+ // No science in these. Intuition and testing only.
+ using mask_t = uint64_t;
+
+ static constexpr unsigned n = ARRAY_LENGTH_CONST (hb_set_digest_shifts);
static constexpr unsigned mask_bytes = sizeof (mask_t);
static constexpr unsigned mask_bits = sizeof (mask_t) * 8;
- static constexpr unsigned num_bits = 0
- + (mask_bytes >= 1 ? 3 : 0)
- + (mask_bytes >= 2 ? 1 : 0)
- + (mask_bytes >= 4 ? 1 : 0)
- + (mask_bytes >= 8 ? 1 : 0)
- + (mask_bytes >= 16? 1 : 0)
- + 0;
+ static constexpr hb_codepoint_t mb1 = mask_bits - 1;
+ static constexpr mask_t one = 1;
+ static constexpr mask_t all = (mask_t) -1;
- static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
- static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
+ void init ()
+ { for (unsigned i = 0; i < n; i++) masks[i] = 0; }
- void init () { mask = 0; }
+ void clear () { init (); }
- static hb_set_digest_bits_pattern_t full () { hb_set_digest_bits_pattern_t d; d.mask = (mask_t) -1; return d; }
+ static hb_set_digest_t full ()
+ {
+ hb_set_digest_t d;
+ for (unsigned i = 0; i < n; i++) d.masks[i] = all;
+ return d;
+ }
- void union_ (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; }
+ void union_ (const hb_set_digest_t &o)
+ { for (unsigned i = 0; i < n; i++) masks[i] |= o.masks[i]; }
- void add (hb_codepoint_t g) { mask |= mask_for (g); }
-
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
{
- if (mask == (mask_t) -1) return false;
- if ((b >> shift) - (a >> shift) >= mask_bits - 1)
+ bool ret;
+
+ ret = false;
+ for (unsigned i = 0; i < n; i++)
+ if (masks[i] != all)
+ ret = true;
+ if (!ret) return false;
+
+ ret = false;
+ for (unsigned i = 0; i < n; i++)
{
- mask = (mask_t) -1;
- return false;
+ mask_t shift = hb_set_digest_shifts[i];
+ if ((b >> shift) - (a >> shift) >= mb1)
+ masks[i] = all;
+ else
+ {
+ mask_t ma = one << ((a >> shift) & mb1);
+ mask_t mb = one << ((b >> shift) & mb1);
+ masks[i] |= mb + (mb - ma) - (mb < ma);
+ ret = true;
+ }
}
- else
- {
- mask_t ma = mask_for (a);
- mask_t mb = mask_for (b);
- mask |= mb + (mb - ma) - (mb < ma);
- return true;
- }
+ return ret;
}
template <typename T>
@@ -125,103 +140,37 @@
template <typename T>
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
- bool may_have (const hb_set_digest_bits_pattern_t &o) const
- { return mask & o.mask; }
-
- bool may_have (hb_codepoint_t g) const
- { return mask & mask_for (g); }
-
bool operator [] (hb_codepoint_t g) const
{ return may_have (g); }
- private:
- static mask_t mask_for (hb_codepoint_t g)
- { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); }
- mask_t mask = 0;
-};
-
-template <typename head_t, typename tail_t>
-struct hb_set_digest_combiner_t
-{
- void init ()
- {
- head.init ();
- tail.init ();
- }
-
- static hb_set_digest_combiner_t full () { hb_set_digest_combiner_t d; d.head = head_t::full(); d.tail = tail_t::full (); return d; }
-
- void union_ (const hb_set_digest_combiner_t &o)
- {
- head.union_ (o.head);
- tail.union_(o.tail);
- }
-
void add (hb_codepoint_t g)
{
- head.add (g);
- tail.add (g);
+ for (unsigned i = 0; i < n; i++)
+ masks[i] |= one << ((g >> hb_set_digest_shifts[i]) & mb1);
}
- bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+ HB_ALWAYS_INLINE
+ bool may_have (hb_codepoint_t g) const
{
- return (int) head.add_range (a, b) | (int) tail.add_range (a, b);
+ for (unsigned i = 0; i < n; i++)
+ if (!(masks[i] & (one << ((g >> hb_set_digest_shifts[i]) & mb1))))
+ return false;
+ return true;
}
- template <typename T>
- void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
- {
- head.add_array (array, count, stride);
- tail.add_array (array, count, stride);
- }
- template <typename T>
- void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
- template <typename T>
- bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
- {
- return head.add_sorted_array (array, count, stride) &&
- tail.add_sorted_array (array, count, stride);
- }
- template <typename T>
- bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
- bool may_have (const hb_set_digest_combiner_t &o) const
+ bool may_intersect (const hb_set_digest_t &o) const
{
- return head.may_have (o.head) && tail.may_have (o.tail);
+ for (unsigned i = 0; i < n; i++)
+ if (!(masks[i] & o.masks[i]))
+ return false;
+ return true;
}
- bool may_have (hb_codepoint_t g) const
- {
- return head.may_have (g) && tail.may_have (g);
- }
+ private:
- bool operator [] (hb_codepoint_t g) const
- { return may_have (g); }
-
- private:
- head_t head;
- tail_t tail;
+ mask_t masks[n] = {};
};
-/*
- * hb_set_digest_t
- *
- * This is a combination of digests that performs "best".
- * There is not much science to this: it's a result of intuition
- * and testing.
- */
-using hb_set_digest_t =
- hb_set_digest_combiner_t
- <
- hb_set_digest_bits_pattern_t<unsigned long, 4>,
- hb_set_digest_combiner_t
- <
- hb_set_digest_bits_pattern_t<unsigned long, 0>,
- hb_set_digest_bits_pattern_t<unsigned long, 9>
- >
- >
-;
-
-
#endif /* HB_SET_DIGEST_HH */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -106,6 +106,7 @@
void del_range (hb_codepoint_t a, hb_codepoint_t b) { s.del_range (a, b); }
bool get (hb_codepoint_t g) const { return s.get (g); }
+ bool may_have (hb_codepoint_t g) const { return get (g); }
/* Has interface. */
bool operator [] (hb_codepoint_t k) const { return get (k); }
@@ -120,6 +121,9 @@
hb_sparseset_t& operator << (const hb_codepoint_pair_t& range)
{ add_range (range.first, range.second); return *this; }
+ bool may_intersect (const hb_sparseset_t &other) const
+ { return s.may_intersect (other.s); }
+
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
{ return s.intersects (first, last); }
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -209,7 +209,7 @@
* @num_coords: The number of variation-space coordinates
* @shaper_list: (array zero-terminated=1): List of shapers to try
*
- * The variable-font version of #hb_shape_plan_create.
+ * The variable-font version of #hb_shape_plan_create.
* Constructs a shaping plan for a combination of @face, @user_features, @props,
* and @shaper_list, plus the variation-space coordinates @coords.
*
@@ -233,7 +233,7 @@
num_coords,
shaper_list);
- if (unlikely (props->direction == HB_DIRECTION_INVALID))
+ if (unlikely (!HB_DIRECTION_IS_VALID (props->direction)))
return hb_shape_plan_get_empty ();
hb_shape_plan_t *shape_plan;
@@ -331,7 +331,7 @@
* @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
- * Attaches a user-data key/data pair to the given shaping plan.
+ * Attaches a user-data key/data pair to the given shaping plan.
*
* Return value: `true` if success, `false` otherwise.
*
@@ -352,7 +352,7 @@
* @shape_plan: A shaping plan
* @key: The user-data key to query
*
- * Fetches the user data associated with the specified key,
+ * Fetches the user data associated with the specified key,
* attached to the specified shaping plan.
*
* Return value: (transfer none): A pointer to the user data
@@ -501,7 +501,7 @@
* @num_coords: The number of variation-space coordinates
* @shaper_list: (array zero-terminated=1): List of shapers to try
*
- * The variable-font version of #hb_shape_plan_create_cached.
+ * The variable-font version of #hb_shape_plan_create_cached.
* Creates a cached shaping plan suitable for reuse, for a combination
* of @face, @user_features, @props, and @shaper_list, plus the
* variation-space coordinates @coords.
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -1128,7 +1128,7 @@
if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr)
size += 3;
}
- if (!buff.alloc (buff.length + size, true))
+ if (!buff.alloc_exact (buff.length + size))
return false;
for (auto &opstr : str.values)
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -45,7 +45,7 @@
void alloc (unsigned size)
{
map.alloc (size);
- vector.alloc (size, true);
+ vector.alloc_exact (size);
}
bool in_error () const
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -95,7 +95,6 @@
HB_ALWAYS_INLINE
void translate (const contour_point_t &p) { x += p.x; y += p.y; }
-
float x;
float y;
uint8_t flag;
@@ -104,20 +103,10 @@
struct contour_point_vector_t : hb_vector_t<contour_point_t>
{
- void extend (const hb_array_t<contour_point_t> &a)
+ bool add_deltas (hb_array_t<const float> deltas_x,
+ hb_array_t<const float> deltas_y,
+ hb_array_t<const bool> indices)
{
- unsigned int old_len = length;
- if (unlikely (!resize (old_len + a.length, false)))
- return;
- auto arrayZ = this->arrayZ + old_len;
- unsigned count = a.length;
- hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0]));
- }
-
- bool add_deltas (const hb_vector_t<float> deltas_x,
- const hb_vector_t<float> deltas_y,
- const hb_vector_t<bool> indices)
- {
if (indices.length != deltas_x.length ||
indices.length != deltas_y.length)
return false;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -296,7 +296,7 @@
HB_UNTAG (c->table_tag), buf_size);
if (unlikely (buf_size > c->source_blob->length * 256 ||
- !buf->alloc (buf_size, true)))
+ !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);
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -53,28 +53,25 @@
}
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
- hb_vector_t (const Iterable &o) : hb_vector_t ()
+ explicit hb_vector_t (const Iterable &o) : hb_vector_t ()
{
- auto iter = hb_iter (o);
- if (iter.is_random_access_iterator || iter.has_fast_len)
- alloc (hb_len (iter), true);
- hb_copy (iter, *this);
+ extend (o);
}
hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
{
- alloc (o.length, true);
+ alloc_exact (o.length);
if (unlikely (in_error ())) return;
copy_array (o.as_array ());
}
hb_vector_t (array_t o) : hb_vector_t ()
{
- alloc (o.length, true);
+ alloc_exact (o.length);
if (unlikely (in_error ())) return;
copy_array (o);
}
hb_vector_t (c_array_t o) : hb_vector_t ()
{
- alloc (o.length, true);
+ alloc_exact (o.length);
if (unlikely (in_error ())) return;
copy_array (o);
}
@@ -87,6 +84,35 @@
}
~hb_vector_t () { fini (); }
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
+ void extend (const Iterable &o)
+ {
+ auto iter = hb_iter (o);
+ if (iter.is_random_access_iterator || iter.has_fast_len)
+ alloc (hb_len (iter), true);
+ while (iter)
+ {
+ if (unlikely (!alloc (length + 1)))
+ return;
+ unsigned room = allocated - length;
+ for (unsigned i = 0; i < room && iter; i++)
+ push_has_room (*iter++);
+ }
+ }
+ void extend (array_t o)
+ {
+ alloc (length + o.length);
+ if (unlikely (in_error ())) return;
+ copy_array (o);
+ }
+ void extend (c_array_t o)
+ {
+ alloc (length + o.length);
+ if (unlikely (in_error ())) return;
+ copy_array (o);
+ }
+
public:
int allocated = 0; /* < 0 means allocation failed. */
unsigned int length = 0;
@@ -132,9 +158,10 @@
hb_vector_t& operator = (const hb_vector_t &o)
{
reset ();
- alloc (o.length, true);
+ alloc_exact (o.length);
if (unlikely (in_error ())) return *this;
+ length = 0;
copy_array (o.as_array ());
return *this;
@@ -218,6 +245,10 @@
// reference to it.
return std::addressof (Crap (Type));
+ return push_has_room (std::forward<Args> (args)...);
+ }
+ template <typename... Args> Type *push_has_room (Args&&... args)
+ {
/* Emplace. */
Type *p = std::addressof (arrayZ[length++]);
return new (p) Type (std::forward<Args> (args)...);
@@ -314,15 +345,20 @@
template <typename T = Type,
hb_enable_if (hb_is_trivially_copyable (T))>
void
+ copy_array (hb_array_t<Type> other)
+ {
+ assert ((int) (length + other.length) <= allocated);
+ hb_memcpy ((void *) (arrayZ + length), (const void *) other.arrayZ, other.length * item_size);
+ length += other.length;
+ }
+ template <typename T = Type,
+ hb_enable_if (hb_is_trivially_copyable (T))>
+ void
copy_array (hb_array_t<const Type> other)
{
- length = other.length;
- if (!HB_OPTIMIZE_SIZE_VAL && sizeof (T) >= sizeof (long long))
- /* This runs faster because of alignment. */
- for (unsigned i = 0; i < length; i++)
- arrayZ[i] = other.arrayZ[i];
- else
- hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
+ assert ((int) (length + other.length) <= allocated);
+ hb_memcpy ((void *) (arrayZ + length), (const void *) other.arrayZ, other.length * item_size);
+ length += other.length;
}
template <typename T = Type,
hb_enable_if (!hb_is_trivially_copyable (T) &&
@@ -330,12 +366,10 @@
void
copy_array (hb_array_t<const Type> other)
{
- length = 0;
- while (length < other.length)
- {
- length++;
- new (std::addressof (arrayZ[length - 1])) Type (other.arrayZ[length - 1]);
- }
+ assert ((int) (length + other.length) <= allocated);
+ for (unsigned i = 0; i < other.length; i++)
+ new (std::addressof (arrayZ[length + i])) Type (other.arrayZ[i]);
+ length += other.length;
}
template <typename T = Type,
hb_enable_if (!hb_is_trivially_copyable (T) &&
@@ -345,13 +379,13 @@
void
copy_array (hb_array_t<const Type> other)
{
- length = 0;
- while (length < other.length)
+ assert ((int) (length + other.length) <= allocated);
+ for (unsigned i = 0; i < other.length; i++)
{
- length++;
- new (std::addressof (arrayZ[length - 1])) Type ();
- arrayZ[length - 1] = other.arrayZ[length - 1];
+ new (std::addressof (arrayZ[length + i])) Type ();
+ arrayZ[length + i] = other.arrayZ[i];
}
+ length += other.length;
}
void
@@ -432,7 +466,16 @@
return true;
}
+ bool alloc_exact (unsigned int size)
+ {
+ return alloc (size, true);
+ }
+ void clear ()
+ {
+ resize (0);
+ }
+
bool resize (int size_, bool initialize = true, bool exact = false)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
@@ -497,7 +540,7 @@
shrink_vector (size);
if (shrink_memory)
- alloc (size, true); /* To force shrinking memory if needed. */
+ alloc_exact (size); /* To force shrinking memory if needed. */
}
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh 2025-03-08 22:22:06 UTC (rev 74540)
@@ -131,6 +131,7 @@
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#pragma GCC diagnostic ignored "-Wcast-function-type-strict" // https://github.com/harfbuzz/harfbuzz/pull/3859#issuecomment-1295409126
#pragma GCC diagnostic ignored "-Wdangling-reference" // https://github.com/harfbuzz/harfbuzz/issues/4043
+#pragma GCC diagnostic ignored "-Wdangling-pointer" // Trigerred by hb_decycler_node_t().
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#pragma GCC diagnostic ignored "-Wformat-zero-length"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
@@ -281,7 +282,9 @@
#define __attribute__(x)
#endif
-#if defined(__GNUC__) && (__GNUC__ >= 3)
+#if defined(__MINGW32__) && (__GNUC__ >= 3)
+#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (gnu_printf, format_idx, arg_idx)))
+#elif defined(__GNUC__) && (__GNUC__ >= 3)
#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
#else
#define HB_PRINTF_FUNC(format_idx, arg_idx)
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build 2025-03-08 22:22:06 UTC (rev 74540)
@@ -43,6 +43,7 @@
'hb-common.cc',
'hb-config.hh',
'hb-debug.hh',
+ 'hb-decycler.hh',
'hb-dispatch.hh',
'hb-draw.cc',
'hb-draw.hh',
@@ -725,6 +726,7 @@
'test-bimap': ['test-bimap.cc', 'hb-static.cc'],
'test-cff': ['test-cff.cc', 'hb-static.cc'],
'test-classdef-graph': ['graph/test-classdef-graph.cc', 'hb-static.cc', 'graph/gsubgpos-context.cc'],
+ 'test-decycler': ['test-decycler.cc', 'hb-static.cc'],
'test-iter': ['test-iter.cc', 'hb-static.cc'],
'test-machinery': ['test-machinery.cc', 'hb-static.cc'],
'test-map': ['test-map.cc', 'hb-static.cc'],
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-decycler.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-decycler.cc (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-decycler.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -0,0 +1,116 @@
+/*
+ * Copyright © 2025 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+#include "hb-decycler.hh"
+
+static void
+tree_recurse_binary (unsigned value,
+ unsigned max_value,
+ hb_decycler_t &decycler)
+{
+ if (value >= max_value)
+ return;
+
+ hb_decycler_node_t node (decycler);
+
+ bool ret = node.visit (value);
+ assert (ret);
+
+ tree_recurse_binary (value * 2 + 1, max_value, decycler);
+ tree_recurse_binary (value * 2 + 2, max_value, decycler);
+}
+
+static void
+tree_recurse_tertiary (unsigned value,
+ unsigned max_value,
+ hb_decycler_t &decycler)
+{
+ /* This function implements an alternative way to use the
+ * decycler. It checks for each node before visiting it.
+ * It demonstrates reusing a node for multiple visits. */
+
+ if (value >= max_value)
+ return;
+
+ hb_decycler_node_t node (decycler);
+
+ value *= 3;
+
+ for (unsigned i = 1; i <= 3; i++)
+ {
+ bool ret = node.visit (value + i);
+ assert (ret);
+
+ tree_recurse_tertiary (value + i, max_value, decycler);
+ }
+}
+
+static void
+test_tree ()
+{
+ hb_decycler_t decycler;
+ tree_recurse_binary (0, 64, decycler);
+ tree_recurse_tertiary (0, 1000, decycler);
+}
+
+static void
+cycle_recurse (signed value,
+ signed cycle_length,
+ hb_decycler_t &decycler)
+{
+ assert (cycle_length > 0);
+
+ hb_decycler_node_t node (decycler);
+
+ if (!node.visit (value))
+ return;
+
+ if (value >= cycle_length)
+ value = value % cycle_length;
+
+ cycle_recurse (value + 1, cycle_length, decycler);
+}
+
+static void
+test_cycle ()
+{
+ hb_decycler_t decycler;
+ cycle_recurse (0, 1, decycler);
+ cycle_recurse (0, 2, decycler);
+ cycle_recurse (2, 3, decycler);
+ cycle_recurse (-20, 8, decycler);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_tree ();
+ test_cycle ();
+
+ return 0;
+}
+
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-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc 2025-03-08 22:22:06 UTC (rev 74540)
@@ -38,15 +38,15 @@
hb_map_t axis_idx_tag_map;
axis_idx_tag_map.set (0, axis_tag);
- OT::TupleVariationData::tuple_variations_t tuple_variations;
+ OT::TupleVariationData<>::tuple_variations_t tuple_variations;
hb_vector_t<unsigned> shared_indices;
- OT::TupleVariationData::tuple_iterator_t iterator;
+ OT::TupleVariationData<>::tuple_iterator_t iterator;
- const OT::TupleVariationData* tuple_var_data = reinterpret_cast<const OT::TupleVariationData*> (cvar_data + 4);
+ const OT::TupleVariationData<>* tuple_var_data = reinterpret_cast<const OT::TupleVariationData<>*> (cvar_data + 4);
unsigned len = sizeof (cvar_data);
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,
+ bool result = OT::TupleVariationData<>::get_tuple_iterator (var_data_bytes, axis_count, cvar_table,
shared_indices, &iterator);
assert (result);
@@ -66,7 +66,7 @@
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_vector_t<double> 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};
+ 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)
@@ -78,7 +78,7 @@
}
}
- hb_vector_t<double> deltas_2 {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, 5.0, -3.0, 0.0, 1.0, 0.0, 5.0, -3.0, 0.0, 97.0, 97.0, 68.0, 68.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 1.0, -1.0, 1.0, 7.0, -1.0, -5.0, 73.0, 73.0, 53.0, 53.0, 0.0, 0.0, 0.0, -1.0, 73.0, 73.0, 53.0, 53.0, 0.0, 0.0, 0.0, -1.0};
+ hb_vector_t<float> deltas_2 {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, 5.0, -3.0, 0.0, 1.0, 0.0, 5.0, -3.0, 0.0, 97.0, 97.0, 68.0, 68.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 1.0, -1.0, 1.0, 7.0, -1.0, -5.0, 73.0, 73.0, 53.0, 53.0, 0.0, 0.0, 0.0, -1.0, 73.0, 73.0, 53.0, 53.0, 0.0, 0.0, 0.0, -1.0};
for (unsigned i = 0 ; i < 65; i++)
{
if (i < 23)
@@ -106,9 +106,9 @@
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_vector_t<double> 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};
+ 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};
- hb_vector_t<double> rounded_deltas_2 {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, 4, -2, 0.0, 1, 0.0, 4, -2, 0.0, 68, 68, 48, 48, 0.0, 0.0, 0.0, 4, 0.0, 0.0, 1, -1, 1, 5, -1, -4, 51, 51, 37, 37, 0.0, 0.0, 0.0, -1, 51, 51, 37, 37, 0.0, 0.0, 0.0, -1};
+ hb_vector_t<float> rounded_deltas_2 {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, 4, -2, 0.0, 1, 0.0, 4, -2, 0.0, 68, 68, 48, 48, 0.0, 0.0, 0.0, 4, 0.0, 0.0, 1, -1, 1, 5, -1, -4, 51, 51, 37, 37, 0.0, 0.0, 0.0, -1, 51, 51, 37, 37, 0.0, 0.0, 0.0, -1};
for (unsigned i = 0; i < 65; i++)
{
Modified: trunk/Build/source/libs/harfbuzz/version.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/version.ac 2025-03-08 21:56:41 UTC (rev 74539)
+++ trunk/Build/source/libs/harfbuzz/version.ac 2025-03-08 22:22:06 UTC (rev 74540)
@@ -8,4 +8,4 @@
dnl --------------------------------------------------------
dnl
dnl m4-include this file to define the current harfbuzz version
-m4_define([harfbuzz_version], [10.2.0])
+m4_define([harfbuzz_version], [10.4.0])
More information about the tex-live-commits
mailing list.