texlive[74729] Build/source/libs: harfbuzz 11.0.0
commits+kakuto at tug.org
commits+kakuto at tug.org
Mon Mar 24 01:38:36 CET 2025
Revision: 74729
https://tug.org/svn/texlive?view=revision&revision=74729
Author: kakuto
Date: 2025-03-24 01:38:36 +0100 (Mon, 24 Mar 2025)
Log Message:
-----------
harfbuzz 11.0.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/RELEASING.md
trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/addTable.py
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/check-symbols.py
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-ragel-artifacts.py
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc
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-atomic.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-deserialize-text-glyphs.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-glyphs.rl
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.rl
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-serialize.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h
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-coretext.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh
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-graphite2.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-object.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-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-color.cc
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-kern-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-hangul.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-thai.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint-extents.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.h
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/justify.py
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc
trunk/Build/source/libs/harfbuzz/include/Makefile.am
trunk/Build/source/libs/harfbuzz/include/Makefile.in
trunk/Build/source/libs/harfbuzz/version.ac
Added Paths:
-----------
trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.mingw.md
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/Cargo.lock
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/Cargo.toml
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/lib.rs
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/meson.build
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-vector.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite-font.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite-shape.cc
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.hh
trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fontations.h
Modified: trunk/Build/source/libs/README
===================================================================
--- trunk/Build/source/libs/README 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/README 2025-03-24 00:38:36 UTC (rev 74729)
@@ -28,7 +28,7 @@
https://sourceforge.net/projects/silgraphite/files/graphite2/
(requires C++11)
-harfbuzz 10.4.0 - checked 09mar25
+harfbuzz 11.0.0 - checked 24mar25
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/ChangeLog 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1,3 +1,8 @@
+2025-03-24 Akira Kakuto <kakuto at jcom.zaq.ne.jp>
+
+ Import harfbuzz-11.0.0.
+ * version.ac, include/Makefile.am: Adjusted.
+
2025-03-09 Akira Kakuto <kakuto at jcom.zaq.ne.jp>
Import harfbuzz-10.4.0.
Modified: trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/ChangeLog 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1,3 +1,8 @@
+2025-03-24 Akira Kakuto <kakuto at jcom.zaq.ne.jp>
+
+ Imported harfbuzz-11.0.0 source tree from:
+ https://github.com/harfbuzz/harfbuzz/releases/download/11.0.0/
+
2025-03-09 Akira Kakuto <kakuto at jcom.zaq.ne.jp>
Imported harfbuzz-10.4.0 source tree from:
Modified: trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes
===================================================================
--- trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/TLpatches/TL-Changes 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1,5 +1,5 @@
-Changes applied to the harfbuzz-10.4.0/ tree as obtained from:
- https://github.com/harfbuzz/harfbuzz/releases/download/10.4.0/
+Changes applied to the harfbuzz-11.0.0/ tree as obtained from:
+ https://github.com/harfbuzz/harfbuzz/releases/download/11.0.0/
Removed:
.clang-format
Modified: trunk/Build/source/libs/harfbuzz/configure
===================================================================
--- trunk/Build/source/libs/harfbuzz/configure 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/configure 2025-03-24 00:38:36 UTC (rev 74729)
@@ -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.4.0.
+# Generated by GNU Autoconf 2.72 for harfbuzz (TeX Live) 11.0.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.4.0'
-PACKAGE_STRING='harfbuzz (TeX Live) 10.4.0'
+PACKAGE_VERSION='11.0.0'
+PACKAGE_STRING='harfbuzz (TeX Live) 11.0.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.4.0 to adapt to many kinds of systems.
+'configure' configures harfbuzz (TeX Live) 11.0.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.4.0:";;
+ short | recursive ) echo "Configuration of harfbuzz (TeX Live) 11.0.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.4.0
+harfbuzz (TeX Live) configure 11.0.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.4.0, which was
+It was created by harfbuzz (TeX Live) $as_me 11.0.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.4.0'
+ VERSION='11.0.0'
# Some tools Automake needs.
@@ -5440,10 +5440,10 @@
echo 'tldbg:KPSE_BASIC done (pkg=harfbuzz, amopt=no-define)' >&5
-HB_VERSION_MAJOR=10
-HB_VERSION_MINOR=4
+HB_VERSION_MAJOR=11
+HB_VERSION_MINOR=0
HB_VERSION_MICRO=0
-HB_VERSION=10.4.0
+HB_VERSION=11.0.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.4.0, which was
+This file was extended by harfbuzz (TeX Live) $as_me 11.0.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.4.0
+harfbuzz (TeX Live) config.status 11.0.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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt 2025-03-24 00:38:36 UTC (rev 74729)
@@ -233,7 +233,7 @@
set (CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${FREETYPE_INCLUDE_DIRS})
set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${FREETYPE_LIBRARIES})
- check_funcs(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var)
+ check_funcs(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var FT_Get_Transform)
endif ()
if (HB_HAVE_FREETYPE)
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/NEWS 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1,3 +1,64 @@
+Overview of changes leading to 11.0.0
+Monday, March 24, 2025
+====================================
+- There are three new font-functions implementations (integrations) in this
+ release:
+ * `hb-coretext` has gained one, calling into the CoreText library,
+ * `hb-directwrite` has gained one, calling into the DirectWrite library.
+ * `hb-fontations` has gained one, calling into the Skrifa Rust library.
+ All three are mostly useful for performance and correctness testing, but some
+ clients might find them useful.
+ An API is added to use them from a single API by providing a backend name
+ string:
+ * `hb_font_set_funcs_using()`
+- Several new APIs are added, to load a font-face using different
+ "face-loaders", and a single entry point to them all using a loader name
+ string:
+ * `hb_ft_face_create_from_file_or_fail()` and
+ `hb_ft_face_create_from_blob_or_fail()`
+ * `hb_coretext_face_create_from_file_or_fail()` and
+ `hb_coretext_face_create_from_blob_or_fail()`
+ * `hb_directwrite_face_create_from_file_or_fail()` and
+ `hb_directwrite_face_create_from_blob_or_fail()`
+ * `hb_face_create_from_file_or_fail_using()`
+- All drawing and painting operations using the default, `hb-ot` functions have
+ become memory allocation-free.
+- Several performance optimizations have been implemented.
+- Application of the `trak` table during shaping has been improved.
+- The `directwrite` shaper now supports font variations, and correctly applies
+ user features.
+- The `hb-directwrite` API and shaper has graduated from experimental.
+- Various bug fixes and other improvements.
+
+- New API:
++hb_malloc
++hb_calloc
++hb_realloc
++hb_free
++hb_face_list_loaders
++hb_face_create_or_fail_using
++hb_face_create_from_file_or_fail_using
++hb_font_list_funcs
++hb_font_set_funcs_using
++hb_coretext_face_create_from_blob_or_fail
++hb_directwrite_face_create_from_file_or_fail
++hb_directwrite_face_create_from_blob_or_fail
++hb_directwrite_font_create
++hb_directwrite_font_get_dw_font_face
++hb_directwrite_font_set_funcs
++hb_fontations_font_set_funcs
++hb_ft_face_create_from_blob_or_fail
++hb_paint_push_font_transform
++hb_paint_push_inverse_font_transform
++HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES
++HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE
++HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES
++HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS
+
+- Deprecated API:
++hb_directwrite_font_get_dw_font
+
+
Overview of changes leading to 10.4.0
Saturday, March 1, 2025
====================================
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.md 2025-03-24 00:38:36 UTC (rev 74729)
@@ -51,6 +51,8 @@
For testing and profiling, see [TESTING.md](TESTING.md).
+For cross-compiling to Windows from Linux or macOS, see [README.mingw.md](README.mingw.md).
+
To get a better idea of where HarfBuzz stands in the text rendering stack you
may want to read [State of Text Rendering 2024][6].
Here are a few presentation slides about HarfBuzz at the
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.mingw.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.mingw.md (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/README.mingw.md 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,211 @@
+Most HarfBuzz developers do so on Linux or macOS. However, HarfBuzz is a
+cross-platform library and it is important to ensure that it works on Windows
+as well. In particular, we use this workflow to develop and test the HarfBuzz
+Uniscribe shaper and DirectWrite shaper and font backend, all from Linux or
+macOS.
+
+This document provides instructions for cross-compiling HarfBuzz on Linux or
+macOS, for Windows, using the MinGW toolchain, and running tests and utilties
+under Wine.
+
+We then discuss using native Windows Uniscribe or DirectWrite DLLs, which
+allows you to test HarfBuzz's shaping against the Microsoft shaping engines
+instead of those provided by Wine.
+
+This document assumes that you are familiar with building HarfBuzz on Linux or
+macOS.
+
+You can build for 32bit or 64bit Windows. If your intention is to use a native
+Uniscribe usp10.dll from Windows 7 or before, you would need to build for 32bit.
+If you want to use a native DirectWrite DLL from Windows 10 or later, you would
+need to build for 64bit.
+
+We suggest you read to the end of this document before starting, as it provides
+a few different ways to build and test HarfBuzz for Windows.
+
+1. Install Wine.
+
+ - Fedora: `dnf install wine`.
+ - Ubuntu, 32bit: `apt install wine wine32`.
+ - Ubuntu, 64bit: `apt install wine wine64`.
+ - Mac: `brew install wine-stable`.
+
+2. Install the `mingw-w64` cross-compiler.
+
+ - Fedora, 32bit: `dnf install mingw32-gcc-c++`
+ - Fedora, 64bit: `dnf install mingw64-gcc-c++`
+ - Ubuntu, 32bit: `apt install g++-mingw-w64-i686`
+ - Ubuntu, 64bit: `apt install g++-mingw-w64-x86-64`
+ - Mac: `brew install mingw-w64`
+
+3. Install dependencies.
+
+First, make sure you do not have the mingw32 harfbuzz package, as that will
+override our own build:
+
+ - Fedora, 32bit: `dnf remove mingw32-harfbuzz`
+ - Fedora, 64bit: `dnf remove mingw64-harfbuzz`
+
+Then install the actual dependencies:
+
+ - Fedora, 32bit: `dnf install mingw32-glib2 mingw32-cairo mingw32-freetype`
+ - Fedora, 64bit: `dnf install mingw64-glib2 mingw64-cairo mingw64-freetype`
+
+If you cannot find these packages for your distribution, or you are on macOS,
+you can skip to the next step, as meson will automatically download and build
+the dependencies for you.
+
+4. If you are familiar with `meson`, you can use the cross-compile files we
+provide to find your way around. But we do not recommend this way. Read until
+the end of this section before deciding which one to use.
+
+ - 32bit: `meson --cross-file=.ci/win32-cross-file.txt build-win -Dglib-enabled -Dcairo=enabled -Dgdi=enabled -Ddirectwrite=enabled`
+ - 64bit: `meson --cross-file=.ci/win64-cross-file.txt build-win -Dglib-enabled -Dcairo=enabled -Dgdi=enabled -Ddirectwrite=enabled`
+
+In which case, you will proceed to run `ninja` as usual to build:
+
+ - `ninja -C build-win`
+
+Or you can simply invoke the scripts we provide for our Continuous Integration
+system, to configure and build HarfBuzz for you. This is the easiest way to
+build HarfBuzz for Windows and how we build our Windows binaries:
+
+ - 32bit: `./.ci/build-win.sh 32 && ln -s build-win32 build-win`
+ - 64bit: `./.ci/build-win.sh 64 && ln -s build-win64 build-win`
+
+This might take a while, since, if you do not have the dependencies installed,
+meson will download and build them for you.
+
+5. If everything succeeds, you should have the `hb-shape.exe`, `hb-view.exe`,
+`hb-subset.exe`, and `hb-info.exe` executables in `build-win/util`.
+
+6. Configure your wine to find system mingw libraries. While there, set it also
+to find the built HarfBuzz DLLs:
+
+ - Fedora, 32bit: `export WINEPATH="$HOME/harfbuzz/build-win/src;/usr/i686-w64-mingw32/sys-root/mingw/bin"`
+ - Fedora, 64bit: `export WINEPATH="$HOME/harfbuzz/build-win/src;/usr/x86_64-w64-mingw32/sys-root/mingw/bin"`
+ - Other systems: `export WINEPATH="$HOME/harfbuzz/build-win/src"`
+
+Adjust for the path where you have built HarfBuzz. You might want to add this
+to your `.bashrc` or `.zshrc` file.
+
+Alternatively, can skip this step if commands are run through the `meson devenv`
+command, which we will introduce in the next step. I personally find it more
+convenient to set the `WINEPATH` variable, as it allows me to run the executables
+directly from the shell.
+
+7. Run the `hb-shape` executable under Wine:
+
+ - `wine build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test`
+
+Or using `meson devenv to do the same:
+
+ - `meson devenv -C build-win util/hb-shape.exe $PWD/perf/fonts/Roboto-Regular.ttf Test`
+
+You probably will get lots of Wine warnings, but if all works fine, you
+should see:
+```
+[gid57=0+1123|gid74=1+1086|gid88=2+1057|gid89=3+670]
+```
+
+You can make Wine less verbose, without hiding all errors, by setting:
+
+ - `export WINEDEBUG=fixme-all,warn-all,err-plugplay,err-seh,err-rpc,err-ntoskrnl,err-winediag,err-systray,err-hid`
+
+Add this to your `.bashrc` or `.zshrc` file as well.
+
+Next, let's try some non-Latin text. Unfortunately, the command-line parsing of
+our cross-compiled glib is not quite Unicode-aware, at least when run under
+Wine. So you will need to find some other way to feed Unicode text to the
+shaper. There are three different ways you can try:
+
+ - `echo حرف | wine build-win/util/hb-shape.exe perf/fonts/Amiri-Regular.ttf`
+ - `wine build-win/util/hb-shape.exe perf/fonts/Amiri-Regular.ttf -u 062D,0631,0641`
+ - `wine build-win/util/hb-shape.exe perf/fonts/Amiri-Regular.ttf --text-file harf.txt`
+
+To get the Unicode codepoints for a string, you can use the `hb-unicode-decode`
+utility:
+```
+$ test/shape/hb-unicode-decode حرف
+U+062D,U+0631,U+0641
+```
+
+8. Next, let's try the `hb-view` utility. By default, `hb-view` outputs ANSI text,
+which Wine will not display correctly. You can use the `-o` option to redirect the
+output to a file, or just redirect the output using the shell, which will produce
+a PNG file.
+
+ - `wine build-win/util/hb-view.exe perf/fonts/Roboto-Regular.ttf Test > test.png`
+
+7. As noted, if your Linux has `binfmt_misc` enabled, you can run the executables
+directly. If not, you can modify the cross-file to use the `exe_wrapper` option as
+specified before.
+
+ - `build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test`
+
+If that does not work, you can use the `wine` command as shown above.
+
+10. You can try running the test suite. If on Linux with `binfmt_misc` enabled, you
+can run the tests directly:
+
+ - `ninja -C build-win test`
+
+For other situations, use `meson devenv`:
+
+ - `meson devenv -C build-win ninja test`
+
+This might take a couple of minutes to run. Running under Wine is expensive, so
+be patient.
+
+If all goes well, tests should run. If all is well, you should probably see about
+400 tests pass, some skipped, but none failing.
+
+11. In the above testing situation, the `directwrite` test will be disabled
+automatically upon detection of running under Wine. The reason the `directwrite`
+test would otherwise fails is that we are running against the Wine-provided
+DirectWrite DLL, which is an incomplete reimplementation of the DirectWrite API
+by Wine, and not the real thing.
+
+If you want to test the Uniscribe or DirectWrite shapers against the real
+Uniscribe / DirectWrite, you can follow the instructions below.
+
+11. Old Uniscribe: Assuming a 32bit build for now.
+
+Bring a 32bit version of `usp10.dll` for yourself from
+`C:\Windows\SysWOW64\usp10.dll` of your 64bit Windows installation,
+or `C:\Windows\System32\usp10.dll` for 32bit Windows installation.
+
+You want one from Windows 7 or earlier. One that is not just a proxy for
+`TextShaping.dll`. Rule of thumb, your `usp10.dll` should have a size more
+than 500kb.
+
+Put the file in `~/.wine/drive_c/windows/syswow64/` so wine can find it.
+
+You can now tell wine to use the native `usp10.dll`:
+
+ - `export WINEDLLOVERRIDES="usp10=n"`
+ - `wine build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test --shaper=uniscribe`
+
+12. DirectWrite and new Uniscribe: You can use the same method to test the
+DirectWrite shaper against the native DirectWrite DLL. Try with a 64bit build
+this time.
+
+Bring `TextShaping.dll`, `DWrite.dll`, and `usp10.dll` from your 64bit Windows
+installation (`C:\Windows\System32`) to `~/.wine/drive_c/windows/system32/`.
+
+You want the ones from Windows 10 or later. You might have some luck downloading
+them from the internet, but be careful with the source. I had success with the
+DLLs from [https://dllme.com](dllme.com), but I cannot vouch for the site.
+
+You can now tell wine to use the native DirectWrite:
+
+ - `export WINEDLLOVERRIDES="textshaping,dwrite,usp10=n"`
+ - `wine build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test --shaper=directwrite`
+
+If all works well, you should be able to rerun the tests and see all pass this time.
+
+13. For some old instructions on how to test HarfBuzz's native Indic shaper against
+Uniscribe, see: https://github.com/harfbuzz/harfbuzz/issues/3671
+
+14. That's it! If you made it this far, you are now able to develop and test
+HarfBuzz on Windows, from Linux or macOS. Enjoy!
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/RELEASING.md
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/RELEASING.md 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/RELEASING.md 2025-03-24 00:38:36 UTC (rev 74729)
@@ -17,7 +17,7 @@
- [ ] Based on severity of changes, decide whether it's a minor or micro release number bump.
-- [ ] Search for 'XSince: REPLACEME' on the repository and replace it with the chosen version for the release, e.g. 'Since: 1.4.7'.
+- [ ] Search for 'REPLACEME' on the repository and replace it with the chosen version for the release, e.g. 'Since: 1.4.7'.
- [ ] Make sure you have correct date and new version at the top of NEWS file.
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson.build 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1,11 +1,12 @@
-project('harfbuzz', 'c', 'cpp',
+project('harfbuzz', ['c', 'cpp'],
meson_version: '>= 0.55.0',
- version: '10.4.0',
+ version: '11.0.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
'cpp_std=c++11',
'wrap_mode=nofallback', # Use --wrap-mode=default to revert, https://github.com/harfbuzz/harfbuzz/pull/2548
+ 'buildtype=debugoptimized',
],
)
@@ -102,9 +103,13 @@
m_dep = cpp.find_library('m', required: false)
-if meson.version().version_compare('>=0.60.0')
+# Painful hack to handle multiple dependencies but also respect options
+if get_option('freetype').disabled()
+ freetype_dep = dependency('', required: false)
+else
# Sadly, FreeType's versioning schemes are different between pkg-config and CMake
- # pkg-config: freetype2, cmake: Freetype
+
+ # Try pkg-config name
freetype_dep = dependency('freetype2',
version: freetype_min_version,
method: 'pkg-config',
@@ -111,35 +116,23 @@
required: false,
allow_fallback: false)
if not freetype_dep.found()
- freetype_dep = dependency('FreeType',
+ # Try cmake name
+ freetype_dep = dependency('Freetype',
version: freetype_min_version_actual,
method: 'cmake',
- required: get_option('freetype'),
- default_options: ['harfbuzz=disabled'],
- allow_fallback: true)
- endif
-else
- # painful hack to handle multiple dependencies but also respect options
- freetype_opt = get_option('freetype')
- # we want to handle enabled manually after fallbacks, but also handle disabled normally
- if freetype_opt.enabled()
- freetype_opt = false
- endif
- # try pkg-config name
- freetype_dep = dependency('freetype2', version: freetype_min_version, method: 'pkg-config', required: freetype_opt)
- # when disabled, leave it not-found
- if not freetype_dep.found() and not get_option('freetype').disabled()
- # Try cmake name
- freetype_dep = dependency('Freetype', version: freetype_min_version_actual, method: 'cmake', required: false)
- # Subproject fallback, `allow_fallback: true` means the fallback will be
- # tried even if the freetype option is set to `auto`.
+ required: false,
+ allow_fallback: false)
+ # Subproject fallback
if not freetype_dep.found()
- freetype_dep = dependency('freetype2',
- version: freetype_min_version,
- method: 'pkg-config',
+ freetype_proj = subproject('freetype2',
+ version: freetype_min_version_actual,
required: get_option('freetype'),
- default_options: ['harfbuzz=disabled'],
- allow_fallback: true)
+ default_options: ['harfbuzz=disabled'])
+ if freetype_proj.found()
+ freetype_dep = freetype_proj.get_variable('freetype_dep')
+ else
+ freetype_dep = dependency('', required: false)
+ endif
endif
endif
endif
@@ -227,17 +220,19 @@
chafa_dep = dependency('chafa', version: chafa_min_version, required: get_option('chafa'))
+fontations_dep_found = false
+if get_option('fontations').enabled()
+ add_languages(['rust'], native: false, required : true)
+ fontations_dep_found = true
+endif
+
conf = configuration_data()
incconfig = include_directories('.')
add_project_arguments('-DHAVE_CONFIG_H', language: ['c', 'cpp'])
-warn_cflags = [
- '-Wno-non-virtual-dtor',
-]
+cpp_args = []
-cpp_args = cpp.get_supported_arguments(warn_cflags)
-
if glib_dep.found()
conf.set('HAVE_GLIB', 1)
endif
@@ -272,6 +267,10 @@
conf.set('HAVE_CHAFA', 1)
endif
+if fontations_dep_found
+ conf.set('HAVE_FONTATIONS', 1)
+endif
+
if wasm_dep.found()
conf.set('HAVE_WASM', 1)
conf.set('HB_WASM_MODULE_DIR', '"'+get_option('prefix')+'/'+get_option('libdir')+'/harfbuzz/wasm"')
@@ -315,7 +314,7 @@
gdi_uniscribe_deps = []
# GDI (Uniscribe) (Windows)
if host_machine.system() == 'windows' and not get_option('gdi').disabled()
- if (get_option('directwrite').enabled() and
+ if (get_option('gdi').enabled() and
not (cpp.has_header('usp10.h') and cpp.has_header('windows.h')))
error('GDI/Uniscribe was enabled explicitly, but required headers are missing.')
endif
@@ -335,10 +334,9 @@
# DirectWrite (Windows)
if host_machine.system() == 'windows' and not get_option('directwrite').disabled()
- if get_option('directwrite').enabled() and not cpp.has_header('dwrite_1.h')
+ if get_option('directwrite').enabled() and not cpp.has_header('dwrite_3.h')
error('DirectWrite was enabled explicitly, but required header is missing.')
endif
-
conf.set('HAVE_DIRECTWRITE', 1)
endif
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt 2025-03-24 00:38:36 UTC (rev 74729)
@@ -15,10 +15,12 @@
description: 'Enable Graphite2 complementary shaper')
option('freetype', type: 'feature', value: 'auto',
description: 'Enable freetype interop helpers')
+option('fontations', type: 'feature', value: 'disabled',
+ description: 'Enabled fontations font functions')
option('gdi', type: 'feature', value: 'disabled',
description: 'Enable GDI helpers and Uniscribe shaper backend (Windows only)')
option('directwrite', type: 'feature', value: 'disabled',
- description: 'Enable DirectWrite shaper backend on Windows (experimental)')
+ description: 'Enable DirectWrite shaper backend on Windows')
option('coretext', type: 'feature', value: 'disabled',
description: 'Enable CoreText shaper backend on macOS')
option('wasm', type: 'feature', value: 'disabled',
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -47,6 +47,11 @@
struct hb_paint_context_t;
}
+struct hb_colr_scratch_t
+{
+ hb_paint_extents_context_t paint_extents;
+};
+
namespace OT {
struct COLR;
@@ -90,7 +95,8 @@
font (font_),
palette (
#ifndef HB_NO_COLOR
- font->face->table.CPAL->get_palette_colors (palette_)
+ // https://github.com/harfbuzz/harfbuzz/issues/5116
+ font->face->table.CPAL->get_palette_colors (palette_ < font->face->table.CPAL->get_palette_count () ? palette_ : 0)
#endif
),
foreground (foreground_),
@@ -932,9 +938,9 @@
void paint_glyph (hb_paint_context_t *c) const
{
TRACE_PAINT (this);
- c->funcs->push_inverse_root_transform (c->data, c->font);
+ c->funcs->push_inverse_font_transform (c->data, c->font);
c->funcs->push_clip_glyph (c->data, gid, c->font);
- c->funcs->push_root_transform (c->data, c->font);
+ c->funcs->push_font_transform (c->data, c->font);
c->recurse (this+paint);
c->funcs->pop_transform (c->data);
c->funcs->pop_clip (c->data);
@@ -1511,10 +1517,12 @@
void paint_glyph (hb_paint_context_t *c) const
{
TRACE_PAINT (this);
+ c->funcs->push_group (c->data);
c->recurse (this+backdrop);
c->funcs->push_group (c->data);
c->recurse (this+src);
c->funcs->pop_group (c->data, (hb_paint_composite_mode_t) (int) mode);
+ c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
}
HBUINT8 format; /* format = 32 */
@@ -2079,6 +2087,8 @@
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
+ bool has_data () const { return has_v0_data () || version; }
+
bool has_v0_data () const { return numBaseGlyphs; }
bool has_v1_data () const
{
@@ -2112,8 +2122,54 @@
{
accelerator_t (hb_face_t *face)
{ colr = hb_sanitize_context_t ().reference_table<COLR> (face); }
- ~accelerator_t () { this->colr.destroy (); }
+ ~accelerator_t ()
+ {
+ auto *scratch = cached_scratch.get_relaxed ();
+ if (scratch)
+ {
+ scratch->~hb_colr_scratch_t ();
+ hb_free (scratch);
+ }
+
+ colr.destroy ();
+ }
+
+
+ bool has_data () const { return colr->has_data (); }
+
+#ifndef HB_NO_PAINT
+ bool
+ get_extents (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents) const
+ {
+ if (unlikely (!has_data ())) return false;
+
+ hb_colr_scratch_t *scratch = acquire_scratch ();
+ if (unlikely (!scratch)) return true;
+ bool ret = colr->get_extents (font, glyph, extents, *scratch);
+ release_scratch (scratch);
+ return ret;
+ }
+
+ 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
+ {
+ if (unlikely (!has_data ())) return false;
+
+ hb_colr_scratch_t *scratch = acquire_scratch ();
+ if (unlikely (!scratch)) return true;
+ bool ret = colr->paint_glyph (font, glyph, funcs, data, palette_index, foreground, clip, *scratch);
+ release_scratch (scratch);
+ return ret;
+ }
+#endif
+
bool is_valid () { return colr.get_blob ()->length; }
void closure_glyphs (hb_codepoint_t glyph,
@@ -2148,7 +2204,33 @@
{ return colr->get_delta_set_index_map_ptr (); }
private:
+
+ hb_colr_scratch_t *acquire_scratch () const
+ {
+ hb_colr_scratch_t *scratch = cached_scratch.get_acquire ();
+
+ if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
+ {
+ scratch = (hb_colr_scratch_t *) hb_calloc (1, sizeof (hb_colr_scratch_t));
+ if (unlikely (!scratch))
+ return nullptr;
+ }
+
+ return scratch;
+ }
+ void release_scratch (hb_colr_scratch_t *scratch) const
+ {
+ if (!cached_scratch.cmpexch (nullptr, scratch))
+ {
+ scratch->~hb_colr_scratch_t ();
+ hb_free (scratch);
+ }
+ }
+
+ public:
hb_blob_ptr_t<COLR> colr;
+ private:
+ hb_atomic_t<hb_colr_scratch_t *> cached_scratch;
};
void closure_glyphs (hb_codepoint_t glyph,
@@ -2520,7 +2602,10 @@
#ifndef HB_NO_PAINT
bool
- get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+ get_extents (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ hb_colr_scratch_t &scratch) const
{
ItemVarStoreInstancer instancer (get_var_store_ptr (),
@@ -2534,10 +2619,10 @@
}
auto *extents_funcs = hb_paint_extents_get_funcs ();
- hb_paint_extents_context_t extents_data;
- bool ret = paint_glyph (font, glyph, extents_funcs, &extents_data, 0, HB_COLOR(0,0,0,0));
+ scratch.paint_extents.clear ();
+ bool ret = paint_glyph (font, glyph, extents_funcs, &scratch.paint_extents, 0, HB_COLOR(0,0,0,0), true, scratch);
- hb_extents_t e = extents_data.get_extents ();
+ auto e = scratch.paint_extents.get_extents ();
if (e.is_void ())
{
extents->x_bearing = 0;
@@ -2547,6 +2632,7 @@
}
else
{
+ // Ugh. We need to undo the synthetic slant here. Leave it for now. :-(.
extents->x_bearing = e.xmin;
extents->y_bearing = e.ymax;
extents->width = e.xmax - e.xmin;
@@ -2583,7 +2669,12 @@
#ifndef HB_NO_PAINT
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
+ 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,
+ hb_colr_scratch_t &scratch) const
{
ItemVarStoreInstancer instancer (get_var_store_ptr (),
get_delta_set_index_map_ptr (),
@@ -2609,6 +2700,7 @@
if (get_clip (glyph, &extents, instancer))
{
font->scale_glyph_extents (&extents);
+ font->synthetic_glyph_extents (&extents);
c.funcs->push_clip_rectangle (c.data,
extents.x_bearing,
extents.y_bearing + extents.height,
@@ -2618,15 +2710,16 @@
else
{
auto *extents_funcs = hb_paint_extents_get_funcs ();
- hb_paint_extents_context_t extents_data;
+ scratch.paint_extents.clear ();
paint_glyph (font, glyph,
- extents_funcs, &extents_data,
+ extents_funcs, &scratch.paint_extents,
palette_index, foreground,
- false);
+ false,
+ scratch);
- hb_extents_t extents = extents_data.get_extents ();
- is_bounded = extents_data.is_bounded ();
+ auto extents = scratch.paint_extents.get_extents ();
+ is_bounded = scratch.paint_extents.is_bounded ();
c.funcs->push_clip_rectangle (c.data,
extents.xmin,
@@ -2636,7 +2729,7 @@
}
}
- c.funcs->push_root_transform (c.data, font);
+ c.funcs->push_font_transform (c.data, font);
if (is_bounded)
c.recurse (*paint);
@@ -2714,9 +2807,7 @@
return;
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);
}
}
@@ -2728,7 +2819,7 @@
if (unlikely (!node.visit (gid)))
return;
- c->funcs->push_inverse_root_transform (c->data, c->font);
+ c->funcs->push_inverse_font_transform (c->data, c->font);
if (c->funcs->color_glyph (c->data, gid, c->font))
{
c->funcs->pop_transform (c->data);
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -126,24 +126,18 @@
return static_transforming_pen_funcs.get_unconst ();
}
-
hb_ubytes_t
-VarComponent::get_path_at (hb_font_t *font,
+VarComponent::get_path_at (const hb_varc_context_t &c,
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_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->table;
+ auto &VARC = *c.font->face->table.VARC->table;
auto &varStore = &VARC+VARC.varStore;
#define READ_UINT32VAR(name) \
@@ -193,9 +187,9 @@
// Axis values
- auto &axisIndices = scratch.axisIndices;
+ auto &axisIndices = c.scratch.axisIndices;
axisIndices.clear ();
- auto &axisValues = scratch.axisValues;
+ auto &axisValues = c.scratch.axisValues;
axisValues.clear ();
if (flags & (unsigned) flags_t::HAVE_AXES)
{
@@ -222,7 +216,7 @@
* limit on the max number of coords for now. */
if ((flags & (unsigned) flags_t::RESET_UNSPECIFIED_AXES) ||
coords.length > HB_VAR_COMPOSITE_MAX_AXES)
- component_coords = hb_array<int> (font->coords, font->num_coords);
+ component_coords = hb_array<int> (c.font->coords, c.font->num_coords);
// Transform
@@ -316,14 +310,18 @@
transform.scaleY = transform.scaleX;
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);
+ total_transform.scale (c.font->x_mult ? 1.f / c.font->x_multf : 0.f,
+ c.font->y_mult ? 1.f / c.font->y_multf : 0.f);
- VARC.get_path_at (font, gid,
- draw_session, component_coords, total_transform,
+ bool same_coords = component_coords.length == coords.length &&
+ component_coords.arrayZ == coords.arrayZ;
+
+ c.depth_left--;
+ VARC.get_path_at (c, gid,
+ component_coords, total_transform,
parent_gid,
- decycler, edges_left, depth_left - 1,
- scratch);
+ same_coords ? cache : nullptr);
+ c.depth_left++;
}
#undef PROCESS_TRANSFORM_COMPONENTS
@@ -333,16 +331,12 @@
}
bool
-VARC::get_path_at (hb_font_t *font,
+VARC::get_path_at (const hb_varc_context_t &c,
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
+ VarRegionList::cache_t *parent_cache) const
{
// Don't recurse on the same glyph.
unsigned idx = glyph == parent_glyph ?
@@ -350,32 +344,49 @@
(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,
- 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;
+ if (c.draw_session)
+ {
+ // 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,
+ c.draw_session->funcs,
+ c.draw_session->draw_data,
+ &c.draw_session->st};
+ hb_draw_session_t transformer_session {transformer_funcs, &context};
+ hb_draw_session_t &shape_draw_session = transform.is_identity () ? *c.draw_session : transformer_session;
- if (!font->face->table.glyf->get_path_at (font, glyph, shape_draw_session, coords, scratch))
+ if (!c.font->face->table.glyf->get_path_at (c.font, glyph, shape_draw_session, coords, c.scratch.glyf_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
+ if (!c.font->face->table.cff2->get_path_at (c.font, glyph, shape_draw_session, coords))
+ if (!c.font->face->table.cff1->get_path (c.font, glyph, shape_draw_session)) // Doesn't have variations
#endif
- return false;
+ return false;
+ }
+ else if (c.extents)
+ {
+ hb_glyph_extents_t glyph_extents;
+ if (!c.font->face->table.glyf->get_extents_at (c.font, glyph, &glyph_extents, coords))
+#ifndef HB_NO_CFF
+ if (!c.font->face->table.cff2->get_extents_at (c.font, glyph, &glyph_extents, coords))
+ if (!c.font->face->table.cff1->get_extents (c.font, glyph, &glyph_extents)) // Doesn't have variations
+#endif
+ return false;
+
+ hb_extents_t comp_extents (glyph_extents);
+ transform.transform_extents (comp_extents);
+ c.extents->union_ (comp_extents);
+ }
return true;
}
- if (depth_left <= 0)
+ if (c.depth_left <= 0)
return true;
- if (*edges_left <= 0)
+ if (c.edges_left <= 0)
return true;
- (*edges_left)--;
+ (c.edges_left)--;
- hb_decycler_node_t node (*decycler);
+ hb_decycler_node_t node (c.decycler);
if (unlikely (!node.visit (glyph)))
return true;
@@ -382,18 +393,20 @@
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));
+ VarRegionList::cache_t *cache = parent_cache ?
+ parent_cache :
+ (this+varStore).create_cache (hb_array (static_cache));
- transform.scale (font->x_multf, font->y_multf);
+ transform.scale (c.font->x_multf, c.font->y_multf);
- VarCompositeGlyph::get_path_at (font, glyph,
- draw_session, coords, transform,
+ VarCompositeGlyph::get_path_at (c,
+ glyph,
+ coords, transform,
record,
- decycler, edges_left, depth_left,
- scratch,
cache);
- (this+varStore).destroy_cache (cache, hb_array (static_cache));
+ if (cache != parent_cache)
+ (this+varStore).destroy_cache (cache, hb_array (static_cache));
return true;
}
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Var/VARC/VARC.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -21,6 +21,24 @@
#ifndef HB_NO_VAR_COMPOSITES
+struct hb_varc_scratch_t
+{
+ hb_vector_t<unsigned> axisIndices;
+ hb_vector_t<float> axisValues;
+ hb_glyf_scratch_t glyf_scratch;
+};
+
+struct hb_varc_context_t
+{
+ hb_font_t *font;
+ hb_draw_session_t *draw_session;
+ hb_extents_t *extents;
+ mutable hb_decycler_t decycler;
+ mutable signed edges_left;
+ mutable signed depth_left;
+ hb_varc_scratch_t &scratch;
+};
+
struct VarComponent
{
enum class flags_t : uint32_t
@@ -44,16 +62,11 @@
};
HB_INTERNAL hb_ubytes_t
- get_path_at (hb_font_t *font,
+ get_path_at (const hb_varc_context_t &c,
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_decycler_t *decycler,
- signed *edges_left,
- signed depth_left,
- hb_glyf_scratch_t &scratch,
VarRegionList::cache_t *cache = nullptr) const;
};
@@ -60,25 +73,21 @@
struct VarCompositeGlyph
{
static void
- get_path_at (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_draw_session_t &draw_session,
+ get_path_at (const hb_varc_context_t &c,
+ hb_codepoint_t gid,
hb_array_t<const int> coords,
hb_transform_t transform,
hb_ubytes_t record,
- hb_decycler_t *decycler,
- signed *edges_left,
- signed depth_left,
- hb_glyf_scratch_t &scratch,
- VarRegionList::cache_t *cache = nullptr)
+ VarRegionList::cache_t *cache)
{
while (record)
{
const VarComponent &comp = * (const VarComponent *) (record.arrayZ);
- record = comp.get_path_at (font, glyph,
- draw_session, coords, transform,
+ record = comp.get_path_at (c,
+ gid,
+ coords, transform,
record,
- decycler, edges_left, depth_left, scratch, cache);
+ cache);
}
}
};
@@ -92,38 +101,49 @@
static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C');
HB_INTERNAL bool
- get_path_at (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_draw_session_t &draw_session,
+ get_path_at (const hb_varc_context_t &c,
+ hb_codepoint_t gid,
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;
+ hb_transform_t transform = HB_TRANSFORM_IDENTITY,
+ hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID,
+ VarRegionList::cache_t *parent_cache = nullptr) const;
bool
get_path (hb_font_t *font,
hb_codepoint_t gid,
hb_draw_session_t &draw_session,
- hb_glyf_scratch_t &scratch) const
+ hb_varc_scratch_t &scratch) const
{
- hb_decycler_t decycler;
- signed edges = HB_MAX_GRAPH_EDGE_COUNT;
+ hb_varc_context_t c {font,
+ &draw_session,
+ nullptr,
+ hb_decycler_t {},
+ HB_MAX_GRAPH_EDGE_COUNT,
+ HB_MAX_NESTING_LEVEL,
+ scratch};
- 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);
+ return get_path_at (c, gid,
+ hb_array (font->coords, font->num_coords));
}
+ bool
+ get_extents (hb_font_t *font,
+ hb_codepoint_t gid,
+ hb_extents_t *extents,
+ hb_varc_scratch_t &scratch) const
+ {
+ hb_varc_context_t c {font,
+ nullptr,
+ extents,
+ hb_decycler_t {},
+ HB_MAX_GRAPH_EDGE_COUNT,
+ HB_MAX_NESTING_LEVEL,
+ scratch};
+
+ return get_path_at (c, gid,
+ hb_array (font->coords, font->num_coords));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -150,7 +170,7 @@
auto *scratch = cached_scratch.get_relaxed ();
if (scratch)
{
- scratch->~hb_glyf_scratch_t ();
+ scratch->~hb_varc_scratch_t ();
hb_free (scratch);
}
@@ -162,34 +182,60 @@
{
if (!table->has_data ()) return false;
- hb_glyf_scratch_t *scratch;
+ auto *scratch = acquire_scratch ();
+ if (unlikely (!scratch)) return true;
+ bool ret = table->get_path (font, gid, draw_session, *scratch);
+ release_scratch (scratch);
+ return ret;
+ }
- // Borrow the cached strach buffer.
+ bool
+ get_extents (hb_font_t *font,
+ hb_codepoint_t gid,
+ hb_glyph_extents_t *extents) const
+ {
+ if (!table->has_data ()) return false;
+
+ hb_extents_t f_extents;
+
+ auto *scratch = acquire_scratch ();
+ if (unlikely (!scratch)) return true;
+ bool ret = table->get_extents (font, gid, &f_extents, *scratch);
+ release_scratch (scratch);
+
+ if (ret)
+ *extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0);
+
+ return ret;
+ }
+
+ private:
+
+ hb_varc_scratch_t *acquire_scratch () const
+ {
+ hb_varc_scratch_t *scratch = cached_scratch.get_acquire ();
+
+ if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
{
- 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;
- }
+ scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t));
+ if (unlikely (!scratch))
+ return nullptr;
}
- bool ret = table->get_path (font, gid, draw_session, *scratch);
-
- // Put it back.
+ return scratch;
+ }
+ void release_scratch (hb_varc_scratch_t *scratch) const
+ {
if (!cached_scratch.cmpexch (nullptr, scratch))
{
- scratch->~hb_glyf_scratch_t ();
+ scratch->~hb_varc_scratch_t ();
hb_free (scratch);
}
-
- return ret;
}
private:
hb_blob_ptr_t<VARC> table;
- hb_atomic_ptr_t<hb_glyf_scratch_t> cached_scratch;
+ hb_atomic_t<hb_varc_scratch_t *> cached_scratch;
};
bool has_data () const { return version.major != 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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -429,16 +429,27 @@
}
public:
- bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+
+ bool get_extents (hb_font_t *font,
+ hb_codepoint_t gid,
+ hb_glyph_extents_t *extents) const
+ { return get_extents_at (font, gid, extents, hb_array (font->coords, font->num_coords)); }
+
+ bool get_extents_at (hb_font_t *font,
+ hb_codepoint_t gid,
+ hb_glyph_extents_t *extents,
+ hb_array_t<const int> coords) const
{
if (unlikely (gid >= num_glyphs)) return false;
#ifndef HB_NO_VAR
- if (font->num_coords)
+ if (coords)
{
hb_glyf_scratch_t scratch;
- return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true),
- hb_array (font->coords, font->num_coords),
+ return get_points (font,
+ gid,
+ points_aggregator_t (font, extents, nullptr, true),
+ coords,
scratch);
}
#endif
@@ -532,7 +543,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;
+ hb_atomic_t<hb_glyf_scratch_t *> cached_scratch;
};
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/addTable.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/addTable.py 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/addTable.py 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+
import sys
from fontTools.ttLib import TTFont
from fontTools.ttLib.tables.DefaultTable import DefaultTable
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/check-symbols.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/check-symbols.py 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/check-symbols.py 2025-03-24 00:38:36 UTC (rev 74729)
@@ -7,18 +7,26 @@
builddir = os.getenv ('builddir', os.path.dirname (__file__))
libs = os.getenv ('libs', '.libs')
-IGNORED_SYMBOLS = '|'.join(['_fini', '_init', '_fdata', '_ftext', '_fbss',
+IGNORED_SYMBOLS = ['_fini', '_init', '_fdata', '_ftext', '_fbss',
'__bss_start', '__bss_start__', '__bss_end__', '_edata', '_end', '_bss_end__',
'__end__', '__gcov_.*', 'llvm_.*', 'flush_fn_list', 'writeout_fn_list', 'mangle_path',
- 'lprofDirMode', 'reset_fn_list'])
+ 'lprofDirMode', 'reset_fn_list']
+# Rust
+IGNORED_SYMBOLS += [
+ 'rust_eh_personality',
+ '_ZN3std9panicking11EMPTY_PANIC.*', # 'std::panicking::EMPTY_PANIC::.*'
+ '_ZN3std3sys3pal4unix4args3imp15ARGV_INIT_ARRAY.*', # 'std::sys::pal::unix::args::imp::ARGV_INIT_ARRAY::.*'
+ '_ZN17compiler_builtins4math4libm7generic4sqrt9RSQRT_TAB.*', # 'compiler_builtins::math::libm::generic::sqrt::RSQRT_TAB::.*'
+]
+
+IGNORED_SYMBOLS = '|'.join (IGNORED_SYMBOLS)
+
nm = os.getenv ('NM', shutil.which ('nm'))
if not nm:
print ('check-symbols.py: \'nm\' not found; skipping test')
sys.exit (77)
-cxxfilt = shutil.which ('c++filt')
-
tested = False
stat = 0
@@ -34,12 +42,6 @@
for s in re.findall (r'^.+ [BCDGIRSTu] .+$', subprocess.check_output (nm.split() + [so]).decode ('utf-8'), re.MULTILINE)
if not re.match (r'.* %s(%s)\b' % (symprefix, IGNORED_SYMBOLS), s)]
- # run again c++filt also if is available
- if cxxfilt:
- EXPORTED_SYMBOLS = subprocess.check_output (
- [cxxfilt], input='\n'.join (EXPORTED_SYMBOLS).encode ()
- ).decode ('utf-8').splitlines ()
-
prefix = (symprefix + os.path.basename (so)).replace ('libharfbuzz', 'hb').replace ('-', '_').split ('.')[0]
print ('Checking that %s does not expose internal symbols' % so)
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/Cargo.lock
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/Cargo.lock (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/Cargo.lock 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,95 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "bytemuck"
+version = "1.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "font-types"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d868ec188a98bb014c606072edd47e52e7ab7297db943b0b28503121e1d037bd"
+dependencies = [
+ "bytemuck",
+]
+
+[[package]]
+name = "harfbuzz_fontations"
+version = "0.0.0"
+dependencies = [
+ "read-fonts",
+ "skrifa",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "read-fonts"
+version = "0.27.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f14974c88fb4fd0a7203719f98020209248c9dbebaf9d10d860337797a905097"
+dependencies = [
+ "bytemuck",
+ "font-types",
+]
+
+[[package]]
+name = "skrifa"
+version = "0.29.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c0ca53de9bb9bee1720c727606275148463cd938eb6bde249dcedeec4967747"
+dependencies = [
+ "bytemuck",
+ "read-fonts",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/Cargo.toml
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/Cargo.toml (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/Cargo.toml 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,28 @@
+[package]
+name = "harfbuzz_fontations"
+edition = "2021"
+
+[dependencies]
+read-fonts = "0.27"
+skrifa = "0.29.2"
+
+[lib]
+name = "harfbuzz_fontations"
+path = "lib.rs"
+crate-type = ["staticlib"]
+
+[profile.release]
+strip = true
+lto = "fat"
+panic = "abort"
+overflow-checks = false
+codegen-units = 1
+
+[profile.debugoptimized]
+inherits = "release"
+debug = true
+codegen-units = 16
+strip = false
+
+[profile.dev]
+lto = "fat"
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/lib.rs
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/lib.rs (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/lib.rs 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,944 @@
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
+include!(concat!(env!("OUT_DIR"), "/hb.rs"));
+
+use std::alloc::{GlobalAlloc, Layout};
+use std::collections::HashMap;
+use std::mem::transmute;
+use std::os::raw::c_void;
+use std::ptr::null_mut;
+use std::sync::atomic::{AtomicPtr, AtomicU32, Ordering};
+use std::sync::{Mutex, OnceLock};
+
+use read_fonts::tables::cpal::ColorRecord;
+use read_fonts::TableProvider;
+use skrifa::charmap::Charmap;
+use skrifa::charmap::MapVariant::Variant;
+use skrifa::color::{
+ Brush, ColorGlyphCollection, ColorPainter, ColorStop, CompositeMode, Extend, Transform,
+};
+use skrifa::font::FontRef;
+use skrifa::instance::{Location, NormalizedCoord, Size};
+use skrifa::metrics::{BoundingBox, GlyphMetrics};
+use skrifa::outline::pen::OutlinePen;
+use skrifa::outline::DrawSettings;
+use skrifa::OutlineGlyphCollection;
+use skrifa::{GlyphId, GlyphNames, MetadataProvider};
+
+struct MyAllocator;
+
+unsafe impl GlobalAlloc for MyAllocator {
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ assert!(layout.align() <= 2 * std::mem::size_of::<*mut u8>());
+ hb_malloc(layout.size()) as *mut u8
+ }
+
+ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+ assert!(layout.align() <= 2 * std::mem::size_of::<*mut u8>());
+ hb_calloc(layout.size(), 1) as *mut u8
+ }
+
+ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ assert!(layout.align() <= 2 * std::mem::size_of::<*mut u8>());
+ hb_realloc(ptr as *mut c_void, new_size) as *mut u8
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+ assert!(layout.align() <= 2 * std::mem::size_of::<*mut u8>());
+ hb_free(ptr as *mut c_void);
+ }
+}
+
+#[global_allocator]
+static GLOBAL: MyAllocator = MyAllocator;
+
+// A struct for storing your “fontations” data
+#[repr(C)]
+struct FontationsData<'a> {
+ face_blob: *mut hb_blob_t,
+ font: *mut hb_font_t,
+ font_ref: FontRef<'a>,
+ char_map: Charmap<'a>,
+ outline_glyphs: OutlineGlyphCollection<'a>,
+ color_glyphs: ColorGlyphCollection<'a>,
+ glyph_names: GlyphNames<'a>,
+ glyph_from_names: OnceLock<HashMap<String, hb_codepoint_t>>,
+ size: Size,
+
+ // Mutex for the below
+ mutex: Mutex<()>,
+ serial: AtomicU32,
+ x_mult: f32,
+ y_mult: f32,
+ location: Location,
+ glyph_metrics: Option<GlyphMetrics<'a>>,
+}
+
+impl FontationsData<'_> {
+ unsafe fn from_hb_font(font: *mut hb_font_t) -> Self {
+ let face_index = hb_face_get_index(hb_font_get_face(font));
+ let face_blob = hb_face_reference_blob(hb_font_get_face(font));
+ let blob_length = hb_blob_get_length(face_blob);
+ let blob_data = hb_blob_get_data(face_blob, null_mut());
+ let face_data = std::slice::from_raw_parts(blob_data as *const u8, blob_length as usize);
+
+ let font_ref = FontRef::from_index(face_data, face_index).unwrap();
+
+ let char_map = Charmap::new(&font_ref);
+
+ let outline_glyphs = font_ref.outline_glyphs();
+
+ let color_glyphs = font_ref.color_glyphs();
+
+ let glyph_names = font_ref.glyph_names();
+
+ let upem = hb_face_get_upem(hb_font_get_face(font));
+
+ let mut data = FontationsData {
+ face_blob,
+ font,
+ font_ref,
+ char_map,
+ outline_glyphs,
+ color_glyphs,
+ glyph_names,
+ glyph_from_names: OnceLock::new(),
+ size: Size::new(upem as f32),
+ mutex: Mutex::new(()),
+ x_mult: 1.0,
+ y_mult: 1.0,
+ serial: AtomicU32::new(u32::MAX),
+ location: Location::default(),
+ glyph_metrics: None,
+ };
+
+ data.check_for_updates();
+
+ data
+ }
+
+ unsafe fn _check_for_updates(&mut self) {
+ let font_serial = hb_font_get_serial(self.font);
+ let serial = self.serial.load(Ordering::Relaxed);
+ if serial == font_serial {
+ return;
+ }
+
+ let _lock = self.mutex.lock().unwrap();
+
+ let mut x_scale: i32 = 0;
+ let mut y_scale: i32 = 0;
+ hb_font_get_scale(self.font, &mut x_scale, &mut y_scale);
+ let upem = hb_face_get_upem(hb_font_get_face(self.font));
+ self.x_mult = x_scale as f32 / upem as f32;
+ self.y_mult = y_scale as f32 / upem as f32;
+
+ let mut num_coords: u32 = 0;
+ let coords = hb_font_get_var_coords_normalized(self.font, &mut num_coords);
+ let coords = if coords.is_null() {
+ &[]
+ } else {
+ std::slice::from_raw_parts(coords, num_coords as usize)
+ };
+ let all_zeros = coords.iter().all(|&x| x == 0);
+ // if all zeros, use Location::default()
+ // otherwise, use the provided coords.
+ // This currently doesn't seem to have a perf effect on fontations, but it's a good idea to
+ // check if the coords are all zeros before creating a Location.
+ self.location = if all_zeros {
+ Location::default()
+ } else {
+ let mut location = Location::new(num_coords as usize);
+ let coords_mut = location.coords_mut();
+ coords_mut
+ .iter_mut()
+ .zip(coords.iter().map(|v| NormalizedCoord::from_bits(*v as i16)))
+ .for_each(|(dest, source)| *dest = source);
+ location
+ };
+
+ let location = transmute::<&Location, &Location>(&self.location);
+ self.glyph_metrics = Some(self.font_ref.glyph_metrics(self.size, location));
+
+ self.serial.store(font_serial, Ordering::Release);
+ }
+ fn check_for_updates(&mut self) {
+ unsafe { self._check_for_updates() }
+ }
+}
+
+extern "C" fn _hb_fontations_data_destroy(font_data: *mut c_void) {
+ let data = unsafe { Box::from_raw(font_data as *mut FontationsData) };
+
+ unsafe {
+ hb_blob_destroy(data.face_blob);
+ }
+}
+
+fn struct_at_offset<T: Copy>(first: *const T, index: u32, stride: u32) -> T {
+ unsafe { *((first as *const u8).offset((index * stride) as isize) as *const T) }
+}
+
+fn struct_at_offset_mut<T: Copy>(first: *mut T, index: u32, stride: u32) -> &'static mut T {
+ unsafe { &mut *((first as *mut u8).offset((index * stride) as isize) as *mut T) }
+}
+
+extern "C" fn _hb_fontations_get_nominal_glyphs(
+ _font: *mut hb_font_t,
+ font_data: *mut ::std::os::raw::c_void,
+ count: ::std::os::raw::c_uint,
+ first_unicode: *const hb_codepoint_t,
+ unicode_stride: ::std::os::raw::c_uint,
+ first_glyph: *mut hb_codepoint_t,
+ glyph_stride: ::std::os::raw::c_uint,
+ _user_data: *mut ::std::os::raw::c_void,
+) -> ::std::os::raw::c_uint {
+ let data = unsafe { &*(font_data as *const FontationsData) };
+ let char_map = &data.char_map;
+
+ for i in 0..count {
+ let unicode = struct_at_offset(first_unicode, i, unicode_stride);
+ let Some(glyph) = char_map.map(unicode) else {
+ return i;
+ };
+ let glyph_id = glyph.to_u32() as hb_codepoint_t;
+ *struct_at_offset_mut(first_glyph, i, glyph_stride) = glyph_id;
+ }
+
+ count
+}
+extern "C" fn _hb_fontations_get_variation_glyph(
+ _font: *mut hb_font_t,
+ font_data: *mut ::std::os::raw::c_void,
+ unicode: hb_codepoint_t,
+ variation_selector: hb_codepoint_t,
+ glyph: *mut hb_codepoint_t,
+ _user_data: *mut ::std::os::raw::c_void,
+) -> hb_bool_t {
+ let data = unsafe { &*(font_data as *const FontationsData) };
+ let char_map = &data.char_map;
+
+ match char_map.map_variant(unicode, variation_selector) {
+ Some(Variant(glyph_id)) => {
+ unsafe { *glyph = glyph_id.to_u32() as hb_codepoint_t };
+ true as hb_bool_t
+ }
+ _ => false as hb_bool_t,
+ }
+}
+
+extern "C" fn _hb_fontations_get_glyph_h_advances(
+ _font: *mut hb_font_t,
+ font_data: *mut ::std::os::raw::c_void,
+ count: ::std::os::raw::c_uint,
+ first_glyph: *const hb_codepoint_t,
+ glyph_stride: ::std::os::raw::c_uint,
+ first_advance: *mut hb_position_t,
+ advance_stride: ::std::os::raw::c_uint,
+ _user_data: *mut ::std::os::raw::c_void,
+) {
+ let data = unsafe { &mut *(font_data as *mut FontationsData) };
+ data.check_for_updates();
+
+ let glyph_metrics = &data.glyph_metrics.as_ref().unwrap();
+
+ for i in 0..count {
+ let glyph = struct_at_offset(first_glyph, i, glyph_stride);
+ let glyph_id = GlyphId::new(glyph);
+ let advance = (glyph_metrics.advance_width(glyph_id).unwrap_or_default() * data.x_mult)
+ .round() as i32;
+ *struct_at_offset_mut(first_advance, i, advance_stride) = advance as hb_position_t;
+ }
+}
+extern "C" fn _hb_fontations_get_glyph_extents(
+ _font: *mut hb_font_t,
+ font_data: *mut ::std::os::raw::c_void,
+ glyph: hb_codepoint_t,
+ extents: *mut hb_glyph_extents_t,
+ _user_data: *mut ::std::os::raw::c_void,
+) -> hb_bool_t {
+ let data = unsafe { &mut *(font_data as *mut FontationsData) };
+ data.check_for_updates();
+
+ let glyph_metrics = &data.glyph_metrics.as_ref().unwrap();
+
+ let glyph_id = GlyphId::new(glyph);
+ let glyph_extents = glyph_metrics.bounds(glyph_id);
+ let Some(glyph_extents) = glyph_extents else {
+ return false as hb_bool_t;
+ };
+
+ let x_bearing = (glyph_extents.x_min * data.x_mult).round() as hb_position_t;
+ let width = (glyph_extents.x_max * data.x_mult).round() as hb_position_t - x_bearing;
+ let y_bearing = (glyph_extents.y_max * data.y_mult).round() as hb_position_t;
+ let height = (glyph_extents.y_min * data.y_mult).round() as hb_position_t - y_bearing;
+
+ unsafe {
+ *extents = hb_glyph_extents_t {
+ x_bearing,
+ y_bearing,
+ width,
+ height,
+ };
+ }
+
+ true as hb_bool_t
+}
+
+extern "C" fn _hb_fontations_get_font_h_extents(
+ _font: *mut hb_font_t,
+ font_data: *mut ::std::os::raw::c_void,
+ extents: *mut hb_font_extents_t,
+ _user_data: *mut ::std::os::raw::c_void,
+) -> hb_bool_t {
+ let data = unsafe { &mut *(font_data as *mut FontationsData) };
+ data.check_for_updates();
+
+ let font_ref = &data.font_ref;
+ let size = &data.size;
+ let location = &data.location;
+ let metrics = font_ref.metrics(*size, location);
+
+ unsafe {
+ (*extents).ascender = (metrics.ascent * data.y_mult).round() as hb_position_t;
+ (*extents).descender = (metrics.descent * data.y_mult).round() as hb_position_t;
+ (*extents).line_gap = (metrics.leading * data.y_mult).round() as hb_position_t;
+ }
+
+ true as hb_bool_t
+}
+
+struct HbPen {
+ x_mult: f32,
+ y_mult: f32,
+ draw_state: *mut hb_draw_state_t,
+ draw_funcs: *mut hb_draw_funcs_t,
+ draw_data: *mut c_void,
+}
+
+impl OutlinePen for HbPen {
+ fn move_to(&mut self, x: f32, y: f32) {
+ unsafe {
+ hb_draw_move_to(
+ self.draw_funcs,
+ self.draw_data,
+ self.draw_state,
+ x * self.x_mult,
+ y * self.y_mult,
+ );
+ }
+ }
+ fn line_to(&mut self, x: f32, y: f32) {
+ unsafe {
+ hb_draw_line_to(
+ self.draw_funcs,
+ self.draw_data,
+ self.draw_state,
+ x * self.x_mult,
+ y * self.y_mult,
+ );
+ }
+ }
+ fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
+ unsafe {
+ hb_draw_quadratic_to(
+ self.draw_funcs,
+ self.draw_data,
+ self.draw_state,
+ x1 * self.x_mult,
+ y1 * self.y_mult,
+ x * self.x_mult,
+ y * self.y_mult,
+ );
+ }
+ }
+ fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
+ unsafe {
+ hb_draw_cubic_to(
+ self.draw_funcs,
+ self.draw_data,
+ self.draw_state,
+ x1 * self.x_mult,
+ y1 * self.y_mult,
+ x2 * self.x_mult,
+ y2 * self.y_mult,
+ x * self.x_mult,
+ y * self.y_mult,
+ );
+ }
+ }
+ fn close(&mut self) {
+ unsafe {
+ hb_draw_close_path(self.draw_funcs, self.draw_data, self.draw_state);
+ }
+ }
+}
+
+extern "C" fn _hb_fontations_draw_glyph(
+ font: *mut hb_font_t,
+ font_data: *mut ::std::os::raw::c_void,
+ glyph: hb_codepoint_t,
+ draw_funcs: *mut hb_draw_funcs_t,
+ draw_data: *mut ::std::os::raw::c_void,
+ _user_data: *mut ::std::os::raw::c_void,
+) {
+ let data = unsafe { &mut *(font_data as *mut FontationsData) };
+ data.check_for_updates();
+
+ let size = &data.size;
+ let location = &data.location;
+ let outline_glyphs = &data.outline_glyphs;
+
+ // Create an outline-glyph
+ let glyph_id = GlyphId::new(glyph);
+ let Some(outline_glyph) = outline_glyphs.get(glyph_id) else {
+ return;
+ };
+ let draw_settings = DrawSettings::unhinted(*size, location);
+ // Allocate zero bytes for the draw_state_t on the stack.
+ let mut draw_state: hb_draw_state_t = unsafe { std::mem::zeroed::<hb_draw_state_t>() };
+
+ let slant = unsafe { hb_font_get_synthetic_slant(font) };
+ let mut x_scale: i32 = 0;
+ let mut y_scale: i32 = 0;
+ unsafe {
+ hb_font_get_scale(font, &mut x_scale, &mut y_scale);
+ }
+ let slant = if y_scale != 0 {
+ slant as f32 * x_scale as f32 / y_scale as f32
+ } else {
+ 0.
+ };
+ draw_state.slant_xy = slant;
+
+ let mut pen = HbPen {
+ x_mult: data.x_mult,
+ y_mult: data.y_mult,
+ draw_state: &mut draw_state,
+ draw_funcs,
+ draw_data,
+ };
+
+ let _ = outline_glyph.draw(draw_settings, &mut pen);
+}
+
+struct HbColorPainter<'a> {
+ font: *mut hb_font_t,
+ paint_funcs: *mut hb_paint_funcs_t,
+ paint_data: *mut c_void,
+ color_records: &'a [ColorRecord],
+ foreground: hb_color_t,
+}
+
+impl HbColorPainter<'_> {
+ fn lookup_color(&self, color_index: u16, alpha: f32) -> hb_color_t {
+ if color_index == 0xFFFF {
+ // Apply alpha to foreground color
+ return ((self.foreground & 0xFFFFFF00)
+ | (((self.foreground & 0xFF) as f32 * alpha).round() as u32))
+ as hb_color_t;
+ }
+
+ let c = self.color_records.get(color_index as usize);
+ if c.is_some() {
+ let c = c.unwrap();
+ (((c.blue as u32) << 24)
+ | ((c.green as u32) << 16)
+ | ((c.red as u32) << 8)
+ | ((c.alpha as f32 * alpha).round() as u32)) as hb_color_t
+ } else {
+ 0 as hb_color_t
+ }
+ }
+
+ fn make_color_line(&self, color_line: &ColorLineData) -> hb_color_line_t {
+ let mut cl = unsafe { std::mem::zeroed::<hb_color_line_t>() };
+ cl.data = color_line as *const ColorLineData as *mut ::std::os::raw::c_void;
+ cl.get_color_stops = Some(_hb_fontations_get_color_stops);
+ cl.get_extend = Some(_hb_fontations_get_extend);
+ cl
+ }
+}
+
+struct ColorLineData<'a> {
+ painter: &'a HbColorPainter<'a>,
+ color_stops: &'a [ColorStop],
+ extend: Extend,
+}
+extern "C" fn _hb_fontations_get_color_stops(
+ _color_line: *mut hb_color_line_t,
+ color_line_data: *mut ::std::os::raw::c_void,
+ start: ::std::os::raw::c_uint,
+ count_out: *mut ::std::os::raw::c_uint,
+ color_stops_out: *mut hb_color_stop_t,
+ _user_data: *mut ::std::os::raw::c_void,
+) -> ::std::os::raw::c_uint {
+ let color_line_data = unsafe { &*(color_line_data as *const ColorLineData) };
+ let color_stops = &color_line_data.color_stops;
+ if count_out.is_null() {
+ return color_stops.len() as u32;
+ }
+ let count = unsafe { *count_out };
+ for i in 0..count {
+ let Some(stop) = color_stops.get(start as usize + i as usize) else {
+ unsafe {
+ *count_out = i;
+ };
+ break;
+ };
+ unsafe {
+ *(color_stops_out.offset(i as isize)) = hb_color_stop_t {
+ offset: stop.offset,
+ color: color_line_data
+ .painter
+ .lookup_color(stop.palette_index, stop.alpha),
+ is_foreground: (stop.palette_index == 0xFFFF) as hb_bool_t,
+ };
+ }
+ }
+ color_stops.len() as u32
+}
+extern "C" fn _hb_fontations_get_extend(
+ _color_line: *mut hb_color_line_t,
+ color_line_data: *mut ::std::os::raw::c_void,
+ _user_data: *mut ::std::os::raw::c_void,
+) -> hb_paint_extend_t {
+ let color_line_data = unsafe { &*(color_line_data as *const ColorLineData) };
+ color_line_data.extend as hb_paint_extend_t // They are the same
+}
+
+pub fn _hb_fontations_unreduce_anchors(
+ x0: f32,
+ y0: f32,
+ x1: f32,
+ y1: f32,
+) -> (f32, f32, f32, f32, f32, f32) {
+ /* Returns (x0, y0, x1, y1, x2, y2) such that the original
+ * `_hb_cairo_reduce_anchors` would produce (xx0, yy0, xx1, yy1)
+ * as outputs.
+ * The OT spec has the following wording; we just need to
+ * invert that operation here:
+ *
+ * Note: An implementation can derive a single vector, from p₀ to a point p₃, by computing the
+ * orthogonal projection of the vector from p₀ to p₁ onto a line perpendicular to line p₀p₂ and
+ * passing through p₀ to obtain point p₃. The linear gradient defined using p₀, p₁ and p₂ as
+ * described above is functionally equivalent to a linear gradient defined by aligning stop
+ * offset 0 to p₀ and aligning stop offset 1.0 to p₃, with each color projecting on either side
+ * of that line in a perpendicular direction. This specification uses three points, p₀, p₁ and
+ * p₂, as that provides greater flexibility in controlling the placement and rotation of the
+ * gradient, as well as variations thereof.
+ */
+
+ let dx = x1 - x0;
+ let dy = y1 - y0;
+
+ (x0, y0, x1, y1, x0 + dy, y0 - dx)
+}
+
+impl ColorPainter for HbColorPainter<'_> {
+ fn push_transform(&mut self, transform: Transform) {
+ unsafe {
+ hb_paint_push_transform(
+ self.paint_funcs,
+ self.paint_data,
+ transform.xx,
+ transform.yx,
+ transform.xy,
+ transform.yy,
+ transform.dx,
+ transform.dy,
+ );
+ }
+ }
+ fn pop_transform(&mut self) {
+ unsafe {
+ hb_paint_pop_transform(self.paint_funcs, self.paint_data);
+ }
+ }
+ fn fill_glyph(
+ &mut self,
+ glyph_id: GlyphId,
+ brush_transform: Option<Transform>,
+ brush: Brush<'_>,
+ ) {
+ unsafe {
+ hb_paint_push_inverse_font_transform(self.paint_funcs, self.paint_data, self.font);
+ }
+ self.push_clip_glyph(glyph_id);
+ unsafe {
+ hb_paint_push_font_transform(self.paint_funcs, self.paint_data, self.font);
+ }
+ if let Some(wrap_in_transform) = brush_transform {
+ self.push_transform(wrap_in_transform);
+ self.fill(brush);
+ self.pop_transform();
+ } else {
+ self.fill(brush);
+ }
+ self.pop_transform();
+ self.pop_clip();
+ self.pop_transform();
+ }
+ fn push_clip_glyph(&mut self, glyph_id: GlyphId) {
+ unsafe {
+ hb_paint_push_clip_glyph(
+ self.paint_funcs,
+ self.paint_data,
+ glyph_id.to_u32() as hb_codepoint_t,
+ self.font,
+ );
+ }
+ }
+ fn push_clip_box(&mut self, bbox: BoundingBox) {
+ unsafe {
+ hb_paint_push_clip_rectangle(
+ self.paint_funcs,
+ self.paint_data,
+ bbox.x_min,
+ bbox.y_min,
+ bbox.x_max,
+ bbox.y_max,
+ );
+ }
+ }
+ fn pop_clip(&mut self) {
+ unsafe {
+ hb_paint_pop_clip(self.paint_funcs, self.paint_data);
+ }
+ }
+ fn fill(&mut self, brush: Brush) {
+ match brush {
+ Brush::Solid {
+ palette_index: color_index,
+ alpha,
+ } => {
+ let is_foreground = color_index == 0xFFFF;
+ unsafe {
+ hb_paint_color(
+ self.paint_funcs,
+ self.paint_data,
+ is_foreground as hb_bool_t,
+ self.lookup_color(color_index, alpha),
+ );
+ }
+ }
+ Brush::LinearGradient {
+ color_stops,
+ extend,
+ p0,
+ p1,
+ } => {
+ let color_stops = ColorLineData {
+ painter: self,
+ color_stops,
+ extend,
+ };
+ let mut color_line = self.make_color_line(&color_stops);
+
+ let (x0, y0, x1, y1, x2, y2) =
+ _hb_fontations_unreduce_anchors(p0.x, p0.y, p1.x, p1.y);
+
+ unsafe {
+ hb_paint_linear_gradient(
+ self.paint_funcs,
+ self.paint_data,
+ &mut color_line,
+ x0,
+ y0,
+ x1,
+ y1,
+ x2,
+ y2,
+ );
+ }
+ }
+ Brush::RadialGradient {
+ color_stops,
+ extend,
+ c0,
+ r0,
+ c1,
+ r1,
+ } => {
+ let color_stops = ColorLineData {
+ painter: self,
+ color_stops,
+ extend,
+ };
+ let mut color_line = self.make_color_line(&color_stops);
+ unsafe {
+ hb_paint_radial_gradient(
+ self.paint_funcs,
+ self.paint_data,
+ &mut color_line,
+ c0.x,
+ c0.y,
+ r0,
+ c1.x,
+ c1.y,
+ r1,
+ );
+ }
+ }
+ Brush::SweepGradient {
+ color_stops,
+ extend,
+ c0,
+ start_angle,
+ end_angle,
+ } => {
+ let color_stops = ColorLineData {
+ painter: self,
+ color_stops,
+ extend,
+ };
+ let mut color_line = self.make_color_line(&color_stops);
+ // Skrifa has this gem, so we swap end_angle and start_angle
+ // when passing to our API:
+ //
+ // * Convert angles and stops from counter-clockwise to clockwise
+ // * for the shader if the gradient is not already reversed due to
+ // * start angle being larger than end angle.
+ //
+ // Undo that.
+ let (start_angle, end_angle) = (360. - start_angle, 360. - end_angle);
+ let start_angle = start_angle.to_radians();
+ let end_angle = end_angle.to_radians();
+ unsafe {
+ hb_paint_sweep_gradient(
+ self.paint_funcs,
+ self.paint_data,
+ &mut color_line,
+ c0.x,
+ c0.y,
+ start_angle,
+ end_angle,
+ );
+ }
+ }
+ }
+ }
+ fn push_layer(&mut self, _mode: CompositeMode) {
+ unsafe {
+ hb_paint_push_group(self.paint_funcs, self.paint_data);
+ }
+ }
+ fn pop_layer_with_mode(&mut self, mode: CompositeMode) {
+ let mode = mode as hb_paint_composite_mode_t; // They are the same
+ unsafe {
+ hb_paint_pop_group(self.paint_funcs, self.paint_data, mode);
+ }
+ }
+}
+
+extern "C" fn _hb_fontations_paint_glyph(
+ font: *mut hb_font_t,
+ font_data: *mut ::std::os::raw::c_void,
+ glyph: hb_codepoint_t,
+ paint_funcs: *mut hb_paint_funcs_t,
+ paint_data: *mut ::std::os::raw::c_void,
+ palette_index: ::std::os::raw::c_uint,
+ foreground: hb_color_t,
+ _user_data: *mut ::std::os::raw::c_void,
+) {
+ let data = unsafe { &mut *(font_data as *mut FontationsData) };
+ data.check_for_updates();
+
+ let font_ref = &data.font_ref;
+ let location = &data.location;
+ let color_glyphs = &data.color_glyphs;
+
+ // Create an color-glyph
+ let glyph_id = GlyphId::new(glyph);
+ let Some(color_glyph) = color_glyphs.get(glyph_id) else {
+ return;
+ };
+
+ let cpal = font_ref.cpal();
+ let color_records = if cpal.is_err() {
+ unsafe { std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0) }
+ } else {
+ let cpal = cpal.unwrap();
+ let num_entries = cpal.num_palette_entries().into();
+ let color_records = cpal.color_records_array();
+ let start_index = cpal.color_record_indices().get(palette_index as usize);
+ let start_index = if start_index.is_some() {
+ start_index
+ } else {
+ // https://github.com/harfbuzz/harfbuzz/issues/5116
+ cpal.color_record_indices().first()
+ };
+
+ if let (Some(Ok(color_records)), Some(start_index)) = (color_records, start_index) {
+ let start_index: usize = start_index.get().into();
+ let color_records = &color_records[start_index..start_index + num_entries];
+ unsafe { std::slice::from_raw_parts(color_records.as_ptr(), num_entries) }
+ } else {
+ unsafe { std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0) }
+ }
+ };
+
+ let mut painter = HbColorPainter {
+ font,
+ paint_funcs,
+ paint_data,
+ color_records,
+ foreground,
+ };
+ unsafe {
+ hb_paint_push_font_transform(paint_funcs, paint_data, font);
+ }
+ let _ = color_glyph.paint(location, &mut painter);
+}
+
+extern "C" fn _hb_fontations_glyph_name(
+ _font: *mut hb_font_t,
+ font_data: *mut ::std::os::raw::c_void,
+ glyph: hb_codepoint_t,
+ name: *mut ::std::os::raw::c_char,
+ size: ::std::os::raw::c_uint,
+ _user_data: *mut ::std::os::raw::c_void,
+) -> hb_bool_t {
+ let data = unsafe { &mut *(font_data as *mut FontationsData) };
+
+ let glyph_name = data.glyph_names.get(GlyphId::new(glyph));
+ match glyph_name {
+ None => false as hb_bool_t,
+ Some(glyph_name) => {
+ let glyph_name = glyph_name.as_str();
+ // Copy the glyph name into the buffer, up to size-1 bytes
+ let len = glyph_name.len().min(size as usize - 1);
+ unsafe {
+ std::ptr::copy_nonoverlapping(glyph_name.as_ptr(), name as *mut u8, len);
+ *name.add(len) = 0;
+ }
+ true as hb_bool_t
+ }
+ }
+}
+
+extern "C" fn _hb_fontations_glyph_from_name(
+ _font: *mut hb_font_t,
+ font_data: *mut ::std::os::raw::c_void,
+ name: *const ::std::os::raw::c_char,
+ len: ::std::os::raw::c_int,
+ glyph: *mut hb_codepoint_t,
+ _user_data: *mut ::std::os::raw::c_void,
+) -> hb_bool_t {
+ let data = unsafe { &mut *(font_data as *mut FontationsData) };
+
+ let name = unsafe { std::slice::from_raw_parts(name as *const u8, len as usize) };
+ let name = std::str::from_utf8(name).unwrap_or_default();
+
+ let glyph_from_names = data.glyph_from_names.get_or_init(|| {
+ data.glyph_names
+ .iter()
+ .map(|(gid, name)| (name.to_string(), gid.to_u32()))
+ .collect()
+ });
+ let glyph_id = glyph_from_names.get(name);
+
+ match glyph_id {
+ None => false as hb_bool_t,
+ Some(glyph_id) => {
+ unsafe {
+ *glyph = *glyph_id;
+ }
+ true as hb_bool_t
+ }
+ }
+}
+
+fn _hb_fontations_font_funcs_get() -> *mut hb_font_funcs_t {
+ static static_ffuncs: AtomicPtr<hb_font_funcs_t> = AtomicPtr::new(null_mut());
+
+ loop {
+ let mut ffuncs = static_ffuncs.load(Ordering::Acquire);
+
+ if !ffuncs.is_null() {
+ return ffuncs;
+ }
+
+ ffuncs = unsafe { hb_font_funcs_create() };
+
+ unsafe {
+ hb_font_funcs_set_nominal_glyphs_func(
+ ffuncs,
+ Some(_hb_fontations_get_nominal_glyphs),
+ null_mut(),
+ None,
+ );
+ hb_font_funcs_set_variation_glyph_func(
+ ffuncs,
+ Some(_hb_fontations_get_variation_glyph),
+ null_mut(),
+ None,
+ );
+ hb_font_funcs_set_glyph_h_advances_func(
+ ffuncs,
+ Some(_hb_fontations_get_glyph_h_advances),
+ null_mut(),
+ None,
+ );
+ hb_font_funcs_set_glyph_extents_func(
+ ffuncs,
+ Some(_hb_fontations_get_glyph_extents),
+ null_mut(),
+ None,
+ );
+ hb_font_funcs_set_font_h_extents_func(
+ ffuncs,
+ Some(_hb_fontations_get_font_h_extents),
+ null_mut(),
+ None,
+ );
+ hb_font_funcs_set_draw_glyph_func(
+ ffuncs,
+ Some(_hb_fontations_draw_glyph),
+ null_mut(),
+ None,
+ );
+ hb_font_funcs_set_paint_glyph_func(
+ ffuncs,
+ Some(_hb_fontations_paint_glyph),
+ null_mut(),
+ None,
+ );
+ hb_font_funcs_set_glyph_name_func(
+ ffuncs,
+ Some(_hb_fontations_glyph_name),
+ null_mut(),
+ None,
+ );
+ hb_font_funcs_set_glyph_from_name_func(
+ ffuncs,
+ Some(_hb_fontations_glyph_from_name),
+ null_mut(),
+ None,
+ );
+ }
+
+ if (static_ffuncs.compare_exchange(null_mut(), ffuncs, Ordering::SeqCst, Ordering::Relaxed))
+ == Ok(null_mut())
+ {
+ return ffuncs;
+ } else {
+ unsafe {
+ hb_font_funcs_destroy(ffuncs);
+ }
+ }
+ }
+}
+
+/// # Safety
+///
+/// This function is unsafe because it connects with the HarfBuzz API.
+#[no_mangle]
+pub unsafe extern "C" fn hb_fontations_font_set_funcs(font: *mut hb_font_t) {
+ let ffuncs = _hb_fontations_font_funcs_get();
+
+ let data = FontationsData::from_hb_font(font);
+ let data_ptr = Box::into_raw(Box::new(data)) as *mut c_void;
+
+ hb_font_set_funcs(font, ffuncs, data_ptr, Some(_hb_fontations_data_destroy));
+}
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/meson.build (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/fontations/meson.build 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,105 @@
+rust = import('unstable-rust')
+
+hb_rs = rust.bindgen(
+ input : '../hb.h',
+ output : 'hb.rs',
+ include_directories: incsrc,
+ args : ['--allowlist-function=hb_.*',
+ '--allowlist-type=hb_.*',
+ '--no-copy=hb_.*',
+ ],
+)
+
+cargo = find_program('cargo')
+rustfmt = find_program('rustfmt')
+
+rust_flags = ''
+cargo_args = [
+ '--package', 'harfbuzz_fontations',
+ '--lib',
+ '--target-dir', meson.current_build_dir(),
+ '--manifest-path', meson.current_source_dir() / 'Cargo.toml',
+ '-Z', 'build-std=std,panic_abort',
+ '-Z', 'build-std-features=panic_immediate_abort',
+]
+
+buildtype = get_option('buildtype')
+if buildtype == 'release' or buildtype == 'debugoptimized'
+ cargo_args += ['--profile', buildtype]
+endif
+
+opt_level = get_option('optimization')
+rust_flags += ' -C opt-level=' + opt_level
+
+harfbuzz_fontations = custom_target(
+ 'harfbuzz_fontations',
+ input: ['lib.rs', 'Cargo.toml', 'Cargo.lock'],
+ output: ['libharfbuzz_fontations.a'],
+ depends: [hb_rs],
+ env: ['OUT_DIR=' + meson.current_build_dir(),
+ 'RUSTFLAGS=' + rust_flags,
+ ],
+ command: [
+ cargo, 'build',
+ ] + cargo_args + [
+ '-Z', 'unstable-options',
+ '--artifact-dir', meson.current_build_dir(),
+ ],
+ install: true,
+ install_dir: join_paths(get_option('prefix'), 'lib'),
+)
+
+harfbuzz_fontations_dep = declare_dependency(
+ link_with: harfbuzz_fontations,
+)
+
+clippy_fix = run_target(
+ 'clippy-fix',
+ env: ['OUT_DIR=' + meson.current_build_dir()],
+ depends: [hb_rs, harfbuzz_fontations],
+ command: [
+ cargo, 'clippy',
+ ] + cargo_args + [
+ '--allow-dirty', '--fix',
+ ],
+)
+if get_option('tests').enabled() and cargo.found()
+ test(
+ 'clippy',
+ cargo,
+ env: ['OUT_DIR=' + meson.current_build_dir()],
+ depends: [hb_rs, harfbuzz_fontations],
+ args: [
+ 'clippy',
+ ] + cargo_args + [
+ '--', '-D', 'warnings',
+ ],
+ timeout: 120,
+ )
+endif
+
+rustfmt_fix = run_target(
+ 'rustfmt-fix',
+ env: ['OUT_DIR=' + meson.current_build_dir()],
+ depends: [hb_rs],
+ command: [
+ rustfmt,
+ '--edition', '2021',
+ '--',
+ meson.current_source_dir() / 'lib.rs',
+ ],
+)
+if get_option('tests').enabled() and rustfmt.found()
+ test(
+ 'rustfmt',
+ rustfmt,
+ env: ['OUT_DIR=' + meson.current_build_dir()],
+ depends: [hb_rs],
+ args: [
+ '--check',
+ '--edition', '2021',
+ '--',
+ meson.current_source_dir() / 'lib.rs',
+ ],
+ )
+endif
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-ragel-artifacts.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-ragel-artifacts.py 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-ragel-artifacts.py 2025-03-24 00:38:36 UTC (rev 74729)
@@ -19,7 +19,9 @@
shutil.copy (INPUT, outdir)
rl = os.path.basename (INPUT)
hh = rl.replace ('.rl', '.hh')
-subprocess.Popen (ragel.split() + ['-e', '-F1', '-o', hh, rl], cwd=outdir).wait ()
+ret = subprocess.Popen (ragel.split() + ['-e', '-F1', '-o', hh, rl], cwd=outdir).wait ()
+if ret:
+ sys.exit (ret)
# copy it also to src/
shutil.copyfile (os.path.join (outdir, hh), os.path.join (CURRENT_SOURCE_DIR, hh))
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -8,6 +8,9 @@
#include "hb-common.cc"
#include "hb-coretext-font.cc"
#include "hb-coretext-shape.cc"
+#include "hb-coretext.cc"
+#include "hb-directwrite-font.cc"
+#include "hb-directwrite-shape.cc"
#include "hb-directwrite.cc"
#include "hb-draw.cc"
#include "hb-face-builder.cc"
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -29,6 +29,8 @@
#include "hb-aat-layout.hh"
#include "hb-aat-map.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-layout-gdef-table.hh"
#include "hb-open-type.hh"
#include "hb-cache.hh"
#include "hb-bit-set.hh"
@@ -48,6 +50,61 @@
using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>;
static_assert (sizeof (hb_aat_class_cache_t) == 256, "");
+struct hb_aat_scratch_t
+{
+ hb_aat_scratch_t () = default;
+ hb_aat_scratch_t (const hb_aat_scratch_t &) = delete;
+
+ hb_aat_scratch_t (hb_aat_scratch_t &&o)
+ {
+ buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ());
+ o.buffer_glyph_set.set_relaxed (nullptr);
+ }
+ hb_aat_scratch_t & operator = (hb_aat_scratch_t &&o)
+ {
+ buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ());
+ o.buffer_glyph_set.set_relaxed (nullptr);
+ return *this;
+ }
+ ~hb_aat_scratch_t ()
+ {
+ auto *s = buffer_glyph_set.get_relaxed ();
+ if (unlikely (!s))
+ return;
+ s->fini ();
+ hb_free (s);
+ }
+
+ hb_bit_set_t *create_buffer_glyph_set () const
+ {
+ hb_bit_set_t *s = buffer_glyph_set.get_acquire ();
+ if (s && buffer_glyph_set.cmpexch (s, nullptr))
+ return s;
+
+ s = (hb_bit_set_t *) hb_calloc (1, sizeof (hb_bit_set_t));
+ if (unlikely (!s))
+ return nullptr;
+ s->init ();
+
+ return s;
+ }
+ void destroy_buffer_glyph_set (hb_bit_set_t *s) const
+ {
+ if (unlikely (!s))
+ return;
+ if (buffer_glyph_set.cmpexch (nullptr, s))
+ return;
+ s->fini ();
+ hb_free (s);
+ }
+
+ mutable hb_atomic_t<hb_bit_set_t *> buffer_glyph_set;
+};
+
+enum { DELETED_GLYPH = 0xFFFF };
+
+#define HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED HB_BUFFER_SCRATCH_FLAG_SHAPER0
+
struct hb_aat_apply_context_t :
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
{
@@ -64,10 +121,11 @@
hb_buffer_t *buffer;
hb_sanitize_context_t sanitizer;
const ankr *ankr_table;
- const OT::GDEF *gdef_table;
+ const OT::GDEF &gdef;
+ bool has_glyph_classes;
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
bool using_buffer_glyph_set = false;
- hb_bit_set_t buffer_glyph_set;
+ hb_bit_set_t *buffer_glyph_set = nullptr;
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;
@@ -90,15 +148,15 @@
void setup_buffer_glyph_set ()
{
- using_buffer_glyph_set = buffer->len >= 4;
+ using_buffer_glyph_set = buffer->len >= 4 && buffer_glyph_set;
- if (using_buffer_glyph_set)
- buffer->collect_codepoints (buffer_glyph_set);
+ if (likely (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);
+ if (likely (using_buffer_glyph_set))
+ return buffer_glyph_set->intersects (*machine_glyph_set);
// Faster for shorter buffers.
for (unsigned i = 0; i < buffer->len; i++)
@@ -106,6 +164,66 @@
return true;
return false;
}
+
+ template <typename T>
+ HB_NODISCARD bool output_glyphs (unsigned int count,
+ const T *glyphs)
+ {
+ if (likely (using_buffer_glyph_set))
+ buffer_glyph_set->add_array (glyphs, count);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (glyphs[i] == DELETED_GLYPH)
+ {
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
+ _hb_glyph_info_set_aat_deleted (&buffer->cur());
+ }
+ else
+ {
+#ifndef HB_NO_OT_LAYOUT
+ if (has_glyph_classes)
+ _hb_glyph_info_set_glyph_props (&buffer->cur(),
+ gdef.get_glyph_props (glyphs[i]));
+#endif
+ }
+ if (unlikely (!buffer->output_glyph (glyphs[i]))) return false;
+ }
+ return true;
+ }
+
+ HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph)
+ {
+ if (glyph == DELETED_GLYPH)
+ return delete_glyph ();
+
+ if (likely (using_buffer_glyph_set))
+ buffer_glyph_set->add (glyph);
+#ifndef HB_NO_OT_LAYOUT
+ if (has_glyph_classes)
+ _hb_glyph_info_set_glyph_props (&buffer->cur(),
+ gdef.get_glyph_props (glyph));
+#endif
+ return buffer->replace_glyph (glyph);
+ }
+
+ HB_NODISCARD bool delete_glyph ()
+ {
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
+ _hb_glyph_info_set_aat_deleted (&buffer->cur());
+ return buffer->replace_glyph (DELETED_GLYPH);
+ }
+
+ void replace_glyph_inplace (unsigned i, hb_codepoint_t glyph)
+ {
+ buffer->info[i].codepoint = glyph;
+ if (likely (using_buffer_glyph_set))
+ buffer_glyph_set->add (glyph);
+#ifndef HB_NO_OT_LAYOUT
+ if (has_glyph_classes)
+ _hb_glyph_info_set_glyph_props (&buffer->info[i],
+ gdef.get_glyph_props (glyph));
+#endif
+ }
};
@@ -113,8 +231,6 @@
* Lookup Table
*/
-enum { DELETED_GLYPH = 0xFFFF };
-
template <typename T> struct Lookup;
template <typename T>
@@ -179,6 +295,7 @@
template <typename set_t, typename filter_t>
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
{
+ if (first == DELETED_GLYPH) return;
if (!filter (value)) return;
glyphs.add_range (first, last);
}
@@ -268,6 +385,7 @@
template <typename set_t, typename filter_t>
void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const
{
+ if (first == DELETED_GLYPH) return;
const auto &values = base+valuesZ;
for (hb_codepoint_t i = first; i <= last; i++)
if (filter (values[i - first]))
@@ -368,6 +486,7 @@
template <typename set_t, typename filter_t>
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
{
+ if (glyph == DELETED_GLYPH) return;
if (!filter (value)) return;
glyphs.add (glyph);
}
@@ -746,6 +865,10 @@
}
// And glyphs in those classes.
+
+ if (filter (CLASS_DELETED_GLYPH))
+ glyphs.add (DELETED_GLYPH);
+
(this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter);
}
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -185,6 +185,9 @@
DEFINE_SIZE_STATIC (2);
};
+ static bool initiateAction (const Entry<EntryData> &entry)
+ { return entry.flags & Push; }
+
static bool performAction (const Entry<EntryData> &entry)
{ return entry.data.kernActionIndex != 0xFFFF; }
@@ -325,8 +328,9 @@
}
else if (buffer->info[idx].mask & kern_mask)
{
- o.x_advance += c->font->em_scale_x (v);
- o.x_offset += c->font->em_scale_x (v);
+ auto scaled = c->font->em_scale_x (v);
+ o.x_advance += scaled;
+ o.x_offset += scaled;
}
}
else
@@ -394,10 +398,8 @@
template <typename set_t>
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
{
- set_t set;
- machine.collect_glyphs (set, num_glyphs);
- left_set.union_ (set);
- right_set.union_ (set);
+ machine.collect_initial_glyphs (left_set, num_glyphs, *this);
+ //machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
}
protected:
@@ -671,10 +673,8 @@
template <typename set_t>
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
{
- set_t set;
- machine.collect_glyphs (set, num_glyphs);
- left_set.union_ (set);
- right_set.union_ (set);
+ machine.collect_initial_glyphs (left_set, num_glyphs, *this);
+ //machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
}
protected:
@@ -921,8 +921,19 @@
* The 'kerx' Table
*/
-using kern_accelerator_data_t = hb_vector_t<hb_pair_t<hb_bit_set_t, hb_bit_set_t>>;
+struct kern_subtable_accelerator_data_t
+{
+ hb_bit_set_t left_set;
+ hb_bit_set_t right_set;
+ mutable hb_aat_class_cache_t class_cache;
+};
+struct kern_accelerator_data_t
+{
+ hb_vector_t<kern_subtable_accelerator_data_t> subtable_accels;
+ hb_aat_scratch_t scratch;
+};
+
template <typename T>
struct KerxTable
{
@@ -985,6 +996,8 @@
{
c->buffer->unsafe_to_concat ();
+ c->setup_buffer_glyph_set ();
+
typedef typename T::SubTable SubTable;
bool ret = false;
@@ -996,6 +1009,8 @@
{
bool reverse;
+ auto &subtable_accel = accel_data.subtable_accels[i];
+
if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation))
goto skip;
@@ -1002,6 +1017,17 @@
if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ())
goto skip;
+ c->left_set = &subtable_accel.left_set;
+ c->right_set = &subtable_accel.right_set;
+ c->machine_glyph_set = &subtable_accel.left_set;
+ c->machine_class_cache = &subtable_accel.class_cache;
+
+ if (!c->buffer_intersects_machine ())
+ {
+ (void) c->buffer->message (c->font, "skipped subtable %u because no glyph matches", c->lookup_index);
+ goto skip;
+ }
+
reverse = bool (st->u.header.coverage & st->u.header.Backwards) !=
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
@@ -1028,9 +1054,6 @@
if (reverse)
c->buffer->reverse ();
- c->left_set = &accel_data[i].first;
- c->right_set = &accel_data[i].second;
-
{
/* See comment in sanitize() for conditional here. */
hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
@@ -1106,9 +1129,13 @@
unsigned int count = thiz()->tableCount;
for (unsigned int i = 0; i < count; i++)
{
- 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));
+ auto &subtable_accel = *accel_data.subtable_accels.push ();
+ if (unlikely (accel_data.subtable_accels.in_error ()))
+ return accel_data;
+
+ st->collect_glyphs (subtable_accel.left_set, subtable_accel.right_set, num_glyphs);
+ subtable_accel.class_cache.clear ();
+
st = &StructAfter<SubTable> (*st);
}
@@ -1137,6 +1164,7 @@
hb_blob_ptr_t<T> table;
kern_accelerator_data_t accel_data;
+ hb_aat_scratch_t scratch;
};
};
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -30,8 +30,6 @@
#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"
/*
@@ -178,12 +176,6 @@
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
- if (!c->buffer_intersects_machine ())
- {
- (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
- return_trace (false);
- }
-
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -242,9 +234,7 @@
ret (false),
c (c_),
table (table_),
- gdef (*c->gdef_table),
mark_set (false),
- has_glyph_classes (gdef.has_glyph_classes ()),
mark (0),
subs (table+table->substitutionTables) {}
@@ -281,12 +271,7 @@
if (replacement)
{
buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
- 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));
+ c->replace_glyph_inplace (mark, *replacement);
ret = true;
}
@@ -312,12 +297,7 @@
}
if (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));
+ c->replace_glyph_inplace (idx, *replacement);
ret = true;
}
@@ -333,9 +313,7 @@
hb_aat_apply_context_t *c;
const ContextualSubtable *table;
private:
- const OT::GDEF &gdef;
bool mark_set;
- bool has_glyph_classes;
unsigned int mark;
const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false> &subs;
};
@@ -348,12 +326,6 @@
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
- if (!c->buffer_intersects_machine ())
- {
- (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
- return_trace (false);
- }
-
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -581,7 +553,7 @@
hb_codepoint_t lig = ligatureData;
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
- if (unlikely (!buffer->replace_glyph (lig))) return;
+ if (unlikely (!c->replace_glyph (lig))) return;
unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
/* Now go and delete all subsequent components. */
@@ -589,8 +561,7 @@
{
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return;
- _hb_glyph_info_set_default_ignorable (&buffer->cur());
- if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return;
+ if (!c->delete_glyph ()) return;
}
if (unlikely (!buffer->move_to (lig_end))) return;
@@ -624,12 +595,6 @@
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
- if (!c->buffer_intersects_machine ())
- {
- (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
- return_trace (false);
- }
-
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -665,15 +630,6 @@
{
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 ();
-
bool ret = false;
unsigned int num_glyphs = c->face->get_num_glyphs ();
@@ -703,12 +659,7 @@
const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
if (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));
+ c->replace_glyph_inplace (i, *replacement);
ret = true;
}
}
@@ -850,9 +801,7 @@
if (buffer->idx < buffer->len && !before)
if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */
- if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
- for (unsigned int i = 0; i < count; i++)
- c->buffer_glyph_set.add (glyphs[i]);
+ if (unlikely (!c->output_glyphs (count, glyphs))) return;
ret = true;
if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();
@@ -881,7 +830,8 @@
if (buffer->idx < buffer->len && !before)
if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */
- if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
+ if (unlikely (!c->output_glyphs (count, glyphs))) return;
+ ret = true;
if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();
@@ -921,12 +871,6 @@
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
- if (!c->buffer_intersects_machine ())
- {
- (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
- return_trace (false);
- }
-
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -1224,6 +1168,7 @@
if (hb_none (hb_iter (c->range_flags) |
hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); })))
goto skip;
+
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;
@@ -1233,6 +1178,12 @@
bool (coverage & ChainSubtable<Types>::Vertical))
goto skip;
+ if (!c->buffer_intersects_machine ())
+ {
+ (void) c->buffer->message (c->font, "skipped chainsubtable %u because no glyph matches", c->lookup_index);
+ goto skip;
+ }
+
/* Buffer contents is always in logical direction. Determine if
* we need to reverse before applying this subtable. We reverse
* back after if we did reverse indeed.
@@ -1376,7 +1327,7 @@
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));
+ this->accels = (hb_atomic_t<hb_aat_layout_chain_accelerator_t *> *) hb_calloc (this->chain_count, sizeof (*accels));
if (unlikely (!this->accels))
{
this->chain_count = 0;
@@ -1423,7 +1374,8 @@
hb_blob_ptr_t<T> table;
unsigned int chain_count;
- hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *accels;
+ hb_atomic_t<hb_aat_layout_chain_accelerator_t *> *accels;
+ hb_aat_scratch_t scratch;
};
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -142,9 +142,9 @@
unsigned j = count - 1;
// Find the two entries that track is between.
- while (i + 1 < count && trackTable[i + 1].get_track_value () < track)
+ while (i + 1 < count && trackTable[i + 1].get_track_value () <= track)
i++;
- while (j > 0 && trackTable[j - 1].get_track_value () > track)
+ while (j > 0 && trackTable[j - 1].get_track_value () >= track)
j--;
// Exact match.
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -58,13 +58,14 @@
buffer (buffer_),
sanitizer (),
ankr_table (&Null (AAT::ankr)),
- gdef_table (
+ gdef (
#ifndef HB_NO_OT_LAYOUT
- face->table.GDEF->table
+ *face->table.GDEF->table
#else
- &Null (GDEF)
+ Null (GDEF)
#endif
),
+ has_glyph_classes (gdef.has_glyph_classes ()),
lookup_index (0)
{
sanitizer.init (blob);
@@ -203,7 +204,7 @@
#endif
-#ifndef HB_NO_AAT
+#ifndef HB_NO_AAT_SHAPE
/*
* mort/morx/kerx/trak
@@ -287,11 +288,14 @@
const hb_feature_t *features,
unsigned num_features)
{
- hb_aat_map_builder_t builder (font->face, plan->props);
- for (unsigned i = 0; i < num_features; i++)
- builder.add_feature (features[i]);
hb_aat_map_t map;
- builder.compile (map);
+ if (num_features)
+ {
+ hb_aat_map_builder_t builder (font->face, plan->props);
+ for (unsigned i = 0; i < num_features; i++)
+ builder.add_feature (features[i]);
+ builder.compile (map);
+ }
{
auto &accel = *font->face->table.morx;
@@ -300,7 +304,10 @@
{
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
if (!buffer->message (font, "start table morx")) return;
- morx.apply (&c, map, accel);
+ c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
+ morx.apply (&c, num_features ? map : plan->aat_map, accel);
+ accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
+ c.buffer_glyph_set = nullptr;
(void) buffer->message (font, "end table morx");
return;
}
@@ -313,7 +320,7 @@
{
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
if (!buffer->message (font, "start table mort")) return;
- mort.apply (&c, map, accel);
+ mort.apply (&c, num_features ? map : plan->aat_map, accel);
(void) buffer->message (font, "end table mort");
return;
}
@@ -320,27 +327,17 @@
}
}
-void
-hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
-{
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- hb_glyph_position_t *pos = buffer->pos;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
- pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
-}
-
static bool
is_deleted_glyph (const hb_glyph_info_t *info)
{
- return info->codepoint == AAT::DELETED_GLYPH;
+ return _hb_glyph_info_is_aat_deleted (info);
}
void
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
{
- buffer->delete_glyphs_inplace (is_deleted_glyph);
+ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED)
+ buffer->delete_glyphs_inplace (is_deleted_glyph);
}
/**
@@ -371,8 +368,11 @@
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
if (!buffer->message (font, "start table kerx")) return;
+ c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
c.set_ankr_table (font->face->table.ankr.get ());
accel.apply (&c);
+ accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
+ c.buffer_glyph_set = nullptr;
(void) buffer->message (font, "end table kerx");
}
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -61,9 +61,6 @@
unsigned num_features);
HB_INTERNAL void
-hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);
-
-HB_INTERNAL void
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer);
HB_INTERNAL void
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -85,6 +85,11 @@
hb_aat_map_builder_t::compile (hb_aat_map_t &m)
{
/* Compute active features per range, and compile each. */
+ if (!features.length)
+ {
+ hb_aat_layout_compile_map (this, &m);
+ return;
+ }
/* Sort features by start/end events. */
hb_vector_t<feature_event_t> feature_events;
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -149,12 +149,12 @@
#define hb_atomic_ptr_impl_get_relaxed(P) (*(P))
#endif
#ifndef hb_atomic_int_impl_set
-inline void hb_atomic_int_impl_set (int *AI, int v) { _hb_memory_w_barrier (); *AI = v; }
-inline void hb_atomic_int_impl_set (short *AI, short v) { _hb_memory_w_barrier (); *AI = v; }
+template <typename T>
+inline void hb_atomic_int_impl_set (T *AI, T v) { _hb_memory_w_barrier (); *AI = v; }
#endif
#ifndef hb_atomic_int_impl_get
-inline int hb_atomic_int_impl_get (const int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; }
-inline short hb_atomic_int_impl_get (const short *AI) { short v = *AI; _hb_memory_r_barrier (); return v; }
+template <typename T>
+inline T hb_atomic_int_impl_get (const T *AI) { T v = *AI; _hb_memory_r_barrier (); return v; }
#endif
#ifndef hb_atomic_ptr_impl_get
inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; }
@@ -161,51 +161,36 @@
#endif
-struct hb_atomic_short_t
+template <typename T>
+struct hb_atomic_t
{
- hb_atomic_short_t () = default;
- constexpr hb_atomic_short_t (short v) : v (v) {}
+ hb_atomic_t () = default;
+ constexpr hb_atomic_t (T v) : v (v) {}
- hb_atomic_short_t& operator = (short v_) { set_relaxed (v_); return *this; }
- operator short () const { return get_relaxed (); }
+ hb_atomic_t& operator = (T v_) { set_relaxed (v_); return *this; }
+ operator T () const { return get_relaxed (); }
- void set_relaxed (short v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
- void set_release (short v_) { hb_atomic_int_impl_set (&v, v_); }
- short get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
- short get_acquire () const { return hb_atomic_int_impl_get (&v); }
- short inc () { return hb_atomic_int_impl_add (&v, 1); }
- short dec () { return hb_atomic_int_impl_add (&v, -1); }
+ void set_relaxed (T v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
+ void set_release (T v_) { hb_atomic_int_impl_set (&v, v_); }
+ T get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
+ T get_acquire () const { return hb_atomic_int_impl_get (&v); }
+ T inc () { return hb_atomic_int_impl_add (&v, 1); }
+ T dec () { return hb_atomic_int_impl_add (&v, -1); }
- short v = 0;
-};
+ int operator ++ (int) { return inc (); }
+ int operator -- (int) { return dec (); }
+ long operator |= (long v_) { set_relaxed (get_relaxed () | v_); return *this; }
-struct hb_atomic_int_t
-{
- hb_atomic_int_t () = default;
- constexpr hb_atomic_int_t (int v) : v (v) {}
-
- hb_atomic_int_t& operator = (int v_) { set_relaxed (v_); return *this; }
- operator int () const { return get_relaxed (); }
-
- void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
- void set_release (int v_) { hb_atomic_int_impl_set (&v, v_); }
- int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
- int get_acquire () const { return hb_atomic_int_impl_get (&v); }
- int inc () { return hb_atomic_int_impl_add (&v, 1); }
- int dec () { return hb_atomic_int_impl_add (&v, -1); }
-
- int v = 0;
+ T v = 0;
};
-template <typename P>
-struct hb_atomic_ptr_t
+template <typename T>
+struct hb_atomic_t<T*>
{
- typedef hb_remove_pointer<P> T;
+ hb_atomic_t () = default;
+ constexpr hb_atomic_t (T* v) : v (v) {}
+ hb_atomic_t (const hb_atomic_t &other) = delete;
- hb_atomic_ptr_t () = default;
- constexpr hb_atomic_ptr_t (T* v) : v (v) {}
- hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete;
-
void init (T* v_ = nullptr) { set_relaxed (v_); }
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -77,7 +77,7 @@
bool successful = true; /* Allocations successful */
mutable unsigned int population = 0;
- mutable hb_atomic_int_t last_page_lookup = 0;
+ mutable hb_atomic_t<unsigned> last_page_lookup = 0;
hb_sorted_vector_t<page_map_t> page_map;
hb_vector_t<page_t> pages;
@@ -88,7 +88,7 @@
{
if (unlikely (!successful)) return false;
- if (pages.length < count && count <= 2)
+ if (pages.length < count && (unsigned) pages.allocated < count && count <= 2)
exact_size = true; // Most sets are small and local
if (unlikely (!pages.resize (count, clear, exact_size) ||
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-vector.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-vector.hh (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-vector.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,195 @@
+/*
+ * 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_BIT_VECTOR_HH
+#define HB_BIT_VECTOR_HH
+
+#include "hb.hh"
+
+#include "hb-atomic.hh"
+
+struct hb_min_max_t
+{
+ void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); }
+ void add_range (hb_codepoint_t a, hb_codepoint_t b)
+ {
+ min_v = hb_min (min_v, a);
+ max_v = hb_max (max_v, b);
+ }
+
+ template <typename set_t>
+ void union_ (const set_t &set)
+ {
+ hb_codepoint_t set_min = set.get_min ();
+ if (unlikely (set_min == HB_CODEPOINT_INVALID))
+ return;
+ hb_codepoint_t set_max = set.get_max ();
+ min_v = hb_min (min_v, set_min);
+ max_v = hb_max (max_v, set_max);
+ }
+
+ hb_codepoint_t get_min () const { return min_v; }
+ hb_codepoint_t get_max () const { return max_v; }
+
+ private:
+ hb_codepoint_t min_v = HB_CODEPOINT_INVALID;
+ hb_codepoint_t max_v = 0;
+};
+
+template <bool atomic = false>
+struct hb_bit_vector_t
+{
+ using int_t = uint64_t;
+ using elt_t = typename std::conditional<atomic, hb_atomic_t<int_t>, int_t>::type;
+
+ hb_bit_vector_t () = delete;
+ hb_bit_vector_t (const hb_bit_vector_t &other) = delete;
+ hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete;
+
+ // Move
+ hb_bit_vector_t (hb_bit_vector_t &&other)
+ : min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts)
+ {
+ other.min_v = other.max_v = other.count = 0;
+ other.elts = nullptr;
+ }
+ hb_bit_vector_t &operator= (hb_bit_vector_t &&other)
+ {
+ hb_swap (min_v, other.min_v);
+ hb_swap (max_v, other.max_v);
+ hb_swap (count, other.count);
+ hb_swap (elts, other.elts);
+ return *this;
+ }
+
+ hb_bit_vector_t (unsigned min_v, unsigned max_v)
+ : min_v (min_v), max_v (max_v)
+ {
+ if (unlikely (min_v >= max_v))
+ {
+ min_v = max_v = count = 0;
+ return;
+ }
+
+ unsigned num = (max_v - min_v + sizeof (int_t) * 8) / (sizeof (int_t) * 8);
+ elts = (elt_t *) hb_calloc (num, sizeof (int_t));
+ if (unlikely (!elts))
+ {
+ min_v = max_v = count = 0;
+ return;
+ }
+
+ count = max_v - min_v + 1;
+ }
+ ~hb_bit_vector_t ()
+ {
+ hb_free (elts);
+ }
+
+ void add (hb_codepoint_t g) { elt (g) |= mask (g); }
+ void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
+ 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 has (hb_codepoint_t g) const { return get (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)
+ {
+ if (unlikely (!count || a > b || a < min_v || b > max_v))
+ return;
+
+ elt_t *la = &elt (a);
+ elt_t *lb = &elt (b);
+ if (la == lb)
+ *la |= (mask (b) << 1) - mask(a);
+ else
+ {
+ *la |= ~(mask (a) - 1llu);
+ la++;
+
+ hb_memset (la, 0xff, (char *) lb - (char *) la);
+
+ *lb |= ((mask (b) << 1) - 1llu);
+ }
+ }
+ void del_range (hb_codepoint_t a, hb_codepoint_t b)
+ {
+ if (unlikely (!count || a > b || a < min_v || b > max_v))
+ return;
+
+ elt_t *la = &elt (a);
+ elt_t *lb = &elt (b);
+ if (la == lb)
+ *la &= ~((mask (b) << 1llu) - mask(a));
+ else
+ {
+ *la &= mask (a) - 1;
+ la++;
+
+ hb_memset (la, 0, (char *) lb - (char *) la);
+
+ *lb &= ~((mask (b) << 1) - 1llu);
+ }
+ }
+ void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
+ { if (v) add_range (a, b); else del_range (a, b); }
+
+ template <typename set_t>
+ void union_ (const set_t &set)
+ {
+ for (hb_codepoint_t g : set)
+ add (g);
+ }
+
+ static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
+ static constexpr unsigned ELT_MASK = ELT_BITS - 1;
+
+ static constexpr elt_t zero = 0;
+
+ elt_t &elt (hb_codepoint_t g)
+ {
+ g -= min_v;
+ if (unlikely (g >= count))
+ return Crap(elt_t);
+ return elts[g / ELT_BITS];
+ }
+ const elt_t& elt (hb_codepoint_t g) const
+ {
+ g -= min_v;
+ if (unlikely (g >= count))
+ return Null(elt_t);
+ return elts[g / ELT_BITS];
+ }
+
+ static constexpr int_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
+
+ hb_codepoint_t min_v = 0, max_v = 0, count = 0;
+ elt_t *elts = nullptr;
+};
+
+
+#endif /* HB_BIT_VECTOR_HH */
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -34,36 +34,36 @@
#line 36 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = {
- 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, 93u, 9u, 123u, 0u, 0u, 0
+ 0u, 0u, 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, 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,
+ 9u, 123u, 9u, 123u, 0
};
static const char _deserialize_json_key_spans[] = {
- 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,
- 85, 115, 0
+ 0, 26, 21, 2, 1, 50, 49, 10,
+ 117, 117, 85, 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,
+ 115, 115
};
static const short _deserialize_json_index_offsets[] = {
- 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
+ 0, 0, 27, 49, 52, 54, 105, 155,
+ 166, 284, 402, 488, 606, 608, 659, 709,
+ 720, 838, 956, 958, 960, 1011, 1061, 1179,
+ 1297, 1300, 1302, 1353, 1403, 1414, 1532, 1650,
+ 1652, 1703, 1753, 1764, 1882, 2000, 2002, 2004,
+ 2055, 2105, 2223, 2341, 2343, 2394, 2444, 2504,
+ 2622, 2682, 2800, 2918, 2920, 2971, 3021, 3139,
+ 3255, 3371
};
static const char _deserialize_json_indicies[] = {
@@ -70,21 +70,30 @@
0, 0, 0, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 2, 1, 3, 1, 4, 5,
+ 1, 6, 7, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 8, 1, 9, 10, 1, 11, 1, 11,
+ 11, 11, 11, 11, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 11, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 12, 1, 12, 12, 12, 12, 12, 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, 12, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 13, 1,
+ 1, 14, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 1, 16, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 1, 18,
+ 18, 18, 18, 18, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 18, 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, 19, 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,
@@ -93,66 +102,66 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 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,
- 1, 1, 1, 1, 1, 1, 1, 3,
- 1, 4, 4, 4, 4, 4, 1, 1,
+ 0, 1, 1, 1, 1, 1, 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, 22, 1, 22, 22, 22, 22, 22,
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, 23, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 23,
+ 1, 18, 18, 18, 18, 18, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 18, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 19, 1, 1, 1,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 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,
- 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,
+ 1, 1, 1, 1, 1, 20, 1, 24,
+ 1, 24, 24, 24, 24, 24, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 24, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 25, 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, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 25, 1, 21, 21, 21, 21, 21,
+ 26, 1, 1, 27, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 1, 29, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 1, 31, 31, 31, 31, 31, 1, 1,
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, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 1, 1, 1, 1,
+ 31, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 32, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -160,44 +169,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, 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, 33, 1, 31,
+ 31, 31, 31, 31, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 31, 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, 32, 1, 1, 1, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
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, 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, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 33, 1, 34, 1, 35,
+ 1, 35, 35, 35, 35, 35, 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, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 36, 1, 36, 36, 36, 36,
+ 36, 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, 36, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 37, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 1, 39, 39,
+ 39, 39, 39, 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, 32, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 39, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 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,
@@ -204,42 +211,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, 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, 41, 1, 39, 39, 39, 39,
+ 39, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 38, 1, 38, 38,
- 38, 38, 38, 1, 1, 1, 1, 1,
+ 1, 1, 1, 39, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 40,
+ 1, 1, 1, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 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, 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,
+ 41, 1, 43, 44, 1, 45, 1, 45,
+ 45, 45, 45, 45, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 45, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 46, 1, 46, 46, 46, 46, 46, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 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, 41, 1, 1,
+ 1, 46, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 47, 1,
+ 1, 48, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 1, 50, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 1, 52,
+ 52, 52, 52, 52, 1, 1, 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, 52, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 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, 1, 1, 1, 1, 1,
@@ -247,42 +256,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, 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,
- 47, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 54, 1, 52, 52, 52,
+ 52, 52, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 52, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 48, 1, 48, 48, 48, 48,
- 48, 1, 1, 1, 1, 1, 1, 1,
+ 53, 1, 1, 1, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 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, 1, 1, 1, 1,
+ 1, 54, 1, 55, 1, 55, 55, 55,
+ 55, 55, 1, 1, 1, 1, 1, 1,
1, 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, 56, 1,
+ 56, 56, 56, 56, 56, 1, 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, 1, 1, 56, 1, 54,
- 54, 54, 54, 54, 1, 1, 1, 1,
+ 1, 1, 1, 1, 57, 1, 1, 58,
+ 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 1, 60, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 1, 62, 62, 62,
+ 62, 62, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 54, 1,
+ 1, 1, 1, 1, 62, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 55, 1, 1, 1, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53,
+ 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, 1, 1, 1, 1, 1,
@@ -291,42 +301,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, 57, 1,
+ 1, 64, 1, 62, 62, 62, 62, 62,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 62, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 63, 1,
+ 1, 1, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 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, 1, 1, 64,
+ 1, 65, 1, 66, 1, 66, 66, 66,
+ 66, 66, 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, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 67, 1,
+ 67, 67, 67, 67, 67, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 67,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 68,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 1, 70, 70, 70, 70, 70, 1,
1, 1, 1, 1, 1, 1, 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, 70, 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, 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,
@@ -334,42 +344,50 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 72, 1,
+ 70, 70, 70, 70, 70, 1, 1, 1,
1, 1, 1, 1, 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, 70,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 68, 1,
+ 1, 1, 1, 71, 1, 1, 1, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
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, 72, 1, 74, 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, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 75, 1, 75, 75, 75, 75, 75,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 75, 1, 76, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 77, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 1, 80, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 81,
+ 79, 82, 82, 82, 82, 82, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 82, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 83, 1, 1, 1,
1, 1, 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,
@@ -376,33 +394,19 @@
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 84, 1, 79,
1, 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, 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, 79, 1, 85, 85, 85, 85, 85,
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, 85, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 86, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -412,36 +416,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, 1, 1, 1, 1, 1, 86,
- 1, 81, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 87,
+ 1, 85, 85, 85, 85, 85, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 85, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 86, 1, 1, 1,
+ 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 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, 81, 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, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 87, 1, 89,
+ 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, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 90, 1, 90, 90, 90, 90,
+ 90, 1, 1, 1, 1, 1, 1, 1,
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, 91, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 1, 85, 85,
+ 85, 85, 85, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 85, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 89, 1, 87, 87, 87, 87, 87,
+ 1, 86, 1, 1, 1, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 1,
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,
@@ -448,50 +459,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, 87, 1, 94, 94, 94, 94,
+ 94, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 89,
- 1, 91, 1, 91, 91, 91, 91, 91,
+ 1, 1, 1, 94, 1, 1, 1, 1,
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, 95, 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, 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, 1, 1, 96, 1,
+ 95, 95, 95, 95, 95, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 95,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 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, 96, 1, 23, 23, 23, 23,
+ 23, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 98, 1, 2, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 23, 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,
@@ -501,48 +502,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,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 3, 1,
- 1, 0
+ 1, 1, 1, 1, 1, 1, 96, 1,
+ 0
};
static const char _deserialize_json_trans_targs[] = {
- 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
+ 1, 0, 2, 3, 18, 24, 37, 43,
+ 51, 4, 12, 5, 6, 7, 8, 11,
+ 8, 11, 9, 1, 10, 9, 10, 57,
+ 13, 14, 15, 16, 17, 16, 17, 9,
+ 1, 10, 19, 20, 21, 22, 23, 9,
+ 1, 10, 23, 25, 31, 26, 27, 28,
+ 29, 30, 29, 30, 9, 1, 10, 32,
+ 33, 34, 35, 36, 35, 36, 9, 1,
+ 10, 38, 39, 40, 41, 42, 9, 1,
+ 10, 42, 44, 45, 46, 49, 50, 46,
+ 47, 48, 9, 1, 10, 9, 1, 10,
+ 50, 52, 53, 49, 54, 54, 55, 56,
+ 1
};
static const char _deserialize_json_trans_actions[] = {
- 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
+ 0, 0, 0, 0, 0, 1, 1, 1,
+ 0, 0, 2, 2, 2, 0, 0, 3,
+ 0, 0, 1, 1, 1, 0, 0, 4,
+ 4, 4, 0, 0, 0, 1, 1, 5,
+ 5, 5, 0, 0, 0, 0, 0, 1,
+ 1, 1, 0, 0, 6, 6, 6, 0,
+ 0, 1, 1, 1, 0, 0, 7, 7,
+ 7, 0, 0, 0, 1, 1, 8, 8,
+ 8, 0, 0, 0, 1, 9, 9, 0,
+ 10, 0, 11, 11, 11, 12, 12, 12,
+ 10, 0, 0, 13, 13, 14, 0, 0,
+ 15
};
-static const int deserialize_json_start = 1;
-static const int deserialize_json_first_final = 56;
+static const int deserialize_json_start = 55;
+static const int deserialize_json_first_final = 55;
static const int deserialize_json_error = 0;
-static const int deserialize_json_en_main = 1;
+static const int deserialize_json_en_main = 55;
#line 111 "hb-buffer-deserialize-json.rl"
@@ -595,7 +595,7 @@
goto _again;
switch ( _deserialize_json_trans_actions[_trans] ) {
- case 1:
+ case 15:
#line 38 "hb-buffer-deserialize-json.rl"
{
hb_memset (&info, 0, sizeof (info));
@@ -602,7 +602,7 @@
hb_memset (&pos , 0, sizeof (pos ));
}
break;
- case 5:
+ case 3:
#line 43 "hb-buffer-deserialize-json.rl"
{
buffer->add_info (info);
@@ -612,21 +612,21 @@
*end_ptr = p;
}
break;
- case 2:
+ case 1:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
}
break;
- case 17:
+ case 10:
#line 55 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 23:
+ case 14:
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 18:
+ case 11:
#line 58 "hb-buffer-deserialize-json.rl"
{
/* TODO Unescape \" and \\ if found. */
@@ -636,35 +636,35 @@
return false;
}
break;
- case 20:
+ case 12:
#line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
break;
- case 8:
+ case 5:
#line 67 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
break;
- case 10:
+ case 6:
#line 68 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
break;
- case 12:
+ case 7:
#line 69 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
break;
- case 3:
+ case 2:
#line 70 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
break;
- case 6:
+ case 4:
#line 71 "hb-buffer-deserialize-json.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
break;
- case 14:
+ case 8:
#line 72 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.mask )) return false; }
break;
- case 16:
+ case 9:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
@@ -672,7 +672,7 @@
#line 55 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 22:
+ case 13:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
@@ -680,109 +680,7 @@
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 19:
-#line 58 "hb-buffer-deserialize-json.rl"
- {
- /* TODO Unescape \" and \\ if found. */
- if (!hb_font_glyph_from_string (font,
- tok+1, p - tok - 2, /* Skip "" */
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 21:
-#line 66 "hb-buffer-deserialize-json.rl"
- { if (!parse_uint (tok, p, &info.codepoint)) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 9:
-#line 67 "hb-buffer-deserialize-json.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 11:
-#line 68 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.x_offset )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 13:
-#line 69 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 4:
-#line 70 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 7:
-#line 71 "hb-buffer-deserialize-json.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 15:
-#line 72 "hb-buffer-deserialize-json.rl"
- { if (!parse_uint (tok, p, &info.mask )) return false; }
-#line 43 "hb-buffer-deserialize-json.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
-#line 786 "hb-buffer-deserialize-json.hh"
+#line 684 "hb-buffer-deserialize-json.hh"
}
_again:
@@ -799,7 +697,7 @@
*end_ptr = p;
- return p == pe && *(p-1) != ']';
+ return p == pe;
}
#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-json.rl 2025-03-24 00:38:36 UTC (rev 74729)
@@ -101,12 +101,12 @@
| yadvance
| glyphflags;
item =
- ( '{' space* element (comma element)* space* '}')
+ ( '{' space* element (comma element)* space* '}' space* (','|']') space* )
>clear_item
@add_item
;
-main := space* '['? space* item (comma item)* space* (','|']')?;
+main := space* '['? space* item*;
}%%
@@ -133,7 +133,7 @@
*end_ptr = p;
- return p == pe && *(p-1) != ']';
+ return p == pe;
}
#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-glyphs.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-glyphs.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-glyphs.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -34,285 +34,247 @@
#line 36 "hb-buffer-deserialize-text-glyphs.hh"
static const unsigned char _deserialize_text_glyphs_trans_keys[] = {
- 0u, 0u, 48u, 57u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u,
- 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 9u, 124u, 9u, 124u, 0
+ 0u, 0u, 35u, 124u, 48u, 57u, 93u, 124u, 45u, 57u, 48u, 57u, 35u, 124u, 45u, 57u,
+ 48u, 57u, 35u, 124u, 35u, 124u, 35u, 124u, 48u, 57u, 35u, 124u, 45u, 57u, 48u, 57u,
+ 44u, 44u, 45u, 57u, 48u, 57u, 35u, 124u, 35u, 124u, 44u, 57u, 35u, 124u, 43u, 124u,
+ 48u, 124u, 35u, 124u, 35u, 124u, 35u, 124u, 0
};
static const char _deserialize_text_glyphs_key_spans[] = {
- 0, 10, 13, 10, 13, 10, 10, 13,
- 10, 1, 13, 10, 14, 82, 116, 116,
- 116, 116, 116, 116, 116, 116, 116, 116,
- 116, 116, 116
+ 0, 90, 10, 32, 13, 10, 90, 13,
+ 10, 90, 90, 90, 10, 90, 13, 10,
+ 1, 13, 10, 90, 90, 14, 90, 82,
+ 77, 90, 90, 90
};
static const short _deserialize_text_glyphs_index_offsets[] = {
- 0, 0, 11, 25, 36, 50, 61, 72,
- 86, 97, 99, 113, 124, 139, 222, 339,
- 456, 573, 690, 807, 924, 1041, 1158, 1275,
- 1392, 1509, 1626
+ 0, 0, 91, 102, 135, 149, 160, 251,
+ 265, 276, 367, 458, 549, 560, 651, 665,
+ 676, 678, 692, 703, 794, 885, 900, 991,
+ 1074, 1152, 1243, 1334
};
static const char _deserialize_text_glyphs_indicies[] = {
- 0, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 1, 3, 1, 1, 4,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 1, 6, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 1, 8, 1, 1,
- 9, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 1, 11, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 1, 13, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 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, 1, 21, 1, 1, 22,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 1, 24, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 1, 20, 1, 1,
- 1, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 1, 26, 26, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 26, 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, 1, 1, 26, 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,
- 1, 1, 1, 1, 1, 26, 1, 28,
- 28, 28, 28, 28, 27, 27, 27, 27,
+ 1, 0, 0, 0, 0, 0, 0,
+ 0, 2, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 5, 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, 6, 7, 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, 7, 0, 8, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 3, 10,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 10, 3,
+ 11, 3, 3, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 3, 14, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 3, 16, 3, 3, 3, 3, 3, 3,
+ 3, 3, 17, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 18, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 18, 3, 19, 3, 3, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 3, 22, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 3, 24, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 25,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 25, 3,
+ 24, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 25, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 25, 3, 16, 3, 3, 3, 3,
+ 3, 3, 3, 3, 17, 3, 3, 3,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 18, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 18, 3, 26, 27,
27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 28, 27,
- 27, 29, 27, 27, 27, 27, 27, 27,
- 27, 30, 1, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 31, 27, 27, 32, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 33, 1, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 28, 27, 34, 34, 34, 34,
- 34, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 34, 26, 26, 35, 26,
- 26, 26, 26, 26, 26, 26, 36, 1,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 37, 26, 26, 38, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 39,
- 1, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 40,
- 26, 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, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 42, 1, 43, 43,
- 43, 43, 43, 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, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 44, 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, 1, 1,
- 1, 1, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 42, 1,
- 46, 46, 46, 46, 46, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 46,
- 1, 1, 47, 1, 1, 1, 1, 1,
- 1, 1, 1, 48, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 49, 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, 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, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 52, 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, 51, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 52, 1, 46,
- 46, 46, 46, 46, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 46, 1,
- 1, 47, 1, 1, 1, 1, 1, 1,
- 1, 1, 48, 1, 1, 1, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 49, 1, 53, 53, 53, 53,
- 53, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 53, 1, 1, 54, 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, 56, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 57,
- 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, 59, 1, 1, 1, 1,
- 1, 1, 1, 60, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 61, 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,
- 59, 1, 1, 1, 1, 1, 1, 1,
- 60, 1, 1, 1, 1, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 61, 1, 53, 53, 53, 53, 53,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 53, 1, 1, 54, 1, 1,
- 1, 1, 1, 1, 1, 55, 1, 1,
- 1, 1, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 1, 1, 1, 1,
- 1, 1, 56, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 57, 1,
- 0
+ 3, 28, 3, 3, 3, 3, 3, 3,
+ 3, 29, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 30, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 31, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 31, 3, 32, 3, 3, 33,
+ 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 3, 35, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 3, 37, 3, 38,
+ 3, 3, 39, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 3, 41, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 3,
+ 43, 3, 3, 3, 3, 3, 3, 3,
+ 44, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 45, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 45, 3, 43, 3, 3, 3, 3,
+ 3, 3, 3, 44, 3, 3, 3, 3,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 45, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 45, 3, 37, 3,
+ 3, 3, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 3, 28, 3, 3,
+ 3, 3, 3, 3, 3, 29, 3, 3,
+ 3, 3, 46, 46, 46, 46, 46, 46,
+ 46, 46, 46, 46, 3, 3, 3, 3,
+ 3, 3, 30, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 31,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 31, 3,
+ 0, 0, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 0, 3, 3, 0, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 0, 0, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 0, 3, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 10, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 10,
+ 3, 49, 48, 48, 48, 48, 48, 48,
+ 48, 50, 3, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 51, 48, 48, 52, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 53, 54, 55, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 55, 48, 57, 56, 56, 56,
+ 56, 56, 56, 56, 58, 3, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 59, 56,
+ 56, 60, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 61, 62, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 62, 56, 63,
+ 48, 48, 48, 48, 48, 48, 48, 64,
+ 3, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 65, 48, 48, 66, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 54, 67, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 67, 48, 0
};
static const char _deserialize_text_glyphs_trans_targs[] = {
- 16, 0, 18, 3, 19, 22, 19, 22,
- 5, 20, 21, 20, 21, 23, 26, 8,
- 9, 12, 9, 12, 10, 11, 24, 25,
- 24, 25, 15, 15, 14, 1, 2, 6,
- 7, 13, 15, 1, 2, 6, 7, 13,
- 14, 17, 14, 17, 14, 18, 17, 1,
- 4, 14, 17, 1, 14, 17, 1, 2,
- 7, 14, 17, 1, 2, 14, 26
+ 1, 2, 4, 0, 12, 14, 23, 26,
+ 3, 24, 26, 5, 6, 11, 6, 11,
+ 2, 7, 26, 8, 9, 10, 9, 10,
+ 2, 26, 13, 22, 2, 4, 14, 26,
+ 15, 16, 21, 16, 21, 17, 18, 19,
+ 20, 19, 20, 2, 4, 26, 22, 24,
+ 1, 2, 4, 12, 14, 27, 23, 26,
+ 1, 2, 4, 12, 14, 23, 26, 2,
+ 4, 12, 14, 26
};
static const char _deserialize_text_glyphs_trans_actions[] = {
- 1, 0, 1, 1, 1, 1, 0, 0,
- 1, 1, 1, 0, 0, 1, 1, 1,
- 1, 1, 0, 0, 2, 1, 1, 1,
- 0, 0, 0, 4, 3, 5, 5, 5,
- 5, 4, 6, 7, 7, 7, 7, 0,
- 6, 8, 8, 0, 0, 0, 9, 10,
- 10, 9, 11, 12, 11, 13, 14, 14,
- 14, 13, 15, 16, 16, 15, 0
+ 0, 1, 1, 0, 1, 1, 0, 1,
+ 2, 2, 3, 2, 2, 2, 0, 0,
+ 4, 4, 4, 2, 2, 2, 0, 0,
+ 5, 5, 2, 2, 6, 6, 6, 6,
+ 2, 2, 2, 0, 0, 7, 2, 2,
+ 2, 0, 0, 8, 8, 8, 0, 0,
+ 9, 10, 10, 10, 10, 9, 9, 10,
+ 12, 13, 13, 13, 13, 12, 13, 14,
+ 14, 14, 14, 14
};
static const char _deserialize_text_glyphs_eof_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 3, 6,
- 8, 0, 8, 9, 11, 11, 9, 13,
- 15, 15, 13
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 11, 0
};
-static const int deserialize_text_glyphs_start = 14;
-static const int deserialize_text_glyphs_first_final = 14;
+static const int deserialize_text_glyphs_start = 25;
+static const int deserialize_text_glyphs_first_final = 25;
static const int deserialize_text_glyphs_error = 0;
-static const int deserialize_text_glyphs_en_main = 14;
+static const int deserialize_text_glyphs_en_main = 25;
-#line 98 "hb-buffer-deserialize-text-glyphs.rl"
+#line 99 "hb-buffer-deserialize-text-glyphs.rl"
static hb_bool_t
@@ -322,39 +284,22 @@
const char **end_ptr,
hb_font_t *font)
{
- const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
+ const char *p = buf, *pe = buf + buf_len, *eof = pe;
/* 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 *end = strchr ((char *) p, ']');
- if (end)
- pe = eof = end;
- else
- {
- end = strrchr ((char *) p, '|');
- if (end)
- pe = eof = end;
- else
- pe = eof = p;
- }
-
const char *tok = nullptr;
int cs;
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 353 "hb-buffer-deserialize-text-glyphs.hh"
+#line 298 "hb-buffer-deserialize-text-glyphs.hh"
{
cs = deserialize_text_glyphs_start;
}
-#line 358 "hb-buffer-deserialize-text-glyphs.hh"
+#line 303 "hb-buffer-deserialize-text-glyphs.hh"
{
int _slen;
int _trans;
@@ -379,13 +324,13 @@
goto _again;
switch ( _deserialize_text_glyphs_trans_actions[_trans] ) {
- case 1:
+ case 2:
#line 51 "hb-buffer-deserialize-text-glyphs.rl"
{
tok = p;
}
break;
- case 7:
+ case 1:
#line 55 "hb-buffer-deserialize-text-glyphs.rl"
{
/* TODO Unescape delimiters. */
@@ -395,27 +340,31 @@
return false;
}
break;
- case 14:
+ case 6:
#line 63 "hb-buffer-deserialize-text-glyphs.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
break;
- case 2:
+ case 7:
#line 64 "hb-buffer-deserialize-text-glyphs.rl"
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
break;
- case 16:
+ case 8:
#line 65 "hb-buffer-deserialize-text-glyphs.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
break;
- case 10:
+ case 4:
#line 66 "hb-buffer-deserialize-text-glyphs.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
break;
- case 12:
+ case 5:
#line 67 "hb-buffer-deserialize-text-glyphs.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
break;
- case 4:
+ case 3:
+#line 68 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+ break;
+ case 9:
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
{
hb_memset (&info, 0, sizeof (info));
@@ -426,7 +375,16 @@
tok = p;
}
break;
- case 6:
+ case 10:
+#line 38 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
+}
+#line 51 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
+}
#line 55 "hb-buffer-deserialize-text-glyphs.rl"
{
/* TODO Unescape delimiters. */
@@ -435,18 +393,8 @@
&info.codepoint))
return false;
}
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
break;
- case 13:
-#line 63 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
+ case 12:
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
{
buffer->add_info (info);
@@ -455,56 +403,6 @@
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
}
- break;
- case 15:
-#line 65 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 9:
-#line 66 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 11:
-#line 67 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 8:
-#line 68 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_uint (tok, p, &info.mask )) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 5:
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
{
hb_memset (&info, 0, sizeof (info));
@@ -514,6 +412,8 @@
{
tok = p;
}
+ break;
+ case 14:
#line 55 "hb-buffer-deserialize-text-glyphs.rl"
{
/* TODO Unescape delimiters. */
@@ -522,8 +422,6 @@
&info.codepoint))
return false;
}
- break;
- case 3:
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
{
hb_memset (&info, 0, sizeof (info));
@@ -533,56 +431,8 @@
{
tok = p;
}
-#line 55 "hb-buffer-deserialize-text-glyphs.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
break;
-#line 554 "hb-buffer-deserialize-text-glyphs.hh"
- }
-
-_again:
- if ( cs == 0 )
- goto _out;
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- switch ( _deserialize_text_glyphs_eof_actions[cs] ) {
- case 6:
-#line 55 "hb-buffer-deserialize-text-glyphs.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
case 13:
-#line 63 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
{
buffer->add_info (info);
@@ -591,56 +441,6 @@
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
}
- break;
- case 15:
-#line 65 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 9:
-#line 66 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 11:
-#line 67 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 8:
-#line 68 "hb-buffer-deserialize-text-glyphs.rl"
- { if (!parse_uint (tok, p, &info.mask )) return false; }
-#line 43 "hb-buffer-deserialize-text-glyphs.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 3:
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
{
hb_memset (&info, 0, sizeof (info));
@@ -658,6 +458,20 @@
&info.codepoint))
return false;
}
+ break;
+#line 463 "hb-buffer-deserialize-text-glyphs.hh"
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ switch ( _deserialize_text_glyphs_eof_actions[cs] ) {
+ case 11:
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
{
buffer->add_info (info);
@@ -667,7 +481,7 @@
*end_ptr = p;
}
break;
-#line 671 "hb-buffer-deserialize-text-glyphs.hh"
+#line 485 "hb-buffer-deserialize-text-glyphs.hh"
}
}
@@ -674,16 +488,9 @@
_out: {}
}
-#line 136 "hb-buffer-deserialize-text-glyphs.rl"
+#line 120 "hb-buffer-deserialize-text-glyphs.rl"
- if (pe < orig_pe && *pe == ']')
- {
- pe++;
- if (p == pe)
- p++;
- }
-
*end_ptr = p;
return p == pe;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-glyphs.rl
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-glyphs.rl 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-glyphs.rl 2025-03-24 00:38:36 UTC (rev 74729)
@@ -86,14 +86,15 @@
offsets?
advances?
glyphflags?
+ ( '|' | ']')
)
>clear_item
%add_item
;
-glyphs = glyph_item (space* '|' space* glyph_item)* space*;
+glyphs = '['? glyph_item* ;
-main := space* glyphs;
+main := glyphs;
}%%
@@ -104,28 +105,11 @@
const char **end_ptr,
hb_font_t *font)
{
- const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
+ const char *p = buf, *pe = buf + buf_len, *eof = pe;
/* 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 *end = strchr ((char *) p, ']');
- if (end)
- pe = eof = end;
- else
- {
- end = strrchr ((char *) p, '|');
- if (end)
- pe = eof = end;
- else
- pe = eof = p;
- }
-
const char *tok = nullptr;
int cs;
hb_glyph_info_t info = {0};
@@ -135,13 +119,6 @@
write exec;
}%%
- if (pe < orig_pe && *pe == ']')
- {
- pe++;
- if (p == pe)
- p++;
- }
-
*end_ptr = p;
return p == pe;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -34,135 +34,106 @@
#line 36 "hb-buffer-deserialize-text-unicode.hh"
static const unsigned char _deserialize_text_unicode_trans_keys[] = {
- 0u, 0u, 9u, 117u, 43u, 102u, 48u, 102u, 48u, 57u, 9u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 0
+ 0u, 0u, 43u, 102u, 48u, 102u, 48u, 124u, 48u, 57u, 62u, 124u, 48u, 124u, 60u, 117u,
+ 85u, 117u, 85u, 117u, 0
};
static const char _deserialize_text_unicode_key_spans[] = {
- 0, 109, 60, 55, 10, 116, 116, 116,
- 116
+ 0, 60, 55, 77, 10, 63, 77, 58,
+ 33, 33
};
static const short _deserialize_text_unicode_index_offsets[] = {
- 0, 0, 110, 171, 227, 238, 355, 472,
- 589
+ 0, 0, 61, 117, 195, 206, 270, 348,
+ 407, 441
};
static const char _deserialize_text_unicode_indicies[] = {
- 0, 0, 0, 0, 0, 1, 1,
+ 0, 1, 1, 1, 1, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 1, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 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, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 1, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 1, 1, 1, 4, 5, 1, 1, 3,
+ 3, 3, 3, 3, 3, 1, 1, 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,
+ 3, 3, 3, 3, 3, 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, 5, 1, 6, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 1, 8,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 2, 1, 3,
- 1, 1, 1, 1, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 1, 1,
- 1, 1, 1, 1, 1, 4, 4, 4,
- 4, 4, 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, 4, 4, 4,
- 4, 4, 4, 1, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 1, 1,
- 1, 1, 1, 1, 1, 4, 4, 4,
- 4, 4, 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, 4, 4, 4,
- 4, 4, 4, 1, 5, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 1, 7,
- 7, 7, 7, 7, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 7, 1,
+ 1, 1, 1, 1, 1, 8, 1, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 1, 1, 1, 1, 8, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 1, 1, 1, 9, 1, 1, 1, 8,
- 8, 8, 8, 8, 8, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 8,
- 8, 8, 8, 8, 8, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 10, 1, 11, 11, 11, 11,
- 11, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 11, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 8, 1, 10, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 11, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 11, 1,
+ 11, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 11, 1, 12, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0,
- 1, 12, 12, 12, 12, 12, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 12, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 13, 1, 12, 12,
- 12, 12, 12, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 12, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 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,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 13, 1, 0
+ 1, 1, 12, 1, 0
};
static const char _deserialize_text_unicode_trans_targs[] = {
- 1, 0, 2, 3, 5, 7, 8, 6,
- 5, 4, 1, 6, 6, 1, 8
+ 2, 0, 3, 3, 4, 9, 5, 6,
+ 9, 6, 8, 1, 1
};
static const char _deserialize_text_unicode_trans_actions[] = {
- 0, 0, 1, 0, 2, 2, 2, 3,
- 0, 4, 3, 0, 5, 5, 0
+ 0, 0, 1, 0, 2, 2, 1, 1,
+ 3, 0, 0, 4, 6
};
static const char _deserialize_text_unicode_eof_actions[] = {
- 0, 0, 0, 0, 0, 3, 0, 5,
- 5
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 5
};
-static const int deserialize_text_unicode_start = 1;
-static const int deserialize_text_unicode_first_final = 5;
+static const int deserialize_text_unicode_start = 7;
+static const int deserialize_text_unicode_first_final = 7;
static const int deserialize_text_unicode_error = 0;
-static const int deserialize_text_unicode_en_main = 1;
+static const int deserialize_text_unicode_en_main = 7;
-#line 79 "hb-buffer-deserialize-text-unicode.rl"
+#line 80 "hb-buffer-deserialize-text-unicode.rl"
static hb_bool_t
@@ -172,37 +143,19 @@
const char **end_ptr,
hb_font_t *font)
{
- const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
+ const char *p = buf, *pe = buf + buf_len, *eof = pe;
- while (p < pe && ISSPACE (*p))
- p++;
- if (p < pe && *p == (buffer->len ? '|' : '<'))
- *end_ptr = ++p;
-
- const char *end = strchr ((char *) p, '>');
- if (end)
- pe = eof = end;
- else
- {
- end = strrchr ((char *) p, '|');
- if (end)
- pe = eof = end;
- else
- pe = eof = p;
- }
-
-
const char *tok = nullptr;
int cs;
hb_glyph_info_t info = {0};
const hb_glyph_position_t pos = {0};
-#line 201 "hb-buffer-deserialize-text-unicode.hh"
+#line 154 "hb-buffer-deserialize-text-unicode.hh"
{
cs = deserialize_text_unicode_start;
}
-#line 206 "hb-buffer-deserialize-text-unicode.hh"
+#line 159 "hb-buffer-deserialize-text-unicode.hh"
{
int _slen;
int _trans;
@@ -227,38 +180,27 @@
goto _again;
switch ( _deserialize_text_unicode_trans_actions[_trans] ) {
- case 1:
+ case 4:
#line 38 "hb-buffer-deserialize-text-unicode.rl"
{
hb_memset (&info, 0, sizeof (info));
}
break;
- case 2:
+ case 1:
#line 51 "hb-buffer-deserialize-text-unicode.rl"
{
tok = p;
}
break;
- case 4:
+ case 2:
#line 55 "hb-buffer-deserialize-text-unicode.rl"
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
break;
case 3:
-#line 55 "hb-buffer-deserialize-text-unicode.rl"
- {if (!parse_hex (tok, p, &info.codepoint )) return false; }
-#line 42 "hb-buffer-deserialize-text-unicode.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- if (buffer->have_positions)
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 5:
#line 57 "hb-buffer-deserialize-text-unicode.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
+ break;
+ case 6:
#line 42 "hb-buffer-deserialize-text-unicode.rl"
{
buffer->add_info (info);
@@ -268,8 +210,12 @@
buffer->pos[buffer->len - 1] = pos;
*end_ptr = p;
}
+#line 38 "hb-buffer-deserialize-text-unicode.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+}
break;
-#line 273 "hb-buffer-deserialize-text-unicode.hh"
+#line 219 "hb-buffer-deserialize-text-unicode.hh"
}
_again:
@@ -281,22 +227,7 @@
if ( p == eof )
{
switch ( _deserialize_text_unicode_eof_actions[cs] ) {
- case 3:
-#line 55 "hb-buffer-deserialize-text-unicode.rl"
- {if (!parse_hex (tok, p, &info.codepoint )) return false; }
-#line 42 "hb-buffer-deserialize-text-unicode.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- if (buffer->have_positions)
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
case 5:
-#line 57 "hb-buffer-deserialize-text-unicode.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
#line 42 "hb-buffer-deserialize-text-unicode.rl"
{
buffer->add_info (info);
@@ -307,7 +238,7 @@
*end_ptr = p;
}
break;
-#line 311 "hb-buffer-deserialize-text-unicode.hh"
+#line 242 "hb-buffer-deserialize-text-unicode.hh"
}
}
@@ -314,16 +245,9 @@
_out: {}
}
-#line 115 "hb-buffer-deserialize-text-unicode.rl"
+#line 98 "hb-buffer-deserialize-text-unicode.rl"
- if (pe < orig_pe && *pe == '>')
- {
- pe++;
- if (p == pe)
- p++;
- }
-
*end_ptr = p;
return p == pe;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.rl
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.rl 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-deserialize-text-unicode.rl 2025-03-24 00:38:36 UTC (rev 74729)
@@ -67,14 +67,15 @@
(
unicode
cluster?
+ ('|' | '>')
)
>clear_item
%add_item
;
-unicodes = unicode_item (space* '|' space* unicode_item)* space*;
+unicodes = '<'? unicode_item*;
-main := space* unicodes;
+main := unicodes;
}%%
@@ -85,26 +86,8 @@
const char **end_ptr,
hb_font_t *font)
{
- const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
+ const char *p = buf, *pe = buf + buf_len, *eof = pe;
- while (p < pe && ISSPACE (*p))
- p++;
- if (p < pe && *p == (buffer->len ? '|' : '<'))
- *end_ptr = ++p;
-
- const char *end = strchr ((char *) p, '>');
- if (end)
- pe = eof = end;
- else
- {
- end = strrchr ((char *) p, '|');
- if (end)
- pe = eof = end;
- else
- pe = eof = p;
- }
-
-
const char *tok = nullptr;
int cs;
hb_glyph_info_t info = {0};
@@ -114,13 +97,6 @@
write exec;
}%%
- if (pe < orig_pe && *pe == '>')
- {
- pe++;
- if (p == pe)
- p++;
- }
-
*end_ptr = p;
return p == pe;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-serialize.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-serialize.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-serialize.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -169,11 +169,13 @@
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
{
hb_glyph_extents_t extents;
- hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
- p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
- extents.x_bearing, extents.y_bearing));
- p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
- extents.width, extents.height));
+ if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents))
+ {
+ p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
+ extents.x_bearing, extents.y_bearing));
+ p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
+ extents.width, extents.height));
+ }
}
*p++ = '}';
@@ -318,8 +320,8 @@
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
{
hb_glyph_extents_t extents;
- hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
- p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
+ if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents))
+ p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
}
if (i == end-1) {
@@ -737,8 +739,7 @@
* Deserializes glyphs @buffer from textual representation in the format
* produced by hb_buffer_serialize_glyphs().
*
- * Return value: `true` if parse was successful, `false` if an error
- * occurred.
+ * Return value: `true` if the full string was parsed, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -810,8 +811,7 @@
* Deserializes Unicode @buffer from textual representation in the format
* produced by hb_buffer_serialize_unicode().
*
- * Return value: `true` if parse was successful, `false` if an error
- * occurred.
+ * Return value: `true` if the full string was parsed, `false` otherwise.
*
* Since: 2.7.3
**/
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -63,24 +63,25 @@
buffer_verify_monotone (hb_buffer_t *buffer,
hb_font_t *font)
{
- /* Check that clusters are monotone. */
- if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
- buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
{
- bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+ /* Cannot perform this check without monotone clusters. */
+ return true;
+ }
- unsigned int num_glyphs;
- hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+ bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
- for (unsigned int i = 1; i < num_glyphs; i++)
- if (info[i-1].cluster != info[i].cluster &&
- (info[i-1].cluster < info[i].cluster) != is_forward)
- {
- buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone.");
- return false;
- }
- }
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+ for (unsigned int i = 1; i < num_glyphs; i++)
+ if (info[i-1].cluster != info[i].cluster &&
+ (info[i-1].cluster < info[i].cluster) != is_forward)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone.");
+ return false;
+ }
+
return true;
}
@@ -92,8 +93,7 @@
unsigned int num_features,
const char * const *shapers)
{
- if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
- buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
{
/* Cannot perform this check without monotone clusters. */
return true;
@@ -207,8 +207,7 @@
unsigned int num_features,
const char * const *shapers)
{
- if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
- buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
{
/* Cannot perform this check without monotone clusters. */
return true;
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -518,7 +518,7 @@
hb_buffer_t::merge_clusters_impl (unsigned int start,
unsigned int end)
{
- if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level))
{
unsafe_to_break (start, end);
return;
@@ -551,7 +551,7 @@
hb_buffer_t::merge_out_clusters (unsigned int start,
unsigned int end)
{
- if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
+ if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level))
return;
if (unlikely (end - start < 2))
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -422,19 +422,35 @@
* @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values.
* @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level,
* equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES.
- *
+ * @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES: Only group clusters, but don't enforce monotone order.
+ *
* Data type for holding HarfBuzz's clustering behavior options. The cluster level
- * dictates one aspect of how HarfBuzz will treat non-base characters
+ * dictates one aspect of how HarfBuzz will treat non-base characters
* during shaping.
*
* In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES, non-base
* characters are merged into the cluster of the base character that precedes them.
+ * There is also cluster merging every time the clusters will otherwise become non-monotone.
*
* In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS, non-base characters are initially
* assigned their own cluster values, which are not merged into preceding base
* clusters. This allows HarfBuzz to perform additional operations like reorder
- * sequences of adjacent marks.
+ * sequences of adjacent marks. The output is still monotone, but the cluster
+ * values are more granular.
*
+ * In @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS, non-base characters are assigned their
+ * own cluster values, which are not merged into preceding base clusters. Moreover,
+ * the cluster values are not merged into monotone order. This is the most granular
+ * cluster level, and it is useful for clients that need to know the exact cluster
+ * values of each character, but is harder to use for clients, since clusters
+ * might appear in any order.
+ *
+ * In @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES, non-base characters are merged into the
+ * cluster of the base character that precedes them. This is similar to the Unicode
+ * Grapheme Cluster algorithm, but it is not exactly the same. The output is
+ * not forced to be monotone. This is useful for clients that want to use HarfBuzz
+ * as a cheap implementation of the Unicode Grapheme Cluster algorithm.
+ *
* @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES is the default, because it maintains
* backward compatibility with older versions of HarfBuzz. New client programs that
* do not need to maintain such backward compatibility are recommended to use
@@ -446,9 +462,52 @@
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0,
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1,
HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2,
+ HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES = 3,
HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
} hb_buffer_cluster_level_t;
+/**
+ * HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE:
+ * @level: #hb_buffer_cluster_level_t to test
+ *
+ * Tests whether a cluster level groups cluster values into monotone order.
+ * Requires that the level be valid.
+ *
+ * Since: 11.0.0
+ */
+#define HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE(level) \
+ ((bool) ((1u << (unsigned) (level)) & \
+ ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \
+ (1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS))))
+
+/**
+ * HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES:
+ * @level: #hb_buffer_cluster_level_t to test
+ *
+ * Tests whether a cluster level groups cluster values by graphemes. Requires
+ * that the level be valid.
+ *
+ * Since: 11.0.0
+ */
+#define HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES(level) \
+ ((bool) ((1u << (unsigned) (level)) & \
+ ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \
+ (1u << HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES))))
+
+/**
+ * HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS
+ * @level: #hb_buffer_cluster_level_t to test
+ *
+ * Tests whether a cluster level does not group cluster values by graphemes.
+ * Requires that the level be valid.
+ *
+ * Since: 11.0.0
+ */
+#define HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS(level) \
+ ((bool) ((1u << (unsigned) (level)) & \
+ ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARCATERS) | \
+ (1u << HB_BUFFER_CLUSTER_LEVEL_CHARACTERS))))
+
HB_EXTERN void
hb_buffer_set_cluster_level (hb_buffer_t *buffer,
hb_buffer_cluster_level_t cluster_level);
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -52,11 +52,11 @@
{
using item_t = typename std::conditional<thread_safe,
typename std::conditional<key_bits + value_bits - cache_bits <= 16,
- hb_atomic_short_t,
- hb_atomic_int_t>::type,
+ hb_atomic_t<unsigned short>,
+ hb_atomic_t<unsigned int>>::type,
typename std::conditional<key_bits + value_bits - cache_bits <= 16,
- short,
- int>::type
+ unsigned short,
+ unsigned int>::type
>::type;
static_assert ((key_bits >= cache_bits), "");
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -726,6 +726,9 @@
float span;
span = angles[n_stops - 1] - angles[0];
+ if (!span)
+ goto done;
+
k = 0;
if (angles[0] >= 0)
{
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -71,7 +71,8 @@
template <typename ACC>
cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
const int *coords_=nullptr, unsigned int num_coords_=0)
- : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
+ : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs),
+ cached_scalars_vector (&acc.cached_scalars_vector)
{
coords = coords_;
num_coords = num_coords_;
@@ -80,11 +81,41 @@
set_ivs (acc.privateDicts[fd].ivs);
}
- void fini ()
+ ~cff2_cs_interp_env_t ()
{
- SUPER::fini ();
+ release_scalars_vector (scalars);
}
+ hb_vector_t<float> *acquire_scalars_vector () const
+ {
+ hb_vector_t<float> *scalars = cached_scalars_vector->get_acquire ();
+
+ if (!scalars || !cached_scalars_vector->cmpexch (scalars, nullptr))
+ {
+ scalars = (hb_vector_t<float> *) hb_calloc (1, sizeof (hb_vector_t<float>));
+ if (unlikely (!scalars))
+ return nullptr;
+ scalars->init ();
+ }
+
+ return scalars;
+ }
+
+ void release_scalars_vector (hb_vector_t<float> *scalars) const
+ {
+ if (!scalars)
+ return;
+
+ scalars->clear ();
+
+ if (!cached_scalars_vector->cmpexch (nullptr, scalars))
+ {
+ scalars->fini ();
+ hb_free (scalars);
+ }
+ scalars = nullptr;
+ }
+
op_code_t fetch_op ()
{
if (this->str_ref.avail ())
@@ -111,14 +142,20 @@
{
if (!seen_blend)
{
- region_count = varStore->varStore.get_region_index_count (get_ivs ());
- if (do_blend)
+ scalars = acquire_scalars_vector ();
+ if (unlikely (!scalars))
+ SUPER::set_error ();
+ else
{
- if (unlikely (!scalars.resize_exact (region_count)))
- SUPER::set_error ();
- else
- varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
- &scalars[0], region_count);
+ region_count = varStore->varStore.get_region_index_count (get_ivs ());
+ if (do_blend)
+ {
+ if (unlikely (!scalars->resize_exact (region_count)))
+ SUPER::set_error ();
+ else
+ varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
+ &(*scalars)[0], region_count);
+ }
}
seen_blend = true;
}
@@ -149,11 +186,11 @@
double v = 0;
if (do_blend)
{
- if (likely (scalars.length == deltas.length))
+ if (likely (scalars && scalars->length == deltas.length))
{
- unsigned count = scalars.length;
+ unsigned count = scalars->length;
for (unsigned i = 0; i < count; i++)
- v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
+ v += (double) scalars->arrayZ[i] * deltas.arrayZ[i].to_real ();
}
}
return v;
@@ -167,7 +204,8 @@
const CFF2ItemVariationStore *varStore;
unsigned int region_count;
unsigned int ivs;
- hb_vector_t<float> scalars;
+ hb_vector_t<float> *scalars = nullptr;
+ hb_atomic_t<hb_vector_t<float> *> *cached_scalars_vector = nullptr;
bool do_blend;
bool seen_vsindex_ = false;
bool seen_blend = false;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -42,7 +42,7 @@
/* hb_options_t */
-hb_atomic_int_t _hb_options;
+hb_atomic_t<unsigned> _hb_options;
void
_hb_options_init ()
@@ -273,7 +273,7 @@
/* Thread-safe lockfree language list */
-static hb_atomic_ptr_t <hb_language_item_t> langs;
+static hb_atomic_t<hb_language_item_t *> langs;
static inline void
free_langs ()
@@ -403,7 +403,7 @@
hb_language_t
hb_language_get_default ()
{
- static hb_atomic_ptr_t <hb_language_t> default_language;
+ static hb_atomic_t<hb_language_t> default_language;
hb_language_t language = default_language;
if (unlikely (language == HB_LANGUAGE_INVALID))
@@ -968,6 +968,9 @@
* understood by hb_feature_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
+ * Note that the feature value will be omitted if it is '1', but the
+ * string won't include any whitespace.
+ *
* Since: 0.9.5
**/
void
@@ -1121,6 +1124,8 @@
* understood by hb_variation_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
+ * Note that the string won't include any whitespace.
+ *
* Since: 1.4.2
*/
void
@@ -1212,7 +1217,59 @@
return hb_color_get_blue (color);
}
+/**
+ * hb_malloc:
+ * @size: The size of the memory to allocate.
+ *
+ * Allocates @size bytes of memory, using the allocator set at
+ * compile-time. Typically just malloc().
+ *
+ * Return value: A pointer to the allocated memory.
+ *
+ * Since: 11.0.0
+ **/
+void* hb_malloc(size_t size) { return hb_malloc_impl (size); }
+/**
+ * hb_calloc:
+ * @nmemb: The number of elements to allocate.
+ * @size: The size of each element.
+ *
+ * Allocates @nmemb elements of @size bytes each, initialized to zero,
+ * using the allocator set at compile-time. Typically just calloc().
+ *
+ * Return value: A pointer to the allocated memory.
+ *
+ * Since: 11.0.0
+ **/
+void* hb_calloc(size_t nmemb, size_t size) { return hb_calloc_impl (nmemb, size); }
+
+/**
+ * hb_realloc:
+ * @ptr: The pointer to the memory to reallocate.
+ * @size: The new size of the memory.
+ *
+ * Reallocates the memory pointed to by @ptr to @size bytes, using the
+ * allocator set at compile-time. Typically just realloc().
+ *
+ * Return value: A pointer to the reallocated memory.
+ *
+ * Since: 11.0.0
+ **/
+void* hb_realloc(void *ptr, size_t size) { return hb_realloc_impl (ptr, size); }
+
+/**
+ * hb_free:
+ * @ptr: The pointer to the memory to free.
+ *
+ * Frees the memory pointed to by @ptr, using the allocator set at
+ * compile-time. Typically just free().
+ *
+ * Since: 11.0.0
+ **/
+void hb_free(void *ptr) { hb_free_impl (ptr); }
+
+
/* If there is no visibility control, then hb-static.cc will NOT
* define anything. Instead, we get it to define one set in here
* only, so only libharfbuzz.so defines them, not other libs. */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -65,6 +65,7 @@
#else
# include <inttypes.h>
#endif
+#include <stddef.h>
#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define HB_DEPRECATED __attribute__((__deprecated__))
@@ -948,6 +949,16 @@
*/
typedef struct hb_font_t hb_font_t;
+/* Not of much use to clients. */
+HB_EXTERN void*
+hb_malloc (size_t size);
+HB_EXTERN void*
+hb_calloc (size_t nmemb, size_t size);
+HB_EXTERN void*
+hb_realloc (void *ptr, size_t size);
+HB_EXTERN void
+hb_free (void *ptr);
+
HB_END_DECLS
#endif /* HB_COMMON_H */
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-font.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -28,7 +28,7 @@
#ifdef HAVE_CORETEXT
-#include "hb-coretext.h"
+#include "hb-coretext.hh"
#include "hb-draw.hh"
#include "hb-font.hh"
@@ -42,24 +42,17 @@
# define kCTFontOrientationVertical kCTFontVerticalOrientation
#endif
-#define MAX_GLYPHS 64u
+#define MAX_GLYPHS 256u
-static void
-_hb_coretext_font_destroy (void *font_data)
-{
- CTFontRef ct_font = (CTFontRef) font_data;
-
- CFRelease (ct_font);
-}
-
static hb_bool_t
-hb_coretext_get_nominal_glyph (hb_font_t *font HB_UNUSED,
- void *font_data,
+hb_coretext_get_nominal_glyph (hb_font_t *font,
+ void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- CTFontRef ct_font = (CTFontRef) font_data;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
+
UniChar ch[2];
CGGlyph cg_glyph[2];
unsigned count = 0;
@@ -85,7 +78,7 @@
}
static unsigned int
-hb_coretext_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
+hb_coretext_get_nominal_glyphs (hb_font_t *font,
void *font_data,
unsigned int count,
const hb_codepoint_t *first_unicode,
@@ -94,6 +87,8 @@
unsigned int glyph_stride,
void *user_data HB_UNUSED)
{
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
+
// If any non-BMP codepoint is requested, use the slow path.
bool slow_path = false;
auto *unicode = first_unicode;
@@ -119,8 +114,6 @@
return count;
}
- CTFontRef ct_font = (CTFontRef) font_data;
-
UniChar ch[MAX_GLYPHS];
CGGlyph cg_glyph[MAX_GLYPHS];
for (unsigned i = 0; i < count; i += MAX_GLYPHS)
@@ -152,14 +145,14 @@
}
static hb_bool_t
-hb_coretext_get_variation_glyph (hb_font_t *font HB_UNUSED,
- void *font_data,
+hb_coretext_get_variation_glyph (hb_font_t *font,
+ void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- CTFontRef ct_font = (CTFontRef) font_data;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
UniChar ch[4];
CGGlyph cg_glyph[4];
@@ -194,12 +187,17 @@
if (cg_glyph[i])
return false;
+ // Humm. CoreText falls back to the default glyph if the variation selector
+ // is not supported. We cannot truly detect that case. So, in essence,
+ // we are always returning true here...
+
*glyph = cg_glyph[0];
return true;
}
static void
-hb_coretext_get_glyph_h_advances (hb_font_t* font, void* font_data,
+hb_coretext_get_glyph_h_advances (hb_font_t* font,
+ void* font_data HB_UNUSED,
unsigned count,
const hb_codepoint_t *first_glyph,
unsigned glyph_stride,
@@ -207,7 +205,7 @@
unsigned advance_stride,
void *user_data HB_UNUSED)
{
- CTFontRef ct_font = (CTFontRef) font_data;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
@@ -233,7 +231,8 @@
#ifndef HB_NO_VERTICAL
static void
-hb_coretext_get_glyph_v_advances (hb_font_t* font, void* font_data,
+hb_coretext_get_glyph_v_advances (hb_font_t* font,
+ void* font_data HB_UNUSED,
unsigned count,
const hb_codepoint_t *first_glyph,
unsigned glyph_stride,
@@ -241,7 +240,7 @@
unsigned advance_stride,
void *user_data HB_UNUSED)
{
- CTFontRef ct_font = (CTFontRef) font_data;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat y_mult = (CGFloat) -font->y_scale / ct_font_size;
@@ -264,18 +263,16 @@
}
}
}
-#endif
-#ifndef HB_NO_VERTICAL
static hb_bool_t
hb_coretext_get_glyph_v_origin (hb_font_t *font,
- void *font_data,
+ void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
{
- CTFontRef ct_font = (CTFontRef) font_data;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat x_mult = (CGFloat) -font->x_scale / ct_font_size;
@@ -294,12 +291,12 @@
static hb_bool_t
hb_coretext_get_glyph_extents (hb_font_t *font,
- void *font_data,
+ void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
- CTFontRef ct_font = (CTFontRef) font_data;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
@@ -310,9 +307,9 @@
kCTFontOrientationDefault, glyphs, NULL, 1);
extents->x_bearing = round (bounds.origin.x * x_mult);
- extents->y_bearing = round (bounds.origin.y * y_mult);
+ extents->y_bearing = round ((bounds.origin.y + bounds.size.height) * y_mult);
extents->width = round (bounds.size.width * x_mult);
- extents->height = round (bounds.size.height * y_mult);
+ extents->height = round (bounds.origin.y * y_mult) - extents->y_bearing;
return true;
}
@@ -319,11 +316,12 @@
static hb_bool_t
hb_coretext_get_font_h_extents (hb_font_t *font,
- void *font_data,
+ void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
- CTFontRef ct_font = (CTFontRef) font_data;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
+
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
@@ -371,7 +369,7 @@
hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data)
{
- CTFontRef ct_font = (CTFontRef) font_data;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
@@ -415,17 +413,20 @@
(UInt8 *) name, size, &len);
name[len] = '\0';
+
+ CFRelease (cf_name);
+
return true;
}
static hb_bool_t
-hb_coretext_get_glyph_from_name (hb_font_t *font HB_UNUSED,
- void *font_data,
+hb_coretext_get_glyph_from_name (hb_font_t *font,
+ void *font_data HB_UNUSED,
const char *name, int len,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- CTFontRef ct_font = (CTFontRef) font_data;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
if (len == -1)
len = strlen (name);
@@ -458,10 +459,8 @@
hb_font_funcs_set_font_h_extents_func (funcs, hb_coretext_get_font_h_extents, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_coretext_get_glyph_h_advances, nullptr, nullptr);
- //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_coretext_get_glyph_h_origin, nullptr, nullptr);
#ifndef HB_NO_VERTICAL
- //hb_font_funcs_set_font_v_extents_func (funcs, hb_coretext_get_font_v_extents, nullptr, nullptr);
hb_font_funcs_set_glyph_v_advances_func (funcs, hb_coretext_get_glyph_v_advances, nullptr, nullptr);
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_coretext_get_glyph_v_origin, nullptr, nullptr);
#endif
@@ -530,8 +529,7 @@
hb_font_set_funcs (font,
_hb_coretext_get_font_funcs (),
- (void *) CFRetain (ct_font),
- _hb_coretext_font_destroy);
+ nullptr, nullptr);
}
#undef MAX_GLYPHS
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext-shape.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -32,279 +32,9 @@
#include "hb-shaper-impl.hh"
-#include "hb-coretext.h"
+#include "hb-coretext.hh"
#include "hb-aat-layout.hh"
-
-/**
- * SECTION:hb-coretext
- * @title: hb-coretext
- * @short_description: CoreText integration
- * @include: hb-coretext.h
- *
- * Functions for using HarfBuzz with the CoreText fonts.
- **/
-
-static CTFontRef create_ct_font (CGFontRef cg_font, CGFloat font_size);
-
-static void
-release_table_data (void *user_data)
-{
- CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
- CFRelease(cf_data);
-}
-
-static hb_blob_t *
-_hb_cg_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
-{
- CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
- CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
- if (unlikely (!cf_data))
- return nullptr;
-
- const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
- const size_t length = CFDataGetLength (cf_data);
- if (!data || !length)
- {
- CFRelease (cf_data);
- return nullptr;
- }
-
- return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
- reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
- release_table_data);
-}
-
-static unsigned
-_hb_cg_get_table_tags (const hb_face_t *face HB_UNUSED,
- unsigned int start_offset,
- unsigned int *table_count,
- hb_tag_t *table_tags,
- void *user_data)
-{
- CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
-
- CTFontRef ct_font = create_ct_font (cg_font, (CGFloat) HB_CORETEXT_DEFAULT_FONT_SIZE);
-
- auto arr = CTFontCopyAvailableTables (ct_font, kCTFontTableOptionNoOptions);
-
- unsigned population = (unsigned) CFArrayGetCount (arr);
- unsigned end_offset;
-
- if (!table_count)
- goto done;
-
- if (unlikely (start_offset >= population))
- {
- *table_count = 0;
- goto done;
- }
-
- end_offset = start_offset + *table_count;
- if (unlikely (end_offset < start_offset))
- {
- *table_count = 0;
- goto done;
- }
- end_offset= hb_min (end_offset, (unsigned) population);
-
- *table_count = end_offset - start_offset;
- for (unsigned i = start_offset; i < end_offset; i++)
- {
- CTFontTableTag tag = (CTFontTableTag)(uintptr_t) CFArrayGetValueAtIndex (arr, i);
- table_tags[i - start_offset] = tag;
- }
-
-done:
- CFRelease (arr);
- CFRelease (ct_font);
- return population;
-}
-
-static void
-_hb_cg_font_release (void *data)
-{
- CGFontRelease ((CGFontRef) data);
-}
-
-
-static CTFontDescriptorRef
-get_last_resort_font_desc ()
-{
- // TODO Handle allocation failures?
- CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
- CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
- (const void **) &last_resort,
- 1,
- &kCFTypeArrayCallBacks);
- CFRelease (last_resort);
- CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault,
- (const void **) &kCTFontCascadeListAttribute,
- (const void **) &cascade_list,
- 1,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFRelease (cascade_list);
-
- CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
- CFRelease (attributes);
- return font_desc;
-}
-
-static void
-release_data (void *info, const void *data, size_t size)
-{
- assert (hb_blob_get_length ((hb_blob_t *) info) == size &&
- hb_blob_get_data ((hb_blob_t *) info, nullptr) == data);
-
- hb_blob_destroy ((hb_blob_t *) info);
-}
-
-static CGFontRef
-create_cg_font (hb_face_t *face)
-{
- CGFontRef cg_font = nullptr;
- if (face->destroy == _hb_cg_font_release)
- {
- cg_font = CGFontRetain ((CGFontRef) face->user_data);
- }
- else
- {
- hb_blob_t *blob = hb_face_reference_blob (face);
- unsigned int blob_length;
- const char *blob_data = hb_blob_get_data (blob, &blob_length);
- if (unlikely (!blob_length))
- DEBUG_MSG (CORETEXT, face, "Face has empty blob");
-
- CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
- if (likely (provider))
- {
- cg_font = CGFontCreateWithDataProvider (provider);
- if (unlikely (!cg_font))
- DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
- CGDataProviderRelease (provider);
- }
- }
- return cg_font;
-}
-
-static CTFontRef
-create_ct_font (CGFontRef cg_font, CGFloat font_size)
-{
- CTFontRef ct_font = nullptr;
-
- /* CoreText does not enable trak table usage / tracking when creating a CTFont
- * using CTFontCreateWithGraphicsFont. The only way of enabling tracking seems
- * to be through the CTFontCreateUIFontForLanguage call. */
- CFStringRef cg_postscript_name = CGFontCopyPostScriptName (cg_font);
- if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) ||
- CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay")))
- {
-#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1080
-# define kCTFontUIFontSystem kCTFontSystemFontType
-# define kCTFontUIFontEmphasizedSystem kCTFontEmphasizedSystemFontType
-#endif
- CTFontUIFontType font_type = kCTFontUIFontSystem;
- if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold")))
- font_type = kCTFontUIFontEmphasizedSystem;
-
- ct_font = CTFontCreateUIFontForLanguage (font_type, font_size, nullptr);
- CFStringRef ct_result_name = CTFontCopyPostScriptName(ct_font);
- if (CFStringCompare (ct_result_name, cg_postscript_name, 0) != kCFCompareEqualTo)
- {
- CFRelease(ct_font);
- ct_font = nullptr;
- }
- CFRelease (ct_result_name);
- }
- CFRelease (cg_postscript_name);
-
- if (!ct_font)
- ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, nullptr, nullptr);
-
- if (unlikely (!ct_font)) {
- DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
- return nullptr;
- }
-
- /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
- * bug indicate that the cascade list reconfiguration occasionally causes
- * crashes in CoreText on OS X 10.9, thus let's skip this step on older
- * operating system versions. Except for the emoji font, where _not_
- * reconfiguring the cascade list causes CoreText crashes. For details, see
- * crbug.com/549610 */
- // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) {
-#pragma GCC diagnostic pop
- CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
- bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
- CFRelease (fontName);
- if (!isEmojiFont)
- return ct_font;
- }
-
- CFURLRef original_url = nullptr;
-#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
- ATSFontRef atsFont;
- FSRef fsref;
- OSStatus status;
- atsFont = CTFontGetPlatformFont (ct_font, NULL);
- status = ATSFontGetFileReference (atsFont, &fsref);
- if (status == noErr)
- original_url = CFURLCreateFromFSRef (NULL, &fsref);
-#else
- original_url = (CFURLRef) CTFontCopyAttribute (ct_font, kCTFontURLAttribute);
-#endif
-
- /* Create font copy with cascade list that has LastResort first; this speeds up CoreText
- * font fallback which we don't need anyway. */
- {
- CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc ();
- CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, last_resort_font_desc);
- CFRelease (last_resort_font_desc);
- if (new_ct_font)
- {
- /* The CTFontCreateCopyWithAttributes call fails to stay on the same font
- * when reconfiguring the cascade list and may switch to a different font
- * when there are fonts that go by the same name, since the descriptor is
- * just name and size.
- *
- * Avoid reconfiguring the cascade lists if the new font is outside the
- * system locations that we cannot access from the sandboxed renderer
- * process in Blink. This can be detected by the new file URL location
- * that the newly found font points to. */
- CFURLRef new_url = nullptr;
-#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
- atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
- status = ATSFontGetFileReference (atsFont, &fsref);
- if (status == noErr)
- new_url = CFURLCreateFromFSRef (NULL, &fsref);
-#else
- new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
-#endif
- // Keep reconfigured font if URL cannot be retrieved (seems to be the case
- // on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606
- if (!original_url || !new_url || CFEqual (original_url, new_url)) {
- CFRelease (ct_font);
- ct_font = new_ct_font;
- } else {
- CFRelease (new_ct_font);
- DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed.");
- }
- if (new_url)
- CFRelease (new_url);
- }
- else
- DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
- }
-
- if (original_url)
- CFRelease (original_url);
- return ct_font;
-}
-
hb_coretext_face_data_t *
_hb_coretext_shaper_face_data_create (hb_face_t *face)
{
@@ -325,103 +55,7 @@
CFRelease ((CGFontRef) data);
}
-/**
- * hb_coretext_face_create:
- * @cg_font: The CGFontRef to work upon
- *
- * Creates an #hb_face_t face object from the specified
- * CGFontRef.
- *
- * Return value: (transfer full): The new face object
- *
- * Since: 0.9.10
- */
-hb_face_t *
-hb_coretext_face_create (CGFontRef cg_font)
-{
- hb_face_t *face = hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
- hb_face_set_get_table_tags_func (face, _hb_cg_get_table_tags, cg_font, nullptr);
- return face;
-}
-/**
- * hb_coretext_face_create_from_file_or_fail:
- * @file_name: A font filename
- * @index: The index of the face within the file
- *
- * Creates an #hb_face_t face object from the specified
- * font file and face index.
- *
- * This is similar in functionality to hb_face_create_from_file_or_fail(),
- * but uses the CoreText library for loading the font file.
- *
- * Return value: (transfer full): The new face object, or `NULL` if
- * no face is found at the specified index or the file cannot be read.
- *
- * Since: 10.1.0
- */
-hb_face_t *
-hb_coretext_face_create_from_file_or_fail (const char *file_name,
- unsigned int index)
-{
- auto url = CFURLCreateFromFileSystemRepresentation (nullptr,
- (const UInt8 *) file_name,
- strlen (file_name),
- false);
- if (unlikely (!url))
- return nullptr;
-
- auto ct_font_desc_array = CTFontManagerCreateFontDescriptorsFromURL (url);
- if (unlikely (!ct_font_desc_array))
- {
- CFRelease (url);
- return nullptr;
- }
- auto ct_font_desc = (CFArrayGetCount (ct_font_desc_array) > index) ?
- (CTFontDescriptorRef) CFArrayGetValueAtIndex (ct_font_desc_array, index) : nullptr;
- if (unlikely (!ct_font_desc))
- {
- CFRelease (ct_font_desc_array);
- CFRelease (url);
- return nullptr;
- }
- CFRelease (url);
- auto ct_font = ct_font_desc ? CTFontCreateWithFontDescriptor (ct_font_desc, 0, nullptr) : nullptr;
- CFRelease (ct_font_desc_array);
- if (unlikely (!ct_font))
- return nullptr;
-
- auto cg_font = ct_font ? CTFontCopyGraphicsFont (ct_font, nullptr) : nullptr;
- CFRelease (ct_font);
- if (unlikely (!cg_font))
- return nullptr;
-
- hb_face_t *face = hb_coretext_face_create (cg_font);
- CFRelease (cg_font);
- if (unlikely (hb_face_is_immutable (face)))
- return nullptr;
-
- return face;
-}
-
-/**
- * hb_coretext_face_get_cg_font:
- * @face: The #hb_face_t to work upon
- *
- * Fetches the CGFontRef associated with an #hb_face_t
- * face object
- *
- * Return value: the CGFontRef found
- *
- * Since: 0.9.10
- */
-CGFontRef
-hb_coretext_face_get_cg_font (hb_face_t *face)
-{
- return (CGFontRef) (const void *) face->data.coretext;
-}
-
-
hb_coretext_font_data_t *
_hb_coretext_shaper_font_data_create (hb_font_t *font)
{
@@ -439,7 +73,9 @@
return nullptr;
}
- if (font->num_coords)
+ unsigned num_axes = hb_ot_var_get_axis_count (face);
+ // https://github.com/harfbuzz/harfbuzz/issues/5163
+ if (num_axes)
{
CFMutableDictionaryRef variations =
CFDictionaryCreateMutable (kCFAllocatorDefault,
@@ -447,14 +83,15 @@
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
- for (unsigned i = 0; i < font->num_coords; i++)
+ unsigned count = hb_max (num_axes, font->num_coords);
+ for (unsigned i = 0; i < count; i++)
{
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);
+ float v = i < font->num_coords ?
+ hb_clamp (font->design_coords[i], info.min_value, info.max_value) :
+ info.default_value;
CFNumberRef tag_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag);
CFNumberRef value_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &v);
@@ -489,94 +126,6 @@
CFRelease ((CTFontRef) data);
}
-/**
- * hb_coretext_font_create:
- * @ct_font: The CTFontRef to work upon
- *
- * Creates an #hb_font_t font object from the specified
- * CTFontRef.
- *
- * The created font uses the default font functions implemented
- * 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().
- *
- * Return value: (transfer full): The new font object
- *
- * Since: 1.7.2
- **/
-hb_font_t *
-hb_coretext_font_create (CTFontRef ct_font)
-{
- CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, nullptr);
- hb_face_t *face = hb_coretext_face_create (cg_font);
- CFRelease (cg_font);
- hb_font_t *font = hb_font_create (face);
- hb_face_destroy (face);
-
- if (unlikely (hb_object_is_immutable (font)))
- return font;
-
- 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));
-
- // https://github.com/harfbuzz/harfbuzz/pull/4895#issuecomment-2408471254
- //hb_coretext_font_set_funcs (font);
-
- return font;
-}
-
-/**
- * hb_coretext_font_get_ct_font:
- * @font: #hb_font_t to work upon
- *
- * Fetches the CTFontRef associated with the specified
- * #hb_font_t font object.
- *
- * Return value: the CTFontRef found
- *
- * Since: 0.9.10
- */
-CTFontRef
-hb_coretext_font_get_ct_font (hb_font_t *font)
-{
- CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
- return ct_font ? (CTFontRef) ct_font : nullptr;
-}
-
-
/*
* shaper
*/
@@ -646,7 +195,7 @@
* B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
* continue pointing to B2 even though B2 was merged into B1's
* cluster... */
- if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
+ if (HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES (buffer->cluster_level))
{
hb_unicode_funcs_t *unicode = buffer->unicode;
unsigned int count = buffer->len;
@@ -1010,7 +559,7 @@
CFArrayRef glyph_runs = CTLineGetGlyphRuns (line);
unsigned int num_runs = CFArrayGetCount (glyph_runs);
- DEBUG_MSG (CORETEXT, nullptr, "Num runs: %d", num_runs);
+ DEBUG_MSG (CORETEXT, nullptr, "Num runs: %u", num_runs);
buffer->len = 0;
uint32_t status_or = 0;
@@ -1292,7 +841,7 @@
* or the native OT backend, only that the cluster indices will be
* monotonic in the output buffer. */
if (count > 1 && (status_or & kCTRunStatusNonMonotonic) &&
- buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
+ HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
{
hb_glyph_info_t *info = buffer->info;
if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,572 @@
+/*
+ * Copyright © 2012,2013 Mozilla Foundation.
+ * Copyright © 2012,2013 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifdef HAVE_CORETEXT
+
+#include "hb-shaper-impl.hh"
+
+#include "hb-coretext.hh"
+
+
+/**
+ * SECTION:hb-coretext
+ * @title: hb-coretext
+ * @short_description: CoreText integration
+ * @include: hb-coretext.h
+ *
+ * Functions for using HarfBuzz with the CoreText fonts.
+ **/
+
+static void
+release_table_data (void *user_data)
+{
+ CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
+ CFRelease(cf_data);
+}
+
+static hb_blob_t *
+_hb_cg_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
+{
+ CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
+ CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
+ if (unlikely (!cf_data))
+ return nullptr;
+
+ const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
+ const size_t length = CFDataGetLength (cf_data);
+ if (!data || !length)
+ {
+ CFRelease (cf_data);
+ return nullptr;
+ }
+
+ return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
+ reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
+ release_table_data);
+}
+
+static unsigned
+_hb_cg_get_table_tags (const hb_face_t *face HB_UNUSED,
+ unsigned int start_offset,
+ unsigned int *table_count,
+ hb_tag_t *table_tags,
+ void *user_data)
+{
+ CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
+
+ CTFontRef ct_font = create_ct_font (cg_font, (CGFloat) HB_CORETEXT_DEFAULT_FONT_SIZE);
+
+ auto arr = CTFontCopyAvailableTables (ct_font, kCTFontTableOptionNoOptions);
+
+ unsigned population = (unsigned) CFArrayGetCount (arr);
+ unsigned end_offset;
+
+ if (!table_count)
+ goto done;
+
+ if (unlikely (start_offset >= population))
+ {
+ *table_count = 0;
+ goto done;
+ }
+
+ end_offset = start_offset + *table_count;
+ if (unlikely (end_offset < start_offset))
+ {
+ *table_count = 0;
+ goto done;
+ }
+ end_offset= hb_min (end_offset, (unsigned) population);
+
+ *table_count = end_offset - start_offset;
+ for (unsigned i = start_offset; i < end_offset; i++)
+ {
+ CTFontTableTag tag = (CTFontTableTag)(uintptr_t) CFArrayGetValueAtIndex (arr, i);
+ table_tags[i - start_offset] = tag;
+ }
+
+done:
+ CFRelease (arr);
+ CFRelease (ct_font);
+ return population;
+}
+
+static void
+_hb_cg_font_release (void *data)
+{
+ CGFontRelease ((CGFontRef) data);
+}
+
+
+static CTFontDescriptorRef
+get_last_resort_font_desc ()
+{
+ // TODO Handle allocation failures?
+ CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
+ CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
+ (const void **) &last_resort,
+ 1,
+ &kCFTypeArrayCallBacks);
+ CFRelease (last_resort);
+ CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault,
+ (const void **) &kCTFontCascadeListAttribute,
+ (const void **) &cascade_list,
+ 1,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFRelease (cascade_list);
+
+ CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
+ CFRelease (attributes);
+ return font_desc;
+}
+
+static void
+release_data (void *info, const void *data, size_t size)
+{
+ assert (hb_blob_get_length ((hb_blob_t *) info) == size &&
+ hb_blob_get_data ((hb_blob_t *) info, nullptr) == data);
+
+ hb_blob_destroy ((hb_blob_t *) info);
+}
+
+CGFontRef
+create_cg_font (CFArrayRef ct_font_desc_array, unsigned int named_instance_index)
+{
+ if (named_instance_index == 0)
+ {
+ // Default instance. We don't know which one is it. Return the first one.
+ // We will set the correct variations on it later.
+ }
+ else
+ named_instance_index--;
+ auto ct_font_desc = (CFArrayGetCount (ct_font_desc_array) > named_instance_index) ?
+ (CTFontDescriptorRef) CFArrayGetValueAtIndex (ct_font_desc_array, named_instance_index) : nullptr;
+ if (unlikely (!ct_font_desc))
+ {
+ CFRelease (ct_font_desc_array);
+ return nullptr;
+ }
+ auto ct_font = ct_font_desc ? CTFontCreateWithFontDescriptor (ct_font_desc, 0, nullptr) : nullptr;
+ CFRelease (ct_font_desc_array);
+ if (unlikely (!ct_font))
+ return nullptr;
+
+ auto cg_font = ct_font ? CTFontCopyGraphicsFont (ct_font, nullptr) : nullptr;
+ CFRelease (ct_font);
+
+ return cg_font;
+}
+
+CGFontRef
+create_cg_font (hb_blob_t *blob, unsigned int index)
+{
+ hb_blob_make_immutable (blob);
+ unsigned int blob_length;
+ const char *blob_data = hb_blob_get_data (blob, &blob_length);
+ if (unlikely (!blob_length))
+ DEBUG_MSG (CORETEXT, blob, "Empty blob");
+
+ unsigned ttc_index = index & 0xFFFF;
+ unsigned named_instance_index = index >> 16;
+
+ if (ttc_index != 0)
+ {
+ DEBUG_MSG (CORETEXT, blob, "TTC index %d not supported", ttc_index);
+ return nullptr; // CoreText does not support TTCs
+ }
+
+ if (unlikely (named_instance_index != 0))
+ {
+ auto ct_font_desc_array = CTFontManagerCreateFontDescriptorsFromData (CFDataCreate (kCFAllocatorDefault, (const UInt8 *) blob_data, blob_length));
+ if (unlikely (!ct_font_desc_array))
+ return nullptr;
+ return create_cg_font (ct_font_desc_array, named_instance_index);
+ }
+
+ hb_blob_reference (blob);
+ CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
+ CGFontRef cg_font = nullptr;
+ if (likely (provider))
+ {
+ cg_font = CGFontCreateWithDataProvider (provider);
+ if (unlikely (!cg_font))
+ DEBUG_MSG (CORETEXT, blob, "CGFontCreateWithDataProvider() failed");
+ CGDataProviderRelease (provider);
+ }
+ return cg_font;
+}
+
+CGFontRef
+create_cg_font (hb_face_t *face)
+{
+ CGFontRef cg_font = nullptr;
+ if (face->destroy == _hb_cg_font_release)
+ cg_font = CGFontRetain ((CGFontRef) face->user_data);
+ else
+ {
+ hb_blob_t *blob = hb_face_reference_blob (face);
+ cg_font = create_cg_font (blob, face->index);
+ hb_blob_destroy (blob);
+ }
+ return cg_font;
+}
+
+CTFontRef
+create_ct_font (CGFontRef cg_font, CGFloat font_size)
+{
+ CTFontRef ct_font = nullptr;
+
+ /* CoreText does not enable trak table usage / tracking when creating a CTFont
+ * using CTFontCreateWithGraphicsFont. The only way of enabling tracking seems
+ * to be through the CTFontCreateUIFontForLanguage call. */
+ CFStringRef cg_postscript_name = CGFontCopyPostScriptName (cg_font);
+ if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) ||
+ CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay")))
+ {
+#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1080
+# define kCTFontUIFontSystem kCTFontSystemFontType
+# define kCTFontUIFontEmphasizedSystem kCTFontEmphasizedSystemFontType
+#endif
+ CTFontUIFontType font_type = kCTFontUIFontSystem;
+ if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold")))
+ font_type = kCTFontUIFontEmphasizedSystem;
+
+ ct_font = CTFontCreateUIFontForLanguage (font_type, font_size, nullptr);
+ CFStringRef ct_result_name = CTFontCopyPostScriptName(ct_font);
+ if (CFStringCompare (ct_result_name, cg_postscript_name, 0) != kCFCompareEqualTo)
+ {
+ CFRelease(ct_font);
+ ct_font = nullptr;
+ }
+ CFRelease (ct_result_name);
+ }
+ CFRelease (cg_postscript_name);
+
+ if (!ct_font)
+ ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, nullptr, nullptr);
+
+ if (unlikely (!ct_font)) {
+ DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
+ return nullptr;
+ }
+
+ /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
+ * bug indicate that the cascade list reconfiguration occasionally causes
+ * crashes in CoreText on OS X 10.9, thus let's skip this step on older
+ * operating system versions. Except for the emoji font, where _not_
+ * reconfiguring the cascade list causes CoreText crashes. For details, see
+ * crbug.com/549610 */
+ // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) {
+#pragma GCC diagnostic pop
+ CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
+ bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
+ CFRelease (fontName);
+ if (!isEmojiFont)
+ return ct_font;
+ }
+
+ CFURLRef original_url = nullptr;
+#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ ATSFontRef atsFont;
+ FSRef fsref;
+ OSStatus status;
+ atsFont = CTFontGetPlatformFont (ct_font, NULL);
+ status = ATSFontGetFileReference (atsFont, &fsref);
+ if (status == noErr)
+ original_url = CFURLCreateFromFSRef (NULL, &fsref);
+#else
+ original_url = (CFURLRef) CTFontCopyAttribute (ct_font, kCTFontURLAttribute);
+#endif
+
+ /* Create font copy with cascade list that has LastResort first; this speeds up CoreText
+ * font fallback which we don't need anyway. */
+ {
+ CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc ();
+ CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, last_resort_font_desc);
+ CFRelease (last_resort_font_desc);
+ if (new_ct_font)
+ {
+ /* The CTFontCreateCopyWithAttributes call fails to stay on the same font
+ * when reconfiguring the cascade list and may switch to a different font
+ * when there are fonts that go by the same name, since the descriptor is
+ * just name and size.
+ *
+ * Avoid reconfiguring the cascade lists if the new font is outside the
+ * system locations that we cannot access from the sandboxed renderer
+ * process in Blink. This can be detected by the new file URL location
+ * that the newly found font points to. */
+ CFURLRef new_url = nullptr;
+#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
+ status = ATSFontGetFileReference (atsFont, &fsref);
+ if (status == noErr)
+ new_url = CFURLCreateFromFSRef (NULL, &fsref);
+#else
+ new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
+#endif
+ // Keep reconfigured font if URL cannot be retrieved (seems to be the case
+ // on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606
+ if (!original_url || !new_url || CFEqual (original_url, new_url)) {
+ CFRelease (ct_font);
+ ct_font = new_ct_font;
+ } else {
+ CFRelease (new_ct_font);
+ DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed.");
+ }
+ if (new_url)
+ CFRelease (new_url);
+ }
+ else
+ DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
+ }
+
+ if (original_url)
+ CFRelease (original_url);
+ return ct_font;
+}
+
+/**
+ * hb_coretext_face_create:
+ * @cg_font: The CGFontRef to work upon
+ *
+ * Creates an #hb_face_t face object from the specified
+ * CGFontRef.
+ *
+ * Return value: (transfer full): The new face object
+ *
+ * Since: 0.9.10
+ */
+hb_face_t *
+hb_coretext_face_create (CGFontRef cg_font)
+{
+ hb_face_t *face = hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
+ hb_face_set_get_table_tags_func (face, _hb_cg_get_table_tags, cg_font, nullptr);
+ return face;
+}
+
+/**
+ * hb_coretext_face_create_from_file_or_fail:
+ * @file_name: A font filename
+ * @index: The index of the face within the file
+ *
+ * Creates an #hb_face_t face object from the specified
+ * font file and face index.
+ *
+ * This is similar in functionality to hb_face_create_from_file_or_fail(),
+ * but uses the CoreText library for loading the font file.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * no face is found at the specified index or the file cannot be read.
+ *
+ * Since: 10.1.0
+ */
+hb_face_t *
+hb_coretext_face_create_from_file_or_fail (const char *file_name,
+ unsigned int index)
+{
+ auto url = CFURLCreateFromFileSystemRepresentation (nullptr,
+ (const UInt8 *) file_name,
+ strlen (file_name),
+ false);
+ if (unlikely (!url))
+ return nullptr;
+
+ auto ct_font_desc_array = CTFontManagerCreateFontDescriptorsFromURL (url);
+ if (unlikely (!ct_font_desc_array))
+ {
+ CFRelease (url);
+ return nullptr;
+ }
+
+ unsigned ttc_index = index & 0xFFFF;
+ unsigned named_instance_index = index >> 16;
+
+ if (ttc_index != 0)
+ {
+ DEBUG_MSG (CORETEXT, nullptr, "TTC index %d not supported", ttc_index);
+ return nullptr; // CoreText does not support TTCs
+ }
+
+ auto cg_font = create_cg_font (ct_font_desc_array, named_instance_index);
+ CFRelease (url);
+
+ hb_face_t *face = hb_coretext_face_create (cg_font);
+ CFRelease (cg_font);
+ if (unlikely (hb_face_is_immutable (face)))
+ return nullptr;
+
+ hb_face_set_index (face, index);
+
+ return face;
+}
+
+/**
+ * hb_coretext_face_create_from_blob_or_fail:
+ * @blob: A blob containing the font data
+ * @index: The index of the face within the blob
+ *
+ * Creates an #hb_face_t face object from the specified
+ * blob and face index.
+ *
+ * This is similar in functionality to hb_face_create_from_blob_or_fail(),
+ * but uses the CoreText library for loading the font data.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * no face is found at the specified index or the blob cannot be read.
+ *
+ * Since: 11.0.0
+ */
+hb_face_t *
+hb_coretext_face_create_from_blob_or_fail (hb_blob_t *blob,
+ unsigned int index)
+{
+ auto cg_font = create_cg_font (blob, index);
+ if (unlikely (!cg_font))
+ return nullptr;
+
+ hb_face_t *face = hb_coretext_face_create (cg_font);
+ CFRelease (cg_font);
+ if (unlikely (hb_face_is_immutable (face)))
+ return nullptr;
+
+ hb_face_set_index (face, index);
+
+ return face;
+}
+
+/**
+ * hb_coretext_face_get_cg_font:
+ * @face: The #hb_face_t to work upon
+ *
+ * Fetches the CGFontRef associated with an #hb_face_t
+ * face object
+ *
+ * Return value: the CGFontRef found
+ *
+ * Since: 0.9.10
+ */
+CGFontRef
+hb_coretext_face_get_cg_font (hb_face_t *face)
+{
+ return (CGFontRef) (const void *) face->data.coretext;
+}
+
+/**
+ * hb_coretext_font_create:
+ * @ct_font: The CTFontRef to work upon
+ *
+ * Creates an #hb_font_t font object from the specified
+ * CTFontRef.
+ *
+ * The created font uses the default font functions implemented
+ * 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().
+ *
+ * Return value: (transfer full): The new font object
+ *
+ * Since: 1.7.2
+ **/
+hb_font_t *
+hb_coretext_font_create (CTFontRef ct_font)
+{
+ CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, nullptr);
+ hb_face_t *face = hb_coretext_face_create (cg_font);
+ CFRelease (cg_font);
+ hb_font_t *font = hb_font_create (face);
+ hb_face_destroy (face);
+
+ if (unlikely (hb_object_is_immutable (font)))
+ return font;
+
+ 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));
+
+ // https://github.com/harfbuzz/harfbuzz/pull/4895#issuecomment-2408471254
+ //hb_coretext_font_set_funcs (font);
+
+ return font;
+}
+
+/**
+ * hb_coretext_font_get_ct_font:
+ * @font: #hb_font_t to work upon
+ *
+ * Fetches the CTFontRef associated with the specified
+ * #hb_font_t font object.
+ *
+ * Return value: the CTFontRef found
+ *
+ * Since: 0.9.10
+ */
+CTFontRef
+hb_coretext_font_get_ct_font (hb_font_t *font)
+{
+ return (CTFontRef) (const void *) font->data.coretext;
+}
+
+
+#endif
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.h 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -84,6 +84,10 @@
hb_coretext_face_create_from_file_or_fail (const char *file_name,
unsigned int index);
+HB_EXTERN hb_face_t *
+hb_coretext_face_create_from_blob_or_fail (hb_blob_t *blob,
+ unsigned int index);
+
HB_EXTERN hb_font_t *
hb_coretext_font_create (CTFontRef ct_font);
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.hh (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2012,2013 Mozilla Foundation.
+ * Copyright © 2012,2013 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+
+#ifndef HB_CORETEXT_HH
+#define HB_CORETEXT_HH
+
+#include "hb.hh"
+
+#include "hb-coretext.h"
+
+#include "hb-aat-layout.hh"
+
+
+HB_INTERNAL CGFontRef
+create_cg_font (CFArrayRef ct_font_desc_array, unsigned int index);
+
+HB_INTERNAL CGFontRef
+create_cg_font (hb_blob_t *blob, unsigned int index);
+
+HB_INTERNAL CGFontRef
+create_cg_font (hb_face_t *face);
+
+HB_INTERNAL CTFontRef
+create_ct_font (CGFontRef cg_font, CGFloat font_size);
+
+
+#endif /* HB_CORETEXT_HH */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -49,15 +49,15 @@
};
union hb_options_union_t {
- int i;
+ unsigned i;
hb_options_t opts;
};
-static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
+static_assert ((sizeof (hb_atomic_t<unsigned>) >= sizeof (hb_options_union_t)), "");
HB_INTERNAL void
_hb_options_init ();
-extern HB_INTERNAL hb_atomic_int_t _hb_options;
+extern HB_INTERNAL hb_atomic_t<unsigned> _hb_options;
static inline hb_options_t
hb_options ()
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite-font.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite-font.cc (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite-font.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,388 @@
+/*
+ * Copyright © 2025 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifdef HAVE_DIRECTWRITE
+
+#include "hb-directwrite.h"
+
+#include <d2d1.h>
+
+#include "hb-draw.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+
+#define MAX_GLYPHS 256u
+
+static unsigned int
+hb_directwrite_get_nominal_glyphs (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ unsigned int count,
+ const hb_codepoint_t *first_unicode,
+ unsigned int unicode_stride,
+ hb_codepoint_t *first_glyph,
+ unsigned int glyph_stride,
+ void *user_data HB_UNUSED)
+{
+ IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
+
+ for (unsigned i = 0; i < count;)
+ {
+ UINT32 unicodes[MAX_GLYPHS];
+ UINT16 gids[MAX_GLYPHS];
+
+ unsigned n = hb_min (MAX_GLYPHS, count - i);
+
+ for (unsigned j = 0; j < n; j++)
+ {
+ unicodes[j] = *first_unicode;
+ first_unicode = &StructAtOffset<const hb_codepoint_t> (first_unicode, unicode_stride);
+ }
+
+ if (!SUCCEEDED (dw_face->GetGlyphIndices (unicodes, n, gids)))
+ return i;
+
+ for (unsigned j = 0; j < n; j++)
+ {
+ if (!gids[j])
+ return i + j;
+ *first_glyph = gids[j];
+ first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
+ }
+
+ i += n;
+ }
+
+ return count;
+}
+
+static hb_bool_t
+hb_directwrite_get_font_h_extents (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_font_extents_t *metrics,
+ void *user_data HB_UNUSED)
+{
+ IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
+
+ DWRITE_FONT_METRICS dw_metrics;
+ dw_face->GetMetrics (&dw_metrics);
+
+ metrics->ascender = font->em_scale_y (dw_metrics.ascent);
+ metrics->descender = -font->em_scale_y (dw_metrics.descent);
+ metrics->line_gap = font->em_scale_y (dw_metrics.lineGap);
+
+ return true;
+}
+
+static void
+hb_directwrite_get_glyph_h_advances (hb_font_t* font,
+ void* font_data HB_UNUSED,
+ unsigned count,
+ const hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride,
+ void *user_data HB_UNUSED)
+{
+ IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
+
+ IDWriteFontFace1 *dw_face1 = nullptr;
+ dw_face->QueryInterface (__uuidof(IDWriteFontFace1), (void**)&dw_face1);
+ assert (dw_face1);
+
+ for (unsigned i = 0; i < count;)
+ {
+ UINT16 gids[MAX_GLYPHS];
+ INT32 advances[MAX_GLYPHS];
+
+ unsigned n = hb_min (MAX_GLYPHS, count - i);
+
+ for (unsigned j = 0; j < n; j++)
+ {
+ gids[j] = *first_glyph;
+ advances[j] = 0;
+ first_glyph = &StructAtOffset<const hb_codepoint_t> (first_glyph, glyph_stride);
+ }
+ dw_face1->GetDesignGlyphAdvances (n, gids, advances, false);
+ for (unsigned j = 0; j < n; j++)
+ {
+ *first_advance = font->em_scale_x (advances[j]);
+ first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
+ }
+
+ i += n;
+ }
+}
+
+#ifndef HB_NO_VERTICAL
+
+static void
+hb_directwrite_get_glyph_v_advances (hb_font_t* font,
+ void* font_data HB_UNUSED,
+ unsigned count,
+ const hb_codepoint_t *first_glyph,
+ unsigned glyph_stride,
+ hb_position_t *first_advance,
+ unsigned advance_stride,
+ void *user_data HB_UNUSED)
+{
+ IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
+
+ IDWriteFontFace1 *dw_face1 = nullptr;
+ dw_face->QueryInterface (__uuidof(IDWriteFontFace1), (void**)&dw_face1);
+ assert (dw_face1);
+
+ for (unsigned i = 0; i < count;)
+ {
+ UINT16 gids[MAX_GLYPHS];
+ INT32 advances[MAX_GLYPHS];
+
+ unsigned n = hb_min (MAX_GLYPHS, count - i);
+
+ for (unsigned j = 0; j < n; j++)
+ {
+ gids[j] = *first_glyph;
+ advances[j] = 0;
+ first_glyph = &StructAtOffset<const hb_codepoint_t> (first_glyph, glyph_stride);
+ }
+ dw_face1->GetDesignGlyphAdvances (n, gids, advances, true);
+ for (unsigned j = 0; j < n; j++)
+ {
+ *first_advance = -font->em_scale_y (advances[j]);
+ first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
+ }
+
+ i += n;
+ }
+}
+
+static hb_bool_t
+hb_directwrite_get_glyph_v_origin (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
+
+ UINT16 gid = glyph;
+ DWRITE_GLYPH_METRICS metrics;
+
+ if (FAILED (dw_face->GetDesignGlyphMetrics (&gid, 1, &metrics)))
+ return false;
+
+ *x = font->em_scale_x (metrics.advanceWidth / 2);
+ *y = font->em_scale_y (metrics.verticalOriginY); // Untested
+
+ return true;
+}
+#endif
+
+static hb_bool_t
+hb_directwrite_get_glyph_extents (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data HB_UNUSED)
+{
+ IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
+
+ UINT16 gid = glyph;
+ DWRITE_GLYPH_METRICS metrics;
+
+ if (FAILED (dw_face->GetDesignGlyphMetrics (&gid, 1, &metrics)))
+ return false;
+
+ extents->x_bearing = font->em_scale_x (metrics.leftSideBearing);
+ extents->y_bearing = font->em_scale_y (metrics.verticalOriginY - metrics.topSideBearing);
+ extents->width = font->em_scale_x (metrics.advanceWidth - metrics.rightSideBearing) - extents->x_bearing;
+ extents->height = font->em_scale_y (metrics.verticalOriginY - metrics.advanceHeight + metrics.bottomSideBearing) - extents->y_bearing; // Magic
+
+ return true;
+}
+
+
+#ifndef HB_NO_DRAW
+
+class GeometrySink : public IDWriteGeometrySink
+{
+ hb_font_t *font;
+ hb_draw_session_t drawing;
+
+public:
+ GeometrySink(hb_font_t *font,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data)
+ : font (font), drawing ({draw_funcs, draw_data, font->slant}) {}
+
+ virtual ~GeometrySink() {}
+
+ HRESULT STDMETHODCALLTYPE Close() override { return S_OK; }
+ void STDMETHODCALLTYPE SetFillMode(D2D1_FILL_MODE) override {}
+ void STDMETHODCALLTYPE SetSegmentFlags(D2D1_PATH_SEGMENT) override {}
+
+ IFACEMETHOD(QueryInterface)(REFIID, void **) override { return E_NOINTERFACE; }
+ IFACEMETHOD_(ULONG, AddRef)() override { return 1; }
+ IFACEMETHOD_(ULONG, Release)() override { return 1; }
+
+ void STDMETHODCALLTYPE BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN) override
+ {
+ drawing.move_to (font->em_scalef_x (startPoint.x), -font->em_scalef_y (startPoint.y));
+ }
+
+ void STDMETHODCALLTYPE AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) override
+ {
+ for (unsigned i = 0; i < beziersCount; ++i)
+ drawing.cubic_to (font->em_scalef_x (beziers[i].point1.x), -font->em_scalef_y (beziers[i].point1.y),
+ font->em_scalef_x (beziers[i].point2.x), -font->em_scalef_y (beziers[i].point2.y),
+ font->em_scalef_x (beziers[i].point3.x), -font->em_scalef_y (beziers[i].point3.y));
+ }
+
+ void STDMETHODCALLTYPE AddLines(const D2D1_POINT_2F *points, UINT pointsCount) override
+ {
+ for (unsigned i = 0; i < pointsCount; ++i)
+ drawing.line_to (font->em_scalef_x (points[i].x), -font->em_scalef_y (points[i].y));
+ }
+
+ void STDMETHODCALLTYPE EndFigure(D2D1_FIGURE_END) override
+ {
+ drawing.close_path ();
+ }
+};
+
+static void
+hb_directwrite_draw_glyph (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data)
+{
+ IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
+
+ GeometrySink sink (font, draw_funcs, draw_data);
+ UINT16 gid = static_cast<UINT16>(glyph);
+ unsigned upem = font->face->get_upem();
+
+ (void) dw_face->GetGlyphRunOutline (upem,
+ &gid, nullptr, nullptr,
+ 1,
+ false, false,
+ &sink);
+}
+
+#endif
+
+static inline void free_static_directwrite_funcs ();
+
+static struct hb_directwrite_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_directwrite_font_funcs_lazy_loader_t>
+{
+ static hb_font_funcs_t *create ()
+ {
+ hb_font_funcs_t *funcs = hb_font_funcs_create ();
+
+ hb_font_funcs_set_nominal_glyphs_func (funcs, hb_directwrite_get_nominal_glyphs, nullptr, nullptr);
+ //hb_font_funcs_set_variation_glyph_func (funcs, hb_directwrite_get_variation_glyph, nullptr, nullptr);
+
+ hb_font_funcs_set_font_h_extents_func (funcs, hb_directwrite_get_font_h_extents, nullptr, nullptr);
+ hb_font_funcs_set_glyph_h_advances_func (funcs, hb_directwrite_get_glyph_h_advances, nullptr, nullptr);
+
+#ifndef HB_NO_VERTICAL
+ hb_font_funcs_set_glyph_v_advances_func (funcs, hb_directwrite_get_glyph_v_advances, nullptr, nullptr);
+ hb_font_funcs_set_glyph_v_origin_func (funcs, hb_directwrite_get_glyph_v_origin, nullptr, nullptr);
+#endif
+
+#ifndef HB_NO_DRAW
+ hb_font_funcs_set_draw_glyph_func (funcs, hb_directwrite_draw_glyph, nullptr, nullptr);
+#endif
+
+ hb_font_funcs_set_glyph_extents_func (funcs, hb_directwrite_get_glyph_extents, nullptr, nullptr);
+
+#ifndef HB_NO_OT_FONT_GLYPH_NAMES
+ //hb_font_funcs_set_glyph_name_func (funcs, hb_directwrite_get_glyph_name, nullptr, nullptr);
+ //hb_font_funcs_set_glyph_from_name_func (funcs, hb_directwrite_get_glyph_from_name, nullptr, nullptr);
+#endif
+
+ hb_font_funcs_make_immutable (funcs);
+
+ hb_atexit (free_static_directwrite_funcs);
+
+ return funcs;
+ }
+} static_directwrite_funcs;
+
+static inline
+void free_static_directwrite_funcs ()
+{
+ static_directwrite_funcs.free_instance ();
+}
+
+static hb_font_funcs_t *
+_hb_directwrite_get_font_funcs ()
+{
+ return static_directwrite_funcs.get_unconst ();
+}
+
+/**
+ * hb_directwrite_font_set_funcs:
+ * @font: #hb_font_t to work upon
+ *
+ * Configures the font-functions structure of the specified
+ * #hb_font_t font object to use DirectWrite font functions.
+ *
+ * In particular, you can use this function to configure an
+ * existing #hb_face_t face object for use with DirectWrite font
+ * functions even if that #hb_face_t face object was initially
+ * created with hb_face_create(), and therefore was not
+ * initially configured to use DirectWrite font functions.
+ *
+ * <note>Note: Internally, this function creates a DirectWrite font.
+ * </note>
+ *
+ * Since: 11.0.0
+ **/
+void
+hb_directwrite_font_set_funcs (hb_font_t *font)
+{
+ IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
+ if (unlikely (!dw_face))
+ {
+ hb_font_set_funcs (font,
+ hb_font_funcs_get_empty (),
+ nullptr, nullptr);
+ return;
+ }
+
+ dw_face->AddRef ();
+ hb_font_set_funcs (font,
+ _hb_directwrite_get_font_funcs (),
+ nullptr, nullptr);
+}
+
+#undef MAX_GLYPHS
+
+#endif
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite-shape.cc (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite-shape.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,656 @@
+/*
+ * 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"
+
+#ifdef HAVE_DIRECTWRITE
+
+#include "hb-shaper-impl.hh"
+
+#include "hb-directwrite.hh"
+
+#include "hb-ms-feature-ranges.hh"
+
+
+/*
+* shaper face data
+*/
+
+hb_directwrite_face_data_t *
+_hb_directwrite_shaper_face_data_create (hb_face_t *face)
+{
+ hb_blob_t *blob = hb_face_reference_blob (face);
+
+ hb_directwrite_face_data_t *data = (hb_directwrite_face_data_t *) dw_face_create (blob, face->index);
+
+ hb_blob_destroy (blob);
+
+ return data;
+}
+
+void
+_hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
+{
+ ((IDWriteFontFace *) data)->Release ();
+}
+
+
+/*
+ * shaper font data
+ */
+
+struct hb_directwrite_font_data_t {};
+
+hb_directwrite_font_data_t *
+_hb_directwrite_shaper_font_data_create (hb_font_t *font)
+{
+ IDWriteFontFace *fontFace = (IDWriteFontFace *) (const void *) font->face->data.directwrite;
+
+ /*
+ * Set up variations.
+ */
+ IDWriteFontFace5 *fontFaceVariations = nullptr;
+ {
+ IDWriteFontFace5 *fontFace5;
+ if (SUCCEEDED (fontFace->QueryInterface (__uuidof (IDWriteFontFace5), (void **) &fontFace5)))
+ {
+ IDWriteFontResource *fontResource;
+ if (SUCCEEDED (fontFace5->GetFontResource (&fontResource)))
+ {
+ hb_vector_t<DWRITE_FONT_AXIS_VALUE> axis_values;
+ if (likely (axis_values.resize_exact (font->num_coords)))
+ {
+ for (unsigned int i = 0; i < font->num_coords; i++)
+ {
+ hb_ot_var_axis_info_t info;
+ unsigned int c = 1;
+ hb_ot_var_get_axis_infos (font->face, i, &c, &info);
+ axis_values[i].axisTag = (DWRITE_FONT_AXIS_TAG) hb_uint32_swap (info.tag);
+ axis_values[i].value = i < font->num_coords ?
+ hb_clamp (font->design_coords[i], info.min_value, info.max_value) :
+ info.default_value;
+ }
+
+ fontResource->CreateFontFace (DWRITE_FONT_SIMULATIONS::DWRITE_FONT_SIMULATIONS_NONE,
+ axis_values.arrayZ, axis_values.length, &fontFaceVariations);
+ }
+ fontResource->Release ();
+ }
+ fontFace5->Release ();
+ }
+ }
+
+ return (hb_directwrite_font_data_t *) fontFaceVariations;
+}
+
+void
+_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
+{
+ ((IDWriteFontFace *) data)->Release ();
+}
+
+
+// Most of TextAnalysis is originally written by Bas Schouten for Mozilla project
+// but now is relicensed to MIT for HarfBuzz use
+class TextAnalysis : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink
+{
+private:
+ hb_reference_count_t mRefCount;
+public:
+ IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
+ { return S_OK; }
+ IFACEMETHOD_ (ULONG, AddRef) ()
+ {
+ return mRefCount.inc () + 1;
+ }
+ IFACEMETHOD_ (ULONG, Release) ()
+ {
+ signed refCount = mRefCount.dec () - 1;
+ assert (refCount >= 0);
+ if (refCount)
+ return refCount;
+ delete this;
+ return 0;
+ }
+
+ // A single contiguous run of characters containing the same analysis
+ // results.
+ struct Run
+ {
+ uint32_t mTextStart; // starting text position of this run
+ uint32_t mTextLength; // number of contiguous code units covered
+ uint32_t mGlyphStart; // starting glyph in the glyphs array
+ uint32_t mGlyphCount; // number of glyphs associated with this run
+ // text
+ DWRITE_SCRIPT_ANALYSIS mScript;
+ uint8_t mBidiLevel;
+ bool mIsSideways;
+
+ bool ContainsTextPosition (uint32_t aTextPosition) const
+ {
+ return aTextPosition >= mTextStart &&
+ aTextPosition < mTextStart + mTextLength;
+ }
+
+ Run *nextRun;
+ };
+
+public:
+ TextAnalysis (const wchar_t* text, uint32_t textLength,
+ const wchar_t* localeName, DWRITE_READING_DIRECTION readingDirection)
+ : mTextLength (textLength), mText (text), mLocaleName (localeName),
+ mReadingDirection (readingDirection), mCurrentRun (nullptr)
+ {
+ mRefCount.init ();
+ }
+ virtual ~TextAnalysis ()
+ {
+ // delete runs, except mRunHead which is part of the TextAnalysis object
+ for (Run *run = mRunHead.nextRun; run;)
+ {
+ Run *origRun = run;
+ run = run->nextRun;
+ delete origRun;
+ }
+ }
+
+ STDMETHODIMP
+ GenerateResults (IDWriteTextAnalyzer* textAnalyzer, Run **runHead)
+ {
+ // Analyzes the text using the script analyzer and returns
+ // the result as a series of runs.
+
+ HRESULT hr = S_OK;
+
+ // Initially start out with one result that covers the entire range.
+ // This result will be subdivided by the analysis processes.
+ mRunHead.mTextStart = 0;
+ mRunHead.mTextLength = mTextLength;
+ mRunHead.mBidiLevel =
+ (mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
+ mRunHead.nextRun = nullptr;
+ mCurrentRun = &mRunHead;
+
+ // Call each of the analyzers in sequence, recording their results.
+ if (SUCCEEDED (hr = textAnalyzer->AnalyzeScript (this, 0, mTextLength, this)))
+ *runHead = &mRunHead;
+
+ return hr;
+ }
+
+ // IDWriteTextAnalysisSource implementation
+
+ IFACEMETHODIMP
+ GetTextAtPosition (uint32_t textPosition,
+ OUT wchar_t const** textString,
+ OUT uint32_t* textLength)
+ {
+ if (textPosition >= mTextLength)
+ {
+ // No text at this position, valid query though.
+ *textString = nullptr;
+ *textLength = 0;
+ }
+ else
+ {
+ *textString = mText + textPosition;
+ *textLength = mTextLength - textPosition;
+ }
+ return S_OK;
+ }
+
+ IFACEMETHODIMP
+ GetTextBeforePosition (uint32_t textPosition,
+ OUT wchar_t const** textString,
+ OUT uint32_t* textLength)
+ {
+ if (textPosition == 0 || textPosition > mTextLength)
+ {
+ // Either there is no text before here (== 0), or this
+ // is an invalid position. The query is considered valid though.
+ *textString = nullptr;
+ *textLength = 0;
+ }
+ else
+ {
+ *textString = mText;
+ *textLength = textPosition;
+ }
+ return S_OK;
+ }
+
+ IFACEMETHODIMP_ (DWRITE_READING_DIRECTION)
+ GetParagraphReadingDirection () { return mReadingDirection; }
+
+ IFACEMETHODIMP GetLocaleName (uint32_t textPosition, uint32_t* textLength,
+ wchar_t const** localeName)
+ { return S_OK; }
+
+ IFACEMETHODIMP
+ GetNumberSubstitution (uint32_t textPosition,
+ OUT uint32_t* textLength,
+ OUT IDWriteNumberSubstitution** numberSubstitution)
+ {
+ // We do not support number substitution.
+ *numberSubstitution = nullptr;
+ *textLength = mTextLength - textPosition;
+
+ return S_OK;
+ }
+
+ // IDWriteTextAnalysisSink implementation
+
+ IFACEMETHODIMP
+ SetScriptAnalysis (uint32_t textPosition, uint32_t textLength,
+ DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis)
+ {
+ SetCurrentRun (textPosition);
+ SplitCurrentRun (textPosition);
+ while (textLength > 0)
+ {
+ Run *run = FetchNextRun (&textLength);
+ run->mScript = *scriptAnalysis;
+ }
+
+ return S_OK;
+ }
+
+ IFACEMETHODIMP
+ SetLineBreakpoints (uint32_t textPosition,
+ uint32_t textLength,
+ const DWRITE_LINE_BREAKPOINT* lineBreakpoints)
+ { return S_OK; }
+
+ IFACEMETHODIMP SetBidiLevel (uint32_t textPosition, uint32_t textLength,
+ uint8_t explicitLevel, uint8_t resolvedLevel)
+ { return S_OK; }
+
+ IFACEMETHODIMP
+ SetNumberSubstitution (uint32_t textPosition, uint32_t textLength,
+ IDWriteNumberSubstitution* numberSubstitution)
+ { return S_OK; }
+
+protected:
+ Run *FetchNextRun (IN OUT uint32_t* textLength)
+ {
+ // Used by the sink setters, this returns a reference to the next run.
+ // Position and length are adjusted to now point after the current run
+ // being returned.
+
+ Run *origRun = mCurrentRun;
+ // Split the tail if needed (the length remaining is less than the
+ // current run's size).
+ if (*textLength < mCurrentRun->mTextLength)
+ SplitCurrentRun (mCurrentRun->mTextStart + *textLength);
+ else
+ // Just advance the current run.
+ mCurrentRun = mCurrentRun->nextRun;
+ *textLength -= origRun->mTextLength;
+
+ // Return a reference to the run that was just current.
+ return origRun;
+ }
+
+ void SetCurrentRun (uint32_t textPosition)
+ {
+ // Move the current run to the given position.
+ // Since the analyzers generally return results in a forward manner,
+ // this will usually just return early. If not, find the
+ // corresponding run for the text position.
+
+ if (mCurrentRun && mCurrentRun->ContainsTextPosition (textPosition))
+ return;
+
+ for (Run *run = &mRunHead; run; run = run->nextRun)
+ if (run->ContainsTextPosition (textPosition))
+ {
+ mCurrentRun = run;
+ return;
+ }
+ assert (0); // We should always be able to find the text position in one of our runs
+ }
+
+ void SplitCurrentRun (uint32_t splitPosition)
+ {
+ if (!mCurrentRun)
+ {
+ assert (0); // SplitCurrentRun called without current run
+ // Shouldn't be calling this when no current run is set!
+ return;
+ }
+ // Split the current run.
+ if (splitPosition <= mCurrentRun->mTextStart)
+ {
+ // No need to split, already the start of a run
+ // or before it. Usually the first.
+ return;
+ }
+ Run *newRun = new Run;
+
+ *newRun = *mCurrentRun;
+
+ // Insert the new run in our linked list.
+ newRun->nextRun = mCurrentRun->nextRun;
+ mCurrentRun->nextRun = newRun;
+
+ // Adjust runs' text positions and lengths.
+ uint32_t splitPoint = splitPosition - mCurrentRun->mTextStart;
+ newRun->mTextStart += splitPoint;
+ newRun->mTextLength -= splitPoint;
+ mCurrentRun->mTextLength = splitPoint;
+ mCurrentRun = newRun;
+ }
+
+protected:
+ // Input
+ // (weak references are fine here, since this class is a transient
+ // stack-based helper that doesn't need to copy data)
+ uint32_t mTextLength;
+ const wchar_t* mText;
+ const wchar_t* mLocaleName;
+ DWRITE_READING_DIRECTION mReadingDirection;
+
+ // Current processing state.
+ Run *mCurrentRun;
+
+ // Output is a list of runs starting here
+ Run mRunHead;
+};
+
+/*
+ * shaper
+ */
+
+hb_bool_t
+_hb_directwrite_shape (hb_shape_plan_t *shape_plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features)
+{
+ IDWriteFontFace *fontFace = (IDWriteFontFace *) (const void *) font->data.directwrite;
+ auto *global = get_directwrite_global ();
+ if (unlikely (!global))
+ return false;
+ IDWriteFactory *dwriteFactory = global->dwriteFactory;
+
+ IDWriteTextAnalyzer* analyzer;
+ dwriteFactory->CreateTextAnalyzer (&analyzer);
+
+ unsigned int scratch_size;
+ hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
+#define ALLOCATE_ARRAY(Type, name, len) \
+ Type *name = (Type *) scratch; \
+ do { \
+ unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
+ assert (_consumed <= scratch_size); \
+ scratch += _consumed; \
+ scratch_size -= _consumed; \
+ } while (0)
+
+#define utf16_index() var1.u32
+
+ ALLOCATE_ARRAY (wchar_t, textString, buffer->len * 2);
+
+ unsigned int chars_len = 0;
+ for (unsigned int i = 0; i < buffer->len; i++)
+ {
+ hb_codepoint_t c = buffer->info[i].codepoint;
+ buffer->info[i].utf16_index () = chars_len;
+ if (likely (c <= 0xFFFFu))
+ textString[chars_len++] = c;
+ else if (unlikely (c > 0x10FFFFu))
+ textString[chars_len++] = 0xFFFDu;
+ else
+ {
+ textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
+ textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1));
+ }
+ }
+
+ ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
+ /* Need log_clusters to assign features. */
+ chars_len = 0;
+ for (unsigned int i = 0; i < buffer->len; i++)
+ {
+ hb_codepoint_t c = buffer->info[i].codepoint;
+ unsigned int cluster = buffer->info[i].cluster;
+ log_clusters[chars_len++] = cluster;
+ if (hb_in_range (c, 0x10000u, 0x10FFFFu))
+ log_clusters[chars_len++] = cluster; /* Surrogates. */
+ }
+
+ DWRITE_READING_DIRECTION readingDirection;
+ readingDirection = buffer->props.direction ?
+ DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
+ DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
+
+ /*
+ * There's an internal 16-bit limit on some things inside the analyzer,
+ * but we never attempt to shape a word longer than 64K characters
+ * in a single gfxShapedWord, so we cannot exceed that limit.
+ */
+ uint32_t textLength = chars_len;
+
+ TextAnalysis analysis (textString, textLength, nullptr, readingDirection);
+ TextAnalysis::Run *runHead;
+ HRESULT hr;
+ hr = analysis.GenerateResults (analyzer, &runHead);
+
+#define FAIL(...) \
+ HB_STMT_START { \
+ DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
+ return false; \
+ } HB_STMT_END
+
+ if (FAILED (hr))
+ FAIL ("Analyzer failed to generate results.");
+
+ uint32_t maxGlyphCount = 3 * textLength / 2 + 16;
+ uint32_t glyphCount;
+ bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
+
+ const wchar_t localeName[20] = {0};
+ if (buffer->props.language)
+ mbstowcs ((wchar_t*) localeName,
+ hb_language_to_string (buffer->props.language), 20);
+
+ /*
+ * Set up features.
+ */
+ static_assert ((sizeof (DWRITE_TYPOGRAPHIC_FEATURES) == sizeof (hb_ms_features_t)), "");
+ static_assert ((sizeof (DWRITE_FONT_FEATURE) == sizeof (hb_ms_feature_t)), "");
+ hb_vector_t<hb_ms_features_t *> range_features;
+ hb_vector_t<uint32_t> range_char_counts;
+
+ // https://github.com/harfbuzz/harfbuzz/pull/5114
+ // The data allocated by these two vectors are used by the above two, so they
+ // should remain alive as long as the above two are.
+ hb_vector_t<hb_ms_feature_t> feature_records;
+ hb_vector_t<hb_ms_range_record_t> range_records;
+ if (num_features)
+ {
+ if (hb_ms_setup_features (features, num_features, feature_records, range_records))
+ {
+ hb_ms_make_feature_ranges (feature_records,
+ range_records,
+ 0,
+ chars_len,
+ log_clusters,
+ range_features,
+ range_char_counts);
+ }
+ }
+
+ uint16_t* clusterMap;
+ clusterMap = new uint16_t[textLength];
+ DWRITE_SHAPING_TEXT_PROPERTIES* textProperties;
+ textProperties = new DWRITE_SHAPING_TEXT_PROPERTIES[textLength];
+
+retry_getglyphs:
+ uint16_t* glyphIndices = new uint16_t[maxGlyphCount];
+ DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties;
+ glyphProperties = new DWRITE_SHAPING_GLYPH_PROPERTIES[maxGlyphCount];
+
+ hr = analyzer->GetGlyphs (textString,
+ chars_len,
+ fontFace,
+ false,
+ isRightToLeft,
+ &runHead->mScript,
+ localeName,
+ nullptr,
+ (const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
+ range_char_counts.arrayZ,
+ range_features.length,
+ maxGlyphCount,
+ clusterMap,
+ textProperties,
+ glyphIndices,
+ glyphProperties,
+ &glyphCount);
+
+ if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
+ {
+ delete [] glyphIndices;
+ delete [] glyphProperties;
+
+ maxGlyphCount *= 2;
+
+ goto retry_getglyphs;
+ }
+ if (FAILED (hr))
+ FAIL ("Analyzer failed to get glyphs.");
+
+ float* glyphAdvances = new float[maxGlyphCount];
+ DWRITE_GLYPH_OFFSET* glyphOffsets = new DWRITE_GLYPH_OFFSET[maxGlyphCount];
+
+ /* The -2 in the following is to compensate for possible
+ * alignment needed after the WORD array. sizeof (WORD) == 2. */
+ unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
+ / (sizeof (WORD) +
+ sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES) +
+ sizeof (int) +
+ sizeof (DWRITE_GLYPH_OFFSET) +
+ sizeof (uint32_t));
+ ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
+
+#undef ALLOCATE_ARRAY
+
+ unsigned fontEmSize = font->face->get_upem ();
+
+ float x_mult = font->x_multf;
+ float y_mult = font->y_multf;
+
+ hr = analyzer->GetGlyphPlacements (textString,
+ clusterMap,
+ textProperties,
+ chars_len,
+ glyphIndices,
+ glyphProperties,
+ glyphCount,
+ fontFace,
+ fontEmSize,
+ false,
+ isRightToLeft,
+ &runHead->mScript,
+ localeName,
+ (const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
+ range_char_counts.arrayZ,
+ range_features.length,
+ glyphAdvances,
+ glyphOffsets);
+
+ if (FAILED (hr))
+ FAIL ("Analyzer failed to get glyph placements.");
+
+ /* Ok, we've got everything we need, now compose output buffer,
+ * very, *very*, carefully! */
+
+ /* Calculate visual-clusters. That's what we ship. */
+ for (unsigned int i = 0; i < glyphCount; i++)
+ vis_clusters[i] = (uint32_t) -1;
+ for (unsigned int i = 0; i < buffer->len; i++)
+ {
+ uint32_t *p =
+ &vis_clusters[log_clusters[buffer->info[i].utf16_index ()]];
+ *p = hb_min (*p, buffer->info[i].cluster);
+ }
+ for (unsigned int i = 1; i < glyphCount; i++)
+ if (vis_clusters[i] == (uint32_t) -1)
+ vis_clusters[i] = vis_clusters[i - 1];
+
+#undef utf16_index
+
+ if (unlikely (!buffer->ensure (glyphCount)))
+ FAIL ("Buffer in error");
+
+#undef FAIL
+
+ /* Set glyph infos */
+ buffer->len = 0;
+ for (unsigned int i = 0; i < glyphCount; i++)
+ {
+ hb_glyph_info_t *info = &buffer->info[buffer->len++];
+
+ info->codepoint = glyphIndices[i];
+ info->cluster = vis_clusters[i];
+
+ /* The rest is crap. Let's store position info there for now. */
+ info->mask = glyphAdvances[i];
+ info->var1.i32 = glyphOffsets[i].advanceOffset;
+ info->var2.i32 = glyphOffsets[i].ascenderOffset;
+ }
+
+ /* Set glyph positions */
+ buffer->clear_positions ();
+ for (unsigned int i = 0; i < glyphCount; i++)
+ {
+ hb_glyph_info_t *info = &buffer->info[i];
+ hb_glyph_position_t *pos = &buffer->pos[i];
+
+ /* TODO vertical */
+ pos->x_advance = round (x_mult * (int32_t) info->mask);
+ pos->x_offset = round (x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32));
+ pos->y_offset = round (y_mult * info->var2.i32);
+ }
+
+ if (isRightToLeft) hb_buffer_reverse (buffer);
+
+ buffer->clear_glyph_flags ();
+ buffer->unsafe_to_break ();
+
+ delete [] clusterMap;
+ delete [] glyphIndices;
+ delete [] textProperties;
+ delete [] glyphProperties;
+ delete [] glyphAdvances;
+ delete [] glyphOffsets;
+
+ /* Wow, done! */
+ return true;
+}
+
+
+#endif
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -26,15 +26,11 @@
#ifdef HAVE_DIRECTWRITE
-#include "hb-shaper-impl.hh"
+#include "hb-directwrite.hh"
-#include <dwrite_1.h>
-#include <dwrite_3.h>
+#include "hb-font.hh"
-#include "hb-directwrite.h"
-#include "hb-ms-feature-ranges.hh"
-
/**
* SECTION:hb-directwrite
* @title: hb-directwrite
@@ -44,124 +40,72 @@
* Functions for using HarfBuzz with DirectWrite fonts.
**/
-/* Declare object creator for dynamic support of DWRITE */
-typedef HRESULT (WINAPI *t_DWriteCreateFactory)(
- DWRITE_FACTORY_TYPE factoryType,
- REFIID iid,
- IUnknown **factory
-);
+static inline void free_static_directwrite_global ();
-
-/*
- * DirectWrite font stream helpers
- */
-
-// This is a font loader which provides only one font (unlike its original design).
-// For a better implementation which was also source of this
-// and DWriteFontFileStream, have a look at to NativeFontResourceDWrite.cpp in Mozilla
-class DWriteFontFileLoader : public IDWriteFontFileLoader
+static struct hb_directwrite_global_lazy_loader_t : hb_lazy_loader_t<hb_directwrite_global_t,
+ hb_directwrite_global_lazy_loader_t>
{
-private:
- IDWriteFontFileStream *mFontFileStream;
-public:
- DWriteFontFileLoader (IDWriteFontFileStream *fontFileStream)
- { mFontFileStream = fontFileStream; }
+ static hb_directwrite_global_t * create ()
+ {
+ hb_directwrite_global_t *global = new hb_directwrite_global_t;
- // IUnknown interface
- IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
- { return S_OK; }
- IFACEMETHOD_ (ULONG, AddRef) () { return 1; }
- IFACEMETHOD_ (ULONG, Release) () { return 1; }
+ if (unlikely (!global))
+ return nullptr;
+ if (unlikely (!global->success))
+ {
+ delete global;
+ return nullptr;
+ }
- // IDWriteFontFileLoader methods
- virtual HRESULT STDMETHODCALLTYPE
- CreateStreamFromKey (void const* fontFileReferenceKey,
- uint32_t fontFileReferenceKeySize,
- OUT IDWriteFontFileStream** fontFileStream)
- {
- *fontFileStream = mFontFileStream;
- return S_OK;
- }
+ hb_atexit (free_static_directwrite_global);
- virtual ~DWriteFontFileLoader() {}
-};
-
-class DWriteFontFileStream : public IDWriteFontFileStream
-{
-private:
- uint8_t *mData;
- uint32_t mSize;
-public:
- DWriteFontFileStream (uint8_t *aData, uint32_t aSize)
- {
- mData = aData;
- mSize = aSize;
+ return global;
}
-
- // IUnknown interface
- IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
- { return S_OK; }
- IFACEMETHOD_ (ULONG, AddRef) () { return 1; }
- IFACEMETHOD_ (ULONG, Release) () { return 1; }
-
- // IDWriteFontFileStream methods
- virtual HRESULT STDMETHODCALLTYPE
- ReadFileFragment (void const** fragmentStart,
- UINT64 fileOffset,
- UINT64 fragmentSize,
- OUT void** fragmentContext)
+ static void destroy (hb_directwrite_global_t *l)
{
- // We are required to do bounds checking.
- if (fileOffset + fragmentSize > mSize) return E_FAIL;
-
- // truncate the 64 bit fileOffset to size_t sized index into mData
- size_t index = static_cast<size_t> (fileOffset);
-
- // We should be alive for the duration of this.
- *fragmentStart = &mData[index];
- *fragmentContext = nullptr;
- return S_OK;
+ delete l;
}
-
- virtual void STDMETHODCALLTYPE
- ReleaseFileFragment (void* fragmentContext) {}
-
- virtual HRESULT STDMETHODCALLTYPE
- GetFileSize (OUT UINT64* fileSize)
+ static hb_directwrite_global_t * get_null ()
{
- *fileSize = mSize;
- return S_OK;
+ return nullptr;
}
+} static_directwrite_global;
- virtual HRESULT STDMETHODCALLTYPE
- GetLastWriteTime (OUT UINT64* lastWriteTime) { return E_NOTIMPL; }
- virtual ~DWriteFontFileStream() {}
-};
+static inline
+void free_static_directwrite_global ()
+{
+ static_directwrite_global.free_instance ();
+}
+hb_directwrite_global_t *
+get_directwrite_global ()
+{
+ return static_directwrite_global.get_unconst ();
+}
-/*
-* shaper face data
-*/
+DWriteFontFileStream::DWriteFontFileStream (hb_blob_t *blob)
+{
+ auto *global = get_directwrite_global ();
+ mLoader = global->fontFileLoader;
+ mRefCount.init ();
+ mLoader->AddRef ();
+ hb_blob_make_immutable (blob);
+ mBlob = hb_blob_reference (blob);
+ mData = (uint8_t *) hb_blob_get_data (blob, &mSize);
+ fontFileKey = mLoader->RegisterFontFileStream (this);
+}
-struct hb_directwrite_face_data_t
+DWriteFontFileStream::~DWriteFontFileStream()
{
- HMODULE dwrite_dll;
- IDWriteFactory *dwriteFactory;
- IDWriteFontFile *fontFile;
- DWriteFontFileStream *fontFileStream;
- DWriteFontFileLoader *fontFileLoader;
- IDWriteFontFace *fontFace;
- hb_blob_t *faceBlob;
-};
+ mLoader->UnregisterFontFileStream (fontFileKey);
+ mLoader->Release ();
+ hb_blob_destroy (mBlob);
+}
-hb_directwrite_face_data_t *
-_hb_directwrite_shaper_face_data_create (hb_face_t *face)
+IDWriteFontFace *
+dw_face_create (hb_blob_t *blob, unsigned index)
{
- hb_directwrite_face_data_t *data = new hb_directwrite_face_data_t;
- if (unlikely (!data))
- return nullptr;
-
#define FAIL(...) \
HB_STMT_START { \
DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
@@ -168,50 +112,18 @@
return nullptr; \
} HB_STMT_END
- data->dwrite_dll = LoadLibrary (TEXT ("DWRITE"));
- if (unlikely (!data->dwrite_dll))
- FAIL ("Cannot find DWrite.DLL");
+ auto *global = get_directwrite_global ();
+ if (unlikely (!global))
+ FAIL ("Couldn't load DirectWrite!");
- t_DWriteCreateFactory p_DWriteCreateFactory;
+ DWriteFontFileStream *fontFileStream = new DWriteFontFileStream (blob);
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-function-type"
-#endif
+ IDWriteFontFile *fontFile;
+ auto hr = global->dwriteFactory->CreateCustomFontFileReference (&fontFileStream->fontFileKey, sizeof (fontFileStream->fontFileKey),
+ global->fontFileLoader, &fontFile);
- p_DWriteCreateFactory = (t_DWriteCreateFactory)
- GetProcAddress (data->dwrite_dll, "DWriteCreateFactory");
+ fontFileStream->Release ();
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-
- if (unlikely (!p_DWriteCreateFactory))
- FAIL ("Cannot find DWriteCreateFactory().");
-
- HRESULT hr;
-
- // TODO: factory and fontFileLoader should be cached separately
- IDWriteFactory* dwriteFactory;
- hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
- (IUnknown**) &dwriteFactory);
-
- if (unlikely (hr != S_OK))
- FAIL ("Failed to run DWriteCreateFactory().");
-
- hb_blob_t *blob = hb_face_reference_blob (face);
- DWriteFontFileStream *fontFileStream;
- fontFileStream = new DWriteFontFileStream ((uint8_t *) hb_blob_get_data (blob, nullptr),
- hb_blob_get_length (blob));
-
- DWriteFontFileLoader *fontFileLoader = new DWriteFontFileLoader (fontFileStream);
- dwriteFactory->RegisterFontFileLoader (fontFileLoader);
-
- IDWriteFontFile *fontFile;
- uint64_t fontFileKey = 0;
- hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey),
- fontFileLoader, &fontFile);
-
if (FAILED (hr))
FAIL ("Failed to load font file from data!");
@@ -221,585 +133,19 @@
uint32_t numberOfFaces;
hr = fontFile->Analyze (&isSupported, &fileType, &faceType, &numberOfFaces);
if (FAILED (hr) || !isSupported)
+ {
+ fontFile->Release ();
FAIL ("Font file is not supported.");
-
-#undef FAIL
-
- IDWriteFontFace *fontFace;
- dwriteFactory->CreateFontFace (faceType, 1, &fontFile, 0,
- DWRITE_FONT_SIMULATIONS_NONE, &fontFace);
-
- data->dwriteFactory = dwriteFactory;
- data->fontFile = fontFile;
- data->fontFileStream = fontFileStream;
- data->fontFileLoader = fontFileLoader;
- data->fontFace = fontFace;
- data->faceBlob = blob;
-
- return data;
-}
-
-void
-_hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
-{
- if (data->fontFace)
- data->fontFace->Release ();
- if (data->fontFile)
- data->fontFile->Release ();
- if (data->dwriteFactory)
- {
- if (data->fontFileLoader)
- data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader);
- data->dwriteFactory->Release ();
}
- delete data->fontFileLoader;
- delete data->fontFileStream;
- hb_blob_destroy (data->faceBlob);
- if (data->dwrite_dll)
- FreeLibrary (data->dwrite_dll);
- delete data;
-}
-
-/*
- * shaper font data
- */
-
-struct hb_directwrite_font_data_t {};
-
-hb_directwrite_font_data_t *
-_hb_directwrite_shaper_font_data_create (hb_font_t *font)
-{
- return (hb_directwrite_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
-{
- if (data != HB_SHAPER_DATA_SUCCEEDED)
- ((IDWriteFont *) (const void *) data)->Release();
-}
-
-
-// Most of TextAnalysis is originally written by Bas Schouten for Mozilla project
-// but now is relicensed to MIT for HarfBuzz use
-class TextAnalysis : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink
-{
-public:
-
- IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
- { return S_OK; }
- IFACEMETHOD_ (ULONG, AddRef) () { return 1; }
- IFACEMETHOD_ (ULONG, Release) () { return 1; }
-
- // A single contiguous run of characters containing the same analysis
- // results.
- struct Run
- {
- uint32_t mTextStart; // starting text position of this run
- uint32_t mTextLength; // number of contiguous code units covered
- uint32_t mGlyphStart; // starting glyph in the glyphs array
- uint32_t mGlyphCount; // number of glyphs associated with this run
- // text
- DWRITE_SCRIPT_ANALYSIS mScript;
- uint8_t mBidiLevel;
- bool mIsSideways;
-
- bool ContainsTextPosition (uint32_t aTextPosition) const
- {
- return aTextPosition >= mTextStart &&
- aTextPosition < mTextStart + mTextLength;
- }
-
- Run *nextRun;
- };
-
-public:
- TextAnalysis (const wchar_t* text, uint32_t textLength,
- const wchar_t* localeName, DWRITE_READING_DIRECTION readingDirection)
- : mTextLength (textLength), mText (text), mLocaleName (localeName),
- mReadingDirection (readingDirection), mCurrentRun (nullptr) {}
- ~TextAnalysis ()
- {
- // delete runs, except mRunHead which is part of the TextAnalysis object
- for (Run *run = mRunHead.nextRun; run;)
- {
- Run *origRun = run;
- run = run->nextRun;
- delete origRun;
- }
- }
-
- STDMETHODIMP
- GenerateResults (IDWriteTextAnalyzer* textAnalyzer, Run **runHead)
- {
- // Analyzes the text using the script analyzer and returns
- // the result as a series of runs.
-
- HRESULT hr = S_OK;
-
- // Initially start out with one result that covers the entire range.
- // This result will be subdivided by the analysis processes.
- mRunHead.mTextStart = 0;
- mRunHead.mTextLength = mTextLength;
- mRunHead.mBidiLevel =
- (mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
- mRunHead.nextRun = nullptr;
- mCurrentRun = &mRunHead;
-
- // Call each of the analyzers in sequence, recording their results.
- if (SUCCEEDED (hr = textAnalyzer->AnalyzeScript (this, 0, mTextLength, this)))
- *runHead = &mRunHead;
-
- return hr;
- }
-
- // IDWriteTextAnalysisSource implementation
-
- IFACEMETHODIMP
- GetTextAtPosition (uint32_t textPosition,
- OUT wchar_t const** textString,
- OUT uint32_t* textLength)
- {
- if (textPosition >= mTextLength)
- {
- // No text at this position, valid query though.
- *textString = nullptr;
- *textLength = 0;
- }
- else
- {
- *textString = mText + textPosition;
- *textLength = mTextLength - textPosition;
- }
- return S_OK;
- }
-
- IFACEMETHODIMP
- GetTextBeforePosition (uint32_t textPosition,
- OUT wchar_t const** textString,
- OUT uint32_t* textLength)
- {
- if (textPosition == 0 || textPosition > mTextLength)
- {
- // Either there is no text before here (== 0), or this
- // is an invalid position. The query is considered valid though.
- *textString = nullptr;
- *textLength = 0;
- }
- else
- {
- *textString = mText;
- *textLength = textPosition;
- }
- return S_OK;
- }
-
- IFACEMETHODIMP_ (DWRITE_READING_DIRECTION)
- GetParagraphReadingDirection () { return mReadingDirection; }
-
- IFACEMETHODIMP GetLocaleName (uint32_t textPosition, uint32_t* textLength,
- wchar_t const** localeName)
- { return S_OK; }
-
- IFACEMETHODIMP
- GetNumberSubstitution (uint32_t textPosition,
- OUT uint32_t* textLength,
- OUT IDWriteNumberSubstitution** numberSubstitution)
- {
- // We do not support number substitution.
- *numberSubstitution = nullptr;
- *textLength = mTextLength - textPosition;
-
- return S_OK;
- }
-
- // IDWriteTextAnalysisSink implementation
-
- IFACEMETHODIMP
- SetScriptAnalysis (uint32_t textPosition, uint32_t textLength,
- DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis)
- {
- SetCurrentRun (textPosition);
- SplitCurrentRun (textPosition);
- while (textLength > 0)
- {
- Run *run = FetchNextRun (&textLength);
- run->mScript = *scriptAnalysis;
- }
-
- return S_OK;
- }
-
- IFACEMETHODIMP
- SetLineBreakpoints (uint32_t textPosition,
- uint32_t textLength,
- const DWRITE_LINE_BREAKPOINT* lineBreakpoints)
- { return S_OK; }
-
- IFACEMETHODIMP SetBidiLevel (uint32_t textPosition, uint32_t textLength,
- uint8_t explicitLevel, uint8_t resolvedLevel)
- { return S_OK; }
-
- IFACEMETHODIMP
- SetNumberSubstitution (uint32_t textPosition, uint32_t textLength,
- IDWriteNumberSubstitution* numberSubstitution)
- { return S_OK; }
-
-protected:
- Run *FetchNextRun (IN OUT uint32_t* textLength)
- {
- // Used by the sink setters, this returns a reference to the next run.
- // Position and length are adjusted to now point after the current run
- // being returned.
-
- Run *origRun = mCurrentRun;
- // Split the tail if needed (the length remaining is less than the
- // current run's size).
- if (*textLength < mCurrentRun->mTextLength)
- SplitCurrentRun (mCurrentRun->mTextStart + *textLength);
- else
- // Just advance the current run.
- mCurrentRun = mCurrentRun->nextRun;
- *textLength -= origRun->mTextLength;
-
- // Return a reference to the run that was just current.
- return origRun;
- }
-
- void SetCurrentRun (uint32_t textPosition)
- {
- // Move the current run to the given position.
- // Since the analyzers generally return results in a forward manner,
- // this will usually just return early. If not, find the
- // corresponding run for the text position.
-
- if (mCurrentRun && mCurrentRun->ContainsTextPosition (textPosition))
- return;
-
- for (Run *run = &mRunHead; run; run = run->nextRun)
- if (run->ContainsTextPosition (textPosition))
- {
- mCurrentRun = run;
- return;
- }
- assert (0); // We should always be able to find the text position in one of our runs
- }
-
- void SplitCurrentRun (uint32_t splitPosition)
- {
- if (!mCurrentRun)
- {
- assert (0); // SplitCurrentRun called without current run
- // Shouldn't be calling this when no current run is set!
- return;
- }
- // Split the current run.
- if (splitPosition <= mCurrentRun->mTextStart)
- {
- // No need to split, already the start of a run
- // or before it. Usually the first.
- return;
- }
- Run *newRun = new Run;
-
- *newRun = *mCurrentRun;
-
- // Insert the new run in our linked list.
- newRun->nextRun = mCurrentRun->nextRun;
- mCurrentRun->nextRun = newRun;
-
- // Adjust runs' text positions and lengths.
- uint32_t splitPoint = splitPosition - mCurrentRun->mTextStart;
- newRun->mTextStart += splitPoint;
- newRun->mTextLength -= splitPoint;
- mCurrentRun->mTextLength = splitPoint;
- mCurrentRun = newRun;
- }
-
-protected:
- // Input
- // (weak references are fine here, since this class is a transient
- // stack-based helper that doesn't need to copy data)
- uint32_t mTextLength;
- const wchar_t* mText;
- const wchar_t* mLocaleName;
- DWRITE_READING_DIRECTION mReadingDirection;
-
- // Current processing state.
- Run *mCurrentRun;
-
- // Output is a list of runs starting here
- Run mRunHead;
-};
-
-/*
- * shaper
- */
-
-hb_bool_t
-_hb_directwrite_shape (hb_shape_plan_t *shape_plan,
- hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features)
-{
- hb_face_t *face = font->face;
- const hb_directwrite_face_data_t *face_data = face->data.directwrite;
- IDWriteFactory *dwriteFactory = face_data->dwriteFactory;
- IDWriteFontFace *fontFace = face_data->fontFace;
-
- IDWriteTextAnalyzer* analyzer;
- dwriteFactory->CreateTextAnalyzer (&analyzer);
-
- unsigned int scratch_size;
- hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
-#define ALLOCATE_ARRAY(Type, name, len) \
- Type *name = (Type *) scratch; \
- do { \
- unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
- assert (_consumed <= scratch_size); \
- scratch += _consumed; \
- scratch_size -= _consumed; \
- } while (0)
-
-#define utf16_index() var1.u32
-
- ALLOCATE_ARRAY (wchar_t, textString, buffer->len * 2);
-
- unsigned int chars_len = 0;
- for (unsigned int i = 0; i < buffer->len; i++)
- {
- hb_codepoint_t c = buffer->info[i].codepoint;
- buffer->info[i].utf16_index () = chars_len;
- if (likely (c <= 0xFFFFu))
- textString[chars_len++] = c;
- else if (unlikely (c > 0x10FFFFu))
- textString[chars_len++] = 0xFFFDu;
- else
- {
- textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
- textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1));
- }
- }
-
- ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
- /* Need log_clusters to assign features. */
- chars_len = 0;
- for (unsigned int i = 0; i < buffer->len; i++)
- {
- hb_codepoint_t c = buffer->info[i].codepoint;
- unsigned int cluster = buffer->info[i].cluster;
- log_clusters[chars_len++] = cluster;
- if (hb_in_range (c, 0x10000u, 0x10FFFFu))
- log_clusters[chars_len++] = cluster; /* Surrogates. */
- }
-
- DWRITE_READING_DIRECTION readingDirection;
- readingDirection = buffer->props.direction ?
- DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
- DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
-
- /*
- * There's an internal 16-bit limit on some things inside the analyzer,
- * but we never attempt to shape a word longer than 64K characters
- * in a single gfxShapedWord, so we cannot exceed that limit.
- */
- uint32_t textLength = chars_len;
-
- TextAnalysis analysis (textString, textLength, nullptr, readingDirection);
- TextAnalysis::Run *runHead;
- HRESULT hr;
- hr = analysis.GenerateResults (analyzer, &runHead);
-
-#define FAIL(...) \
- HB_STMT_START { \
- DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
- return false; \
- } HB_STMT_END
-
- if (FAILED (hr))
- FAIL ("Analyzer failed to generate results.");
-
- uint32_t maxGlyphCount = 3 * textLength / 2 + 16;
- uint32_t glyphCount;
- bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
-
- const wchar_t localeName[20] = {0};
- if (buffer->props.language)
- mbstowcs ((wchar_t*) localeName,
- hb_language_to_string (buffer->props.language), 20);
-
- /*
- * Set up features.
- */
- static_assert ((sizeof (DWRITE_TYPOGRAPHIC_FEATURES) == sizeof (hb_ms_features_t)), "");
- static_assert ((sizeof (DWRITE_FONT_FEATURE) == sizeof (hb_ms_feature_t)), "");
- hb_vector_t<hb_ms_features_t *> range_features;
- hb_vector_t<uint32_t> range_char_counts;
- if (num_features)
- {
- hb_vector_t<hb_ms_feature_t> feature_records;
- hb_vector_t<hb_ms_range_record_t> range_records;
- if (hb_ms_setup_features (features, num_features, feature_records, range_records))
- hb_ms_make_feature_ranges (feature_records,
- range_records,
- 0,
- chars_len,
- log_clusters,
- range_features,
- range_char_counts);
- }
-
- uint16_t* clusterMap;
- clusterMap = new uint16_t[textLength];
- DWRITE_SHAPING_TEXT_PROPERTIES* textProperties;
- textProperties = new DWRITE_SHAPING_TEXT_PROPERTIES[textLength];
-
-retry_getglyphs:
- uint16_t* glyphIndices = new uint16_t[maxGlyphCount];
- DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties;
- glyphProperties = new DWRITE_SHAPING_GLYPH_PROPERTIES[maxGlyphCount];
-
- hr = analyzer->GetGlyphs (textString,
- chars_len,
- fontFace,
- false,
- isRightToLeft,
- &runHead->mScript,
- localeName,
- nullptr,
- (const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
- range_char_counts.arrayZ,
- range_features.length,
- maxGlyphCount,
- clusterMap,
- textProperties,
- glyphIndices,
- glyphProperties,
- &glyphCount);
-
- if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
- {
- delete [] glyphIndices;
- delete [] glyphProperties;
-
- maxGlyphCount *= 2;
-
- goto retry_getglyphs;
- }
- if (FAILED (hr))
- FAIL ("Analyzer failed to get glyphs.");
-
- float* glyphAdvances = new float[maxGlyphCount];
- DWRITE_GLYPH_OFFSET* glyphOffsets = new DWRITE_GLYPH_OFFSET[maxGlyphCount];
-
- /* The -2 in the following is to compensate for possible
- * alignment needed after the WORD array. sizeof (WORD) == 2. */
- unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
- / (sizeof (WORD) +
- sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES) +
- sizeof (int) +
- sizeof (DWRITE_GLYPH_OFFSET) +
- sizeof (uint32_t));
- ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
-
-#undef ALLOCATE_ARRAY
-
- int fontEmSize = font->face->get_upem ();
- if (fontEmSize < 0) fontEmSize = -fontEmSize;
-
- if (fontEmSize < 0) fontEmSize = -fontEmSize;
- double x_mult = (double) font->x_scale / fontEmSize;
- double y_mult = (double) font->y_scale / fontEmSize;
-
- hr = analyzer->GetGlyphPlacements (textString,
- clusterMap,
- textProperties,
- chars_len,
- glyphIndices,
- glyphProperties,
- glyphCount,
- fontFace,
- fontEmSize,
- false,
- isRightToLeft,
- &runHead->mScript,
- localeName,
- (const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
- range_char_counts.arrayZ,
- range_features.length,
- glyphAdvances,
- glyphOffsets);
-
- if (FAILED (hr))
- FAIL ("Analyzer failed to get glyph placements.");
-
- /* Ok, we've got everything we need, now compose output buffer,
- * very, *very*, carefully! */
-
- /* Calculate visual-clusters. That's what we ship. */
- for (unsigned int i = 0; i < glyphCount; i++)
- vis_clusters[i] = (uint32_t) -1;
- for (unsigned int i = 0; i < buffer->len; i++)
- {
- uint32_t *p =
- &vis_clusters[log_clusters[buffer->info[i].utf16_index ()]];
- *p = hb_min (*p, buffer->info[i].cluster);
- }
- for (unsigned int i = 1; i < glyphCount; i++)
- if (vis_clusters[i] == (uint32_t) -1)
- vis_clusters[i] = vis_clusters[i - 1];
-
-#undef utf16_index
-
- if (unlikely (!buffer->ensure (glyphCount)))
- FAIL ("Buffer in error");
-
#undef FAIL
- /* Set glyph infos */
- buffer->len = 0;
- for (unsigned int i = 0; i < glyphCount; i++)
- {
- hb_glyph_info_t *info = &buffer->info[buffer->len++];
+ IDWriteFontFace *fontFace = nullptr;
+ global->dwriteFactory->CreateFontFace (faceType, 1, &fontFile, index,
+ DWRITE_FONT_SIMULATIONS_NONE, &fontFace);
+ fontFile->Release ();
- info->codepoint = glyphIndices[i];
- info->cluster = vis_clusters[i];
-
- /* The rest is crap. Let's store position info there for now. */
- info->mask = glyphAdvances[i];
- info->var1.i32 = glyphOffsets[i].advanceOffset;
- info->var2.i32 = glyphOffsets[i].ascenderOffset;
- }
-
- /* Set glyph positions */
- buffer->clear_positions ();
- for (unsigned int i = 0; i < glyphCount; i++)
- {
- hb_glyph_info_t *info = &buffer->info[i];
- hb_glyph_position_t *pos = &buffer->pos[i];
-
- /* TODO vertical */
- pos->x_advance = x_mult * (int32_t) info->mask;
- pos->x_offset = x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32);
- pos->y_offset = y_mult * info->var2.i32;
- }
-
- if (isRightToLeft) hb_buffer_reverse (buffer);
-
- buffer->clear_glyph_flags ();
- buffer->unsafe_to_break ();
-
- delete [] clusterMap;
- delete [] glyphIndices;
- delete [] textProperties;
- delete [] glyphProperties;
- delete [] glyphAdvances;
- delete [] glyphOffsets;
-
- /* Wow, done! */
- return true;
+ return fontFace;
}
struct _hb_directwrite_font_table_context {
@@ -823,8 +169,8 @@
uint32_t length;
void *table_context;
BOOL exists;
- if (!dw_face || FAILED (dw_face->TryGetFontTable (hb_uint32_swap (tag), &data,
- &length, &table_context, &exists)))
+ if (FAILED (dw_face->TryGetFontTable (hb_uint32_swap (tag), &data,
+ &length, &table_context, &exists)))
return nullptr;
if (!data || !exists || !length)
@@ -834,6 +180,11 @@
}
_hb_directwrite_font_table_context *context = (_hb_directwrite_font_table_context *) hb_malloc (sizeof (_hb_directwrite_font_table_context));
+ if (unlikely (!context))
+ {
+ dw_face->ReleaseFontTable (table_context);
+ return nullptr;
+ }
context->face = dw_face;
context->table_context = table_context;
@@ -844,8 +195,7 @@
static void
_hb_directwrite_face_release (void *data)
{
- if (data)
- ((IDWriteFontFace *) data)->Release ();
+ ((IDWriteFontFace *) data)->Release ();
}
/**
@@ -861,13 +211,85 @@
hb_face_t *
hb_directwrite_face_create (IDWriteFontFace *dw_face)
{
- if (dw_face)
- dw_face->AddRef ();
- return hb_face_create_for_tables (_hb_directwrite_reference_table, dw_face,
- _hb_directwrite_face_release);
+ if (!dw_face)
+ return hb_face_get_empty ();
+
+ dw_face->AddRef ();
+ hb_face_t *face = hb_face_create_for_tables (_hb_directwrite_reference_table,
+ dw_face,
+ _hb_directwrite_face_release);
+
+ hb_face_set_index (face, dw_face->GetIndex ());
+ hb_face_set_glyph_count (face, dw_face->GetGlyphCount ());
+
+ return face;
}
/**
+ * hb_directwrite_face_create_from_file_or_fail:
+ * @file_name: A font filename
+ * @index: The index of the face within the file
+ *
+ * Creates an #hb_face_t face object from the specified
+ * font file and face index.
+ *
+ * This is similar in functionality to hb_face_create_from_file_or_fail(),
+ * but uses the DirectWrite library for loading the font file.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * no face is found at the specified index or the file cannot be read.
+ *
+ * Since: 11.0.0
+ */
+hb_face_t *
+hb_directwrite_face_create_from_file_or_fail (const char *file_name,
+ unsigned int index)
+{
+ auto *blob = hb_blob_create_from_file_or_fail (file_name);
+ if (unlikely (!blob))
+ return nullptr;
+
+ return hb_directwrite_face_create_from_blob_or_fail (blob, index);
+}
+
+/**
+ * hb_directwrite_face_create_from_blob_or_fail:
+ * @blob: A blob containing the font data
+ * @index: The index of the face within the blob
+ *
+ * Creates an #hb_face_t face object from the specified
+ * blob and face index.
+ *
+ * This is similar in functionality to hb_face_create_from_blob_or_fail(),
+ * but uses the DirectWrite library for loading the font data.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * no face is found at the specified index or the blob cannot be read.
+ *
+ * Since: 11.0.0
+ */
+HB_EXTERN hb_face_t *
+hb_directwrite_face_create_from_blob_or_fail (hb_blob_t *blob,
+ unsigned int index)
+{
+ IDWriteFontFace *dw_face = dw_face_create (blob, index);
+ if (unlikely (!dw_face))
+ return nullptr;
+
+ hb_face_t *face = hb_directwrite_face_create (dw_face);
+ if (unlikely (hb_object_is_immutable (face)))
+ {
+ dw_face->Release ();
+ return face;
+ }
+
+ /* Let there be dragons here... */
+ face->data.directwrite.cmpexch (nullptr, (hb_directwrite_face_data_t *) dw_face);
+
+ return face;
+}
+
+/**
* hb_directwrite_face_get_dw_font_face:
* @face: a #hb_face_t object
*
@@ -880,7 +302,7 @@
IDWriteFontFace *
hb_directwrite_face_get_dw_font_face (hb_face_t *face)
{
- return face->data.directwrite->fontFace;
+ return (IDWriteFontFace *) (const void *) face->data.directwrite;
}
#ifndef HB_DISABLE_DEPRECATED
@@ -906,29 +328,25 @@
/**
* hb_directwrite_font_create:
- * @dw_font: a DirectWrite IDWriteFont object.
+ * @dw_face: a DirectWrite IDWriteFontFace object.
*
- * Constructs a new font object from the specified DirectWrite IDWriteFont.
+ * Constructs a new font object from the specified DirectWrite IDWriteFontFace.
*
* Return value: #hb_font_t object corresponding to the given input
*
- * Since: 10.3.0
+ * Since: 11.0.0
**/
hb_font_t *
-hb_directwrite_font_create (IDWriteFont *dw_font)
+hb_directwrite_font_create (IDWriteFontFace *dw_face)
{
- 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;
+ return font;
/* Copy font variations */
if (SUCCEEDED (dw_face->QueryInterface (__uuidof (IDWriteFontFace5), (void**) &dw_face5)))
@@ -945,7 +363,7 @@
{
for (uint32_t i = 0; i < count; ++i)
{
- hb_tag_t tag = values[i].axisTag;
+ hb_tag_t tag = hb_uint32_swap (values[i].axisTag);
float value = values[i].value;
vars[i] = {tag, value};
}
@@ -956,28 +374,45 @@
dw_face5->Release ();
}
- dw_font->AddRef ();
- font->data.directwrite.cmpexch (nullptr, (hb_directwrite_font_data_t *) dw_font);
+ /* Let there be dragons here... */
+ dw_face->AddRef ();
+ font->data.directwrite.cmpexch (nullptr, (hb_directwrite_font_data_t *) dw_face);
-done:
- dw_face->Release ();
return font;
}
/**
+* hb_directwrite_font_get_dw_font_face:
+* @font: a #hb_font_t object
+*
+* Gets the DirectWrite IDWriteFontFace associated with @font.
+*
+* Return value: DirectWrite IDWriteFontFace object corresponding to the given input
+*
+* Since: 11.0.0
+**/
+IDWriteFontFace *
+hb_directwrite_font_get_dw_font_face (hb_font_t *font)
+{
+ return (IDWriteFontFace *) (const void *) font->data.directwrite;
+}
+
+
+/**
* hb_directwrite_font_get_dw_font:
* @font: a #hb_font_t object
*
-* Gets the DirectWrite IDWriteFont associated with @font.
+* Deprecated.
*
-* Return value: DirectWrite IDWriteFont object corresponding to the given input
+* Return value: Returns `NULL`.
*
* Since: 10.3.0
+* Deprecated: 11.0.0:
**/
IDWriteFont *
hb_directwrite_font_get_dw_font (hb_font_t *font)
{
- return (IDWriteFont *) (const void *) font->data.directwrite;
+ return nullptr;
}
#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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -27,20 +27,33 @@
#include "hb.h"
+#include <dwrite_3.h>
+
HB_BEGIN_DECLS
HB_EXTERN hb_face_t *
hb_directwrite_face_create (IDWriteFontFace *dw_face);
+HB_EXTERN hb_face_t *
+hb_directwrite_face_create_from_file_or_fail (const char *file_name,
+ unsigned int index);
+
+HB_EXTERN hb_face_t *
+hb_directwrite_face_create_from_blob_or_fail (hb_blob_t *blob,
+ unsigned int index);
+
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_directwrite_font_create (IDWriteFontFace *dw_face);
-HB_EXTERN IDWriteFont *
-hb_directwrite_font_get_dw_font (hb_font_t *font);
+HB_EXTERN IDWriteFontFace *
+hb_directwrite_font_get_dw_font_face (hb_font_t *font);
+HB_EXTERN void
+hb_directwrite_font_set_funcs (hb_font_t *font);
+
#ifndef HB_DISABLE_DEPRECATED
HB_DEPRECATED_FOR (hb_directwrite_face_get_dw_font_face)
@@ -47,6 +60,10 @@
HB_EXTERN IDWriteFontFace *
hb_directwrite_face_get_font_face (hb_face_t *face);
+HB_DEPRECATED
+HB_EXTERN IDWriteFont *
+hb_directwrite_font_get_dw_font (hb_font_t *font);
+
#endif
HB_END_DECLS
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.hh (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,243 @@
+/*
+ * 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_DIRECTWRITE_HH
+#define HB_DIRECTWRITE_HH
+
+#include "hb.hh"
+
+#include "hb-directwrite.h"
+
+#include "hb-mutex.hh"
+#include "hb-map.hh"
+
+/*
+ * DirectWrite font stream helpers
+ */
+
+// Have a look at to NativeFontResourceDWrite.cpp in Mozilla
+
+
+/* Declare object creator for dynamic support of DWRITE */
+typedef HRESULT (WINAPI *t_DWriteCreateFactory)(
+ DWRITE_FACTORY_TYPE factoryType,
+ REFIID iid,
+ IUnknown **factory
+);
+
+class DWriteFontFileLoader : public IDWriteFontFileLoader
+{
+private:
+ hb_reference_count_t mRefCount;
+ hb_mutex_t mutex;
+ hb_hashmap_t<uint64_t, IDWriteFontFileStream *> mFontStreams;
+ uint64_t mNextFontFileKey = 0;
+public:
+ DWriteFontFileLoader ()
+ {
+ mRefCount.init ();
+ }
+
+ uint64_t RegisterFontFileStream (IDWriteFontFileStream *fontFileStream)
+ {
+ fontFileStream->AddRef ();
+ auto lock = hb_lock_t (mutex);
+ mFontStreams.set (mNextFontFileKey, fontFileStream);
+ return mNextFontFileKey++;
+ }
+ void UnregisterFontFileStream (uint64_t fontFileKey)
+ {
+ auto lock = hb_lock_t (mutex);
+ IDWriteFontFileStream *stream = mFontStreams.get (fontFileKey);
+ if (stream)
+ {
+ mFontStreams.del (fontFileKey);
+ stream->Release ();
+ }
+ }
+
+ // IUnknown interface
+ IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
+ { return S_OK; }
+ IFACEMETHOD_ (ULONG, AddRef) ()
+ {
+ return mRefCount.inc () + 1;
+ }
+ IFACEMETHOD_ (ULONG, Release) ()
+ {
+ signed refCount = mRefCount.dec () - 1;
+ assert (refCount >= 0);
+ if (refCount)
+ return refCount;
+ delete this;
+ return 0;
+ }
+
+ // IDWriteFontFileLoader methods
+ virtual HRESULT STDMETHODCALLTYPE
+ CreateStreamFromKey (void const* fontFileReferenceKey,
+ uint32_t fontFileReferenceKeySize,
+ OUT IDWriteFontFileStream** fontFileStream)
+ {
+ if (fontFileReferenceKeySize != sizeof (uint64_t))
+ return E_INVALIDARG;
+ uint64_t fontFileKey = * (uint64_t *) fontFileReferenceKey;
+ IDWriteFontFileStream *stream = mFontStreams.get (fontFileKey);
+ if (!stream)
+ return E_FAIL;
+ stream->AddRef ();
+ *fontFileStream = stream;
+ return S_OK;
+ }
+
+ virtual ~DWriteFontFileLoader()
+ {
+ for (auto v : mFontStreams.values ())
+ v->Release ();
+ }
+};
+
+class DWriteFontFileStream : public IDWriteFontFileStream
+{
+private:
+ hb_reference_count_t mRefCount;
+ hb_blob_t *mBlob;
+ uint8_t *mData;
+ unsigned mSize;
+ DWriteFontFileLoader *mLoader;
+public:
+ uint64_t fontFileKey;
+public:
+ DWriteFontFileStream (hb_blob_t *blob);
+
+ // IUnknown interface
+ IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
+ { return S_OK; }
+ IFACEMETHOD_ (ULONG, AddRef) ()
+ {
+ return mRefCount.inc () + 1;
+ }
+ IFACEMETHOD_ (ULONG, Release) ()
+ {
+ signed refCount = mRefCount.dec () - 1;
+ assert (refCount >= 0);
+ if (refCount)
+ return refCount;
+ delete this;
+ return 0;
+ }
+
+ // IDWriteFontFileStream methods
+ virtual HRESULT STDMETHODCALLTYPE
+ ReadFileFragment (void const** fragmentStart,
+ UINT64 fileOffset,
+ UINT64 fragmentSize,
+ OUT void** fragmentContext)
+ {
+ // We are required to do bounds checking.
+ if (fileOffset + fragmentSize > mSize) return E_FAIL;
+
+ // truncate the 64 bit fileOffset to size_t sized index into mData
+ size_t index = static_cast<size_t> (fileOffset);
+
+ // We should be alive for the duration of this.
+ *fragmentStart = &mData[index];
+ *fragmentContext = nullptr;
+ return S_OK;
+ }
+
+ virtual void STDMETHODCALLTYPE
+ ReleaseFileFragment (void* fragmentContext) {}
+
+ virtual HRESULT STDMETHODCALLTYPE
+ GetFileSize (OUT UINT64* fileSize)
+ {
+ *fileSize = mSize;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE
+ GetLastWriteTime (OUT UINT64* lastWriteTime) { return E_NOTIMPL; }
+
+ virtual ~DWriteFontFileStream();
+};
+
+struct hb_directwrite_global_t
+{
+ hb_directwrite_global_t ()
+ {
+ dwrite_dll = LoadLibraryW (L"DWrite.dll");
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
+
+ t_DWriteCreateFactory p_DWriteCreateFactory = (t_DWriteCreateFactory)
+ GetProcAddress (dwrite_dll, "DWriteCreateFactory");
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+ if (unlikely (!p_DWriteCreateFactory))
+ return;
+
+ HRESULT hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
+ (IUnknown**) &dwriteFactory);
+
+ if (unlikely (hr != S_OK))
+ return;
+
+ fontFileLoader = new DWriteFontFileLoader ();
+ dwriteFactory->RegisterFontFileLoader (fontFileLoader);
+
+ success = true;
+ }
+ ~hb_directwrite_global_t ()
+ {
+ if (fontFileLoader)
+ fontFileLoader->Release ();
+ if (dwriteFactory)
+ dwriteFactory->Release ();
+ if (dwrite_dll)
+ FreeLibrary (dwrite_dll);
+ }
+
+ bool success = false;
+ HMODULE dwrite_dll;
+ IDWriteFactory *dwriteFactory;
+ DWriteFontFileLoader *fontFileLoader;
+};
+
+
+HB_INTERNAL hb_directwrite_global_t *
+get_directwrite_global ();
+
+HB_INTERNAL IDWriteFontFace *
+dw_face_create (hb_blob_t *blob, unsigned index);
+
+
+#endif /* HB_DIRECTWRITE_HH */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.h 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -41,9 +41,16 @@
* @path_start_y: Y component of the start of current path
* @current_x: X component of current point
* @current_y: Y component of current point
+ * @slant_xy: (Since: 11.0.0): Slanting factor for synthetic oblique
*
* Current drawing state.
*
+ * The @slant_xy is a slanting factor for synthetic oblique. If the font's
+ * oblique angle is not 0, this factor is used to slant the drawing. For
+ * fonts with uniform x and y scales, this factor is calculated as
+ * tan(oblique_angle). For fonts with non-uniform scales, this factor is
+ * calculated as tan(oblique_angle) * x_scale / y_scale, or 0 if y_scale is 0.
+ *
* Since: 4.0.0
**/
typedef struct hb_draw_state_t {
@@ -55,6 +62,8 @@
float current_x;
float current_y;
+ float slant_xy;
+
/*< private >*/
hb_var_num_t reserved1;
hb_var_num_t reserved2;
@@ -62,7 +71,6 @@
hb_var_num_t reserved4;
hb_var_num_t reserved5;
hb_var_num_t reserved6;
- hb_var_num_t reserved7;
} hb_draw_state_t;
/**
@@ -70,7 +78,7 @@
*
* The default #hb_draw_state_t at the start of glyph drawing.
*/
-#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}}
+#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}}
/**
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -99,6 +99,10 @@
float to_x, float to_y)
{
if (unlikely (st.path_open)) close_path (draw_data, st);
+
+ if (st.slant_xy)
+ to_x += to_y * st.slant_xy;
+
st.current_x = to_x;
st.current_y = to_y;
}
@@ -109,7 +113,12 @@
float to_x, float to_y)
{
if (unlikely (!st.path_open)) start_path (draw_data, st);
+
+ if (st.slant_xy)
+ to_x += to_y * st.slant_xy;
+
emit_line_to (draw_data, st, to_x, to_y);
+
st.current_x = to_x;
st.current_y = to_y;
}
@@ -121,7 +130,15 @@
float to_x, float to_y)
{
if (unlikely (!st.path_open)) start_path (draw_data, st);
+
+ if (st.slant_xy)
+ {
+ control_x += control_y * st.slant_xy;
+ to_x += to_y * st.slant_xy;
+ }
+
emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
+
st.current_x = to_x;
st.current_y = to_y;
}
@@ -134,7 +151,16 @@
float to_x, float to_y)
{
if (unlikely (!st.path_open)) start_path (draw_data, st);
+
+ if (st.slant_xy)
+ {
+ control1_x += control1_y * st.slant_xy;
+ control2_x += control2_y * st.slant_xy;
+ to_x += to_y * st.slant_xy;
+ }
+
emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
+
st.current_x = to_x;
st.current_y = to_y;
}
@@ -168,10 +194,9 @@
struct hb_draw_session_t
{
- hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f)
- : slant {slant_}, not_slanted {slant == 0.f},
- funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
- {}
+ hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_xy = 0.f)
+ : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
+ { st.slant_xy = slant_xy; }
~hb_draw_session_t () { close_path (); }
@@ -178,22 +203,14 @@
HB_ALWAYS_INLINE
void move_to (float to_x, float to_y)
{
- if (likely (not_slanted))
- funcs->move_to (draw_data, st,
- to_x, to_y);
- else
- funcs->move_to (draw_data, st,
- to_x + to_y * slant, to_y);
+ funcs->move_to (draw_data, st,
+ to_x, to_y);
}
HB_ALWAYS_INLINE
void line_to (float to_x, float to_y)
{
- if (likely (not_slanted))
- funcs->line_to (draw_data, st,
- to_x, to_y);
- else
- funcs->line_to (draw_data, st,
- to_x + to_y * slant, to_y);
+ funcs->line_to (draw_data, st,
+ to_x, to_y);
}
void
HB_ALWAYS_INLINE
@@ -200,14 +217,9 @@
quadratic_to (float control_x, float control_y,
float to_x, float to_y)
{
- if (likely (not_slanted))
- funcs->quadratic_to (draw_data, st,
- control_x, control_y,
- to_x, to_y);
- else
- funcs->quadratic_to (draw_data, st,
- control_x + control_y * slant, control_y,
- to_x + to_y * slant, to_y);
+ funcs->quadratic_to (draw_data, st,
+ control_x, control_y,
+ to_x, to_y);
}
void
HB_ALWAYS_INLINE
@@ -215,16 +227,10 @@
float control2_x, float control2_y,
float to_x, float to_y)
{
- if (likely (not_slanted))
- funcs->cubic_to (draw_data, st,
- control1_x, control1_y,
- control2_x, control2_y,
- to_x, to_y);
- else
- funcs->cubic_to (draw_data, st,
- control1_x + control1_y * slant, control1_y,
- control2_x + control2_y * slant, control2_y,
- to_x + to_y * slant, to_y);
+ funcs->cubic_to (draw_data, st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y);
}
HB_ALWAYS_INLINE
void close_path ()
@@ -233,8 +239,6 @@
}
public:
- float slant;
- bool not_slanted;
hb_draw_funcs_t *funcs;
void *draw_data;
hb_draw_state_t st;
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -34,7 +34,17 @@
#include "hb-ot-face.hh"
#include "hb-ot-cmap-table.hh"
+#ifdef HAVE_FREETYPE
+#include "hb-ft.h"
+#endif
+#ifdef HAVE_CORETEXT
+#include "hb-coretext.h"
+#endif
+#ifdef HAVE_DIRECTWRITE
+#include "hb-directwrite.h"
+#endif
+
/**
* SECTION:hb-face
* @title: hb-face
@@ -72,14 +82,14 @@
if (unlikely (!blob))
return 0;
- /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
- /* Make API signature const after. */
- hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
- const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
- unsigned int ret = ot.get_face_count ();
- hb_blob_destroy (sanitized);
+ hb_sanitize_context_t c (blob);
- return ret;
+ const char *start = hb_blob_get_data (blob, nullptr);
+ auto *ot = reinterpret_cast<OT::OpenTypeFontFile *> (const_cast<char *> (start));
+ if (unlikely (!ot->sanitize (&c)))
+ return 0;
+
+ return ot->get_face_count ();
}
/*
@@ -318,9 +328,211 @@
return face;
}
+
+static struct supported_face_loaders_t {
+ char name[16];
+ hb_face_t * (*from_file) (const char *font_file, unsigned face_index);
+ hb_face_t * (*from_blob) (hb_blob_t *blob, unsigned face_index);
+} supported_face_loaders[] =
+{
+ {"ot",
+#ifndef HB_NO_OPEN
+ hb_face_create_from_file_or_fail,
+#else
+ nullptr,
#endif
+ hb_face_create_or_fail
+ },
+#ifdef HAVE_FREETYPE
+ {"ft",
+ hb_ft_face_create_from_file_or_fail,
+ hb_ft_face_create_from_blob_or_fail
+ },
+#endif
+#ifdef HAVE_CORETEXT
+ {"coretext",
+ hb_coretext_face_create_from_file_or_fail,
+ hb_coretext_face_create_from_blob_or_fail
+ },
+#endif
+#ifdef HAVE_DIRECTWRITE
+ {"directwrite",
+ hb_directwrite_face_create_from_file_or_fail,
+ hb_directwrite_face_create_from_blob_or_fail
+ },
+#endif
+};
+static const char *get_default_loader_name ()
+{
+ static hb_atomic_t<const char *> static_loader_name;
+ const char *loader_name = static_loader_name.get_acquire ();
+ if (!loader_name)
+ {
+ loader_name = getenv ("HB_FACE_LOADER");
+ if (!loader_name)
+ loader_name = "";
+ if (!static_loader_name.cmpexch (nullptr, loader_name))
+ loader_name = static_loader_name.get_acquire ();
+ }
+ return loader_name;
+}
+
/**
+ * hb_face_create_from_file_or_fail_using:
+ * @file_name: A font filename
+ * @index: The index of the face within the file
+ * @loader_name: (nullable): The name of the loader to use, or `NULL`
+ *
+ * A thin wrapper around the face loader functions registered with HarfBuzz.
+ * If @loader_name is `NULL` or the empty string, the first available loader
+ * is used.
+ *
+ * For example, the FreeType ("ft") loader might be able to load
+ * WOFF and WOFF2 files if FreeType is built with those features,
+ * whereas the OpenType ("ot") loader will not.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * the file cannot be read or the loader fails to load the face.
+ *
+ * Since: 11.0.0
+ **/
+hb_face_t *
+hb_face_create_from_file_or_fail_using (const char *file_name,
+ unsigned int index,
+ const char *loader_name)
+{
+ // Duplicated in hb_face_create_or_fail_using
+ bool retry = false;
+ if (!loader_name || !*loader_name)
+ {
+ loader_name = get_default_loader_name ();
+ retry = true;
+ }
+ if (loader_name && !*loader_name) loader_name = nullptr;
+
+retry:
+ for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
+ {
+ if (!loader_name || (supported_face_loaders[i].from_file && !strcmp (supported_face_loaders[i].name, loader_name)))
+ return supported_face_loaders[i].from_file (file_name, index);
+ }
+
+ if (retry)
+ {
+ retry = false;
+ loader_name = nullptr;
+ goto retry;
+ }
+
+ return nullptr;
+}
+
+/**
+ * hb_face_create_or_fail_using:
+ * @blob: #hb_blob_t to work upon
+ * @index: The index of the face within @blob
+ * @loader_name: (nullable): The name of the loader to use, or `NULL`
+ *
+ * A thin wrapper around the face loader functions registered with HarfBuzz.
+ * If @loader_name is `NULL` or the empty string, the first available loader
+ * is used.
+ *
+ * For example, the FreeType ("ft") loader might be able to load
+ * WOFF and WOFF2 files if FreeType is built with those features,
+ * whereas the OpenType ("ot") loader will not.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * the loader fails to load the face.
+ *
+ * Since: 11.0.0
+ **/
+hb_face_t *
+hb_face_create_or_fail_using (hb_blob_t *blob,
+ unsigned int index,
+ const char *loader_name)
+{
+ // Duplicated in hb_face_create_from_file_or_fail_using
+ bool retry = false;
+ if (!loader_name || !*loader_name)
+ {
+ loader_name = get_default_loader_name ();
+ retry = true;
+ }
+ if (loader_name && !*loader_name) loader_name = nullptr;
+
+retry:
+ for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
+ {
+ if (!loader_name || (supported_face_loaders[i].from_blob && !strcmp (supported_face_loaders[i].name, loader_name)))
+ return supported_face_loaders[i].from_blob (blob, index);
+ }
+
+ if (retry)
+ {
+ retry = false;
+ loader_name = nullptr;
+ goto retry;
+ }
+
+ return nullptr;
+}
+
+static inline void free_static_face_loader_list ();
+
+static const char * const nil_face_loader_list[] = {nullptr};
+
+static struct hb_face_loader_list_lazy_loader_t : hb_lazy_loader_t<const char *,
+ hb_face_loader_list_lazy_loader_t>
+{
+ static const char ** create ()
+ {
+ const char **face_loader_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_face_loaders), sizeof (const char *));
+ if (unlikely (!face_loader_list))
+ return nullptr;
+
+ unsigned i;
+ for (i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
+ face_loader_list[i] = supported_face_loaders[i].name;
+ face_loader_list[i] = nullptr;
+
+ hb_atexit (free_static_face_loader_list);
+
+ return face_loader_list;
+ }
+ static void destroy (const char **l)
+ { hb_free (l); }
+ static const char * const * get_null ()
+ { return nil_face_loader_list; }
+} static_face_loader_list;
+
+static inline
+void free_static_face_loader_list ()
+{
+ static_face_loader_list.free_instance ();
+}
+
+/**
+ * hb_face_list_loaders:
+ *
+ * Retrieves the list of face loaders supported by HarfBuzz.
+ *
+ * Return value: (transfer none) (array zero-terminated=1): a
+ * `NULL`-terminated array of supported face loaders
+ * constant strings. The returned array is owned by HarfBuzz
+ * and should not be modified or freed.
+ *
+ * Since: 11.0.0
+ **/
+const char **
+hb_face_list_loaders ()
+{
+ return static_face_loader_list.get_unconst ();
+}
+#endif
+
+
+/**
* hb_face_get_empty:
*
* Fetches the singleton empty face object.
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -64,9 +64,23 @@
unsigned int index);
HB_EXTERN hb_face_t *
+hb_face_create_or_fail_using (hb_blob_t *blob,
+ unsigned int index,
+ const char *loader_name);
+
+HB_EXTERN hb_face_t *
hb_face_create_from_file_or_fail (const char *file_name,
unsigned int index);
+HB_EXTERN hb_face_t *
+hb_face_create_from_file_or_fail_using (const char *file_name,
+ unsigned int index,
+ const char *loader_name);
+
+HB_EXTERN const char **
+hb_face_list_loaders (void);
+
+
/**
* hb_reference_table_func_t:
* @face: an #hb_face_t to reference table for
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -49,8 +49,8 @@
hb_object_header_t header;
unsigned int index; /* Face index in a collection, zero-based. */
- mutable hb_atomic_int_t upem; /* Units-per-EM. */
- mutable hb_atomic_int_t num_glyphs; /* Number of glyphs. */
+ mutable hb_atomic_t<unsigned> upem; /* Units-per-EM. */
+ mutable hb_atomic_t<unsigned> num_glyphs;/* Number of glyphs. */
hb_reference_table_func_t reference_table_func;
void *user_data;
@@ -70,7 +70,7 @@
plan_node_t *next;
};
#ifndef HB_NO_SHAPER
- hb_atomic_ptr_t<plan_node_t> shape_plans;
+ hb_atomic_t<plan_node_t *> shape_plans;
#endif
hb_blob_t *reference_table (hb_tag_t tag) const
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -38,7 +38,23 @@
#include "hb-ot-var-avar-table.hh"
#include "hb-ot-var-fvar-table.hh"
+#ifndef HB_NO_OT_FONT
+#include "hb-ot.h"
+#endif
+#ifdef HAVE_FREETYPE
+#include "hb-ft.h"
+#endif
+#ifdef HAVE_FONTATIONS
+#include "hb-fontations.h"
+#endif
+#ifdef HAVE_CORETEXT
+#include "hb-coretext.h"
+#endif
+#ifdef HAVE_DIRECTWRITE
+#include "hb-directwrite.h"
+#endif
+
/**
* SECTION:hb-font
* @title: hb-font
@@ -1854,10 +1870,7 @@
{
hb_font_t *font = _hb_font_create (face);
-#ifndef HB_NO_OT_FONT
- /* Install our in-house, very lightweight, funcs. */
- hb_ot_font_set_funcs (font);
-#endif
+ hb_font_set_funcs_using (font, nullptr);
#ifndef HB_NO_VAR
if (face && face->index >> 16)
@@ -1880,7 +1893,7 @@
font->design_coords = design_coords;
font->num_coords = coords_length;
- font->mults_changed (); // Easiest to call this to drop cached data
+ font->changed ();
}
/**
@@ -1935,7 +1948,8 @@
}
}
- font->mults_changed ();
+ font->changed ();
+ font->serial_coords = font->serial;
return font;
}
@@ -2023,7 +2037,7 @@
hb_bool_t replace)
{
if (!hb_object_is_immutable (font))
- font->serial++;
+ font->changed ();
return hb_object_set_user_data (font, key, data, destroy, replace);
}
@@ -2098,7 +2112,7 @@
unsigned int
hb_font_get_serial (hb_font_t *font)
{
- return font->serial;
+ return font->serial.get_acquire ();
}
/**
@@ -2117,9 +2131,7 @@
if (hb_object_is_immutable (font))
return;
- font->serial++;
-
- font->mults_changed ();
+ font->changed ();
}
/**
@@ -2141,8 +2153,6 @@
if (parent == font->parent)
return;
- font->serial++;
-
if (!parent)
parent = hb_font_get_empty ();
@@ -2151,6 +2161,8 @@
font->parent = hb_font_reference (parent);
hb_font_destroy (old);
+
+ font->changed ();
}
/**
@@ -2188,8 +2200,6 @@
if (face == font->face)
return;
- font->serial++;
-
if (unlikely (!face))
face = hb_face_get_empty ();
@@ -2197,9 +2207,11 @@
hb_face_make_immutable (face);
font->face = hb_face_reference (face);
- font->mults_changed ();
+ font->changed ();
hb_face_destroy (old);
+
+ font->changed ();
}
/**
@@ -2244,8 +2256,6 @@
return;
}
- font->serial++;
-
if (font->destroy)
font->destroy (font->user_data);
@@ -2257,6 +2267,8 @@
font->klass = klass;
font->user_data = font_data;
font->destroy = destroy;
+
+ font->changed ();
}
/**
@@ -2283,17 +2295,153 @@
return;
}
- font->serial++;
-
if (font->destroy)
font->destroy (font->user_data);
font->user_data = font_data;
font->destroy = destroy;
+
+ font->changed ();
}
+static struct supported_font_funcs_t {
+ char name[16];
+ void (*func) (hb_font_t *);
+} supported_font_funcs[] =
+{
+#ifndef HB_NO_OT_FONT
+ {"ot", hb_ot_font_set_funcs},
+#endif
+#ifdef HAVE_FREETYPE
+ {"ft", hb_ft_font_set_funcs},
+#endif
+#ifdef HAVE_FONTATIONS
+ {"fontations",hb_fontations_font_set_funcs},
+#endif
+#ifdef HAVE_CORETEXT
+ {"coretext", hb_coretext_font_set_funcs},
+#endif
+#ifdef HAVE_DIRECTWRITE
+ {"directwrite",hb_directwrite_font_set_funcs},
+#endif
+};
+static const char *get_default_funcs_name ()
+{
+ static hb_atomic_t<const char *> static_funcs_name;
+ const char *name = static_funcs_name.get_acquire ();
+ if (!name)
+ {
+ name = getenv ("HB_FONT_FUNCS");
+ if (!name)
+ name = "";
+ if (!static_funcs_name.cmpexch (nullptr, name))
+ name = static_funcs_name.get_acquire ();
+ }
+ return name;
+}
+
/**
+ * hb_font_set_funcs_using:
+ * @font: #hb_font_t to work upon
+ * @name: The name of the font-functions structure to use, or `NULL`
+ *
+ * Sets the font-functions structure to use for a font, based on the
+ * specified name.
+ *
+ * If @name is `NULL` or the empty string, the default (first) functioning font-functions
+ * are used. This default can be changed by setting the `HB_FONT_FUNCS` environment
+ * variable to the name of the desired font-functions.
+ *
+ * Return value: `true` if the font-functions was found and set, `false` otherwise
+ *
+ * Since: 11.0.0
+ **/
+hb_bool_t
+hb_font_set_funcs_using (hb_font_t *font,
+ const char *name)
+{
+ bool retry = false;
+
+ if (!name || !*name)
+ {
+ name = get_default_funcs_name ();
+ retry = true;
+ }
+ if (name && !*name) name = nullptr;
+
+retry:
+ for (unsigned i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
+ if (!name || strcmp (supported_font_funcs[i].name, name) == 0)
+ {
+ supported_font_funcs[i].func (font);
+ if (name || font->klass != hb_font_funcs_get_empty ())
+ return true;
+ }
+
+ if (retry)
+ {
+ retry = false;
+ name = nullptr;
+ goto retry;
+ }
+
+ return false;
+}
+
+static inline void free_static_font_funcs_list ();
+
+static const char * const nil_font_funcs_list[] = {nullptr};
+
+static struct hb_font_funcs_list_lazy_loader_t : hb_lazy_loader_t<const char *,
+ hb_font_funcs_list_lazy_loader_t>
+{
+ static const char ** create ()
+ {
+ const char **font_funcs_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_font_funcs), sizeof (const char *));
+ if (unlikely (!font_funcs_list))
+ return nullptr;
+
+ unsigned i;
+ for (i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
+ font_funcs_list[i] = supported_font_funcs[i].name;
+ font_funcs_list[i] = nullptr;
+
+ hb_atexit (free_static_font_funcs_list);
+
+ return font_funcs_list;
+ }
+ static void destroy (const char **l)
+ { hb_free (l); }
+ static const char * const * get_null ()
+ { return nil_font_funcs_list; }
+} static_font_funcs_list;
+
+static inline
+void free_static_font_funcs_list ()
+{
+ static_font_funcs_list.free_instance ();
+}
+
+/**
+ * hb_font_list_funcs:
+ *
+ * Retrieves the list of font functions supported by HarfBuzz.
+ *
+ * Return value: (transfer none) (array zero-terminated=1): a
+ * `NULL`-terminated array of supported font functions
+ * constant strings. The returned array is owned by HarfBuzz
+ * and should not be modified or freed.
+ *
+ * Since: 11.0.0
+ **/
+const char **
+hb_font_list_funcs ()
+{
+ return static_font_funcs_list.get_unconst ();
+}
+
+/**
* hb_font_set_scale:
* @font: #hb_font_t to work upon
* @x_scale: Horizontal scale value to assign
@@ -2339,11 +2487,10 @@
if (font->x_scale == x_scale && font->y_scale == y_scale)
return;
- font->serial++;
-
font->x_scale = x_scale;
font->y_scale = y_scale;
- font->mults_changed ();
+
+ font->changed ();
}
/**
@@ -2390,10 +2537,10 @@
if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
return;
- font->serial++;
-
font->x_ppem = x_ppem;
font->y_ppem = y_ppem;
+
+ font->changed ();
}
/**
@@ -2437,9 +2584,9 @@
if (font->ptem == ptem)
return;
- font->serial++;
+ font->ptem = ptem;
- font->ptem = ptem;
+ font->changed ();
}
/**
@@ -2499,12 +2646,11 @@
font->embolden_in_place == (bool) in_place)
return;
- font->serial++;
-
font->x_embolden = x_embolden;
font->y_embolden = y_embolden;
font->embolden_in_place = in_place;
- font->mults_changed ();
+
+ font->changed ();
}
/**
@@ -2558,10 +2704,9 @@
if (font->slant == slant)
return;
- font->serial++;
+ font->slant = slant;
- font->slant = slant;
- font->mults_changed ();
+ font->changed ();
}
/**
@@ -2607,8 +2752,6 @@
if (hb_object_is_immutable (font))
return;
- font->serial_coords = ++font->serial;
-
if (!variations_length && font->instance_index == HB_FONT_NO_VAR_NAMED_INSTANCE)
{
hb_font_set_var_coords_normalized (font, nullptr, 0);
@@ -2677,8 +2820,6 @@
if (hb_object_is_immutable (font))
return;
- font->serial_coords = ++font->serial;
-
// TODO Share some of this code with set_variations()
const OT::fvar &fvar = *font->face->table.fvar;
@@ -2749,8 +2890,6 @@
if (hb_object_is_immutable (font))
return;
- font->serial_coords = ++font->serial;
-
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
@@ -2787,8 +2926,6 @@
if (font->instance_index == instance_index)
return;
- font->serial_coords = ++font->serial;
-
font->instance_index = instance_index;
hb_font_set_variations (font, nullptr, 0);
}
@@ -2834,8 +2971,6 @@
if (hb_object_is_immutable (font))
return;
- font->serial_coords = ++font->serial;
-
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1052,7 +1052,13 @@
void *font_data,
hb_destroy_func_t destroy);
+HB_EXTERN hb_bool_t
+hb_font_set_funcs_using (hb_font_t *font,
+ const char *name);
+HB_EXTERN const char **
+hb_font_list_funcs (void);
+
HB_EXTERN void
hb_font_set_scale (hb_font_t *font,
int x_scale,
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -32,6 +32,7 @@
#include "hb.hh"
#include "hb-face.hh"
+#include "hb-atomic.hh"
#include "hb-shaper.hh"
@@ -105,8 +106,8 @@
struct hb_font_t
{
hb_object_header_t header;
- unsigned int serial;
- unsigned int serial_coords;
+ hb_atomic_t<unsigned> serial;
+ hb_atomic_t<unsigned> serial_coords;
hb_font_t *parent;
hb_face_t *face;
@@ -191,23 +192,34 @@
void scale_glyph_extents (hb_glyph_extents_t *extents)
{
- float x1 = em_fscale_x (extents->x_bearing);
- float y1 = em_fscale_y (extents->y_bearing);
- float x2 = em_fscale_x (extents->x_bearing + extents->width);
- float y2 = em_fscale_y (extents->y_bearing + extents->height);
+ float x1 = em_scale_x (extents->x_bearing);
+ float y1 = em_scale_y (extents->y_bearing);
+ float x2 = em_scale_x (extents->x_bearing + extents->width);
+ float y2 = em_scale_y (extents->y_bearing + extents->height);
+ extents->x_bearing = floorf (x1);
+ extents->y_bearing = floorf (y1);
+ extents->width = ceilf (x2) - extents->x_bearing;
+ extents->height = ceilf (y2) - extents->y_bearing;
+ }
+
+ void synthetic_glyph_extents (hb_glyph_extents_t *extents)
+ {
/* Apply slant. */
if (slant_xy)
{
- x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
- x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
+ hb_position_t x1 = extents->x_bearing;
+ hb_position_t y1 = extents->y_bearing;
+ hb_position_t x2 = extents->x_bearing + extents->width;
+ hb_position_t y2 = extents->y_bearing + extents->height;
+
+ x1 += floorf (hb_min (y1 * slant_xy, y2 * slant_xy));
+ x2 += ceilf (hb_max (y1 * slant_xy, y2 * slant_xy));
+
+ extents->x_bearing = x1;
+ extents->width = x2 - extents->x_bearing;
}
- extents->x_bearing = floorf (x1);
- extents->y_bearing = floorf (y1);
- extents->width = ceilf (x2) - extents->x_bearing;
- extents->height = ceilf (y2) - extents->y_bearing;
-
if (x_strength || y_strength)
{
/* Y */
@@ -389,10 +401,14 @@
hb_glyph_extents_t *extents)
{
hb_memset (extents, 0, sizeof (*extents));
- return klass->get.f.glyph_extents (this, user_data,
- glyph,
- extents,
- !klass->user_data ? nullptr : klass->user_data->glyph_extents);
+ bool ret = klass->get.f.glyph_extents (this, user_data,
+ glyph,
+ extents,
+ !klass->user_data ? nullptr : klass->user_data->glyph_extents);
+ if (ret)
+ synthetic_glyph_extents (extents);
+
+ return ret;
}
hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
@@ -686,7 +702,7 @@
return false;
}
- void mults_changed ()
+ void changed ()
{
float upem = face->get_upem ();
@@ -703,6 +719,8 @@
slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
data.fini ();
+
+ serial++;
}
hb_position_t em_mult (int16_t v, int64_t mult)
Added: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fontations.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fontations.h (rev 0)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fontations.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -0,0 +1,56 @@
+/*
+ * 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_FONTATIONS_H
+#define HB_FONTATIONS_H
+
+#include "hb.h"
+
+/**
+ * SECTION: hb-fontations
+ * @title: hb-fontations
+ * @short_description: Fontations integration
+ * @include: hb-fontations.h
+ *
+ * Functions for using HarfBuzz with
+ * [Fontations](https://github.com/googlefonts/fontations/) fonts.
+ **/
+
+HB_BEGIN_DECLS
+
+/**
+ * hb_fontations_font_set_funcs:
+ * @font: #hb_font_t to work upon
+ *
+ * Configures the font-functions structure of the specified #hb_font_t font
+ * object to use Fontations font functions.
+ *
+ * Since: 11.0.0
+ **/
+HB_EXTERN void
+hb_fontations_font_set_funcs (hb_font_t *font);
+
+HB_END_DECLS
+
+#endif /* HB_FONTATIONS_H */
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft-colr.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -83,7 +83,7 @@
hb_ft_paint_context_t (const hb_ft_font_t *ft_font,
hb_font_t *font,
hb_paint_funcs_t *paint_funcs, void *paint_data,
- FT_Color *palette,
+ hb_array_t<const FT_Color> palette,
unsigned palette_index,
hb_color_t foreground) :
ft_font (ft_font), font(font),
@@ -103,7 +103,7 @@
hb_font_t *font;
hb_paint_funcs_t *funcs;
void *data;
- FT_Color *palette;
+ hb_array_t<const FT_Color> palette;
unsigned palette_index;
hb_color_t foreground;
hb_decycler_t glyphs_decycler;
@@ -167,7 +167,7 @@
hb_color_get_red (color),
(hb_color_get_alpha (color) * stop.color.alpha) >> 14);
}
- else
+ else if (c->palette)
{
FT_Color ft_color = c->palette[stop.color.palette_index];
color_stops->color = HB_COLOR (ft_color.blue,
@@ -175,6 +175,8 @@
ft_color.red,
(ft_color.alpha * stop.color.alpha) >> 14);
}
+ else
+ color_stops->color = HB_COLOR (0, 0, 0, 0);
}
color_stops++;
@@ -229,9 +231,7 @@
if (unlikely (!node.visit ((uintptr_t) other_paint.p)))
continue;
- c->funcs->push_group (c->data);
c->recurse (other_paint);
- c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
}
}
break;
@@ -316,11 +316,11 @@
break;
case FT_COLR_PAINTFORMAT_GLYPH:
{
- c->funcs->push_inverse_root_transform (c->data, c->font);
+ c->funcs->push_inverse_font_transform (c->data, c->font);
c->ft_font->lock.unlock ();
c->funcs->push_clip_glyph (c->data, paint.u.glyph.glyphID, c->font);
c->ft_font->lock.lock ();
- c->funcs->push_root_transform (c->data, c->font);
+ c->funcs->push_font_transform (c->data, c->font);
c->recurse (paint.u.glyph.paint);
c->funcs->pop_transform (c->data);
c->funcs->pop_clip (c->data);
@@ -335,7 +335,7 @@
if (unlikely (!node.visit (gid)))
return;
- c->funcs->push_inverse_root_transform (c->data, c->font);
+ c->funcs->push_inverse_font_transform (c->data, c->font);
c->ft_font->lock.unlock ();
if (c->funcs->color_glyph (c->data, gid, c->font))
{
@@ -451,10 +451,12 @@
break;
case FT_COLR_PAINTFORMAT_COMPOSITE:
{
+ c->funcs->push_group (c->data);
c->recurse (paint.u.composite.backdrop_paint);
c->funcs->push_group (c->data);
c->recurse (paint.u.composite.source_paint);
c->funcs->pop_group (c->data, _hb_ft_paint_composite_mode (paint.u.composite.composite_mode));
+ c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
}
break;
@@ -479,8 +481,8 @@
/* Face is locked. */
- FT_Error error;
- FT_Color* palette;
+ FT_Palette_Data palette_data = {};
+ FT_Color* palette = NULL;
FT_LayerIterator iterator;
FT_Bool have_layers;
@@ -487,10 +489,17 @@
FT_UInt layer_glyph_index;
FT_UInt layer_color_index;
- error = FT_Palette_Select(ft_face, palette_index, &palette);
- if (error)
- palette = NULL;
+ (void) FT_Palette_Data_Get(ft_face, &palette_data);
+ (void) FT_Palette_Select(ft_face, palette_index, &palette);
+ if (!palette)
+ {
+ // https://github.com/harfbuzz/harfbuzz/issues/5116
+ (void) FT_Palette_Select(ft_face, 0, &palette);
+ }
+ auto palette_array = hb_array ((const FT_Color *) palette,
+ palette ? palette_data.num_palette_entries : 0);
+
/* COLRv1 */
FT_OpaquePaint paint = {0};
if (FT_Get_Color_Glyph_Paint (ft_face, gid,
@@ -499,7 +508,7 @@
{
hb_ft_paint_context_t c (ft_font, font,
paint_funcs, paint_data,
- palette, palette_index, foreground);
+ palette_array, palette_index, foreground);
hb_decycler_node_t node (c.glyphs_decycler);
node.visit (gid);
@@ -524,10 +533,10 @@
hb_paint_extents_context_t extents_data;
hb_ft_paint_context_t ce (ft_font, font,
extents_funcs, &extents_data,
- palette, palette_index, foreground);
+ palette_array, palette_index, foreground);
hb_decycler_node_t node2 (ce.glyphs_decycler);
node2.visit (gid);
- ce.funcs->push_root_transform (ce.data, font);
+ ce.funcs->push_font_transform (ce.data, font);
ce.recurse (paint);
ce.funcs->pop_transform (ce.data);
hb_extents_t extents = extents_data.get_extents ();
@@ -540,7 +549,7 @@
extents.ymax);
}
- c.funcs->push_root_transform (c.data, font);
+ c.funcs->push_font_transform (c.data, font);
if (is_bounded)
{
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -101,7 +101,7 @@
mutable hb_mutex_t lock; /* Protects members below. */
FT_Face ft_face;
- mutable unsigned cached_serial;
+ mutable hb_atomic_t<unsigned> cached_serial;
mutable hb_ft_advance_cache_t advance_cache;
};
@@ -118,7 +118,7 @@
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
- ft_font->cached_serial = (unsigned) -1;
+ ft_font->cached_serial = UINT_MAX;
new (&ft_font->advance_cache) hb_ft_advance_cache_t;
return ft_font;
@@ -213,9 +213,10 @@
{
if (font->serial != ft_font->cached_serial)
{
+ hb_lock_t lock (ft_font->lock);
_hb_ft_hb_font_changed (font, ft_font->ft_face);
ft_font->advance_cache.clear ();
- ft_font->cached_serial = font->serial;
+ ft_font->cached_serial.set_release (font->serial.get_acquire ());
return true;
}
return false;
@@ -478,6 +479,8 @@
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_position_t *orig_first_advance = first_advance;
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
@@ -561,6 +564,8 @@
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Fixed v;
float y_mult;
@@ -614,6 +619,8 @@
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
float x_mult, y_mult;
@@ -658,6 +665,8 @@
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Vector kerningv;
@@ -677,10 +686,12 @@
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
float x_mult, y_mult;
- float slant_xy = font->slant_xy;
+
#ifdef HAVE_FT_GET_TRANSFORM
if (ft_font->transform)
{
@@ -708,34 +719,11 @@
float x2 = x1 + x_mult * ft_face->glyph->metrics.width;
float y2 = y1 + y_mult * -ft_face->glyph->metrics.height;
- /* Apply slant. */
- if (slant_xy)
- {
- x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
- x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
- }
-
extents->x_bearing = floorf (x1);
extents->y_bearing = floorf (y1);
extents->width = ceilf (x2) - extents->x_bearing;
extents->height = ceilf (y2) - extents->y_bearing;
- if (font->x_strength || font->y_strength)
- {
- /* Y */
- int y_shift = font->y_strength;
- if (font->y_scale < 0) y_shift = -y_shift;
- extents->y_bearing += y_shift;
- extents->height -= y_shift;
-
- /* X */
- int x_shift = font->x_strength;
- if (font->x_scale < 0) x_shift = -x_shift;
- if (font->embolden_in_place)
- extents->x_bearing -= x_shift / 2;
- extents->width += x_shift;
- }
-
return true;
}
@@ -749,6 +737,8 @@
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
@@ -826,6 +816,8 @@
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
float y_mult;
@@ -916,6 +908,8 @@
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
@@ -990,6 +984,8 @@
void *user_data)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
@@ -1079,10 +1075,8 @@
hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
- //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
#ifndef HB_NO_VERTICAL
- //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
#endif
@@ -1090,7 +1084,6 @@
#ifndef HB_NO_OT_SHAPE_FALLBACK
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
#endif
- //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
@@ -1456,6 +1449,10 @@
* variation-axis settings on the @font.
* This call is fast if nothing has changed on @font.
*
+ * Note that as of version 11.0.0, calling this function is not necessary,
+ * as HarfBuzz will automatically detect changes to the font and update
+ * the underlying FT_Face as needed.
+ *
* Return value: true if changed, false otherwise
*
* Since: 4.4.0
@@ -1587,7 +1584,8 @@
* font file and face index.
*
* This is similar in functionality to hb_face_create_from_file_or_fail(),
- * but uses the FreeType library for loading the font file.
+ * but uses the FreeType library for loading the font file. This can
+ * be useful, for example, to load WOFF and WOFF2 font data.
*
* Return value: (transfer full): The new face object, or `NULL` if
* no face is found at the specified index or the file cannot be read.
@@ -1624,7 +1622,76 @@
return face;
}
+static hb_user_data_key_t ft_blob_key = {0};
+
static void
+_destroy_blob (void *p)
+{
+ hb_blob_destroy ((hb_blob_t *) p);
+}
+
+/**
+ * hb_ft_face_create_from_blob_or_fail:
+ * @blob: A blob
+ * @index: The index of the face within the blob
+ *
+ * Creates an #hb_face_t face object from the specified
+ * font blob and face index.
+ *
+ * This is similar in functionality to hb_face_create_from_blob_or_fail(),
+ * but uses the FreeType library for loading the font blob. This can
+ * be useful, for example, to load WOFF and WOFF2 font data.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * loading fails (eg. blob does not contain valid font data).
+ *
+ * Since: 11.0.0
+ */
+hb_face_t *
+hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob,
+ unsigned int index)
+{
+ FT_Library ft_library = reference_ft_library ();
+ if (unlikely (!ft_library))
+ {
+ DEBUG_MSG (FT, ft_library, "reference_ft_library failed");
+ return nullptr;
+ }
+
+ hb_blob_make_immutable (blob);
+ unsigned blob_size;
+ const char *blob_data = hb_blob_get_data (blob, &blob_size);
+
+ FT_Face ft_face;
+ if (unlikely (FT_New_Memory_Face (ft_library,
+ (const FT_Byte *) blob_data,
+ blob_size,
+ index,
+ &ft_face)))
+ return nullptr;
+
+ hb_face_t *face = hb_ft_face_create_referenced (ft_face);
+ FT_Done_Face (ft_face);
+
+ ft_face->generic.data = ft_library;
+ ft_face->generic.finalizer = finalize_ft_library;
+
+ if (hb_face_is_immutable (face))
+ return nullptr;
+
+ // Hook the blob to the hb_face_t, since FT_Face still needs it.
+ hb_blob_reference (blob);
+ if (!hb_face_set_user_data (face, &ft_blob_key, blob, _destroy_blob, true))
+ {
+ hb_blob_destroy (blob);
+ hb_face_destroy (face);
+ return nullptr;
+ }
+
+ return face;
+}
+
+static void
_release_blob (void *arg)
{
FT_Face ft_face = (FT_Face) arg;
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -88,6 +88,10 @@
hb_ft_face_create_from_file_or_fail (const char *file_name,
unsigned int index);
+HB_EXTERN hb_face_t *
+hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob,
+ unsigned int index);
+
/*
* hb-font from ft-face.
*/
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-geometry.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -30,6 +30,11 @@
struct hb_extents_t
{
hb_extents_t () {}
+ hb_extents_t (const hb_glyph_extents_t &extents) :
+ xmin (hb_min (extents.x_bearing, extents.x_bearing + extents.width)),
+ ymin (hb_min (extents.y_bearing, extents.y_bearing + extents.height)),
+ xmax (hb_max (extents.x_bearing, extents.x_bearing + extents.width)),
+ ymax (hb_max (extents.y_bearing, extents.y_bearing + extents.height)) {}
hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
@@ -38,6 +43,12 @@
void union_ (const hb_extents_t &o)
{
+ if (o.is_empty ()) return;
+ if (is_empty ())
+ {
+ *this = o;
+ return;
+ }
xmin = hb_min (xmin, o.xmin);
ymin = hb_min (ymin, o.ymin);
xmax = hb_max (xmax, o.xmax);
@@ -46,6 +57,11 @@
void intersect (const hb_extents_t &o)
{
+ if (o.is_empty () || is_empty ())
+ {
+ *this = hb_extents_t {};
+ return;
+ }
xmin = hb_max (xmin, o.xmin);
ymin = hb_max (ymin, o.ymin);
xmax = hb_min (xmax, o.xmax);
@@ -69,6 +85,18 @@
}
}
+ hb_glyph_extents_t to_glyph_extents (bool xneg = false, bool yneg = false) const
+ {
+ hb_position_t x0 = (hb_position_t) roundf (xmin);
+ hb_position_t y0 = (hb_position_t) roundf (ymin);
+ hb_position_t x1 = (hb_position_t) roundf (xmax);
+ hb_position_t y1 = (hb_position_t) roundf (ymax);
+ return hb_glyph_extents_t {xneg ? x1 : x0,
+ yneg ? y0 : y1,
+ xneg ? x0 - x1 : x1 - x0,
+ yneg ? y1 - y0 : y0 - y1};
+ }
+
float xmin = 0.f;
float ymin = 0.f;
float xmax = -1.f;
@@ -218,7 +246,7 @@
EMPTY,
};
- hb_bounds_t (status_t status) : status (status) {}
+ hb_bounds_t (status_t status = UNBOUNDED) : status (status) {}
hb_bounds_t (const hb_extents_t &extents) :
status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -68,7 +68,7 @@
{
hb_face_t *face;
gr_face *grface;
- hb_atomic_ptr_t<hb_graphite2_tablelist_t> tlist;
+ hb_atomic_t<hb_graphite2_tablelist_t *> tlist;
};
static const void *hb_graphite2_get_table (const void *data, unsigned int tag, size_t *len)
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -273,7 +273,7 @@
private:
/* Must only have one pointer. */
- hb_atomic_ptr_t<Stored *> instance;
+ hb_atomic_t<Stored *> instance;
};
/* Specializations. */
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-object.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-object.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-object.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -142,7 +142,7 @@
struct hb_reference_count_t
{
- mutable hb_atomic_int_t ref_count;
+ mutable hb_atomic_t<int> ref_count;
void init (int v = 1) { ref_count = v; }
int get_relaxed () const { return ref_count; }
@@ -213,8 +213,8 @@
struct hb_object_header_t
{
hb_reference_count_t ref_count;
- mutable hb_atomic_int_t writable = 0;
- hb_atomic_ptr_t<hb_user_data_array_t> user_data;
+ mutable hb_atomic_t<bool> writable = false;
+ hb_atomic_t<hb_user_data_array_t *> user_data;
bool is_inert () const { return !ref_count.get_relaxed (); }
};
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1888,7 +1888,7 @@
bool ensure_run ()
{
- if (likely (run_count > 0)) return true;
+ if (run_count > 0) return true;
if (unlikely (p >= end))
{
@@ -1943,6 +1943,11 @@
unsigned count = hb_min (n - i, (unsigned) run_count);
switch (width)
{
+ case 0:
+ {
+ arrayZ += count;
+ break;
+ }
case 1:
{
const auto *pp = (const HBINT8 *) p;
@@ -1958,6 +1963,8 @@
#endif
for (; j < count; j++)
*arrayZ++ += scaled ? *pp++ * scale : *pp++;
+
+ p = (const unsigned char *) pp;
}
break;
case 2:
@@ -1975,6 +1982,8 @@
#endif
for (; j < count; j++)
*arrayZ++ += scaled ? *pp++ * scale : *pp++;
+
+ p = (const unsigned char *) pp;
}
break;
case 4:
@@ -1982,10 +1991,11 @@
const auto *pp = (const HBINT32 *) p;
for (unsigned j = 0; j < count; j++)
*arrayZ++ += scaled ? *pp++ * scale : *pp++;
+
+ p = (const unsigned char *) pp;
}
break;
}
- p += count * width;
run_count -= count;
i += count;
}
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1176,7 +1176,8 @@
if (unlikely (!font_interp.interpret (*font))) goto fail;
PRIVDICTVAL *priv = &privateDicts[i];
const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
- if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
+ if (unlikely (font->privateDictInfo.size &&
+ privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
num_interp_env_t env2 (privDictStr);
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
priv->init ();
@@ -1191,7 +1192,8 @@
PRIVDICTVAL *priv = &privateDicts[0];
const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
- if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
+ if (font->privateDictInfo.size &&
+ unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
num_interp_env_t env (privDictStr);
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
priv->init ();
@@ -1483,7 +1485,7 @@
int cmp (const gname_t &a) const { return cmp (&a, this); }
};
- mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
+ mutable hb_atomic_t<hb_sorted_vector_t<gname_t> *> glyph_names;
typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
};
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -103,6 +103,14 @@
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const
{
+ return get_extents_at (font, glyph, extents, hb_array (font->coords, font->num_coords));
+}
+
+bool OT::cff2::accelerator_t::get_extents_at (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ hb_array_t<const int> coords) const
+{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
return true;
@@ -112,7 +120,7 @@
unsigned int fd = fdSelect->get_fd (glyph);
const hb_ubytes_t str = (*charStrings)[glyph];
- cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords);
+ cff2_cs_interp_env_t<number_t> env (str, *this, fd, coords.arrayZ, coords.length);
cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t, number_t> interp (env);
cff2_extents_param_t param;
if (unlikely (!interp.interpret (param))) return false;
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -458,7 +458,8 @@
if (unlikely (!font_interp.interpret (*font))) goto fail;
const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
- if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
+ if (unlikely (font->privateDictInfo.size &&
+ privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
cff2_priv_dict_interp_env_t env2 (privDictStr);
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2);
privateDicts[i].init ();
@@ -481,6 +482,13 @@
privateDicts.fini ();
hb_blob_destroy (blob);
blob = nullptr;
+
+ auto *scalars = cached_scalars_vector.get_acquire ();
+ if (scalars && cached_scalars_vector.cmpexch (scalars, nullptr))
+ {
+ scalars->fini ();
+ hb_free (scalars);
+ }
}
hb_vector_t<uint16_t> *create_glyph_to_sid_map () const
@@ -508,6 +516,8 @@
hb_vector_t<cff2_font_dict_values_t> fontDicts;
hb_vector_t<PRIVDICTVAL> privateDicts;
+ mutable hb_atomic_t<hb_vector_t<float> *> cached_scalars_vector;
+
unsigned int num_glyphs = 0;
};
@@ -518,6 +528,10 @@
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
+ HB_INTERNAL bool get_extents_at (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ hb_array_t<const int> coords) 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-color.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -204,7 +204,7 @@
hb_bool_t
hb_ot_color_has_layers (hb_face_t *face)
{
- return face->table.COLR->has_v0_data ();
+ return face->table.COLR->colr->has_v0_data ();
}
/**
@@ -221,7 +221,7 @@
hb_bool_t
hb_ot_color_has_paint (hb_face_t *face)
{
- return face->table.COLR->has_v1_data ();
+ return face->table.COLR->colr->has_v1_data ();
}
/**
@@ -240,7 +240,7 @@
hb_ot_color_glyph_has_paint (hb_face_t *face,
hb_codepoint_t glyph)
{
- return face->table.COLR->has_paint_for_glyph (glyph);
+ return face->table.COLR->colr->has_paint_for_glyph (glyph);
}
/**
@@ -266,7 +266,7 @@
unsigned int *layer_count, /* IN/OUT. May be NULL. */
hb_ot_color_layer_t *layers /* OUT. May be NULL. */)
{
- return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers);
+ return face->table.COLR->colr->get_glyph_layers (glyph, start_offset, layer_count, layers);
}
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -136,7 +136,7 @@
/* OpenType color fonts. */
#ifndef HB_NO_COLOR
-HB_OT_CORE_TABLE (OT, COLR)
+HB_OT_ACCELERATOR (OT, COLR)
HB_OT_CORE_TABLE (OT, CPAL)
HB_OT_ACCELERATOR (OT, CBDT)
HB_OT_ACCELERATOR (OT, sbix)
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -36,6 +36,7 @@
#include "hb-ot-name-table.hh"
#include "hb-ot-post-table.hh"
#include "OT/Color/CBDT/CBDT.hh"
+#include "OT/Color/COLR/COLR.hh"
#include "OT/Color/sbix/sbix.hh"
#include "OT/Color/svg/svg.hh"
#include "hb-ot-layout-gdef-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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -85,8 +85,8 @@
#endif
/* h_advance caching */
- mutable hb_atomic_int_t cached_coords_serial;
- mutable hb_atomic_ptr_t<hb_ot_font_advance_cache_t> advance_cache;
+ mutable hb_atomic_t<int> cached_coords_serial;
+ mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache;
};
static hb_ot_font_t *
@@ -471,6 +471,9 @@
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;
+#ifndef HB_NO_VAR_COMPOSITES
+ if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
+#endif
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -27,6 +27,7 @@
#ifndef HB_OT_KERN_TABLE_HH
#define HB_OT_KERN_TABLE_HH
+#include "hb-aat-layout-common.hh"
#include "hb-aat-layout-kerx-table.hh"
@@ -400,6 +401,7 @@
hb_blob_ptr_t<kern> table;
AAT::kern_accelerator_data_t accel_data;
+ AAT::hb_aat_scratch_t scratch;
};
protected:
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -2565,7 +2565,7 @@
if (cache)
{
cached_value = &(cache[region_index]);
- if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
+ if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
return *cached_value;
}
@@ -2743,7 +2743,7 @@
if (cache)
{
cached_value = &(cache[region_index]);
- if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
+ if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
return *cached_value;
}
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -4900,7 +4900,7 @@
this->lookup_count = table->get_lookup_count ();
- this->accels = (hb_atomic_ptr_t<hb_ot_layout_lookup_accelerator_t> *) hb_calloc (this->lookup_count, sizeof (*accels));
+ this->accels = (hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *) hb_calloc (this->lookup_count, sizeof (*accels));
if (unlikely (!this->accels))
{
this->lookup_count = 0;
@@ -4948,7 +4948,7 @@
hb_blob_ptr_t<T> table;
unsigned int lookup_count;
- hb_atomic_ptr_t<hb_ot_layout_lookup_accelerator_t> *accels;
+ hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *accels;
};
protected:
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -131,13 +131,15 @@
hb_font_t *font,
hb_buffer_t *buffer)
{
- hb_blob_t *blob = font->face->table.kern.get_blob ();
- const auto& kern = *font->face->table.kern;
+ auto &accel = *font->face->table.kern;
+ hb_blob_t *blob = accel.get_blob ();
AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
if (!buffer->message (font, "start table kern")) return;
- kern.apply (&c);
+ c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
+ accel.apply (&c);
+ accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
(void) buffer->message (font, "end table kern");
}
#endif
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -202,7 +202,8 @@
/* If GEN_CAT=FORMAT, top byte masks: */
UPROPS_MASK_Cf_ZWJ = 0x0100u,
UPROPS_MASK_Cf_ZWNJ = 0x0200u,
- UPROPS_MASK_Cf_VS = 0x0400u
+ UPROPS_MASK_Cf_VS = 0x0400u,
+ UPROPS_MASK_Cf_AAT_DELETED = 0x0800u
};
HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
@@ -386,6 +387,8 @@
static inline void
_hb_ot_layout_reverse_graphemes (hb_buffer_t *buffer)
{
+ // MONOTONE_GRAPHEMES was already applied and is taken care of by _hb_grapheme_group_func.
+ // So we just check for MONOTONE_CHARACTERS here.
buffer->reverse_groups (_hb_grapheme_group_func,
buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
}
@@ -418,6 +421,17 @@
return;
info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
}
+static inline bool
+_hb_glyph_info_is_aat_deleted (const hb_glyph_info_t *info)
+{
+ return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_AAT_DELETED);
+}
+static inline void
+_hb_glyph_info_set_aat_deleted (hb_glyph_info_t *info)
+{
+ _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_FORMAT);
+ info->unicode_props() |= UPROPS_MASK_Cf_AAT_DELETED;
+}
/* lig_props: aka lig_id / lig_comp
*
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -290,7 +290,7 @@
const Array16Of<HBUINT16> *glyphNameIndex = nullptr;
hb_vector_t<uint32_t> index_to_offset;
const uint8_t *pool = nullptr;
- hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
+ hb_atomic_t<uint16_t *> gids_sorted_by_name;
};
bool has_data () const { return version.to_int (); }
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -84,6 +84,7 @@
props (props),
map (face, props)
#ifndef HB_NO_AAT_SHAPE
+ , aat_map (face, props)
, apply_morx (_hb_apply_morx (face, props))
#endif
{
@@ -106,6 +107,10 @@
plan.props = props;
plan.shaper = shaper;
map.compile (plan.map, key);
+#ifndef HB_NO_AAT_SHAPE
+ if (apply_morx)
+ aat_map.compile (plan.aat_map);
+#endif
#ifndef HB_NO_OT_SHAPE_FRACTIONS
plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
@@ -551,7 +556,7 @@
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
return;
- if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
+ if (HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES (buffer->cluster_level))
foreach_grapheme (buffer, start, end)
buffer->merge_clusters (start, end);
else
@@ -609,7 +614,7 @@
* Ogham fonts are supposed to be implemented BTT or not. Need to research that
* first. */
if ((HB_DIRECTION_IS_HORIZONTAL (direction) &&
- direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) ||
+ direction != horiz_dir && HB_DIRECTION_IS_VALID (horiz_dir)) ||
(HB_DIRECTION_IS_VERTICAL (direction) &&
direction != HB_DIRECTION_TTB))
{
@@ -1109,10 +1114,6 @@
/* Finish off. Has to follow a certain order. */
hb_ot_layout_position_finish_advances (c->font, c->buffer);
hb_ot_zero_width_default_ignorables (c->buffer);
-#ifndef HB_NO_AAT_SHAPE
- if (c->plan->apply_morx)
- hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
-#endif
hb_ot_layout_position_finish_offsets (c->font, c->buffer);
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -66,6 +66,7 @@
hb_segment_properties_t props;
const struct hb_ot_shaper_t *shaper;
hb_ot_map_t map;
+ hb_aat_map_t aat_map;
const void *data;
#ifndef HB_NO_OT_SHAPE_FRACTIONS
hb_mask_t frac_mask, numr_mask, dnom_mask;
@@ -141,6 +142,7 @@
hb_segment_properties_t props;
hb_ot_map_builder_t map;
#ifndef HB_NO_AAT_SHAPE
+ hb_aat_map_builder_t aat_map;
bool apply_morx : 1;
#else
static constexpr bool apply_morx = false;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -260,7 +260,7 @@
* mask_array[NONE] == 0. */
hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
- hb_atomic_ptr_t<arabic_fallback_plan_t> fallback_plan;
+ hb_atomic_t<arabic_fallback_plan_t *> fallback_plan;
unsigned int do_fallback : 1;
unsigned int has_stch : 1;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-hangul.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-hangul.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-hangul.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -298,8 +298,7 @@
end = start + 2;
if (unlikely (!buffer->successful))
break;
- if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
- buffer->merge_out_clusters (start, end);
+ buffer->merge_out_clusters (start, end);
continue;
}
}
@@ -372,8 +371,7 @@
if (i < end)
info[i++].hangul_shaping_feature() = TJMO;
- if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
- buffer->merge_out_clusters (start, end);
+ buffer->merge_out_clusters (start, end);
continue;
}
else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint)))
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -301,7 +301,7 @@
#else
static constexpr bool uniscribe_bug_compatible = false;
#endif
- mutable hb_atomic_int_t virama_glyph;
+ mutable hb_atomic_t<hb_codepoint_t> virama_glyph;
hb_indic_would_substitute_feature_t rphf;
hb_indic_would_substitute_feature_t pref;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-thai.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-thai.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-thai.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -360,7 +360,7 @@
{
/* Since we decomposed, and NIKHAHIT is combining, merge clusters with the
* previous cluster. */
- if (start && buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
+ if (start)
buffer->merge_out_clusters (start - 1, end);
}
}
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -326,7 +326,7 @@
hb_tag_t lang_tag = hb_tag_from_string (lang_str, first_len);
- static hb_atomic_int_t last_tag_idx; /* Poor man's cache. */
+ static hb_atomic_t<unsigned> last_tag_idx = 0; /* Poor man's cache. */
unsigned tag_idx = last_tag_idx;
if (likely (tag_idx < ot_languages_len && ot_languages[tag_idx].language == lang_tag) ||
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -53,10 +53,6 @@
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 {
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint-extents.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint-extents.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint-extents.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -35,13 +35,22 @@
struct hb_paint_extents_context_t
{
- hb_paint_extents_context_t ()
+ void clear ()
{
+ transforms.clear ();
+ clips.clear ();
+ groups.clear ();
+
transforms.push (hb_transform_t{});
clips.push (hb_bounds_t{hb_bounds_t::UNBOUNDED});
groups.push (hb_bounds_t{hb_bounds_t::EMPTY});
}
+ hb_paint_extents_context_t ()
+ {
+ clear ();
+ }
+
hb_extents_t get_extents ()
{
return groups.tail().extents;
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -465,6 +465,42 @@
}
/**
+ * hb_paint_push_font_transform:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @font: a font
+ *
+ * Push the transform reflecting the font's scale and slant
+ * settings onto the paint functions.
+ *
+ * Since: 11.0.0
+ */
+void
+hb_paint_push_font_transform (hb_paint_funcs_t *funcs, void *paint_data,
+ const hb_font_t *font)
+{
+ funcs->push_font_transform (paint_data, font);
+}
+
+/**
+ * hb_paint_push_inverse_font_transform:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @font: a font
+ *
+ * Push the inverse of the transform reflecting the font's
+ * scale and slant settings onto the paint functions.
+ *
+ * Since: 11.0.0
+ */
+void
+hb_paint_push_inverse_font_transform (hb_paint_funcs_t *funcs, void *paint_data,
+ const hb_font_t *font)
+{
+ funcs->push_inverse_font_transform (paint_data, font);
+}
+
+/**
* hb_paint_pop_transform:
* @funcs: paint functions
* @paint_data: associated data passed by the caller
@@ -646,7 +682,7 @@
float x0, float y0, float r0,
float x1, float y1, float r1)
{
- funcs->radial_gradient (paint_data, color_line, x0, y0, r0, y1, x1, r1);
+ funcs->radial_gradient (paint_data, color_line, x0, y0, r0, x1, y1, r1);
}
/**
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.h
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.h 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.h 2025-03-24 00:38:36 UTC (rev 74729)
@@ -957,6 +957,14 @@
float dx, float dy);
HB_EXTERN void
+hb_paint_push_font_transform (hb_paint_funcs_t *funcs, void *paint_data,
+ const hb_font_t *font);
+
+HB_EXTERN void
+hb_paint_push_inverse_font_transform (hb_paint_funcs_t *funcs, void *paint_data,
+ const hb_font_t *font);
+
+HB_EXTERN void
hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data);
HB_EXTERN hb_bool_t
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-paint.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -157,7 +157,7 @@
/* Internal specializations. */
- void push_root_transform (void *paint_data,
+ void push_font_transform (void *paint_data,
const hb_font_t *font)
{
float upem = font->face->get_upem ();
@@ -168,8 +168,8 @@
xscale/upem, 0, slant * yscale/upem, yscale/upem, 0, 0);
}
- void push_inverse_root_transform (void *paint_data,
- hb_font_t *font)
+ void push_inverse_font_transform (void *paint_data,
+ const hb_font_t *font)
{
float upem = font->face->get_upem ();
int xscale = font->x_scale ? font->x_scale : upem;
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -30,6 +30,7 @@
#include "hb.hh"
#include "hb-bit-set-invertible.hh"
+#include "hb-bit-vector.hh" // Just to include
template <typename impl_t>
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -91,8 +91,10 @@
*
* Retrieves the list of shapers supported by HarfBuzz.
*
- * Return value: (transfer none) (array zero-terminated=1): an array of
- * constant strings
+ * Return value: (transfer none) (array zero-terminated=1): a
+ * `NULL`-terminated array of supported shapers constant string.
+ * The returned array is owned by HarfBuzz and should not be
+ * modified or freed.
*
* Since: 0.9.2
**/
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -41,6 +41,7 @@
#include "hb-ot-maxp-table.hh"
#ifndef HB_NO_VISIBILITY
+
#include "hb-ot-name-language-static.hh"
uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -570,7 +570,7 @@
parsed_cs_str_vec_t parsed_charstrings;
parsed_cs_str_vec_t parsed_global_subrs;
hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
- mutable hb_atomic_ptr_t<glyph_to_sid_map_t> glyph_to_sid_map;
+ mutable hb_atomic_t<glyph_to_sid_map_t *> glyph_to_sid_map;
private:
hb_blob_t* original_blob;
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-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -90,7 +90,13 @@
{
auto iter = hb_iter (o);
if (iter.is_random_access_iterator || iter.has_fast_len)
- alloc (hb_len (iter), true);
+ {
+ if (unlikely (!alloc (hb_len (iter), true)))
+ return;
+ unsigned count = hb_len (iter);
+ for (unsigned i = 0; i < count; i++)
+ push_has_room (*iter++);
+ }
while (iter)
{
if (unlikely (!alloc (length + 1)))
@@ -436,7 +442,6 @@
new_allocated += (new_allocated >> 1) + 8;
}
-
/* Reallocate */
bool overflows =
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -113,7 +113,7 @@
struct hb_wasm_face_data_t {
hb_blob_t *wasm_blob;
wasm_module_t wasm_module;
- mutable hb_atomic_ptr_t<hb_wasm_shape_plan_t> plan;
+ mutable hb_atomic_t<hb_wasm_shape_plan_t *> plan;
};
static bool
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh 2025-03-24 00:38:36 UTC (rev 74729)
@@ -230,33 +230,6 @@
#define HB_PASTE(a,b) HB_PASTE1(a,b)
-/* Compile-time custom allocator support. */
-
-#if !defined(HB_CUSTOM_MALLOC) \
- && defined(hb_malloc_impl) \
- && defined(hb_calloc_impl) \
- && defined(hb_realloc_impl) \
- && defined(hb_free_impl)
-#define HB_CUSTOM_MALLOC
-#endif
-
-#ifdef HB_CUSTOM_MALLOC
-extern "C" void* hb_malloc_impl(size_t size);
-extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
-extern "C" void* hb_realloc_impl(void *ptr, size_t size);
-extern "C" void hb_free_impl(void *ptr);
-#define hb_malloc hb_malloc_impl
-#define hb_calloc hb_calloc_impl
-#define hb_realloc hb_realloc_impl
-#define hb_free hb_free_impl
-#else
-#define hb_malloc malloc
-#define hb_calloc calloc
-#define hb_realloc realloc
-#define hb_free free
-#endif
-
-
/*
* Compiler attributes
*/
@@ -282,7 +255,7 @@
#define __attribute__(x)
#endif
-#if defined(__MINGW32__) && (__GNUC__ >= 3)
+#if defined(__MINGW32__) && (__GNUC__ >= 3) && !defined(__clang__)
#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)))
@@ -539,7 +512,30 @@
#define HB_PI 3.14159265358979f
#define HB_2_PI (2.f * HB_PI)
+/* Compile-time custom allocator support. */
+#if !defined(HB_CUSTOM_MALLOC) \
+ && defined(hb_malloc_impl) \
+ && defined(hb_calloc_impl) \
+ && defined(hb_realloc_impl) \
+ && defined(hb_free_impl)
+#define HB_CUSTOM_MALLOC
+#endif
+
+#ifdef HB_CUSTOM_MALLOC
+extern "C" void* hb_malloc_impl(size_t size);
+extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
+extern "C" void* hb_realloc_impl(void *ptr, size_t size);
+extern "C" void hb_free_impl(void *ptr);
+#else
+#define hb_malloc_impl malloc
+#define hb_calloc_impl calloc
+#define hb_realloc_impl realloc
+#define hb_free_impl free
+#endif
+
+
+
/* Headers we include for everyone. Keep topologically sorted by dependency.
* They express dependency amongst themselves, but no other file should include
* them directly.*/
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/justify.py
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/justify.py 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/justify.py 2025-03-24 00:38:36 UTC (rev 74729)
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+
import gi
gi.require_version("Gtk", "3.0")
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build 2025-03-24 00:38:36 UTC (rev 74729)
@@ -28,6 +28,9 @@
'hb-atomic.hh',
'hb-bimap.hh',
'hb-bit-page.hh',
+ 'hb-bit-set.hh',
+ 'hb-bit-set-invertible.hh',
+ 'hb-bit-vector.hh',
'hb-blob.cc',
'hb-blob.hh',
'hb-buffer-serialize.cc',
@@ -199,6 +202,7 @@
'hb-ot-os2-unicode-ranges.hh',
'hb-ot-post-macroman.hh',
'hb-ot-post-table.hh',
+ 'hb-ot-post-table-v2subset.hh',
'hb-ot-shaper-arabic-fallback.hh',
'hb-ot-shaper-arabic-joining-list.hh',
'hb-ot-shaper-arabic-pua.hh',
@@ -241,7 +245,9 @@
'hb-ot-var-varc-table.hh',
'hb-ot-var.cc',
'hb-ot-vorg-table.hh',
+ 'hb-priority-queue.hh',
'hb-pool.hh',
+ 'hb-repacker.hh',
'hb-sanitize.hh',
'hb-serialize.hh',
'hb-set-digest.hh',
@@ -326,6 +332,9 @@
hb_ft_sources = files('hb-ft.cc', 'hb-ft-colr.hh')
hb_ft_headers = files('hb-ft.h')
+hb_fontations_sources = files()
+hb_fontations_headers = files('hb-fontations.h')
+
hb_glib_sources = files('hb-glib.cc')
hb_glib_headers = files('hb-glib.h')
@@ -340,6 +349,7 @@
'hb-wasm-api-common.hh',
'hb-wasm-api-face.hh',
'hb-wasm-api-font.hh',
+ 'hb-wasm-api-list.hh',
'hb-wasm-api-shape.hh',
'hb-wasm-shape.cc',
)
@@ -347,10 +357,10 @@
# System-dependent sources and headers
-hb_coretext_sources = files('hb-coretext-shape.cc', 'hb-coretext-font.cc')
+hb_coretext_sources = files('hb-coretext.cc', 'hb-coretext.hh', 'hb-coretext-font.cc', 'hb-coretext-shape.cc')
hb_coretext_headers = files('hb-coretext.h')
-hb_directwrite_sources = files('hb-directwrite.cc')
+hb_directwrite_sources = files('hb-directwrite.cc', 'hb-directwrite.hh', 'hb-directwrite-font.cc', 'hb-directwrite-shape.cc')
hb_directwrite_headers = files('hb-directwrite.h')
hb_gdi_sources = files('hb-gdi.cc')
@@ -513,6 +523,15 @@
harfbuzz_deps += coretext_deps
endif
+if conf.get('HAVE_FONTATIONS', 0) == 1
+
+ subdir('fontations')
+
+ hb_sources += hb_fontations_sources
+ hb_headers += hb_fontations_headers
+ harfbuzz_deps += [harfbuzz_fontations_dep]
+endif
+
have_icu = conf.get('HAVE_ICU', 0) == 1
have_icu_builtin = conf.get('HAVE_ICU_BUILTIN', 0) == 1
if have_icu and have_icu_builtin
@@ -650,6 +669,7 @@
hb_cairo_sources = [
'hb-cairo.cc',
'hb-cairo-utils.cc',
+ 'hb-cairo-utils.hh',
'hb-static.cc'
]
@@ -663,7 +683,7 @@
include_directories: incconfig,
dependencies: [m_dep, cairo_dep],
link_with: [libharfbuzz],
- cpp_args: cpp_args + extra_hb_cpp_args,
+ cpp_args: cpp_args + extra_hb_cpp_args,
soversion: hb_so_version,
version: version,
install: true,
Modified: trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc
===================================================================
--- trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc 2025-03-24 00:38:36 UTC (rev 74729)
@@ -43,6 +43,23 @@
#ifndef HB_NO_BUFFER_SERIALIZE
+ hb_buffer_serialize_format_t format = HB_BUFFER_SERIALIZE_FORMAT_TEXT;
+ if (argc > 1)
+ {
+ if (!strcmp (argv[1], "--json"))
+ {
+ format = HB_BUFFER_SERIALIZE_FORMAT_JSON;
+ argc--;
+ argv++;
+ }
+ else if (!strcmp (argv[1], "--text"))
+ {
+ format = HB_BUFFER_SERIALIZE_FORMAT_TEXT;
+ argc--;
+ argv++;
+ }
+ }
+
if (argc < 2)
argv[1] = (char *) "/dev/null";
@@ -68,10 +85,13 @@
while (true)
{
const char *p = line;
+ const char *end = p + strlen (p);
+ if (p < end && *(end - 1) == '\n')
+ end--;
if (!hb_buffer_deserialize_glyphs (buf,
- p, -1, &p,
+ p, end - p, &p,
font,
- HB_BUFFER_SERIALIZE_FORMAT_TEXT))
+ format))
{
ret = false;
break;
@@ -97,7 +117,8 @@
unsigned len;
offset += hb_buffer_serialize_glyphs (buf, offset, count,
out, sizeof (out), &len,
- font, HB_BUFFER_SERIALIZE_FORMAT_TEXT,
+ font,
+ format,
HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS);
fwrite (out, 1, len, stdout);
}
Modified: trunk/Build/source/libs/harfbuzz/include/Makefile.am
===================================================================
--- trunk/Build/source/libs/harfbuzz/include/Makefile.am 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/include/Makefile.am 2025-03-24 00:38:36 UTC (rev 74729)
@@ -23,6 +23,7 @@
$(HARFBUZZ_SRC)/hb-draw.h \
$(HARFBUZZ_SRC)/hb-face.h \
$(HARFBUZZ_SRC)/hb-font.h \
+ $(HARFBUZZ_SRC)/hb-fontations.h \
$(HARFBUZZ_SRC)/hb-map.h \
$(HARFBUZZ_SRC)/hb-ot-deprecated.h \
$(HARFBUZZ_SRC)/hb-paint.h \
Modified: trunk/Build/source/libs/harfbuzz/include/Makefile.in
===================================================================
--- trunk/Build/source/libs/harfbuzz/include/Makefile.in 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/include/Makefile.in 2025-03-24 00:38:36 UTC (rev 74729)
@@ -255,10 +255,10 @@
$(HARFBUZZ_SRC)/hb-buffer.h $(HARFBUZZ_SRC)/hb-common.h \
$(HARFBUZZ_SRC)/hb-deprecated.h $(HARFBUZZ_SRC)/hb-draw.h \
$(HARFBUZZ_SRC)/hb-face.h $(HARFBUZZ_SRC)/hb-font.h \
- $(HARFBUZZ_SRC)/hb-map.h $(HARFBUZZ_SRC)/hb-ot-deprecated.h \
- $(HARFBUZZ_SRC)/hb-paint.h $(HARFBUZZ_SRC)/hb-set.h \
- $(HARFBUZZ_SRC)/hb-shape.h $(HARFBUZZ_SRC)/hb-shape-plan.h \
- $(HARFBUZZ_SRC)/hb-style.h \
+ $(HARFBUZZ_SRC)/hb-fontations.h $(HARFBUZZ_SRC)/hb-map.h \
+ $(HARFBUZZ_SRC)/hb-ot-deprecated.h $(HARFBUZZ_SRC)/hb-paint.h \
+ $(HARFBUZZ_SRC)/hb-set.h $(HARFBUZZ_SRC)/hb-shape.h \
+ $(HARFBUZZ_SRC)/hb-shape-plan.h $(HARFBUZZ_SRC)/hb-style.h \
$(HARFBUZZ_SRC)/hb-subset-serialize.h \
$(HARFBUZZ_SRC)/hb-unicode.h $(HARFBUZZ_BLD)/hb-version.h \
$(HARFBUZZ_SRC)/hb-ot.h $(HARFBUZZ_SRC)/hb-ot-color.h \
Modified: trunk/Build/source/libs/harfbuzz/version.ac
===================================================================
--- trunk/Build/source/libs/harfbuzz/version.ac 2025-03-23 20:22:52 UTC (rev 74728)
+++ trunk/Build/source/libs/harfbuzz/version.ac 2025-03-24 00:38:36 UTC (rev 74729)
@@ -8,4 +8,4 @@
dnl --------------------------------------------------------
dnl
dnl m4-include this file to define the current harfbuzz version
-m4_define([harfbuzz_version], [10.4.0])
+m4_define([harfbuzz_version], [11.0.0])
More information about the tex-live-commits
mailing list.