diff options
Diffstat (limited to 'Build')
173 files changed, 13600 insertions, 1834 deletions
diff --git a/Build/source/libs/README b/Build/source/libs/README index 40ab740d995..8ae77021eaa 100644 --- a/Build/source/libs/README +++ b/Build/source/libs/README @@ -25,8 +25,8 @@ graphite2 1.3.14 - checked 10apr20 http://sourceforge.net/projects/silgraphite/files/graphite2/ (requires C++11) -harfbuzz 7.3.0 - checked 10may23 - https://github.com/harfbuzz/harfbuzz/releases/tag/7.3.0 +harfbuzz 8.0.0 - checked 09jul23 + https://github.com/harfbuzz/harfbuzz/releases/tag/8.0.0 icu 72.1 - checked 07jan23 https://github.com/unicode-org/icu/releases/ diff --git a/Build/source/libs/harfbuzz/ChangeLog b/Build/source/libs/harfbuzz/ChangeLog index 7902e4ab167..e921dc1e8a5 100644 --- a/Build/source/libs/harfbuzz/ChangeLog +++ b/Build/source/libs/harfbuzz/ChangeLog @@ -1,3 +1,8 @@ +2023-07-09 Akira Kakuto <kakuto@jcom.zaq.ne.jp> + + Import harfbuzz-8.0.0. + * version.ac, Makefile.am: Adjusted. + 2023-05-10 Akira Kakuto <kakuto@jcom.zaq.ne.jp> Import harfbuzz-7.3.0. diff --git a/Build/source/libs/harfbuzz/Makefile.am b/Build/source/libs/harfbuzz/Makefile.am index 750810d4935..770e25830a7 100644 --- a/Build/source/libs/harfbuzz/Makefile.am +++ b/Build/source/libs/harfbuzz/Makefile.am @@ -138,11 +138,10 @@ libharfbuzz_a_SOURCES = \ @HARFBUZZ_TREE@/src/hb-subset-cff-common.cc \ @HARFBUZZ_TREE@/src/hb-subset-cff-common.hh \ @HARFBUZZ_TREE@/src/hb-subset-cff1.cc \ - @HARFBUZZ_TREE@/src/hb-subset-cff1.hh \ @HARFBUZZ_TREE@/src/hb-subset-cff2.cc \ - @HARFBUZZ_TREE@/src/hb-subset-cff2.hh \ @HARFBUZZ_TREE@/src/hb-subset-input.hh \ @HARFBUZZ_TREE@/src/hb-subset-instancer-solver.cc \ + @HARFBUZZ_TREE@/src/hb-subset-instancer-solver.hh \ @HARFBUZZ_TREE@/src/hb-subset.hh \ @HARFBUZZ_TREE@/src/hb-ucd-table.hh \ @HARFBUZZ_TREE@/src/hb-ucd.cc \ diff --git a/Build/source/libs/harfbuzz/Makefile.in b/Build/source/libs/harfbuzz/Makefile.in index 2b2a13fbbcf..df897960894 100644 --- a/Build/source/libs/harfbuzz/Makefile.in +++ b/Build/source/libs/harfbuzz/Makefile.in @@ -822,11 +822,10 @@ libharfbuzz_a_SOURCES = @HARFBUZZ_TREE@/src/hb-algs.hh \ @HARFBUZZ_TREE@/src/hb-subset-cff-common.cc \ @HARFBUZZ_TREE@/src/hb-subset-cff-common.hh \ @HARFBUZZ_TREE@/src/hb-subset-cff1.cc \ - @HARFBUZZ_TREE@/src/hb-subset-cff1.hh \ @HARFBUZZ_TREE@/src/hb-subset-cff2.cc \ - @HARFBUZZ_TREE@/src/hb-subset-cff2.hh \ @HARFBUZZ_TREE@/src/hb-subset-input.hh \ @HARFBUZZ_TREE@/src/hb-subset-instancer-solver.cc \ + @HARFBUZZ_TREE@/src/hb-subset-instancer-solver.hh \ @HARFBUZZ_TREE@/src/hb-subset.hh \ @HARFBUZZ_TREE@/src/hb-ucd-table.hh \ @HARFBUZZ_TREE@/src/hb-ucd.cc \ diff --git a/Build/source/libs/harfbuzz/TLpatches/ChangeLog b/Build/source/libs/harfbuzz/TLpatches/ChangeLog index 03674f018bf..dd9f36eaae0 100644 --- a/Build/source/libs/harfbuzz/TLpatches/ChangeLog +++ b/Build/source/libs/harfbuzz/TLpatches/ChangeLog @@ -1,3 +1,8 @@ +2023-07-09 Akira Kakuto <kakuto@jcom.zaq.ne.jp> + + Imported harfbuzz-8.0.0 source tree from: + https://github.com/harfbuzz/harfbuzz/releases/download/8.0.0/ + 2023-05-10 Akira Kakuto <kakuto@jcom.zaq.ne.jp> Imported harfbuzz-7.3.0 source tree from: diff --git a/Build/source/libs/harfbuzz/TLpatches/TL-Changes b/Build/source/libs/harfbuzz/TLpatches/TL-Changes index f8d67d9d627..8bc3ce1a166 100644 --- a/Build/source/libs/harfbuzz/TLpatches/TL-Changes +++ b/Build/source/libs/harfbuzz/TLpatches/TL-Changes @@ -1,5 +1,5 @@ -Changes applied to the harfbuzz-7.3.0/ tree as obtained from: - https://github.com/harfbuzz/harfbuzz/releases/download/7.3.0/ +Changes applied to the harfbuzz-8.0.0/ tree as obtained from: + https://github.com/harfbuzz/harfbuzz/releases/download/8.0.0/ Removed: COPYING diff --git a/Build/source/libs/harfbuzz/configure b/Build/source/libs/harfbuzz/configure index 30cb9d4954b..2a0a9399b7e 100755 --- a/Build/source/libs/harfbuzz/configure +++ b/Build/source/libs/harfbuzz/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for harfbuzz (TeX Live) 7.3.0. +# Generated by GNU Autoconf 2.71 for harfbuzz (TeX Live) 8.0.0. # # Report bugs to <tex-k@tug.org>. # @@ -611,8 +611,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='harfbuzz (TeX Live)' PACKAGE_TARNAME='harfbuzz--tex-live-' -PACKAGE_VERSION='7.3.0' -PACKAGE_STRING='harfbuzz (TeX Live) 7.3.0' +PACKAGE_VERSION='8.0.0' +PACKAGE_STRING='harfbuzz (TeX Live) 8.0.0' PACKAGE_BUGREPORT='tex-k@tug.org' PACKAGE_URL='' @@ -1346,7 +1346,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures harfbuzz (TeX Live) 7.3.0 to adapt to many kinds of systems. +\`configure' configures harfbuzz (TeX Live) 8.0.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1418,7 +1418,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of harfbuzz (TeX Live) 7.3.0:";; + short | recursive ) echo "Configuration of harfbuzz (TeX Live) 8.0.0:";; esac cat <<\_ACEOF @@ -1523,7 +1523,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -harfbuzz (TeX Live) configure 7.3.0 +harfbuzz (TeX Live) configure 8.0.0 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2064,7 +2064,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by harfbuzz (TeX Live) $as_me 7.3.0, which was +It was created by harfbuzz (TeX Live) $as_me 8.0.0, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -4823,7 +4823,7 @@ fi # Define the identity of the package. PACKAGE='harfbuzz--tex-live-' - VERSION='7.3.0' + VERSION='8.0.0' # Some tools Automake needs. @@ -5033,10 +5033,10 @@ WARNING_CFLAGS=$kpse_cv_warning_cflags -HB_VERSION_MAJOR=7 -HB_VERSION_MINOR=3 +HB_VERSION_MAJOR=8 +HB_VERSION_MINOR=0 HB_VERSION_MICRO=0 -HB_VERSION=7.3.0 +HB_VERSION=8.0.0 ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -8817,7 +8817,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by harfbuzz (TeX Live) $as_me 7.3.0, which was +This file was extended by harfbuzz (TeX Live) $as_me 8.0.0, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -8885,7 +8885,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -harfbuzz (TeX Live) config.status 7.3.0 +harfbuzz (TeX Live) config.status 8.0.0 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog index f427a88e6c4..372845e7703 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog +++ b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog @@ -1,3 +1,5275 @@ +commit b4305532a7746422e0b615eee6304119c1092fd8 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun Jul 9 02:54:30 2023 +0300 + + 8.0.0 + + NEWS | 42 ++++++++++++++++++++++++++++++++++++++++++ + configure.ac | 2 +- + docs/harfbuzz-docs.xml | 1 + + meson.build | 2 +- + src/hb-common.h | 2 +- + src/hb-ot-layout.cc | 8 ++++---- + src/hb-version.h | 6 +++--- + 7 files changed, 53 insertions(+), 10 deletions(-) + +commit 5b8ba51251b8d1603c792366b7062de836bb525c +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun Jul 9 02:50:45 2023 +0300 + + [doc] Fix warning about missing hb-gobject section + + We don’t build hb-gobject docs anymore, lets not bother gtk-doc with it. + + src/hb-gobject-structs.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 0ed946c379f1fe90c855f37dd31e5377beae4946 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun Jul 9 03:01:47 2023 +0300 + + [wasm] Fix warning + + In file included from src/harfbuzz.cc:62: + src/hb-wasm-shape.cc:27:9: warning: 'HB_DEBUG_WASM' macro redefined [-Wmacro-redefined] + ^ + src/hb-debug.hh:393:9: note: previous definition is here + ^ + 1 warning generated. + + src/hb-wasm-shape.cc | 1 + + 1 file changed, 1 insertion(+) + +commit afe0910295f0b5bd245d68d5b142bcc9319b87ee +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun Jul 9 02:45:52 2023 +0300 + + [font] Actually deprecate get_glyph_shape() + + We previously marked it as deprecated in the documentation but didn’t + actually deprecate it in code. Now the only known users have migrated to + draw_glyph(), lets deprecate o=it for good. + + docs/harfbuzz-sections.txt | 6 +++--- + src/hb-deprecated.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + src/hb-font.cc | 4 ++++ + src/hb-font.h | 45 +-------------------------------------------- + src/main.cc | 4 ++-- + test/api/test-ot-face.c | 2 +- + 6 files changed, 57 insertions(+), 50 deletions(-) + +commit c6a01441d9ce638634f193dbc9aadd8c432de55b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 16:32:15 2023 -0600 + + [sanitize] Always-inline OffsetTo::sanitize() + + 8% speed up in sanitizing Gulzar. + + src/hb-open-type.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit f60dbd906a4bf89354af1ed0616a61a5099d8c1a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 16:21:24 2023 -0600 + + Fix thinko + + Fixes https://oss-fuzz.com/testcase-detail/4787105656864768 + + src/hb-open-type.hh | 8 ++++---- + ...uzz-testcase-minimized-hb-shape-fuzzer-4787105656864768 | Bin 0 -> 44 bytes + 2 files changed, 4 insertions(+), 4 deletions(-) + +commit d84c5f29b71aa7b1ff2d09cf4dc2cf3fccc5659e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 15:22:51 2023 -0600 + + Revert "[gsubgpos] Make (Chain)Context funcs templatized" + + This reverts commit 03ac08d267eb7ad2f1ac039115fc0030ea475fae. + + src/OT/Layout/GSUB/Ligature.hh | 13 +-- + .../Layout/GSUB/ReverseChainSingleSubstFormat1.hh | 8 +- + src/hb-ot-layout-gsubgpos.hh | 93 +++++++++------------- + 3 files changed, 47 insertions(+), 67 deletions(-) + +commit e73223b9e59a4f0af54880d3e26f8db55688f291 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 15:22:18 2023 -0600 + + [gsubgpos] Make (Chain)Context funcs templatized + + Unfortunately they still won't be inlined because the matcher_t + needs function pointers. So, no speed up. Going to revert. + + src/OT/Layout/GSUB/Ligature.hh | 13 ++- + .../Layout/GSUB/ReverseChainSingleSubstFormat1.hh | 8 +- + src/hb-ot-layout-gsubgpos.hh | 93 +++++++++++++--------- + 3 files changed, 67 insertions(+), 47 deletions(-) + +commit 3e3820badd9d72d908334a862d546bcb64ccfd30 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 14:36:23 2023 -0600 + + Simplify a few bool returns + + Unnecessary. Cast to bool does the job. + + src/hb-ot-layout.hh | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +commit 1c8d54deeff506d66e91ff84a8bd43698ec91387 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 14:28:07 2023 -0600 + + [shape] Another always-inline + + src/hb-ot-layout-gsubgpos.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit df45067fbb14a62c2048bf1b01349bf17f90ee6d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 14:22:59 2023 -0600 + + [shape] More always-inline + + src/hb-ot-layout-gsubgpos.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit c3a28be5094f23b0806f94c069ff3d888f065d48 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 14:20:45 2023 -0600 + + [shape] One more always-inline + + src/hb-ot-layout-gsubgpos.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit 728812348185194de87e5558a5770351d12447bf +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 14:14:27 2023 -0600 + + Allow overriding HB_ALWAYS_INLINE + + src/hb.hh | 2 ++ + 1 file changed, 2 insertions(+) + +commit 9fea19ebff62a4e9aa344e271d58acf416214d2a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 13:56:24 2023 -0600 + + [shape] Another always-inline + + src/hb-ot-layout-gsubgpos.hh | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +commit 5b45c56c9ecae7a5d67d336219aab4d971573bab +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 13:47:41 2023 -0600 + + [shape] Always-inline more + + Another 10% speedup in BM_Shape Gulzar-Regular. + + src/hb-ot-layout-gsubgpos.hh | 47 ++++++++++++++++++++++++++++++++------------ + 1 file changed, 34 insertions(+), 13 deletions(-) + +commit bb9692e8a3b1a17481dae46c57e1727361f96e26 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 13:45:48 2023 -0600 + + [shape] Always-inline match_input + + 10% speedup in BM_Shape Gulzar-Regular. + + src/hb-ot-layout-gsubgpos.hh | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +commit 6c451054fbbee75ffc4a68e423786bf19648e315 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 12:55:34 2023 -0600 + + [sanitize] Sprinkle a few unlikely's + + src/hb-ot-layout-gsubgpos.hh | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +commit 4ecc62c28d392a00d8f613da565fae335930a88d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 12:53:23 2023 -0600 + + [sanitize] Simplify ChainRule::sanitize again + + check_struct does the same now. + + src/hb-ot-layout-gsubgpos.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 253ec08b3db433f07175f21f90555657a9ce55f3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 12:48:05 2023 -0600 + + [sanitize] Speed up check_struct on x64 + + src/hb-sanitize.hh | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +commit fb02f4a8975655b405ac4bc3f9982383f33ea6dc +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 8 12:29:18 2023 -0600 + + [sanitize] Micro-optimize ChainRule::sanitize + + src/hb-ot-layout-gsubgpos.hh | 7 ++++--- + src/hb-sanitize.hh | 18 ++++++++++++++++++ + 2 files changed, 22 insertions(+), 3 deletions(-) + +commit c650858c639764717f3d7276ad67bd5bf55aaedc +Author: Khaled Hosny <khaled@libreoffice.org> +Date: Sat Jul 8 13:57:05 2023 +0300 + + [graphite] Fix cluster advance width + + Based on https://github.com/harfbuzz/harfbuzz/issues/4309#issuecomment-1624730406 + + Fixes https://github.com/harfbuzz/harfbuzz/issues/4309 + + src/hb-graphite2.cc | 5 +++-- + src/wasm/graphite/shape.cc | 5 +++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +commit 73ee9c346f3acccbe14a4caf258b636de7c459be +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 22:47:20 2023 -0600 + + Revert "[sanitize] Only check trailing edge of ranges" + + This reverts commit e4856cf8098b9741a910e7f7979096cf11d8fead. + + This is wrong on at least 32-bit systems. Might add a condition + version later. + + src/hb-sanitize.hh | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +commit 0b879afb5abda0af4624dd2cedf609acb4d17c87 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 22:35:43 2023 -0600 + + [sanitize] Inline Coverage::sanitize + + src/OT/Layout/Common/Coverage.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit 92448910a76e399afce6375923dbcf36bc3a541e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 22:16:24 2023 -0600 + + [sanitize] Minor inline a few more short functions + + src/hb-open-type.hh | 6 ++++++ + 1 file changed, 6 insertions(+) + +commit d84504206c420250bfe80bee25f6a59a7177c9eb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 21:56:17 2023 -0600 + + [sanitize] Optimize away an overflow check when not needed + + When the length argument is 16bit... + + src/hb-open-type.hh | 8 ++++---- + src/hb-sanitize.hh | 14 ++++++++++++++ + 2 files changed, 18 insertions(+), 4 deletions(-) + +commit e4856cf8098b9741a910e7f7979096cf11d8fead +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 21:21:33 2023 -0600 + + [sanitize] Only check trailing edge of ranges + + Assumptions... + + Speeds up Gulzar load_face_and_shape benchmark by 7%. + + src/hb-sanitize.hh | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +commit 6a683ea6ebc4d187d3f9ccf1a5c087b30cd82f27 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 21:02:15 2023 -0600 + + [sanitize] Enlighten check_range() some more + + No need to check for len=0 arrays. They must still be in range. + + src/hb-ot-var-fvar-table.hh | 3 ++- + src/hb-sanitize.hh | 7 +++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +commit c24ea1036b45ea48ecc3081698ec04be646b74d0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 20:43:20 2023 -0600 + + [sanitize] Minor tweak to len=0 case which is handled otherwise anyway + + src/hb-sanitize.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 403bc7caa41474644b4a7c14046c70ec8013c385 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 20:17:32 2023 -0600 + + [sanitize] Simplify Rule::sanitize() + + src/hb-ot-layout-gsubgpos.hh | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 385896ff665a167ffcc633ebf84280549d9f5b2e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 19:56:19 2023 -0600 + + [sanitize] Speed up ChainRule::sanitize() + + 10% speedup in sanitizing Gulzar-Regular. + + src/hb-ot-layout-gsubgpos.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 2006d3211f300b1f602d9701f4b26634fe6f21b7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 17:07:11 2023 -0600 + + [sanitize] Add "fastpath" for ArrayOfOffset16To<> objects with max size + + Unfortunately this doesn't speed up NotoNastaliq or Gulzar as I was + hoping for. Their GSUB tables are not large enough for this to kick + in... + + src/OT/Layout/GSUB/Ligature.hh | 1 + + src/hb-machinery.hh | 4 ++++ + src/hb-null.hh | 9 +++++++++ + src/hb-open-type.hh | 25 +++++++++++++++++++++++++ + src/hb-ot-layout-gsubgpos.hh | 2 ++ + 5 files changed, 41 insertions(+) + +commit 7a85663c2bd9a0e553bf6c02ca92f7c645bed915 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 19:21:18 2023 -0600 + + Revert "[sanitize] Add "fastpath" for ArrayOfOffset16To<> objects with max size" + + This reverts commit 10f8556c73f3cf231c6b5a900a6a1903f9516f90. + + This was, unfortunately, wrong :(. + + src/OT/Layout/GSUB/Ligature.hh | 5 +---- + src/hb-machinery.hh | 4 ---- + src/hb-null.hh | 9 --------- + src/hb-open-type.hh | 25 ------------------------- + src/hb-ot-layout-gsubgpos.hh | 12 ++---------- + 5 files changed, 3 insertions(+), 52 deletions(-) + +commit f2a3680fab317a67416c267ea8fc51cc7206b3f0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 19:21:03 2023 -0600 + + Revert "[gsubgpos] Limit (Chain)ContextFormat3 for consistency" + + This reverts commit 90b48917dadbef51bc5e90904d0f81e81199b9e2. + + src/hb-ot-layout-gsubgpos.hh | 32 +++++++++++++------------------- + 1 file changed, 13 insertions(+), 19 deletions(-) + +commit 90b48917dadbef51bc5e90904d0f81e81199b9e2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 18:50:01 2023 -0600 + + [gsubgpos] Limit (Chain)ContextFormat3 for consistency + + src/hb-ot-layout-gsubgpos.hh | 32 +++++++++++++++++++------------- + 1 file changed, 19 insertions(+), 13 deletions(-) + +commit 3b02f694e80dd3c1b0517145ef7b075c9c9acb05 +Merge: 10f8556c7 68b789145 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 18:39:28 2023 -0600 + + [sanitize/GSUBGPOS] Limit max-size of a few offset arrays + + This significantly speeds up Gulzar-Regular sanitize, by 40%. + +commit 10f8556c73f3cf231c6b5a900a6a1903f9516f90 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 17:07:11 2023 -0600 + + [sanitize] Add "fastpath" for ArrayOfOffset16To<> objects with max size + + src/OT/Layout/GSUB/Ligature.hh | 5 ++++- + src/hb-machinery.hh | 4 ++++ + src/hb-null.hh | 9 +++++++++ + src/hb-open-type.hh | 25 +++++++++++++++++++++++++ + src/hb-ot-layout-gsubgpos.hh | 12 ++++++++++-- + 5 files changed, 52 insertions(+), 3 deletions(-) + +commit 68b78914595347008eb344859699dc62257a7a67 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 17:07:11 2023 -0600 + + [sanitize] Add "fastpath" for ArrayOfOffset16To<> objects with max size + + Unfortunately this doesn't speed up NotoNastaliq or Gulzar as I was + hoping for. Their GSUB tables are not large enough for this to kick + in... + + src/OT/Layout/GSUB/Ligature.hh | 1 + + src/hb-machinery.hh | 4 ++++ + src/hb-null.hh | 9 +++++++++ + src/hb-open-type.hh | 25 +++++++++++++++++++++++++ + src/hb-ot-layout-gsubgpos.hh | 2 ++ + 5 files changed, 41 insertions(+) + +commit 90752cd5b76d1768afc10e9bcab4235d97e7686f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 15:47:28 2023 -0600 + + [type] Add HeadlessArray16Of + + src/OT/Layout/GSUB/Ligature.hh | 2 +- + src/hb-open-type.hh | 3 ++- + src/hb-ot-layout-gsubgpos.hh | 2 +- + 3 files changed, 4 insertions(+), 3 deletions(-) + +commit 59abcda269e7148131d00d17218f5718f217bf13 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jul 7 14:27:18 2023 -0600 + + [sanitize] Add an ALWAYS_INLINE + + Looks like it was always inlined anyway. + + src/hb-sanitize.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit 45a17212304de8787b509cc9375bb92571fca9f5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jul 6 16:06:50 2023 -0600 + + [ot-font] Prefer CFF2 over CFF1 + + src/hb-ot-font.cc | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +commit 43d0aff672981f2efca6b7398e81f020676ad442 +Author: أحمد المحمودي <96682+aelmahmoudy@users.noreply.github.com> +Date: Tue Jul 4 09:22:53 2023 +0300 + + [introspection] Pass both libharfbuzz_gobject & libharfbuzz as positional parameters + + Fixes #4304 + + src/meson.build | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 25297408de73f8bf31ebecd241f959455ed00e95 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jul 3 10:34:26 2023 -0600 + + [COLR] Fix PaintComposite sanitize timeout + + Was timing out after recent sanitize() change. + + Fixes https://oss-fuzz.com/testcase-detail/5692635449524224 + + src/OT/Color/COLR/COLR.hh | 1 + + ...uzz-testcase-minimized-hb-draw-fuzzer-5692635449524224 | Bin 0 -> 185 bytes + 2 files changed, 1 insertion(+) + +commit a8c655e6510c33de2241b854c1a37ffbe2eee9ff +Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> +Date: Mon Jul 3 10:17:36 2023 +0000 + + Bump actions/checkout from 3.5.1 to 3.5.3 + + Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.1 to 3.5.3. + - [Release notes](https://github.com/actions/checkout/releases) + - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) + - [Commits](https://github.com/actions/checkout/compare/v3.5.1...c85c95e3d7251135ab7dc9ce3241c5835cc595a9) + + --- + updated-dependencies: + - dependency-name: actions/checkout + dependency-type: direct:production + update-type: version-update:semver-patch + ... + + Signed-off-by: dependabot[bot] <support@github.com> + + .github/workflows/scorecard.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit de2c10732df151156ac55afdf648f3fd296dfa50 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 16:44:48 2023 -0600 + + [ot-map] Speed up for default shaper + + Sort late, the reduced number of features. + + src/hb-ot-map.cc | 6 ++++-- + src/hb-ot-map.hh | 8 ++++++++ + src/hb-ot-shape.cc | 7 +++++++ + 3 files changed, 19 insertions(+), 2 deletions(-) + +commit 8156c5a6856a3c9c0cc98714dc047fe4a703d603 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 16:35:32 2023 -0600 + + [ot-map] Minor micro-optimize + + src/hb-ot-map.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 5ac9eaa035402fe0369baadea3c945c58a4534ed +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 16:18:08 2023 -0600 + + [sanitize] Minor micro-optimize + + src/hb-sanitize.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit e8948d634e1835f379053d9b924b834137967b86 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 15:35:18 2023 -0600 + + [set-digest] Micro-optimize more + + src/hb-set-digest.hh | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +commit cb73ba710480f698828b8d6526605849d6899bad +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 15:27:26 2023 -0600 + + [set-digest] Fixup for previous commit + + src/hb-set-digest.hh | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 918ad8929403d2106fdca1370a1c3e9929e301f9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 14:54:24 2023 -0600 + + [set-digest] Early terminate add_range() if we're full + + src/hb-set-digest.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit bb33675e60be3884a3d6adf6417c353f0202e70f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 14:11:40 2023 -0600 + + [sanitize] Micro-optimize check_range() + + src/hb-sanitize.hh | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +commit d1c82a1cc68667ff8ca6c1fe2b4fa277504c0a5c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 13:38:22 2023 -0600 + + [sanitize] Speed up check_struct() + + Don't account for length here. Should not be a problem. + Fingers crossed fuzzers. + + 18% speed up in load_face_and_shape Gulzar-Regular. + + src/hb-sanitize.hh | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +commit ec943866229b44b26b79cd271a1e3f874fe16e7c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 13:29:53 2023 -0600 + + [OffsetTo] Micro-optimize away a check + + src/hb-open-type.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit eae8278896e1dcd6d8eecb9401785acdf76f81a6 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 13:07:26 2023 -0600 + + [GPOS] Micro-optimize lazy_some_gpos check + + Speeds up 11% in: + BM_Font/load_face_and_shape/Roboto-Regular.ttf/hb + + src/OT/Layout/GPOS/PairPosFormat2.hh | 5 +++-- + src/OT/Layout/GPOS/PairSet.hh | 5 +++-- + src/OT/Layout/GPOS/ValueFormat.hh | 6 +++--- + 3 files changed, 9 insertions(+), 7 deletions(-) + +commit 46e54a23907eb5f46977ceac22abb4d43fcd7061 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 13:03:16 2023 -0600 + + [GPOS] Remove extra check + + src/OT/Layout/GPOS/ValueFormat.hh | 3 --- + 1 file changed, 3 deletions(-) + +commit 13438da16e5967b2600cb347ad5a179812526ba2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 12:56:13 2023 -0600 + + [benchmark-font] Minor move a variable + + perf/benchmark-font.cc | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +commit 7f5380fe949ba64fab19d86f670e2215249cbb96 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 12:19:22 2023 -0600 + + [Composite] Don't apply transformation if phantom_only + + src/OT/glyf/Glyph.hh | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +commit 0cf759b0d4c8c1252347f2d92dd10202672d4191 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 12:15:43 2023 -0600 + + [Glyph] Don't shift anchored Composite if phantom_only + + Fixes https://oss-fuzz.com/testcase-detail/5114131137822720 + + src/OT/glyf/Glyph.hh | 2 +- + ...z-testcase-minimized-hb-shape-fuzzer-5114131137822720 | Bin 0 -> 5119 bytes + 2 files changed, 1 insertion(+), 1 deletion(-) + +commit 645bde473818a14368ea9f95261037160c574d05 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 12:07:22 2023 -0600 + + [Glyph] Pass phantom-only to gvar only for SIMPLE glyphs + + For Composites we need to get the translation offset deltas. + + src/OT/glyf/Glyph.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit e92eefaabbed7aa04fe98214ae43b061d1497735 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 11:35:51 2023 -0600 + + [gvar] Cache two values in shared_tuple_active_idx + + Speeds up varc-hangul.ttf draw_glyph by 10%. + + src/hb-ot-var-common.hh | 17 ++++++++++++----- + src/hb-ot-var-gvar-table.hh | 15 +++++++++------ + 2 files changed, 21 insertions(+), 11 deletions(-) + +commit 7d72fdd5bf423dcbdf19b5bae25494e6b3c59cd0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jul 2 09:55:37 2023 -0600 + + [benchmark-font] Do some work in draw_glyph callbacks + + For no good reason other than matching what I'm adding to + skrifa benchmark. Doesn't seem to affect benchmarks whatsoever. + + perf/benchmark-font.cc | 33 +++++++++++++++++++++++++++------ + 1 file changed, 27 insertions(+), 6 deletions(-) + +commit 47b5ee6789ca9125cc4299da1f3a3c05300dff78 +Merge: 7a3566825 2d6091fc4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jul 1 14:48:39 2023 -0400 + + Merge pull request #4306 from harfbuzz/gpos-lazy-device + + GPOS lazy Device + +commit 2d6091fc42c81ba68fe6710de42d313cfda7a309 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 30 11:48:56 2023 -0600 + + [GPOS] Make AnchorMatrix sanitize lazy again + + Was reverted in the previous commit, because it was incomplete. + + src/OT/Layout/GPOS/AnchorFormat3.hh | 3 --- + src/OT/Layout/GPOS/AnchorMatrix.hh | 14 ++++++++++---- + src/OT/Layout/GPOS/MarkArray.hh | 2 +- + src/OT/Layout/GPOS/ValueFormat.hh | 6 +++--- + src/hb-ot-layout-gsubgpos.hh | 2 +- + src/hb-sanitize.hh | 4 ++-- + 6 files changed, 17 insertions(+), 14 deletions(-) + +commit 0887382cdf64f9c590eb9c086f7f5622c482e32c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 30 11:39:46 2023 -0600 + + [GPOS] Fix sanitize + + src/OT/Layout/GPOS/AnchorMatrix.hh | 3 --- + 1 file changed, 3 deletions(-) + +commit 83eb744e09bb8ff7a9c78c79569100f560f129fb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 30 11:33:39 2023 -0600 + + [sanizie] Inline check_range if not OPTIMIZE_SIZE + + BM_Font/load_face_and_shape/NotoNastaliqUrdu-Regular.ttf/hb -0.1046 -0.1051 194 173 193 172 + BM_Font/load_face_and_shape/NotoSerifMyanmar-Regular.otf/hb -0.2401 -0.2412 36 27 36 27 + + src/hb-sanitize.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit 690af7aa69b05db6a925bcdaeac4ea0d7efba5da +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 30 10:36:01 2023 -0600 + + [GPOS] Sanitize Device tables lazily + + This speeds up face loading for variable fonts by 80%! + + Comparing before to after + Benchmark Time CPU Time Old Time New CPU Old CPU New + --------------------------------------------------------------------------------------------------------------------------------------------------------------- + BM_Font/load_face_and_shape/Roboto-Regular.ttf/hb -0.0368 -0.0366 20 20 20 19 + BM_Font/load_face_and_shape/RobotoFlex-Variable.ttf/hb -0.7149 -0.7162 77 22 77 22 + BM_Font/load_face_and_shape/RobotoFlex-Variable.ttf/var/hb -0.7241 -0.7255 80 22 79 22 + BM_Font/load_face_and_shape/SourceSansPro-Regular.otf/hb -0.1441 -0.1445 28 24 28 24 + BM_Font/load_face_and_shape/AdobeVFPrototype.otf/hb -0.7893 -0.7910 66 14 66 14 + BM_Font/load_face_and_shape/AdobeVFPrototype.otf/var/hb -0.7865 -0.7882 67 14 66 14 + BM_Font/load_face_and_shape/SourceSerifVariable-Roman.ttf/hb -0.8895 -0.8900 227 25 226 25 + BM_Font/load_face_and_shape/SourceSerifVariable-Roman.ttf/var/hb -0.8895 -0.8900 226 25 225 25 + BM_Font/load_face_and_shape/Comfortaa-Regular-new.ttf/hb -0.5512 -0.5531 42 19 42 19 + BM_Font/load_face_and_shape/NotoNastaliqUrdu-Regular.ttf/hb -0.1511 -0.1510 227 192 225 191 + BM_Font/load_face_and_shape/NotoSerifMyanmar-Regular.otf/hb -0.1494 -0.1498 41 35 40 34 + OVERALL_GEOMEAN -0.6443 -0.6456 0 0 0 0 + + src/OT/Layout/GPOS/AnchorFormat3.hh | 11 +++++-- + src/OT/Layout/GPOS/AnchorMatrix.hh | 4 +++ + src/OT/Layout/GPOS/SinglePosFormat1.hh | 3 +- + src/OT/Layout/GPOS/SinglePosFormat2.hh | 3 +- + src/OT/Layout/GPOS/ValueFormat.hh | 52 +++++++++++++++++++++++++--------- + src/hb-kern.hh | 2 +- + src/hb-ot-layout-gsubgpos.hh | 12 ++++++-- + src/hb-ot-layout.cc | 5 ++-- + src/hb-ot-shaper-arabic-fallback.hh | 2 +- + src/hb-sanitize.hh | 18 +++++++++++- + 10 files changed, 87 insertions(+), 25 deletions(-) + +commit 7a35668258f8e93c867cf560ca0999d8952d1c93 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 30 10:50:25 2023 -0600 + + Minor variable fix + + src/hb-machinery.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit d338506ccf892b0ce489314d2d2f94c6b875368a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 30 10:13:05 2023 -0600 + + [GPOS] Reuse sanitize_values_stride_unsafe in another function + + src/OT/Layout/GPOS/ValueFormat.hh | 14 +++----------- + 1 file changed, 3 insertions(+), 11 deletions(-) + +commit 0fceaef0f7ec123e931fc31f9d71ba87fa60b079 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 30 08:50:49 2023 -0600 + + [benchmark-subset] Report in microseconds, not milli + + We're in that range now. :) + + perf/benchmark-subset.cc | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 547dc1a40ef6d83eb426afd1470bddf2b11bdfab +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 30 08:48:43 2023 -0600 + + [benchmark-font] Add load_face_and_shape benchmark + + To measure face-loading performance + + perf/benchmark-font.cc | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +commit fcf70af1349f2eeb9f58f67d2cc7d8e2c3ebf012 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 30 08:43:10 2023 -0600 + + [perf] Fix break + + perf/benchmark-font.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 794fac327cf13b4b4d8a66281c15df6aac2d15c6 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 20:55:52 2023 -0600 + + [glyf] Minor another range for loop + + src/OT/glyf/glyf.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 0ae167662657c084ecc26db27830b51c469240f2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 20:38:42 2023 -0600 + + [CompositeGlyph] Minor use a range for loop + + src/OT/glyf/CompositeGlyph.hh | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +commit 05c01ad5d34cf6ca4f350233eccbec129f860231 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 16:49:20 2023 -0600 + + [SimpleGlyph] Minor use a range for loop + + src/OT/glyf/SimpleGlyph.hh | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +commit 4123e0c75762ed1e6fa69e2926a4d4cee5e6747c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 16:27:35 2023 -0600 + + [path-builder] Speed up mid-point calculation + + src/OT/glyf/path-builder.hh | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +commit 73376b24cfe7cfe27b7b4b9abbe46ff441189b2a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 16:14:45 2023 -0600 + + [subset/cff1] More error handling + + src/hb-subset-cff1.cc | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +commit cc44b3bce0a7be5536df7df910b5bc73a5e4a741 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 16:12:10 2023 -0600 + + [subset/cff1] Handle an error condition + + Fixes https://oss-fuzz.com/testcase-detail/5191907895279616 + + src/hb-subset-cff1.cc | 11 +++++++---- + ...-testcase-minimized-hb-subset-fuzzer-5191907895279616 | Bin 0 -> 2025 bytes + 2 files changed, 7 insertions(+), 4 deletions(-) + +commit fc38c01ab06ac376b42b8d70c9453da45afabcc5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 15:29:15 2023 -0600 + + Minor inline a function + + src/hb-ot-var-gvar-table.hh | 1 + + 1 file changed, 1 insertion(+) + +commit a520177e523eab8bf9a407aab46d8308ac12439a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 14:56:05 2023 -0600 + + [gvar] Remove unnecessary initialization + + src/hb-ot-var-gvar-table.hh | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +commit ca44c38c5298e9ffc9b0b843c3fd5df63c9747a7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 14:41:21 2023 -0600 + + Add HB_ALWAYS_INLINE + + With MSVC implementation as well. + + src/OT/glyf/glyf.hh | 2 +- + src/OT/glyf/path-builder.hh | 2 +- + src/hb-draw.hh | 20 ++++++++++---------- + src/hb.hh | 6 ++++++ + 4 files changed, 18 insertions(+), 12 deletions(-) + +commit 0a00dc0c7197b61b7662d40d12e9432f27dbd6ec +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 14:17:47 2023 -0600 + + [draw] Add a few unlikely's + + src/hb-draw.hh | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +commit 2d9c3da06ad63066a748be486c33bed81f418868 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 13:31:11 2023 -0600 + + [draw] Inline more functions + + src/hb-draw.hh | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +commit 17f29c81110bed6b9be684b6c0cfdacb01414bb1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 13:27:09 2023 -0600 + + [benchmark_font/draw_glyphs] Implement quadratic_to + + Not interested in the fallback implementation here. + + perf/benchmark-font.cc | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit d26b3adebee059cbcc72850f4ad31ecf3f2b913f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 13:25:52 2023 -0600 + + [draw-session] Inline small functions + + src/hb-draw.hh | 5 +++++ + 1 file changed, 5 insertions(+) + +commit 7aba1e6dd2f5be40e818838ef23d0a0d605a8485 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 12:44:34 2023 -0600 + + [cache] Minor use a range for loop + + src/hb-cache.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit afae537c3ca4d2ddae2b8bee400966a08bf74e6e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 12:42:44 2023 -0600 + + [cache] Minor remove .init() + + Use constructor. + + src/hb-cache.hh | 4 +--- + src/hb-ft.cc | 2 +- + src/hb-ot-font.cc | 6 +++--- + 3 files changed, 5 insertions(+), 7 deletions(-) + +commit c49ca371151ef3afc3a4ecf0b8918cdd8ac16541 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 12:38:45 2023 -0600 + + [Glyph] Minor micro-optimize away a function call + + For when coords are not set. + + src/OT/glyf/Glyph.hh | 9 +++++---- + src/hb-ot-var-gvar-table.hh | 2 -- + 2 files changed, 5 insertions(+), 6 deletions(-) + +commit 5fb7b02ac1212e9dfde920738285a2a58d19f9e1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 12:28:43 2023 -0600 + + [CompositeGlyph] Minor use range loop + + src/OT/glyf/CompositeGlyph.hh | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +commit 20b32b049bad64d802b33979372c8cdc5a0c4cb4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 12:08:11 2023 -0600 + + [SimpleGlyph] Micro-optimize phantom_only + + src/OT/glyf/SimpleGlyph.hh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit d1660eaf32777c50400326d99211926e82ec2f35 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 11:59:03 2023 -0600 + + [subset/cff] Minor use HB_OPTIMIZE_SIZE_VAL + + src/hb-ot-cff-common.hh | 96 +++++++++++++++++++++++++------------------------ + 1 file changed, 49 insertions(+), 47 deletions(-) + +commit 04809ede8e5d9943be8a294acecdffe2f0be492f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 11:58:53 2023 -0600 + + [CompositeGlyph] Micro-optimize translate() + + src/OT/glyf/CompositeGlyph.hh | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +commit 229db9735e3832ca81a751ec318ba396aeb89d85 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 11:54:10 2023 -0600 + + [CompositeGlyph] Minor use vector::push() + + src/OT/glyf/CompositeGlyph.hh | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +commit 75101802a169b48a69a82f64e49169d810ded741 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 10:54:49 2023 -0600 + + [CompositeGlyph] Micro-optimize + + src/OT/glyf/CompositeGlyph.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit e9d74d6bb352a2ac01554f8bdea65c3acc2879b5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 10:53:52 2023 -0600 + + [SimpleGlyph] Minor add an unlikely to error condition + + src/OT/glyf/SimpleGlyph.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 6abca413aeb7be1342180aa945f54fd45cdea12f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 10:39:49 2023 -0600 + + [path-builder] Micro-optimize + + No need to initialize these when has_data=false. + + src/OT/glyf/path-builder.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 5703c1c4ea5cc47120cba8f8b0f4fc1178f6efef +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 29 10:35:23 2023 -0600 + + [path-builder] Add a couple of unlikely's + + src/OT/glyf/path-builder.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit f5eead04e63e6092fba494471b18016cabe50a15 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 28 15:07:15 2023 -0600 + + [glyf/gvar] Optimize getting variable phantom points + + Used when there's no HVAR table and get_h_advance(). + + I see some 10% speedup with a SourceSerifVariable-Roman with + the HVAR table removed. + + src/OT/glyf/Glyph.hh | 3 ++- + src/hb-ot-var-gvar-table.hh | 30 +++++++++++++++++------------- + 2 files changed, 19 insertions(+), 14 deletions(-) + +commit e42d6df55e034b92979fb41db852c648114c18c0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 28 14:25:11 2023 -0600 + + [glyf] Minor refactor a couple of lines and micro-optimize + + src/OT/glyf/glyf.hh | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +commit c31471d10e14ca66a1b668905fac2ab40941ea41 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 28 13:51:54 2023 -0600 + + [glyf] Micro-optimize + + src/OT/glyf/glyf.hh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit 83d75d5e9b32866e62e21ca155bb176b6d3fa81e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 28 13:35:24 2023 -0600 + + [glyf] always_inline consume_point + + 7% speedup in: + BM_Font/draw_glyph/Roboto-Regular.ttf/hb + + src/OT/glyf/path-builder.hh | 1 + + 1 file changed, 1 insertion(+) + +commit 8795ccedd61ea26793d0912b5ee02fe9ae45c9aa +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 28 13:29:29 2023 -0600 + + Revert "[SimpleGlyph] Avoid branches in read_points" + + This reverts commit ba062c713e469f91f57f3c85990f721789ec7c2a. + + src/OT/glyf/SimpleGlyph.hh | 21 ++++----------------- + 1 file changed, 4 insertions(+), 17 deletions(-) + +commit ba062c713e469f91f57f3c85990f721789ec7c2a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 28 13:24:37 2023 -0600 + + [SimpleGlyph] Avoid branches in read_points + + Calculate total bytes in read_flags and bounds-check once. + + This slows things down apparently, so going to revert. + + src/OT/glyf/SimpleGlyph.hh | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +commit 62f5ed461ea5fa4fd63631ddeb505ea16e2becb4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 28 12:02:52 2023 -0600 + + [subset/cff] Fix an infinite loop + + Fixes https://oss-fuzz.com/testcase-detail/5419002026131456 + + src/hb-ot-cff-common.hh | 6 +++--- + src/hb-subset-cff-common.cc | 3 ++- + ...-testcase-minimized-hb-subset-fuzzer-5419002026131456 | Bin 0 -> 1718 bytes + 3 files changed, 5 insertions(+), 4 deletions(-) + +commit 87b573615f5f521650a325d8eb29afc736d1c8cc +Author: Chun-wei Fan <fanchunwei@src.gnome.org> +Date: Wed Jun 28 15:38:40 2023 +0800 + + README.python.md: Add some notes for Windows + + Note that the DLLs for HarfBuzz and its deps must be found %PATH% on Windows so + that pygobject is able to import and use HarfBuzz in Python scripts. + + Also note that for Visual Studio builds, it is recommended that Visual Studio + 2019 or later is used for the build, possibly in regards with how the + preprocessor handles C++ code when running g-ir-scanner. + + README.python.md | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +commit 10b9ca54e17379584bc7583b018268697f925dfd +Author: أحمد المحمودي (Ahmed El-Mahmoudy) <aelmahmoudy@users.sourceforge.net> +Date: Wed Jun 28 07:46:33 2023 +0200 + + Fix typo: subtitution -> substitution + + src/OT/Layout/GSUB/Sequence.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 73a82af1f4abe15f3e96074b5bf1a636c890c85f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 27 17:05:22 2023 -0600 + + [subset/cff] Remove stale wrong code + + With my recent rewrite of serialize_header, this seems to + work now. + + src/hb-ot-cff-common.hh | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +commit 158eba66b32c4e61a95d33fdcf9107de84073475 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 27 16:22:54 2023 -0600 + + [subset/cff] Fix compiler error + + About variable with internal linkage with no definition. + + src/hb-ot-cff-common.hh | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +commit b04721993f0501519af4835d074fdfa3700935d1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 27 16:07:54 2023 -0600 + + [subset/cff1] Micro-optimize code + + Let compiler see whether optional argument is present. + + src/hb-ot-cff-common.hh | 8 ++++++-- + src/hb-subset-cff1.cc | 2 +- + src/hb-subset-cff2.cc | 2 +- + 3 files changed, 8 insertions(+), 4 deletions(-) + +commit 1cabb65b0a8cb4db16b7616f48f245f3ace08bd3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 27 16:01:17 2023 -0600 + + [subset/cff] Micro-optimize CFFIndex::serialize_header + + Unfortunately hb_array_t::begin/end are faster than its _begin/_end. + As such, a range loop on array itself is faster than range loop on + pipeline starting with array. Rework code to loop on the array always. + + src/hb-ot-cff-common.hh | 69 ++++++++++++++++++++++++++++++------------------- + src/hb-subset-cff1.cc | 2 +- + 2 files changed, 43 insertions(+), 28 deletions(-) + +commit dfaf9cd54b06e5d4d2765abae2e09183c7765815 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 27 14:56:32 2023 -0600 + + [subset/cff1] Minor optimize + + src/hb-subset-cff1.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 41f85d0179dd60ee49e3064213bd4bbf5edaec96 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 27 12:50:04 2023 -0600 + + [benchmark-font] Add RobotoFlex + + We didn't have a variable TTF before! + + perf/benchmark-font.cc | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit 585c84268dedc94cd41edf932b86b2a28c014032 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 27 11:28:38 2023 -0600 + + [subset/cff1] Minor micro-optimize + + src/hb-subset-cff1.cc | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +commit 00904503d865c56495a49a5cf4b8c313f959dd9c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 27 08:18:18 2023 -0600 + + [config] Graduate avar2 from boring-expansion + + src/hb-config.hh | 1 - + 1 file changed, 1 deletion(-) + +commit 3edd6cdcd55dabec87ed8da9ffed82b1c41e0720 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 27 06:56:00 2023 -0600 + + [vector] Minor micro-optimize shrink_vector + + The compiler seems to understand this pattern better. + + src/hb-vector.hh | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +commit aed215639a89a7241fa5d647483326c0cad6f535 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 22:51:50 2023 -0600 + + [subset/cff1] Micro-optimize + + src/hb-ot-cff1-table.hh | 4 ++-- + src/hb-subset-cff1.cc | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +commit 40a1c08f4c7a74b71a7a832b86b94fe8f6aa06b3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 19:03:04 2023 -0600 + + [subset/cff1] Micro-optimize + + src/hb-subset-cff1.cc | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +commit bd3e78770e166c9813031d4be76ecd23c39c0c8b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 18:55:39 2023 -0600 + + [subset/cff1] Reuse a function + + src/hb-ot-cff1-table.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit ffd23d3a310caf400d9458e286adbbd4aadcbece +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 18:54:06 2023 -0600 + + [subset/cff1] Micro-optimize Charset serialization + + src/hb-ot-cff1-table.hh | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +commit 452557cd18e8072b07e48464a0428fecf732f32c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 18:40:54 2023 -0600 + + Replace a free with hb_free + + Ouch. + + src/OT/glyf/CompositeGlyph.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 1fc128f6095f4caa29cc1001cd87090b9f0dce80 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 18:34:27 2023 -0600 + + Replace a few memset/memcpy's with hb_ equivalents + + src/OT/glyf/VarCompositeGlyph.hh | 2 +- + src/OT/name/name.hh | 2 +- + src/hb-cairo-utils.cc | 2 +- + src/hb-cairo.cc | 2 +- + src/hb-map.hh | 2 +- + src/hb-shape.cc | 2 +- + src/hb-vector.hh | 4 ++-- + src/hb-wasm-api-buffer.hh | 12 ++++++------ + src/hb-wasm-api-face.hh | 2 +- + src/hb-wasm-api-font.hh | 6 +++--- + src/hb-wasm-shape.cc | 2 +- + 11 files changed, 19 insertions(+), 19 deletions(-) + +commit 2c359635dfb05a9f3a1ed4740203b9efae2379a8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 18:28:11 2023 -0600 + + [face-builder] Don't zero allocation + + We overwrite it. + + src/hb-open-file.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 347b94481100d2eefc88c1e6bc71aa20dcb907bb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 18:09:40 2023 -0600 + + [null] Fix getting Crap(hb_bytes_t) + + Fixes https://oss-fuzz.com/testcase-detail/6187272924692480 + + src/hb-null.hh | 6 +++--- + ...z-testcase-minimized-hb-subset-fuzzer-6187272924692480 | Bin 0 -> 609 bytes + 2 files changed, 3 insertions(+), 3 deletions(-) + +commit 49c52fa95316042390bc07bc9fe9438b63cd3320 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 17:55:29 2023 -0600 + + [cmap] Don't zero a few allocations unnecessarily + + src/hb-ot-cmap-table.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit e4b2d9c3f33be4e216d5ab6893e9899907f20680 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 17:52:37 2023 -0600 + + [pool] Don't clear unused memory + + src/hb-pool.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 6129702eb8a13eac75176772a61adfc63c185f34 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 17:34:54 2023 -0600 + + [subset/cff] Simplify some allocation embedding + + src/hb-ot-cff1-table.hh | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +commit 99db06b4d2fa420f46dceccd4c9a625d5325d8b3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 17:30:31 2023 -0600 + + [var] Simplify a couple of copy operations + + src/hb-ot-var-common.hh | 20 +++++--------------- + 1 file changed, 5 insertions(+), 15 deletions(-) + +commit 73bcd3f241aa641935235753492ddfebebf9373f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 17:24:40 2023 -0600 + + [var] Adjust a few allocations to not clean space + + Since we immediately copy. + + src/hb-ot-var-common.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit b1e7e8ba2f6705efee8633c4a63513686308c891 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 17:19:45 2023 -0600 + + [algs] Fix return of hb_memset() + + src/hb-algs.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit c2bab073916870f336ca0b4b658bf70aa99a401c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 16:34:53 2023 -0600 + + [subset/cff] Minor optimization + + src/hb-ot-cff-common.hh | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +commit 570fb4df58fcaa58c82b363f4edb5d61f1d948fb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 16:26:12 2023 -0600 + + [subset/cff] Add a vector pre-alloc + + src/hb-ot-cff-common.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit e447d394a60ee2878e16bc772d36c988c546caa6 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 16:02:41 2023 -0600 + + [subset/cff1] Micro-optimize + + src/hb-subset-cff1.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 50499e9e4094825700fdfbf19d85bcd0cdbd506d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 15:32:27 2023 -0600 + + [subset/cff1] Minor use rvalues in a few vector push() places + + src/hb-subset-cff1.cc | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +commit e5b3d4b10588befb7a2e63f5a3137344356908b7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 14:24:38 2023 -0600 + + [subset/cff1] Minor use ?: + + src/hb-subset-cff1.cc | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +commit 81e2db7cbcb87668c562329390a49d95a3a604bb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 14:17:44 2023 -0600 + + [subset/cff1] Speed up plan_subset_charset + + src/hb-ot-cff-common.hh | 2 +- + src/hb-ot-cff1-table.hh | 7 ++++--- + src/hb-subset-cff1.cc | 13 ++++++++++++- + 3 files changed, 17 insertions(+), 5 deletions(-) + +commit d3f90a8ca709f3f1b61484f832303b644ddb8744 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 14:02:26 2023 -0600 + + [subset/cff] Use a typedef for glyph_to_sid_map_t + + src/hb-ot-cff-common.hh | 2 ++ + src/hb-ot-cff1-table.hh | 12 ++++++------ + src/hb-subset-cff-common.hh | 4 ++-- + src/hb-subset-cff1.cc | 8 ++++---- + 4 files changed, 14 insertions(+), 12 deletions(-) + +commit 6783701b4e4443ae0db754d74349f05244e4316b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 12:31:22 2023 -0600 + + [subset] Handle an error condition + + Fixes https://oss-fuzz.com/testcase-detail/6306810588692480 + + src/hb-subset-plan.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 7d3d157de8c4ba87246f3ccefaede95e0f4b0566 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 12:02:21 2023 -0600 + + [subset/cff] Speed up hb_plan_subset_cff_fdselect + + src/hb-subset-cff-common.cc | 2 ++ + 1 file changed, 2 insertions(+) + +commit f79d961a319e57213e194421bede954c148cdfd7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 11:32:37 2023 -0600 + + [vector] Speedup push() + + src/hb-subset-cff1.cc | 8 +------- + src/hb-vector.hh | 5 ++--- + 2 files changed, 3 insertions(+), 10 deletions(-) + +commit b4b80bcaeabdc2e3c08649a2d75c4af0c4fb72ae +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 11:29:32 2023 -0600 + + [subset/cff1] Speed up plan_subset_charset + + src/hb-subset-cff1.cc | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +commit 7305ec47b1359ad791b1ae152d3c39aa19423715 +Merge: 4a628b236 3bdb8639e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 26 12:35:03 2023 -0400 + + Merge pull request #4300 from pnacht/scorecard-action + + Add Scorecard action + +commit 4a628b236f2adbc715d5f923143022c097c298d5 +Author: arch1t3cht <arch1t3cht@gmail.com> +Date: Mon Jun 26 15:19:29 2023 +0200 + + [meson] Remove incorrect option for ICU subproject + + Fixes #4298 . + + meson.build | 1 - + 1 file changed, 1 deletion(-) + +commit 3bdb8639e43ddf2f145c3b5c803d3648f49b834a +Author: Pedro Nacht <pedro.k.night@gmail.com> +Date: Mon Jun 26 11:25:10 2023 -0300 + + Add Scorecard badge to README + + README.md | 2 ++ + 1 file changed, 2 insertions(+) + +commit 27ef6c081ea26897d36d1ee3dbd6e503e72c9c33 +Author: Pedro Nacht <pedro.k.night@gmail.com> +Date: Mon Jun 26 11:22:18 2023 -0300 + + Create scorecard.yml + + .github/workflows/scorecard.yml | 64 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 64 insertions(+) + +commit 6c4f975dcb7d807b30c074aacb5d2b551078dbd1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 23:37:08 2023 -0600 + + Add a fuzzer font + + ...-testcase-minimized-hb-subset-fuzzer-4552226966994944 | Bin 0 -> 1524 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +commit 87f1b80d27527d50d99b998a0d734115390bcd3f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 23:14:01 2023 -0600 + + [bimap] Write with a map & vector combo + + Faster for getting keys. + + Speeds up 10% in: + BM_subset/subset_glyphs/RobotoFlex-Variable.ttf/retaingids/10 + + src/hb-bimap.hh | 61 ++++++++++++++++++++++++++++++++++++++-------- + src/hb-ot-layout-common.hh | 4 +-- + 2 files changed, 53 insertions(+), 12 deletions(-) + +commit e7ad017ca6607d9576c4292d82b6c417710a4e54 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 22:25:24 2023 -0600 + + [subset/cff] Allocate more memory for retain-gids + + To avoid serializing twice. + + 20% speedup in: + BM_subset/subset_glyphs/SourceSansPro-Regular.otf/retaingids/10 + + src/hb-subset.cc | 35 +++++++++++++++++++++++++---------- + 1 file changed, 25 insertions(+), 10 deletions(-) + +commit 30f1ab86eacdaba8c98579f3d520d7b23989b4ca +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 19:29:03 2023 -0600 + + [subset/cff1] Fix typo + + src/hb-subset-cff1.cc | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 7c7db0fcba4513e5121f8a6ff74aaec634caa26a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 19:07:40 2023 -0600 + + [subset/cff1] Minor shuffle code around + + src/hb-subset-cff1.cc | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +commit 1e09ebebc1164108e7768b3ba1c66041c424daff +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 18:24:42 2023 -0600 + + [subset/cff1] Minor use vector length instead of map population + + src/hb-subset-cff1.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 23109dde5ed517a0904a49f912c14017fcb3b10d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 18:21:57 2023 -0600 + + [subset/cff1] Minor use an exact allocation + + src/hb-subset-cff1.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 393f0f9f16944654ddd2235eacef20951ce598b7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 18:14:56 2023 -0600 + + [map] Rename resize() to alloc() + + Better matches the functionality, and hb_vector_t. + + src/hb-bimap.hh | 10 +++++----- + src/hb-map.hh | 12 ++++++------ + src/hb-multimap.hh | 4 ++-- + src/hb-ot-cmap-table.hh | 2 +- + src/hb-ot-post-table-v2subset.hh | 6 +++--- + src/hb-subset-accelerator.hh | 2 +- + src/hb-subset-cff-common.hh | 2 +- + src/hb-subset-cff1.cc | 6 +++--- + src/hb-subset-plan.cc | 10 +++++----- + 9 files changed, 27 insertions(+), 27 deletions(-) + +commit 793f663bad20a226919ec45e23ff03c3176777c3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 17:33:57 2023 -0600 + + [vector] Speed up hb_vector_t<hb_array_t<U>> + + src/hb-vector.hh | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +commit 289bad82f0ff949403e5d058372e20cc32450cbd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 17:26:40 2023 -0600 + + [subset/cff1] Minor use a dagger + + src/hb-ot-cff1-table.hh | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +commit 31d971d1aa410ef14513792b794ddb4514c0499d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 17:23:52 2023 -0600 + + [vector] Sprinkle std::addressof + + src/hb-vector.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit c03c0a9d765f2ea0b67b15f4ead4aa35c76279ae +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 17:13:59 2023 -0600 + + [subset/cff1] Remove unnecessary remap_sid_t::reset + + The object is initialized automatically. + + src/hb-subset-cff1.cc | 9 --------- + 1 file changed, 9 deletions(-) + +commit 6ed0d04b699f6353feb3ce1d23eca9348271284a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 17:10:36 2023 -0600 + + [subset/cff1] In remap_sid_t::reset(), reset everything + + Previous code wasn't resetting next=0; tests were passing. + It's always called when sidmap is empty. So, redundant, + but keeping as is. + + src/hb-subset-cff1.cc | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +commit 7e97233c352b614aa316dfeb3a161db62c7b2bcd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 17:06:02 2023 -0600 + + [subset/cff1] Comment + + src/hb-ot-cff1-table.hh | 1 + + 1 file changed, 1 insertion(+) + +commit 86a550dc7e182a53eb950278b42d0243b7185f73 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 17:01:40 2023 -0600 + + [subset/cff1] Speed up string writing + + src/hb-ot-cff1-table.hh | 10 +++++----- + src/hb-subset-cff1.cc | 17 ++++++++++++++++- + 2 files changed, 21 insertions(+), 6 deletions(-) + +commit dc1b172408ae02a64cac6edefd333d3651f7e92c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 16:35:36 2023 -0600 + + [subset/cff1] Minor reuse a returned value + + src/hb-subset-cff1.cc | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 95341bcc15944efdb352c415a3b38b6c13ba5221 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 16:31:54 2023 -0600 + + [subset/cff1] Minor use {} initialization syntax + + src/hb-subset-cff1.cc | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit be0cec288b3cabf5d20f93fc32e3586cd4a9093e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 16:01:13 2023 -0600 + + [map] Micro-optimize iteration + + Make is_real() faster (removes a shift). is_used() gets inlined + so is not slowed down by this change. + + src/hb-map.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 9dbea6071a41eb8595e888146c74ea7efb790455 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 25 14:28:02 2023 -0600 + + [subset/cff1] Fix resource leak in error case + + src/hb-subset-cff1.cc | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +commit e310473cec824c91a249bd23910ccb975d278b50 +Author: David Corbett <corbett.dav@northeastern.edu> +Date: Sat Jun 24 21:50:58 2023 -0400 + + [use] Allow multiple CMAbv glyphs on subjoined + + src/hb-ot-shaper-use-machine.rl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit d4bbe3f48663944385f25f608438e1eb678fc4b7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 18:13:30 2023 -0600 + + [subset/cff] Reuse a calculate index total data size + + src/hb-ot-cff-common.hh | 24 ++++++++++++++++-------- + src/hb-subset-cff1.cc | 5 +++-- + src/hb-subset-cff2.cc | 5 +++-- + 3 files changed, 22 insertions(+), 12 deletions(-) + +commit ec0fbf8fa6ada90f6564b2d5c69c181aa3f4011f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 16:13:13 2023 -0600 + + [subset/ClassDef] Micro-optimize use_class_zero calc + + Probably never matters. + + src/hb-ot-layout-common.hh | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +commit b557a84123a0bc9dec4dc3178301fd9a67a6c709 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 15:31:54 2023 -0600 + + [algs] Speed up fasthash for aligned uint64_t + + src/hb-algs.hh | 26 ++++++++++++++++++++++---- + 1 file changed, 22 insertions(+), 4 deletions(-) + +commit fc80d20cb5cd25ee2d2579f2da018870e76aaa0e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 15:21:30 2023 -0600 + + [serialize] Only hash at most 128 bytes for object_t + + Optimization. Shouldn't in reality bring down the hash performance. + Byte objects differ in their early bytes anyway. + + src/hb-serialize.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 19eb5e3b6ceb7f844af4f9cefdc2312ff2d763b1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 15:12:13 2023 -0600 + + [subset/cff1] Micro-optimize Charset::serialize + + src/hb-ot-cff1-table.hh | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +commit d36b87bde4ff91ad0eb0dbb19c7183c7d6d46d81 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 14:42:21 2023 -0600 + + [vector] Speed up hb_vector_t<hb_vector_t<U>>::realloc_vector + + Use in CFF subsetting. + + src/hb-vector.hh | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +commit b96eed02942e816b723abab73b272ab99b430390 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 14:30:21 2023 -0600 + + [vector] Speed up vector_t<vector_t<U>>::resize() + + Used in CFF subsetting... + + src/hb-vector.hh | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +commit b80b628a8aef423f7c04887e9802caab14fea187 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 13:41:42 2023 -0600 + + [subset/cff1] Speed up plan_subset_charset + + src/hb-ot-cff1-table.hh | 21 +++++++++++++-------- + src/hb-subset-cff1.cc | 8 ++++++++ + 2 files changed, 21 insertions(+), 8 deletions(-) + +commit 1902f6ccbb90fea33da74973657e6ecfec7a6c99 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 13:21:21 2023 -0600 + + [map] Inline an accessor function + + src/hb-map.hh | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 43d2ced8417c2a7666faf01f8e65fa14e40da2cb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 13:16:51 2023 -0600 + + [map] Minor remove a conditional + + src/hb-map.hh | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 817236dcb89672f1bd9fbbf9d43ffd5189da395e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 13:12:40 2023 -0600 + + [map] Speed up is_real + + src/hb-map.hh | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +commit 628ffd052e2c7d6c4e9ffdce529e29b319066c30 +Merge: 33507a9c2 b10cff990 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 14:43:09 2023 -0400 + + Merge pull request #4287 from googlefonts/tuple_varstore_compile + + [instancer] compile tuple variations + +commit 33507a9c27cb45947e9e1cf6999e69891d0a7ae3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 12:40:35 2023 -0600 + + [subset/cff] Micro-optimize hb_plan_subset_cff_fdselect + + src/hb-subset-cff-common.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit ecb46f701376e127de68f40ee0bda98c0ec6c63a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 12:18:33 2023 -0600 + + [subset/cff1] Comment + + src/hb-subset-plan.cc | 3 +++ + 1 file changed, 3 insertions(+) + +commit 4332cb3376b03cf5d4acfb044228632da50a2a6a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 12:03:42 2023 -0600 + + [subset] Fix bot failure + + src/hb-subset.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit c4b2950debbe5ebeca88c68ec43f42398d4969a7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 11:55:39 2023 -0600 + + [subset/cff1] Use cached subset-accel for seac calculations + + Before we were creating a new (non-subset) accel each time. + + src/hb-ot-cff1-table.cc | 6 +++--- + src/hb-ot-cff1-table.hh | 4 +++- + src/hb-ot-cff2-table.hh | 2 ++ + src/hb-subset-plan.cc | 9 +++++---- + 4 files changed, 13 insertions(+), 8 deletions(-) + +commit b10cff9906de237cb7f56abd9e4ba99959966954 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jun 20 13:36:10 2023 -0700 + + [instancer] address review comments + + manage memory through vector when possible + + src/hb-ot-var-common.hh | 267 ++++++++++++++++++++++---------------------- + src/hb-ot-var-cvar-table.hh | 18 ++- + src/test-tuple-varstore.cc | 8 +- + 3 files changed, 149 insertions(+), 144 deletions(-) + +commit 5f3991391863e97f84842d32c0b18e83e5ed2081 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 11:22:01 2023 -0600 + + [subset/cff] Move lazy cff-accelerator to cff-subset-accelerator + + Fixes https://github.com/harfbuzz/harfbuzz/issues/4295 + + src/hb-ot-cff1-table.hh | 8 ++++++++ + src/hb-ot-cff2-table.hh | 8 ++++++++ + src/hb-subset-accelerator.hh | 4 ---- + src/hb-subset-cff-common.hh | 9 +++------ + src/hb-subset-cff1.cc | 13 ++++++------- + src/hb-subset-plan.cc | 3 --- + src/hb-subset.cc | 8 ++++++-- + 7 files changed, 31 insertions(+), 22 deletions(-) + +commit 3a827123a1a4db75ab621e2c94e65816e4eaba58 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 11:16:57 2023 -0600 + + [benchmark-subset] Free cached face upon exist + + For better valgrind output. + + perf/benchmark-subset.cc | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +commit 97d63e8d1d935cb1fdca08ccb0b53646a0165b13 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 10:43:34 2023 -0600 + + [subset/cff] Move serialize to accelerator + + src/hb-ot-cff1-table.hh | 2 ++ + src/hb-ot-cff2-table.hh | 3 +++ + src/hb-subset-cff1.cc | 33 ++++++++++++++++++--------------- + src/hb-subset-cff2.cc | 34 ++++++++++++++++++---------------- + 4 files changed, 41 insertions(+), 31 deletions(-) + +commit 7344411cc248742358d623b4954558bcd21daa73 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 10:27:44 2023 -0600 + + [subset] Sprinkle some HB_NO_SUBSET_CFF + + src/hb-subset-accelerator.hh | 3 +++ + src/hb-subset-plan.cc | 7 +++++-- + src/hb-subset-plan.hh | 2 ++ + src/hb-subset.cc | 2 ++ + 4 files changed, 12 insertions(+), 2 deletions(-) + +commit 26f320dcd349813ec687fa0aaab40b2e844db6ca +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 10:24:32 2023 -0600 + + [subset/cff] Remove unused method + + src/hb-ot-cff1-table.hh | 2 -- + src/hb-ot-cff2-table.hh | 2 -- + src/hb-subset-cff1.cc | 7 ------- + src/hb-subset-cff2.cc | 7 ------- + 4 files changed, 18 deletions(-) + +commit 43ec78f92c4c26c50a9cddabfb36de697b41d4e0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 23 10:22:30 2023 -0600 + + [subset/cff] Cache CFF accelerator in hb_subset_plan_t + + This shows 7% speedup in: + BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/retaingids/10 + + src/hb-atomic.hh | 1 + + src/hb-machinery.hh | 9 ++++++- + src/hb-ot-cff1-table.hh | 15 ++++++++++- + src/hb-ot-cff2-table.hh | 15 ++++++++++- + src/hb-subset-accelerator.hh | 29 +++++++++++---------- + src/hb-subset-cff-common.hh | 5 +--- + src/hb-subset-cff1.cc | 13 +++++----- + src/hb-subset-cff2.cc | 11 ++++---- + src/hb-subset-plan.cc | 40 +++++++++++++++++++++++++++- + src/hb-subset-plan.hh | 62 ++++++++++++++++++++++---------------------- + src/hb-subset.cc | 38 +++++++++++++++++++++------ + 11 files changed, 165 insertions(+), 73 deletions(-) + +commit 154aae3af6db4c9b20060ec9e610fcdd0c1db366 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 20:41:16 2023 -0600 + + [subset] Minor use an auto variable + + I need this later. :D + + src/hb-subset.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 64e49e0f71d02ccc1209f75aa725ef073a7fb036 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 20:27:20 2023 -0600 + + [subset-cff2] Store num_glyphs in plan + + Like cff1 code does. + + Also, check for .notdef, like cff1 code does. + + src/hb-subset-cff2.cc | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +commit f05561dd4ef8002e89eaec4cac92b64090417660 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 20:25:04 2023 -0600 + + [subset-cff1] Use plan.num_glyphs instead of passing again + + src/hb-subset-cff1.cc | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +commit 7a124a0b4e4a3b901f3cb7bd9d4df76f176be0c6 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 20:18:20 2023 -0600 + + [cff1] Use constructor for accelerator_templ_t + + src/hb-ot-cff1-table.hh | 68 ++++++++++++++++++++++++------------------------- + src/hb-ot-cff2-table.hh | 1 - + src/hb-subset-cff1.cc | 8 ++---- + 3 files changed, 36 insertions(+), 41 deletions(-) + +commit ad025ddf05f1c9dc3eaaea00cd1a80adba7fa8bd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 20:09:36 2023 -0600 + + [subset-cff] Simplify a bit + + src/Makefile.sources | 2 -- + src/hb-ot-cff1-table.hh | 3 +-- + src/hb-ot-cff2-table.hh | 3 +-- + src/hb-subset-cff-common.hh | 3 +++ + src/hb-subset-cff1.cc | 3 +-- + src/hb-subset-cff1.hh | 37 ------------------------------------- + src/hb-subset-cff2.cc | 3 +-- + src/hb-subset-cff2.hh | 37 ------------------------------------- + src/meson.build | 2 -- + 9 files changed, 7 insertions(+), 86 deletions(-) + +commit e1753782c18beea4cee93001924985b83db92ccf +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 19:45:29 2023 -0600 + + [subset-cff] Handle an error condition + + src/hb-subset-cff-common.hh | 1 + + 1 file changed, 1 insertion(+) + +commit cb5f4d0c68d081f75245bdd0da9d75b0726acac5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 18:46:33 2023 -0600 + + [subset-plan] Avoid a copy in freeing name-table-overrides + + src/hb-map.hh | 2 +- + src/hb-subset-plan.hh | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +commit d8fba5c6b016e7d6cead4b000b6947b9db240176 +Author: David Corbett <corbett.dav@northeastern.edu> +Date: Thu Jun 22 19:25:54 2023 -0400 + + [use] Add FM categories to `POST_BASE_FLAGS64` + + src/hb-ot-shaper-use.cc | 3 +++ + .../fonts/d0430ea499348c420946f6abc2efc84fdf8f00e3.ttf | Bin 0 -> 1308 bytes + test/shape/data/in-house/tests/use-syllable.tests | 1 + + 3 files changed, 4 insertions(+) + +commit 6a17622a75cf8dea9f1cf5f7b1e4d9be9145ac49 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 18:35:10 2023 -0600 + + [array] Speed up iteration + + These are faster than relying on the random-access methods + (forward, rewind, item_it). + + src/hb-array.hh | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +commit f839bd11d250b953712733bdb3187eec3bf67419 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 17:29:57 2023 -0600 + + [multimap] Use one fewer object + + Also fix error-checking to check for sub-object errors. + + src/hb-multimap.hh | 29 ++++++++++++++--------------- + 1 file changed, 14 insertions(+), 15 deletions(-) + +commit 280edb909b0f0b244b8deb6e0e24eb2516ac038f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 17:07:31 2023 -0600 + + [map] Use a variable instead of function for is_trivial + + src/hb-map.hh | 17 +++++++---------- + 1 file changed, 7 insertions(+), 10 deletions(-) + +commit 0aa939e70f575e8f7715530a48550ef12ae68d4d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 17:05:55 2023 -0600 + + [map] Add a constexpr + + src/hb-map.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit cf386e8ce2f28ae1ca40cec849b55e71c36636cf +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 17:02:10 2023 -0600 + + [map] Speed up resize() + + src/hb-map.hh | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +commit abd6c305ff5d1a6126624b906ceec870cd5f15ee +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 16:44:29 2023 -0600 + + [subset-plan] Micro-optimize + + src/hb-subset-plan.cc | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit 7b53d2dbdde3b90f35651a449fc55ea27a7230d9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 16:35:11 2023 -0600 + + [subset] Avoid copying gid_to_unicode multimap + + Construct it in the accelerator directly. + + src/hb-subset-accelerator.hh | 21 +++++++++++++-------- + src/hb-subset-plan.cc | 13 ------------- + 2 files changed, 13 insertions(+), 21 deletions(-) + +commit 272e159c8987afb8b6d139b89cc1267b802027aa +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 16:31:50 2023 -0600 + + [subset] Speed up populating reverse cmap + + src/hb-subset-plan.cc | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +commit 8f80d9d38db92a391ff5c0794f2a38176cd97e9e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 16:22:47 2023 -0600 + + [subset-accelerator] Avoid a multimap copy + + src/hb-subset-accelerator.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit f55619b8360505ff352c60e728dbf0c2e960e303 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jun 20 12:37:05 2023 -0700 + + [instancer] add subset () for cvar + + src/hb-ot-var-cvar-table.hh | 40 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 39 insertions(+), 1 deletion(-) + +commit e39e02017e1537cd9f085b1f5999887a309c20c6 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jun 20 11:48:53 2023 -0700 + + [instancer] add serialize() method for TupleVariationData + + src/hb-ot-var-common.hh | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 67 insertions(+) + +commit 5ef0199da331959e6b27da90d1032f78d3d775ef +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jun 20 11:39:20 2023 -0700 + + [instancer] instantiate() and compile_bytes () for tuple_variations_t + + Also add testing code + + src/hb-ot-var-common.hh | 28 ++++++++++++++++++++++++++++ + src/test-tuple-varstore.cc | 23 +++++++++++++++++++++++ + 2 files changed, 51 insertions(+) + +commit 48c70ce5f667d6b24d7d4a72bc03095760dc3752 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jun 20 11:30:51 2023 -0700 + + [instancer] add compile_tuple_var_header() + + src/hb-ot-var-common.hh | 116 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 116 insertions(+) + +commit 6354b71f81bb85951d84d245eb68ec4e107aea55 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jun 20 11:24:05 2023 -0700 + + [instancer] add compile_deltas() for tuple_delta_t + + src/hb-ot-var-common.hh | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 70 insertions(+) + +commit a00ad83a3bc0e86a16a791c0085403dd9a42b5a4 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jun 20 11:17:11 2023 -0700 + + [instancer] add encode_delta_run() + + src/hb-ot-var-common.hh | 165 ++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 158 insertions(+), 7 deletions(-) + +commit 19e5033b9c8d24ee6ce2df124576d5d724d80fc2 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jun 20 11:02:41 2023 -0700 + + [instancer] add compile_all_point_sets() and find_shared_points () + + compiled bytes for points set are stored in a hashmap + + src/hb-ot-var-common.hh | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 61 insertions(+) + +commit 065e0af5925f260a5fcd40ec0a502ec8aa3ada85 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jun 20 10:58:24 2023 -0700 + + [instancer] add compile_point_set() for tuple_variations_t + + Also add a byte_data_t struct to store compiled bytes + + src/hb-ot-var-common.hh | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 103 insertions(+) + +commit e41b688b50506844739794d715596f24c6ae9545 +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Jun 12 13:25:19 2023 -0700 + + [instancer] fix bug in tuple varstore decompiling + + when points count is 0, it means deltas will apply to all points + + src/hb-ot-var-common.hh | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +commit 5c2aa1a8e726b657db49b881c88ccf2c95a64899 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 11:02:22 2023 -0600 + + [syllabic] Add buffer messages for inserting dotted-circle + + src/hb-ot-shaper-syllabic.cc | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +commit f0f6f6a8057a80ddb8a96ed05f1584e7780f29f0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 10:58:44 2023 -0600 + + [layout] More message massaging + + src/hb-ot-layout.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 7232c01dce7384ad6c9acd3c9b97780abbe85c1f +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Jun 22 09:37:48 2023 -0700 + + [instancer-solver] add tests for instancer-solver crossing calculation fix + + src/test-subset-instancer-solver.cc | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +commit 37555f84891c50dfd7ca4478e81acfd8c9393988 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 22 10:21:19 2023 -0600 + + [layout] Trace chosen script tag + + src/hb-ot-layout.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit c56275c09c426261723c029644f7f355823c05b8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 21 19:01:46 2023 -0600 + + [instancer-solver] Notation + + src/hb-subset-instancer-solver.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit dbac23357f0ad9cba73965a4a00ca85bf01dcef9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 21 18:54:11 2023 -0600 + + [instancer-solver] Simplify, from upstream + + src/hb-subset-instancer-solver.cc | 65 ++++++++------------------------------- + 1 file changed, 12 insertions(+), 53 deletions(-) + +commit 32a9ac2e3a581c68fffac0203d568944bb1d133b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 21 18:30:31 2023 -0600 + + [instancer/L4] Add a comment from upstream + + src/hb-subset-instancer-solver.cc | 2 ++ + 1 file changed, 2 insertions(+) + +commit 244f3224b9a6e9e22f65796a984ef7058e7af930 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 21 17:54:49 2023 -0600 + + [instancer-solver] Port optimization from upstream + + Fixes https://github.com/harfbuzz/harfbuzz/issues/4291 + + src/hb-subset-instancer-solver.cc | 165 +++++++++++++++++++++--------------- + src/test-subset-instancer-solver.cc | 6 +- + 2 files changed, 101 insertions(+), 70 deletions(-) + +commit 197bb35972d66fa01b26bf6fcb1a2268717ef574 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 21 15:16:53 2023 -0600 + + [instancer-solver] Further simplify + + From https://github.com/fonttools/fonttools/pull/3179/commits/94e081611c6b40fa6284049a753479d1038bdb1c + + src/hb-subset-instancer-solver.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 6788932d81c163cc7634a6b04115e556a1b19299 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 21 15:16:19 2023 -0600 + + [instancer-solver] Simplify + + From https://github.com/fonttools/fonttools/pull/3179/commits/7385cbbc34080d5ed3e9017eb38945cfb03cfe17 + + src/hb-subset-instancer-solver.cc | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +commit de0c5aed5b7ca26570eb91e25930813e9123fe56 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 21 15:14:23 2023 -0600 + + [instancer-solver] Backport bugfix from fonttools + + Fixes https://github.com/harfbuzz/harfbuzz/issues/4289 + + Test not ported yet. + + src/hb-subset-instancer-solver.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit a77f28286569b1d187aa7470a4721222a3fc44e7 +Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> +Date: Mon Jun 19 22:51:01 2023 +0000 + + Bump meson from 0.62.0 to 1.1.1 in /.ci + + Bumps [meson](https://github.com/mesonbuild/meson) from 0.62.0 to 1.1.1. + - [Release notes](https://github.com/mesonbuild/meson/releases) + - [Commits](https://github.com/mesonbuild/meson/compare/0.62.0...1.1.1) + + --- + updated-dependencies: + - dependency-name: meson + dependency-type: direct:production + update-type: version-update:semver-major + ... + + Signed-off-by: dependabot[bot] <support@github.com> + + .ci/requirements.in | 2 +- + .ci/requirements.txt | 14 +++++++------- + 2 files changed, 8 insertions(+), 8 deletions(-) + +commit a094a6bd9c9504bb9b6f7673ec5a81e8f0f89cbb +Merge: db700b567 0be1e5a73 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 19 18:50:02 2023 -0400 + + Merge pull request #4275 from pnacht/pinned_pip + + Hash-pin Python dependencies in CI + +commit 0be1e5a73dc0d987848ff32592c569d34e7b2024 +Author: Pedro Kaj Kjellerup Nacht <pnacht@google.com> +Date: Mon Jun 19 20:49:38 2023 +0000 + + Use meson 0.62.0, remove retry + + Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht@google.com> + + .ci/requirements.in | 2 +- + .ci/requirements.txt | 6 +++--- + .github/workflows/msvc-ci.yml | 33 +++++++-------------------------- + 3 files changed, 11 insertions(+), 30 deletions(-) + +commit 3679293a450f62c1eb5318d87992b8f727c6517a +Author: Pedro Kaj Kjellerup Nacht <pnacht@google.com> +Date: Mon Jun 19 19:46:41 2023 +0000 + + msvc-ci: Retry if meson setup is flaky + + Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht@google.com> + + .github/workflows/msvc-ci.yml | 35 +++++++++++++++++++++++++++-------- + 1 file changed, 27 insertions(+), 8 deletions(-) + +commit 0ccb5c365f61319a68506ab5c5c08c9f12ea1ca5 +Author: Pedro Kaj Kjellerup Nacht <pnacht@google.com> +Date: Mon Jun 19 19:39:58 2023 +0000 + + Only use fonttools in msys2-ci + + Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht@google.com> + + .github/workflows/msys2-ci.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 546508733d940202d009f95d9414aa229d17150c +Author: Pedro Kaj Kjellerup Nacht <pnacht@google.com> +Date: Mon Jun 19 19:36:43 2023 +0000 + + Move fonttools to separate requirements file + + Necessary because msys2/mingw don't accept the other deps + (not supported?), and msys2-ci.yml only needs fonttools. + + Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht@google.com> + + .ci/requirements-fonttools.in | 1 + + .ci/requirements-fonttools.txt | 42 ++++++++++++++++++++++++++++++++++++++++++ + .ci/requirements.in | 2 +- + .ci/requirements.txt | 40 ++++++++++++++++++++++++++++++++++++---- + 4 files changed, 80 insertions(+), 5 deletions(-) + +commit db700b5670d9475cc8ed4880cc9447b232c5e432 +Author: Garret Rieger <grieger@google.com> +Date: Mon Jun 12 23:38:26 2023 +0000 + + [subset] fix fuzzer timeout. + + Fixes: https://oss-fuzz.com/testcase-detail/6681253479579648. Limits iteration of coverage table during MATH subset to valid glyphs. + + src/hb-iter.hh | 2 +- + src/hb-ot-math-table.hh | 9 +++++---- + ...-testcase-minimized-hb-subset-fuzzer-6681253479579648 | Bin 0 -> 3472 bytes + 3 files changed, 6 insertions(+), 5 deletions(-) + +commit e2722696793cacc8e58546e902451a9b2c65bac4 +Author: Pedro Kaj Kjellerup Nacht <pnacht@google.com> +Date: Mon Jun 12 14:36:49 2023 +0000 + + Bump meson to 0.60.0 + + Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht@google.com> + + .ci/requirements.in | 2 +- + .ci/requirements.txt | 5 +++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +commit e39c4cf5a92881d81ba0219a7153116bb53ad59c +Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> +Date: Mon Jun 12 10:58:52 2023 +0000 + + Bump ilammy/msvc-dev-cmd from 1.12.0 to 1.12.1 + + Bumps [ilammy/msvc-dev-cmd](https://github.com/ilammy/msvc-dev-cmd) from 1.12.0 to 1.12.1. + - [Release notes](https://github.com/ilammy/msvc-dev-cmd/releases) + - [Commits](https://github.com/ilammy/msvc-dev-cmd/compare/7315a94840631165970262a99c72cfb48a65d25d...cec98b9d092141f74527d0afa6feb2af698cfe89) + + --- + updated-dependencies: + - dependency-name: ilammy/msvc-dev-cmd + dependency-type: direct:production + update-type: version-update:semver-patch + ... + + Signed-off-by: dependabot[bot] <support@github.com> + + .github/workflows/msvc-ci.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit d82c7623c5c146abeb4cea6e5dc8e6318a139a24 +Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> +Date: Mon Jun 12 10:58:57 2023 +0000 + + Bump actions/checkout from 3.5.2 to 3.5.3 + + Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3. + - [Release notes](https://github.com/actions/checkout/releases) + - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) + - [Commits](https://github.com/actions/checkout/compare/8e5e7e5ab8b370d6c329ec480221332ada57f0ab...c85c95e3d7251135ab7dc9ce3241c5835cc595a9) + + --- + updated-dependencies: + - dependency-name: actions/checkout + dependency-type: direct:production + update-type: version-update:semver-patch + ... + + Signed-off-by: dependabot[bot] <support@github.com> + + .github/workflows/arm-ci.yml | 2 +- + .github/workflows/configs-build.yml | 2 +- + .github/workflows/coverity-scan.yml | 2 +- + .github/workflows/linux-ci.yml | 2 +- + .github/workflows/macos-ci.yml | 2 +- + .github/workflows/msvc-ci.yml | 2 +- + .github/workflows/msys2-ci.yml | 2 +- + 7 files changed, 7 insertions(+), 7 deletions(-) + +commit 1159b9d3ee0b5c772728aee035fe1a5220da11a9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 10 10:54:32 2023 -0600 + + [subset/cff1] Remove always-true check + + src/hb-subset-cff1.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit fad2c4aea6087e39c4589d5698acf93d1a56c173 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 10 10:22:27 2023 -0600 + + [subset/cff] Simplify a few serialize calls + + src/hb-subset-cff1.cc | 24 ++++++++---------------- + src/hb-subset-cff2.cc | 12 ++++-------- + 2 files changed, 12 insertions(+), 24 deletions(-) + +commit 2e6919d5262e5fc747f6ac18057e8c0e286ade89 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 10 10:08:56 2023 -0600 + + [subset/cff2] Error handling + + Fixes https://oss-fuzz.com/testcase-detail/4916785942757376 + + src/hb-subset-cff2.cc | 12 ++++++++++-- + ...z-testcase-minimized-hb-subset-fuzzer-4916785942757376 | Bin 0 -> 331 bytes + 2 files changed, 10 insertions(+), 2 deletions(-) + +commit 5906f90ce1feb3894da4019fe4b34e788eb21c5b +Author: Pedro Kaj Kjellerup Nacht <pnacht@google.com> +Date: Wed Jun 7 18:54:57 2023 +0000 + + Hash-pin Actions + + Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht@google.com> + + .github/workflows/arm-ci.yml | 2 +- + .github/workflows/cifuzz.yml | 2 +- + .github/workflows/configs-build.yml | 2 +- + .github/workflows/coverity-scan.yml | 2 +- + .github/workflows/linux-ci.yml | 6 +++--- + .github/workflows/macos-ci.yml | 6 +++--- + .github/workflows/msvc-ci.yml | 8 ++++---- + .github/workflows/msys2-ci.yml | 4 ++-- + 8 files changed, 16 insertions(+), 16 deletions(-) + +commit 0935b3279565ca3c5608a43dc5a4ce65e90b851f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 18:47:33 2023 -0600 + + [vector] Speed up shrink_vector for trivial destructors + + src/hb-vector.hh | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +commit da2e2c8c25b45cadcebd814a3f42e3d32c4b5e93 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 17:16:53 2023 -0600 + + [subset/cff] Speed up offset writing + + src/hb-ot-cff-common.hh | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +commit c85ca75eff9658f727059afe3c79a8bc34281ece +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 15:57:49 2023 -0600 + + [buffer-verify] Simplify a couple ifs + + src/hb-buffer-verify.cc | 19 ++++++------------- + 1 file changed, 6 insertions(+), 13 deletions(-) + +commit e527c17e239fbbc0856add5723be9b57e3a48662 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 15:56:12 2023 -0600 + + [buffer-verify] Don't consider shaping failure as error + + src/hb-buffer-verify.cc | 18 ++---------------- + 1 file changed, 2 insertions(+), 16 deletions(-) + +commit cb516075b6880352900d07016f1ccce2dada9c62 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 15:50:53 2023 -0600 + + [buffer-verify] Error handling + + src/hb-buffer-verify.cc | 41 +++++++++++++++++++++++------------------ + 1 file changed, 23 insertions(+), 18 deletions(-) + +commit 39dd777a12573d488c05c4b59693302cb38f37e7 +Merge: fea47dd3f 3669a6271 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 15:25:20 2023 -0600 + + Merge pull request #4271 from googlefonts/change_axis_limits + + [instancer] change tuple variations' axis limits + +commit 3669a6271043912de8d0ee566a4effc3a56927f9 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Jun 8 13:26:37 2023 -0700 + + fix bot + + src/hb-ot-var-common.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 9fd367663a25bbcdcdff958ebc3665ddf8017077 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Jun 8 12:27:36 2023 -0700 + + [instancer] add testing code for change_tuple_variation_axis_limits() + + Also fixed a small bug + + src/Makefile.am | 2 +- + src/hb-ot-var-common.hh | 2 +- + src/meson.build | 2 +- + src/test-tuple-varstore.cc | 35 +++++++++++++++++++++++++++++++++++ + 4 files changed, 38 insertions(+), 3 deletions(-) + +commit 8057661f077dbca4f8b1f702771b70a9e1e29dd4 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Jun 8 12:10:27 2023 -0700 + + [instancer] use axis tag as hashmap key instead of axis index + + This makes remove_axis() and set_tent() faster, which are used by + change_axis_limits () + + src/hb-ot-var-common.hh | 16 ++++++++++++---- + src/hb-ot-var-cvar-table.hh | 2 ++ + src/test-tuple-varstore.cc | 11 ++++++++--- + 3 files changed, 22 insertions(+), 7 deletions(-) + +commit 389446c563f9caab73df6d58a43fc5d1ed991920 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Jun 8 09:07:47 2023 -0700 + + [instancer] add merge_tuple_variations () + + src/hb-ot-var-common.hh | 27 +++++++++++++++++++++++++++ + src/hb-subset-instancer-solver.hh | 18 ++++++++++++++++++ + 2 files changed, 45 insertions(+) + +commit fea47dd3f2186175feaa710200277158f3698506 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 15:03:27 2023 -0600 + + [vector] Fix vector error handling when allocation used to be 0 + + src/hb-vector.hh | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +commit 11308c4d1f4a8aaab11893810e9809cb76e4e1c6 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 14:51:18 2023 -0600 + + [graph] Remove manual destruction + + Happens automatically by destructor. + + src/graph/graph.hh | 1 - + 1 file changed, 1 deletion(-) + +commit d08aee5a7e5dde5158393e8f03c63fad8a4f3682 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 13:20:28 2023 -0600 + + Add fuzzing test + + ...-testcase-minimized-hb-subset-fuzzer-6442117271257088 | Bin 0 -> 4043 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +commit dbdeb2649d3506b5179ff1bdedf3bc9b5442a038 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 12:08:29 2023 -0600 + + [vector] Keep allocated size when in error + + src/hb-vector.hh | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +commit 9df07c3c303299ea782176aad901cd7831f4e025 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 11:46:06 2023 -0600 + + [gsubgpos] Prevent a leak in closure + + If the push wasn't successful we were constructing an + hb_set_t on the Crap data... At least that's my reading + of the code. + + src/hb-ot-layout-gsubgpos.hh | 48 ++++++++++++++++++++++++++------------------ + 1 file changed, 29 insertions(+), 19 deletions(-) + +commit 0f0b3bee2157be6ad0c2ef9bbac39a9cae29e85c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 8 11:13:33 2023 -0600 + + [map] Fix use-after-move issue + + src/hb-map.hh | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +commit a67a7867d2f8e83b9c307f70b8997dedf3f9d154 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 20:24:02 2023 -0600 + + [cff] Tweak CFFIndex accessors again + + Faster; avoiding multiply. + + src/hb-ot-cff-common.hh | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +commit 04c5e46ac6258cc7fafda479cfce1594edb90a2b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 19:18:04 2023 -0600 + + [subset/cff] Fix comment + + src/hb-ot-cff-common.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 8832da83091358c919f3b685d9d168bd92e1c1d5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 18:58:52 2023 -0600 + + [subset/cff] Comment + + src/hb-ot-cff-common.hh | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +commit 092373f3512ea6b5f4e8280b5e81dc22ed2e4844 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 17:49:13 2023 -0600 + + [subset/cff] Comment + + src/hb-ot-cff-common.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit e0b60bd08d8af88e61fea3b399b1654f3683be4f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 17:25:47 2023 -0600 + + [subset/cff1] Speed up remap_sids + + src/hb-map.hh | 13 +++++++++---- + src/hb-subset-cff1.cc | 10 +++++----- + 2 files changed, 14 insertions(+), 9 deletions(-) + +commit 67b16247274d1fc04d36d4242680b0a06912eae0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 16:15:48 2023 -0600 + + [set] Simplify a few set iterations as range loop + + src/OT/Layout/Common/CoverageFormat1.hh | 2 +- + src/OT/Layout/Common/CoverageFormat2.hh | 2 +- + src/graph/graph.hh | 3 +-- + src/hb-bimap.hh | 3 +-- + src/hb-ot-cmap-table.hh | 3 +-- + src/hb-ot-layout-common.hh | 5 ++--- + src/hb-ot-layout.cc | 5 ++--- + src/hb-ot-os2-table.hh | 3 +-- + src/hb-subset-cff-common.hh | 3 +-- + src/test-gsub-get-alternates.cc | 2 +- + 10 files changed, 12 insertions(+), 19 deletions(-) + +commit 988e4f068ebc3797a419eaefa16d2f8547c780bd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 15:57:47 2023 -0600 + + [iter] Comment + + src/hb-iter.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 0364c69e6d6209b65739968fb72f73e504e1fd20 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 15:52:18 2023 -0600 + + [iter] Add has_fast_len + + Set iterators are not random_access, but have fast len(). + + src/hb-array.hh | 2 ++ + src/hb-bit-set-invertible.hh | 1 + + src/hb-bit-set.hh | 1 + + src/hb-iter.hh | 1 + + src/hb-map.hh | 2 +- + src/hb-vector.hh | 2 +- + 6 files changed, 7 insertions(+), 2 deletions(-) + +commit 2d1589221ddcc64dedd6fa72b853e34b0fff0fab +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 15:47:08 2023 -0600 + + [subset/hdmx] Remove an unintended vector copy + + src/hb-ot-hdmx-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 81b2a56d5423d5b1476f279d0c720bb00ffa231b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 15:04:20 2023 -0600 + + [set] Micro-optimize iteration + + src/hb-bit-set-invertible.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit ad620af6f6d36f2e10d6affaf2112e3f35c656c9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 14:59:22 2023 -0600 + + Revert "[iter] Another try at writing some for loops as range loops" + + This reverts commit 69c6928289cad871b5b096fbdcd2827fdb80c3ad. + + This had code size increase, and slows down non-random-access + iterators since it accesses __end__ which is O(n). + + src/hb-iter.hh | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +commit 59f2d2f6c2aa61e9e859934a7b710d822e905610 +Author: Pedro Kaj Kjellerup Nacht <pnacht@google.com> +Date: Wed Jun 7 19:50:09 2023 +0000 + + Set dependabot to update requirements.txt + + Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht@google.com> + + .github/dependabot.yml | 4 ++++ + 1 file changed, 4 insertions(+) + +commit 7c08bb85d589cc1ae5f506832dd90efddf0a06a6 +Author: Pedro Kaj Kjellerup Nacht <pnacht@google.com> +Date: Wed Jun 7 19:47:57 2023 +0000 + + Adopt requirements.txt file in workflows + + Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht@google.com> + + .github/workflows/linux-ci.yml | 2 +- + .github/workflows/macos-ci.yml | 2 +- + .github/workflows/msvc-ci.yml | 2 +- + .github/workflows/msys2-ci.yml | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +commit a8e2f1b6eaf31d76e41e46dc70aba35263c671be +Author: Pedro Kaj Kjellerup Nacht <pnacht@google.com> +Date: Wed Jun 7 19:40:26 2023 +0000 + + Add .ci/requirements files + + Signed-off-by: Pedro Kaj Kjellerup Nacht <pnacht@google.com> + + .ci/requirements.in | 4 ++ + .ci/requirements.txt | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 179 insertions(+) + +commit 80d6e996d75e46e3aa2c3ab32fc898a6d22af556 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 14:21:40 2023 -0600 + + [subset/cff1] Fix wrong comma location! + + src/hb-ot-cff1-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 69c6928289cad871b5b096fbdcd2827fdb80c3ad +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 14:11:02 2023 -0600 + + [iter] Another try at writing some for loops as range loops + + src/hb-iter.hh | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +commit 138461beb474cc65fe4b967efbd12b4e7753ead1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 14:07:39 2023 -0600 + + [susbet/cff] Minor remove one indirection + + src/hb-ot-cff-common.hh | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +commit 41369b661735242937ebc7734edea27984ca3b1d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 14:04:42 2023 -0600 + + Revert "[subset/cff1] Optimize writing of consecutive names" + + This reverts commit 3b25a630403b65eb5608d10c3b8d082a141bd5c8. + + Not worth it. Shows 0.5% speedup only on SourceSansPro/retaingids/10 + + Doesn't have code size increase though. + + src/hb-ot-cff-common.hh | 23 ----------------------- + src/hb-ot-cff1-table.hh | 2 +- + 2 files changed, 1 insertion(+), 24 deletions(-) + +commit 3b25a630403b65eb5608d10c3b8d082a141bd5c8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 14:04:25 2023 -0600 + + [subset/cff1] Optimize writing of consecutive names + + src/hb-ot-cff-common.hh | 23 +++++++++++++++++++++++ + src/hb-ot-cff1-table.hh | 2 +- + 2 files changed, 24 insertions(+), 1 deletion(-) + +commit 78082357c8bcee2adea53caa9da8cee1c7ec2970 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 12:43:05 2023 -0600 + + Revert "[iter] Rewrite some loops as range loops" + + This reverts commit 7a5242a30f3c41755a095909989221b4d22690ef. + + This times out test-set. Obviously broke something (in hb_all + I think). Not bothering to figure out right now. + + src/hb-iter.hh | 35 ++++++++++++++++++----------------- + 1 file changed, 18 insertions(+), 17 deletions(-) + +commit 7a5242a30f3c41755a095909989221b4d22690ef +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 12:36:15 2023 -0600 + + [iter] Rewrite some loops as range loops + + src/hb-iter.hh | 35 +++++++++++++++++------------------ + 1 file changed, 17 insertions(+), 18 deletions(-) + +commit cc9651d55d4909ba3baed8b089ee44f8a2a6c270 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 12:20:48 2023 -0600 + + [map] Micro-optimize + + src/hb-map.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 79113ec3b19b80f79efb92214c04774cb7556c7c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 12:14:43 2023 -0600 + + [subset/cff1] Micro-optimize String writing + + src/hb-ot-cff1-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 5fe96213aae0cac6f6ef25fdbb7ef64a0c6cd557 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 12:05:57 2023 -0600 + + [subset/cff] Micro-optimize CFFIndex writing + + src/hb-ot-cff-common.hh | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +commit 70b13ef00ba86f8315a56d44f3ad065b9a81763c +Merge: b80b6a4f5 01f9b7977 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Jun 7 11:46:37 2023 -0600 + + Merge pull request #4267 from googlefonts/decompile_tuple_varstore + + [instancer] decompile tuple varstore + +commit b80b6a4f5fc64027c43adbe60942a468db81a017 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 18:11:55 2023 -0600 + + [cff] Remove unused types + + src/hb-ot-cff-common.hh | 5 +---- + src/hb-ot-cff1-table.hh | 3 +-- + src/hb-ot-cff2-table.hh | 1 - + 3 files changed, 2 insertions(+), 7 deletions(-) + +commit 26ac1d4b485c2b96fdc9069583f443b1ab455ab5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 18:08:59 2023 -0600 + + [cff] Remove unused method + + src/hb-ot-cff-common.hh | 40 +--------------------------------------- + 1 file changed, 1 insertion(+), 39 deletions(-) + +commit c6ce1f81ece74e20e4ae8b4b4d424a1694c3ed15 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 17:17:29 2023 -0600 + + [cff] Micro-optimize CFFIndex::operator[] + + src/hb-ot-cff-common.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit a55d0b88662c01471f254a452650703586820b4e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 17:13:09 2023 -0600 + + [subset/cff] Inline type only used once + + src/hb-cff-interp-common.hh | 2 -- + src/hb-ot-cff1-table.hh | 2 +- + 2 files changed, 1 insertion(+), 3 deletions(-) + +commit 2960d13f1bcd573f985b44a40f7340694a99dd9b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 16:24:28 2023 -0600 + + [subset/cff1] Micro-optimize string writing + + src/hb-ot-cff1-table.hh | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +commit 35e152b9f44a3bbac48a1837d91962fa8619d80f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 16:21:14 2023 -0600 + + [subset/cff] Micro-optimize CFFIndex for empty strings + + src/hb-ot-cff-common.hh | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +commit acae5ed25c0da62153c9dd5c1d377886039384cc +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 16:18:44 2023 -0600 + + [subset/cff1] Speed up sid mapping + + Don't need a full inc_bimap. + + src/hb-ot-cff1-table.hh | 2 +- + src/hb-subset-cff1.cc | 13 +++++++++++-- + 2 files changed, 12 insertions(+), 3 deletions(-) + +commit 9e80f6b1b6a8481252368923ae5b4f10ee7c1d2c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 15:38:14 2023 -0600 + + [subset/cff1] Speed up plan_subset_charset + + 25% speedup in --benchmark_filter=subset_glyphs/SourceSansPro'.*retaingids/10 + + src/hb-subset-cff1.cc | 2 ++ + 1 file changed, 2 insertions(+) + +commit fd13aa9effceb1ad87d48ad35c2271217324b6c0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 15:33:51 2023 -0600 + + [subset/cff1] Optimize CFF::CFF1StringIndex::serialize + + src/hb-ot-cff1-table.hh | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +commit ada1e9a924b7a38071757511117892d3b76cb475 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 14:46:06 2023 -0600 + + [graph/serialize] Handle empty blob + + Fixes https://oss-fuzz.com/testcase-detail/4877513265119232 + + src/graph/serialize.hh | 3 +++ + ...-testcase-minimized-hb-repacker-fuzzer-4877513265119232 | Bin 0 -> 10 bytes + 2 files changed, 3 insertions(+) + +commit a92b288e655a94e076f0c3205f99e9162d35e20c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Jun 6 14:32:25 2023 -0600 + + [serializer] Handle snapshotting when current is nullptr + + Happens with memory failure / fuzzing. + + Fixes https://oss-fuzz.com/testcase-detail/6292420615340032 + + src/hb-serialize.hh | 17 +++++++++++++---- + ...estcase-minimized-hb-subset-fuzzer-6292420615340032 | Bin 0 -> 2116 bytes + 2 files changed, 13 insertions(+), 4 deletions(-) + +commit 01f9b79777ab4ad26a04b37f96bd6db841fdbe33 +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Jun 5 17:26:20 2023 -0700 + + address review comments + + src/Makefile.am | 8 +++---- + src/hb-ot-var-common.hh | 26 ++++++---------------- + src/hb-ot-var-cvar-table.hh | 2 +- + src/meson.build | 2 +- + ...le-tuple-varstore.cc => test-tuple-varstore.cc} | 0 + 5 files changed, 13 insertions(+), 25 deletions(-) + +commit f01ebe97b294444704c06c0501afddf999faddbe +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 21:38:37 2023 -0600 + + [vector] Minor write more idiomatic + + src/hb-vector.hh | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +commit cd8f7c02017e8b574639463587460d09f12b4477 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 17:17:44 2023 -0600 + + [subset/cff] Optimize fdselect + + src/hb-subset-cff-common.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 796a0df93e7c84f97aaba13ddb41a00447e2e902 +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Jun 5 15:33:43 2023 -0700 + + try to fix bot + + src/hb-ot-var-common.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit dcecb4d16b6ed34a79db245bb191d7b295585fdd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 16:03:36 2023 -0600 + + [subset/ValueFormat] Micro-optimize + + src/OT/Layout/GPOS/ValueFormat.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit 5676adefbc49174aaa654bf2df826c2712a039a9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 15:56:19 2023 -0600 + + [subset/cff1] Remove an unneeded copy method + + Same as serializer embed(). + + src/hb-ot-cff-common.hh | 10 ---------- + src/hb-subset-cff1.cc | 2 +- + 2 files changed, 1 insertion(+), 11 deletions(-) + +commit 7d9698123ce38fbada898760c748bddad0662831 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 15:44:50 2023 -0600 + + [subset/cff1] Micro-optimize + + Is ugly but shows speedup. + + src/hb-ot-cff-common.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 469e82a2275355e8dd814fc9d6b3f01788c08dfa +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 15:23:22 2023 -0600 + + [subset/PairPos] Micro-optimize + + src/OT/Layout/GPOS/PairPosFormat2.hh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit 6593d2aabac47a1e1953a0b9e74a401c02a02e93 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 15:11:43 2023 -0600 + + [subset/PairPos] Speed up + + src/OT/Layout/GPOS/PairPosFormat2.hh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit ed6bee20047ed5b97e6ed9ee460bf5c551341e71 +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Jun 5 14:03:22 2023 -0700 + + [instancer] add a test for decompile cvar tuple variations data + + src/Makefile.am | 5 +++ + src/meson.build | 1 + + src/test-decompile-tuple-varstore.cc | 79 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 85 insertions(+) + +commit bd9cdecd59b24f0886df3ce605fc1a8be18c4546 +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Jun 5 13:52:05 2023 -0700 + + [instancer] add decompile_tuple_variations() for cvar table + + src/hb-ot-var-cvar-table.hh | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +commit 452990edcae85e5f46e083cbb4494a38845ae791 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 17:46:36 2023 -0600 + + [cff1] Add TODO + + src/hb-ot-cff1-table.hh | 1 + + 1 file changed, 1 insertion(+) + +commit 072c9c06e0ebba7b93e1e1eb1388c59dac6d8d8f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 16:04:29 2023 -0600 + + Revert "[subset/cff1] Micro-optimize" + + This reverts commit 93020621f0651920ff92e19f543fbf2351c8311b. + + This slowed down the common path actually. + + src/hb-ot-cff1-table.hh | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +commit f102d57a526a8c32de2e89bec630c0f8aa417bc7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 16:03:34 2023 -0600 + + [subset/cff1] Micro-optimize + + src/hb-ot-cff1-table.hh | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +commit cdfbd7b6c6d00a6ff31496d1797c957406b94239 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:58:14 2023 -0600 + + [subset/cff1] Micro-optimize + + src/hb-ot-cff1-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 7b97262b03bf86fe19901820903fe508e563787a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:55:18 2023 -0600 + + [subset/cff1] Micro-optimize + + src/hb-ot-cff1-table.hh | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +commit 59387dbe43806d37e094bea15ee3b017a3fbaa8c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 14:47:27 2023 -0600 + + [subset/cff] Speed up sid mapping + + src/hb-ot-cff1-table.hh | 47 +++++++++++++++++++++++++++++++++-------------- + src/hb-subset-cff1.cc | 14 ++++++++------ + 2 files changed, 41 insertions(+), 20 deletions(-) + +commit 2012df0755f88f7d104e7c08897ad85b52b659ea +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Jun 5 13:46:04 2023 -0700 + + [instancer] add struct tuple_variation_t + + And add function to decompile TupleVariationData into the struct + + src/hb-ot-var-common.hh | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 111 insertions(+) + +commit 9f508b7393ed4cb9dbcd3ebf1ccd30cc33e5add8 +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Jun 5 13:35:28 2023 -0700 + + [instancer] add unpack_axis_tuples () in TupleVariationHeader + + src/hb-ot-var-common.hh | 47 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + +commit ffc6899b0cb788304d2ee7a8c415c3be8d04691b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 14:16:47 2023 -0600 + + [subset/cff1] Use a vector, instead of map, for glyph_to_sid_map + + Much faster. + + src/hb-ot-cff1-table.hh | 20 ++++++++++++-------- + src/hb-ot-cff2-table.hh | 2 +- + src/hb-subset-cff-common.hh | 12 +++++++++--- + src/hb-subset-cff1.cc | 13 ++++++++----- + 4 files changed, 30 insertions(+), 17 deletions(-) + +commit 7b0ecbd8960e376c9c2d8bb9e95b4d9b616d1743 +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Jun 5 13:08:12 2023 -0700 + + [instancer] add struct tuple_delta_t to represent 1 tuple variation + + src/hb-ot-var-common.hh | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 126 insertions(+) + +commit 1636e112c477369e0c95192ce7c94966fe48c85c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 13:44:00 2023 -0600 + + [cff] Micro-optimize + + src/hb-ot-cff-common.hh | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +commit 27299e0d20fa06dfbde60631c6273db8624ac0c4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 13:41:04 2023 -0600 + + [subset/cff] Minor use hb_len() + + src/hb-ot-cff-common.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 377ccb31e16389887980bdea2830ce7829b50960 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 13:38:06 2023 -0600 + + [subset/cff] Speed up set_offset_at + + src/hb-ot-cff-common.hh | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +commit 90122925ffcd786365bfb1907c3e6b88230b73d0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 13:33:10 2023 -0600 + + [subset/cff1] Minor speedup + + src/hb-subset-cff1.cc | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +commit 238cb0fbfd6f7143ad718c7aa488c30865f253fd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Jun 5 13:27:03 2023 -0600 + + [subset/cff1] Speed up for retaingids + + src/hb-subset-cff1.cc | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +commit 9de413bf010d7a73082931ee081f595fa5e24acd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 17:43:48 2023 -0600 + + [subset/cff1] Micro-optimize + + src/hb-subset-cff1.cc | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +commit ca353e644d3b920f9559cdc7b29b7460edee7f88 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 17:25:29 2023 -0600 + + [subset/cff1] Style + + src/hb-subset-cff1.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit e077ca893eadd993bd52bb902c6f43e488f4a509 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 16:23:36 2023 -0600 + + [subset/cff] Micro-optimize + + src/hb-subset-cff1.cc | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +commit 126d1441964840808a1551fe404beec7f1fe8c5e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 16:23:36 2023 -0600 + + [subset/cff] Micro-optimize + + src/hb-subset-cff-common.cc | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +commit a24025c90d6ccc2846b1bec71fa3ad86329fe3c4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 16:15:43 2023 -0600 + + [subset/cff1] Micro-optimize + + src/hb-subset-cff1.cc | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit 5a3ac0ab349067308dec04a36fac4d58f46c4c42 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:37:25 2023 -0600 + + [subset/cff1] Another micro-optimization + + src/hb-subset-cff1.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 331398286aa5a7ec7fc7066ae9959756f8ee1735 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:33:22 2023 -0600 + + [subset/cff1] Micro-optimize + + src/hb-subset-cff1.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 595aa58379bbbb14149212b9619f6047751d6f78 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:24:36 2023 -0600 + + [UnsizedArray] Minor simplify operator[] + + src/hb-open-type.hh | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +commit 319ea3b967fdcac14af55ce229740f2fd3c764af +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:23:20 2023 -0600 + + [UnsizedArrayOf] Simplify operator[] + + No need to check for overflow. Caller is responsible for correct + access. + + src/hb-open-type.hh | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +commit 6188a3f5a42644b1b86082012c046c23ba443393 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:12:56 2023 -0600 + + [subset/cff] Minor signedness change + + src/hb-ot-cff-common.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 887f299351a79f608ac93fbee1ec4f4f7fc7e02c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:11:17 2023 -0600 + + [susbet/cff] Reuse iterator + + src/hb-ot-cff-common.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit f5b82846336fd01e6ef613c8bd0cf5456da2db35 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:10:08 2023 -0600 + + [subset/cff1] Minor use hb_len + + src/hb-ot-cff-common.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 70638170714e417921eb98db001c3248ed235d46 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 15:03:16 2023 -0600 + + [subset/cff1] Speed up writing 1byte charstrings + + As in the holes of retaingids. + + src/hb-ot-cff-common.hh | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +commit 21ff023a46b567b4d2b6297088e205b83ab1bbdf +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 14:08:24 2023 -0600 + + [subset/cff1] Speed up encoding for retaingids + + src/hb-subset-cff1.cc | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +commit b15222399822baf52a735743ca281bcd98173fec +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 13:58:10 2023 -0600 + + [cff] Minor type change + + src/hb-ot-cff-common.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 640774b9f190226609d5948183d1df8055ceceb4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 13:26:14 2023 -0600 + + [subset/cff] Speed up subsr subset for retaingids + + src/hb-subset-cff-common.hh | 32 +++++++++++++++----------------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +commit 6b11a3d971807f6fa90f284739491acc4ed21cca +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 13:18:43 2023 -0600 + + [subset/cff] Speed up closure_subroutines for retaingids + + src/hb-subset-cff-common.hh | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +commit 31014832a9925bbc2ad892fa5de1704e8e8f5312 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 12:58:02 2023 -0600 + + [cff1] More hygiene + + src/hb-ot-cff1-table.hh | 15 ++++++++++----- + src/hb-subset-cff1.cc | 4 ++-- + 2 files changed, 12 insertions(+), 7 deletions(-) + +commit bf0a08c930506a7301517f5678c2fdb1b34b6595 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 12:54:35 2023 -0600 + + [cff1] Hygiene + + src/hb-open-type.hh | 2 +- + src/hb-ot-cff1-table.hh | 13 +++++++------ + src/hb-subset-cff1.cc | 2 +- + 3 files changed, 9 insertions(+), 8 deletions(-) + +commit ebc5257e29fb803e0b7c893a2dc0187c3641040f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 11:25:16 2023 -0600 + + [cff1] Add a couple of unlikely's + + src/hb-ot-cff1-table.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 9cdc0b6419d3371c94c919a100b64ece99e89fe0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 11:18:56 2023 -0600 + + [subset/cff] Speed up subset_cff_fdselect + + src/hb-ot-cff-common.hh | 31 +++++++++++++++++++++++++++---- + src/hb-subset-cff-common.cc | 5 ++++- + 2 files changed, 31 insertions(+), 5 deletions(-) + +commit 858a022358807720d6ff7fc20206484997766524 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 10:55:41 2023 -0600 + + Revert "[cff] Optimize writing out Index offsets" + + This reverts commit 78ba23c58766c16992ddc4e3af403824aa845fe2. + + Not enough gain, and bloats code size. + + src/hb-ot-cff-common.hh | 52 ------------------------------------------------- + 1 file changed, 52 deletions(-) + +commit 78ba23c58766c16992ddc4e3af403824aa845fe2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 10:52:19 2023 -0600 + + [cff] Optimize writing out Index offsets + + src/hb-ot-cff-common.hh | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +commit 89ce804833a3d4f53cbdfdc728eea3c393a84ecd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 10:20:39 2023 -0600 + + [serialize] Remove attribute malloc + + This broke tests. It wasn't technically correct. + + src/hb-serialize.hh | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +commit 3f2a1b644a470d5dcc9b8347a2cc1914b3550da3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 10:13:53 2023 -0600 + + Fix build + + src/hb-ot-cmap-table.hh | 2 +- + src/hb-serialize.hh | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +commit e1715056fc15ce37ff486486ea89ee51412d3e51 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 10:09:02 2023 -0600 + + [serialize] One more attribute + + src/hb-serialize.hh | 1 + + 1 file changed, 1 insertion(+) + +commit 15048e50ece21a8b22b4c00c728f7c841175f560 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 10:07:04 2023 -0600 + + [serialize] Add more function attributes + + src/OT/glyf/SubsetGlyph.hh | 2 +- + src/hb-serialize.hh | 6 ++++-- + 2 files changed, 5 insertions(+), 3 deletions(-) + +commit aad12ca649ddb0979f4815b0fd824bae9c918abe +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 09:57:51 2023 -0600 + + [serialize] Add a few function attributes + + src/hb-serialize.hh | 4 ++++ + 1 file changed, 4 insertions(+) + +commit 4e076da9d0492dba35d38305876cc6d5badf6f75 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 09:48:42 2023 -0600 + + Another try at fixing build + + src/OT/name/name.hh | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +commit b08866afda7f88b8df4e6603e4e35adfbe7e0761 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 09:44:37 2023 -0600 + + Fix build + + src/OT/name/name.hh | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +commit 82741304d3636de1a6ffbe5ca13012bebb94229b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 09:41:41 2023 -0600 + + [subset] start_embed never returns nullptr + + Remove checks. + + src/OT/Color/CBDT/CBDT.hh | 8 +----- + src/OT/Color/COLR/COLR.hh | 3 +-- + src/OT/Color/sbix/sbix.hh | 5 ---- + src/OT/Layout/GDEF/GDEF.hh | 3 --- + src/OT/Layout/GPOS/AnchorFormat3.hh | 1 - + src/OT/Layout/GPOS/CursivePosFormat1.hh | 1 - + .../Layout/GSUB/ReverseChainSingleSubstFormat1.hh | 1 - + src/OT/glyf/glyf.hh | 5 ++-- + src/OT/name/name.hh | 3 +-- + src/hb-ot-cff-common.hh | 2 +- + src/hb-ot-cmap-table.hh | 8 ++---- + src/hb-ot-hdmx-table.hh | 3 +-- + src/hb-ot-hmtx-table.hh | 3 +-- + src/hb-ot-layout-common.hh | 14 +++++----- + src/hb-ot-layout-gsubgpos.hh | 6 +---- + src/hb-ot-math-table.hh | 4 --- + src/hb-ot-post-table.hh | 3 +-- + src/hb-ot-stat-table.hh | 2 -- + src/hb-ot-var-common.hh | 1 - + src/hb-ot-vorg-table.hh | 2 +- + src/hb-subset-cff1.cc | 31 +++++++--------------- + src/hb-subset-cff2.cc | 20 +++++--------- + 22 files changed, 37 insertions(+), 92 deletions(-) + +commit c2eaedd2cda2da854834f1fd59dadffeec9b45cd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 09:25:07 2023 -0600 + + [fuzzing] Add a test font + + From https://oss-fuzz.com/testcase-detail/5855710991482880 + + ...case-minimized-hb-subset-fuzzer-5855710991482880.fuzz | Bin 0 -> 1048 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +commit af3fdf1f9e09fb7e47d4528d81fd510730b80745 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 09:22:42 2023 -0600 + + [subset/glyf] Simplify error handling + + src/OT/glyf/glyf.hh | 31 ++++++++++--------------------- + 1 file changed, 10 insertions(+), 21 deletions(-) + +commit 3dd1de46d637f36bc30bbd7dd8be3a058d1f1864 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 09:15:14 2023 -0600 + + [subset/glyf] Fix a few return_trace's + + src/OT/glyf/glyf.hh | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +commit 73f2f935a077274fef3343e36352b4e01678d662 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Jun 4 09:12:18 2023 -0600 + + [subset/glyf] Fix another leak + + src/OT/glyf/glyf.hh | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +commit 3d08a2f10cada7c72513d9491ddf66820ef008fb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 23:38:38 2023 -0600 + + [subset/glyf] Fix leak + + src/OT/glyf/glyf.hh | 6 ++++++ + 1 file changed, 6 insertions(+) + +commit fc33200d79aacd007773b8ed6c64486848b8ebc7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 23:29:39 2023 -0600 + + [subset/glyf] Avoid a vector copy + + Oops! + + src/OT/glyf/glyf.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 3bfcbd61490a3fc44f28b813aa8a89bcb9e60e48 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 23:17:56 2023 -0600 + + [subset/glyf] Minor use range lopp + + src/OT/glyf/glyf.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 917c8d0ac526ef1a0217e74f2e9553fd81cbb6b9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 23:15:56 2023 -0600 + + [subset/glyf] Minor change of value + + src/OT/glyf/glyf.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 2b8c43135ad409c9d613a1e80a43924594fa1c3f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 23:01:27 2023 -0600 + + [vector] Oops! + + src/hb-vector.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 054f966a570ef37e0153b6591cbb2ff165517738 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 22:52:16 2023 -0600 + + [subset/cff1] Don't allocate memory for retaingid holes + + 40% speedup in BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/retaingids/10 + benchmark. + + src/hb-cff-interp-common.hh | 2 ++ + src/hb-static.cc | 3 +++ + src/hb-subset-cff-common.hh | 14 ++++++++++++-- + src/hb-vector.hh | 10 ++++++++-- + 4 files changed, 25 insertions(+), 4 deletions(-) + +commit b5792f117a8df69025baf0543bc978a0e0f6ee72 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 22:24:06 2023 -0600 + + [subset] Reuse num_glyphs in various places + + src/OT/Color/CBDT/CBDT.hh | 3 ++- + src/hb-ot-var-hvar-table.hh | 3 ++- + src/hb-subset-cff-common.hh | 6 ++++-- + src/hb-subset-cff1.cc | 5 +++-- + 4 files changed, 11 insertions(+), 6 deletions(-) + +commit 7e4311a868e33d21eccb0f714572f552028931c0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 22:11:47 2023 -0600 + + [cff] Speed up for retaingids + + src/hb-subset-cff-common.hh | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +commit ca237e6ba89193c92161298accc57b2a6542a296 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 22:07:29 2023 -0600 + + [subset/cff] Reuse num_glyphs + + src/hb-subset-cff-common.hh | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +commit 1590754ba8f292df6e1e1b58ff874fb0efda87ee +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 22:04:52 2023 -0600 + + [subset/cff] Speed up for retaingids + + src/hb-subset-cff-common.cc | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +commit dff3a936d21703d0a548546f5fcfa3a122beda27 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 22:00:28 2023 -0600 + + [subset/cff1] Speed up for retaingids + + src/hb-subset-cff1.cc | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +commit fa8d15d520b9b1f9012aef7ecdf4f3947c162e96 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 21:58:21 2023 -0600 + + [subset/cff1] Reuse num_glyphs + + src/hb-subset-cff1.cc | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit 937ead2f02a13d551b428a8358a5e17550387ee6 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 21:38:56 2023 -0600 + + [subset/hvar] Speed up for retaingids + + src/hb-ot-var-hvar-table.hh | 32 ++++++++++++++++++-------------- + 1 file changed, 18 insertions(+), 14 deletions(-) + +commit acab716b1c8b1a071d0551f8e4df07444b2c0446 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 21:15:36 2023 -0600 + + [subset/hvar] Speed up for retaingids + + src/hb-ot-var-hvar-table.hh | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +commit bc6dbf436a373579f405b6bf91c256b7ac779f92 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 21:09:33 2023 -0600 + + [subset/gvar] Micro-optimize + + src/hb-ot-var-gvar-table.hh | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +commit 841347533adfbdc3de79f7bb288220e380246d56 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 21:08:30 2023 -0600 + + [subset/gvar] Speed up for retaingids + + src/hb-ot-var-gvar-table.hh | 53 ++++++++++++++++++++++++++++++--------------- + 1 file changed, 36 insertions(+), 17 deletions(-) + +commit 87cf09bd2c7b7bb001a974296de13617a34e6627 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 21:00:56 2023 -0600 + + [subset/loca] Fix up for retaingid null glyphs at the end + + We currently don't have those, but in case we add. + + src/OT/glyf/glyf-helpers.hh | 6 ++++++ + 1 file changed, 6 insertions(+) + +commit 2fb670a5281bbfe057d9ebc1dd84fb67d9d6c8f7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 20:56:04 2023 -0600 + + [subset/gvar] Speed up for retaingids + + src/hb-ot-var-gvar-table.hh | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +commit 5b1679343afc9d6a7acc8a6e0f3c1974516e3501 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 20:45:52 2023 -0600 + + [subset/hdmx] Micro-optimize + + src/hb-ot-hdmx-table.hh | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +commit 9b733532dff1e31b93d03a30443af6e67229da4c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 20:44:08 2023 -0600 + + [subset/hdmx] Fix build + + src/hb-ot-hdmx-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 4d4792ce3db59844b8a220712e12cd6873d3d7c3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 20:34:51 2023 -0600 + + [subset/hdmx] Speed up more for retaingids + + src/hb-ot-hdmx-table.hh | 37 +++++++++++++++++++++---------------- + 1 file changed, 21 insertions(+), 16 deletions(-) + +commit a3f7ed709b8dec880fab338d8db6494c2d7de998 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 20:25:14 2023 -0600 + + [subset/hdmx] Don't clear memory unnecessarily + + src/hb-ot-hdmx-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit e263c3ccbbca438767c180431e695a99c575a695 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 20:20:57 2023 -0600 + + [subset/hdmx] Speed up + + src/hb-ot-hdmx-table.hh | 2 +- + src/hb-subset-plan.hh | 9 --------- + 2 files changed, 1 insertion(+), 10 deletions(-) + +commit 0e16be9b2cfc549edbaa4a643d9c15c6570771bd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 19:45:44 2023 -0600 + + [subset-plan] Reuse glyph_for_gid result + + src/hb-subset-plan.cc | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +commit 590fb3529a27a2a652c74baa2c8bebad34ec5c42 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 19:21:22 2023 -0600 + + [subset] Reduce memory pressure + + src/hb-subset.cc | 67 +++++++++++++++++++++++++++++--------------------------- + 1 file changed, 35 insertions(+), 32 deletions(-) + +commit c03c3000164c873275a8b60fa07661a9fe74243e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 19:05:10 2023 -0600 + + [subset] Tweak memory allocation + + Reduces chances of rework, specially for glyf table if padding + is needed... + + src/hb-subset.cc | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 38fa0323303bf6c289314932ad4d41ac40734eac +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 18:51:09 2023 -0600 + + Revert "[subset/loca] Build in the serializer memory" + + This reverts commit 546b51818666ca1ddb01824f752eccbd6a751b4b. + + src/OT/glyf/glyf-helpers.hh | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +commit 546b51818666ca1ddb01824f752eccbd6a751b4b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 18:50:35 2023 -0600 + + [subset/loca] Build in the serializer memory + + Because it's hot. Doesn't seem to speed up though. Slight + slowdown. Going to revert. + + src/OT/glyf/glyf-helpers.hh | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +commit 3cb2b49e61fed1aef8c17432abd25f536a919c30 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 18:44:56 2023 -0600 + + [subset/loca] Shuffle code around + + src/OT/glyf/glyf-helpers.hh | 15 +++++++-------- + src/OT/glyf/glyf.hh | 21 +++++++++------------ + 2 files changed, 16 insertions(+), 20 deletions(-) + +commit f014112d16a205e5b9e9406205e7854076df8b02 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 18:27:24 2023 -0600 + + Revert "[subset] Allow adding table directly from subset()" + + This reverts commit 25a6514887ebe899bd4ede1e283e067f97e15def. + + src/hb-ot-hmtx-table.hh | 39 +++++++++++++++++---------------------- + src/hb-subset.cc | 18 ++---------------- + 2 files changed, 19 insertions(+), 38 deletions(-) + +commit 25a6514887ebe899bd4ede1e283e067f97e15def +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 18:26:36 2023 -0600 + + [subset] Allow adding table directly from subset() + + And do it for hmtx. Going to revert since it slows things down. + Apparently the serializer buffer is in caches and hot, so faster + to write to and copy even. + + src/hb-ot-hmtx-table.hh | 39 ++++++++++++++++++++++----------------- + src/hb-subset.cc | 18 ++++++++++++++++-- + 2 files changed, 38 insertions(+), 19 deletions(-) + +commit b0d0babb2e9fe81ee1e96dddfc1fadfeac0b3bab +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 17:14:55 2023 -0600 + + [subset/loca] Rewrite loop faster + + src/OT/glyf/glyf-helpers.hh | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +commit 8dab4441021822f37b3c17194357932c1afc3313 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 17:06:30 2023 -0600 + + [subset/hmtx] Micro-optimize last commit + + hb_zip has its own overhead... + + src/hb-ot-hmtx-table.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit e981dc24c8f04c42addce2a595ab4d60d76dae36 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 17:01:52 2023 -0600 + + [subset/hmtx] Rewrite loop faster for retaingid + + src/hb-ot-hmtx-table.hh | 23 ++++++++++------------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +commit 4a9da0261925c116e738917d8692ecf9d5c90d77 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 16:46:29 2023 -0600 + + [subset/hmtx] Micro-optimize + + src/hb-ot-hmtx-table.hh | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +commit 6a3fcc64f3f8d72eb87c15f23720665b42c22f27 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 16:38:18 2023 -0600 + + [map] Don't call hash() if map is empty + + src/hb-map.hh | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +commit 735d249639a83b7c12c1792551ed4cbbebce7ef2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 16:35:03 2023 -0600 + + [map] Remove an unlikely + + Empty maps are common in some subsetting operations. + + src/hb-map.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit ca27925d55b89a049c1013888a55c4784d255f47 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 16:18:15 2023 -0600 + + Use hb_codepoint_pair_t in more places + + src/OT/Layout/GSUB/Common.hh | 2 -- + src/OT/glyf/glyf-helpers.hh | 4 ++-- + src/graph/pairpos-graph.hh | 10 +++++----- + src/graph/test-classdef-graph.cc | 2 +- + src/hb-algs.hh | 2 ++ + src/hb-bit-set-invertible.hh | 4 ++-- + src/hb-bit-set.hh | 2 +- + src/hb-map.hh | 2 +- + src/hb-ot-cmap-table.hh | 6 +++--- + src/hb-ot-hmtx-table.hh | 4 ++-- + src/hb-ot-layout-common.hh | 8 ++++---- + src/hb-set.hh | 4 ++-- + src/hb-subset-plan-member-list.hh | 4 ++-- + src/hb-subset-plan.cc | 9 ++++----- + src/test-map.cc | 6 +++--- + src/test-set.cc | 2 +- + 16 files changed, 35 insertions(+), 36 deletions(-) + +commit 841e86fd9873dba727af843d638880d8257c89fb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 16:09:45 2023 -0600 + + [subset/hmtx] Further speedup! + + src/hb-ot-hmtx-table.hh | 44 +++++++++++++++++++++++++++----------------- + 1 file changed, 27 insertions(+), 17 deletions(-) + +commit de729ec10566e8dd8bf1f22d9bbf73c2b9f54aeb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 15:48:54 2023 -0600 + + [meta] Return reference from reference-wrapper + + src/hb-iter.hh | 6 +++--- + src/hb-meta.hh | 8 ++++---- + 2 files changed, 7 insertions(+), 7 deletions(-) + +commit c7493efeafcf2ac9af39e8049a2a907065e26756 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 15:39:27 2023 -0600 + + [subset/loca] Micro-optimize + + src/OT/glyf/glyf-helpers.hh | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +commit 13a4c7b3d3bb6c3fb2cbbed1f1de717f58162dae +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 15:12:53 2023 -0600 + + [subset/hmtx] Comment + + src/hb-ot-hmtx-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 4da2996fe2dba5134e7e7f40cb089c9a1e30fb64 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 15:08:20 2023 -0600 + + [doc] Fix + + src/hb-common.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit c3e7f4516658d18c60160b567939bad746404d6e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Jun 3 14:56:47 2023 -0600 + + Add HB_CODEPOINT_INVALID + + Fixes https://github.com/harfbuzz/harfbuzz/issues/4262 + + docs/harfbuzz-sections.txt | 1 + + src/hb-common.h | 10 ++++++++++ + src/hb-map.h | 2 +- + src/hb-set.h | 2 +- + 4 files changed, 13 insertions(+), 2 deletions(-) + +commit efefec13ccedc1461867544e2066e2042e86c66f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 20:33:52 2023 -0600 + + [subset/glyf] Remove unneeded codepath + + src/OT/glyf/SubsetGlyph.hh | 7 ------- + 1 file changed, 7 deletions(-) + +commit ac1f5ca0d9cb94089954a2e4ddf7e064600c5004 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 17:07:44 2023 -0600 + + [subset/loca] Micro-optimize + + src/OT/glyf/glyf-helpers.hh | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +commit 6eae932566330f1485be920bc942069020ca24b0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 17:05:27 2023 -0600 + + [subset/loca] Reduce a vector allocation + + src/OT/glyf/glyf-helpers.hh | 46 +++++++++++++++++++++++++++++---------------- + src/OT/glyf/glyf.hh | 34 ++++++++++++++------------------- + 2 files changed, 44 insertions(+), 36 deletions(-) + +commit cd249d236494784b21502b151d90b326259bae93 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 16:15:05 2023 -0600 + + [subset/hmtx] Micro-optimize + + src/hb-ot-hmtx-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit ec8965e432db27f81b3275c6979fef707f3b9da9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 16:10:25 2023 -0600 + + [subset/glyf] Don't clear loca allocation + + src/OT/glyf/glyf-helpers.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 916629d1827bbf450d41f06639af27a708634713 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 16:08:49 2023 -0600 + + [subset/hmtx] Don't clear allocation + + src/hb-ot-hmtx-table.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 24b069cd53cec2d8afa4e7b90cf5b47c91e215c9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 15:55:53 2023 -0600 + + [subset] Pre-alloc a few maps + + src/hb-multimap.hh | 5 +++++ + src/hb-ot-post-table-v2subset.hh | 12 +++++++++--- + src/hb-subset-plan.cc | 2 ++ + 3 files changed, 16 insertions(+), 3 deletions(-) + +commit 7319d0d71226c15c6c744c6d4e2def72cd20b368 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 15:41:47 2023 -0600 + + [subset-plan] Add a couple of map pre-allocations + + Approximate... + + src/hb-subset-plan.cc | 3 +++ + 1 file changed, 3 insertions(+) + +commit 76904b0423119ad1a2540bd98bb69246781eacc5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 15:30:12 2023 -0600 + + [subset-plan] Simplify / speedup planning glyphset + + src/hb-subset-plan.cc | 27 ++++++++------------------- + 1 file changed, 8 insertions(+), 19 deletions(-) + +commit 965ce7bba4bf8203cce04b6d21b393532e2e7131 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 15:24:00 2023 -0600 + + [subset-plan] Speed up planning new_to_old_gid_list + + src/hb-subset-plan.cc | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +commit b67e464b1cefb733df073590588ab8fcca320bfc +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 15:11:06 2023 -0600 + + [subset/retaingid] Regain perf lost + + In 0f12fd5a66a5dd1c3c9ac5ea8a52341bafcfe567 + + src/OT/glyf/glyf.hh | 20 ++++++-------------- + src/hb-ot-hmtx-table.hh | 14 ++++++++------ + src/hb-subset-plan-member-list.hh | 2 +- + src/hb-subset-plan.cc | 10 ++++------ + 4 files changed, 19 insertions(+), 27 deletions(-) + +commit 0f12fd5a66a5dd1c3c9ac5ea8a52341bafcfe567 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 13:58:55 2023 -0600 + + [subset/glyf] Fix for non-monotonic glyphmap + + Slows things down again, but is correct. Still a good win + combined with the previous changes. + + src/OT/glyf/glyf.hh | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +commit 66ce902c3aeccede074a21abafa7482ca24e5031 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 13:53:21 2023 -0600 + + [glyf] Reduce allocation again + + src/OT/glyf/glyf.hh | 35 ++++++++++++++++++++++------------- + 1 file changed, 22 insertions(+), 13 deletions(-) + +commit 0e0110e7f210e568e8afc6d63a200e2e28004ebe +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 13:34:58 2023 -0600 + + [glyf] Avoid a SubsetGlyph copy + + Unfortunately hb_second() always does a copy... + + src/OT/glyf/glyf.hh | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +commit 33ea8b5e5d152159cd2acbd4054b99cd5559d195 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Jun 2 13:10:52 2023 -0600 + + [subset/glyf] Don't allocate empty SubsetGlyf's + + Shows 33% speedup on Mplus/retaingid/10 benchmark: + + Comparing before to after + Benchmark Time CPU Time Old Time New CPU Old CPU New + -------------------------------------------------------------------------------------------------------------------------------------------------------- + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10 -0.3296 -0.3294 0 0 0 0 + + src/OT/glyf/glyf.hh | 47 +++++++++++++++++++++++++++++------------------ + 1 file changed, 29 insertions(+), 18 deletions(-) + +commit ad872e231349a5cfdd2daf34a8021216431f5d59 +Author: Garret Rieger <grieger@google.com> +Date: Fri Jun 2 18:32:09 2023 +0000 + + [subset] Optimize hmtx/vmtx serialization. + + Make serializer allocation up front to avoid bounds checking overhead for each metric. + + Benchmarks: + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10_median -0.1005 -0.1005 0 0 0 0 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/64_median -0.0693 -0.0692 0 0 0 0 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/512_median -0.0294 -0.0293 1 1 1 1 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/4096_median -0.0033 -0.0032 3 3 3 3 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10000_median +0.0170 +0.0171 7 7 7 7 + + src/hb-ot-hmtx-table.hh | 24 +++++++++--------------- + 1 file changed, 9 insertions(+), 15 deletions(-) + +commit c6368e014dbfaef1515507b41414a99f998d8616 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 20:51:17 2023 -0600 + + [map] Return const reference from operator() + + Like we do in operator[]. + + src/hb-map.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit b04ca1c188bfd7113c9c4ef546fa8b1535a28d30 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 20:43:07 2023 -0600 + + Revert "[subset/glyf] Exact allocation" + + This reverts commit a830f085c849846f8441f5d92d4db36130ef71f8. + + Weirdly enough in a benchmark I'm running I see this show + some slowdown. Makes zero sense. + + src/OT/glyf/glyf.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit a830f085c849846f8441f5d92d4db36130ef71f8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 20:37:29 2023 -0600 + + [subset/glyf] Exact allocation + + src/OT/glyf/glyf.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit ff0b85cf571cb94dbbc5091179f7874926a88dbe +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 20:30:56 2023 -0600 + + [subset/glyf] Empty .notdef only if old-gid was also 0 + + Otherwise it wasn't a .notdef, even if new-gid is 0. + + src/OT/glyf/glyf.hh | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +commit 65a7d8c6f033963d70d03885226bb5a07a397488 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 20:20:00 2023 -0600 + + [glyf] Empty glyphs need no padding + + src/OT/glyf/SubsetGlyph.hh | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +commit 73c18d1d42792cba70634a0cf8b7324f79c9e701 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 20:06:42 2023 -0600 + + [glyf] Micro-optimize padded_offsets + + src/OT/glyf/glyf.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 88d8a6d69f7baf57d29aaa1fe29be0f05956652b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 19:24:02 2023 -0600 + + [BEInt] Use packed-int trick for writing as well + + src/hb-algs.hh | 67 +++++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 45 insertions(+), 22 deletions(-) + +commit 4d853b8ba6e491ec85a7077abb208740b44e61bf +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 18:47:58 2023 -0600 + + [subset/regaingid/glyf] Add a fastpath for empty glyphs + + Mplus benchmark: + Comparing before to after + Benchmark Time CPU Time Old Time New CPU Old CPU New + ----------------------------------------------------------------------------------------------------------------------------------------------------------- + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10 -0.1764 -0.1771 0 0 0 0 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/64 -0.1394 -0.1394 0 0 0 0 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/512 -0.0644 -0.0645 0 0 0 0 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/4096 +0.0132 +0.0131 1 1 1 1 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/retaingids/10000 -0.0029 -0.0034 3 3 3 3 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/10 +0.0364 +0.0362 0 0 0 0 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/64 +0.0346 +0.0343 0 0 0 0 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/512 +0.0271 +0.0268 0 0 0 0 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/4096 +0.0193 +0.0193 1 1 1 1 + BM_subset/subset_glyphs/Mplus1p-Regular.ttf/10000 -0.0240 -0.0243 2 2 2 2 + OVERALL_GEOMEAN -0.0305 -0.0307 0 0 0 0 + + src/OT/glyf/SubsetGlyph.hh | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +commit 6ec7629fba96f8be175eac108f7eee83de6cae21 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 18:18:30 2023 -0600 + + [subset/glyf] Add a const + + src/OT/glyf/SubsetGlyph.hh | 2 +- + src/OT/glyf/glyf.hh | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +commit 9f54ab922f42e954f19432aeacb4bb4022c27e3d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 17:45:03 2023 -0600 + + [subset-plan] Keep a reverse-gid vector + + To speed up iteration. + + src/hb-ot-hmtx-table.hh | 16 +++++++++------- + src/hb-subset-plan-member-list.hh | 2 ++ + src/hb-subset-plan.cc | 9 ++++++++- + 3 files changed, 19 insertions(+), 8 deletions(-) + +commit 6b0d3867978c3f42ab8dfbebcedd7567adf28bfe +Author: Garret Rieger <grieger@google.com> +Date: Thu Jun 1 23:59:55 2023 +0000 + + [subset] in subset benchmarks switch nohinting with retaingids. + + retain gids is a more interesting case than no hinting for performance. + + perf/benchmark-subset.cc | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +commit 1ae99d1a10e4add937488591632f94edca7bdbdd +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Jun 1 15:22:26 2023 -0700 + + bug fix + + src/hb-ot-var-common.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit aa7dd70a862d6fa516e0aa8194e4cd4983cda934 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Jun 1 14:24:33 2023 -0600 + + [hmtx] Reduce map usage slightly + + src/hb-ot-hmtx-table.hh | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +commit f41c5ec961c559a99045cc84760bac422998b2e3 +Author: Garret Rieger <grieger@google.com> +Date: Thu Jun 1 18:38:05 2023 +0000 + + [map] update map benchmark to also test lookups that hit. + + perf/benchmark-map.cc | 52 ++++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 45 insertions(+), 7 deletions(-) + +commit 4acf6a82bf47a602a9378c84d80a9ccb885145d0 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue May 30 09:26:58 2023 -0700 + + [instancer-solver] port solver fix from fonttools + + See https://github.com/fonttools/fonttools/issues/3139 + + src/hb-subset-instancer-solver.cc | 2 +- + src/test-subset-instancer-solver.cc | 18 ++++++++++++++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + +commit f3b4d35f362efb818959814b741e94facda5fd29 +Author: Garret Rieger <grieger@google.com> +Date: Mon May 29 22:38:40 2023 +0000 + + [subset] Fix fuzzer crash. + + https://oss-fuzz.com/testcase-detail/6608005089853440 + + src/hb-serialize.hh | 6 +++++- + ...z-testcase-minimized-hb-subset-fuzzer-6608005089853440 | Bin 0 -> 999 bytes + 2 files changed, 5 insertions(+), 1 deletion(-) + +commit ff326fbe8f5dfb579b6468ffba13bad279322d2b +Author: Garret Rieger <grieger@google.com> +Date: Mon May 29 21:31:01 2023 +0000 + + [repacker] check the result of add_buffer() in other places where it's called. + + src/graph/classdef-graph.hh | 8 +++++++- + src/graph/coverage-graph.hh | 8 +++++++- + src/graph/gsubgpos-graph.hh | 12 +++++++++--- + 3 files changed, 23 insertions(+), 5 deletions(-) + +commit 66a84355ab8a6c2b1e724e844ef4a79ca22a5cf7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon May 29 17:17:15 2023 -0600 + + [hash] Use unsigned types + + Hopefully ubsan wouldn't complain about overflows now. + + src/hb-algs.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 4a93576bca0f56e82a1d8ad67733df9c5ddb8dcd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun May 28 13:22:35 2023 -0600 + + Revert "[map] Speedup for int types" + + This reverts commit c1b75f5ff0460274229801816265a0efe5731b3a. + + I was seeing very long chains (140) and a 17% slowdown in + BM_subset/subset_codepoints/RobotoFlex-Variable.ttf/512 + + Bummer. + + src/hb-map.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit c1b75f5ff0460274229801816265a0efe5731b3a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun May 28 12:53:17 2023 -0600 + + [map] Speedup for int types + + Since our int hash is now good, we don't need the modulo prime + here, so forgo it. Major speedup: + + Comparing before to after + Benchmark Time CPU Time Old Time New CPU Old CPU New + ------------------------------------------------------------------------------------------------------------------- + BM_MapInsert/16 -0.4136 -0.4137 6 4 6 4 + BM_MapInsert/64 -0.4442 -0.4441 6 3 6 3 + BM_MapInsert/512 -0.5382 -0.5383 8 4 8 4 + BM_MapInsert/4096 -0.4160 -0.4162 8 5 8 5 + BM_MapInsert/32768 -0.3256 -0.3258 12 8 12 8 + BM_MapInsert/262144 -0.1723 -0.1727 11 10 11 9 + BM_MapInsert/1048576 -0.2310 -0.2309 28 22 28 22 + BM_MapLookup/16 -0.0247 -0.0247 3 3 3 3 + BM_MapLookup/64 -0.1039 -0.1038 3 3 3 3 + BM_MapLookup/512 -0.1076 -0.1079 4 3 4 3 + BM_MapLookup/4096 -0.3729 -0.3732 9 6 9 6 + BM_MapLookup/32768 +0.2467 +0.2468 9 12 9 12 + BM_MapLookup/262144 -0.1862 -0.1868 14 11 14 11 + BM_MapLookup/1048576 +0.1159 +0.1160 15 17 15 17 + OVERALL_GEOMEAN -0.2414 -0.2416 0 0 0 0 + + src/hb-map.hh | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +commit 7f111787e467a52b9b29daae3783a27b620c5593 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat May 27 12:41:05 2023 -0600 + + [benchmark-map] Remove overhead + + perf/benchmark-map.cc | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +commit 5666807328c0cf0f6ac5d6f9079d33edb5b42d88 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat May 27 12:37:36 2023 -0600 + + [benchmark-map] Improve Insert benchmark + + Previously it was enlarging the map depending on whatever + number of runs the benchmark-runner decided to run the loop. + That wasn't very useful... + + perf/benchmark-map.cc | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +commit 00900f761f45fd963f727241ffe56d14b2b1b768 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat May 27 10:13:53 2023 -0600 + + [hash] Enable better hash for integers + + https://github.com/harfbuzz/harfbuzz/pull/4228#issuecomment-1565079537 + + src/hb-algs.hh | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +commit 20c564bc7620be7f9325376601797fc20622f845 +Author: Garret Rieger <grieger@google.com> +Date: Fri May 26 23:04:25 2023 +0000 + + [repacker] Fix fuzzer memory leak. + + https://oss-fuzz.com/testcase-detail/6419865171525632 + + src/graph/graph.hh | 3 ++- + src/graph/gsubgpos-context.cc | 6 +++++- + src/graph/gsubgpos-context.hh | 4 ++-- + ...stcase-minimized-hb-repacker-fuzzer-6419865171525632 | Bin 0 -> 65751 bytes + 4 files changed, 9 insertions(+), 4 deletions(-) + +commit 5abe713203210cfc190a1b94482b9aceab0ec724 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 26 15:56:30 2023 -0600 + + [map] Resize map on long chain probes + + src/hb-map.hh | 9 +++++++++ + 1 file changed, 9 insertions(+) + +commit a652281ed6125e49ab43f0b25e88bc72b2d98085 +Author: Garret Rieger <grieger@google.com> +Date: Fri May 26 19:47:50 2023 +0000 + + [subset] Fix fuzzer timeout. + + Fixes https://oss-fuzz.com/testcase-detail/5979721620652032. Timeout was caused by degenerate map insert behaviour due to poor integer hash function. Presize the map to avoid it. Also fixes collect_mapping() for cmap format 13. + + src/hb-ot-cmap-table.hh | 13 ++++++++++--- + .../clusterfuzz-testcase-hb-subset-fuzzer-5979721620652032 | Bin 0 -> 80 bytes + 2 files changed, 10 insertions(+), 3 deletions(-) + +commit 208c9490cb29e057dd57f897de739076746d84c2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 26 12:02:03 2023 -0600 + + [VarComposite] Limit number of axes that are copied + + Bandaid for https://oss-fuzz.com/testcase-detail/4591122882887680 + + src/OT/glyf/Glyph.hh | 5 ++++- + src/OT/glyf/coord-setter.hh | 2 ++ + src/hb-limits.hh | 4 ++++ + 3 files changed, 10 insertions(+), 1 deletion(-) + +commit 5872bdf64ddbf99f7863da382f79ab408cd99e8c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 26 11:41:54 2023 -0600 + + [vector] Add copy-constructor for array_t's + + src/OT/glyf/Glyph.hh | 2 +- + src/hb-vector.hh | 22 +++++++++++++++++----- + src/test-vector.cc | 5 +++++ + 3 files changed, 23 insertions(+), 6 deletions(-) + +commit 42aba5ff30647587d446ab6279d02f8dbe2a84cf +Author: Chun-wei Fan <fanc999@yahoo.com.tw> +Date: Wed May 24 12:19:50 2023 +0800 + + harfbuzz-config.cmake.in: Support Windows usage + + Apply the appropriate library prefix/suffix by whether we are building + as a statib build in Meson, or by using + ${CMAKE_[SHARED|IMPORT]_LIBRARY_PREFIX} and + ${CMAKE_[SHARED|IMPORT]_LIRBARY_SUFFIX} as appropriate according to + the target platform for shared builds. + + src/harfbuzz-config.cmake.in | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +commit 84354d3f23241a17878b54d635ff68c65508aa71 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 23 11:57:22 2023 -0600 + + [cff] When max-ops is reached return false + + Slight speedup too. + + src/hb-cff-interp-cs-common.hh | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +commit 2655b7607c21e1233378959f87a210e4431ad4d7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 23 10:57:58 2023 -0600 + + [map] Micro-optimize + + This shows a speedup. + + src/hb-map.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 12b0680e60ece83844436f61d4269ce38f689c8f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 23 10:49:41 2023 -0600 + + [map] Fix set() + + This was broken in 2133aa2407657d0b3b4b73a4951c05ed26d055f2. + + We have to keep probing over tombstones. + + src/hb-map.hh | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +commit 4056315c868693c655373856a83603fdc1587aab +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon May 22 14:17:12 2023 -0600 + + [font] Remove redundant avar mapping line + + The avar mapping happens in hb_ot_var_normalize_coords() call. + + src/hb-font.cc | 3 --- + 1 file changed, 3 deletions(-) + +commit 592a3d0e96db8ba75432ea2de1fa106a533da09f +Merge: 2f21dc23b 0d354e044 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun May 21 22:00:53 2023 +0200 + + Merge pull request #4237 from harfbuzz/layout-font-extents + + [layout] Add hb_ot_layout_get_font_extents() + +commit 0d354e0442d12b71aec58ac83e7b6ede377c263e +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun May 21 19:01:04 2023 +0300 + + [layout] Add tests for baseline 2 APIs + + test/api/test-baseline.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +commit e047b1abbcb7edc9c4a5263b524a9a52f6a6198d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat May 20 10:27:31 2023 -0600 + + [layout] Improve docs + + src/hb-ot-layout.cc | 9 +++++++++ + 1 file changed, 9 insertions(+) + +commit 132391ad62b90c27a95429b81a27febf4b183a37 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 19 15:01:49 2023 -0600 + + [layout] Add test for font_extents + + test/api/Makefile.am | 1 + + test/api/fonts/base-minmax.ttf | Bin 0 -> 352 bytes + test/api/meson.build | 1 + + test/api/test-base-minmax.c | 66 +++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 68 insertions(+) + +commit 6996e64f72896ee1d210f5fdc5fea143590f9f3f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 19 14:22:13 2023 -0600 + + [BASE] Sanitize and get_min_max fixups + + Seems to work now. + + src/hb-ot-layout-base-table.hh | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +commit 02e0e9394b42d8f5290a2e9699890b180c09d151 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 19 13:18:06 2023 -0600 + + [layout] Fetch default font extents if localized extents not found + + src/hb-ot-layout.cc | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +commit 8ccc1ff21e404ab02f673a0727af58cbadc822a9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 19 13:14:57 2023 -0600 + + [layout] Mark language as nullable + + GI needs it apparently. + + src/hb-ot-layout.cc | 6 +++--- + src/hb-ot-tag.cc | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +commit 792ca22ca3212dc5f69f3c85901f63b538ae00b5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 19 11:42:20 2023 -0600 + + [layout] Document new API + + src/hb-ot-layout.cc | 39 ++++++++++++++++++++++++++++++++++++--- + 1 file changed, 36 insertions(+), 3 deletions(-) + +commit 0894813a38d7ba7db1e58c829be15fe4149811b3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 19 11:30:03 2023 -0600 + + [layout] Add "2" version of BASE table API + + ...that do the script/language resolution. + + Part of https://github.com/harfbuzz/harfbuzz/pull/4237 + + Ref https://github.com/harfbuzz/harfbuzz/issues/3439 + + docs/harfbuzz-sections.txt | 3 ++ + src/hb-ot-layout.cc | 109 +++++++++++++++++++++++++++++++++++++++++++-- + src/hb-ot-layout.h | 32 +++++++++++-- + 3 files changed, 136 insertions(+), 8 deletions(-) + +commit 3e110c69c45a0d4d453ca9db74848442b6670671 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri May 19 11:06:26 2023 -0600 + + [layout] Add hb_ot_layout_get_font_extents() + + Untested. + + Fixes https://github.com/harfbuzz/harfbuzz/issues/3290 + + docs/harfbuzz-sections.txt | 1 + + src/hb-ot-layout-base-table.hh | 3 +-- + src/hb-ot-layout.cc | 21 +++++++++++++++++++++ + src/hb-ot-layout.h | 6 ++++++ + 4 files changed, 29 insertions(+), 2 deletions(-) + +commit 2f21dc23b51043bb95343d3c6a910a105536f8c2 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu May 18 07:14:28 2023 +0100 + + [wasm] [docs] Improve build flags information + + docs/wasm-shaper.md | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +commit 134cc8edfa14bd50be0802f644f36b03030d17a7 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Wed May 17 16:58:49 2023 +0100 + + [wasm] [docs] How to build + + docs/wasm-shaper.md | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +commit 5543d05885011d5acb0ef53759a85e759168918f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed May 17 17:29:44 2023 +0200 + + [subset] Use vector instead of map for glyph bounds (#4232) + + * [subset] Use vector instead of map for glyph bounds + + Is faster. + + Part of https://github.com/harfbuzz/harfbuzz/issues/4231 + + * [subset] initialize bounds_vec value to 0xFFFFFFFF + + Some non-EMPTY glyph might have 0 bounds width/height + + --------- + + Co-authored-by: Qunxin Liu <qxliu@google.com> + + src/OT/glyf/Glyph.hh | 8 ++++---- + src/hb-ot-hmtx-table.hh | 12 +++++++----- + src/hb-subset-plan-member-list.hh | 4 ++-- + src/hb-subset-plan.cc | 11 +++++++++-- + 4 files changed, 22 insertions(+), 13 deletions(-) + +commit ccfd7ef08c28c2f49d7fc52dbbc4b3fa7461b5e5 +Merge: c248fd913 6ed792ef4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed May 17 16:00:33 2023 +0200 + + Merge pull request #4131 from harfbuzz/wasm + + [wasm] WebAssembly shaper + +commit 6ed792ef4b00287e16e0b5eda7fe9488e6060e9a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed May 17 07:58:27 2023 -0600 + + [meson] Report WebAssembly build + + meson.build | 3 ++- + meson_options.txt | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +commit 56af88d04848dec4d4d4ad6d713b22d92edff7e8 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Wed May 17 12:38:59 2023 +0100 + + [wasm] More thorough API docs + + docs/wasm-shaper.md | 368 +++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 367 insertions(+), 1 deletion(-) + +commit c248fd91334feb0a427051aab75dfe9fb93f6d22 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed May 10 01:44:10 2023 -0600 + + [hash] Comment + + src/hb-algs.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 42f4dab8dbd0fab994170047700076fbf1c85a23 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed May 10 01:11:32 2023 -0600 + + [hash] Switch to Knuth multiplicative hash + + Wow, the old adhoc one was why the cmap test was timing out! + + src/hb-algs.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 0270e3e97492d975c7f65bb01dd819a4c9314cae +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 23:46:18 2023 -0600 + + [map] Reinstate quadratic probing + + src/hb-map.hh | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +commit 19b628bdf074a30c222b04b5f2c50f1db655f03b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 23:40:07 2023 -0600 + + Revert "[map] Implement Robinhood hashing" + + This reverts commit 705617856818056a44a627f340c91e335c57f310. + + src/hb-algs.hh | 2 +- + src/hb-map.hh | 40 ++++++---------------------------------- + 2 files changed, 7 insertions(+), 35 deletions(-) + +commit 18c3ba5018a7c1cd6701775e397d699cb7e7a11b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 22:44:22 2023 -0600 + + [map] Implement Robinhood hashing + + Numbers are not improved though. :( + + src/hb-algs.hh | 2 +- + src/hb-map.hh | 40 ++++++++++++++++++++++++++++++++++------ + 2 files changed, 35 insertions(+), 7 deletions(-) + +commit 2133aa2407657d0b3b4b73a4951c05ed26d055f2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 21:06:17 2023 -0600 + + [map] Inline code for set() + + src/hb-map.hh | 32 ++++++++++++++------------------ + 1 file changed, 14 insertions(+), 18 deletions(-) + +commit 5bf5188ea2d31cd162f61b923e56614c446e7ad3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 20:47:46 2023 -0600 + + [map] Simplify del() + + src/hb-map.hh | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +commit 2ffec3a6f4881cabab6f4ca8d3e200a952f2d083 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 20:44:23 2023 -0600 + + [map] Shuffle fetch_item + + src/hb-map.hh | 28 ++++++++++++++++------------ + 1 file changed, 16 insertions(+), 12 deletions(-) + +commit 1dc99128b92f4bb7b2737c129961082e642f7c4c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 20:37:12 2023 -0600 + + [map] Separate has() code from set() code + + src/hb-map.hh | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +commit 2dd0803c850521d104bb927de8fc54e2b9d64166 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 20:35:09 2023 -0600 + + [map] Downgrade from quadratic to linear probing + + src/hb-map.hh | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 498197671a8d828d4a4254818693dbd502707ed2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 20:24:12 2023 -0600 + + [map] Write get() in terms of has() + + src/hb-map.hh | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +commit f37941bb52457f3be81f34de62e4f5b93f048cf0 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue May 9 11:53:15 2023 -0700 + + [instancer] add tests for instancer-solver from python test suite + + Also fix bug in the solver code + + src/Makefile.am | 5 + + src/hb-subset-instancer-solver.cc | 4 +- + src/meson.build | 1 + + src/test-subset-instancer-solver.cc | 351 ++++++++++++++++++++++++++++++++++++ + 4 files changed, 359 insertions(+), 2 deletions(-) + +commit 39ac79a7f5afb812880e8f376b00a85c509c0cf5 +Author: Qunxin Liu <qxliu@google.com> +Date: Wed May 10 10:22:49 2023 -0700 + + address review comments + + src/hb-ot-stat-table.hh | 20 ++++------------- + src/hb-ot-var-fvar-table.hh | 47 ++++++++++++++++++++------------------- + src/hb-subset-instancer-solver.hh | 3 +++ + src/hb-subset-plan.cc | 3 --- + 4 files changed, 31 insertions(+), 42 deletions(-) + +commit 58f68dd37a595c51f8e9545de165cd5a1ff5479e +Author: Qunxin Liu <qxliu@google.com> +Date: Thu May 4 14:25:14 2023 -0700 + + [instancer] wrap hb_subset_input_Set_axis_range() under experimental + + Also add notes: it's not actually working yet. + + docs/harfbuzz-sections.txt | 1 + + src/gen-def.py | 1 + + src/hb-subset-input.cc | 6 +++++- + src/hb-subset.h | 2 +- + 4 files changed, 8 insertions(+), 2 deletions(-) + +commit f3a3c3b29d2c0e4557dc8bc9666bb1efab11af82 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu May 4 13:19:12 2023 -0700 + + fix bot + + src/hb-ot-stat-table.hh | 2 -- + 1 file changed, 2 deletions(-) + +commit efc77dc68fea89e8ddc03d09b605e7d6ad6ff240 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu May 4 10:59:09 2023 -0700 + + [instancer] update code for collecting FeatureVariationRecord + + src/hb-ot-layout-common.hh | 95 +++++++++++++++++++++++++++++----------------- + src/hb-subset-plan.cc | 27 +++++++++---- + 2 files changed, 80 insertions(+), 42 deletions(-) + +commit bf298e505064e6b02757e31d5557a611a0a065be +Author: Qunxin Liu <qxliu@google.com> +Date: Mon May 1 13:40:19 2023 -0700 + + [instancer ]update OS_2/post/glyf tables to accept Triple for axes positions + + src/OT/glyf/glyf.hh | 2 +- + src/hb-ot-os2-table.hh | 4 ++-- + src/hb-ot-post-table.hh | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +commit 51c7451bb52ab0a16539b33b46f7d9a725f8f989 +Author: Qunxin Liu <qxliu@google.com> +Date: Mon May 1 13:38:02 2023 -0700 + + [instancer] update fvar table to accept Tripe for axes positions + + src/hb-ot-stat-table.hh | 2 +- + src/hb-ot-var-fvar-table.hh | 78 +++++++++++++++++++++++++++++++-------------- + src/hb-subset-plan.cc | 2 +- + 3 files changed, 56 insertions(+), 26 deletions(-) + +commit bf46d566f9522b39cd4d1def1e33335b1918fff1 +Author: Qunxin Liu <qxliu@google.com> +Date: Mon May 1 11:23:51 2023 -0700 + + [instancer] update STAT table to accept Triples for axes positions + + src/hb-ot-stat-table.hh | 59 +++++++++++++++++++++++++++++-------------------- + 1 file changed, 35 insertions(+), 24 deletions(-) + +commit 779e8ba080014402fc62ec9dcef3b61d4a5aa21a +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Apr 27 13:48:24 2023 -0700 + + [instancer] update subset-plan.cc to accept Triple as axes positions + + src/hb-subset-plan.cc | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +commit 22cca43dedecdec80278d26bd1626c8a1992787f +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Apr 20 14:37:29 2023 -0700 + + [instancer ]update internal hashmap to use Triple instead of single value + + -Added hb-subset-instancer-solver.hh file and moved Triple struct to the + head file + + src/Makefile.sources | 1 + + src/hb-subset-input.cc | 7 ++-- + src/hb-subset-input.hh | 3 +- + src/hb-subset-instancer-solver.cc | 39 +--------------------- + src/hb-subset-instancer-solver.hh | 69 +++++++++++++++++++++++++++++++++++++++ + src/hb-subset-plan-member-list.hh | 8 ++--- + src/hb-subset-plan.hh | 4 +++ + src/meson.build | 1 + + 8 files changed, 86 insertions(+), 46 deletions(-) + +commit 0799afe2b6b9c1e06505a7e6a604cfb597b5c9ef +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Apr 20 14:02:20 2023 -0700 + + [instancer] Add hb_subset_input_set_axis_range() API + + src/hb-subset-input.cc | 40 ++++++++++++++++++++++++++++++++++++++++ + src/hb-subset.h | 7 +++++++ + 2 files changed, 47 insertions(+) + +commit 5d543d64222c6ce45332d0c188790f90691ef112 +Merge: 4584bcdc3 5d0cc0062 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 19:02:26 2023 -0600 + + Merge pull request #4228 from harfbuzz/better-hash + + Better hash + +commit 5d0cc0062a75013a388f6929b59cbfa7939dc6e1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 18:40:35 2023 -0600 + + [hash] Disable int hash as it has negative performance gain + + src/hb-algs.hh | 8 ++++++++ + 1 file changed, 8 insertions(+) + +commit 1fbb08584b172553651a7842ec9ee977991c93c7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 17:11:05 2023 -0600 + + [hash] Adjust prime number + + Previous one wasn't a prime. Ouch! + + src/hb-algs.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 9cc7eb80ffac20cc5cfa90b80bcff2872f6c466b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 16:13:46 2023 -0600 + + [hash] Speed-up int64 hash + + src/hb-algs.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + commit 4584bcdc326564829d3cee3572386c90e4fd1974 Author: Khaled Hosny <khaled@aliftype.com> Date: Wed May 10 00:20:25 2023 +0300 @@ -12,6 +5284,214 @@ Date: Wed May 10 00:20:25 2023 +0300 src/hb-version.h | 4 ++-- 6 files changed, 27 insertions(+), 5 deletions(-) +commit 826fe2c9f78932af8c5aed4ba4db6328f83f44fe +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 13:48:38 2023 -0600 + + [hash] Wrap specialization in HB_OPTIMIZE_SIZE_MORE + + src/hb-array.hh | 2 ++ + 1 file changed, 2 insertions(+) + +commit b2b15fa30aeaad022a7953f2a150442d69e30e5b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 13:39:52 2023 -0600 + + [hash] Links + + src/hb-algs.hh | 3 ++- + src/hb-array.hh | 3 +++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +commit 05567da082b59bc422356c8c10cbe8fc87a6bd13 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 12:22:43 2023 -0600 + + Revert "[hash] Use fasthash for integer hash" + + This reverts commit 3bf758a57071572a0ffae3c359b4cfec5a096312. + + This was resulting in long chains again :(. + + src/hb-algs.hh | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +commit bdaa74d25ff5477c72f69249181b5d840cb4cb59 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 11:58:35 2023 -0600 + + [hash] Use fasthash for integer hash + + This seems to speed things up surprisingly. + + src/hb-algs.hh | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +commit a58bbe5408b76c6b22d3b097649b7eef530c3e13 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 12:06:35 2023 -0600 + + [set] Use better hash + + src/hb-bit-page.hh | 5 +---- + src/hb-bit-set.hh | 6 +++++- + 2 files changed, 6 insertions(+), 5 deletions(-) + +commit fe3339ea241528652f3480fb061abca3c6bb2ed8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 11:31:06 2023 -0600 + + [algs] Add hash for 64bit ints + + src/hb-algs.hh | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +commit 33ef96b649fd249808af6a13f376efb819e31882 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 11:13:51 2023 -0600 + + [glyf] Micro-optimize a few hash operations + + src/OT/glyf/Glyph.hh | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +commit abb92388cc8bebff0cf40cbed0045292e038bcd8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 10:54:54 2023 -0600 + + Revert "[map] Adjust resizing criteria" + + This reverts commit 1fa4b415315257bdbae08e6539f2ca63423572e8. + + src/hb-map.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 1fa4b415315257bdbae08e6539f2ca63423572e8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 10:52:58 2023 -0600 + + [map] Adjust resizing criteria + + src/hb-map.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit f04d08b883d9b4894d5329cec351d2f0ea50590b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 02:14:30 2023 -0600 + + [fasthash] Remove GNU extension + + src/hb-algs.hh | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +commit 99f5050ccd35e6e447661af2ed330f509ae9bcd8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 02:07:54 2023 -0600 + + [algs] Remove HB_NO_PACKED + + We depend on packed attribute in fasthash now. + + src/hb-algs.hh | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +commit da619c69c8f1a4be9e29bbc95cf684bf38641468 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 02:06:37 2023 -0600 + + [fasthash] Try to fix unaligned access + + src/hb-algs.hh | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +commit 075ecff750088854854147d0b32b88b120693a48 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 01:43:39 2023 -0600 + + [hash] Work around g++ bug?! + + I kid you not. Revert this and see src/test-map loop forever + eating your memory freezing your maching. + + In this loop: + + { + hb_hashmap_t<int, int> m0; + hb_hashmap_t<std::string, int> m1; + hb_hashmap_t<int, std::string> m2; + hb_hashmap_t<std::string, std::string> m3; + + std::string s; + for (unsigned i = 1; i < 1000; i++) + { + s += "x"; + m0.set (i, i); + m1.set (s, i); + m2.set (i, s); + m3.set (s, s); + } + } + + i will not stop at 1000 and just keeps going. If you figure out + what's going on, please enlighten me! + + src/hb-algs.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 9fbab46f2636aabf70ff10acc6c141b147794a2a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue May 9 01:42:44 2023 -0600 + + [cairo] Fix a clang warning + + src/hb-cairo-utils.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit e2fd49ff1a419dad6d6dd077aa25c20d054530ff +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon May 8 23:37:47 2023 -0600 + + [hash] Comment + + src/hb-algs.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit fa64e42d755709df2837fcfb8d60ff6d8b1179fb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon May 8 23:31:52 2023 -0600 + + [algs] Adjust int hash + + src/hb-algs.hh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit 078b2a510189088ceda4cf23bc7c0197518831dd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon May 8 22:28:48 2023 -0600 + + [hash] Use a Mersenne prime for int hash + + And hope that compiler optimizes to int ops instead of modula. + + Improves chaining it seems. + + Part of https://github.com/harfbuzz/harfbuzz/pull/4228 + + src/hb-algs.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit fe0f7dc57bc7411c7cc7eb80fa44c8dd8c5e4644 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon May 8 22:19:02 2023 -0600 + + [bytes] Use fasthash as hash algorithm + + Part of https://github.com/harfbuzz/harfbuzz/pull/4228 + + src/hb-algs.hh | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/hb-array.hh | 18 ++------------ + 2 files changed, 78 insertions(+), 16 deletions(-) + commit 4bbcff2c5c00d4e2029a176c3388ad4fe77945df Author: Rod S <rsheeter@google.com> Date: Mon May 8 20:29:35 2023 -0700 @@ -21,6 +5501,28 @@ Date: Mon May 8 20:29:35 2023 -0700 docs/usermanual-getting-started.xml | 4 ++++ 1 file changed, 4 insertions(+) +commit c005e3a2e30eaea700e67907dc816709263b4046 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon May 8 16:33:31 2023 -0600 + + [bytes] Simplify hash function + + Part of https://github.com/harfbuzz/harfbuzz/issues/4227 + + src/hb-array.hh | 32 ++++---------------------------- + 1 file changed, 4 insertions(+), 28 deletions(-) + +commit 0e026808036f59d3ea4e5954b1a19fcfcb9a9702 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon May 8 16:31:58 2023 -0600 + + [hash] Add hash impl for integers + + Part of https://github.com/harfbuzz/harfbuzz/issues/4227 + + src/hb-algs.hh | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + commit b7a8d23bc8594c84c72d54dbbffa1c1acbb92c67 Author: Behdad Esfahbod <behdad@behdad.org> Date: Mon May 8 14:32:24 2023 -0600 @@ -2444,6 +7946,1599 @@ Date: Tue Apr 4 10:33:58 2023 -0700 test/subset/meson.build | 1 + 11 files changed, 128 insertions(+), 1 deletion(-) +commit 2663a9b6f98a4afebe43ee213c5c14af6c2c5ce5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Mar 31 17:38:23 2023 -0600 + + [wasm] Rename a couple APIs + + src/hb-wasm-api-blob.hh | 20 -------------------- + src/hb-wasm-api-face.hh | 27 ++++++++++++++++++--------- + src/hb-wasm-api-font.hh | 11 +++++++++++ + src/hb-wasm-api-list.hh | 4 ++-- + src/hb-wasm-api.h | 10 +++++----- + 5 files changed, 36 insertions(+), 36 deletions(-) + +commit d2fb583a5a2e7839a88a8a4b3c1832459223c732 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Mar 31 12:18:41 2023 -0600 + + [wasm-graphite] Fix advance signedness + + src/wasm/graphite/shape.cc | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +commit f9dd402ef8c49bbb89d7c1311a6008a492f4182d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Mar 31 12:18:35 2023 -0600 + + [wasm] Fix header + + src/hb-wasm-api.h | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +commit 85a1fdd93fcafbfdd91bec2d16cf0ce6f3a0cd79 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Mon Mar 27 14:42:21 2023 +0100 + + [wasm] get/set font variation parameters + + src/hb-wasm-api-font.hh | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ + src/hb-wasm-api-list.hh | 2 ++ + src/hb-wasm-api.h | 14 +++++++++++++ + 3 files changed, 72 insertions(+) + +commit 0bfad127c3a907d5c50e59ab61a2beac69853cb1 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sun Mar 26 17:44:55 2023 +0100 + + [wasm] Make _hb_wasm_module_reader conditional + + Or else uharfbuzz doesn't build. + + src/hb-wasm-shape.cc | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +commit 3fc48d4ada4e4ed1535f7a38cba9b3f85d21ad9b +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sun Mar 26 17:43:14 2023 +0100 + + [wasm] [experimental] wrap hb_face_create and hb_create_font + + src/hb-wasm-api-blob.hh | 20 ++++++++++++++++++++ + src/hb-wasm-api-face.hh | 9 +++++++++ + src/hb-wasm-api-list.hh | 2 ++ + src/hb-wasm-api.h | 5 +++++ + 4 files changed, 36 insertions(+) + +commit 0a16c60b42a03603d12affd9746da1d0a0e67adf +Author: Simon Cozens <simon@simon-cozens.org> +Date: Fri Mar 10 14:31:56 2023 +0000 + + [wasm-rust] Derive some friendly traits + + src/wasm/rust/harfbuzz-wasm/src/lib.rs | 1 + + 1 file changed, 1 insertion(+) + +commit 6ff994f31d4dc0a929dffae2ff6772096a2e51fd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Mar 3 15:33:48 2023 -0700 + + [wasm-api-shape] Avoid a couple of crashes + + src/hb-wasm-api-shape.hh | 8 ++++++++ + 1 file changed, 8 insertions(+) + +commit b6c18144106955f30ac9ec645b0c7eac860c6a7f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Mar 3 11:31:08 2023 -0700 + + [wasm] Comment + + src/hb-wasm-api-list.hh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit e78d8653cebc1803f669c238b2e42300717af7c8 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu Mar 2 19:47:33 2023 +0000 + + [wasm-rust] panic if buffer_set_contents fails + + src/wasm/rust/harfbuzz-wasm/src/lib.rs | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +commit 74a2f338c67a8c3cd5220b19366f0331332dd69d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Mar 2 10:29:01 2023 -0700 + + [wasm-shape] Don't crash if font is bad + + src/hb-wasm-shape.cc | 5 +++++ + 1 file changed, 5 insertions(+) + +commit 7df9b3dd892abfcb31be072ae47193cb0482b51e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Feb 26 14:54:07 2023 -0700 + + [wasm-api-list] Add TODO + + src/hb-wasm-api-list.hh | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +commit f5a0bd223b2194203aa7435ac09fc73468544a46 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Feb 26 14:05:26 2023 -0700 + + [wasm-shape] Comment re thread-safety + + src/hb-wasm-shape.cc | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +commit 7e5064ac1b259f5f92a588fc42096337c2f37a1c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Feb 26 14:01:56 2023 -0700 + + [wasm-shape] Comment re thread-safety + + src/hb-wasm-shape.cc | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +commit 5235ee68adc1bec46fb7e0cb4f327f814961d595 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Feb 26 13:15:39 2023 -0700 + + [wasm-shape] Remove explicit running-mode setting + + It does it automatically. + + src/hb-wasm-shape.cc | 5 ----- + 1 file changed, 5 deletions(-) + +commit e89415b5b9f82ae1893343496ec659a0947b7055 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Feb 26 13:14:37 2023 -0700 + + [wasm-shape] Print another error message + + src/hb-wasm-shape.cc | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 6aea77c643777b7ed550edc63f65859c05430e53 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Feb 26 12:28:25 2023 -0700 + + [wasm-shape] Add (disabled) module support + + meson.build | 1 + + src/hb-wasm-shape.cc | 66 +++++++++++++++++++++++++++++++++++++++++++++- + src/wasm/graphite/Makefile | 2 +- + 3 files changed, 67 insertions(+), 2 deletions(-) + +commit 142ceaf2466b66fc868f125b4adc6e727b981f3b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sun Feb 26 12:18:31 2023 -0700 + + [wasm-shape] Print module instantiation error + + src/hb-wasm-shape.cc | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +commit 7e397d8695f32c91bddbf373cd19f4c6e61fa882 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sun Feb 26 13:57:34 2023 +0000 + + [wasm-rust] Fix shape parameters + + src/wasm/sample/rust/hello-wasm/src/lib.rs | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +commit d942f72c2a6325a25e213bbce5bc3a943be39861 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sun Feb 26 13:57:07 2023 +0000 + + [wasm-rust] Fix path + + src/wasm/sample/rust/hello-wasm/Cargo.toml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 52b11546c8b76206b97fd49d65ae2e850a7212d3 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sun Feb 26 13:57:00 2023 +0000 + + [wasm-rust] Optional kurbo dependency + + src/wasm/rust/harfbuzz-wasm/Cargo.toml | 1 + + src/wasm/rust/harfbuzz-wasm/src/lib.rs | 92 ++++++++++++++++++++++++++++++++-- + 2 files changed, 88 insertions(+), 5 deletions(-) + +commit 0c90555e5932817f7c3d820c5883172dd86844a9 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sun Feb 26 13:55:17 2023 +0000 + + [wasm] Fix Rust docs + + docs/wasm-shaper.md | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +commit 4f537df67de6d1475de5caf14d9cfd9886621dc1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 15:29:35 2023 -0700 + + [wasm] Disable check-libstdc++ test + + Since libiwasm.so links to it. + + src/meson.build | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +commit 2482bb120b8f29c830fe1c05d9b6bc75a651eae1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 15:14:25 2023 -0700 + + [wasm-shape] Add XXX item + + src/hb-wasm-shape.cc | 2 ++ + 1 file changed, 2 insertions(+) + +commit a53690a937bc7c4273e5f46a7f87ac8945ff282b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 15:10:10 2023 -0700 + + [wasm-shape] Minor rename + + src/hb-wasm-shape.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 3226b4342b88e44764393a6a9e1af458d70fa5fe +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 15:03:03 2023 -0700 + + [wasm-shape] Use hb allocators + + src/hb-wasm-shape.cc | 2 -- + 1 file changed, 2 deletions(-) + +commit 4096115b48e88881a73218b15e4f83ea128abbad +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 14:22:03 2023 -0700 + + [wasm-graphite] Export malloc/free + + Makes the wasm-micro-runtime use these instead of internal heap. + + src/wasm/graphite/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 7b1c5e86aea4babcecb572a9b69f04cf95f5d102 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 14:18:09 2023 -0700 + + [wasm-shape] Minor conditionalize allocation + + src/hb-wasm-shape.cc | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +commit 196c6b6c1f8f528c5fbdce540156fb6375e03a80 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 14:05:15 2023 -0700 + + [wasm-buffer] Fix buffer_contents_realloc + + src/hb-wasm-api-buffer.hh | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +commit b9d4758bf9679a1ad502f0beba7db75569fbf1a4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 13:07:56 2023 -0700 + + [wasm/graphite] Add commented out allocator export + + src/wasm/graphite/Makefile | 2 ++ + 1 file changed, 2 insertions(+) + +commit 3c599434332ba806babf4f280e491b5560ff0778 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 13:04:54 2023 -0700 + + [wasm/graphite] Remove stale comment + + src/wasm/graphite/shape.cc | 2 -- + 1 file changed, 2 deletions(-) + +commit 6311b72fcce18703eff35010bd20c05a748ae3e5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 12:57:57 2023 -0700 + + [wasm-shape] Shuffle code around + + src/hb-wasm-shape.cc | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +commit 9b66e45481c81c9af43d3dd5c2babad2121a9f59 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 12:44:32 2023 -0700 + + [wasm/graphite] Remove unused variable + + Wasm cannot export those? + + src/wasm/graphite/shape.cc | 3 --- + 1 file changed, 3 deletions(-) + +commit c5a88a068b933ab67ffa8c39c97ad11f2dfbd7d0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 12:43:22 2023 -0700 + + [wasm-api] Minor cleanup + + src/hb-wasm-api.h | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +commit 8215e7063232ffe3ff262c9839f1841e6d9bd7a1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 12:37:11 2023 -0700 + + [wasm-graphite] Memory hygiene + + src/wasm/graphite/shape.cc | 4 ++++ + 1 file changed, 4 insertions(+) + +commit faaae04359862e49d0750592d0fc1ddf8b6d4e37 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 12:36:57 2023 -0700 + + [wasm-shape] Minor + + src/hb-wasm-shape.cc | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +commit d5d8fc046fbd7b758f2e31b74e1b86b06b3acf8d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 12:17:30 2023 -0700 + + [wasm/graphite] Include standard headers + + Since we use emcc here. + + src/wasm/graphite/shape.cc | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +commit 1f86890b7526821279c6bf2bd3ead189bf558459 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 11:55:34 2023 -0700 + + [wasm/graphite] Typo + + src/wasm/graphite/Makefile | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit f95c2cc6d5ce9db646efde99768e2847016afc38 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 11:10:28 2023 -0700 + + [wasm] Infra for iwasm llvm build + + meson.build | 2 ++ + src/meson.build | 1 + + 2 files changed, 3 insertions(+) + +commit 65f7bac73c774e3e75efc35566b2d9466726ffd2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 11:07:31 2023 -0700 + + Revert "[wasm-shape] No need to set default runnint mode" + + This reverts commit fa484fac08a868e885b3252522668824f0f0fe71. + + src/hb-wasm-shape.cc | 5 +++++ + 1 file changed, 5 insertions(+) + +commit d894a10699c08ebf2f4854f28b6343a6b5ff7aea +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 10:48:41 2023 -0700 + + [wasm-shape] Debug message + + src/hb-wasm-shape.cc | 3 +++ + 1 file changed, 3 insertions(+) + +commit 91eb2f49dbf1e84da5e64f20a2b3c5b6f37f3c83 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 10:44:45 2023 -0700 + + [wasm-api-buffer] Minor variable + + src/hb-wasm-api-buffer.hh | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +commit 4260de12c1bb271033d9cd3b0f47a4cf77190bf3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 10:43:27 2023 -0700 + + [wasm] Add HB_ARRAY_APP2NATIVE + + src/hb-wasm-api-buffer.hh | 7 +++---- + src/hb-wasm-api-face.hh | 2 +- + src/hb-wasm-api-font.hh | 4 ++-- + src/hb-wasm-api.hh | 5 +++++ + 4 files changed, 11 insertions(+), 7 deletions(-) + +commit 1537e252bad82ea03b2a1550d2464bddc24e6e49 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 10:35:15 2023 -0700 + + [wasm] Minor blob validation + + src/hb-wasm-api-face.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 918df8ccaf48041994e3b107ed7d2f32d643ff03 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 10:29:03 2023 -0700 + + [wasm-api] Add glyph_outline_free + + src/hb-wasm-api-font.hh | 16 ++++++++++++++++ + src/hb-wasm-api-list.hh | 3 +++ + src/hb-wasm-api.h | 4 ++++ + src/wasm/sample/c/shape-fallback.cc | 8 +++++++- + 4 files changed, 30 insertions(+), 1 deletion(-) + +commit 7fff4a19ad0dc598f9eae271d2314003b2e44df5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 10:25:19 2023 -0700 + + [wasm-api] Reuse allocation in font_copy_glyph_outline + + src/hb-wasm-api-font.hh | 19 +++++++++++++++++++ + src/hb-wasm-api.h | 1 + + src/wasm/sample/c/shape-fallback.cc | 2 +- + 3 files changed, 21 insertions(+), 1 deletion(-) + +commit 41362cc339d2e6e547291cf73dcc147fe39966d1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 10:08:22 2023 -0700 + + [wasm] Simplify memory cleaning + + src/hb-wasm-api-buffer.hh | 3 ++- + src/hb-wasm-api-face.hh | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +commit 6746ca4ae2aa0623a56676eb77bb63975e1016b0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 09:41:20 2023 -0700 + + [wasm] Minor remove undefine function + + src/wasm/sample/c/shape-fallback.cc | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +commit b08026187ab7fbec7f8d6d4adca0a8dc9d02d74b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 09:34:03 2023 -0700 + + [wasm-api] Memory house-keeping + + src/hb-wasm-api-buffer.hh | 2 ++ + src/hb-wasm-api-face.hh | 2 ++ + 2 files changed, 4 insertions(+) + +commit f2d227ad9f03038ddbdb70b5a45adb29a19f5fb0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 09:30:40 2023 -0700 + + [wasm-api] Respect existing blob allocation in face_copy_blob + + src/hb-wasm-api-face.hh | 19 +++++++++++++++++-- + src/hb-wasm-api.h | 1 + + src/wasm/graphite/shape.cc | 2 +- + src/wasm/sample/c/shape-fallback.cc | 2 +- + 4 files changed, 20 insertions(+), 4 deletions(-) + +commit e7540043de3f38c4f442e696b569bcc6af90587f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 09:18:40 2023 -0700 + + [wasm-api] Make buffer_copy_contents reuse contents + + src/hb-wasm-api-buffer.hh | 26 +++++++++++++++++++++++++- + src/hb-wasm-api.h | 1 + + src/wasm/graphite/shape.cc | 2 +- + src/wasm/sample/c/shape-fallback.cc | 2 +- + 4 files changed, 28 insertions(+), 3 deletions(-) + +commit 65966e0c3da0fdb5a59abcc76533dfceccbc1425 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 08:59:03 2023 -0700 + + [wasm-api] Add font_copy_glyph_outline + + src/hb-wasm-api-font.hh | 46 +++++++++++++++++++++++++++++++++++++ + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 36 +++++++++++++++++++++++++++-- + src/wasm/sample/c/shape-fallback.cc | 4 ++++ + 4 files changed, 85 insertions(+), 2 deletions(-) + +commit 92a57b4b4aa60620040dd5a31dcb764643da9496 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sat Feb 25 15:38:08 2023 +0000 + + [wasm-rust] update font_copy_table API + + src/wasm/rust/harfbuzz-wasm/src/lib.rs | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +commit db789eacb41ecd74ee3c32d245e7e15640c58198 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sat Feb 25 15:35:37 2023 +0000 + + [wasm-rust] Docs and API update + + docs/wasm-shaper.md | 8 ++++---- + src/wasm/rust/harfbuzz-wasm/src/lib.rs | 12 ++++++++++-- + 2 files changed, 14 insertions(+), 6 deletions(-) + +commit 0d237d062e0826138769c405bb1c04c9ed8da247 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 08:32:35 2023 -0700 + + [wasm-shape] No need to set default runnint mode + + It's detected automatically apparently. + + src/hb-wasm-shape.cc | 5 ----- + 1 file changed, 5 deletions(-) + +commit 2004528cf8375b82c687e8b9eb12d485d14427f1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 08:23:14 2023 -0700 + + [wasm-api] Change face_copy_table to return success + + src/hb-wasm-api-face.hh | 29 ++++++++++++++++++++--------- + src/hb-wasm-api-list.hh | 2 +- + src/hb-wasm-api.h | 7 ++++--- + src/wasm/graphite/shape.cc | 4 +++- + src/wasm/sample/c/shape-fallback.cc | 5 ++++- + 5 files changed, 32 insertions(+), 15 deletions(-) + +commit 83b9c34f0b5d9b6b6f65aae0e1bb92877972a5ed +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sat Feb 25 15:23:22 2023 +0000 + + [wasm] Add rust example + + src/wasm/sample/rust/hello-wasm/Cargo.toml | 13 +++++++++++++ + src/wasm/sample/rust/hello-wasm/src/lib.rs | 18 ++++++++++++++++++ + 2 files changed, 31 insertions(+) + +commit 840b5dff734e566b258fc3a1ee556739af31b45c +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sat Feb 25 15:20:39 2023 +0000 + + [wasm] Improve Rust docs, refer to new crate + + docs/wasm-shaper.md | 103 +++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 69 insertions(+), 34 deletions(-) + +commit 28a7c1f93247d692475ded0ea4dd6d0b5dd94044 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 08:16:31 2023 -0700 + + [wasm-api] Rename face_reference_table to face_copy_table + + src/hb-wasm-api-face.hh | 6 +++--- + src/hb-wasm-api-list.hh | 2 +- + src/hb-wasm-api.h | 6 +++--- + src/wasm/graphite/shape.cc | 2 +- + src/wasm/rust/harfbuzz-wasm/src/lib.rs | 4 ++-- + src/wasm/sample/c/shape-fallback.cc | 2 +- + 6 files changed, 11 insertions(+), 11 deletions(-) + +commit b5b577f29fd20016fab21b454403510d1098f132 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 08:12:16 2023 -0700 + + [wasm-api] Make buffer_copy_contents return success + + src/hb-wasm-api-buffer.hh | 24 ++++++++++++++++-------- + src/hb-wasm-api-list.hh | 2 +- + src/hb-wasm-api.h | 5 +++-- + src/wasm/graphite/shape.cc | 4 ++-- + src/wasm/sample/c/shape-fallback.cc | 4 +++- + 5 files changed, 25 insertions(+), 14 deletions(-) + +commit 1023a80d395318e444458d0eebccab363133d5ef +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 07:57:04 2023 -0700 + + [wasm] Fix up samples + + src/{wasm/graphite => }/addTable.py | 0 + src/wasm/graphite/Makefile | 17 ++++++++++------- + src/wasm/sample/addTable.py | 16 ---------------- + src/wasm/sample/c/Makefile | 14 ++++++++------ + 4 files changed, 18 insertions(+), 29 deletions(-) + +commit 4ad659a6088d4b86599a3334a9c0f7ceeec8c79e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Feb 25 07:48:35 2023 -0700 + + [wasm] Move wasm-graphite + + src/{wasm-graphite => wasm/graphite}/Makefile | 0 + src/{wasm-graphite => wasm/graphite}/addTable.py | 0 + src/{wasm-graphite => wasm/graphite}/shape.cc | 0 + 3 files changed, 0 insertions(+), 0 deletions(-) + +commit 514a8d58d8820b7b21e2f25933bc9b0d6ea70672 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sat Feb 25 14:42:13 2023 +0000 + + [wasm-api] Add ergonomic Rust interface + + src/wasm/rust/harfbuzz-wasm/Cargo.toml | 8 + + src/wasm/rust/harfbuzz-wasm/src/lib.rs | 364 +++++++++++++++++++++++++++++++++ + 2 files changed, 372 insertions(+) + +commit 74deaa9e7888f1433c053802877911cb643221f9 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Sat Feb 25 13:33:49 2023 +0000 + + [wasm-api] Restructure samples/libraries + + src/{wasm-sample => wasm/sample}/addTable.py | 0 + src/{wasm-sample => wasm/sample/c}/Makefile | 0 + src/{wasm-sample => wasm/sample/c}/shape-fallback.cc | 0 + src/{wasm-sample => wasm/sample/c}/shape-ot.cc | 0 + src/{wasm-sample => wasm/sample/c}/test.ttf | Bin + 5 files changed, 0 insertions(+), 0 deletions(-) + +commit 4bdfaeecefae4136b9ceb451138f8055c7b74d02 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 20:05:35 2023 -0700 + + [wasm-shape] Set glyph flags + + src/hb-wasm-shape.cc | 6 ++++++ + 1 file changed, 6 insertions(+) + +commit 77f0f3c11a5b9e2d5bbf20a6e2840c19822bc134 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 20:01:22 2023 -0700 + + [wasm-api] Make buffer_copy_contents return zero length on mem fail + + src/hb-wasm-api-buffer.hh | 4 ++-- + src/hb-wasm-shape.cc | 15 ++------------- + src/wasm-graphite/shape.cc | 2 ++ + 3 files changed, 6 insertions(+), 15 deletions(-) + +commit 16ecb96922e2f1389cd634a2b908df0a72f8ac1f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 19:53:47 2023 -0700 + + [wasm-api] Return success from buffer_contents_realloc + + src/hb-wasm-api-buffer.hh | 42 ++++++++++++++++++++++++++++-------------- + src/hb-wasm-api-list.hh | 2 +- + src/hb-wasm-api.h | 6 +++--- + src/wasm-graphite/shape.cc | 3 ++- + 4 files changed, 34 insertions(+), 19 deletions(-) + +commit 2568890d15f2a271738a2ef23ca73d173bf120df +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 19:04:39 2023 -0700 + + [wasm-shape] Retry shaping if out-of-memory + + src/hb-wasm-shape.cc | 26 +++++++++++++++++++++++--- + src/wasm-graphite/shape.cc | 4 ++++ + 2 files changed, 27 insertions(+), 3 deletions(-) + +commit cb382e489d656a3d955c15feb99ea887f6d8985a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 17:56:14 2023 -0700 + + [wasm-shape] Cache wasm-shape-plan + + src/hb-wasm-api-buffer.hh | 3 + + src/hb-wasm-shape.cc | 202 +++++++++++++++++++++++++++++++--------------- + 2 files changed, 140 insertions(+), 65 deletions(-) + +commit 73de7d4d05ab2c78e56a4b6156b52ebd2f107c8f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 17:44:33 2023 -0700 + + [wasm-api] Add shape_plan + + src/hb-wasm-api.h | 9 ++++- + src/hb-wasm-shape.cc | 75 ++++++++++++++++++++++++++++++++------- + src/wasm-graphite/shape.cc | 24 ++++++++++--- + src/wasm-sample/shape-fallback.cc | 3 +- + src/wasm-sample/shape-ot.cc | 3 +- + 5 files changed, 93 insertions(+), 21 deletions(-) + +commit a267249930503f99a2517cd35f90556cefdea854 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 17:22:22 2023 -0700 + + [wasm] Typo + + src/harfbuzz.cc | 2 ++ + src/hb-wasm-shape.cc | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +commit 99d2dab30f317058075d5a82c0dfedc898d6912d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 17:04:05 2023 -0700 + + [wasm] Try at autotools build + + configure.ac | 23 +++++++++++++++++++++++ + src/Makefile.am | 10 ++++++++++ + src/Makefile.sources | 15 +++++++++++++-- + src/harfbuzz.cc | 2 -- + 4 files changed, 46 insertions(+), 4 deletions(-) + +commit ed39e0766194194e0fcdd4b45cd428c4c1abd43d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 16:20:06 2023 -0700 + + [wasm] Fix docs + + docs/harfbuzz-sections.txt | 1 + + 1 file changed, 1 insertion(+) + +commit c5af08c0dc7388198019eab3ff16eccd614fce94 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 15:57:10 2023 -0700 + + [wasm] Add to harfbuzz.cc and hb-features + + src/Makefile.am | 9 +++++---- + src/harfbuzz.cc | 2 ++ + src/hb-features.h.in | 7 +++++++ + src/hb-wasm-api.cc | 6 ++++++ + src/meson.build | 3 ++- + 5 files changed, 22 insertions(+), 5 deletions(-) + +commit aa8f9eed63698ae5b40b7f3cca284a5535eaf661 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 15:20:37 2023 -0700 + + [wasm-shape] Use JIT running-modes if available + + Build wasm-micro-runtime with: + + $ cmake . -DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_FAST_JIT=1 + + or: + + $ cmake . -DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_JIT=1 + + The latter needs llvm and is harder to get working. Still trying. + + src/hb-wasm-shape.cc | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +commit 8d960dfe68da0393eafd92a66fa4277b2e1d6e63 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 15:07:40 2023 -0700 + + [wasm-sample] Remove Wasm table from test.ttf again + + Was added by mistake. + + src/wasm-sample/test.ttf | Bin 23468 -> 22116 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +commit 1c6d640e1fbf459b3cf2ef66ad48560e8469f72e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 15:01:36 2023 -0700 + + [wasm-shaper] Whitespace + + src/hb-wasm-shape.cc | 9 +++------ + src/wasm-graphite/Makefile | 2 +- + 2 files changed, 4 insertions(+), 7 deletions(-) + +commit 9f8ad3928afeaf10a0dac8e7d0f3df6bd822c63d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 14:16:11 2023 -0700 + + [wasm-api] Bind shaper features + + src/hb-wasm-api-blob.hh | 2 +- + src/hb-wasm-api-buffer.hh | 6 +++--- + src/hb-wasm-api-font.hh | 6 +++--- + src/hb-wasm-api-list.hh | 2 +- + src/hb-wasm-api-shape.hh | 14 ++++++++++++-- + src/hb-wasm-api.h | 18 +++++++++++++++--- + src/hb-wasm-api.hh | 11 ++++++++++- + src/hb-wasm-shape.cc | 12 +++++++++++- + src/wasm-graphite/shape.cc | 5 ++++- + src/wasm-sample/shape-fallback.cc | 5 ++++- + src/wasm-sample/shape-ot.cc | 7 +++++-- + 11 files changed, 69 insertions(+), 19 deletions(-) + +commit 2327fe9d8a77c930ec5e939060c714ef3008d325 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 13:35:47 2023 -0700 + + [hb-wasm] Remove TODO + + src/hb-wasm-shape.cc | 2 -- + 1 file changed, 2 deletions(-) + +commit b130b2b3317d296f0120acf5f9aab4bab39f2506 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 13:34:16 2023 -0700 + + [graphite] Simplify direction handling + + src/hb-graphite2.cc | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +commit ec3270c7bb162a8e8996192922628502dab9d5a2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 13:31:10 2023 -0700 + + [wasm-graphite] Ensure native direction here too + + Binds buffer_get_script and script_get_horizontal_direction. + + src/hb-wasm-api-buffer.hh | 8 ++++++++ + src/hb-wasm-api-common.hh | 44 ++++++++++++++++++++++++++++++++++++++++++++ + src/hb-wasm-api-list.hh | 3 +++ + src/hb-wasm-api.cc | 1 + + src/hb-wasm-api.h | 11 +++++++++++ + src/meson.build | 1 + + src/wasm-graphite/shape.cc | 21 +++++++++++++++------ + 7 files changed, 83 insertions(+), 6 deletions(-) + +commit cbc71c56bcc5eded3e2393a0b1d2b380fa5944a0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 13:15:11 2023 -0700 + + [graphite] Ensure native direction + + Mirrored characters come out wrong. Oh well. Better than before though. + + src/hb-graphite2.cc | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +commit 39f8703df17cc49b8630597fc250b13ef61870b8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 12:42:22 2023 -0700 + + [wasm-api] Match interface and implementation signatures + + src/hb-wasm-api-blob.hh | 5 ++-- + src/hb-wasm-api-buffer.hh | 65 +++++++++++++++++++++-------------------------- + src/hb-wasm-api-face.hh | 12 ++++----- + src/hb-wasm-api-font.hh | 55 +++++++++++++++++---------------------- + src/hb-wasm-api-shape.hh | 9 +++---- + src/hb-wasm-api.hh | 1 - + 6 files changed, 64 insertions(+), 83 deletions(-) + +commit fea3ffe03147c35180be09b42caee90a96c61a34 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 12:31:32 2023 -0700 + + [wasm-api] Beautify internal API + + src/hb-wasm-api-blob.hh | 2 +- + src/hb-wasm-api-buffer.hh | 16 +++++++------- + src/hb-wasm-api-face.hh | 4 ++-- + src/hb-wasm-api-font.hh | 20 +++++++++--------- + src/hb-wasm-api-shape.hh | 4 ++-- + src/hb-wasm-api.h | 53 +++++++++++++++++++++++++---------------------- + src/hb-wasm-api.hh | 3 ++- + 7 files changed, 53 insertions(+), 49 deletions(-) + +commit fe557e2f21108181496b8f23c92595e0d24d7d20 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 12:20:31 2023 -0700 + + [wasm-api] Bind font_get_glyph_extents + + Untested. + + src/hb-wasm-api-font.hh | 17 +++++++++++++++++ + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 12 ++++++++++++ + 3 files changed, 30 insertions(+) + +commit b3b6e8da86b8bda05311fe9524ac169040ba9cf3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 12:03:53 2023 -0700 + + [wasm-api] Bind buffer_reverse + + src/hb-wasm-api-buffer.hh | 9 +++++++++ + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 3 +++ + 3 files changed, 13 insertions(+) + +commit 863ec70e1240379875fe72baeada79c0d9f79fe4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 12:00:29 2023 -0700 + + [wasm-shape] Add TODO items + + src/hb-wasm-shape.cc | 5 +++++ + 1 file changed, 5 insertions(+) + +commit 1acff90b0337d9a0158c4b8afddaf485a8037b67 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 11:53:47 2023 -0700 + + [wasm-api] Bind font_glyph_to_string + + src/hb-wasm-api-font.hh | 12 ++++++++++++ + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 5 +++++ + src/wasm-graphite/shape.cc | 3 +++ + src/wasm-sample/shape-fallback.cc | 8 +++++++- + 5 files changed, 28 insertions(+), 1 deletion(-) + +commit 7537d48f081f25e3bd78dcacf9218535a1e40c2f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 11:47:17 2023 -0700 + + [wasm] Remove a few lingering hb_ + + src/hb-wasm-api-font.hh | 12 ++++++------ + src/hb-wasm-api.h | 32 ++++++++++++++++---------------- + src/wasm-graphite/shape.cc | 2 +- + 3 files changed, 23 insertions(+), 23 deletions(-) + +commit d7f76f30b0dcfda3f4322b3e240be30b4a141cc7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 11:31:04 2023 -0700 + + [wasm-graphite] Memory cleanup + + src/wasm-graphite/shape.cc | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +commit 5738851b1ca0471b4ac270b89549466202fddf10 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 11:05:59 2023 -0700 + + [wasm-api] Disallow "wasm" shaper in shape_with + + src/hb-wasm-api-shape.hh | 3 +++ + 1 file changed, 3 insertions(+) + +commit 2bde2f66f1391ca4d1c0e38142a6ea0f175173ab +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 11:03:13 2023 -0700 + + [wasm-api] Bind shape_with + + src/hb-wasm-api-list.hh | 3 ++ + src/hb-wasm-api-shape.hh | 50 ++++++++++++++++++++++++++ + src/hb-wasm-api.cc | 1 + + src/hb-wasm-api.h | 8 +++++ + src/meson.build | 1 + + src/wasm-sample/Makefile | 15 ++++---- + src/wasm-sample/{shape.c => shape-fallback.cc} | 6 ++-- + src/wasm-sample/shape-ot.cc | 14 ++++++++ + 8 files changed, 90 insertions(+), 8 deletions(-) + +commit a08dbf41cd20bf36828b58a4e4b448671ee036c1 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 10:13:21 2023 -0700 + + [wasm-api] Bind buffer_reverse_clusters + + src/hb-wasm-api-buffer.hh | 8 ++++++++ + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 2 ++ + src/wasm-graphite/Makefile | 2 +- + src/wasm-graphite/shape.cc | 6 +++--- + 5 files changed, 15 insertions(+), 4 deletions(-) + +commit 0a51ed31b0bba05727210f27548ebd3b55052fe3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 10:07:59 2023 -0700 + + [wasm-api] Bind buffer_get_direction + + src/hb-wasm-api-buffer.hh | 10 ++++++++++ + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 17 +++++++++++++++++ + src/wasm-graphite/shape.cc | 11 ++++++----- + 4 files changed, 34 insertions(+), 5 deletions(-) + +commit a5c844a1de2a6f5c0acda723d4367c41d7a7b90c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 09:52:38 2023 -0700 + + [wasm] Rename macro + + src/hb-wasm-api-blob.hh | 2 +- + src/hb-wasm-api-buffer.hh | 6 +++--- + src/hb-wasm-api-font.hh | 4 ++-- + src/hb-wasm-api.hh | 2 +- + 4 files changed, 7 insertions(+), 7 deletions(-) + +commit 23b58b5667aa6ffe2780860e7a9202149e05eac3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 09:50:34 2023 -0700 + + [wasm-api] Bind font_get_scale + + src/hb-wasm-api-buffer.hh | 2 +- + src/hb-wasm-api-face.hh | 2 +- + src/hb-wasm-api-font.hh | 15 ++++++++++++++- + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 5 +++++ + src/hb-wasm-api.hh | 2 +- + src/wasm-graphite/shape.cc | 6 ++++-- + 7 files changed, 27 insertions(+), 6 deletions(-) + +commit 149199ee26cfac1ff211b2283f8c79b1c7b8cdd0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 09:39:25 2023 -0700 + + [wasm-api] Bind face_get_upem + + src/hb-wasm-api-face.hh | 9 +++++++++ + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 5 +++++ + src/wasm-graphite/shape.cc | 4 ++-- + 4 files changed, 17 insertions(+), 2 deletions(-) + +commit 2d295183b8ed47fa3efa4b83aff1d7781d97ab4f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 09:20:42 2023 -0700 + + [wasm-api] Add buffer_contents_realloc + + src/hb-wasm-api-buffer.hh | 33 ++++++++++++++++++++++++++++++++- + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 4 ++++ + src/wasm-graphite/shape.cc | 3 +-- + 4 files changed, 38 insertions(+), 3 deletions(-) + +commit 07ece174954a3345f05be3c23766119e6554dbf5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Feb 24 08:08:18 2023 -0700 + + [wasm-graphite] Initial code + + src/hb-wasm-api-face.hh | 2 +- + src/hb-wasm-shape.cc | 2 +- + src/wasm-graphite/Makefile | 22 +++++ + src/wasm-graphite/addTable.py | 16 ++++ + src/wasm-graphite/shape.cc | 210 ++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 250 insertions(+), 2 deletions(-) + +commit ae981eec8e33abe7052176733c1ed84cdaeb082f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 21:36:17 2023 -0700 + + [graphite] Remove script handling + + https://github.com/harfbuzz/harfbuzz/issues/3439#issuecomment-1442650148 + + src/hb-graphite2.cc | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +commit 5ab7f7a7d41720bb8ea189df0c5c47db1a22d550 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 16:11:54 2023 -0700 + + [wasm-sample] Make addTable take args + + src/wasm-sample/Makefile | 2 +- + src/wasm-sample/addTable.py | 11 ++++++++--- + src/wasm-sample/test.ttf | Bin 22116 -> 23468 bytes + 3 files changed, 9 insertions(+), 4 deletions(-) + +commit 551528a6e6bef10b3bfbc254c949d7247fba8176 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 16:06:39 2023 -0700 + + [wasm-sample] Remove unused prototype + + src/wasm-sample/shape.c | 2 -- + 1 file changed, 2 deletions(-) + +commit 926f8a326e42b557d2991bddf5e234289677c362 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 15:52:13 2023 -0700 + + [wasm-sample] Actually shape text! + + src/wasm-sample/shape.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit c1dc112121e8ce7e3c75fae0c9e3589176bbc2f8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 15:47:56 2023 -0700 + + [wasm-api] Bind buffer_set_contents + + src/hb-buffer.hh | 7 +++++++ + src/hb-wasm-api-buffer.hh | 34 +++++++++++++++++++++++++++++++--- + src/hb-wasm-api-list.hh | 7 ++++--- + src/hb-wasm-api.h | 4 ++++ + src/wasm-sample/shape.c | 8 +++++++- + 5 files changed, 53 insertions(+), 7 deletions(-) + +commit e0fec1dda01f1060dd474537dcbe5084ef46a88f +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu Feb 23 22:18:22 2023 +0000 + + [wasm-api] Wrap some of hb-font + + src/hb-wasm-api-font.hh | 31 +++++++++++++++++++++++++++++++ + src/hb-wasm-api-list.hh | 5 ++++- + src/hb-wasm-api.h | 13 ++++++++++++- + 3 files changed, 47 insertions(+), 2 deletions(-) + +commit af1f41a43ee7b7bb06e43e7000101019ae24f66a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 15:17:18 2023 -0700 + + [wasm-api] Clear structs in _free() + + src/hb-wasm-api-blob.hh | 3 +++ + src/hb-wasm-api-buffer.hh | 4 ++++ + 2 files changed, 7 insertions(+) + +commit 099a0150e1ba3af96d52629a04fe5def489c4b34 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 15:15:06 2023 -0700 + + [wasm] Add HB_STRUCT_TYPE + + src/hb-wasm-api-blob.hh | 5 ++--- + src/hb-wasm-api-buffer.hh | 5 ++--- + src/hb-wasm-api.hh | 9 +++++++++ + 3 files changed, 13 insertions(+), 6 deletions(-) + +commit 851ef1380aec550e51a4d8055a9c8aef2b57aeeb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 15:06:18 2023 -0700 + + [wasm-api] Add buffer-contents-free + + src/hb-wasm-api-buffer.hh | 13 +++++++++++++ + src/hb-wasm-api-list.hh | 1 + + src/hb-wasm-api.h | 5 +++-- + src/wasm-sample/shape.c | 2 ++ + 4 files changed, 19 insertions(+), 2 deletions(-) + +commit d38f02ab30e3696614c295f88beadb655110599a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 15:03:03 2023 -0700 + + [wasm-api] Make ref types actual pointers on the wasm side + + src/hb-wasm-api-buffer.hh | 2 +- + src/hb-wasm-api-face.hh | 2 +- + src/hb-wasm-api-font.hh | 4 ++-- + src/hb-wasm-api.h | 25 ++++++++++++------------- + src/wasm-sample/shape.c | 4 ++-- + 5 files changed, 18 insertions(+), 19 deletions(-) + +commit cbd5c554fb28d3aa2ac834c28e6d89600e969f62 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 14:54:46 2023 -0700 + + [wasm-api] Add blob_free + + src/hb-wasm-api-blob.hh | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ + src/hb-wasm-api-list.hh | 3 +++ + src/hb-wasm-api.cc | 1 + + src/hb-wasm-api.h | 3 ++- + src/meson.build | 1 + + src/wasm-sample/Makefile | 2 ++ + src/wasm-sample/shape.c | 2 +- + 7 files changed, 59 insertions(+), 2 deletions(-) + +commit 3bec8dca1ca108a9c64af36c768eda58bdec2d95 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 14:35:01 2023 -0700 + + [wasm-sample] Free blob data for now + + src/wasm-sample/shape.c | 4 ++++ + 1 file changed, 4 insertions(+) + +commit d45a13f1018a18a8ea797b717253cbf6f42f9fe8 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 14:28:16 2023 -0700 + + [wasm] Add wasm-sample/ + + src/wasm-sample/Makefile | 18 ++++++++++++++++++ + src/wasm-sample/addTable.py | 11 +++++++++++ + src/wasm-sample/shape.c | 25 +++++++++++++++++++++++++ + src/wasm-sample/test.ttf | Bin 0 -> 22116 bytes + 4 files changed, 54 insertions(+) + +commit 5cecfe865919ff2c72a0409e34265d79f78750d0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 13:58:40 2023 -0700 + + [wasm-api] Bind buffer_copy_contents + + src/hb-wasm-api-buffer.hh | 58 +++++++++++++++++++++++++++++++++++++++++++++++ + src/hb-wasm-api-face.hh | 8 +++---- + src/hb-wasm-api-font.hh | 8 +++---- + src/hb-wasm-api-list.hh | 3 +++ + src/hb-wasm-api.cc | 1 + + src/hb-wasm-api.h | 43 ++++++++++++++++++++++++++++++++++- + src/meson.build | 9 +++++++- + 7 files changed, 120 insertions(+), 10 deletions(-) + +commit 50b22368d04893afa9227ac2c3321ef43c5ae638 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 13:41:41 2023 -0700 + + Revert "Fix function signature" + + This reverts commit d70ebf98b0c696f3c66a20b1243cb347e3e3abc8. + + Nope. A struct return is not returned that way. + + src/hb-wasm-api-list.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 743cd2c46ee0c81958e2c360d56391da679107f6 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu Feb 23 20:35:16 2023 +0000 + + Fix function signature + + src/hb-wasm-api-list.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 3b88bd9742b06e5f0ebd90b39f1fdce6b2129e91 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 13:27:46 2023 -0700 + + [wasm-api] Make ptr_t a pointer on the wasm side + + src/hb-wasm-api.h | 7 ++++--- + src/hb-wasm-api.hh | 4 +++- + 2 files changed, 7 insertions(+), 4 deletions(-) + +commit d7a6671676f9ec5b6b2e8f3a964d1ef9f85f9e3a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 13:16:49 2023 -0700 + + [wasm-api] Add debugprint1/2/3/4 + + src/hb-wasm-api-list.hh | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +commit 108995bbc67aa4a45657127eab6b9f89171355fd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 13:04:38 2023 -0700 + + [wasm-api] Finish face_reference_table + + src/hb-wasm-api-face.hh | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +commit 69b1707d82b498eb88a097c72595a848c3e0007f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 13:00:06 2023 -0700 + + [wasm] Return empty object when ref2obj fails + + src/hb-wasm-api-face.hh | 2 -- + src/hb-wasm-api-font.hh | 3 --- + src/hb-wasm-api.hh | 2 +- + 3 files changed, 1 insertion(+), 6 deletions(-) + +commit e87b1b3ec3a67bf42edac41236e1e70a56ff7072 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 12:23:52 2023 -0700 + + [wasm-api] Try to add face_reference_table + + src/hb-wasm-api-face.hh | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ + src/hb-wasm-api-list.hh | 3 +++ + src/hb-wasm-api.cc | 4 +--- + src/hb-wasm-api.h | 41 ++++++++++++++++++++++++++++++--------- + src/hb-wasm-api.hh | 19 ++++++++++++++++-- + 5 files changed, 104 insertions(+), 14 deletions(-) + +commit e03726d26948b6f9cf2c64df75230c3e15433f44 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 12:00:42 2023 -0700 + + [wasm] Ignore API in the docs + + docs/meson.build | 1 + + 1 file changed, 1 insertion(+) + +commit 747dcf561d710d324b02249806fa0b113178c3d2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 11:53:08 2023 -0700 + + [wasm] Strong typing for object references + + Such that wasm cannot crash us by passing wrong object refs. + + https://github.com/bytecodealliance/wasm-micro-runtime/discussions/1987 + + It still is unsafe if some code in the process other than HarfBuzz + registers refs with wasm-micro-runtime, since wasm_externref_ref2obj() + takes no context variable and looks up refs globally :(. + + Maybe I fix that later by keeping a hash table of ref->obj-type instead. + + src/hb-wasm-api.cc | 11 ++--------- + src/hb-wasm-api.hh | 32 ++++++++++++++++++++++++++++++++ + src/hb-wasm-shape.cc | 41 +++++++++++++++++++++-------------------- + 3 files changed, 55 insertions(+), 29 deletions(-) + +commit 6b72a18c7b981ac0126ea3b585f16449ce3dd25b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 11:06:48 2023 -0700 + + [wasm-api] Rename file + + src/{hb-wasm-font.hh => hb-wasm-api-font.hh} | 0 + src/hb-wasm-api.cc | 2 +- + 2 files changed, 1 insertion(+), 1 deletion(-) + +commit 42d121ae79ce547f1bbe82b9fa771725604546d3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 11:05:19 2023 -0700 + + [wasm] Add hb-wasm-api.cc + + src/hb-wasm-api-list.hh | 1 - + src/hb-wasm-api.cc | 45 +++++++++++++++++++++++++++++++++++++++++++++ + src/hb-wasm-api.hh | 20 -------------------- + src/hb-wasm-shape.cc | 1 + + src/meson.build | 2 +- + 5 files changed, 47 insertions(+), 22 deletions(-) + +commit 980706441b58878cb168543eef70247eccc6abf6 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 10:58:22 2023 -0700 + + [wasm] Add hb-wasm-api-list.hh + + src/hb-wasm-api-list.hh | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ + src/hb-wasm-api.hh | 30 +----------------------- + 2 files changed, 62 insertions(+), 29 deletions(-) + +commit 65efad6b59f6252b2b314e5e16b958bf1b8f4e80 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 10:49:02 2023 -0700 + + [wasm] Make debugprint use debug API + + src/hb-wasm-api.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit bb8a04cbadc16c8195b87e8fd307a2403d2212fa +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 10:37:44 2023 -0700 + + [wasm] Remove the print(returnval) and use it to fail shaper + + docs/wasm-shaper.md | 2 -- + src/hb-wasm-shape.cc | 8 +------- + 2 files changed, 1 insertion(+), 9 deletions(-) + +commit 11fc83c0ba349a6f376a8409971b5698bba39b19 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu Feb 23 17:34:02 2023 +0000 + + [Docs] Pass a C string from Rust to HB + + docs/wasm-shaper.md | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +commit 36dd27bf3f4c35fde6041a91aeb275d4c8624624 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu Feb 23 17:33:50 2023 +0000 + + Just printf, don't take length + + src/hb-wasm-api.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 3bc0ecf28c97a5891a9f2cfb371c41505640beef +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 10:30:35 2023 -0700 + + [wasm-api] Add ref_t + + src/hb-wasm-api.h | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +commit 62f3c7cf67c8b468b49380346a0dbd22c0ad174e +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 10:29:04 2023 -0700 + + [wasm-api] Add macros for ref handling + + src/hb-wasm-api.hh | 13 ++++++++++++- + src/hb-wasm-font.hh | 9 ++++----- + 2 files changed, 16 insertions(+), 6 deletions(-) + +commit 4c8a414a101c9657fda42d2fdb9789407b034c99 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 10:22:12 2023 -0700 + + [wasm-api] Clean up debugprint + + src/hb-wasm-api.hh | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +commit 63904538c8215312489afd0277d78199c88a512a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 10:11:22 2023 -0700 + + [wasm-api] Use i32 instead of externref in API spec + + Oh well... + + src/hb-wasm-api.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit bd28d01a6a1e562dc611e386544075f6caeacf21 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 09:49:46 2023 -0700 + + [wasm-api] Add HB_WASM_INTERFACE + + src/hb-wasm-api.h | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +commit ed1a70c7e8ddf78ea3fd3e6208e683870ff7e893 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu Feb 23 16:41:17 2023 +0000 + + Only export debugprint when HB_DEBUG_WASM + + src/hb-wasm-api.hh | 2 ++ + 1 file changed, 2 insertions(+) + +commit 89c50b0ccb60fc0d73f2b9d65ccbdaebe6fef5b1 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu Feb 23 16:41:04 2023 +0000 + + Fix debugprint format string + + src/hb-wasm-api.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit f0200445d0606019cec868dfc92b1cde5015e6d5 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu Feb 23 16:38:39 2023 +0000 + + Initial WASM docs and Rust example + + docs/wasm-shaper.md | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 116 insertions(+) + +commit fd1f7f46f46cd9dba29ad4975f09f6d4073edae4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 09:25:05 2023 -0700 + + [wasm-api] Implement font_get_face + + src/hb-wasm-api.hh | 7 ++++++- + src/hb-wasm-font.hh | 12 ++++++++++-- + 2 files changed, 16 insertions(+), 3 deletions(-) + +commit 9f4dc2e103290cd7447ab24b2561c52d0f66344b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 09:18:25 2023 -0700 + + [wasm] Bind native API + + src/hb-wasm-api.h | 10 ++++++++-- + src/hb-wasm-api.hh | 27 +++++++++++++++++++++++++++ + src/hb-wasm-font.hh | 3 ++- + src/hb-wasm-shape.cc | 25 ++----------------------- + 4 files changed, 39 insertions(+), 26 deletions(-) + +commit e79a7318c4956fa9a8974812332480ccc5a13991 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 09:03:06 2023 -0700 + + [wasm] Start adding wasm-api + + src/harfbuzz-subset.cc | 1 - + src/harfbuzz.cc | 1 - + src/hb-wasm-api.h | 29 +++++++++++++++++------------ + src/hb-wasm-api.hh | 45 +++++++++++++++++++++++++++++++++++++++++++++ + src/hb-wasm-font.hh | 44 ++++++++++++++++++++++++++++++++++++++++++++ + src/hb-wasm-shape.cc | 4 ++-- + 6 files changed, 108 insertions(+), 16 deletions(-) + +commit 829ba7428476da0616d6b92b88189224acc36cf0 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 08:32:14 2023 -0700 + + [wasm] Add hb-wasm-api.h + + src/hb-wasm-api.h | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 70 insertions(+) + +commit 11c6d46086f5758a71df8e58059e087cd9c1766f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Feb 23 08:16:49 2023 -0700 + + [wasm] Pass font & buff to shape() function + + src/hb-wasm-shape.cc | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +commit 05bf9842128376db20b1c1da91efe0257b23a351 +Author: Simon Cozens <simon@simon-cozens.org> +Date: Thu Feb 23 14:55:49 2023 +0000 + + Add a simple callback native function + + src/hb-wasm-shape.cc | 27 ++++++++++++--------------- + 1 file changed, 12 insertions(+), 15 deletions(-) + +commit bdbc1568bac50371d4b552e179ecfc338f12fd43 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Feb 22 23:30:28 2023 -0700 + + [wasm] Port from c_api to wasm-micro-runtime wasm_runtime API + + src/hb-debug.hh | 4 ++ + src/hb-wasm-shape.cc | 190 +++++++++++++++++++++++++++++++-------------------- + 2 files changed, 119 insertions(+), 75 deletions(-) + +commit db8e51e01b972aaf6d32309ef5aa381964950af4 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Feb 22 13:33:34 2023 -0700 + + [wasm] More boilerplate + + src/hb-wasm-shape.cc | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 67 insertions(+), 2 deletions(-) + +commit fcc8be409b8a8034af54caa0ccd0a91206fdbf6b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Feb 22 12:57:19 2023 -0700 + + [wasm] Add meson build option + + Autotools support missing. + + meson.build | 5 ++++- + meson_options.txt | 2 ++ + src/hb-wasm-shape.cc | 57 +++++++++++++++++++++++++++++++++++++++++++--------- + src/meson.build | 10 ++++++++- + 4 files changed, 63 insertions(+), 11 deletions(-) + +commit 425fc7f3ee257b7aee9a481a04d368c4ccf57c4d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Feb 22 12:19:06 2023 -0700 + + [wasm] Add wasm shaper skeleton + + meson.build | 2 + + src/Makefile.sources | 1 + + src/harfbuzz-subset.cc | 1 + + src/harfbuzz.cc | 1 + + src/hb-shaper-list.hh | 5 +++ + src/hb-wasm-shape.cc | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ + src/meson.build | 1 + + 7 files changed, 111 insertions(+) + commit 04a47932a3844f7e73e3af8b05fb98c8b54fb779 Author: Behdad Esfahbod <behdad@behdad.org> Date: Fri Mar 31 11:44:08 2023 -0600 diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS index ff35843192d..5b82163de8b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS +++ b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS @@ -1,3 +1,45 @@ +Overview of changes leading to 8.0.0 +Sunday, July 9, 2023 +==================================== +- New, experimental, WebAssembly (WASM) shaper, that provides greater + flexibility over OpenType/AAT/Graphite shaping, using WebAssembly embedded + inside the font file. Currently WASM shaper is disabled by default and needs + to be enabled at build time. For details, see: + + https://github.com/harfbuzz/harfbuzz/blob/main/docs/wasm-shaper.md + + For example fonts making use of the WASM shaper, see: + + https://github.com/simoncozens/wasm-examples + +- Improvements to Experimental features introduced in earlier releases: + - Support for subsetting beyond-64k and VarComposites fonts. + - Support for instancing variable fonts with cubic “glyf” table. + +- Many big speed optimizations: + - Up to 89% speedup loading variable fonts for shaping. + - Up to 88% speedup in small subsets of large (eg. CJK) fonts (both TTF and + OTF), essential for Incremental Font Transfer (IFT). + - Over 50% speedup in loading Roboto font for shaping. + - Up to 40% speed up in loading (sanitizing) complex fonts. + - 30% speed up in shaping Gulzar font. + - Over 25% speedup in glyph loading Roboto font. + - 10% speed up loading glyph shapes in VarComposite Hangul font. + - hb-hashmap optimizations & hashing improvements. + +- New macro HB_ALWAYS_INLINE. HarfBuzz now inlines functions more aggressively, + which results in some speedup at the expense of bigger code size. To disable + this feature define the macro to just inline. + +- New API: ++HB_CODEPOINT_INVALID ++hb_ot_layout_get_baseline2() ++hb_ot_layout_get_baseline_with_fallback2() ++hb_ot_layout_get_font_extents() ++hb_ot_layout_get_font_extents2() ++hb_subset_input_set_axis_range() + + Overview of changes leading to 7.3.0 Tuesday, May 9, 2023 ==================================== diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/README b/Build/source/libs/harfbuzz/harfbuzz-src/README index 4202961e04a..87f5755cb0d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/README +++ b/Build/source/libs/harfbuzz/harfbuzz-src/README @@ -5,6 +5,8 @@ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&utm_medium=referral&utm_content=harfbuzz/harfbuzz&utm_campaign=Badge_Grade) [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz) [![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/harfbuzz/harfbuzz/badge)](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz) + # HarfBuzz diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/README.md b/Build/source/libs/harfbuzz/harfbuzz-src/README.md index 4202961e04a..87f5755cb0d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/README.md +++ b/Build/source/libs/harfbuzz/harfbuzz-src/README.md @@ -5,6 +5,8 @@ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&utm_medium=referral&utm_content=harfbuzz/harfbuzz&utm_campaign=Badge_Grade) [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz) [![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/harfbuzz/harfbuzz/badge)](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz) + # HarfBuzz diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/README.python.md b/Build/source/libs/harfbuzz/harfbuzz-src/README.python.md index 7496f045ec9..c945d08a826 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/README.python.md +++ b/Build/source/libs/harfbuzz/harfbuzz-src/README.python.md @@ -9,9 +9,13 @@ sudo apt-get install libgirepository1.0-dev And then run `meson setup` and make sure that `Introspection` is reported enabled in output. +If you are building with Visual Studio, it is recommended that Visual Studio +2019 or later is used for this build, for the best build experience. + Compile and install. -Make sure you have the installation lib dir in `LD_LIBRARY_PATH`, as needed +Make sure you have the installation lib dir in `LD_LIBRARY_PATH` (or the +installation DLL dir in `PATH` for Windows systems), as needed for the linker to find the library. Then make sure you also have `GI_TYPELIB_PATH` pointing to the resulting diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in b/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in index 1ac401a8b10..ab960fbed4f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in +++ b/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in @@ -136,6 +136,12 @@ /* Define to 1 if you have the <usp10.h> header file. */ #undef HAVE_USP10_H +/* Have wasm-micro-runtime library */ +#undef HAVE_WASM + +/* Define to 1 if you have the <wasm_export.h> header file. */ +#undef HAVE_WASM_EXPORT_H + /* Define to 1 if you have the <windows.h> header file. */ #undef HAVE_WINDOWS_H diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac b/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac index a95006baa8a..a2d532ed672 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac +++ b/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [7.3.0], + [8.0.0], [https://github.com/harfbuzz/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) @@ -417,6 +417,28 @@ AM_CONDITIONAL(HAVE_CORETEXT, $have_coretext) dnl =========================================================================== +AC_ARG_WITH(wasm, + [AS_HELP_STRING([--with-wasm=@<:@yes/no/auto@:>@], + [Use the wasm-micro-runtime library @<:@default=no@:>@])],, + [with_wasm=no]) +have_wasm=false +if test "x$with_wasm" = "xyes" -o "x$with_wasm" = "xauto"; then + AC_CHECK_HEADERS(wasm_export.h, have_wasm=true) +fi +if test "x$with_wasm" = "xyes" -a "x$have_wasm" != "xtrue"; then + AC_MSG_ERROR([wasm support requested but not found]) +fi +if $have_wasm; then + WASM_CFLAGS= + WASM_LIBS="-liwasm" + AC_SUBST(WASM_CFLAGS) + AC_SUBST(WASM_LIBS) + AC_DEFINE(HAVE_WASM, 1, [Have wasm-micro-runtime library]) +fi +AM_CONDITIONAL(HAVE_WASM, $have_wasm) + +dnl =========================================================================== + AC_CONFIG_FILES([ Makefile src/Makefile @@ -478,6 +500,7 @@ Platform shapers (not normally needed): DirectWrite: ${have_directwrite} GDI: ${have_gdi} Uniscribe: ${have_uniscribe} + WebAssembly: ${have_wasm} Other features: Documentation: ${enable_gtk_doc} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/meson.build b/Build/source/libs/harfbuzz/harfbuzz-src/meson.build index 512c690362f..284701222cb 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/meson.build +++ b/Build/source/libs/harfbuzz/harfbuzz-src/meson.build @@ -1,6 +1,6 @@ project('harfbuzz', 'c', 'cpp', meson_version: '>= 0.55.0', - version: '7.3.0', + version: '8.0.0', default_options: [ 'cpp_eh=none', # Just to support msvc, we are passing -fno-exceptions also anyway 'cpp_rtti=false', # Just to support msvc, we are passing -fno-rtti also anyway @@ -115,13 +115,15 @@ glib_dep = dependency('glib-2.0', required: get_option('glib')) gobject_dep = dependency('gobject-2.0', required: get_option('gobject')) graphite2_dep = dependency('graphite2', required: get_option('graphite2')) graphite_dep = dependency('graphite2', required: get_option('graphite')) +wasm_dep = cpp.find_library('iwasm', required: get_option('wasm')) +# How to check whether iwasm was built, and hence requires, LLVM? +#llvm_dep = cpp.find_library('LLVM-15', required: get_option('wasm')) if meson.version().version_compare('>=0.60.0') # pkg-config: icu-uc, cmake: ICU but with components icu_dep = dependency('icu-uc', 'ICU', components: 'uc', required: get_option('icu'), - default_options: ['harfbuzz=disabled'], allow_fallback: true) else # painful hack to handle multiple dependencies but also respect options @@ -230,6 +232,11 @@ if chafa_dep.found() conf.set('HAVE_CHAFA', 1) endif +if wasm_dep.found() + conf.set('HAVE_WASM', 1) + conf.set('HB_WASM_MODULE_DIR', '"'+get_option('prefix')+'/'+get_option('libdir')+'/harfbuzz/wasm"') +endif + if graphite2_dep.found() or graphite_dep.found() conf.set('HAVE_GRAPHITE2', 1) endif @@ -419,10 +426,11 @@ build_summary = { }, 'Additional shapers': {'Graphite2': conf.get('HAVE_GRAPHITE2', 0) == 1, + 'WebAssembly (experimental)': conf.get('HAVE_WASM', 0) == 1, }, 'Platform shapers (not normally needed)': {'CoreText': conf.get('HAVE_CORETEXT', 0) == 1, - 'DirectWrite': conf.get('HAVE_DIRECTWRITE', 0) == 1, + 'DirectWrite (experimental)': conf.get('HAVE_DIRECTWRITE', 0) == 1, 'GDI/Uniscribe': (conf.get('HAVE_GDI', 0) == 1) and (conf.get('HAVE_UNISCRIBE', 0) == 1), }, 'Other features': diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt b/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt index 9438202e1bd..ace50eb31f5 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt +++ b/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt @@ -21,6 +21,8 @@ option('directwrite', type: 'feature', value: 'disabled', description: 'Enable DirectWrite shaper backend on Windows (experimental)') option('coretext', type: 'feature', value: 'disabled', description: 'Enable CoreText shaper backend on macOS') +option('wasm', type: 'feature', value: 'disabled', + description: 'Enable WebAssembly shaper backend (experimental)') # Common feature options option('tests', type: 'feature', value: 'enabled', yield: true, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am index 56dc32d9a78..430d44a453b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am @@ -114,6 +114,16 @@ else HB_HAS_CORETEXT_DEF = undef HB_HAS_CORETEXT endif +if HAVE_WASM +HBCFLAGS += $(WASM_CFLAGS) +HBNONPCLIBS += $(WASM_LIBS) +HBSOURCES += $(HB_WASM_sources) +HBHEADERS += $(HB_WASM_headers) +HB_HAS_WASM_DEF = define HB_HAS_WASM 1 +else +HB_HAS_WASM_DEF = undef HB_HAS_WASM +endif + BUILT_SOURCES += \ hb-version.h @@ -273,16 +283,17 @@ DISTCLEANFILES += \ hb-features.h: hb-features.h.in $(top_builddir)/config.status $(AM_V_GEN) $(SED) \ -e 's/mesondefine HB_HAS_CAIRO/$(HB_HAS_CAIRO_DEF)/' \ + -e 's/mesondefine HB_HAS_CORETEXT/$(HB_HAS_CORETEXT_DEF)/' \ + -e 's/mesondefine HB_HAS_DIRECTWRITE/$(HB_HAS_DIRECTWRITE_DEF)/' \ -e 's/mesondefine HB_HAS_FREETYPE/$(HB_HAS_FREETYPE_DEF)/' \ -e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \ -e 's/mesondefine HB_HAS_GDI/$(HB_HAS_GDI_DEF)/' \ - -e 's/mesondefine HB_HAS_GRAPHITE/$(HB_HAS_GRAPHITE_DEF)/' \ -e 's/mesondefine HB_HAS_GLIB/$(HB_HAS_GLIB_DEF)/' \ -e 's/mesondefine HB_HAS_GOBJECT/$(HB_HAS_GOBJECT_DEF)/' \ - -e 's/mesondefine HB_HAS_UNISCRIBE/$(HB_HAS_UNISCRIBE_DEF)/' \ - -e 's/mesondefine HB_HAS_DIRECTWRITE/$(HB_HAS_DIRECTWRITE_DEF)/' \ - -e 's/mesondefine HB_HAS_CORETEXT/$(HB_HAS_CORETEXT_DEF)/' \ + -e 's/mesondefine HB_HAS_GRAPHITE/$(HB_HAS_GRAPHITE_DEF)/' \ -e 's/mesondefine HB_HAS_ICU/$(HB_HAS_ICU_DEF)/' \ + -e 's/mesondefine HB_HAS_UNISCRIBE/$(HB_HAS_UNISCRIBE_DEF)/' \ + -e 's/mesondefine HB_HAS_WASM/$(HB_HAS_WASM_DEF)/' \ "$<" > "$@" || ($(RM) "$@"; false) @@ -445,6 +456,8 @@ COMPILED_TESTS = \ test-vector \ test-repacker \ test-classdef-graph \ + test-instancer-solver \ + test-tuple-varstore \ $(NULL) COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS) @@ -515,6 +528,14 @@ test_vector_SOURCES = test-vector.cc hb-static.cc test_vector_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) test_vector_LDADD = $(COMPILED_TESTS_LDADD) +test_instancer_solver_SOURCES = test-subset-instancer-solver.cc hb-subset-instancer-solver.cc hb-static.cc +test_instancer_solver_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) +test_instancer_solver_LDADD = $(COMPILED_TESTS_LDADD) + +test_tuple_varstore_SOURCES = test-tuple-varstore.cc hb-subset-instancer-solver.cc hb-static.cc +test_tuple_varstore_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) +test_tuple_varstore_LDADD = $(COMPILED_TESTS_LDADD) + dist_check_SCRIPTS = \ check-c-linkage-decls.py \ check-externs.py \ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources index 85537a58a4b..fbbff5325e2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources @@ -338,10 +338,22 @@ HB_GDI_headers = hb-gdi.h HB_UNISCRIBE_sources = hb-uniscribe.cc HB_UNISCRIBE_headers = hb-uniscribe.h -# Sources for libharfbuzz-gobject and libharfbuzz-icu HB_ICU_sources = hb-icu.cc HB_ICU_headers = hb-icu.h +HB_WASM_sources = \ + hb-wasm-api.cc \ + hb-wasm-api.hh \ + hb-wasm-api-blob.hh \ + hb-wasm-api-buffer.hh \ + hb-wasm-api-common.hh \ + hb-wasm-api-face.hh \ + hb-wasm-api-font.hh \ + hb-wasm-api-shape.hh \ + hb-wasm-shape.cc \ + $(NULL) +HB_WASM_headers = hb-wasm-api.h + # Sources for libharfbuzz-subset HB_SUBSET_sources = \ hb-number.cc \ @@ -353,11 +365,10 @@ HB_SUBSET_sources = \ hb-subset-cff-common.cc \ hb-subset-cff-common.hh \ hb-subset-cff1.cc \ - hb-subset-cff1.hh \ hb-subset-cff2.cc \ - hb-subset-cff2.hh \ hb-subset-input.cc \ hb-subset-input.hh \ + hb-subset-instancer-solver.hh \ hb-subset-instancer-solver.cc \ hb-subset-accelerator.hh \ hb-subset-plan.cc \ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh index b125052344f..457039bfc6c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/CBDT/CBDT.hh @@ -397,7 +397,6 @@ struct IndexSubtableRecord TRACE_SERIALIZE (this); auto *subtable = c->serializer->start_embed<IndexSubtable> (); - if (unlikely (!subtable)) return_trace (false); if (unlikely (!c->serializer->extend_min (subtable))) return_trace (false); auto *old_subtable = get_subtable (base); @@ -545,7 +544,8 @@ struct IndexSubtableArray const IndexSubtableRecord*>> *lookup /* OUT */) const { bool start_glyph_is_set = false; - for (hb_codepoint_t new_gid = 0; new_gid < c->plan->num_output_glyphs (); new_gid++) + unsigned num_glyphs = c->plan->num_output_glyphs (); + for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++) { hb_codepoint_t old_gid; if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) continue; @@ -576,9 +576,6 @@ struct IndexSubtableArray { TRACE_SUBSET (this); - auto *dst = c->serializer->start_embed<IndexSubtableArray> (); - if (unlikely (!dst)) return_trace (false); - hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> lookup; build_lookup (c, bitmap_size_context, &lookup); if (unlikely (!c->serializer->propagate_error (lookup))) @@ -993,12 +990,10 @@ CBLC::subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - auto *cblc_prime = c->serializer->start_embed<CBLC> (); - // Use a vector as a secondary buffer as the tables need to be built in parallel. hb_vector_t<char> cbdt_prime; - if (unlikely (!cblc_prime)) return_trace (false); + auto *cblc_prime = c->serializer->start_embed<CBLC> (); if (unlikely (!c->serializer->extend_min (cblc_prime))) return_trace (false); cblc_prime->version = version; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh index 2a479842941..6591bb4380a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/COLR/COLR.hh @@ -409,7 +409,6 @@ struct ColorLine { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); @@ -1434,6 +1433,7 @@ struct PaintComposite { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + c->check_ops (this->min_size) && // PainComposite can get exponential src.sanitize (c, this) && backdrop.sanitize (c, this)); } @@ -2167,7 +2167,7 @@ struct COLR if (version == 0 && (!base_it || !layer_it)) return_trace (false); - COLR *colr_prime = c->serializer->start_embed<COLR> (); + auto *colr_prime = c->serializer->start_embed<COLR> (); if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false); if (version == 0) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/sbix/sbix.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/sbix/sbix.hh index 46ad3fd58e1..ce8693cfb16 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/sbix/sbix.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Color/sbix/sbix.hh @@ -48,7 +48,6 @@ struct SBIXGlyph { TRACE_SERIALIZE (this); SBIXGlyph* new_glyph = c->start_embed<SBIXGlyph> (); - if (unlikely (!new_glyph)) return_trace (nullptr); if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr); new_glyph->xOffset = xOffset; @@ -143,7 +142,6 @@ struct SBIXStrike unsigned int num_output_glyphs = c->plan->num_output_glyphs (); auto* out = c->serializer->start_embed<SBIXStrike> (); - if (unlikely (!out)) return_trace (false); auto snap = c->serializer->snapshot (); if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false); out->ppem = ppem; @@ -388,7 +386,6 @@ struct sbix TRACE_SERIALIZE (this); auto *out = c->serializer->start_embed<Array32OfOffset32To<SBIXStrike>> (); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); hb_vector_t<Offset32To<SBIXStrike>*> new_strikes; @@ -423,8 +420,6 @@ struct sbix { TRACE_SUBSET (this); - sbix *sbix_prime = c->serializer->start_embed<sbix> (); - if (unlikely (!sbix_prime)) return_trace (false); if (unlikely (!c->serializer->embed (this->version))) return_trace (false); if (unlikely (!c->serializer->embed (this->flags))) return_trace (false); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh index 9ca88f788a9..25056c9bc35 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/Coverage.hh @@ -57,6 +57,9 @@ struct Coverage public: DEFINE_SIZE_UNION (2, format); +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh index 5d68e3d15e7..3f598d40efc 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat1.hh @@ -79,7 +79,7 @@ struct CoverageFormat1_3 { if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2) { - for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) return true; return false; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh index fa501d659d5..9c875423568 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/Common/CoverageFormat2.hh @@ -122,7 +122,7 @@ struct CoverageFormat2_4 { if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) { - for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) return true; return false; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh index c1ff7961996..d995ba0d4c1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GDEF/GDEF.hh @@ -49,8 +49,6 @@ struct AttachPoint : Array16Of<HBUINT16> { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); - return_trace (out->serialize (c->serializer, + iter ())); } }; @@ -202,7 +200,6 @@ struct CaretValueFormat3 { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); if (!c->serializer->embed (caretValueFormat)) return_trace (false); if (!c->serializer->embed (coordinate)) return_trace (false); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorFormat3.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorFormat3.hh index e7e3c5c6d1e..8684f60ca5d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorFormat3.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorFormat3.hh @@ -25,7 +25,9 @@ struct AnchorFormat3 bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); + if (unlikely (!c->check_struct (this))) return_trace (false); + + return_trace (xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); } void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, @@ -35,9 +37,9 @@ struct AnchorFormat3 *x = font->em_fscale_x (xCoordinate); *y = font->em_fscale_y (yCoordinate); - if (font->x_ppem || font->num_coords) + if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this)) *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache); - if (font->y_ppem || font->num_coords) + if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this)) *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache); } @@ -45,7 +47,6 @@ struct AnchorFormat3 { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->embed (format))) return_trace (false); if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false); if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh index c442efa1eaa..bd9b1897397 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/AnchorMatrix.hh @@ -21,18 +21,25 @@ struct AnchorMatrix if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false); unsigned int count = rows * cols; if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false); + + if (c->lazy_some_gpos) + return_trace (true); + for (unsigned int i = 0; i < count; i++) if (!matrixZ[i].sanitize (c, this)) return_trace (false); return_trace (true); } - const Anchor& get_anchor (unsigned int row, unsigned int col, - unsigned int cols, bool *found) const + const Anchor& get_anchor (hb_ot_apply_context_t *c, + unsigned int row, unsigned int col, + unsigned int cols, bool *found) const { *found = false; if (unlikely (row >= rows || col >= cols)) return Null (Anchor); - *found = !matrixZ[row * cols + col].is_null (); - return this+matrixZ[row * cols + col]; + auto &offset = matrixZ[row * cols + col]; + if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor); + *found = !offset.is_null (); + return this+offset; } template <typename Iterator, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/CursivePosFormat1.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/CursivePosFormat1.hh index b8773ba0aaa..a459124dfea 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/CursivePosFormat1.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/CursivePosFormat1.hh @@ -278,7 +278,6 @@ struct CursivePosFormat1 const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); auto it = + hb_zip (this+coverage, entryExitRecord) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkArray.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkArray.hh index ff43ffb8c57..34e2ab8f6e3 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkArray.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/MarkArray.hh @@ -28,7 +28,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove const Anchor& mark_anchor = this + record.markAnchor; bool found; - const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found); + const Anchor& glyph_anchor = anchors.get_anchor (c, glyph_index, mark_class, class_count, &found); /* If this subtable doesn't have an anchor for this base and this class, * return false such that the subsequent subtables have a chance at it. */ if (unlikely (!found)) return_trace (false); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh index 31329dfcb59..05e6c0fa548 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -54,8 +54,9 @@ struct PairPosFormat2_4 return_trace (c->check_range ((const void *) values, count, stride) && - valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && - valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); + (c->lazy_some_gpos || + (valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && + valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)))); } bool intersects (const hb_set_t *glyphs) const @@ -298,11 +299,13 @@ struct PairPosFormat2_4 out->valueFormat2 = out->valueFormat2.drop_device_table_flags (); } + unsigned total_len = len1 + len2; + hb_vector_t<unsigned> class2_idxs (+ hb_range ((unsigned) class2Count) | hb_filter (klass2_map)); for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) { - for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) + for (unsigned class2_idx : class2_idxs) { - unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); + unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * total_len; valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], &c->plan->layout_variation_idx_delta_map); valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &c->plan->layout_variation_idx_delta_map); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairSet.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairSet.hh index 9faff49909a..db301bb8160 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairSet.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/PairSet.hh @@ -52,8 +52,9 @@ struct PairSet unsigned int count = len; const PairValueRecord *record = &firstPairValueRecord; - return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) && - closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)); + return_trace (c->lazy_some_gpos || + (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) && + closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride))); } bool intersects (const hb_set_t *glyphs, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh index 623e4e66b20..dff1f7316d5 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat1.hh @@ -90,6 +90,7 @@ struct SinglePosFormat1 bool position_single (hb_font_t *font, + hb_blob_t *table_blob, hb_direction_t direction, hb_codepoint_t gid, hb_glyph_position_t &pos) const @@ -100,7 +101,7 @@ struct SinglePosFormat1 /* This is ugly... */ hb_buffer_t buffer; buffer.props.direction = direction; - OT::hb_ot_apply_context_t c (1, font, &buffer); + OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob); valueFormat.apply_value (&c, this, values, pos); return true; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh index e8f2d7c2c6e..168ad3bb8c8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/SinglePosFormat2.hh @@ -94,6 +94,7 @@ struct SinglePosFormat2 bool position_single (hb_font_t *font, + hb_blob_t *table_blob, hb_direction_t direction, hb_codepoint_t gid, hb_glyph_position_t &pos) const @@ -105,7 +106,7 @@ struct SinglePosFormat2 /* This is ugly... */ hb_buffer_t buffer; buffer.props.direction = direction; - OT::hb_ot_apply_context_t c (1, font, &buffer); + OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob); valueFormat.apply_value (&c, this, &values[index * valueFormat.get_len ()], diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/ValueFormat.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/ValueFormat.hh index 1aa451abcc8..461a13d4b70 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/ValueFormat.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GPOS/ValueFormat.hh @@ -118,21 +118,25 @@ struct ValueFormat : HBUINT16 auto *cache = c->var_store_cache; /* pixel -> fractional pixel */ - if (format & xPlaDevice) { - if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store, cache); + if (format & xPlaDevice) + { + if (use_x_device) glyph_pos.x_offset += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache); values++; } - if (format & yPlaDevice) { - if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store, cache); + if (format & yPlaDevice) + { + if (use_y_device) glyph_pos.y_offset += get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache); values++; } - if (format & xAdvDevice) { - if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache); + if (format & xAdvDevice) + { + if (horizontal && use_x_device) glyph_pos.x_advance += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache); values++; } - if (format & yAdvDevice) { + if (format & yAdvDevice) + { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache); + if (!horizontal && use_y_device) glyph_pos.y_advance -= get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache); values++; } return ret; @@ -174,6 +178,9 @@ struct ValueFormat : HBUINT16 if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++); if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++); + if (!has_device ()) + return; + if (format & xPlaDevice) { add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map); @@ -233,14 +240,12 @@ struct ValueFormat : HBUINT16 if (format & ValueFormat::xAdvDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } if (format & ValueFormat::yAdvDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } @@ -277,11 +282,23 @@ struct ValueFormat : HBUINT16 { return *static_cast<Offset16To<Device> *> (value); } - static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr) + static inline const Offset16To<Device>& get_device (const Value* value) { - if (worked) *worked |= bool (*value); return *static_cast<const Offset16To<Device> *> (value); } + static inline const Device& get_device (const Value* value, + bool *worked, + const void *base, + hb_sanitize_context_t &c) + { + if (worked) *worked |= bool (*value); + auto &offset = *static_cast<const Offset16To<Device> *> (value); + + if (unlikely (!offset.sanitize (&c, base))) + return Null(Device); + + return base + offset; + } void add_delta_to_value (HBINT16 *value, const void *base, @@ -340,25 +357,26 @@ struct ValueFormat : HBUINT16 bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const { TRACE_SANITIZE (this); - return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values))); + + if (unlikely (!c->check_range (values, get_size ()))) return_trace (false); + + if (c->lazy_some_gpos) + return_trace (true); + + return_trace (!has_device () || sanitize_value_devices (c, base, values)); } bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const { TRACE_SANITIZE (this); - unsigned int len = get_len (); + unsigned size = get_size (); - if (!c->check_range (values, count, get_size ())) return_trace (false); + if (!c->check_range (values, count, size)) return_trace (false); - if (!has_device ()) return_trace (true); + if (c->lazy_some_gpos) + return_trace (true); - for (unsigned int i = 0; i < count; i++) { - if (!sanitize_value_devices (c, base, values)) - return_trace (false); - values += len; - } - - return_trace (true); + return_trace (sanitize_values_stride_unsafe (c, base, values, count, size)); } /* Just sanitize referenced Device tables. Doesn't check the values themselves. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Common.hh index 968bba0481a..b849494d88a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Common.hh @@ -8,8 +8,6 @@ namespace OT { namespace Layout { namespace GSUB_impl { -typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t; - template<typename Iterator> static void SingleSubst_serialize (hb_serialize_context_t *c, Iterator it); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Ligature.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Ligature.hh index 8674a52fb52..db3fc55f773 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Ligature.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Ligature.hh @@ -13,12 +13,13 @@ struct Ligature public: typename Types::HBGlyphID ligGlyph; /* GlyphID of ligature to substitute */ - HeadlessArrayOf<typename Types::HBGlyphID> + HeadlessArray16Of<typename Types::HBGlyphID> component; /* Array of component GlyphIDs--start * with the second component--ordered * in writing direction */ public: DEFINE_SIZE_ARRAY (Types::size + 2, component); + DEFINE_SIZE_MAX (65536 * Types::HBGlyphID::static_size); bool sanitize (hb_sanitize_context_t *c) const { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh index 2c2e1aa44fd..916fa281b32 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh @@ -191,7 +191,6 @@ struct ReverseChainSingleSubstFormat1 TRACE_SERIALIZE (this); auto *out = c->serializer->start_embed (this); - if (unlikely (!c->serializer->check_success (out))) return_trace (false); if (unlikely (!c->serializer->embed (this->format))) return_trace (false); if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Sequence.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Sequence.hh index ae3292f3295..a26cf8c6a65 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Sequence.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/Layout/GSUB/Sequence.hh @@ -53,7 +53,7 @@ struct Sequence if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) { c->buffer->message (c->font, - "replaced glyph at %u (multiple subtitution)", + "replaced glyph at %u (multiple substitution)", c->buffer->idx - 1u); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh index d81fadf7c88..60858a5a581 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/CompositeGlyph.hh @@ -90,24 +90,36 @@ struct CompositeGlyphRecord static void transform (const float (&matrix)[4], hb_array_t<contour_point_t> points) { - auto arrayZ = points.arrayZ; - unsigned count = points.length; - if (matrix[0] != 1.f || matrix[1] != 0.f || matrix[2] != 0.f || matrix[3] != 1.f) - for (unsigned i = 0; i < count; i++) - arrayZ[i].transform (matrix); + for (auto &point : points) + point.transform (matrix); } static void translate (const contour_point_t &trans, hb_array_t<contour_point_t> points) { - auto arrayZ = points.arrayZ; - unsigned count = points.length; - - if (trans.x != 0.f || trans.y != 0.f) - for (unsigned i = 0; i < count; i++) - arrayZ[i].translate (trans); + if (HB_OPTIMIZE_SIZE_VAL) + { + if (trans.x != 0.f || trans.y != 0.f) + for (auto &point : points) + point.translate (trans); + } + else + { + if (trans.x != 0.f && trans.y != 0.f) + for (auto &point : points) + point.translate (trans); + else + { + if (trans.x != 0.f) + for (auto &point : points) + point.x += trans.x; + else if (trans.y != 0.f) + for (auto &point : points) + point.y += trans.y; + } + } } void transform_points (hb_array_t<contour_point_t> points, @@ -131,9 +143,8 @@ struct CompositeGlyphRecord float matrix[4]; contour_point_t trans; get_transformation (matrix, trans); - points.alloc (points.length + 4); // For phantom points - if (unlikely (!points.resize (points.length + 1))) return false; - points.arrayZ[points.length - 1] = trans; + if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points + points.push (trans); return true; } @@ -382,7 +393,7 @@ struct CompositeGlyph { /* last 4 points in points_with_deltas are phantom points and should not be included */ if (i >= points_with_deltas.length - 4) { - free (o); + hb_free (o); return false; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh index 2bd5fe8206d..2611c1e21dd 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/Glyph.hh @@ -114,8 +114,8 @@ struct Glyph if (type != EMPTY) { - plan->bounds_width_map.set (new_gid, xMax - xMin); - plan->bounds_height_map.set (new_gid, yMax - yMin); + plan->bounds_width_vec[new_gid] = xMax - xMin; + plan->bounds_height_vec[new_gid] = yMax - yMin; } unsigned len = all_points.length; @@ -124,10 +124,12 @@ struct Glyph float topSideY = all_points[len - 2].y; float bottomSideY = all_points[len - 1].y; + uint32_t hash = hb_hash (new_gid); + signed hori_aw = roundf (rightSideX - leftSideX); if (hori_aw < 0) hori_aw = 0; int lsb = roundf (xMin - leftSideX); - plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb)); + plan->hmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) hori_aw, lsb)); //flag value should be computed using non-empty glyphs if (type != EMPTY && lsb != xMin) plan->head_maxp_info.allXMinIsLsb = false; @@ -135,7 +137,7 @@ struct Glyph signed vert_aw = roundf (topSideY - bottomSideY); if (vert_aw < 0) vert_aw = 0; int tsb = roundf (topSideY - yMax); - plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb)); + plan->vmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) vert_aw, tsb)); } bool compile_header_bytes (const hb_subset_plan_t *plan, @@ -369,9 +371,11 @@ struct Glyph } #ifndef HB_NO_VAR - glyf_accelerator.gvar->apply_deltas_to_points (gid, - coords, - points.as_array ().sub_array (old_length)); + if (coords) + glyf_accelerator.gvar->apply_deltas_to_points (gid, + coords, + points.as_array ().sub_array (old_length), + phantom_only && type == SIMPLE); #endif // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it @@ -379,7 +383,7 @@ struct Glyph if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE) { if (unlikely (!points_with_deltas->resize (points.length))) return false; - points_with_deltas->copy_vector (points); + *points_with_deltas = points; } switch (type) { @@ -417,14 +421,17 @@ struct Glyph for (unsigned int i = 0; i < PHANTOM_COUNT; i++) phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; - float matrix[4]; - contour_point_t default_trans; - item.get_transformation (matrix, default_trans); + if (comp_points) // Empty in case of phantom_only + { + float matrix[4]; + contour_point_t default_trans; + item.get_transformation (matrix, default_trans); - /* Apply component transformation & translation (with deltas applied) */ - item.transform_points (comp_points, matrix, points[comp_index]); + /* Apply component transformation & translation (with deltas applied) */ + item.transform_points (comp_points, matrix, points[comp_index]); + } - if (item.is_anchored ()) + if (item.is_anchored () && !phantom_only) { unsigned int p1, p2; item.get_anchor_points (p1, p2); @@ -466,7 +473,10 @@ struct Glyph assert (record_points.length == item_num_points); auto component_coords = coords; - if (item.is_reset_unspecified_axes ()) + /* Copying coords is expensive; so we have put an arbitrary + * limit on the max number of coords for now. */ + if (item.is_reset_unspecified_axes () || + coords.length > HB_GLYF_VAR_COMPOSITE_MAX_AXES) component_coords = hb_array<int> (); coord_setter_t coord_setter (component_coords); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh index 555bcee346e..1d42cc29250 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SimpleGlyph.hh @@ -154,10 +154,9 @@ struct SimpleGlyph { int v = 0; - unsigned count = points_.length; - for (unsigned i = 0; i < count; i++) + for (auto &point : points_) { - unsigned flag = points_.arrayZ[i].flag; + unsigned flag = point.flag; if (flag & short_flag) { if (unlikely (p + 1 > end)) return false; @@ -175,7 +174,7 @@ struct SimpleGlyph p += HBINT16::static_size; } } - points_.arrayZ[i].*m = v; + point.*m = v; } return true; } @@ -192,9 +191,10 @@ struct SimpleGlyph unsigned old_length = points.length; points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy - if (!points.resize (points.length + num_points, false)) return false; + if (unlikely (!points.resize (points.length + num_points, false))) return false; auto points_ = points.as_array ().sub_array (old_length); - hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points); + if (!phantom_only) + hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points); if (phantom_only) return true; for (int i = 0; i < num_contours; i++) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SubsetGlyph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SubsetGlyph.hh index 26dc374eab6..8099d3c1269 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SubsetGlyph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/SubsetGlyph.hh @@ -22,7 +22,7 @@ struct SubsetGlyph bool serialize (hb_serialize_context_t *c, bool use_short_loca, - const hb_subset_plan_t *plan) + const hb_subset_plan_t *plan) const { TRACE_SERIALIZE (this); @@ -40,7 +40,7 @@ struct SubsetGlyph pad = 0; while (pad_length > 0) { - c->embed (pad); + (void) c->embed (pad); pad_length--; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/VarCompositeGlyph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/VarCompositeGlyph.hh index 6dc6fd9ded1..50cbece3cad 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/VarCompositeGlyph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/VarCompositeGlyph.hh @@ -214,7 +214,7 @@ struct VarCompositeGlyphRecord points.alloc (points.length + num_points + 4); // For phantom points if (unlikely (!points.resize (points.length + num_points, false))) return false; contour_point_t *rec_points = points.arrayZ + (points.length - num_points); - memset (rec_points, 0, num_points * sizeof (rec_points[0])); + hb_memset (rec_points, 0, num_points * sizeof (rec_points[0])); unsigned fl = flags; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/coord-setter.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/coord-setter.hh index df64ed5af7d..cf05929362f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/coord-setter.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/coord-setter.hh @@ -16,6 +16,8 @@ struct coord_setter_t int& operator [] (unsigned idx) { + if (unlikely (idx >= HB_GLYF_VAR_COMPOSITE_MAX_AXES)) + return Crap(int); if (coords.length < idx + 1) coords.resize (idx + 1); return coords[idx]; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf-helpers.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf-helpers.hh index 30106b2b98b..d0a5a132f05 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf-helpers.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf-helpers.hh @@ -12,24 +12,44 @@ namespace OT { namespace glyf_impl { -template<typename IteratorIn, typename IteratorOut, - hb_requires (hb_is_source_of (IteratorIn, unsigned int)), - hb_requires (hb_is_sink_of (IteratorOut, unsigned))> +template<typename IteratorIn, typename TypeOut, + hb_requires (hb_is_source_of (IteratorIn, unsigned int))> static void -_write_loca (IteratorIn&& it, bool short_offsets, IteratorOut&& dest) +_write_loca (IteratorIn&& it, + const hb_sorted_vector_t<hb_codepoint_pair_t> new_to_old_gid_list, + bool short_offsets, + TypeOut *dest, + unsigned num_offsets) { unsigned right_shift = short_offsets ? 1 : 0; - unsigned int offset = 0; - dest << 0; - + it - | hb_map ([=, &offset] (unsigned int padded_size) - { - offset += padded_size; - DEBUG_MSG (SUBSET, nullptr, "loca entry offset %u", offset); - return offset >> right_shift; - }) - | hb_sink (dest) - ; + unsigned offset = 0; + TypeOut value; + value = 0; + *dest++ = value; + hb_codepoint_t last = 0; + for (auto _ : new_to_old_gid_list) + { + hb_codepoint_t gid = _.first; + for (; last < gid; last++) + { + DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset); + *dest++ = value; + } + + unsigned padded_size = *it++; + offset += padded_size; + DEBUG_MSG (SUBSET, nullptr, "loca entry gid %u offset %u padded-size %u", gid, offset, padded_size); + value = offset >> right_shift; + *dest++ = value; + + last++; // Skip over gid + } + unsigned num_glyphs = num_offsets - 1; + for (; last < num_glyphs; last++) + { + DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset); + *dest++ = value; + } } static bool @@ -67,11 +87,14 @@ _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca) template<typename Iterator, hb_requires (hb_is_source_of (Iterator, unsigned int))> static bool -_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca) +_add_loca_and_head (hb_subset_context_t *c, + Iterator padded_offsets, + bool use_short_loca) { - unsigned num_offsets = padded_offsets.len () + 1; + unsigned num_offsets = c->plan->num_output_glyphs () + 1; unsigned entry_size = use_short_loca ? 2 : 4; - char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets); + + char *loca_prime_data = (char *) hb_malloc (entry_size * num_offsets); if (unlikely (!loca_prime_data)) return false; @@ -79,9 +102,9 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s entry_size, num_offsets, entry_size * num_offsets); if (use_short_loca) - _write_loca (padded_offsets, true, hb_array ((HBUINT16 *) loca_prime_data, num_offsets)); + _write_loca (padded_offsets, c->plan->new_to_old_gid_list, true, (HBUINT16 *) loca_prime_data, num_offsets); else - _write_loca (padded_offsets, false, hb_array ((HBUINT32 *) loca_prime_data, num_offsets)); + _write_loca (padded_offsets, c->plan->new_to_old_gid_list, false, (HBUINT32 *) loca_prime_data, num_offsets); hb_blob_t *loca_blob = hb_blob_create (loca_prime_data, entry_size * num_offsets, @@ -89,8 +112,8 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s loca_prime_data, hb_free); - bool result = plan->add_table (HB_OT_TAG_loca, loca_blob) - && _add_head_and_set_loca_version (plan, use_short_loca); + bool result = c->plan->add_table (HB_OT_TAG_loca, loca_blob) + && _add_head_and_set_loca_version (c->plan, use_short_loca); hb_blob_destroy (loca_blob); return result; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh index dd08dda6ee1..6300cf4be0c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/glyf.hh @@ -85,75 +85,72 @@ struct glyf return_trace (false); } - glyf *glyf_prime = c->serializer->start_embed <glyf> (); - if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false); - hb_font_t *font = nullptr; if (c->plan->normalized_coords) { font = _create_font_for_instancing (c->plan); - if (unlikely (!font)) return false; + if (unlikely (!font)) + return_trace (false); } hb_vector_t<unsigned> padded_offsets; - unsigned num_glyphs = c->plan->num_output_glyphs (); - if (unlikely (!padded_offsets.resize (num_glyphs))) - { - hb_font_destroy (font); - return false; - } + if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true))) + return_trace (false); hb_vector_t<glyf_impl::SubsetGlyph> glyphs; if (!_populate_subset_glyphs (c->plan, font, glyphs)) { hb_font_destroy (font); - return false; + return_trace (false); } if (font) hb_font_destroy (font); unsigned max_offset = 0; - for (unsigned i = 0; i < num_glyphs; i++) + for (auto &g : glyphs) { - padded_offsets[i] = glyphs[i].padded_size (); - max_offset += padded_offsets[i]; + unsigned size = g.padded_size (); + padded_offsets.push (size); + max_offset += size; } bool use_short_loca = false; if (likely (!c->plan->force_long_loca)) use_short_loca = max_offset < 0x1FFFF; - if (!use_short_loca) { - for (unsigned i = 0; i < num_glyphs; i++) - padded_offsets[i] = glyphs[i].length (); + if (!use_short_loca) + { + padded_offsets.resize (0); + for (auto &g : glyphs) + padded_offsets.push (g.length ()); } - bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan); + auto *glyf_prime = c->serializer->start_embed <glyf> (); + bool result = glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan); if (c->plan->normalized_coords && !c->plan->pinned_at_default) _free_compiled_subset_glyphs (glyphs); - if (!result) return false; - - if (unlikely (c->serializer->in_error ())) return_trace (false); + if (unlikely (!c->serializer->check_success (glyf_impl::_add_loca_and_head (c, + padded_offsets.iter (), + use_short_loca)))) + return_trace (false); - return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan, - padded_offsets.iter (), - use_short_loca))); + return result; } bool _populate_subset_glyphs (const hb_subset_plan_t *plan, hb_font_t *font, - hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const; + hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const; hb_font_t * _create_font_for_instancing (const hb_subset_plan_t *plan) const; void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs) const { - for (unsigned i = 0; i < glyphs.length; i++) - glyphs[i].free_compiled_bytes (); + for (auto &g : glyphs) + g.free_compiled_bytes (); } protected: @@ -222,13 +219,14 @@ struct glyf_accelerator_t if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only))) return false; + unsigned count = all_points.length; + assert (count >= glyf_impl::PHANTOM_COUNT); + count -= glyf_impl::PHANTOM_COUNT; + if (consumer.is_consuming_contour_points ()) { - unsigned count = all_points.length; - assert (count >= glyf_impl::PHANTOM_COUNT); - count -= glyf_impl::PHANTOM_COUNT; - for (unsigned point_index = 0; point_index < count; point_index++) - consumer.consume_point (all_points[point_index]); + for (auto &point : all_points.as_array ().sub_array (0, count)) + consumer.consume_point (point); consumer.points_end (); } @@ -236,7 +234,7 @@ struct glyf_accelerator_t contour_point_t *phantoms = consumer.get_phantoms_sink (); if (phantoms) for (unsigned i = 0; i < glyf_impl::PHANTOM_COUNT; ++i) - phantoms[i] = all_points[all_points.length - glyf_impl::PHANTOM_COUNT + i]; + phantoms[i] = all_points.arrayZ[count + i]; return true; } @@ -299,6 +297,7 @@ struct glyf_accelerator_t if (extents) bounds = contour_bounds_t (); } + HB_ALWAYS_INLINE void consume_point (const contour_point_t &point) { bounds.add (point); } void points_end () { bounds.get_extents (font, extents, scaled); } @@ -431,16 +430,17 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan, hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const { OT::glyf_accelerator_t glyf (plan->source); - unsigned num_glyphs = plan->num_output_glyphs (); - if (!glyphs.resize (num_glyphs)) return false; + if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false; - for (auto p : plan->glyph_map->iter ()) + for (const auto &pair : plan->new_to_old_gid_list) { - unsigned new_gid = p.second; - glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid]; - subset_glyph.old_gid = p.first; + hb_codepoint_t new_gid = pair.first; + hb_codepoint_t old_gid = pair.second; + glyf_impl::SubsetGlyph *p = glyphs.push (); + glyf_impl::SubsetGlyph& subset_glyph = *p; + subset_glyph.old_gid = old_gid; - if (unlikely (new_gid == 0 && + if (unlikely (old_gid == 0 && new_gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) && !plan->normalized_coords) subset_glyph.source_glyph = glyf_impl::Glyph (); @@ -487,7 +487,7 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const { hb_variation_t var; var.tag = _.first; - var.value = _.second; + var.value = _.second.middle; vars.push (var); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh index f7f732d3363..f5505245033 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/glyf/path-builder.hh @@ -21,11 +21,11 @@ struct path_builder_t operator bool () const { return has_data; } bool has_data = false; - float x = 0.; - float y = 0.; + float x; + float y; - optional_point_t lerp (optional_point_t p, float t) - { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); } + optional_point_t mid (optional_point_t p) + { return optional_point_t ((x + p.x) * 0.5f, (y + p.y) * 0.5f); } } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2; path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) : @@ -37,6 +37,7 @@ struct path_builder_t * https://stackoverflow.com/a/20772557 * * Cubic support added. */ + HB_ALWAYS_INLINE void consume_point (const contour_point_t &point) { bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE; @@ -46,7 +47,7 @@ struct path_builder_t bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC); #endif optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y)); - if (!first_oncurve) + if (unlikely (!first_oncurve)) { if (is_on_curve) { @@ -62,7 +63,7 @@ struct path_builder_t } else if (first_offcurve) { - optional_point_t mid = first_offcurve.lerp (p, .5f); + optional_point_t mid = first_offcurve.mid (p); first_oncurve = mid; last_offcurve = p; draw_session->move_to (mid.x, mid.y); @@ -98,7 +99,7 @@ struct path_builder_t } else { - optional_point_t mid = last_offcurve.lerp (p, .5f); + optional_point_t mid = last_offcurve.mid (p); if (is_cubic) { @@ -123,13 +124,13 @@ struct path_builder_t } } - if (point.is_end_point) + if (unlikely (point.is_end_point)) { if (first_offcurve && last_offcurve) { - optional_point_t mid = last_offcurve.lerp (first_offcurve2 ? - first_offcurve2 : - first_offcurve, .5f); + optional_point_t mid = last_offcurve.mid (first_offcurve2 ? + first_offcurve2 : + first_offcurve); if (last_offcurve2) draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, last_offcurve.x, last_offcurve.y, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh index c1839f3b683..c8de1013456 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/OT/name/name.hh @@ -359,7 +359,7 @@ struct name record.nameID = ids.name_id; record.length = 0; // handled in NameRecord copy() record.offset = 0; - memcpy (name_records, &record, NameRecord::static_size); + hb_memcpy (name_records, &record, NameRecord::static_size); name_records++; } #endif @@ -384,10 +384,7 @@ struct name bool subset (hb_subset_context_t *c) const { - TRACE_SUBSET (this); - - name *name_prime = c->serializer->start_embed<name> (); - if (unlikely (!name_prime)) return_trace (false); + auto *name_prime = c->serializer->start_embed<name> (); #ifdef HB_EXPERIMENTAL_API const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides = @@ -436,7 +433,7 @@ struct name if (!name_table_overrides->is_empty ()) { if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population (), true))) - return_trace (false); + return false; for (const auto& record_ids : name_table_overrides->keys ()) { if (name_table_overrides->get (record_ids).length == 0) @@ -448,13 +445,13 @@ struct name } #endif - return (name_prime->serialize (c->serializer, it, - std::addressof (this + stringOffset) + return name_prime->serialize (c->serializer, it, + std::addressof (this + stringOffset) #ifdef HB_EXPERIMENTAL_API - , insert_name_records - , name_table_overrides + , insert_name_records + , name_table_overrides #endif - )); + ); } bool sanitize_records (hb_sanitize_context_t *c) const diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py index 6011817bc54..c34976a0677 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py @@ -22,6 +22,7 @@ if '--experimental-api' not in sys.argv: """hb_shape_justify hb_subset_repack_or_fail hb_subset_input_override_name_table +hb_subset_input_set_axis_range """.splitlines () symbols = [x for x in symbols if x not in experimental_symbols] symbols = "\n".join (symbols) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/classdef-graph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/classdef-graph.hh index c2e24a70678..4ae0c13acce 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/classdef-graph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/classdef-graph.hh @@ -94,7 +94,13 @@ struct ClassDef : public OT::ClassDef } hb_bytes_t class_def_copy = serializer.copy_bytes (); - c.add_buffer ((char *) class_def_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer. + if (!class_def_copy.arrayZ) return false; + // Give ownership to the context, it will cleanup the buffer. + if (!c.add_buffer ((char *) class_def_copy.arrayZ)) + { + hb_free ((char *) class_def_copy.arrayZ); + return false; + } auto& obj = c.graph.vertices_[dest_obj].obj; obj.head = (char *) class_def_copy.arrayZ; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/coverage-graph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/coverage-graph.hh index 49d09363156..bd6e91a1f27 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/coverage-graph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/coverage-graph.hh @@ -118,7 +118,13 @@ struct Coverage : public OT::Layout::Common::Coverage } hb_bytes_t coverage_copy = serializer.copy_bytes (); - c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer. + if (!coverage_copy.arrayZ) return false; + // Give ownership to the context, it will cleanup the buffer. + if (!c.add_buffer ((char *) coverage_copy.arrayZ)) + { + hb_free ((char *) coverage_copy.arrayZ); + return false; + } auto& obj = c.graph.vertices_[dest_obj].obj; obj.head = (char *) coverage_copy.arrayZ; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh index 294a9999185..53d0bc94e10 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/graph.hh @@ -359,7 +359,6 @@ struct graph_t ~graph_t () { - vertices_.fini (); for (char* b : buffers) hb_free (b); } @@ -401,9 +400,10 @@ struct graph_t return vertices_[i].obj; } - void add_buffer (char* buffer) + bool add_buffer (char* buffer) { buffers.push (buffer); + return !buffers.in_error (); } /* @@ -732,8 +732,7 @@ struct graph_t remap_obj_indices (index_map, parents.iter (), true); // Update roots set with new indices as needed. - uint32_t next = HB_SET_VALUE_INVALID; - while (roots.next (&next)) + for (auto next : roots) { const uint32_t *v; if (index_map.has (next, &v)) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.cc index b2044426d46..d66eb49cfd2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.cc @@ -52,7 +52,11 @@ unsigned gsubgpos_graph_context_t::create_node (unsigned size) if (!buffer) return -1; - add_buffer (buffer); + if (!add_buffer (buffer)) { + // Allocation did not get stored for freeing later. + hb_free (buffer); + return -1; + } return graph.new_node (buffer, buffer + size); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.hh index 9fe9662e645..26b7cfe4d43 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-context.hh @@ -47,9 +47,9 @@ struct gsubgpos_graph_context_t HB_INTERNAL unsigned create_node (unsigned size); - void add_buffer (char* buffer) + bool add_buffer (char* buffer) { - graph.add_buffer (buffer); + return graph.add_buffer (buffer); } private: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh index c170638409f..78d50963257 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/gsubgpos-graph.hh @@ -166,7 +166,7 @@ struct Lookup : public OT::Lookup } if (all_new_subtables) { - add_sub_tables (c, this_index, type, all_new_subtables); + return add_sub_tables (c, this_index, type, all_new_subtables); } return true; @@ -184,7 +184,7 @@ struct Lookup : public OT::Lookup return sub_table->split_subtables (c, parent_idx, objidx); } - void add_sub_tables (gsubgpos_graph_context_t& c, + bool add_sub_tables (gsubgpos_graph_context_t& c, unsigned this_index, unsigned type, hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids) @@ -200,7 +200,12 @@ struct Lookup : public OT::Lookup size_t new_size = v.table_size () + new_subtable_count * OT::Offset16::static_size; char* buffer = (char*) hb_calloc (1, new_size); - c.add_buffer (buffer); + if (!buffer) return false; + if (!c.add_buffer (buffer)) + { + hb_free (buffer); + return false; + } hb_memcpy (buffer, v.obj.head, v.table_size()); v.obj.head = buffer; @@ -239,6 +244,7 @@ struct Lookup : public OT::Lookup // The head location of the lookup has changed, invalidating the lookups map entry // in the context. Update the map. c.lookups.set (this_index, new_lookup); + return true; } void fix_existing_subtable_links (gsubgpos_graph_context_t& c, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh index 1c13eb24f94..f655b715580 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/pairpos-graph.hh @@ -215,7 +215,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType auto gid_and_class = + coverage->iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1->get_class (gid)); + return hb_codepoint_pair_t (gid, class_def_1->get_class (gid)); }) ; class_def_size_estimator_t estimator (gid_and_class); @@ -386,14 +386,14 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType auto klass_map = + coverage_table->iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1_table->get_class (gid)); + return hb_codepoint_pair_t (gid, class_def_1_table->get_class (gid)); }) | hb_filter ([&] (hb_codepoint_t klass) { return klass >= start && klass < end; }, hb_second) - | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, hb_codepoint_t> gid_and_class) { + | hb_map_retains_sorting ([&] (hb_codepoint_pair_t gid_and_class) { // Classes must be from 0...N so subtract start - return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid_and_class.first, gid_and_class.second - start); + return hb_codepoint_pair_t (gid_and_class.first, gid_and_class.second - start); }) ; @@ -519,7 +519,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType auto klass_map = + coverage.table->iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1.table->get_class (gid)); + return hb_codepoint_pair_t (gid, class_def_1.table->get_class (gid)); }) | hb_filter ([&] (hb_codepoint_t klass) { return klass < count; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/serialize.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/serialize.hh index 2e0b845baa9..06e4bf44d8e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/serialize.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/serialize.hh @@ -226,6 +226,9 @@ inline hb_blob_t* serialize (const graph_t& graph) { hb_vector_t<char> buffer; size_t size = graph.total_size_in_bytes (); + + if (!size) return hb_blob_get_empty (); + if (!buffer.alloc (size)) { DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer."); return nullptr; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc index 55854ff5c29..266be5e2d40 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/graph/test-classdef-graph.cc @@ -27,7 +27,7 @@ #include "gsubgpos-context.hh" #include "classdef-graph.hh" -typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> gid_and_class_t; +typedef hb_codepoint_pair_t gid_and_class_t; typedef hb_vector_t<gid_and_class_t> gid_and_class_list_t; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-config.cmake.in b/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-config.cmake.in index ced97919a23..95b5d0afd27 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-config.cmake.in +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz-config.cmake.in @@ -13,12 +13,18 @@ list(GET _harfbuzz_version_info 2 unset(_harfbuzz_version_info) if ("@default_library@" MATCHES "static") + set(_harfbuzz_lib_prefix "lib") set(_harfbuzz_lib_suffix ".a") else () if (APPLE) + set(_harfbuzz_lib_prefix "${CMAKE_SHARED_LIBRARY_PREFIX}") set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}") elseif (UNIX) + set(_harfbuzz_lib_prefix "${CMAKE_SHARED_LIBRARY_PREFIX}") set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}") + elseif (WIN32) + set(_harfbuzz_lib_prefix "${CMAKE_IMPORT_LIBRARY_PREFIX}") + set(_harfbuzz_lib_suffix "${CMAKE_IMPORT_LIBRARY_SUFFIX}") else () # Unsupported. set(harfbuzz_FOUND 0) @@ -29,19 +35,19 @@ endif () add_library(harfbuzz::harfbuzz SHARED IMPORTED) set_target_properties(harfbuzz::harfbuzz PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz" - IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}") + IMPORTED_LOCATION "${_harfbuzz_libdir}/${_harfbuzz_lib_prefix}harfbuzz${_harfbuzz_lib_suffix}") add_library(harfbuzz::icu SHARED IMPORTED) set_target_properties(harfbuzz::icu PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz" INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz" - IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}") + IMPORTED_LOCATION "${_harfbuzz_libdir}/${_harfbuzz_lib_prefix}harfbuzz-icu${_harfbuzz_lib_suffix}") add_library(harfbuzz::subset SHARED IMPORTED) set_target_properties(harfbuzz::subset PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz" INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz" - IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}") + IMPORTED_LOCATION "${_harfbuzz_libdir}/${_harfbuzz_lib_prefix}harfbuzz-subset${_harfbuzz_lib_suffix}") # Only add the gobject library if it was built. set(_harfbuzz_have_gobject "@have_gobject@") @@ -50,10 +56,11 @@ if (_harfbuzz_have_gobject) set_target_properties(harfbuzz::gobject PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz" INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz" - IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}") + IMPORTED_LOCATION "${_harfbuzz_libdir}/${_harfbuzz_lib_prefix}harfbuzz-gobject${_harfbuzz_lib_suffix}") endif () # Clean out variables we used in our scope. +unset(_harfbuzz_lib_prefix) unset(_harfbuzz_lib_suffix) unset(_harfbuzz_current) unset(_harfbuzz_revision) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc index d7e8a93f393..26e2bc1450d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc @@ -58,3 +58,5 @@ #include "hb-ucd.cc" #include "hb-unicode.cc" #include "hb-uniscribe.cc" +#include "hb-wasm-api.cc" +#include "hb-wasm-shape.cc" diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh index da383e050a9..374965d56e8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh @@ -87,6 +87,19 @@ static inline constexpr uint16_t hb_uint16_swap (uint16_t v) static inline constexpr uint32_t hb_uint32_swap (uint32_t v) { return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } +#ifndef HB_FAST_INT_ACCESS +#if defined(__OPTIMIZE__) && \ + defined(__BYTE_ORDER) && \ + (__BYTE_ORDER == __BIG_ENDIAN || \ + (__BYTE_ORDER == __LITTLE_ENDIAN && \ + hb_has_builtin(__builtin_bswap16) && \ + hb_has_builtin(__builtin_bswap32))) +#define HB_FAST_INT_ACCESS 1 +#else +#define HB_FAST_INT_ACCESS 0 +#endif +#endif + template <typename Type, int Bytes = sizeof (Type)> struct BEInt; template <typename Type> @@ -101,21 +114,25 @@ struct BEInt<Type, 1> template <typename Type> struct BEInt<Type, 2> { + struct __attribute__((packed)) packed_uint16_t { uint16_t v; }; + public: BEInt () = default; - constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF), - uint8_t ((V ) & 0xFF)} {} - struct __attribute__((packed)) packed_uint16_t { uint16_t v; }; - constexpr operator Type () const - { -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - defined(__BYTE_ORDER) && \ - (__BYTE_ORDER == __BIG_ENDIAN || \ - (__BYTE_ORDER == __LITTLE_ENDIAN && \ - hb_has_builtin(__builtin_bswap16))) - /* Spoon-feed the compiler a big-endian integer with alignment 1. - * https://github.com/harfbuzz/harfbuzz/pull/1398 */ + BEInt (Type V) +#if HB_FAST_INT_ACCESS +#if __BYTE_ORDER == __LITTLE_ENDIAN + { ((packed_uint16_t *) v)->v = __builtin_bswap16 (V); } +#else /* __BYTE_ORDER == __BIG_ENDIAN */ + { ((packed_uint16_t *) v)->v = V; } +#endif +#else + : v {uint8_t ((V >> 8) & 0xFF), + uint8_t ((V ) & 0xFF)} {} +#endif + + constexpr operator Type () const { +#if HB_FAST_INT_ACCESS #if __BYTE_ORDER == __LITTLE_ENDIAN return __builtin_bswap16 (((packed_uint16_t *) v)->v); #else /* __BYTE_ORDER == __BIG_ENDIAN */ @@ -146,22 +163,27 @@ struct BEInt<Type, 3> template <typename Type> struct BEInt<Type, 4> { + struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; + public: BEInt () = default; - constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF), - uint8_t ((V >> 16) & 0xFF), - uint8_t ((V >> 8) & 0xFF), - uint8_t ((V ) & 0xFF)} {} - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; + BEInt (Type V) +#if HB_FAST_INT_ACCESS +#if __BYTE_ORDER == __LITTLE_ENDIAN + { ((packed_uint32_t *) v)->v = __builtin_bswap32 (V); } +#else /* __BYTE_ORDER == __BIG_ENDIAN */ + { ((packed_uint32_t *) v)->v = V; } +#endif +#else + : v {uint8_t ((V >> 24) & 0xFF), + uint8_t ((V >> 16) & 0xFF), + uint8_t ((V >> 8) & 0xFF), + uint8_t ((V ) & 0xFF)} {} +#endif + constexpr operator Type () const { -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - defined(__BYTE_ORDER) && \ - (__BYTE_ORDER == __BIG_ENDIAN || \ - (__BYTE_ORDER == __LITTLE_ENDIAN && \ - hb_has_builtin(__builtin_bswap32))) - /* Spoon-feed the compiler a big-endian integer with alignment 1. - * https://github.com/harfbuzz/harfbuzz/pull/1398 */ +#if HB_FAST_INT_ACCESS #if __BYTE_ORDER == __LITTLE_ENDIAN return __builtin_bswap32 (((packed_uint32_t *) v)->v); #else /* __BYTE_ORDER == __BIG_ENDIAN */ @@ -231,12 +253,119 @@ struct } HB_FUNCOBJ (hb_bool); + +/* The MIT License + + Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com) + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + + +// Compression function for Merkle-Damgard construction. +// This function is generated using the framework provided. +#define mix(h) ( \ + (h) ^= (h) >> 23, \ + (h) *= 0x2127599bf4325c37ULL, \ + (h) ^= (h) >> 47) + +static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed) +{ + struct __attribute__((packed)) packed_uint64_t { uint64_t v; }; + const uint64_t m = 0x880355f21e6d1965ULL; + const packed_uint64_t *pos = (const packed_uint64_t *)buf; + const packed_uint64_t *end = pos + (len / 8); + const unsigned char *pos2; + uint64_t h = seed ^ (len * m); + uint64_t v; + +#ifndef HB_OPTIMIZE_SIZE + if (((uintptr_t) pos & 7) == 0) + { + while (pos != end) + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" + v = * (const uint64_t *) (pos++); +#pragma GCC diagnostic pop + h ^= mix(v); + h *= m; + } + } + else +#endif + { + while (pos != end) + { + v = pos++->v; + h ^= mix(v); + h *= m; + } + } + + pos2 = (const unsigned char*)pos; + v = 0; + + switch (len & 7) { + case 7: v ^= (uint64_t)pos2[6] << 48; HB_FALLTHROUGH; + case 6: v ^= (uint64_t)pos2[5] << 40; HB_FALLTHROUGH; + case 5: v ^= (uint64_t)pos2[4] << 32; HB_FALLTHROUGH; + case 4: v ^= (uint64_t)pos2[3] << 24; HB_FALLTHROUGH; + case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH; + case 2: v ^= (uint64_t)pos2[1] << 8; HB_FALLTHROUGH; + case 1: v ^= (uint64_t)pos2[0]; + h ^= mix(v); + h *= m; + } + + return mix(h); +} + +static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed) +{ + // the following trick converts the 64-bit hashcode to Fermat + // residue, which shall retain information from both the higher + // and lower parts of hashcode. + uint64_t h = fasthash64(buf, len, seed); + return h - (h >> 32); +} + struct { private: template <typename T> constexpr auto - impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) + impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) + + // Horrible: std:hash() of integers seems to be identity in gcc / clang?! + // https://github.com/harfbuzz/harfbuzz/pull/4228 + // + // For performance characteristics see: + // https://github.com/harfbuzz/harfbuzz/pull/4228#issuecomment-1565079537 + template <typename T, + hb_enable_if (std::is_integral<T>::value && sizeof (T) <= sizeof (uint32_t))> constexpr auto + impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, v * 2654435761u /* Knuh's multiplicative hash */) + template <typename T, + hb_enable_if (std::is_integral<T>::value && sizeof (T) > sizeof (uint32_t))> constexpr auto + impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (v ^ (v >> 32)) * 2654435761u /* Knuth's multiplicative hash */) template <typename T> constexpr auto impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v))) @@ -551,6 +680,8 @@ struct hb_pair_t template <typename T1, typename T2> static inline hb_pair_t<T1, T2> hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); } +typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t; + struct { template <typename Pair> constexpr typename Pair::first_t @@ -853,7 +984,7 @@ static inline void * hb_memset (void *s, int c, unsigned int n) { /* It's illegal to pass NULL to memset(), even if n is zero. */ - if (unlikely (!n)) return 0; + if (unlikely (!n)) return s; return memset (s, c, n); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh index 1a22e15c0fb..760f90259c8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh @@ -75,11 +75,25 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> */ typedef Type& __item_t__; static constexpr bool is_random_access_iterator = true; + static constexpr bool has_fast_len = true; + Type& __item__ () const + { + if (unlikely (!length)) return CrapOrNull (Type); + return *arrayZ; + } Type& __item_at__ (unsigned i) const { if (unlikely (i >= length)) return CrapOrNull (Type); return arrayZ[i]; } + void __next__ () + { + if (unlikely (!length)) + return; + length--; + backwards_length++; + arrayZ++; + } void __forward__ (unsigned n) { if (unlikely (n > length)) @@ -88,6 +102,14 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> backwards_length += n; arrayZ += n; } + void __prev__ () + { + if (unlikely (!backwards_length)) + return; + length++; + backwards_length--; + arrayZ--; + } void __rewind__ (unsigned n) { if (unlikely (n > backwards_length)) @@ -123,6 +145,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> uint32_t hash () const { // FNV-1a hash function + // https://github.com/harfbuzz/harfbuzz/pull/4228 uint32_t current = /*cbf29ce4*/0x84222325; for (auto &v : *this) { @@ -326,6 +349,7 @@ struct hb_sorted_array_t : HB_ITER_USING (iter_base_t); static constexpr bool is_random_access_iterator = true; static constexpr bool is_sorted_iterator = true; + static constexpr bool has_fast_len = true; hb_sorted_array_t () = default; hb_sorted_array_t (const hb_sorted_array_t&) = default; @@ -453,55 +477,21 @@ inline bool hb_array_t<const unsigned char>::operator == (const hb_array_t<const /* Specialize hash() for byte arrays. */ +#ifndef HB_OPTIMIZE_SIZE_MORE template <> inline uint32_t hb_array_t<const char>::hash () const { - // FNV-1a hash function - uint32_t current = /*cbf29ce4*/0x84222325; - unsigned i = 0; - -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; - for (; i + 4 <= this->length; i += 4) - { - current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v); - current = current * 16777619; - } -#endif - - for (; i < this->length; i++) - { - current = current ^ hb_hash (this->arrayZ[i]); - current = current * 16777619; - } - return current; + // https://github.com/harfbuzz/harfbuzz/pull/4228 + return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */); } template <> inline uint32_t hb_array_t<const unsigned char>::hash () const { - // FNV-1a hash function - uint32_t current = /*cbf29ce4*/0x84222325; - unsigned i = 0; - -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; - for (; i + 4 <= this->length; i += 4) - { - current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v); - current = current * 16777619; - } -#endif - - for (; i < this->length; i++) - { - current = current ^ hb_hash (this->arrayZ[i]); - current = current * 16777619; - } - return current; + // https://github.com/harfbuzz/harfbuzz/pull/4228 + return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */); } +#endif typedef hb_array_t<const char> hb_bytes_t; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh index a6283de1408..303dfe6d047 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh @@ -204,6 +204,7 @@ struct hb_atomic_ptr_t 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_); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh index 9edefd97106..4006fc4ebd0 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh @@ -39,10 +39,10 @@ struct hb_bimap_t back_map.reset (); } - void resize (unsigned pop) + void alloc (unsigned pop) { - forw_map.resize (pop); - back_map.resize (pop); + forw_map.alloc (pop); + back_map.alloc (pop); } bool in_error () const { return forw_map.in_error () || back_map.in_error (); } @@ -83,7 +83,6 @@ struct hb_bimap_t unsigned int get_population () const { return forw_map.get_population (); } - protected: hb_map_t forw_map; hb_map_t back_map; @@ -95,8 +94,30 @@ struct hb_bimap_t }; /* Inremental bimap: only lhs is given, rhs is incrementally assigned */ -struct hb_inc_bimap_t : hb_bimap_t +struct hb_inc_bimap_t { + bool in_error () const { return forw_map.in_error () || back_map.in_error (); } + + unsigned int get_population () const { return forw_map.get_population (); } + + void reset () + { + forw_map.reset (); + back_map.reset (); + } + + void alloc (unsigned pop) + { + forw_map.alloc (pop); + back_map.alloc (pop); + } + + void clear () + { + forw_map.clear (); + back_map.resize (0); + } + /* Add a mapping from lhs to rhs with a unique value if lhs is unknown. * Return the rhs value as the result. */ @@ -105,32 +126,41 @@ struct hb_inc_bimap_t : hb_bimap_t hb_codepoint_t rhs = forw_map[lhs]; if (rhs == HB_MAP_VALUE_INVALID) { - rhs = next_value++; - set (lhs, rhs); + rhs = back_map.length; + forw_map.set (lhs, rhs); + back_map.push (lhs); } return rhs; } hb_codepoint_t skip () - { return next_value++; } + { + hb_codepoint_t start = back_map.length; + back_map.push (HB_MAP_VALUE_INVALID); + return start; + } hb_codepoint_t skip (unsigned count) - { return next_value += count; } + { + hb_codepoint_t start = back_map.length; + for (unsigned i = 0; i < count; i++) + back_map.push (HB_MAP_VALUE_INVALID); + return start; + } hb_codepoint_t get_next_value () const - { return next_value; } + { return back_map.length; } void add_set (const hb_set_t *set) { - hb_codepoint_t i = HB_SET_VALUE_INVALID; - while (hb_set_next (set, &i)) add (i); + for (auto i : *set) add (i); } /* Create an identity map. */ bool identity (unsigned int size) { clear (); - for (hb_codepoint_t i = 0; i < size; i++) set (i, i); + for (hb_codepoint_t i = 0; i < size; i++) add (i); return !in_error (); } @@ -145,20 +175,30 @@ struct hb_inc_bimap_t : hb_bimap_t { hb_codepoint_t count = get_population (); hb_vector_t <hb_codepoint_t> work; - work.resize (count); + if (unlikely (!work.resize (count, false))) return; for (hb_codepoint_t rhs = 0; rhs < count; rhs++) - work[rhs] = back_map[rhs]; + work.arrayZ[rhs] = back_map[rhs]; work.qsort (cmp_id); clear (); for (hb_codepoint_t rhs = 0; rhs < count; rhs++) - set (work[rhs], rhs); + add (work.arrayZ[rhs]); } + hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); } + hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; } + + hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); } + bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); } + protected: - unsigned int next_value = 0; + hb_map_t forw_map; + hb_vector_t<hb_codepoint_t> back_map; + + public: + auto keys () const HB_AUTO_RETURN (+ back_map.iter()) }; #endif /* HB_BIMAP_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh index 9b027ac5905..e578d2643fa 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh @@ -104,10 +104,7 @@ struct hb_bit_page_t } uint32_t hash () const { - return - + hb_iter (v) - | hb_reduce ([] (uint32_t h, const elt_t &_) { return h * 31 + hb_hash (_); }, (uint32_t) 0u) - ; + return hb_bytes_t ((const char *) &v, sizeof (v)).hash (); } void add (hb_codepoint_t g) { elt (g) |= mask (g); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh index 1eb1b1c2092..e765a479ae6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh @@ -136,7 +136,7 @@ struct hb_bit_set_invertible_t /* Sink interface. */ hb_bit_set_invertible_t& operator << (hb_codepoint_t v) { add (v); return *this; } - hb_bit_set_invertible_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range) + hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range) { add_range (range.first, range.second); return *this; } bool intersects (hb_codepoint_t first, hb_codepoint_t last) const @@ -162,7 +162,7 @@ struct hb_bit_set_invertible_t auto it1 = iter (); auto it2 = other.iter (); return hb_all (+ hb_zip (it1, it2) - | hb_map ([](hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) { return _.first == _.second; })); + | hb_map ([](hb_codepoint_pair_t _) { return _.first == _.second; })); } } @@ -345,6 +345,7 @@ struct hb_bit_set_invertible_t struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t> { static constexpr bool is_sorted_iterator = true; + static constexpr bool has_fast_len = true; iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t), bool init = true) : s (&s_), v (INVALID), l(0) { @@ -363,7 +364,7 @@ struct hb_bit_set_invertible_t unsigned __len__ () const { return l; } iter_t end () const { return iter_t (*s, false); } bool operator != (const iter_t& o) const - { return s != o.s || v != o.v; } + { return v != o.v || s != o.s; } protected: const hb_bit_set_invertible_t *s; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh index d290f6114cf..a84d751fb35 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh @@ -134,7 +134,11 @@ struct hb_bit_set_t { uint32_t h = 0; for (auto &map : page_map) - h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]); + { + auto &page = pages.arrayZ[map.index]; + if (unlikely (page.is_empty ())) continue; + h = h * 31 + hb_hash (map.major) + hb_hash (page); + } return h; } @@ -342,7 +346,7 @@ struct hb_bit_set_t /* Sink interface. */ hb_bit_set_t& operator << (hb_codepoint_t v) { add (v); return *this; } - hb_bit_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range) + hb_bit_set_t& operator << (const hb_codepoint_pair_t& range) { add_range (range.first, range.second); return *this; } bool intersects (hb_codepoint_t first, hb_codepoint_t last) const @@ -862,6 +866,7 @@ struct hb_bit_set_t struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t> { static constexpr bool is_sorted_iterator = true; + static constexpr bool has_fast_len = true; iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t), bool init = true) : s (&s_), v (INVALID), l(0) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc index f111b2d8dcf..15a53919def 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-verify.cc @@ -162,14 +162,8 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer, hb_buffer_set_flags (fragment, flags); hb_buffer_append (fragment, text_buffer, text_start, text_end); - if (!hb_shape_full (font, fragment, features, num_features, shapers)) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); - hb_buffer_destroy (reconstruction); - hb_buffer_destroy (fragment); - return false; - } - else if (!fragment->successful || fragment->shaping_failed) + if (!hb_shape_full (font, fragment, features, num_features, shapers) || + fragment->successful || fragment->shaping_failed) { hb_buffer_destroy (reconstruction); hb_buffer_destroy (fragment); @@ -185,15 +179,18 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer, } bool ret = true; - hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); - if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + if (likely (reconstruction->successful)) { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed."); - ret = false; + hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed."); + ret = false; - /* Return the reconstructed result instead so it can be inspected. */ - hb_buffer_set_length (buffer, 0); - hb_buffer_append (buffer, reconstruction, 0, -1); + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } } hb_buffer_destroy (reconstruction); @@ -316,28 +313,13 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, /* * Shape the two fragment streams. */ - if (!hb_shape_full (font, fragments[0], features, num_features, shapers)) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); - ret = false; - goto out; - } - else if (!fragments[0]->successful || fragments[0]->shaping_failed) - { - ret = true; - goto out; - } - if (!hb_shape_full (font, fragments[1], features, num_features, shapers)) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); - ret = false; + if (!hb_shape_full (font, fragments[0], features, num_features, shapers) || + !fragments[0]->successful || fragments[0]->shaping_failed) goto out; - } - else if (!fragments[1]->successful || fragments[1]->shaping_failed) - { - ret = true; + + if (!hb_shape_full (font, fragments[1], features, num_features, shapers) || + !fragments[1]->successful || fragments[1]->shaping_failed) goto out; - } if (!forward) { @@ -377,21 +359,23 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, hb_buffer_reverse (reconstruction); } - /* - * Diff results. - */ - diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); - if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + if (likely (reconstruction->successful)) { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed."); - ret = false; + /* + * Diff results. + */ + diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed."); + ret = false; - /* Return the reconstructed result instead so it can be inspected. */ - hb_buffer_set_length (buffer, 0); - hb_buffer_append (buffer, reconstruction, 0, -1); + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } } - out: hb_buffer_destroy (reconstruction); hb_buffer_destroy (fragments[0]); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh index 7a97fc71688..4d48b7f167e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh @@ -493,6 +493,13 @@ struct hb_buffer_t HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size); + HB_NODISCARD bool resize (unsigned length) + { + assert (!have_output); + if (unlikely (!ensure (length))) return false; + len = length; + return true; + } HB_NODISCARD bool ensure (unsigned int size) { return likely (!size || size < allocated) ? true : enlarge (size); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh index 8371465c6c2..6d8a54cf102 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cache.hh @@ -62,14 +62,12 @@ struct hb_cache_t static_assert ((key_bits >= cache_bits), ""); static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), ""); - hb_cache_t () { init (); } - - void init () { clear (); } + hb_cache_t () { clear (); } void clear () { - for (unsigned i = 0; i < ARRAY_LENGTH (values); i++) - values[i] = -1; + for (auto &v : values) + v = -1; } bool get (unsigned int key, unsigned int *value) const diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc index 0f94d8169f2..ec1499e861e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo-utils.cc @@ -80,7 +80,7 @@ hb_cairo_read_blob (void *closure, if (r->offset + length > size) return CAIRO_STATUS_READ_ERROR; - memcpy (data, d + r->offset, length); + hb_memcpy (data, d + r->offset, length); r->offset += length; return CAIRO_STATUS_SUCCESS; @@ -763,7 +763,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops, } //assert (angles[0] + k * span <= 0 && 0 < angles[n_stops - 1] + k * span); - span = fabs (span); + span = fabsf (span); for (signed l = k; l < 1000; l++) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo.cc index f005afd17e7..68c7bc064ff 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cairo.cc @@ -956,7 +956,7 @@ hb_cairo_glyphs_from_buffer (hb_buffer_t *buffer, if (clusters && *num_clusters && utf8) { - memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0])); + hb_memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0])); hb_bool_t backward = HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (buffer)); *cluster_flags = backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : (cairo_text_cluster_flags_t) 0; unsigned int cluster = 0; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh index 949bfebf9be..1d1f10f2bfa 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh @@ -26,6 +26,8 @@ #ifndef HB_CFF_INTERP_COMMON_HH #define HB_CFF_INTERP_COMMON_HH +extern HB_INTERNAL const unsigned char *endchar_str; + namespace CFF { using namespace OT; @@ -336,8 +338,6 @@ struct byte_str_ref_t hb_ubytes_t str; }; -using byte_str_array_t = hb_vector_t<hb_ubytes_t>; - /* stack */ template <typename ELEM, int LIMIT> struct cff_stack_t diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh index f40be51f0d7..28a777eb0d4 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh @@ -883,14 +883,12 @@ struct cs_interpreter_t : interpreter_t<ENV> unsigned max_ops = HB_CFF_MAX_OPS; for (;;) { - if (unlikely (!--max_ops)) + OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); + if (unlikely (SUPER::env.in_error () || !--max_ops)) { SUPER::env.set_error (); - break; - } - OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); - if (unlikely (SUPER::env.in_error ())) return false; + } if (SUPER::env.is_endchar ()) break; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h index a5da4e76a32..a9fe666b392 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h @@ -104,6 +104,16 @@ typedef int hb_bool_t; * **/ typedef uint32_t hb_codepoint_t; + +/** + * HB_CODEPOINT_INVALID: + * + * Unused #hb_codepoint_t value. + * + * Since: 8.0.0 + */ +#define HB_CODEPOINT_INVALID ((hb_codepoint_t) -1) + /** * hb_position_t: * diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh index 26f7cba83e2..335c6976f6f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh @@ -113,7 +113,6 @@ /* Closure of options. */ #ifdef HB_NO_BORING_EXPANSION -#define HB_NO_AVAR2 #define HB_NO_BEYOND_64K #define HB_NO_CUBIC_GLYF #define HB_NO_VAR_COMPOSITES diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh index 0ac4515fa85..6055fce962c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh @@ -389,6 +389,10 @@ struct hb_no_trace_t { #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0) #endif +#ifndef HB_DEBUG_WASM +#define HB_DEBUG_WASM (HB_DEBUG+0) +#endif + /* * With tracing. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h index b032a941b28..9fcce6d9ac4 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h @@ -255,6 +255,52 @@ HB_EXTERN hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); + +/** + * hb_font_get_glyph_shape_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @draw_funcs: The draw functions to send the shape data to + * @draw_data: The data accompanying the draw functions + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * Since: 4.0.0 + * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead + **/ +typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data); + +/** + * hb_font_funcs_set_glyph_shape_func: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets the implementation function for #hb_font_get_glyph_shape_func_t, + * which is the same as #hb_font_draw_glyph_func_t. + * + * Since: 4.0.0 + * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead + **/ +HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func) +HB_EXTERN void +hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_shape_func_t func, + void *user_data, hb_destroy_func_t destroy); + +HB_DEPRECATED_FOR (hb_font_draw_glyph) +HB_EXTERN void +hb_font_get_glyph_shape (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data); + + #endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh index 768f51a8756..25dee1261ef 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh @@ -93,50 +93,57 @@ struct hb_draw_funcs_t !user_data ? nullptr : user_data->close_path); } - void move_to (void *draw_data, hb_draw_state_t &st, - float to_x, float to_y) + void + HB_ALWAYS_INLINE + move_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) { - if (st.path_open) close_path (draw_data, st); + if (unlikely (st.path_open)) close_path (draw_data, st); st.current_x = to_x; st.current_y = to_y; } - void line_to (void *draw_data, hb_draw_state_t &st, - float to_x, float to_y) + void + HB_ALWAYS_INLINE + line_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) { - if (!st.path_open) start_path (draw_data, st); + if (unlikely (!st.path_open)) start_path (draw_data, st); emit_line_to (draw_data, st, to_x, to_y); st.current_x = to_x; st.current_y = to_y; } void + HB_ALWAYS_INLINE quadratic_to (void *draw_data, hb_draw_state_t &st, float control_x, float control_y, float to_x, float to_y) { - if (!st.path_open) start_path (draw_data, st); + if (unlikely (!st.path_open)) start_path (draw_data, st); emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); st.current_x = to_x; st.current_y = to_y; } void + HB_ALWAYS_INLINE cubic_to (void *draw_data, hb_draw_state_t &st, float control1_x, float control1_y, float control2_x, float control2_y, float to_x, float to_y) { - if (!st.path_open) start_path (draw_data, st); + if (unlikely (!st.path_open)) start_path (draw_data, st); emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); st.current_x = to_x; st.current_y = to_y; } void + HB_ALWAYS_INLINE close_path (void *draw_data, hb_draw_state_t &st) { - if (st.path_open) + if (likely (st.path_open)) { if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y)) emit_line_to (draw_data, st, st.path_start_x, st.path_start_y); @@ -168,6 +175,7 @@ struct hb_draw_session_t ~hb_draw_session_t () { close_path (); } + HB_ALWAYS_INLINE void move_to (float to_x, float to_y) { if (likely (not_slanted)) @@ -177,6 +185,7 @@ struct hb_draw_session_t funcs->move_to (draw_data, st, to_x + to_y * slant, to_y); } + HB_ALWAYS_INLINE void line_to (float to_x, float to_y) { if (likely (not_slanted)) @@ -187,6 +196,7 @@ struct hb_draw_session_t to_x + to_y * slant, to_y); } void + HB_ALWAYS_INLINE quadratic_to (float control_x, float control_y, float to_x, float to_y) { @@ -200,6 +210,7 @@ struct hb_draw_session_t to_x + to_y * slant, to_y); } void + HB_ALWAYS_INLINE cubic_to (float control1_x, float control1_y, float control2_x, float control2_y, float to_x, float to_y) @@ -215,6 +226,7 @@ struct hb_draw_session_t control2_x + control2_y * slant, control2_y, to_x + to_y * slant, to_y); } + HB_ALWAYS_INLINE void close_path () { funcs->close_path (draw_data, st); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc index 688513112a7..f062bfaf757 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc @@ -1389,6 +1389,7 @@ hb_font_get_glyph_from_name (hb_font_t *font, return font->get_glyph_from_name (name, len, glyph); } +#ifndef HB_DISABLE_DEPRECATED /** * hb_font_get_glyph_shape: * @font: #hb_font_t to work upon @@ -1410,6 +1411,7 @@ hb_font_get_glyph_shape (hb_font_t *font, { hb_font_draw_glyph (font, glyph, dfuncs, draw_data); } +#endif /** * hb_font_draw_glyph: @@ -2648,7 +2650,6 @@ hb_font_set_variations (hb_font_t *font, if (axes[axis_index].axisTag == tag) design_coords[axis_index] = v; } - font->face->table.avar->map_coords (normalized, coords_length); hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized); _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length); @@ -2720,8 +2721,6 @@ hb_font_set_variation (hb_font_t *font, if (axes[axis_index].axisTag == tag) design_coords[axis_index] = value; - font->face->table.avar->map_coords (normalized, coords_length); - hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized); _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length); @@ -3058,6 +3057,7 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, #endif +#ifndef HB_DISABLE_DEPRECATED void hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_shape_func_t func, @@ -3066,3 +3066,4 @@ hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, { hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); } +#endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h index f3b589bd0d8..3c2355af2d7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h @@ -486,25 +486,6 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void * void *user_data); /** - * hb_font_get_glyph_shape_func_t: - * @font: #hb_font_t to work upon - * @font_data: @font user data pointer - * @glyph: The glyph ID to query - * @draw_funcs: The draw functions to send the shape data to - * @draw_data: The data accompanying the draw functions - * @user_data: User data pointer passed by the caller - * - * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. - * - * Since: 4.0.0 - * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead - **/ -typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data, - void *user_data); - -/** * hb_font_draw_glyph_func_t: * @font: #hb_font_t to work upon * @font_data: @font user data pointer @@ -804,32 +785,13 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, void *user_data, hb_destroy_func_t destroy); /** - * hb_font_funcs_set_glyph_shape_func: - * @ffuncs: A font-function structure - * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign - * @user_data: Data to pass to @func - * @destroy: (nullable): The function to call when @user_data is not needed anymore - * - * Sets the implementation function for #hb_font_get_glyph_shape_func_t, - * which is the same as #hb_font_draw_glyph_func_t. - * - * Since: 4.0.0 - * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead - **/ -HB_EXTERN void -hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_shape_func_t func, - void *user_data, hb_destroy_func_t destroy); - -/** * hb_font_funcs_set_draw_glyph_func: * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func * @destroy: (nullable): The function to call when @user_data is not needed anymore * - * Sets the implementation function for #hb_font_draw_glyph_func_t, - * which is the same as #hb_font_get_glyph_shape_func_t. + * Sets the implementation function for #hb_font_draw_glyph_func_t. * * Since: 7.0.0 **/ @@ -935,11 +897,6 @@ hb_font_get_glyph_from_name (hb_font_t *font, hb_codepoint_t *glyph); HB_EXTERN void -hb_font_get_glyph_shape (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_funcs_t *dfuncs, void *draw_data); - -HB_EXTERN void hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_draw_funcs_t *dfuncs, void *draw_data); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc index 1105862fbc9..6ca3f854655 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc @@ -114,7 +114,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; ft_font->cached_serial = (unsigned) -1; - ft_font->advance_cache.init (); + new (&ft_font->advance_cache) hb_ft_advance_cache_t; return ft_font; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc index 332cc84888d..d66de0b237f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc @@ -29,7 +29,7 @@ #ifdef HAVE_GOBJECT -/** +/* * SECTION:hb-gobject * @title: hb-gobject * @short_description: GObject integration support diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc index 9e068f8d84d..7ea03862238 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc @@ -248,6 +248,21 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, gr_fref_set_feature_value (fref, features[i].value, feats); } + hb_direction_t direction = buffer->props.direction; + hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script); + /* TODO vertical: + * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType + * Ogham fonts are supposed to be implemented BTT or not. Need to research that + * first. */ + if ((HB_DIRECTION_IS_HORIZONTAL (direction) && + direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) || + (HB_DIRECTION_IS_VERTICAL (direction) && + direction != HB_DIRECTION_TTB)) + { + hb_buffer_reverse_clusters (buffer); + direction = HB_DIRECTION_REVERSE (direction); + } + gr_segment *seg = nullptr; const gr_slot *is; unsigned int ci = 0, ic = 0; @@ -261,21 +276,11 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, for (unsigned int i = 0; i < buffer->len; ++i) chars[i] = buffer->info[i].codepoint; - /* TODO ensure_native_direction. */ - - hb_tag_t script_tag[HB_OT_MAX_TAGS_PER_SCRIPT]; - unsigned int count = HB_OT_MAX_TAGS_PER_SCRIPT; - hb_ot_tags_from_script_and_language (hb_buffer_get_script (buffer), - HB_LANGUAGE_INVALID, - &count, - script_tag, - nullptr, nullptr); - seg = gr_make_seg (nullptr, grface, - count ? script_tag[count - 1] : HB_OT_TAG_DEFAULT_SCRIPT, + HB_TAG_NONE, // https://github.com/harfbuzz/harfbuzz/issues/3439#issuecomment-1442650148 feats, gr_utf32, chars, buffer->len, - 2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0)); + 2 | (direction == HB_DIRECTION_RTL ? 1 : 0)); if (unlikely (!seg)) { if (feats) gr_featureval_destroy (feats); @@ -327,7 +332,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, float yscale = (float) font->y_scale / upem; yscale *= yscale / xscale; unsigned int curradv = 0; - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) { curradv = gr_slot_origin_X(gr_seg_first_slot(seg)) * xscale; clusters[0].advance = gr_seg_advance_X(seg) * xscale - curradv; @@ -356,16 +361,17 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, c->num_chars = before - c->base_char; c->base_glyph = ic; c->num_glyphs = 0; - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) { c->advance = curradv - gr_slot_origin_X(is) * xscale; curradv -= c->advance; } else { + auto origin_X = gr_slot_origin_X (is) * xscale; c->advance = 0; - clusters[ci].advance += gr_slot_origin_X(is) * xscale - curradv; - curradv += clusters[ci].advance; + clusters[ci].advance += origin_X - curradv; + curradv = origin_X; } ci++; } @@ -375,7 +381,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, clusters[ci].num_chars = after + 1 - clusters[ci].base_char; } - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) clusters[ci].advance += curradv; else clusters[ci].advance += gr_seg_advance_X(seg) * xscale - curradv; @@ -397,7 +403,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, unsigned int currclus = UINT_MAX; const hb_glyph_info_t *info = buffer->info; hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, nullptr); - if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (!HB_DIRECTION_IS_BACKWARD (direction)) { curradvx = 0; for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is)) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh index b123b2f27cf..61e05180be4 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh @@ -63,6 +63,7 @@ struct hb_iter_t static constexpr bool is_iterator = true; static constexpr bool is_random_access_iterator = false; static constexpr bool is_sorted_iterator = false; + static constexpr bool has_fast_len = false; // Should be checked in combination with is_random_access_iterator. private: /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ @@ -393,7 +394,7 @@ struct hb_map_iter_t : private: Iter it; - hb_reference_wrapper<Proj> f; + mutable hb_reference_wrapper<Proj> f; }; template <typename Proj, hb_function_sortedness_t Sorted> @@ -456,8 +457,8 @@ struct hb_filter_iter_t : private: Iter it; - hb_reference_wrapper<Pred> p; - hb_reference_wrapper<Proj> f; + mutable hb_reference_wrapper<Pred> p; + mutable hb_reference_wrapper<Proj> f; }; template <typename Pred, typename Proj> struct hb_filter_iter_factory_t @@ -841,7 +842,7 @@ struct template <typename Iterable, hb_requires (hb_is_iterable (Iterable))> auto operator () (Iterable&& it, unsigned count) const HB_AUTO_RETURN - ( hb_zip (hb_range (count), it) | hb_map (hb_second) ) + ( hb_zip (hb_range (count), it) | hb_map_retains_sorting (hb_second) ) /* Specialization arrays. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh index 9ea945caed6..9ac744c9ddc 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh @@ -53,7 +53,7 @@ struct hb_kern_machine_t return; buffer->unsafe_to_concat (); - OT::hb_ot_apply_context_t c (1, font, buffer); + OT::hb_ot_apply_context_t c (1, font, buffer, hb_blob_get_empty ()); c.set_lookup_mask (kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); auto &skippy_iter = c.iter_input; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-limits.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-limits.hh index 0f60e9e2101..c503b30652b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-limits.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-limits.hh @@ -89,6 +89,10 @@ #endif +#ifndef HB_GLYF_VAR_COMPOSITE_MAX_AXES +#define HB_GLYF_VAR_COMPOSITE_MAX_AXES 4096 +#endif + #ifndef HB_GLYF_MAX_POINTS #define HB_GLYF_MAX_POINTS 20000 #endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh index 1084725af2a..cde1e99d6f3 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh @@ -131,6 +131,10 @@ static inline Type& StructAfter(TObject &X) unsigned int get_size () const { return (size - (array).min_size + (array).get_size ()); } \ DEFINE_SIZE_ARRAY(size, array) +#define DEFINE_SIZE_MAX(size) \ + DEFINE_INSTANCE_ASSERTION (sizeof (*this) <= (size)) \ + static constexpr unsigned max_size = (size) + /* @@ -180,6 +184,9 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData> hb_lazy_loader_t<Returned,Subclass,Data,WheresData,Stored> >::value Funcs; + hb_lazy_loader_t () = default; + hb_lazy_loader_t (const hb_lazy_loader_t &other) = delete; + void init0 () {} /* Init, when memory is already set to 0. No-op for us. */ void init () { instance.set_relaxed (nullptr); } void fini () { do_destroy (instance.get_acquire ()); init (); } @@ -278,7 +285,11 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData> template <typename T, unsigned int WheresFace> struct hb_face_lazy_loader_t : hb_lazy_loader_t<T, hb_face_lazy_loader_t<T, WheresFace>, - hb_face_t, WheresFace> {}; + hb_face_t, WheresFace> +{ + // Hack; have them here for API parity with hb_table_lazy_loader_t + hb_blob_t *get_blob () { return this->get ()->get_blob (); } +}; template <typename T, unsigned int WheresFace, bool core=false> struct hb_table_lazy_loader_t : hb_lazy_loader_t<T, @@ -288,7 +299,7 @@ struct hb_table_lazy_loader_t : hb_lazy_loader_t<T, { static hb_blob_t *create (hb_face_t *face) { - auto c = hb_sanitize_context_t (); + hb_sanitize_context_t c; if (core) c.set_num_glyphs (0); // So we don't recurse ad infinitum, or doesn't need num_glyphs return c.reference_table<T> (face); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h index e928628fa7a..0ae171714ec 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h @@ -44,7 +44,7 @@ HB_BEGIN_DECLS * * Since: 1.7.7 */ -#define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1) +#define HB_MAP_VALUE_INVALID HB_CODEPOINT_INVALID /** * hb_map_t: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh index c685a9a3e13..e8abeec6367 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh @@ -45,9 +45,9 @@ struct hb_hashmap_t hb_hashmap_t () { init (); } ~hb_hashmap_t () { fini (); } - hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (o.population); hb_copy (o, *this); } + hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { alloc (o.population); hb_copy (o, *this); } hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); } - hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); resize (o.population); hb_copy (o, *this); return *this; } + hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); alloc (o.population); hb_copy (o, *this); return *this; } hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; } hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t () @@ -60,29 +60,28 @@ struct hb_hashmap_t hb_hashmap_t (const Iterable &o) : hb_hashmap_t () { auto iter = hb_iter (o); - if (iter.is_random_access_iterator) - resize (hb_len (iter)); + if (iter.is_random_access_iterator || iter.has_fast_len) + alloc (hb_len (iter)); hb_copy (iter, *this); } struct item_t { K key; - uint32_t hash : 30; + uint32_t is_real_ : 1; uint32_t is_used_ : 1; - uint32_t is_tombstone_ : 1; + uint32_t hash : 30; V value; item_t () : key (), + is_real_ (false), is_used_ (false), hash (0), - is_used_ (false), is_tombstone_ (false), value () {} bool is_used () const { return is_used_; } void set_used (bool is_used) { is_used_ = is_used; } - bool is_tombstone () const { return is_tombstone_; } - void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; } - bool is_real () const { return is_used_ && !is_tombstone_; } + void set_real (bool is_real) { is_real_ = is_real; } + bool is_real () const { return is_real_; } template <bool v = minus_one, hb_enable_if (v == false)> @@ -98,10 +97,15 @@ struct hb_hashmap_t bool operator == (const K &o) const { return hb_deref (key) == hb_deref (o); } bool operator == (const item_t &o) const { return *this == o.key; } hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); } - hb_pair_t<const K &, const V &> get_pair_ref() const { return hb_pair_t<const K &, const V &> (key, value); } + hb_pair_t<const K &, V &> get_pair_ref() { return hb_pair_t<const K &, V &> (key, value); } uint32_t total_hash () const { return (hash * 31) + hb_hash (value); } + + static constexpr bool is_trivial = std::is_trivially_constructible<K>::value && + std::is_trivially_destructible<K>::value && + std::is_trivially_constructible<V>::value && + std::is_trivially_destructible<V>::value; }; hb_object_header_t header; @@ -110,6 +114,7 @@ struct hb_hashmap_t unsigned int occupancy; /* Including tombstones. */ unsigned int mask; unsigned int prime; + unsigned int max_chain_length; item_t *items; friend void swap (hb_hashmap_t& a, hb_hashmap_t& b) @@ -123,6 +128,7 @@ struct hb_hashmap_t hb_swap (a.occupancy, b.occupancy); hb_swap (a.mask, b.mask); hb_swap (a.prime, b.prime); + hb_swap (a.max_chain_length, b.max_chain_length); hb_swap (a.items, b.items); } void init () @@ -133,16 +139,19 @@ struct hb_hashmap_t population = occupancy = 0; mask = 0; prime = 0; + max_chain_length = 0; items = nullptr; } void fini () { hb_object_fini (this); - if (likely (items)) { + if (likely (items)) + { unsigned size = mask + 1; - for (unsigned i = 0; i < size; i++) - items[i].~item_t (); + if (!item_t::is_trivial) + for (unsigned i = 0; i < size; i++) + items[i].~item_t (); hb_free (items); items = nullptr; } @@ -157,7 +166,7 @@ struct hb_hashmap_t bool in_error () const { return !successful; } - bool resize (unsigned new_population = 0) + bool alloc (unsigned new_population = 0) { if (unlikely (!successful)) return false; @@ -171,8 +180,11 @@ struct hb_hashmap_t successful = false; return false; } - for (auto &_ : hb_iter (new_items, new_size)) - new (&_) item_t (); + if (!item_t::is_trivial) + for (auto &_ : hb_iter (new_items, new_size)) + new (&_) item_t (); + else + hb_memset (new_items, 0, (size_t) new_size * sizeof (item_t)); unsigned int old_size = size (); item_t *old_items = items; @@ -181,6 +193,7 @@ struct hb_hashmap_t population = occupancy = 0; mask = new_size - 1; prime = prime_for (power); + max_chain_length = power * 2; items = new_items; /* Insert back old items. */ @@ -192,7 +205,8 @@ struct hb_hashmap_t old_items[i].hash, std::move (old_items[i].value)); } - old_items[i].~item_t (); + if (!item_t::is_trivial) + old_items[i].~item_t (); } hb_free (old_items); @@ -201,72 +215,124 @@ struct hb_hashmap_t } template <typename KK, typename VV> - bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool is_delete=false) + bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool overwrite = true) { if (unlikely (!successful)) return false; - if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; - item_t &item = item_for_hash (key, hash); + if (unlikely ((occupancy + occupancy / 2) >= mask && !alloc ())) return false; + + hash &= 0x3FFFFFFF; // We only store lower 30bit of hash + unsigned int tombstone = (unsigned int) -1; + unsigned int i = hash % prime; + unsigned length = 0; + unsigned step = 0; + while (items[i].is_used ()) + { + if ((std::is_integral<K>::value || items[i].hash == hash) && + items[i] == key) + { + if (!overwrite) + return false; + else + break; + } + if (!items[i].is_real () && tombstone == (unsigned) -1) + tombstone = i; + i = (i + ++step) & mask; + length++; + } - if (is_delete && !(item == key)) - return true; /* Trying to delete non-existent key. */ + item_t &item = items[tombstone == (unsigned) -1 ? i : tombstone]; if (item.is_used ()) { occupancy--; - if (!item.is_tombstone ()) - population--; + population -= item.is_real (); } item.key = std::forward<KK> (key); item.value = std::forward<VV> (value); item.hash = hash; item.set_used (true); - item.set_tombstone (is_delete); + item.set_real (true); occupancy++; - if (!is_delete) - population++; + population++; + + if (unlikely (length > max_chain_length) && occupancy * 8 > mask) + alloc (mask - 8); // This ensures we jump to next larger size return true; } template <typename VV> - bool set (const K &key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); } + bool set (const K &key, VV&& value, bool overwrite = true) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value), overwrite); } template <typename VV> - bool set (K &&key, VV&& value) { return set_with_hash (std::move (key), hb_hash (key), std::forward<VV> (value)); } + bool set (K &&key, VV&& value, bool overwrite = true) + { + uint32_t hash = hb_hash (key); + return set_with_hash (std::move (key), hash, std::forward<VV> (value), overwrite); + } const V& get_with_hash (const K &key, uint32_t hash) const { - if (unlikely (!items)) return item_t::default_value (); - auto &item = item_for_hash (key, hash); - return item.is_real () && item == key ? item.value : item_t::default_value (); + if (!items) return item_t::default_value (); + auto *item = fetch_item (key, hb_hash (key)); + if (item) + return item->value; + return item_t::default_value (); } const V& get (const K &key) const { - if (unlikely (!items)) return item_t::default_value (); + if (!items) return item_t::default_value (); return get_with_hash (key, hb_hash (key)); } - void del (const K &key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); } + void del (const K &key) + { + if (!items) return; + auto *item = fetch_item (key, hb_hash (key)); + if (item) + { + item->set_real (false); + population--; + } + } /* Has interface. */ const V& operator [] (K k) const { return get (k); } template <typename VV=V> - bool has (K key, VV **vp = nullptr) const + bool has (const K &key, VV **vp = nullptr) const { - if (unlikely (!items)) - return false; - auto &item = item_for_hash (key, hb_hash (key)); - if (item.is_real () && item == key) + if (!items) return false; + auto *item = fetch_item (key, hb_hash (key)); + if (item) { - if (vp) *vp = std::addressof (item.value); + if (vp) *vp = std::addressof (item->value); return true; } - else - return false; + return false; + } + item_t *fetch_item (const K &key, uint32_t hash) const + { + hash &= 0x3FFFFFFF; // We only store lower 30bit of hash + unsigned int i = hash % prime; + unsigned step = 0; + while (items[i].is_used ()) + { + if ((std::is_integral<K>::value || items[i].hash == hash) && + items[i] == key) + { + if (items[i].is_real ()) + return &items[i]; + else + return nullptr; + } + i = (i + ++step) & mask; + } + return nullptr; } /* Projection. */ - V operator () (K k) const { return get (k); } + const V& operator () (K k) const { return get (k); } unsigned size () const { return mask ? mask + 1 : 0; } @@ -393,24 +459,6 @@ struct hb_hashmap_t hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v) { set (std::move (v.first), std::move (v.second)); return *this; } - item_t& item_for_hash (const K &key, uint32_t hash) const - { - hash &= 0x3FFFFFFF; // We only store lower 30bit of hash - unsigned int i = hash % prime; - unsigned int step = 0; - unsigned int tombstone = (unsigned) -1; - while (items[i].is_used ()) - { - if ((hb_is_same (K, hb_codepoint_t) || items[i].hash == hash) && - items[i] == key) - return items[i]; - if (tombstone == (unsigned) -1 && items[i].is_tombstone ()) - tombstone = i; - i = (i + ++step) & mask; - } - return items[tombstone == (unsigned) -1 ? i : tombstone]; - } - static unsigned int prime_for (unsigned int shift) { /* Following comment and table copied from glib. */ @@ -481,7 +529,7 @@ struct hb_map_t : hb_hashmap_t<hb_codepoint_t, hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {} hb_map_t& operator= (const hb_map_t&) = default; hb_map_t& operator= (hb_map_t&&) = default; - hb_map_t (std::initializer_list<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> lst) : hashmap (lst) {} + hb_map_t (std::initializer_list<hb_codepoint_pair_t> lst) : hashmap (lst) {} template <typename Iterable, hb_requires (hb_is_iterable (Iterable))> hb_map_t (const Iterable &o) : hashmap (o) {} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh index 31aa7fa6f16..52ff4a84127 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh @@ -153,8 +153,8 @@ struct hb_reference_wrapper hb_reference_wrapper (T v) : v (v) {} bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } - operator T () const { return v; } - T get () const { return v; } + operator T& () { return v; } + T& get () { return v; } T v; }; template <typename T> @@ -163,8 +163,8 @@ struct hb_reference_wrapper<T&> hb_reference_wrapper (T& v) : v (std::addressof (v)) {} bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } - operator T& () const { return *v; } - T& get () const { return *v; } + operator T& () { return *v; } + T& get () { return *v; } T* v; }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-multimap.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-multimap.hh index b4a8cc62a3e..0184279c127 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-multimap.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-multimap.hh @@ -38,10 +38,10 @@ struct hb_multimap_t { void add (hb_codepoint_t k, hb_codepoint_t v) { - hb_codepoint_t *i; - if (multiples_indices.has (k, &i)) + hb_vector_t<hb_codepoint_t> *m; + if (multiples.has (k, &m)) { - multiples_values[*i].push (v); + m->push (v); return; } @@ -51,12 +51,7 @@ struct hb_multimap_t hb_codepoint_t old = *old_v; singulars.del (k); - multiples_indices.set (k, multiples_values.length); - auto *vec = multiples_values.push (); - - vec->push (old); - vec->push (v); - + multiples.set (k, hb_vector_t<hb_codepoint_t> {old, v}); return; } @@ -69,22 +64,31 @@ struct hb_multimap_t if (singulars.has (k, &v)) return hb_array (v, 1); - hb_codepoint_t *i; - if (multiples_indices.has (k, &i)) - return multiples_values[*i].as_array (); + hb_vector_t<hb_codepoint_t> *m; + if (multiples.has (k, &m)) + return m->as_array (); return hb_array_t<const hb_codepoint_t> (); } bool in_error () const { - return singulars.in_error () || multiples_indices.in_error () || multiples_values.in_error (); + if (singulars.in_error () || multiples.in_error ()) + return true; + for (const auto &m : multiples.values_ref ()) + if (m.in_error ()) + return true; + return false; + } + + void alloc (unsigned size) + { + singulars.alloc (size); } protected: hb_map_t singulars; - hb_map_t multiples_indices; - hb_vector_t<hb_vector_t<hb_codepoint_t>> multiples_values; + hb_hashmap_t<hb_codepoint_t, hb_vector_t<hb_codepoint_t>> multiples; }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh index 3da2d75ef5e..29825162832 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh @@ -49,6 +49,15 @@ using hb_has_min_size = _hb_has_min_size<T, void>; #define hb_has_min_size(T) hb_has_min_size<T>::value template <typename T, typename> +struct _hb_has_max_size : hb_false_type {}; +template <typename T> +struct _hb_has_max_size<T, hb_void_t<decltype (T::max_size)>> + : hb_true_type {}; +template <typename T> +using hb_has_max_size = _hb_has_max_size<T, void>; +#define hb_has_max_size(T) hb_has_max_size<T>::value + +template <typename T, typename> struct _hb_has_null_size : hb_false_type {}; template <typename T> struct _hb_has_null_size<T, hb_void_t<decltype (T::null_size)>> @@ -176,7 +185,7 @@ template <typename Type> static inline Type& Crap () { static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); Type *obj = reinterpret_cast<Type *> (_hb_CrapPool); - memcpy (obj, &Null (Type), sizeof (*obj)); + memcpy (obj, std::addressof (Null (Type)), sizeof (*obj)); return *obj; } template <typename QType> @@ -211,11 +220,11 @@ struct hb_nonnull_ptr_t T * operator = (T *v_) { return v = v_; } T * operator -> () const { return get (); } T & operator * () const { return *get (); } - T ** operator & () const { return &v; } + T ** operator & () const { return std::addressof (v); } /* Only auto-cast to const types. */ template <typename C> operator const C * () const { return get (); } operator const char * () const { return (const char *) get (); } - T * get () const { return v ? v : const_cast<T *> (&Null (T)); } + T * get () const { return v ? v : const_cast<T *> (std::addressof (Null (T))); } T * get_raw () const { return v; } private: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh index 13570a46e0c..04f144a72c7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh @@ -131,7 +131,7 @@ typedef struct OpenTypeOffsetTable sfnt_version = sfnt_tag; /* Take space for numTables, searchRange, entrySelector, RangeShift * and the TableRecords themselves. */ - unsigned num_items = it.len (); + unsigned num_items = hb_len (it); if (unlikely (!tables.serialize (c, num_items))) return_trace (false); const char *dir_end = (const char *) c->head; @@ -145,7 +145,7 @@ typedef struct OpenTypeOffsetTable unsigned len = blob->length; /* Allocate room for the table and copy it. */ - char *start = (char *) c->allocate_size<void> (len); + char *start = (char *) c->allocate_size<void> (len, false); if (unlikely (!start)) return false; TableRecord &rec = tables.arrayZ[i]; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh index 4c9bfebcec1..6d464a3535e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh @@ -312,6 +312,8 @@ struct _hb_has_null<Type, true> template <typename Type, typename OffsetType, bool has_null=true> struct OffsetTo : Offset<OffsetType, has_null> { + using target_t = Type; + // Make sure Type is not unbounded; works only for types that are fully defined at OffsetTo time. static_assert (has_null == false || (hb_has_null_size (Type) || !hb_has_min_size (Type)), ""); @@ -416,12 +418,15 @@ struct OffsetTo : Offset<OffsetType, has_null> { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); - if (unlikely (this->is_null ())) return_trace (true); + //if (unlikely (this->is_null ())) return_trace (true); if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false); return_trace (true); } template <typename ...Ts> +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -462,24 +467,16 @@ struct UnsizedArrayOf HB_DELETE_CREATE_COPY_ASSIGN (UnsizedArrayOf); - const Type& operator [] (int i_) const + const Type& operator [] (unsigned int i) const { - unsigned int i = (unsigned int) i_; - const Type *p = &arrayZ[i]; - if (unlikely ((const void *) p < (const void *) arrayZ)) return Null (Type); /* Overflowed. */ - _hb_compiler_memory_r_barrier (); - return *p; + return arrayZ[i]; } - Type& operator [] (int i_) + Type& operator [] (unsigned int i) { - unsigned int i = (unsigned int) i_; - Type *p = &arrayZ[i]; - if (unlikely ((const void *) p < (const void *) arrayZ)) return Crap (Type); /* Overflowed. */ - _hb_compiler_memory_r_barrier (); - return *p; + return arrayZ[i]; } - unsigned int get_size (unsigned int len) const + static unsigned int get_size (unsigned int len) { return len * Type::static_size; } template <typename T> operator T * () { return arrayZ; } @@ -533,6 +530,7 @@ struct UnsizedArrayOf } template <typename ...Ts> + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -720,7 +718,32 @@ struct ArrayOf return_trace (out); } + /* Special-case ArrayOf Offset16To structs with a maximum size. */ + template <typename T = Type, + typename Base = void, + hb_enable_if (hb_has_max_size (typename T::target_t) && + sizeof (T) == 2)> + HB_ALWAYS_INLINE + bool sanitize (hb_sanitize_context_t *c, const Base *base) const + { + TRACE_SANITIZE (this); + + if (unlikely (!sanitize_shallow (c))) return_trace (false); + + unsigned max_len = 65536 + Type::target_t::max_size; + + if (unlikely (c->check_range_fast (base, max_len))) + return_trace (true); + + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!c->dispatch (arrayZ[i], base))) + return_trace (false); + return_trace (true); + } + template <typename ...Ts> + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -736,7 +759,7 @@ struct ArrayOf bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (len.sanitize (c) && c->check_array (arrayZ, len)); + return_trace (len.sanitize (c) && c->check_array_sized (arrayZ, len, sizeof (LenType))); } public: @@ -797,7 +820,7 @@ template <typename Type> using List16OfOffset16To = List16OfOffsetTo<Type, HBUINT16>; /* An array starting at second element. */ -template <typename Type, typename LenType=HBUINT16> +template <typename Type, typename LenType> struct HeadlessArrayOf { static constexpr unsigned item_size = Type::static_size; @@ -861,6 +884,7 @@ struct HeadlessArrayOf } template <typename ...Ts> + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -878,7 +902,7 @@ struct HeadlessArrayOf { TRACE_SANITIZE (this); return_trace (lenP1.sanitize (c) && - (!lenP1 || c->check_array (arrayZ, lenP1 - 1))); + (!lenP1 || c->check_array_sized (arrayZ, lenP1 - 1, sizeof (LenType)))); } public: @@ -887,6 +911,7 @@ struct HeadlessArrayOf public: DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); }; +template <typename Type> using HeadlessArray16Of = HeadlessArrayOf<Type, HBUINT16>; /* An array storing length-1. */ template <typename Type, typename LenType=HBUINT16> @@ -912,6 +937,7 @@ struct ArrayOfM1 { return lenM1.static_size + (lenM1 + 1) * Type::static_size; } template <typename ...Ts> + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -929,7 +955,7 @@ struct ArrayOfM1 { TRACE_SANITIZE (this); return_trace (lenM1.sanitize (c) && - (c->check_array (arrayZ, lenM1 + 1))); + (c->check_array_sized (arrayZ, lenM1 + 1, sizeof (LenType)))); } public: @@ -1096,6 +1122,7 @@ struct VarSizedBinSearchArrayOf { return header.static_size + header.nUnits * header.unitSize; } template <typename ...Ts> + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh index f22824fc699..a2f90c8f5e2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh @@ -48,12 +48,24 @@ static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offs struct code_pair_t { - hb_codepoint_t code; + unsigned code; hb_codepoint_t glyph; }; + using str_buff_t = hb_vector_t<unsigned char>; using str_buff_vec_t = hb_vector_t<str_buff_t>; +using glyph_to_sid_map_t = hb_vector_t<code_pair_t>; + +struct length_f_t +{ + template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> + unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); } + + unsigned operator () (unsigned _) const { return _; } +} +HB_FUNCOBJ (length_f); /* CFF INDEX */ template <typename COUNT> @@ -62,42 +74,52 @@ struct CFFIndex unsigned int offset_array_size () const { return offSize * (count + 1); } - CFFIndex *copy (hb_serialize_context_t *c) const - { - TRACE_SERIALIZE (this); - unsigned int size = get_size (); - CFFIndex *out = c->allocate_size<CFFIndex> (size, false); - if (likely (out)) - hb_memcpy (out, this, size); - return_trace (out); - } - template <typename Iterable, hb_requires (hb_is_iterable (Iterable))> bool serialize (hb_serialize_context_t *c, - const Iterable &iterable) + const Iterable &iterable, + const unsigned *p_data_size = nullptr) { TRACE_SERIALIZE (this); + unsigned data_size; + if (p_data_size) + data_size = *p_data_size; + else + total_size (iterable, &data_size); + auto it = hb_iter (iterable); - serialize_header(c, + it | hb_map (hb_iter) | hb_map (hb_len)); + if (unlikely (!serialize_header (c, +it, data_size))) return_trace (false); + unsigned char *ret = c->allocate_size<unsigned char> (data_size, false); + if (unlikely (!ret)) return_trace (false); for (const auto &_ : +it) - hb_iter (_).copy (c); + { + unsigned len = _.length; + if (len <= 1) + { + if (!len) + continue; + *ret++ = *_.arrayZ; + continue; + } + hb_memcpy (ret, _.arrayZ, len); + ret += len; + } return_trace (true); } template <typename Iterator, hb_requires (hb_is_iterator (Iterator))> bool serialize_header (hb_serialize_context_t *c, - Iterator it) + Iterator it, + unsigned data_size) { TRACE_SERIALIZE (this); - unsigned total = + it | hb_reduce (hb_add, 0); - unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; + unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8; /* serialize CFFIndex header */ if (unlikely (!c->extend_min (this))) return_trace (false); - this->count = it.len (); + this->count = hb_len (it); if (!this->count) return_trace (true); if (unlikely (!c->extend (this->offSize))) return_trace (false); this->offSize = off_size; @@ -106,25 +128,88 @@ struct CFFIndex /* serialize indices */ unsigned int offset = 1; - unsigned int i = 0; - for (unsigned _ : +it) + if (HB_OPTIMIZE_SIZE_VAL) { - set_offset_at (i++, offset); - offset += _; + unsigned int i = 0; + for (const auto &_ : +it) + { + set_offset_at (i++, offset); + offset += length_f (_); + } + set_offset_at (i, offset); } - set_offset_at (i, offset); - + else + switch (off_size) + { + case 1: + { + HBUINT8 *p = (HBUINT8 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + case 2: + { + HBUINT16 *p = (HBUINT16 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + case 3: + { + HBUINT24 *p = (HBUINT24 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + case 4: + { + HBUINT32 *p = (HBUINT32 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + default: + break; + } + + assert (offset == data_size + 1); return_trace (true); } template <typename Iterable, hb_requires (hb_is_iterable (Iterable))> - static unsigned total_size (const Iterable &iterable) + static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr) { - auto it = + hb_iter (iterable) | hb_map (hb_iter) | hb_map (hb_len); - if (!it) return 0; + auto it = + hb_iter (iterable); + if (!it) + { + if (data_size) *data_size = 0; + return min_size; + } + + unsigned total = 0; + for (const auto &_ : +it) + total += length_f (_); + + if (data_size) *data_size = total; - unsigned total = + it | hb_reduce (hb_add, 0); unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total; @@ -133,13 +218,16 @@ struct CFFIndex void set_offset_at (unsigned int index, unsigned int offset) { assert (index <= count); - HBUINT8 *p = offsets + offSize * index + offSize; + unsigned int size = offSize; - for (; size; size--) + const HBUINT8 *p = offsets; + switch (size) { - --p; - *p = offset & 0xFF; - offset >>= 8; + case 1: ((HBUINT8 *) p)[index] = offset; break; + case 2: ((HBUINT16 *) p)[index] = offset; break; + case 3: ((HBUINT24 *) p)[index] = offset; break; + case 4: ((HBUINT32 *) p)[index] = offset; break; + default: return; } } @@ -149,37 +237,30 @@ struct CFFIndex assert (index <= count); unsigned int size = offSize; - const HBUINT8 *p = offsets + size * index; + const HBUINT8 *p = offsets; switch (size) { - case 1: return * (HBUINT8 *) p; - case 2: return * (HBUINT16 *) p; - case 3: return * (HBUINT24 *) p; - case 4: return * (HBUINT32 *) p; + case 1: return ((HBUINT8 *) p)[index]; + case 2: return ((HBUINT16 *) p)[index]; + case 3: return ((HBUINT24 *) p)[index]; + case 4: return ((HBUINT32 *) p)[index]; default: return 0; } } - unsigned int length_at (unsigned int index) const - { - unsigned offset0 = offset_at (index); - unsigned offset1 = offset_at (index + 1); - if (unlikely (offset1 < offset0 || offset1 > offset_at (count))) - return 0; - return offset1 - offset0; - } - const unsigned char *data_base () const - { return (const unsigned char *) this + min_size + offSize.static_size + offset_array_size (); } + { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); } public: hb_ubytes_t operator [] (unsigned int index) const { if (unlikely (index >= count)) return hb_ubytes_t (); _hb_compiler_memory_r_barrier (); - unsigned length = length_at (index); - if (unlikely (!length)) return hb_ubytes_t (); - return hb_ubytes_t (data_base () + offset_at (index) - 1, length); + unsigned offset0 = offset_at (index); + unsigned offset1 = offset_at (index + 1); + if (unlikely (offset1 < offset0 || offset1 > offset_at (count))) + return hb_ubytes_t (); + return hb_ubytes_t (data_base () + offset0, offset1 - offset0); } unsigned int get_size () const @@ -197,7 +278,7 @@ struct CFFIndex (count < count + 1u && c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 && c->check_array (offsets, offSize, count + 1u) && - c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count) - 1))))); + c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count)))))); } public: @@ -211,47 +292,6 @@ struct CFFIndex DEFINE_SIZE_MIN (COUNT::static_size); }; -template <typename COUNT, typename TYPE> -struct CFFIndexOf : CFFIndex<COUNT> -{ - template <typename DATA, typename PARAM1, typename PARAM2> - bool serialize (hb_serialize_context_t *c, - unsigned int offSize_, - const DATA *dataArray, - unsigned int dataArrayLen, - const hb_vector_t<unsigned int> &dataSizeArray, - const PARAM1 ¶m1, - const PARAM2 ¶m2) - { - TRACE_SERIALIZE (this); - /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (this))) return_trace (false); - this->count = dataArrayLen; - this->offSize = offSize_; - if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1), false))) - return_trace (false); - - /* serialize indices */ - unsigned int offset = 1; - unsigned int i = 0; - for (; i < dataArrayLen; i++) - { - this->set_offset_at (i, offset); - offset += dataSizeArray[i]; - } - this->set_offset_at (i, offset); - - /* serialize data */ - for (unsigned int i = 0; i < dataArrayLen; i++) - { - TYPE *dest = c->start_embed<TYPE> (); - if (unlikely (!dest || !dest->serialize (c, dataArray[i], param1, param2))) - return_trace (false); - } - return_trace (true); - } -}; - /* Top Dict, Font Dict, Private Dict */ struct Dict : UnsizedByteStr { @@ -327,7 +367,7 @@ struct table_info_t }; template <typename COUNT> -struct FDArray : CFFIndexOf<COUNT, FontDict> +struct FDArray : CFFIndex<COUNT> { template <typename DICTVAL, typename INFO, typename Iterator, typename OP_SERIALIZER> bool serialize (hb_serialize_context_t *c, @@ -338,7 +378,11 @@ struct FDArray : CFFIndexOf<COUNT, FontDict> /* serialize INDEX data */ hb_vector_t<unsigned> sizes; + if (it.is_random_access_iterator) + sizes.alloc (hb_len (it)); + c->push (); + char *data_base = c->head; + it | hb_map ([&] (const hb_pair_t<const DICTVAL&, const INFO&> &_) { @@ -348,10 +392,16 @@ struct FDArray : CFFIndexOf<COUNT, FontDict> }) | hb_sink (sizes) ; + unsigned data_size = c->head - data_base; c->pop_pack (false); + if (unlikely (sizes.in_error ())) return_trace (false); + + /* It just happens that the above is packed right after the header below. + * Such a hack. */ + /* serialize INDEX header */ - return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes))); + return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes), data_size)); } }; @@ -368,8 +418,11 @@ struct FDSelect0 { return_trace (true); } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const - { return (hb_codepoint_t) fds[glyph]; } + unsigned get_fd (hb_codepoint_t glyph) const + { return fds[glyph]; } + + hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const + { return {fds[glyph], glyph + 1}; } unsigned int get_size (unsigned int num_glyphs) const { return HBUINT8::static_size * num_glyphs; } @@ -427,12 +480,20 @@ struct FDSelect3_4 return +1; } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const + unsigned get_fd (hb_codepoint_t glyph) const { auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range); return range ? range->fd : ranges[nRanges () - 1].fd; } + hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const + { + auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range); + unsigned fd = range ? range->fd : ranges[nRanges () - 1].fd; + hb_codepoint_t end = range ? range[1].first : ranges[nRanges () - 1].first; + return {fd, end}; + } + GID_TYPE &nRanges () { return ranges.len; } GID_TYPE nRanges () const { return ranges.len; } GID_TYPE &sentinel () { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); } @@ -469,7 +530,7 @@ struct FDSelect } } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const + unsigned get_fd (hb_codepoint_t glyph) const { if (this == &Null (FDSelect)) return 0; @@ -480,6 +541,18 @@ struct FDSelect default:return 0; } } + /* Returns pair of fd and one after last glyph in range. */ + hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const + { + if (this == &Null (FDSelect)) return {0, 1}; + + switch (format) + { + case 0: return u.format0.get_fd_range (glyph); + case 3: return u.format3.get_fd_range (glyph); + default:return {0, 1}; + } + } bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc index 5040c746234..66df28aae1d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc @@ -574,11 +574,11 @@ bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h struct get_seac_param_t { - get_seac_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) {} + get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {} bool has_seac () const { return base && accent; } - const OT::cff1::accelerator_t *cff; + const OT::cff1::accelerator_subset_t *cff; hb_codepoint_t base = 0; hb_codepoint_t accent = 0; }; @@ -596,7 +596,7 @@ struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_par } }; -bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const +bool OT::cff1::accelerator_subset_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const { if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh index 4d0a965eee9..3d658ac626d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh @@ -28,7 +28,7 @@ #define HB_OT_CFF1_TABLE_HH #include "hb-ot-cff-common.hh" -#include "hb-subset-cff1.hh" +#include "hb-subset-cff-common.hh" #include "hb-draw.hh" #include "hb-paint.hh" @@ -52,7 +52,6 @@ enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 }; enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 }; typedef CFFIndex<HBUINT16> CFF1Index; -template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {}; typedef CFFIndex<HBUINT16> CFF1Index; typedef CFF1Index CFF1CharStrings; @@ -110,6 +109,7 @@ struct Encoding1 { hb_codepoint_t get_code (hb_codepoint_t glyph) const { + /* TODO: Add cache like get_sid. */ assert (glyph > 0); glyph--; for (unsigned int i = 0; i < nRanges (); i++) @@ -173,11 +173,7 @@ struct Encoding bool serialize (hb_serialize_context_t *c, const Encoding &src) { TRACE_SERIALIZE (this); - unsigned int size = src.get_size (); - Encoding *dest = c->allocate_size<Encoding> (size); - if (unlikely (!dest)) return_trace (false); - hb_memcpy (dest, &src, size); - return_trace (true); + return_trace (c->embed (src)); } /* serialize a subset Encoding */ @@ -312,26 +308,29 @@ struct Encoding }; /* Charset */ -struct Charset0 { - bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const +struct Charset0 +{ + bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c)); + if (num_charset_entries) *num_charset_entries = num_glyphs; + return_trace (sids.sanitize (c, num_glyphs - 1)); } hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const { if (unlikely (glyph >= num_glyphs)) return 0; - if (glyph == 0) + if (unlikely (glyph == 0)) return 0; else return sids[glyph - 1]; } - void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const { + mapping->resize (num_glyphs, false); for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++) - mapping->set (gid, sids[gid - 1]); + mapping->arrayZ[gid] = {sids[gid - 1], gid}; } hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const @@ -347,13 +346,13 @@ struct Charset0 { return 0; } - unsigned int get_size (unsigned int num_glyphs) const + static unsigned int get_size (unsigned int num_glyphs) { assert (num_glyphs > 0); - return HBUINT16::static_size * (num_glyphs - 1); + return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1); } - HBUINT16 sids[HB_VAR_ARRAY]; + UnsizedArrayOf<HBUINT16> sids; DEFINE_SIZE_ARRAY(0, sids); }; @@ -374,38 +373,62 @@ struct Charset_Range { template <typename TYPE> struct Charset1_2 { - bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const + bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); num_glyphs--; - for (unsigned int i = 0; num_glyphs > 0; i++) + unsigned i; + for (i = 0; num_glyphs > 0; i++) { if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1))) return_trace (false); num_glyphs -= (ranges[i].nLeft + 1); } + if (num_charset_entries) + *num_charset_entries = i; return_trace (true); } - hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs, + code_pair_t *cache = nullptr) const { if (unlikely (glyph >= num_glyphs)) return 0; - if (glyph == 0) return 0; - glyph--; - for (unsigned int i = 0;; i++) + unsigned i; + hb_codepoint_t start_glyph; + if (cache && likely (cache->glyph <= glyph)) { - if (glyph <= ranges[i].nLeft) - return (hb_codepoint_t) ranges[i].first + glyph; - glyph -= (ranges[i].nLeft + 1); + i = cache->code; + start_glyph = cache->glyph; + } + else + { + if (unlikely (glyph == 0)) return 0; + i = 0; + start_glyph = 1; + } + glyph -= start_glyph; + for (;; i++) + { + unsigned count = ranges[i].nLeft; + if (glyph <= count) + { + if (cache) + *cache = {i, start_glyph}; + return ranges[i].first + glyph; + } + count++; + start_glyph += count; + glyph -= count; } return 0; } - void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const { + mapping->resize (num_glyphs, false); hb_codepoint_t gid = 1; if (gid >= num_glyphs) return; @@ -413,8 +436,9 @@ struct Charset1_2 { { hb_codepoint_t sid = ranges[i].first; unsigned count = ranges[i].nLeft + 1; + unsigned last = gid + count; for (unsigned j = 0; j < count; j++) - mapping->set (gid++, sid++); + mapping->arrayZ[gid++] = {sid++, last - 1}; if (gid >= num_glyphs) break; @@ -439,21 +463,26 @@ struct Charset1_2 { unsigned int get_size (unsigned int num_glyphs) const { - unsigned int size = HBUINT8::static_size; - int glyph = (int)num_glyphs; + int glyph = (int) num_glyphs; + unsigned num_ranges = 0; assert (glyph > 0); glyph--; for (unsigned int i = 0; glyph > 0; i++) { glyph -= (ranges[i].nLeft + 1); - size += Charset_Range<TYPE>::static_size; + num_ranges++; } - return size; + return get_size_for_ranges (num_ranges); + } + + static unsigned int get_size_for_ranges (unsigned int num_ranges) + { + return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges); } - Charset_Range<TYPE> ranges[HB_VAR_ARRAY]; + UnsizedArrayOf<Charset_Range<TYPE>> ranges; DEFINE_SIZE_ARRAY (0, ranges); }; @@ -469,11 +498,7 @@ struct Charset bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs) { TRACE_SERIALIZE (this); - unsigned int size = src.get_size (num_glyphs); - Charset *dest = c->allocate_size<Charset> (size); - if (unlikely (!dest)) return_trace (false); - hb_memcpy (dest, &src, size); - return_trace (true); + return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs))); } /* serialize a subset Charset */ @@ -490,13 +515,13 @@ struct Charset { case 0: { - Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1)); + Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false); if (unlikely (!fmt0)) return_trace (false); unsigned int glyph = 0; for (unsigned int i = 0; i < sid_ranges.length; i++) { - hb_codepoint_t sid = sid_ranges[i].code; - for (int left = (int)sid_ranges[i].glyph; left >= 0; left--) + hb_codepoint_t sid = sid_ranges.arrayZ[i].code; + for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--) fmt0->sids[glyph++] = sid++; } } @@ -504,29 +529,35 @@ struct Charset case 1: { - Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length); + Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false); if (unlikely (!fmt1)) return_trace (false); + hb_codepoint_t all_glyphs = 0; for (unsigned int i = 0; i < sid_ranges.length; i++) { - if (unlikely (!(sid_ranges[i].glyph <= 0xFF))) - return_trace (false); - fmt1->ranges[i].first = sid_ranges[i].code; - fmt1->ranges[i].nLeft = sid_ranges[i].glyph; + auto &_ = sid_ranges.arrayZ[i]; + all_glyphs |= _.glyph; + fmt1->ranges[i].first = _.code; + fmt1->ranges[i].nLeft = _.glyph; } + if (unlikely (!(all_glyphs <= 0xFF))) + return_trace (false); } break; case 2: { - Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length); + Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false); if (unlikely (!fmt2)) return_trace (false); + hb_codepoint_t all_glyphs = 0; for (unsigned int i = 0; i < sid_ranges.length; i++) { - if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF))) - return_trace (false); - fmt2->ranges[i].first = sid_ranges[i].code; - fmt2->ranges[i].nLeft = sid_ranges[i].glyph; + auto &_ = sid_ranges.arrayZ[i]; + all_glyphs |= _.glyph; + fmt2->ranges[i].first = _.code; + fmt2->ranges[i].nLeft = _.glyph; } + if (unlikely (!(all_glyphs <= 0xFFFF))) + return_trace (false); } break; @@ -545,18 +576,19 @@ struct Charset } } - hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs, + code_pair_t *cache = nullptr) const { switch (format) { case 0: return u.format0.get_sid (glyph, num_glyphs); - case 1: return u.format1.get_sid (glyph, num_glyphs); - case 2: return u.format2.get_sid (glyph, num_glyphs); + case 1: return u.format1.get_sid (glyph, num_glyphs, cache); + case 2: return u.format2.get_sid (glyph, num_glyphs, cache); default:return 0; } } - void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const { switch (format) { @@ -578,7 +610,7 @@ struct Charset } } - bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) @@ -586,9 +618,9 @@ struct Charset switch (format) { - case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ())); - case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ())); - case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ())); + case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries)); + case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries)); + case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries)); default:return_trace (false); } } @@ -606,10 +638,10 @@ struct Charset struct CFF1StringIndex : CFF1Index { bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, - const hb_inc_bimap_t &sidmap) + const hb_vector_t<unsigned> &sidmap) { TRACE_SERIALIZE (this); - if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0))) + if (unlikely ((strings.count == 0) || (sidmap.length == 0))) { if (unlikely (!c->extend_min (this->count))) return_trace (false); @@ -617,15 +649,13 @@ struct CFF1StringIndex : CFF1Index return_trace (true); } - byte_str_array_t bytesArray; - if (!bytesArray.resize (sidmap.get_population ())) - return_trace (false); - for (unsigned int i = 0; i < strings.count; i++) - { - hb_codepoint_t j = sidmap[i]; - if (j != HB_MAP_VALUE_INVALID) - bytesArray[j] = strings[i]; - } + if (unlikely (sidmap.in_error ())) return_trace (false); + + // Save this in a vector since serialize() iterates it twice. + hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap) + | hb_map (strings)); + + if (unlikely (bytesArray.in_error ())) return_trace (false); bool result = CFF1Index::serialize (c, bytesArray); return_trace (result); @@ -932,7 +962,7 @@ struct cff1_private_dict_opset_t : dict_opset_t } }; -struct cff1_private_dict_opset_subset : dict_opset_t +struct cff1_private_dict_opset_subset_t : dict_opset_t { static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval) { @@ -978,7 +1008,7 @@ typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_t typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t; typedef CFF1Index CFF1NameIndex; -typedef CFF1IndexOf<TopDict> CFF1TopDictIndex; +typedef CFF1Index CFF1TopDictIndex; struct cff1_font_dict_values_mod_t { @@ -1031,8 +1061,10 @@ struct cff1 template <typename PRIVOPSET, typename PRIVDICTVAL> struct accelerator_templ_t { - void init (hb_face_t *face) + accelerator_templ_t (hb_face_t *face) { + if (!face) return; + topDict.init (); fontDicts.init (); privateDicts.init (); @@ -1046,22 +1078,22 @@ struct cff1 const OT::cff1 *cff = this->blob->template as<OT::cff1> (); if (cff == &Null (OT::cff1)) - { fini (); return; } + goto fail; nameIndex = &cff->nameIndex (cff); if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc)) - { fini (); return; } + goto fail; topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ()); if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0)) - { fini (); return; } + goto fail; { /* parse top dict */ const hb_ubytes_t topDictStr = (*topDictIndex)[0]; - if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!topDictStr.sanitize (&sc))) goto fail; cff1_top_dict_interp_env_t env (topDictStr); cff1_top_dict_interpreter_t top_interp (env); - if (unlikely (!top_interp.interpret (topDict))) { fini (); return; } + if (unlikely (!top_interp.interpret (topDict))) goto fail; } if (is_predef_charset ()) @@ -1069,7 +1101,7 @@ struct cff1 else { charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset); - if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; } + if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries))) goto fail; } fdCount = 1; @@ -1079,7 +1111,7 @@ struct cff1 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset); if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) || (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count))) - { fini (); return; } + goto fail; fdCount = fdArray->count; } @@ -1092,36 +1124,36 @@ struct cff1 encoding = &Null (Encoding); if (is_CID ()) { - if (unlikely (charset == &Null (Charset))) { fini (); return; } + if (unlikely (charset == &Null (Charset))) goto fail; } else { if (!is_predef_encoding ()) { encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset); - if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; } + if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) goto fail; } } stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ()); if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc)) - { fini (); return; } + goto fail; globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ()); if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc)) - { fini (); return; } + goto fail; charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset); if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc))) - { fini (); return; } + goto fail; num_glyphs = charStrings->count; if (num_glyphs != sc.get_num_glyphs ()) - { fini (); return; } + goto fail; if (unlikely (!privateDicts.resize (fdCount))) - { fini (); return; } + goto fail; for (unsigned int i = 0; i < fdCount; i++) privateDicts[i].init (); @@ -1131,27 +1163,27 @@ struct cff1 for (unsigned int i = 0; i < fdCount; i++) { hb_ubytes_t fontDictStr = (*fdArray)[i]; - if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; cff1_font_dict_values_t *font; cff1_top_dict_interp_env_t env (fontDictStr); cff1_font_dict_interpreter_t font_interp (env); font = fontDicts.push (); - if (unlikely (fontDicts.in_error ())) { fini (); return; } + if (unlikely (fontDicts.in_error ())) goto fail; font->init (); - if (unlikely (!font_interp.interpret (*font))) { fini (); return; } + if (unlikely (!font_interp.interpret (*font))) goto fail; PRIVDICTVAL *priv = &privateDicts[i]; const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!privDictStr.sanitize (&sc))) goto fail; num_interp_env_t env2 (privDictStr); dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2); priv->init (); - if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } + if (unlikely (!priv_interp.interpret (*priv))) goto fail; priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); if (priv->localSubrs != &Null (CFF1Subrs) && unlikely (!priv->localSubrs->sanitize (&sc))) - { fini (); return; } + goto fail; } } else /* non-CID */ @@ -1160,20 +1192,25 @@ struct cff1 PRIVDICTVAL *priv = &privateDicts[0]; const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!privDictStr.sanitize (&sc))) goto fail; num_interp_env_t env (privDictStr); dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env); priv->init (); - if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } + if (unlikely (!priv_interp.interpret (*priv))) goto fail; priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); if (priv->localSubrs != &Null (CFF1Subrs) && unlikely (!priv->localSubrs->sanitize (&sc))) - { fini (); return; } + goto fail; } - } - void fini () + return; + + fail: + _fini (); + } + ~accelerator_templ_t () { _fini (); } + void _fini () { sc.end_processing (); topDict.fini (); @@ -1183,6 +1220,8 @@ struct cff1 blob = nullptr; } + hb_blob_t *get_blob () const { return blob; } + bool is_valid () const { return blob; } bool is_CID () const { return topDict.is_CID (); } @@ -1203,13 +1242,14 @@ struct cff1 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } - hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const + hb_codepoint_t glyph_to_code (hb_codepoint_t glyph, + code_pair_t *glyph_to_sid_cache = nullptr) const { if (encoding != &Null (Encoding)) return encoding->get_code (glyph); else { - hb_codepoint_t sid = glyph_to_sid (glyph); + hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache); if (sid == 0) return 0; hb_codepoint_t code = 0; switch (topDict.EncodingOffset) @@ -1227,12 +1267,14 @@ struct cff1 } } - hb_map_t *create_glyph_to_sid_map () const + glyph_to_sid_map_t *create_glyph_to_sid_map () const { if (charset != &Null (Charset)) { - hb_map_t *mapping = hb_map_create (); - mapping->set (0, 0); + auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t)); + if (unlikely (!mapping)) return nullptr; + mapping = new (mapping) glyph_to_sid_map_t (); + mapping->push (code_pair_t {0, 1}); charset->collect_glyph_to_sid_map (mapping, num_glyphs); return mapping; } @@ -1240,10 +1282,11 @@ struct cff1 return nullptr; } - hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const + hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph, + code_pair_t *cache = nullptr) const { if (charset != &Null (Charset)) - return charset->get_sid (glyph, num_glyphs); + return charset->get_sid (glyph, num_glyphs, cache); else { hb_codepoint_t sid = 0; @@ -1312,19 +1355,17 @@ struct cff1 hb_vector_t<PRIVDICTVAL> privateDicts; unsigned int num_glyphs = 0; + unsigned int num_charset_entries = 0; }; struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> { - accelerator_t (hb_face_t *face) + accelerator_t (hb_face_t *face) : SUPER (face) { - SUPER::init (face); - glyph_names.set_relaxed (nullptr); if (!is_valid ()) return; if (is_CID ()) return; - } ~accelerator_t () { @@ -1334,8 +1375,6 @@ struct cff1 names->fini (); hb_free (names); } - - SUPER::fini (); } bool get_glyph_name (hb_codepoint_t glyph, @@ -1386,9 +1425,10 @@ struct cff1 /* TODO */ /* fill glyph names */ + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) { - hb_codepoint_t sid = glyph_to_sid (gid); + hb_codepoint_t sid = glyph_to_sid (gid, &glyph_to_sid_cache); gname_t gname; gname.sid = sid; if (sid < cff1_std_strings_length) @@ -1426,7 +1466,6 @@ struct cff1 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const; - HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; private: @@ -1453,9 +1492,24 @@ struct cff1 typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER; }; - struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {}; + struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> + { + accelerator_subset_t (hb_face_t *face) : SUPER (face) {} + ~accelerator_subset_t () + { + if (cff_accelerator) + cff_subset_accelerator_t::destroy (cff_accelerator); + } + + HB_INTERNAL bool subset (hb_subset_context_t *c) const; + HB_INTERNAL bool serialize (hb_serialize_context_t *c, + struct cff1_subset_plan &plan) const; + HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; + + mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr; - bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); } + typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER; + }; protected: HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid); @@ -1479,6 +1533,10 @@ struct cff1_accelerator_t : cff1::accelerator_t { cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {} }; +struct cff1_subset_accelerator_t : cff1::accelerator_subset_t { + cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF1_TABLE_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh index 2134d486603..9913cdad0c6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh @@ -28,7 +28,7 @@ #define HB_OT_CFF2_TABLE_HH #include "hb-ot-cff-common.hh" -#include "hb-subset-cff2.hh" +#include "hb-subset-cff-common.hh" #include "hb-draw.hh" #include "hb-paint.hh" @@ -41,7 +41,6 @@ namespace CFF { #define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2') typedef CFFIndex<HBUINT32> CFF2Index; -template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {}; typedef CFF2Index CFF2CharStrings; typedef Subrs<HBUINT32> CFF2Subrs; @@ -393,6 +392,8 @@ struct cff2 { accelerator_templ_t (hb_face_t *face) { + if (!face) return; + topDict.init (); fontDicts.init (); privateDicts.init (); @@ -464,7 +465,6 @@ struct cff2 goto fail; } - return; fail: @@ -481,11 +481,13 @@ struct cff2 blob = nullptr; } - hb_map_t *create_glyph_to_sid_map () const + hb_vector_t<uint16_t> *create_glyph_to_sid_map () const { return nullptr; } + hb_blob_t *get_blob () const { return blob; } + bool is_valid () const { return blob; } protected: @@ -518,9 +520,24 @@ struct cff2 HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; }; - typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t; + struct accelerator_subset_t : accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> + { + accelerator_subset_t (hb_face_t *face) : SUPER (face) {} + ~accelerator_subset_t () + { + if (cff_accelerator) + cff_subset_accelerator_t::destroy (cff_accelerator); + } - bool subset (hb_subset_context_t *c) const { return hb_subset_cff2 (c); } + HB_INTERNAL bool subset (hb_subset_context_t *c) const; + HB_INTERNAL bool serialize (hb_serialize_context_t *c, + struct cff2_subset_plan &plan, + hb_array_t<int> normalized_coords) const; + + mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr; + + typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> SUPER; + }; public: FixedVersion<HBUINT8> version; /* Version of CFF2 table. set to 0x0200u */ @@ -535,6 +552,10 @@ struct cff2_accelerator_t : cff2::accelerator_t { cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {} }; +struct cff2_subset_accelerator_t : cff2::accelerator_subset_t { + cff2_subset_accelerator_t (hb_face_t *face) : cff2::accelerator_subset_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF2_TABLE_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh index cf5ccd53e95..30401b1926e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh @@ -277,10 +277,10 @@ struct CmapSubtableFormat4 } } writer(c); - writer.end_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount); - c->allocate_size<HBUINT16> (2); // padding - writer.start_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount); - writer.id_delta_ = c->allocate_size<HBINT16> (HBINT16::static_size * segcount); + writer.end_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount, false); + (void) c->allocate_size<HBUINT16> (2); // padding + writer.start_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount, false); + writer.id_delta_ = c->allocate_size<HBINT16> (HBINT16::static_size * segcount, false); if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false; @@ -325,7 +325,7 @@ struct CmapSubtableFormat4 { auto format4_iter = + it - | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) + | hb_filter ([&] (const hb_codepoint_pair_t _) { return _.first <= 0xFFFF; }) ; @@ -335,7 +335,7 @@ struct CmapSubtableFormat4 if (unlikely (!c->extend_min (this))) return; this->format = 4; - hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> cp_to_gid { + hb_vector_t<hb_codepoint_pair_t> cp_to_gid { format4_iter }; @@ -757,8 +757,7 @@ struct CmapSubtableLongSegmented hb_codepoint_t gid = this->groups[i].glyphID; if (!gid) { - /* Intention is: if (hb_is_same (T, CmapSubtableFormat13)) continue; */ - if (! T::group_get_glyph (this->groups[i], end)) continue; + if (T::formatNumber == 13) continue; start++; gid++; } @@ -766,11 +765,13 @@ struct CmapSubtableLongSegmented if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs)) end = start + (hb_codepoint_t) num_glyphs - gid; + mapping->alloc (mapping->get_population () + end - start + 1); + for (unsigned cp = start; cp <= end; cp++) { unicodes->add (cp); mapping->set (cp, gid); - gid++; + gid += T::increment; } } } @@ -794,6 +795,9 @@ struct CmapSubtableLongSegmented struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12> { + static constexpr int increment = 1; + static constexpr int formatNumber = 12; + static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, hb_codepoint_t u) { return likely (group.startCharCode <= group.endCharCode) ? @@ -866,6 +870,9 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12> struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13> { + static constexpr int increment = 0; + static constexpr int formatNumber = 13; + static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, hb_codepoint_t u HB_UNUSED) { return group.glyphID; } @@ -917,8 +924,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange> DefaultUVS* copy (hb_serialize_context_t *c, const hb_set_t *unicodes) const { - DefaultUVS *out = c->start_embed<DefaultUVS> (); - if (unlikely (!out)) return nullptr; + auto *out = c->start_embed<DefaultUVS> (); auto snap = c->snapshot (); HBUINT32 len; @@ -931,8 +937,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange> hb_codepoint_t start = HB_SET_VALUE_INVALID; hb_codepoint_t end = HB_SET_VALUE_INVALID; - for (hb_codepoint_t u = HB_SET_VALUE_INVALID; - unicodes->next (&u);) + for (auto u : *unicodes) { if (!as_array ().bsearch (u)) continue; @@ -1067,9 +1072,7 @@ struct NonDefaultUVS : SortedArray32Of<UVSMapping> const hb_set_t *glyphs_requested, const hb_map_t *glyph_map) const { - NonDefaultUVS *out = c->start_embed<NonDefaultUVS> (); - if (unlikely (!out)) return nullptr; - + auto *out = c->start_embed<NonDefaultUVS> (); auto it = + as_array () | hb_filter ([&] (const UVSMapping& _) @@ -1767,7 +1770,6 @@ struct cmap TRACE_SUBSET (this); cmap *cmap_prime = c->serializer->start_embed<cmap> (); - if (unlikely (!c->serializer->check_success (cmap_prime))) return_trace (false); auto encodingrec_iter = + hb_iter (encodingRecord) @@ -1798,7 +1800,7 @@ struct cmap auto it = + c->plan->unicode_to_new_gid_list.iter () - | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) + | hb_filter ([&] (const hb_codepoint_pair_t _) { return (_.second != HB_MAP_VALUE_INVALID); }) ; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc index c89a1954a98..b3677c6a4c0 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc @@ -38,8 +38,8 @@ #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" -#include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" +#include "hb-ot-cff1-table.hh" #include "hb-ot-hmtx-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise. @@ -98,7 +98,7 @@ _hb_ot_font_create (hb_font_t *font) { cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t)); if (unlikely (!cmap_cache)) goto out; - cmap_cache->init (); + new (cmap_cache) hb_ot_font_cmap_cache_t (); if (unlikely (!hb_face_set_user_data (font->face, &hb_ot_font_cmap_cache_user_data_key, cmap_cache, @@ -230,8 +230,8 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, use_cache = false; goto out; } + new (cache) hb_ot_font_advance_cache_t; - cache->init (); if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache))) { hb_free (cache); @@ -255,7 +255,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, { /* Use cache. */ if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords) { - ot_font->advance_cache->init (); + ot_font->advance_cache->clear (); ot_font->cached_coords_serial.set_release (font->serial_coords); } @@ -436,8 +436,8 @@ hb_ot_get_glyph_extents (hb_font_t *font, #endif if (ot_face->glyf->get_extents (font, glyph, extents)) return true; #ifndef HB_NO_OT_FONT_CFF - if (ot_face->cff1->get_extents (font, glyph, extents)) return true; if (ot_face->cff2->get_extents (font, glyph, extents)) return true; + if (ot_face->cff1->get_extents (font, glyph, extents)) return true; #endif return false; @@ -525,8 +525,8 @@ hb_ot_draw_glyph (hb_font_t *font, embolden ? &outline : draw_data, font->slant_xy); if (!font->face->table.glyf->get_path (font, glyph, draw_session)) #ifndef HB_NO_CFF - if (!font->face->table.cff1->get_path (font, glyph, draw_session)) if (!font->face->table.cff2->get_path (font, glyph, draw_session)) + if (!font->face->table.cff1->get_path (font, glyph, draw_session)) #endif {} } @@ -565,8 +565,8 @@ hb_ot_paint_glyph (hb_font_t *font, #endif if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; #ifndef HB_NO_CFF - if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; + if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; #endif } #endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh index 3bfd75502a4..cbcf6f5f22f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh @@ -46,21 +46,23 @@ struct DeviceRecord template<typename Iterator, hb_requires (hb_is_iterator (Iterator))> - bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it) + bool serialize (hb_serialize_context_t *c, + unsigned pixelSize, + Iterator it, + const hb_vector_t<hb_codepoint_pair_t> new_to_old_gid_list, + unsigned num_glyphs) { TRACE_SERIALIZE (this); - unsigned length = it.len (); - - if (unlikely (!c->extend (this, length))) return_trace (false); + if (unlikely (!c->extend (this, num_glyphs))) return_trace (false); this->pixelSize = pixelSize; this->maxWidth = + it | hb_reduce (hb_max, 0u); - + it - | hb_sink (widthsZ.as_array (length)); + for (auto &_ : new_to_old_gid_list) + widthsZ[_.first] = *it++; return_trace (true); } @@ -89,7 +91,11 @@ struct hdmx template<typename Iterator, hb_requires (hb_is_iterator (Iterator))> - bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it) + bool serialize (hb_serialize_context_t *c, + unsigned version, + Iterator it, + const hb_vector_t<hb_codepoint_pair_t> &new_to_old_gid_list, + unsigned num_glyphs) { TRACE_SERIALIZE (this); @@ -97,10 +103,10 @@ struct hdmx this->version = version; this->numRecords = it.len (); - this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0); + this->sizeDeviceRecord = DeviceRecord::get_size (num_glyphs); for (const hb_item_type<Iterator>& _ : +it) - c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second); + c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second, new_to_old_gid_list, num_glyphs); return_trace (c->successful ()); } @@ -110,31 +116,30 @@ struct hdmx { TRACE_SUBSET (this); - hdmx *hdmx_prime = c->serializer->start_embed <hdmx> (); - if (unlikely (!hdmx_prime)) return_trace (false); + auto *hdmx_prime = c->serializer->start_embed <hdmx> (); + unsigned num_input_glyphs = get_num_glyphs (); auto it = + hb_range ((unsigned) numRecords) - | hb_map ([c, this] (unsigned _) + | hb_map ([c, num_input_glyphs, this] (unsigned _) { const DeviceRecord *device_record = &StructAtOffset<DeviceRecord> (&firstDeviceRecord, _ * sizeDeviceRecord); auto row = - + hb_range (c->plan->num_output_glyphs ()) - | hb_map (c->plan->reverse_glyph_map) - | hb_map ([this, c, device_record] (hb_codepoint_t _) + + hb_iter (c->plan->new_to_old_gid_list) + | hb_map ([num_input_glyphs, device_record] (hb_codepoint_pair_t _) { - if (c->plan->is_empty_glyph (_)) - return Null (HBUINT8); - return device_record->widthsZ.as_array (get_num_glyphs ()) [_]; + return device_record->widthsZ.as_array (num_input_glyphs) [_.second]; }) ; return hb_pair ((unsigned) device_record->pixelSize, +row); }) ; - hdmx_prime->serialize (c->serializer, version, it); + hdmx_prime->serialize (c->serializer, version, it, + c->plan->new_to_old_gid_list, + c->plan->num_output_glyphs ()); return_trace (true); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh index 835a1a585e8..fed6ca1c7a2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh @@ -83,7 +83,7 @@ struct hmtxvmtx bool subset_update_header (hb_subset_context_t *c, unsigned int num_hmetrics, const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map, - const hb_map_t *bounds_map) const + const hb_vector_t<unsigned> &bounds_vec) const { hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (c->plan->source, H::tableTag); hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob); @@ -114,6 +114,7 @@ struct hmtxvmtx HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET, caretOffset); } + bool empty = true; int min_lsb = 0x7FFF; int min_rsb = 0x7FFF; int max_extent = -0x7FFF; @@ -125,9 +126,10 @@ struct hmtxvmtx int lsb = _.second.second; max_adv = hb_max (max_adv, adv); - if (bounds_map->has (gid)) + if (bounds_vec[gid] != 0xFFFFFFFF) { - unsigned bound_width = bounds_map->get (gid); + empty = false; + unsigned bound_width = bounds_vec[gid]; int rsb = adv - lsb - bound_width; int extent = lsb + bound_width; min_lsb = hb_min (min_lsb, lsb); @@ -137,7 +139,7 @@ struct hmtxvmtx } table->advanceMax = max_adv; - if (!bounds_map->is_empty ()) + if (!empty) { table->minLeadingBearing = min_lsb; table->minTrailingBearing = min_rsb; @@ -156,32 +158,31 @@ struct hmtxvmtx hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, Iterator it, - unsigned num_long_metrics) + const hb_vector_t<hb_codepoint_pair_t> new_to_old_gid_list, + unsigned num_long_metrics, + unsigned total_num_metrics) { - unsigned idx = 0; - for (auto _ : it) + LongMetric* long_metrics = c->allocate_size<LongMetric> (num_long_metrics * LongMetric::static_size); + FWORD* short_metrics = c->allocate_size<FWORD> ((total_num_metrics - num_long_metrics) * FWORD::static_size); + if (!long_metrics || !short_metrics) return; + + short_metrics -= num_long_metrics; + + for (auto _ : new_to_old_gid_list) { - if (idx < num_long_metrics) - { - LongMetric lm; - lm.advance = _.first; - lm.sb = _.second; - if (unlikely (!c->embed<LongMetric> (&lm))) return; - } - else if (idx < 0x10000u) + hb_codepoint_t gid = _.first; + auto mtx = *it++; + + if (gid < num_long_metrics) { - FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size); - if (unlikely (!sb)) return; - *sb = _.second; + LongMetric& lm = long_metrics[gid]; + lm.advance = mtx.first; + lm.sb = mtx.second; } + else if (gid < 0x10000u) + short_metrics[gid] = mtx.second; else - { - // TODO: This does not do tail optimization. - UFWORD *adv = c->allocate_size<UFWORD> (UFWORD::static_size); - if (unlikely (!adv)) return; - *adv = _.first; - } - idx++; + ((UFWORD*) short_metrics)[gid] = mtx.first; } } @@ -189,8 +190,7 @@ struct hmtxvmtx { TRACE_SUBSET (this); - T *table_prime = c->serializer->start_embed <T> (); - if (unlikely (!table_prime)) return_trace (false); + auto *table_prime = c->serializer->start_embed <T> (); accelerator_t _mtx (c->plan->source); unsigned num_long_metrics; @@ -209,31 +209,36 @@ struct hmtxvmtx } auto it = - + hb_range (c->plan->num_output_glyphs ()) - | hb_map ([c, &_mtx, mtx_map] (unsigned _) + + hb_iter (c->plan->new_to_old_gid_list) + | hb_map ([c, &_mtx, mtx_map] (hb_codepoint_pair_t _) { - if (!mtx_map->has (_)) + hb_codepoint_t new_gid = _.first; + hb_codepoint_t old_gid = _.second; + + hb_pair_t<unsigned, int> *v = nullptr; + if (!mtx_map->has (new_gid, &v)) { - hb_codepoint_t old_gid; - if (!c->plan->old_gid_for_new_gid (_, &old_gid)) - return hb_pair (0u, 0); int lsb = 0; if (!_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb)) (void) _glyf_get_leading_bearing_without_var_unscaled (c->plan->source, old_gid, !T::is_horizontal, &lsb); return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb); } - return mtx_map->get (_); + return *v; }) ; - table_prime->serialize (c->serializer, it, num_long_metrics); + table_prime->serialize (c->serializer, + it, + c->plan->new_to_old_gid_list, + num_long_metrics, + c->plan->num_output_glyphs ()); if (unlikely (c->serializer->in_error ())) return_trace (false); // Amend header num hmetrics if (unlikely (!subset_update_header (c, num_long_metrics, mtx_map, - T::is_horizontal ? &c->plan->bounds_width_map : &c->plan->bounds_height_map))) + T::is_horizontal ? c->plan->bounds_width_vec : c->plan->bounds_height_vec))) return_trace (false); return_trace (true); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh index 8179e5acd52..2b7e9e4b184 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh @@ -170,8 +170,8 @@ struct FeatMinMaxRecord { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - minCoord.sanitize (c, this) && - maxCoord.sanitize (c, this))); + minCoord.sanitize (c, base) && + maxCoord.sanitize (c, base))); } protected: @@ -187,7 +187,6 @@ struct FeatMinMaxRecord * of MinMax table (may be NULL) */ public: DEFINE_SIZE_STATIC (8); - }; struct MinMax @@ -274,7 +273,7 @@ struct BaseLangSysRecord { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - minMax.sanitize (c, this))); + minMax.sanitize (c, base))); } protected: @@ -297,7 +296,8 @@ struct BaseScript const BaseCoord &get_base_coord (int baseline_tag_index) const { return (this+baseValues).get_base_coord (baseline_tag_index); } - bool has_data () const { return baseValues; } + bool has_values () const { return baseValues; } + bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ } bool sanitize (hb_sanitize_context_t *c) const { @@ -383,7 +383,7 @@ struct Axis const BaseCoord **coord) const { const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); - if (!base_script.has_data ()) + if (!base_script.has_values ()) { *coord = nullptr; return false; @@ -410,7 +410,7 @@ struct Axis const BaseCoord **max_coord) const { const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); - if (!base_script.has_data ()) + if (!base_script.has_min_max ()) { *min_coord = *max_coord = nullptr; return false; @@ -425,8 +425,8 @@ struct Axis { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - (this+baseTagList).sanitize (c) && - (this+baseScriptList).sanitize (c))); + baseTagList.sanitize (c, this) && + baseScriptList.sanitize (c, this))); } protected: @@ -473,14 +473,13 @@ struct BASE return true; } - /* TODO: Expose this separately sometime? */ bool get_min_max (hb_font_t *font, hb_direction_t direction, hb_tag_t script_tag, hb_tag_t language_tag, hb_tag_t feature_tag, hb_position_t *min, - hb_position_t *max) + hb_position_t *max) const { const BaseCoord *min_coord, *max_coord; if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh index 36f123b559b..b3af128e02d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh @@ -55,19 +55,22 @@ static bool ClassDef_remap_and_serialize ( hb_serialize_context_t *c, const hb_set_t &klasses, bool use_class_zero, - hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */ + hb_sorted_vector_t<hb_codepoint_pair_t> &glyph_and_klass, /* IN/OUT */ hb_map_t *klass_map /*IN/OUT*/); struct hb_collect_feature_substitutes_with_var_context_t { const hb_map_t *axes_index_tag_map; - const hb_hashmap_t<hb_tag_t, int> *axes_location; + const hb_hashmap_t<hb_tag_t, Triple> *axes_location; hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map; hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map; + bool& insert_catch_all_feature_variation_record; // not stored in subset_plan hb_set_t *feature_indices; bool apply; + bool variation_applied; + bool universal; unsigned cur_record_idx; hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map; }; @@ -807,7 +810,7 @@ struct Feature { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->featureParams.serialize_subset (c, featureParams, this, tag); @@ -981,7 +984,7 @@ struct RecordListOfFeature : RecordListOf<Feature> { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + hb_enumerate (*this) | hb_filter (l->feature_index_map, hb_first) @@ -1078,7 +1081,7 @@ struct LangSys { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); const uint32_t *v; out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu; @@ -1188,7 +1191,7 @@ struct Script return false; auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); bool defaultLang = false; if (has_default_lang_sys ()) @@ -1247,7 +1250,7 @@ struct RecordListOfScript : RecordListOf<Script> { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); for (auto _ : + hb_enumerate (*this)) { @@ -1367,7 +1370,7 @@ struct Lookup { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->lookupType = lookupType; out->lookupFlag = lookupFlag; @@ -1456,7 +1459,7 @@ struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType> { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + hb_enumerate (*this) | hb_filter (l->lookup_index_map, hb_first) @@ -1482,7 +1485,7 @@ struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType> static bool ClassDef_remap_and_serialize (hb_serialize_context_t *c, const hb_set_t &klasses, bool use_class_zero, - hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */ + hb_sorted_vector_t<hb_codepoint_pair_t> &glyph_and_klass, /* IN/OUT */ hb_map_t *klass_map /*IN/OUT*/) { if (!klass_map) @@ -1573,7 +1576,7 @@ struct ClassDefFormat1_3 TRACE_SUBSET (this); const hb_map_t &glyph_map = c->plan->glyph_map_gsub; - hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass; + hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass; hb_set_t orig_klasses; hb_codepoint_t start = startGlyph; @@ -1592,10 +1595,13 @@ struct ClassDefFormat1_3 orig_klasses.add (klass); } - unsigned glyph_count = glyph_filter - ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter)) - : glyph_map.get_population (); - use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length; + if (use_class_zero) + { + unsigned glyph_count = glyph_filter + ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter)) + : glyph_map.get_population (); + use_class_zero = glyph_count <= glyph_and_klass.length; + } if (!ClassDef_remap_and_serialize (c->serializer, orig_klasses, use_class_zero, @@ -1830,7 +1836,7 @@ struct ClassDefFormat2_4 const hb_map_t &glyph_map = c->plan->glyph_map_gsub; const hb_set_t &glyph_set = *c->plan->glyphset_gsub (); - hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass; + hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass; hb_set_t orig_klasses; if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2 @@ -1916,7 +1922,7 @@ struct ClassDefFormat2_4 { if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) { - for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + for (auto g : *glyphs) if (get_class (g)) return true; return false; @@ -1976,8 +1982,7 @@ struct ClassDefFormat2_4 unsigned count = rangeRecord.len; if (count > glyphs->get_population () * hb_bit_storage (count) * 8) { - for (hb_codepoint_t g = HB_SET_VALUE_INVALID; - glyphs->next (&g);) + for (auto g : *glyphs) { unsigned i; if (rangeRecord.as_array ().bfind (g, &i) && @@ -2377,7 +2382,7 @@ struct VarRegionList return_trace (c->check_struct (this) && axesZ.sanitize (c, axisCount * regionCount)); } - bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_bimap_t ®ion_map) + bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_inc_bimap_t ®ion_map) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); @@ -2494,7 +2499,7 @@ struct VarData bool serialize (hb_serialize_context_t *c, const VarData *src, const hb_inc_bimap_t &inner_map, - const hb_bimap_t ®ion_map) + const hb_inc_bimap_t ®ion_map) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); @@ -2905,9 +2910,9 @@ struct VariationStore enum Cond_with_Var_flag_t { KEEP_COND_WITH_VAR = 0, - DROP_COND_WITH_VAR = 1, - DROP_RECORD_WITH_VAR = 2, - MEM_ERR_WITH_VAR = 3, + KEEP_RECORD_WITH_VAR = 1, + DROP_COND_WITH_VAR = 2, + DROP_RECORD_WITH_VAR = 3, }; struct ConditionFormat1 @@ -2940,29 +2945,42 @@ struct ConditionFormat1 hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex); - //axis not pinned, keep the condition - if (!c->axes_location->has (axis_tag)) + Triple axis_range (-1.f, 0.f, 1.f); + if (c->axes_location->has (axis_tag)) + axis_range = c->axes_location->get (axis_tag); + + int axis_min_val = axis_range.minimum; + int axis_default_val = axis_range.middle; + int axis_max_val = axis_range.maximum; + + int16_t filter_min_val = filterRangeMinValue.to_int (); + int16_t filter_max_val = filterRangeMaxValue.to_int (); + + if (axis_default_val < filter_min_val || + axis_default_val > filter_max_val) + c->apply = false; + + //condition not met, drop the entire record + if (axis_min_val > filter_max_val || axis_max_val < filter_min_val || + filter_min_val > filter_max_val) + return DROP_RECORD_WITH_VAR; + + //condition met and axis pinned, drop the condition + if (c->axes_location->has (axis_tag) && + c->axes_location->get (axis_tag).is_point ()) + return DROP_COND_WITH_VAR; + + if (filter_max_val != axis_max_val || filter_min_val != axis_min_val) { // add axisIndex->value into the hashmap so we can check if the record is // unique with variations - int16_t min_val = filterRangeMinValue.to_int (); - int16_t max_val = filterRangeMaxValue.to_int (); - hb_codepoint_t val = (max_val << 16) + min_val; + hb_codepoint_t val = (filter_max_val << 16) + filter_min_val; condition_map->set (axisIndex, val); return KEEP_COND_WITH_VAR; } - //axis pinned, check if condition is met - //TODO: add check for axis Ranges - int v = c->axes_location->get (axis_tag); - - //condition not met, drop the entire record - if (v < filterRangeMinValue.to_int () || v > filterRangeMaxValue.to_int ()) - return DROP_RECORD_WITH_VAR; - - //axis pinned and condition met, drop the condition - return DROP_COND_WITH_VAR; + return KEEP_RECORD_WITH_VAR; } bool evaluate (const int *coords, unsigned int coord_len) const @@ -3001,7 +3019,7 @@ struct Condition { switch (u.format) { case 1: return u.format1.keep_with_variations (c, condition_map); - default:return KEEP_COND_WITH_VAR; + default: c->apply = false; return KEEP_COND_WITH_VAR; } } @@ -3046,45 +3064,50 @@ struct ConditionSet return true; } - Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const + void keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const { hb_map_t *condition_map = hb_map_create (); - if (unlikely (!condition_map)) return MEM_ERR_WITH_VAR; + if (unlikely (!condition_map)) return; hb::shared_ptr<hb_map_t> p {condition_map}; hb_set_t *cond_set = hb_set_create (); - if (unlikely (!cond_set)) return MEM_ERR_WITH_VAR; + if (unlikely (!cond_set)) return; hb::shared_ptr<hb_set_t> s {cond_set}; + c->apply = true; + bool should_keep = false; unsigned num_kept_cond = 0, cond_idx = 0; for (const auto& offset : conditions) { Cond_with_Var_flag_t ret = (this+offset).keep_with_variations (c, condition_map); - // one condition is not met, drop the entire record + // condition is not met or condition out of range, drop the entire record if (ret == DROP_RECORD_WITH_VAR) - return DROP_RECORD_WITH_VAR; + return; - // axis not pinned, keep this condition if (ret == KEEP_COND_WITH_VAR) { + should_keep = true; cond_set->add (cond_idx); num_kept_cond++; } + + if (ret == KEEP_RECORD_WITH_VAR) + should_keep = true; + cond_idx++; } - // all conditions met - if (num_kept_cond == 0) return DROP_COND_WITH_VAR; + if (!should_keep) return; //check if condition_set is unique with variations if (c->conditionset_map->has (p)) //duplicate found, drop the entire record - return DROP_RECORD_WITH_VAR; + return; c->conditionset_map->set (p, 1); c->record_cond_idx_map->set (c->cur_record_idx, s); - - return KEEP_COND_WITH_VAR; + if (should_keep && num_kept_cond == 0) + c->universal = true; } bool subset (hb_subset_context_t *c, @@ -3289,12 +3312,11 @@ struct FeatureVariationRecord void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c, const void *base) const { - // ret == 1, all conditions met - if ((base+conditions).keep_with_variations (c) == DROP_COND_WITH_VAR && - c->apply) + (base+conditions).keep_with_variations (c); + if (c->apply && !c->variation_applied) { (base+substitutions).collect_feature_substitutes_with_variations (c); - c->apply = false; // set variations only once + c->variation_applied = true; // set variations only once } } @@ -3361,7 +3383,12 @@ struct FeatureVariations { c->cur_record_idx = i; varRecords[i].collect_feature_substitutes_with_variations (c, this); + if (c->universal) + break; } + if (c->variation_applied && !c->universal && + !c->record_cond_idx_map->is_empty ()) + c->insert_catch_all_feature_variation_record = true; } FeatureVariations* copy (hb_serialize_context_t *c) const diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh index 8e5be92d12e..e10adb78beb 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh @@ -143,9 +143,12 @@ struct hb_closure_context_t : return active_glyphs_stack.tail (); } - hb_set_t& push_cur_active_glyphs () + hb_set_t* push_cur_active_glyphs () { - return *active_glyphs_stack.push (); + hb_set_t *s = active_glyphs_stack.push (); + if (unlikely (active_glyphs_stack.in_error ())) + return nullptr; + return s; } bool pop_cur_done_glyphs () @@ -427,6 +430,9 @@ struct hb_ot_apply_context_t : MATCH_MAYBE }; +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif may_match_t may_match (hb_glyph_info_t &info, hb_codepoint_t glyph_data) const { @@ -446,6 +452,9 @@ struct hb_ot_apply_context_t : SKIP_MAYBE }; +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif may_skip_t may_skip (const hb_ot_apply_context_t *c, const hb_glyph_info_t &info) const { @@ -516,6 +525,9 @@ struct hb_ot_apply_context_t : } #endif +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif void reset (unsigned int start_index_, unsigned int num_items_) { @@ -525,6 +537,9 @@ struct hb_ot_apply_context_t : matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif void reset_fast (unsigned int start_index_, unsigned int num_items_) { @@ -540,6 +555,9 @@ struct hb_ot_apply_context_t : } matcher_t::may_skip_t +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif may_skip (const hb_glyph_info_t &info) const { return matcher.may_skip (c, info); } @@ -549,6 +567,9 @@ struct hb_ot_apply_context_t : SKIP }; +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif match_t match (hb_glyph_info_t &info) { matcher_t::may_skip_t skip = matcher.may_skip (c, info); @@ -567,6 +588,9 @@ struct hb_ot_apply_context_t : return SKIP; } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool next (unsigned *unsafe_to = nullptr) { assert (num_items > 0); @@ -600,6 +624,9 @@ struct hb_ot_apply_context_t : *unsafe_to = end; return false; } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool prev (unsigned *unsafe_from = nullptr) { assert (num_items > 0); @@ -703,6 +730,7 @@ struct hb_ot_apply_context_t : hb_font_t *font; hb_face_t *face; hb_buffer_t *buffer; + hb_sanitize_context_t sanitizer; recurse_func_t recurse_func = nullptr; const GDEF &gdef; const GDEF::accelerator_t &gdef_accel; @@ -729,9 +757,11 @@ struct hb_ot_apply_context_t : hb_ot_apply_context_t (unsigned int table_index_, hb_font_t *font_, - hb_buffer_t *buffer_) : + hb_buffer_t *buffer_, + hb_blob_t *table_blob_) : table_index (table_index_), font (font_), face (font->face), buffer (buffer_), + sanitizer (table_blob_), gdef ( #ifndef HB_NO_OT_LAYOUT *face->table.GDEF->table @@ -808,6 +838,9 @@ struct hb_ot_apply_context_t : return true; } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool check_glyph_property (const hb_glyph_info_t *info, unsigned int match_props) const { @@ -1213,14 +1246,17 @@ static inline bool would_match_input (hb_would_apply_context_t *c, return true; } template <typename HBUINT> -static inline bool match_input (hb_ot_apply_context_t *c, - unsigned int count, /* Including the first glyph (not matched) */ - const HBUINT input[], /* Array of input values--start with second glyph */ - match_func_t match_func, - const void *match_data, - unsigned int *end_position, - unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], - unsigned int *p_total_component_count = nullptr) +#ifndef HB_OPTIMIZE_SIZE +HB_ALWAYS_INLINE +#endif +static bool match_input (hb_ot_apply_context_t *c, + unsigned int count, /* Including the first glyph (not matched) */ + const HBUINT input[], /* Array of input values--start with second glyph */ + match_func_t match_func, + const void *match_data, + unsigned int *end_position, + unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], + unsigned int *p_total_component_count = nullptr) { TRACE_APPLY (nullptr); @@ -1456,12 +1492,15 @@ static inline bool ligate_input (hb_ot_apply_context_t *c, } template <typename HBUINT> -static inline bool match_backtrack (hb_ot_apply_context_t *c, - unsigned int count, - const HBUINT backtrack[], - match_func_t match_func, - const void *match_data, - unsigned int *match_start) +#ifndef HB_OPTIMIZE_SIZE +HB_ALWAYS_INLINE +#endif +static bool match_backtrack (hb_ot_apply_context_t *c, + unsigned int count, + const HBUINT backtrack[], + match_func_t match_func, + const void *match_data, + unsigned int *match_start) { TRACE_APPLY (nullptr); @@ -1485,13 +1524,16 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c, } template <typename HBUINT> -static inline bool match_lookahead (hb_ot_apply_context_t *c, - unsigned int count, - const HBUINT lookahead[], - match_func_t match_func, - const void *match_data, - unsigned int start_index, - unsigned int *end_index) +#ifndef HB_OPTIMIZE_SIZE +HB_ALWAYS_INLINE +#endif +static bool match_lookahead (hb_ot_apply_context_t *c, + unsigned int count, + const HBUINT lookahead[], + match_func_t match_func, + const void *match_data, + unsigned int start_index, + unsigned int *end_index) { TRACE_APPLY (nullptr); @@ -1615,10 +1657,13 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, } covered_seq_indicies.add (seqIndex); + hb_set_t *cur_active_glyphs = c->push_cur_active_glyphs (); + if (unlikely (!cur_active_glyphs)) + return; if (has_pos_glyphs) { - c->push_cur_active_glyphs () = std::move (pos_glyphs); + *cur_active_glyphs = std::move (pos_glyphs); } else { - c->push_cur_active_glyphs ().set (*c->glyphs); + *cur_active_glyphs = *c->glyphs; } unsigned endIndex = inputCount; @@ -2001,8 +2046,7 @@ struct Rule bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (inputCount.sanitize (c) && - lookupCount.sanitize (c) && + return_trace (c->check_struct (this) && c->check_range (inputZ.arrayZ, inputZ.item_size * (inputCount ? inputCount - 1 : 0) + LookupRecord::static_size * lookupCount)); @@ -2021,6 +2065,7 @@ struct Rule * design order */ public: DEFINE_SIZE_ARRAY (4, inputZ); + DEFINE_SIZE_MAX (65536 * (Types::HBUINT::static_size + LookupRecord::static_size)); }; template <typename Types> @@ -2168,8 +2213,9 @@ struct ContextFormat1_4 void closure (hb_closure_context_t *c) const { - hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); - get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs); + hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs (); + if (unlikely (!cur_active_glyphs)) return; + get_coverage ().intersect_set (c->previous_parent_active_glyphs (), *cur_active_glyphs); struct ContextClosureLookupContext lookup_context = { {intersects_glyph, intersected_glyph}, @@ -2338,9 +2384,10 @@ struct ContextFormat2_5 if (!(this+coverage).intersects (c->glyphs)) return; - hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs (); + if (unlikely (!cur_active_glyphs)) return; get_coverage ().intersect_set (c->previous_parent_active_glyphs (), - cur_active_glyphs); + *cur_active_glyphs); const ClassDef &class_def = this+classDef; @@ -2583,10 +2630,10 @@ struct ContextFormat3 if (!(this+coverageZ[0]).intersects (c->glyphs)) return; - hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs (); + if (unlikely (!cur_active_glyphs)) return; get_coverage ().intersect_set (c->previous_parent_active_glyphs (), - cur_active_glyphs); - + *cur_active_glyphs); const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount)); struct ContextClosureLookupContext lookup_context = { @@ -2687,14 +2734,14 @@ struct ContextFormat3 bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!c->check_struct (this)) return_trace (false); + if (unlikely (!c->check_struct (this))) return_trace (false); unsigned int count = glyphCount; - if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */ - if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false); + if (unlikely (!count)) return_trace (false); /* We want to access coverageZ[0] freely. */ + if (unlikely (!c->check_array (coverageZ.arrayZ, count))) return_trace (false); for (unsigned int i = 0; i < count; i++) - if (!coverageZ[i].sanitize (c, this)) return_trace (false); + if (unlikely (!coverageZ[i].sanitize (c, this))) return_trace (false); const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount)); - return_trace (c->check_array (lookupRecord, lookupCount)); + return_trace (likely (c->check_array (lookupRecord, lookupCount))); } protected: @@ -3014,8 +3061,6 @@ struct ChainRule const hb_map_t *lookahead_map = nullptr) const { TRACE_SERIALIZE (this); - auto *out = c->start_embed (this); - if (unlikely (!out)) return_trace (false); const hb_map_t *mapping = backtrack_map; serialize_array (c, backtrack.len, + backtrack.iter () @@ -3077,13 +3122,14 @@ struct ChainRule bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!backtrack.sanitize (c)) return_trace (false); + /* Hyper-optimized sanitized because this is really hot. */ + if (unlikely (!backtrack.len.sanitize (c))) return_trace (false); const auto &input = StructAfter<decltype (inputX)> (backtrack); - if (!input.sanitize (c)) return_trace (false); + if (unlikely (!input.lenP1.sanitize (c))) return_trace (false); const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); - if (!lookahead.sanitize (c)) return_trace (false); + if (unlikely (!lookahead.len.sanitize (c))) return_trace (false); const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); - return_trace (lookup.sanitize (c)); + return_trace (likely (lookup.sanitize (c))); } protected: @@ -3091,7 +3137,7 @@ struct ChainRule backtrack; /* Array of backtracking values * (to be matched before the input * sequence) */ - HeadlessArrayOf<typename Types::HBUINT> + HeadlessArray16Of<typename Types::HBUINT> inputX; /* Array of input values (start with * second glyph) */ Array16Of<typename Types::HBUINT> @@ -3102,6 +3148,7 @@ struct ChainRule * design order) */ public: DEFINE_SIZE_MIN (8); + DEFINE_SIZE_MAX (65536 * (3 * Types::HBUINT::static_size + LookupRecord::static_size)); }; template <typename Types> @@ -3251,9 +3298,10 @@ struct ChainContextFormat1_4 void closure (hb_closure_context_t *c) const { - hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs (); + if (unlikely (!cur_active_glyphs)) return; get_coverage ().intersect_set (c->previous_parent_active_glyphs (), - cur_active_glyphs); + *cur_active_glyphs); struct ChainContextClosureLookupContext lookup_context = { {intersects_glyph, intersected_glyph}, @@ -3423,10 +3471,10 @@ struct ChainContextFormat2_5 if (!(this+coverage).intersects (c->glyphs)) return; - hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs (); + if (unlikely (!cur_active_glyphs)) return; get_coverage ().intersect_set (c->previous_parent_active_glyphs (), - cur_active_glyphs); - + *cur_active_glyphs); const ClassDef &backtrack_class_def = this+backtrackClassDef; const ClassDef &input_class_def = this+inputClassDef; @@ -3727,10 +3775,11 @@ struct ChainContextFormat3 if (!(this+input[0]).intersects (c->glyphs)) return; - hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs (); + hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs (); + if (unlikely (!cur_active_glyphs)) + return; get_coverage ().intersect_set (c->previous_parent_active_glyphs (), - cur_active_glyphs); - + *cur_active_glyphs); const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); @@ -3849,8 +3898,6 @@ struct ChainContextFormat3 { TRACE_SUBSET (this); - auto *out = c->serializer->start_embed (this); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->embed (this->format))) return_trace (false); if (!serialize_coverage_offsets (c, backtrack.iter (), this)) @@ -3877,14 +3924,14 @@ struct ChainContextFormat3 bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!backtrack.sanitize (c, this)) return_trace (false); + if (unlikely (!backtrack.sanitize (c, this))) return_trace (false); const auto &input = StructAfter<decltype (inputX)> (backtrack); - if (!input.sanitize (c, this)) return_trace (false); - if (!input.len) return_trace (false); /* To be consistent with Context. */ + if (unlikely (!input.sanitize (c, this))) return_trace (false); + if (unlikely (!input.len)) return_trace (false); /* To be consistent with Context. */ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input); - if (!lookahead.sanitize (c, this)) return_trace (false); + if (unlikely (!lookahead.sanitize (c, this))) return_trace (false); const auto &lookup = StructAfter<decltype (lookupX)> (lookahead); - return_trace (lookup.sanitize (c)); + return_trace (likely (lookup.sanitize (c))); } protected: @@ -3974,7 +4021,7 @@ struct ExtensionFormat1 TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->format = format; out->extensionLookupType = extensionLookupType; @@ -4503,7 +4550,10 @@ struct GSUBGPOS { accelerator_t (hb_face_t *face) { - this->table = hb_sanitize_context_t ().reference_table<T> (face); + hb_sanitize_context_t sc; + sc.lazy_some_gpos = true; + this->table = sc.reference_table<T> (face); + if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face))) { hb_blob_destroy (this->table.get_blob ()); @@ -4528,6 +4578,8 @@ struct GSUBGPOS this->table.destroy (); } + hb_blob_t *get_blob () const { return table.get_blob (); } + hb_ot_layout_lookup_accelerator_t *get_accel (unsigned lookup_index) const { if (unlikely (lookup_index >= lookup_count)) return nullptr; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc index c66ee8cfd06..020b8a6c828 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc @@ -1316,8 +1316,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face, hb_set_t feature_indexes; hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes); - for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID; - hb_set_next (&feature_indexes, &feature_index);) + for (auto feature_index : feature_indexes) g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes); g.feature_variation_collect_lookups (&feature_indexes, nullptr, lookup_indexes); @@ -1570,7 +1569,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, glyphs_length = glyphs->get_population (); if (lookups) { - for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);) + for (auto lookup_index : *lookups) gsub.get_lookup (lookup_index).closure (&c, lookup_index); } else @@ -1953,7 +1952,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, { const unsigned int table_index = proxy.table_index; unsigned int i = 0; - OT::hb_ot_apply_context_t c (table_index, font, buffer); + OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob ()); c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func<OT::hb_ot_apply_context_t>); for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) @@ -2011,20 +2010,20 @@ void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, h { GSUBProxy proxy (font->face); if (buffer->messaging () && - !buffer->message (font, "start table GSUB")) return; + !buffer->message (font, "start table GSUB script tag '%c%c%c%c'", HB_UNTAG (chosen_script[0]))) return; apply (proxy, plan, font, buffer); if (buffer->messaging ()) - (void) buffer->message (font, "end table GSUB"); + (void) buffer->message (font, "end table GSUB script tag '%c%c%c%c'", HB_UNTAG (chosen_script[0])); } void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const { GPOSProxy proxy (font->face); if (buffer->messaging () && - !buffer->message (font, "start table GPOS")) return; + !buffer->message (font, "start table GPOS script tag '%c%c%c%c'", HB_UNTAG (chosen_script[1]))) return; apply (proxy, plan, font, buffer); if (buffer->messaging ()) - (void) buffer->message (font, "end table GPOS"); + (void) buffer->message (font, "end table GPOS script tag '%c%c%c%c'", HB_UNTAG (chosen_script[1])); } void @@ -2036,6 +2035,112 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, } #ifndef HB_NO_BASE + +static void +choose_base_tags (hb_script_t script, + hb_language_t language, + hb_tag_t *script_tag, + hb_tag_t *language_tag) +{ + hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT]; + unsigned script_count = ARRAY_LENGTH (script_tags); + + hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE]; + unsigned language_count = ARRAY_LENGTH (language_tags); + + hb_ot_tags_from_script_and_language (script, language, + &script_count, script_tags, + &language_count, language_tags); + + *script_tag = script_count ? script_tags[script_count - 1] : HB_OT_TAG_DEFAULT_SCRIPT; + *language_tag = language_count ? language_tags[language_count - 1] : HB_OT_TAG_DEFAULT_LANGUAGE; +} + +/** + * hb_ot_layout_get_font_extents: + * @font: a font + * @direction: text direction. + * @script_tag: script tag. + * @language_tag: language tag. + * @extents: (out) (nullable): font extents if found. + * + * Fetches script/language-specific font extents. These values are + * looked up in the `BASE` table's `MinMax` records. + * + * If no such extents are found, the default extents for the font are + * fetched. As such, the return value of this function can for the + * most part be ignored. Note that the per-script/language extents + * do not have a line-gap value, and the line-gap is set to zero in + * that case. + * + * Return value: `true` if found script/language-specific font extents. + * + * Since: 8.0.0 + **/ +hb_bool_t +hb_ot_layout_get_font_extents (hb_font_t *font, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_font_extents_t *extents) +{ + hb_position_t min, max; + if (font->face->table.BASE->get_min_max (font, direction, script_tag, language_tag, HB_TAG_NONE, + &min, &max)) + { + if (extents) + { + extents->ascender = max; + extents->descender = min; + extents->line_gap = 0; + } + return true; + } + + hb_font_get_extents_for_direction (font, direction, extents); + return false; +} + +/** + * hb_ot_layout_get_font_extents2: + * @font: a font + * @direction: text direction. + * @script: script. + * @language: (nullable): language. + * @extents: (out) (nullable): font extents if found. + * + * Fetches script/language-specific font extents. These values are + * looked up in the `BASE` table's `MinMax` records. + * + * If no such extents are found, the default extents for the font are + * fetched. As such, the return value of this function can for the + * most part be ignored. Note that the per-script/language extents + * do not have a line-gap value, and the line-gap is set to zero in + * that case. + * + * This function is like hb_ot_layout_get_font_extents() but takes + * #hb_script_t and #hb_language_t instead of OpenType #hb_tag_t. + * + * Return value: `true` if found script/language-specific font extents. + * + * Since: 8.0.0 + **/ +hb_bool_t +hb_ot_layout_get_font_extents2 (hb_font_t *font, + hb_direction_t direction, + hb_script_t script, + hb_language_t language, + hb_font_extents_t *extents) +{ + hb_tag_t script_tag, language_tag; + choose_base_tags (script, language, &script_tag, &language_tag); + return hb_ot_layout_get_font_extents (font, + direction, + script_tag, + language_tag, + extents); +} + /** * hb_ot_layout_get_horizontal_baseline_tag_for_script: * @script: a script tag. @@ -2134,6 +2239,42 @@ hb_ot_layout_get_baseline (hb_font_t *font, } /** + * hb_ot_layout_get_baseline2: + * @font: a font + * @baseline_tag: a baseline tag + * @direction: text direction. + * @script: script. + * @language: (nullable): language, currently unused. + * @coord: (out) (nullable): baseline value if found. + * + * Fetches a baseline value from the face. + * + * This function is like hb_ot_layout_get_baseline() but takes + * #hb_script_t and #hb_language_t instead of OpenType #hb_tag_t. + * + * Return value: `true` if found baseline value in the font. + * + * Since: 8.0.0 + **/ +hb_bool_t +hb_ot_layout_get_baseline2 (hb_font_t *font, + hb_ot_layout_baseline_tag_t baseline_tag, + hb_direction_t direction, + hb_script_t script, + hb_language_t language, + hb_position_t *coord /* OUT. May be NULL. */) +{ + hb_tag_t script_tag, language_tag; + choose_base_tags (script, language, &script_tag, &language_tag); + return hb_ot_layout_get_baseline (font, + baseline_tag, + direction, + script_tag, + language_tag, + coord); +} + +/** * hb_ot_layout_get_baseline_with_fallback: * @font: a font * @baseline_tag: a baseline tag @@ -2355,6 +2496,41 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font, } } +/** + * hb_ot_layout_get_baseline_with_fallback2: + * @font: a font + * @baseline_tag: a baseline tag + * @direction: text direction. + * @script: script. + * @language: (nullable): language, currently unused. + * @coord: (out): baseline value if found. + * + * Fetches a baseline value from the face, and synthesizes + * it if the font does not have it. + * + * This function is like hb_ot_layout_get_baseline_with_fallback() but takes + * #hb_script_t and #hb_language_t instead of OpenType #hb_tag_t. + * + * Since: 8.0.0 + **/ +void +hb_ot_layout_get_baseline_with_fallback2 (hb_font_t *font, + hb_ot_layout_baseline_tag_t baseline_tag, + hb_direction_t direction, + hb_script_t script, + hb_language_t language, + hb_position_t *coord /* OUT */) +{ + hb_tag_t script_tag, language_tag; + choose_base_tags (script, language, &script_tag, &language_tag); + hb_ot_layout_get_baseline_with_fallback (font, + baseline_tag, + direction, + script_tag, + language_tag, + coord); +} + #endif @@ -2451,9 +2627,10 @@ hb_ot_layout_lookup_get_optical_bound (hb_font_t *font, hb_codepoint_t glyph) { const OT::PosLookup &lookup = font->face->table.GPOS->table->get_lookup (lookup_index); + hb_blob_t *blob = font->face->table.GPOS->get_blob (); hb_glyph_position_t pos = {0}; hb_position_single_dispatch_t c; - lookup.dispatch (&c, font, direction, glyph, pos); + lookup.dispatch (&c, font, blob, direction, glyph, pos); hb_position_t ret = 0; switch (direction) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h index 10dcc65ac07..b0fae3707fa 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h @@ -447,6 +447,20 @@ hb_ot_layout_feature_get_characters (hb_face_t *face, * BASE */ +HB_EXTERN hb_bool_t +hb_ot_layout_get_font_extents (hb_font_t *font, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_font_extents_t *extents); + +HB_EXTERN hb_bool_t +hb_ot_layout_get_font_extents2 (hb_font_t *font, + hb_direction_t direction, + hb_script_t script, + hb_language_t language, + hb_font_extents_t *extents); + /** * hb_ot_layout_baseline_tag_t: * @HB_OT_LAYOUT_BASELINE_TAG_ROMAN: The baseline used by alphabetic scripts such as Latin, Cyrillic and Greek. @@ -499,6 +513,14 @@ hb_ot_layout_get_baseline (hb_font_t *font, hb_tag_t language_tag, hb_position_t *coord /* OUT. May be NULL. */); +HB_EXTERN hb_bool_t +hb_ot_layout_get_baseline2 (hb_font_t *font, + hb_ot_layout_baseline_tag_t baseline_tag, + hb_direction_t direction, + hb_script_t script, + hb_language_t language, + hb_position_t *coord /* OUT. May be NULL. */); + HB_EXTERN void hb_ot_layout_get_baseline_with_fallback (hb_font_t *font, hb_ot_layout_baseline_tag_t baseline_tag, @@ -507,6 +529,14 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font, hb_tag_t language_tag, hb_position_t *coord /* OUT */); +HB_EXTERN void +hb_ot_layout_get_baseline_with_fallback2 (hb_font_t *font, + hb_ot_layout_baseline_tag_t baseline_tag, + hb_direction_t direction, + hb_script_t script, + hb_language_t language, + hb_position_t *coord /* OUT */); + HB_END_DECLS #endif /* HB_OT_LAYOUT_H */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh index 9505d5f1470..d71889331d8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh @@ -448,7 +448,7 @@ _hb_glyph_info_get_lig_id (const hb_glyph_info_t *info) static inline bool _hb_glyph_info_ligated_internal (const hb_glyph_info_t *info) { - return !!(info->lig_props() & IS_LIG_BASE); + return info->lig_props() & IS_LIG_BASE; } static inline unsigned int @@ -496,37 +496,37 @@ _hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info) static inline bool _hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info) { - return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH); + return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH; } static inline bool _hb_glyph_info_is_ligature (const hb_glyph_info_t *info) { - return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE); + return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; } static inline bool _hb_glyph_info_is_mark (const hb_glyph_info_t *info) { - return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); + return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK; } static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info) { - return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED); + return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED; } static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info) { - return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED); + return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED; } static inline bool _hb_glyph_info_multiplied (const hb_glyph_info_t *info) { - return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED); + return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED; } static inline bool diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc index 8882dbaccb4..bacd56ef3fc 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc @@ -213,7 +213,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, /* Sort features and merge duplicates */ if (feature_infos.length) { - feature_infos.qsort (); + if (!is_simple) + feature_infos.qsort (); auto *f = feature_infos.arrayZ; unsigned int j = 0; unsigned count = feature_infos.length; @@ -314,7 +315,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, map->needs_fallback = !found; } //feature_infos.shrink (0); /* Done with these */ - + if (is_simple) + m.features.qsort (); add_gsub_pause (nullptr); add_gpos_pause (nullptr); @@ -350,7 +352,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, } /* Sort lookups and merge duplicates */ - if (last_num_lookups < lookups.length) + if (last_num_lookups + 1 < lookups.length) { lookups.as_array ().sub_array (last_num_lookups, lookups.length - last_num_lookups).qsort (); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh index efc8cae96a4..8af8129ceba 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh @@ -60,6 +60,13 @@ struct hb_ot_map_t int cmp (const hb_tag_t tag_) const { return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; } + + HB_INTERNAL static int cmp (const void *pa, const void *pb) + { + const feature_map_t *a = (const feature_map_t *) pa; + const feature_map_t *b = (const feature_map_t *) pb; + return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; + } }; struct lookup_map_t { @@ -273,6 +280,7 @@ struct hb_ot_map_builder_t hb_face_t *face; hb_segment_properties_t props; + bool is_simple; hb_tag_t chosen_script[2]; bool found_script[2]; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh index dccf720f46b..b11da464b22 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh @@ -73,7 +73,6 @@ struct MathConstants { TRACE_SERIALIZE (this); auto *out = c->start_embed (this); - if (unlikely (!out)) return_trace (nullptr); HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2); if (unlikely (!p)) return_trace (nullptr); @@ -310,7 +309,6 @@ struct MathKern { TRACE_SERIALIZE (this); auto *out = c->start_embed (this); - if (unlikely (!out)) return_trace (nullptr); if (unlikely (!c->embed (heightCount))) return_trace (nullptr); @@ -572,6 +570,7 @@ struct MathGlyphInfo auto it = + hb_iter (this+extendedShapeCoverage) + | hb_take (c->plan->source->get_num_glyphs ()) | hb_filter (glyphset) | hb_map_retains_sorting (glyph_map) ; @@ -757,8 +756,6 @@ struct MathGlyphAssembly bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); if (!c->serializer->copy (italicsCorrection, this)) return_trace (false); if (!c->serializer->copy<HBUINT16> (partRecords.len)) return_trace (false); @@ -945,13 +942,13 @@ struct MathVariants if (unlikely (!c->serializer->extend_min (out))) return_trace (false); if (!c->serializer->check_assign (out->minConnectorOverlap, minConnectorOverlap, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); - + hb_sorted_vector_t<hb_codepoint_t> new_vert_coverage; hb_sorted_vector_t<hb_codepoint_t> new_hori_coverage; hb_set_t indices; collect_coverage_and_indices (new_vert_coverage, vertGlyphCoverage, 0, vertGlyphCount, indices, glyphset, glyph_map); collect_coverage_and_indices (new_hori_coverage, horizGlyphCoverage, vertGlyphCount, vertGlyphCount + horizGlyphCount, indices, glyphset, glyph_map); - + if (!c->serializer->check_assign (out->vertGlyphCount, new_vert_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); if (!c->serializer->check_assign (out->horizGlyphCount, new_hori_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) @@ -963,10 +960,10 @@ struct MathVariants if (!o) return_trace (false); o->serialize_subset (c, glyphConstruction[i], this); } - + if (new_vert_coverage) out->vertGlyphCoverage.serialize_serialize (c->serializer, new_vert_coverage.iter ()); - + if (new_hori_coverage) out->horizGlyphCoverage.serialize_serialize (c->serializer, new_hori_coverage.iter ()); return_trace (true); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh index 97d18b9d75d..72cb662473d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh @@ -249,7 +249,7 @@ struct OS2 if (c->plan->user_axes_location.has (HB_TAG ('w','g','h','t')) && !c->plan->pinned_at_default) { - float weight_class = c->plan->user_axes_location.get (HB_TAG ('w','g','h','t')); + float weight_class = c->plan->user_axes_location.get (HB_TAG ('w','g','h','t')).middle; if (!c->serializer->check_assign (os2_prime->usWeightClass, roundf (hb_clamp (weight_class, 1.0f, 1000.0f)), HB_SERIALIZE_ERROR_INT_OVERFLOW)) @@ -259,7 +259,7 @@ struct OS2 if (c->plan->user_axes_location.has (HB_TAG ('w','d','t','h')) && !c->plan->pinned_at_default) { - float width = c->plan->user_axes_location.get (HB_TAG ('w','d','t','h')); + float width = c->plan->user_axes_location.get (HB_TAG ('w','d','t','h')).middle; if (!c->serializer->check_assign (os2_prime->usWidthClass, roundf (map_wdth_to_widthclass (width)), HB_SERIALIZE_ERROR_INT_OVERFLOW)) @@ -287,8 +287,7 @@ struct OS2 /* This block doesn't show up in profiles. If it ever did, * we can rewrite it to iterate over OS/2 ranges and use * set iteration to check if the range matches. */ - for (hb_codepoint_t cp = HB_SET_VALUE_INVALID; - codepoints->next (&cp);) + for (auto cp : *codepoints) { unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp); if (bit < 128) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table-v2subset.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table-v2subset.hh index 951e6395d6d..d44233610a6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table-v2subset.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table-v2subset.hh @@ -79,6 +79,11 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const post::accelerator_t _post (c->plan->source); hb_hashmap_t<hb_bytes_t, uint32_t, true> glyph_name_to_new_index; + + old_new_index_map.alloc (num_glyphs); + old_gid_new_index_map.alloc (num_glyphs); + glyph_name_to_new_index.alloc (num_glyphs); + for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++) { hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid); @@ -86,11 +91,12 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const unsigned new_index; const uint32_t *new_index2; - if (old_index <= 257) new_index = old_index; + if (old_index <= 257) + new_index = old_index; else if (old_new_index_map.has (old_index, &new_index2)) - { new_index = *new_index2; - } else { + else + { hb_bytes_t s = _post.find_glyph_name (old_gid); new_index = glyph_name_to_new_index.get (s); if (new_index == (unsigned)-1) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh index 042fa611adf..761e49d1198 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh @@ -96,8 +96,7 @@ struct post bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - post *post_prime = c->serializer->start_embed<post> (); - if (unlikely (!post_prime)) return_trace (false); + auto *post_prime = c->serializer->start_embed<post> (); bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES; if (!serialize (c->serializer, glyph_names)) @@ -117,7 +116,7 @@ struct post if (c->plan->user_axes_location.has (HB_TAG ('s','l','n','t')) && !c->plan->pinned_at_default) { - float italic_angle = c->plan->user_axes_location.get (HB_TAG ('s','l','n','t')); + float italic_angle = c->plan->user_axes_location.get (HB_TAG ('s','l','n','t')).middle; italic_angle = hb_max (-90.f, hb_min (italic_angle, 90.f)); post_prime->italicAngle.set_float (italic_angle); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc index 3d207e06815..d84313f190e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc @@ -313,6 +313,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, { hb_ot_map_builder_t *map = &planner->map; + map->is_simple = true; + map->enable_feature (HB_TAG('r','v','r','n')); map->add_gsub_pause (nullptr); @@ -354,7 +356,10 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */ if (planner->shaper->collect_features) + { + map->is_simple = false; planner->shaper->collect_features (planner); + } map->enable_feature (HB_TAG ('B','u','z','z')); /* Considered required. */ map->enable_feature (HB_TAG ('B','U','Z','Z')); /* Considered discretionary. */ @@ -378,6 +383,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH); } + if (num_user_features) + map->is_simple = false; for (unsigned int i = 0; i < num_user_features; i++) { const hb_feature_t *feature = &user_features[i]; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh index e7a69008b72..66a8bfbd28f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-arabic-fallback.hh @@ -368,7 +368,7 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan, hb_font_t *font, hb_buffer_t *buffer) { - OT::hb_ot_apply_context_t c (0, font, buffer); + OT::hb_ot_apply_context_t c (0, font, buffer, hb_blob_get_empty ()); for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) if (fallback_plan->lookup_array[i]) { c.set_lookup_mask (fallback_plan->mask_array[i]); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh index 353e32d32c0..7dd47755af0 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-indic-machine.hh @@ -53,7 +53,7 @@ enum indic_syllable_type_t { }; -#line 57 "hb-ot-shaper-indic-machine.hh" +#line 54 "hb-ot-shaper-indic-machine.hh" #define indic_syllable_machine_ex_A 9u #define indic_syllable_machine_ex_C 1u #define indic_syllable_machine_ex_CM 16u @@ -76,7 +76,7 @@ enum indic_syllable_type_t { #define indic_syllable_machine_ex_ZWNJ 5u -#line 80 "hb-ot-shaper-indic-machine.hh" +#line 75 "hb-ot-shaper-indic-machine.hh" static const unsigned char _indic_syllable_machine_trans_keys[] = { 8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, @@ -460,7 +460,7 @@ find_syllables_indic (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 464 "hb-ot-shaper-indic-machine.hh" +#line 453 "hb-ot-shaper-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -476,7 +476,7 @@ find_syllables_indic (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 480 "hb-ot-shaper-indic-machine.hh" +#line 465 "hb-ot-shaper-indic-machine.hh" { int _slen; int _trans; @@ -490,7 +490,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 494 "hb-ot-shaper-indic-machine.hh" +#line 477 "hb-ot-shaper-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -593,7 +593,7 @@ _eof_trans: #line 114 "hb-ot-shaper-indic-machine.rl" {act = 6;} break; -#line 597 "hb-ot-shaper-indic-machine.hh" +#line 559 "hb-ot-shaper-indic-machine.hh" } _again: @@ -602,7 +602,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 606 "hb-ot-shaper-indic-machine.hh" +#line 566 "hb-ot-shaper-indic-machine.hh" } if ( ++p != pe ) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-syllabic.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-syllabic.cc index 89226ae4a1f..97f62035c69 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-syllabic.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-syllabic.cc @@ -40,6 +40,14 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font, if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) return false; if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE))) + { + if (buffer->messaging ()) + (void) buffer->message (font, "skipped inserting dotted-circles because there is no broken syllables"); + return false; + } + + if (buffer->messaging () && + !buffer->message (font, "start inserting dotted-circles")) return false; hb_codepoint_t dottedcircle_glyph; @@ -84,6 +92,10 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font, (void) buffer->next_glyph (); } buffer->sync (); + + if (buffer->messaging ()) + (void) buffer->message (font, "end inserting dotted-circles"); + return true; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.rl b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.rl index 256e46dc580..bd55380ab25 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.rl +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use-machine.rl @@ -110,7 +110,7 @@ export FMPst = 47; # CONS_FINAL_MOD UIPC = Not_Applicable h = H | HVM | IS | Sk; -consonant_modifiers = CMAbv* CMBlw* ((h B | SUB) CMAbv? CMBlw*)*; +consonant_modifiers = CMAbv* CMBlw* ((h B | SUB) CMAbv* CMBlw*)*; medial_consonants = MPre? MAbv? MBlw? MPst?; dependent_vowels = VPre* VAbv* VBlw* VPst* | H; vowel_modifiers = HVM? VMPre* VMAbv* VMBlw* VMPst*; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use.cc index 342aba12358..c35765af95a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shaper-use.cc @@ -377,6 +377,9 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) #define POST_BASE_FLAGS64 (FLAG64 (USE(FAbv)) | \ FLAG64 (USE(FBlw)) | \ FLAG64 (USE(FPst)) | \ + FLAG64 (USE(FMAbv)) | \ + FLAG64 (USE(FMBlw)) | \ + FLAG64 (USE(FMPst)) | \ FLAG64 (USE(MAbv)) | \ FLAG64 (USE(MBlw)) | \ FLAG64 (USE(MPst)) | \ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh index de553dd72ff..f7bb3791cab 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh @@ -57,6 +57,16 @@ enum // Reserved = 0xFFFC /* Reserved for future use — set to zero. */ }; +static bool axis_value_is_outside_axis_range (hb_tag_t axis_tag, float axis_value, + const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) +{ + if (!user_axes_location->has (axis_tag)) + return false; + + Triple axis_range = user_axes_location->get (axis_tag); + return (axis_value < axis_range.minimum || axis_value > axis_range.maximum); +} + struct StatAxisRecord { int cmp (hb_tag_t key) const { return tag.cmp (key); } @@ -96,23 +106,19 @@ struct AxisValueFormat1 } bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, - const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const { hb_tag_t axis_tag = get_axis_tag (axis_records); float axis_value = get_value (); - if (!user_axes_location->has (axis_tag) || - fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) - return true; - - return false; + return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location); } bool subset (hb_subset_context_t *c, const hb_array_t<const StatAxisRecord> axis_records) const { TRACE_SUBSET (this); - const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location; + const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location; if (keep_axis_value (axis_records, user_axes_location)) return_trace (c->serializer->embed (this)); @@ -155,23 +161,19 @@ struct AxisValueFormat2 } bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, - const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const { hb_tag_t axis_tag = get_axis_tag (axis_records); float axis_value = get_value (); - if (!user_axes_location->has (axis_tag) || - fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) - return true; - - return false; + return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location); } bool subset (hb_subset_context_t *c, const hb_array_t<const StatAxisRecord> axis_records) const { TRACE_SUBSET (this); - const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location; + const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location; if (keep_axis_value (axis_records, user_axes_location)) return_trace (c->serializer->embed (this)); @@ -218,23 +220,19 @@ struct AxisValueFormat3 } bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, - const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const { hb_tag_t axis_tag = get_axis_tag (axis_records); float axis_value = get_value (); - if (!user_axes_location->has (axis_tag) || - fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) - return true; - - return false; + return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location); } bool subset (hb_subset_context_t *c, const hb_array_t<const StatAxisRecord> axis_records) const { TRACE_SUBSET (this); - const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location; + const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location; if (keep_axis_value (axis_records, user_axes_location)) return_trace (c->serializer->embed (this)); @@ -291,7 +289,7 @@ struct AxisValueFormat4 { return axisValues.as_array (axisCount)[axis_index]; } bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, - const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const { hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount); @@ -301,8 +299,7 @@ struct AxisValueFormat4 float axis_value = rec.get_value (); hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag (); - if (user_axes_location->has (axis_tag) && - fabsf(axis_value - user_axes_location->get (axis_tag)) > 0.001f) + if (axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location)) return false; } @@ -313,7 +310,7 @@ struct AxisValueFormat4 const hb_array_t<const StatAxisRecord> axis_records) const { TRACE_SUBSET (this); - const hb_hashmap_t<hb_tag_t, float> *user_axes_location = &c->plan->user_axes_location; + const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location = &c->plan->user_axes_location; if (!keep_axis_value (axis_records, user_axes_location)) return_trace (false); @@ -402,7 +399,7 @@ struct AxisValue } bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, - hb_hashmap_t<hb_tag_t, float> *user_axes_location) const + hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const { switch (u.format) { @@ -451,8 +448,6 @@ struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>> const hb_array_t<const StatAxisRecord> axis_records) const { TRACE_SUBSET (this); - auto *out = c->serializer->start_embed (this); - if (unlikely (!out)) return_trace (false); auto axisValueOffsets = as_array (axisValueCount); count = 0; @@ -517,7 +512,7 @@ struct STAT return axis_value.get_value_name_id (); } - void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location, + void collect_name_ids (hb_hashmap_t<hb_tag_t, Triple> *user_axes_location, hb_set_t *nameids_to_retain /* OUT */) const { if (!has_data ()) return; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc index 547f9573d05..53b6b38f66d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc @@ -412,7 +412,7 @@ parse_private_use_subtag (const char *private_use_subtag, /** * hb_ot_tags_from_script_and_language: * @script: an #hb_script_t to convert. - * @language: an #hb_language_t to convert. + * @language: (nullable): an #hb_language_t to convert. * @script_count: (inout) (optional): maximum number of script tags to retrieve (IN) * and actual number of script tags retrieved (OUT) * @script_tags: (out) (optional): array of size at least @script_count to store the diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh index 7d4bf2241ca..44ec64bc03f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-common.hh @@ -36,19 +36,14 @@ struct DeltaSetIndexMapFormat01 { friend struct DeltaSetIndexMap; + unsigned get_size () const + { return min_size + mapCount * get_width (); } + private: DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); - auto *out = c->start_embed (this); - if (unlikely (!out)) return_trace (nullptr); - - unsigned total_size = min_size + mapCount * get_width (); - HBUINT8 *p = c->allocate_size<HBUINT8> (total_size); - if (unlikely (!p)) return_trace (nullptr); - - hb_memcpy (p, this, HBUINT8::static_size * total_size); - return_trace (out); + return_trace (c->embed (this)); } template <typename T> @@ -65,7 +60,7 @@ struct DeltaSetIndexMapFormat01 entryFormat = ((width-1)<<4)|(inner_bit_count-1); mapCount = output_map.length; - HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length); + HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length, false); if (unlikely (!p)) return_trace (false); for (unsigned int i = 0; i < output_map.length; i++) { @@ -242,6 +237,7 @@ struct VarStoreInstancer /* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */ struct TupleVariationHeader { + friend struct tuple_delta_t; unsigned get_size (unsigned axis_count) const { return min_size + get_all_tuples (axis_count).get_size (); } @@ -250,14 +246,67 @@ struct TupleVariationHeader const TupleVariationHeader &get_next (unsigned axis_count) const { return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count)); } + bool unpack_axis_tuples (unsigned axis_count, + const hb_array_t<const F2DOT14> shared_tuples, + const hb_map_t *axes_old_index_tag_map, + hb_hashmap_t<hb_tag_t, Triple>& axis_tuples /* OUT */) const + { + const F2DOT14 *peak_tuple = nullptr; + if (has_peak ()) + peak_tuple = get_peak_tuple (axis_count).arrayZ; + else + { + unsigned int index = get_index (); + if (unlikely ((index + 1) * axis_count > shared_tuples.length)) + return false; + peak_tuple = shared_tuples.sub_array (axis_count * index, axis_count).arrayZ; + } + + const F2DOT14 *start_tuple = nullptr; + const F2DOT14 *end_tuple = nullptr; + bool has_interm = has_intermediate (); + + if (has_interm) + { + start_tuple = get_start_tuple (axis_count).arrayZ; + end_tuple = get_end_tuple (axis_count).arrayZ; + } + + for (unsigned i = 0; i < axis_count; i++) + { + float peak = peak_tuple[i].to_float (); + if (peak == 0.f) continue; + + hb_tag_t *axis_tag; + if (!axes_old_index_tag_map->has (i, &axis_tag)) + return false; + + float start, end; + if (has_interm) + { + start = start_tuple[i].to_float (); + end = end_tuple[i].to_float (); + } + else + { + start = hb_min (peak, 0.f); + end = hb_max (peak, 0.f); + } + axis_tuples.set (*axis_tag, Triple (start, peak, end)); + } + + return true; + } + float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count, const hb_array_t<const F2DOT14> shared_tuples, - const hb_vector_t<int> *shared_tuple_active_idx = nullptr) const + const hb_vector_t<hb_pair_t<int,int>> *shared_tuple_active_idx = nullptr) const { const F2DOT14 *peak_tuple; unsigned start_idx = 0; unsigned end_idx = coord_count; + unsigned step = 1; if (has_peak ()) peak_tuple = get_peak_tuple (coord_count).arrayZ; @@ -272,10 +321,16 @@ struct TupleVariationHeader { if (unlikely (index >= shared_tuple_active_idx->length)) return 0.f; - int v = (*shared_tuple_active_idx).arrayZ[index]; - if (v != -1) + auto _ = (*shared_tuple_active_idx).arrayZ[index]; + if (_.second != -1) + { + start_idx = _.first; + end_idx = _.second + 1; + step = _.second - _.first; + } + else if (_.first != -1) { - start_idx = v; + start_idx = _.first; end_idx = start_idx + 1; } } @@ -291,7 +346,7 @@ struct TupleVariationHeader } float scalar = 1.f; - for (unsigned int i = start_idx; i < end_idx; i++) + for (unsigned int i = start_idx; i < end_idx; i += step) { int peak = peak_tuple[i].to_int (); if (!peak) continue; @@ -333,6 +388,7 @@ struct TupleVariationHeader TupleIndexMask = 0x0FFFu }; + TuppleIndex& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; } DEFINE_SIZE_STATIC (2); }; @@ -365,6 +421,468 @@ struct TupleVariationHeader DEFINE_SIZE_MIN (4); }; +/* not using hb_bytes_t: avoid potential build issues with some compilers */ +struct byte_data_t +{ + hb_bytes_t bytes; + + byte_data_t () = default; + byte_data_t (const char *p_, unsigned len_) : bytes (hb_bytes_t (p_, len_)) {} + + void fini () { bytes.fini (); } + + bool operator == (const byte_data_t& o) const + { return bytes.arrayZ == o.bytes.arrayZ && bytes.length == o.bytes.length; } + + explicit operator bool () const { return bytes.length; } + + void copy (hb_serialize_context_t *c) const + { c->embed (bytes.arrayZ, bytes.length); } +}; + +enum packed_delta_flag_t +{ + DELTAS_ARE_ZERO = 0x80, + DELTAS_ARE_WORDS = 0x40, + DELTA_RUN_COUNT_MASK = 0x3F +}; + +struct tuple_delta_t +{ + public: + hb_hashmap_t<hb_tag_t, Triple> axis_tuples; + + /* indices_length = point_count, indice[i] = 1 means point i is referenced */ + hb_vector_t<bool> indices; + + hb_vector_t<float> deltas_x; + /* empty for cvar tuples */ + hb_vector_t<float> deltas_y; + + /* compiled data: header and deltas + * compiled point data is saved in a hashmap within tuple_variations_t cause + * some point sets might be reused by different tuple variations */ + hb_vector_t<char> compiled_tuple_header; + hb_vector_t<char> compiled_deltas; + + tuple_delta_t () = default; + tuple_delta_t (const tuple_delta_t& o) = default; + + tuple_delta_t (tuple_delta_t&& o) : tuple_delta_t () + { + axis_tuples = std::move (o.axis_tuples); + indices = std::move (o.indices); + deltas_x = std::move (o.deltas_x); + deltas_y = std::move (o.deltas_y); + } + + tuple_delta_t& operator = (tuple_delta_t&& o) + { + hb_swap (*this, o); + return *this; + } + + void remove_axis (hb_tag_t axis_tag) + { axis_tuples.del (axis_tag); } + + bool set_tent (hb_tag_t axis_tag, Triple tent) + { return axis_tuples.set (axis_tag, tent); } + + tuple_delta_t& operator += (const tuple_delta_t& o) + { + unsigned num = indices.length; + for (unsigned i = 0; i < num; i++) + { + if (indices.arrayZ[i]) + { + if (o.indices.arrayZ[i]) + { + deltas_x[i] += o.deltas_x[i]; + if (deltas_y && o.deltas_y) + deltas_y[i] += o.deltas_y[i]; + } + } + else + { + if (!o.indices.arrayZ[i]) continue; + deltas_x[i] = o.deltas_x[i]; + if (deltas_y && o.deltas_y) + deltas_y[i] = o.deltas_y[i]; + } + } + return *this; + } + + tuple_delta_t& operator *= (float scalar) + { + if (scalar == 1.0f) + return *this; + + unsigned num = indices.length; + for (unsigned i = 0; i < num; i++) + { + if (!indices.arrayZ[i]) continue; + + deltas_x[i] *= scalar; + if (deltas_y) + deltas_y[i] *= scalar; + } + return *this; + } + + hb_vector_t<tuple_delta_t> change_tuple_var_axis_limit (hb_tag_t axis_tag, Triple axis_limit) const + { + hb_vector_t<tuple_delta_t> out; + Triple *tent; + if (!axis_tuples.has (axis_tag, &tent)) + { + out.push (*this); + return out; + } + + if ((tent->minimum < 0.f && tent->maximum > 0.f) || + !(tent->minimum <= tent->middle && tent->middle <= tent->maximum)) + return out; + + if (tent->middle == 0.f) + { + out.push (*this); + return out; + } + + result_t solutions = rebase_tent (*tent, axis_limit); + for (auto t : solutions) + { + tuple_delta_t new_var = *this; + if (t.second == Triple ()) + new_var.remove_axis (axis_tag); + else + new_var.set_tent (axis_tag, t.second); + + new_var *= t.first; + out.push (std::move (new_var)); + } + + return out; + } + + /* deltas should be compiled already before we compile tuple + * variation header cause we need to fill in the size of the + * serialized data for this tuple variation */ + //TODO(qxliu):add option to use sharedTuples in gvar + bool compile_tuple_var_header (const hb_map_t& axes_index_map, + unsigned points_data_length, + const hb_map_t& axes_old_index_tag_map) + { + if (!compiled_deltas) return false; + + unsigned cur_axis_count = axes_index_map.get_population (); + /* allocate enough memory: 1 peak + 2 intermediate coords + fixed header size */ + unsigned alloc_len = 3 * cur_axis_count * (F2DOT14::static_size) + 4; + if (unlikely (!compiled_tuple_header.resize (alloc_len))) return false; + + unsigned flag = 0; + /* skip the first 4 header bytes: variationDataSize+tupleIndex */ + F2DOT14* p = reinterpret_cast<F2DOT14 *> (compiled_tuple_header.begin () + 4); + F2DOT14* end = reinterpret_cast<F2DOT14 *> (compiled_tuple_header.end ()); + hb_array_t<F2DOT14> coords (p, end - p); + + /* encode peak coords */ + unsigned peak_count = encode_peak_coords(coords, flag, axes_index_map, axes_old_index_tag_map); + if (!peak_count) return false; + + /* encode interim coords, it's optional so returned num could be 0 */ + unsigned interim_count = encode_interm_coords (coords.sub_array (peak_count), flag, axes_index_map, axes_old_index_tag_map); + + //TODO(qxliu): add option to use shared_points in gvar + flag |= TupleVariationHeader::TuppleIndex::PrivatePointNumbers; + + unsigned serialized_data_size = points_data_length + compiled_deltas.length; + TupleVariationHeader *o = reinterpret_cast<TupleVariationHeader *> (compiled_tuple_header.begin ()); + o->varDataSize = serialized_data_size; + o->tupleIndex = flag; + + unsigned total_header_len = 4 + (peak_count + interim_count) * (F2DOT14::static_size); + return compiled_tuple_header.resize (total_header_len); + } + + unsigned encode_peak_coords (hb_array_t<F2DOT14> peak_coords, + unsigned& flag, + const hb_map_t& axes_index_map, + const hb_map_t& axes_old_index_tag_map) const + { + unsigned orig_axis_count = axes_old_index_tag_map.get_population (); + auto it = peak_coords.iter (); + unsigned count = 0; + for (unsigned i = 0; i < orig_axis_count; i++) + { + if (!axes_index_map.has (i)) /* axis pinned */ + continue; + hb_tag_t axis_tag = axes_old_index_tag_map.get (i); + Triple *coords; + if (!axis_tuples.has (axis_tag, &coords)) + (*it).set_int (0); + else + (*it).set_float (coords->middle); + it++; + count++; + } + flag |= TupleVariationHeader::TuppleIndex::EmbeddedPeakTuple; + return count; + } + + /* if no need to encode intermediate coords, then just return p */ + unsigned encode_interm_coords (hb_array_t<F2DOT14> coords, + unsigned& flag, + const hb_map_t& axes_index_map, + const hb_map_t& axes_old_index_tag_map) const + { + unsigned orig_axis_count = axes_old_index_tag_map.get_population (); + unsigned cur_axis_count = axes_index_map.get_population (); + + auto start_coords_iter = coords.sub_array (0, cur_axis_count).iter (); + auto end_coords_iter = coords.sub_array (cur_axis_count).iter (); + bool encode_needed = false; + unsigned count = 0; + for (unsigned i = 0; i < orig_axis_count; i++) + { + if (!axes_index_map.has (i)) /* axis pinned */ + continue; + hb_tag_t axis_tag = axes_old_index_tag_map.get (i); + Triple *coords; + float min_val = 0.f, val = 0.f, max_val = 0.f; + if (axis_tuples.has (axis_tag, &coords)) + { + min_val = coords->minimum; + val = coords->middle; + max_val = coords->maximum; + } + + (*start_coords_iter).set_float (min_val); + (*end_coords_iter).set_float (max_val); + + start_coords_iter++; + end_coords_iter++; + count += 2; + if (min_val != hb_min (val, 0.f) || max_val != hb_max (val, 0.f)) + encode_needed = true; + } + + if (encode_needed) + { + flag |= TupleVariationHeader::TuppleIndex::IntermediateRegion; + return count; + } + return 0; + } + + bool compile_deltas () + { + hb_vector_t<int> rounded_deltas; + if (unlikely (!rounded_deltas.alloc (indices.length))) + return false; + + for (unsigned i = 0; i < indices.length; i++) + { + if (!indices[i]) continue; + int rounded_delta = (int) roundf (deltas_x[i]); + rounded_deltas.push (rounded_delta); + } + + if (!rounded_deltas) return false; + /* allocate enough memories 3 * num_deltas */ + unsigned alloc_len = 3 * rounded_deltas.length; + if (deltas_y) + alloc_len *= 2; + + if (unlikely (!compiled_deltas.resize (alloc_len))) return false; + + unsigned i = 0; + unsigned encoded_len = encode_delta_run (i, compiled_deltas.as_array (), rounded_deltas); + + if (deltas_y) + { + /* reuse the rounded_deltas vector, check that deltas_y have the same num of deltas as deltas_x */ + unsigned j = 0; + for (unsigned idx = 0; idx < indices.length; idx++) + { + if (!indices[idx]) continue; + int rounded_delta = (int) roundf (deltas_y[idx]); + + if (j >= rounded_deltas.length) return false; + + rounded_deltas[j++] = rounded_delta; + } + + if (j != rounded_deltas.length) return false; + encoded_len += encode_delta_run (i, compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas); + } + return compiled_deltas.resize (encoded_len); + } + + unsigned encode_delta_run (unsigned& i, + hb_array_t<char> encoded_bytes, + const hb_vector_t<int>& deltas) const + { + unsigned num_deltas = deltas.length; + unsigned encoded_len = 0; + while (i < num_deltas) + { + int val = deltas[i]; + if (val == 0) + encoded_len += encode_delta_run_as_zeroes (i, encoded_bytes.sub_array (encoded_len), deltas); + else if (val >= -128 && val <= 127) + encoded_len += encode_delta_run_as_bytes (i, encoded_bytes.sub_array (encoded_len), deltas); + else + encoded_len += encode_delta_run_as_words (i, encoded_bytes.sub_array (encoded_len), deltas); + } + return encoded_len; + } + + unsigned encode_delta_run_as_zeroes (unsigned& i, + hb_array_t<char> encoded_bytes, + const hb_vector_t<int>& deltas) const + { + unsigned num_deltas = deltas.length; + unsigned run_length = 0; + auto it = encoded_bytes.iter (); + unsigned encoded_len = 0; + while (i < num_deltas && deltas[i] == 0) + { + i++; + run_length++; + } + + while (run_length >= 64) + { + *it++ = (DELTAS_ARE_ZERO | 63); + run_length -= 64; + encoded_len++; + } + + if (run_length) + { + *it++ = (DELTAS_ARE_ZERO | (run_length - 1)); + encoded_len++; + } + return encoded_len; + } + + unsigned encode_delta_run_as_bytes (unsigned &i, + hb_array_t<char> encoded_bytes, + const hb_vector_t<int>& deltas) const + { + unsigned start = i; + unsigned num_deltas = deltas.length; + while (i < num_deltas) + { + int val = deltas[i]; + if (val > 127 || val < -128) + break; + + /* from fonttools: if there're 2 or more zeros in a sequence, + * it is better to start a new run to save bytes. */ + if (val == 0 && i + 1 < num_deltas && deltas[i+1] == 0) + break; + + i++; + } + unsigned run_length = i - start; + + unsigned encoded_len = 0; + auto it = encoded_bytes.iter (); + + while (run_length >= 64) + { + *it++ = 63; + encoded_len++; + + for (unsigned j = 0; j < 64; j++) + { + *it++ = static_cast<char> (deltas[start + j]); + encoded_len++; + } + + start += 64; + run_length -= 64; + } + + if (run_length) + { + *it++ = run_length - 1; + encoded_len++; + + while (start < i) + { + *it++ = static_cast<char> (deltas[start++]); + encoded_len++; + } + } + + return encoded_len; + } + + unsigned encode_delta_run_as_words (unsigned &i, + hb_array_t<char> encoded_bytes, + const hb_vector_t<int>& deltas) const + { + unsigned start = i; + unsigned num_deltas = deltas.length; + while (i < num_deltas) + { + int val = deltas[i]; + + /* start a new run for a single zero value*/ + if (val == 0) break; + + /* from fonttools: continue word-encoded run if there's only one + * single value in the range [-128, 127] because it is more compact. + * Only start a new run when there're 2 continuous such values. */ + if (val >= -128 && val <= 127 && + i + 1 < num_deltas && + deltas[i+1] >= -128 && deltas[i+1] <= 127) + break; + + i++; + } + + unsigned run_length = i - start; + auto it = encoded_bytes.iter (); + unsigned encoded_len = 0; + while (run_length >= 64) + { + *it++ = (DELTAS_ARE_WORDS | 63); + encoded_len++; + + for (unsigned j = 0; j < 64; j++) + { + int16_t delta_val = deltas[start + j]; + *it++ = static_cast<char> (delta_val >> 8); + *it++ = static_cast<char> (delta_val & 0xFF); + + encoded_len += 2; + } + + start += 64; + run_length -= 64; + } + + if (run_length) + { + *it++ = (DELTAS_ARE_WORDS | (run_length - 1)); + while (start < i) + { + int16_t delta_val = deltas[start++]; + *it++ = static_cast<char> (delta_val >> 8); + *it++ = static_cast<char> (delta_val & 0xFF); + + encoded_len += 2; + } + } + return encoded_len; + } +}; + struct TupleVariationData { bool sanitize (hb_sanitize_context_t *c) const @@ -378,7 +896,7 @@ struct TupleVariationData unsigned get_size (unsigned axis_count) const { unsigned total_size = min_size; - unsigned count = tupleVarCount; + unsigned count = tupleVarCount.get_count (); const TupleVariationHeader *tuple_var_header = &(get_tuple_var_header()); for (unsigned i = 0; i < count; i++) { @@ -392,8 +910,354 @@ struct TupleVariationData const TupleVariationHeader &get_tuple_var_header (void) const { return StructAfter<TupleVariationHeader> (data); } + struct tuple_iterator_t; + struct tuple_variations_t + { + hb_vector_t<tuple_delta_t> tuple_vars; + + private: + /* referenced point set->compiled point data map */ + hb_hashmap_t<const hb_vector_t<bool>*, byte_data_t> point_data_map; + /* referenced point set-> count map, used in finding shared points */ + hb_hashmap_t<const hb_vector_t<bool>*, unsigned> point_set_count_map; + + public: + ~tuple_variations_t () { fini (); } + void fini () + { + for (auto _ : point_data_map.values ()) + _.fini (); + + point_set_count_map.fini (); + tuple_vars.fini (); + } + + unsigned get_var_count () const + { return tuple_vars.length; } + + bool create_from_tuple_var_data (tuple_iterator_t iterator, + unsigned tuple_var_count, + unsigned point_count, + bool is_gvar, + const hb_map_t *axes_old_index_tag_map, + const hb_vector_t<unsigned> &shared_indices, + const hb_array_t<const F2DOT14> shared_tuples) + { + do + { + const HBUINT8 *p = iterator.get_serialized_data (); + unsigned int length = iterator.current_tuple->get_data_size (); + if (unlikely (!iterator.var_data_bytes.check_range (p, length))) + { fini (); return false; } + + hb_hashmap_t<hb_tag_t, Triple> axis_tuples; + if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, axes_old_index_tag_map, axis_tuples) + || axis_tuples.is_empty ()) + { fini (); return false; } + + hb_vector_t<unsigned> private_indices; + bool has_private_points = iterator.current_tuple->has_private_points (); + const HBUINT8 *end = p + length; + if (has_private_points && + !TupleVariationData::unpack_points (p, private_indices, end)) + { fini (); return false; } + + const hb_vector_t<unsigned> &indices = has_private_points ? private_indices : shared_indices; + bool apply_to_all = (indices.length == 0); + unsigned num_deltas = apply_to_all ? point_count : indices.length; + + hb_vector_t<int> deltas_x; + + if (unlikely (!deltas_x.resize (num_deltas, false) || + !TupleVariationData::unpack_deltas (p, deltas_x, end))) + { fini (); return false; } + + hb_vector_t<int> deltas_y; + if (is_gvar) + { + if (unlikely (!deltas_y.resize (num_deltas, false) || + !TupleVariationData::unpack_deltas (p, deltas_y, end))) + { fini (); return false; } + } + + tuple_delta_t var; + var.axis_tuples = std::move (axis_tuples); + if (unlikely (!var.indices.resize (point_count) || + !var.deltas_x.resize (point_count, false))) + { fini (); return false; } + + if (is_gvar && unlikely (!var.deltas_y.resize (point_count, false))) + { fini (); return false; } + + for (unsigned i = 0; i < num_deltas; i++) + { + unsigned idx = apply_to_all ? i : indices[i]; + if (idx >= point_count) continue; + var.indices[idx] = true; + var.deltas_x[idx] = static_cast<float> (deltas_x[i]); + if (is_gvar) + var.deltas_y[idx] = static_cast<float> (deltas_y[i]); + } + tuple_vars.push (std::move (var)); + } while (iterator.move_to_next ()); + return true; + } + + void change_tuple_variations_axis_limits (const hb_hashmap_t<hb_tag_t, Triple> *normalized_axes_location) + { + for (auto _ : *normalized_axes_location) + { + hb_tag_t axis_tag = _.first; + Triple axis_limit = _.second; + hb_vector_t<tuple_delta_t> new_vars; + for (const tuple_delta_t& var : tuple_vars) + { + hb_vector_t<tuple_delta_t> out = var.change_tuple_var_axis_limit (axis_tag, axis_limit); + if (!out) continue; + unsigned new_len = new_vars.length + out.length; + + if (unlikely (!new_vars.alloc (new_len, false))) + { fini (); return;} + + for (unsigned i = 0; i < out.length; i++) + new_vars.push (std::move (out[i])); + } + tuple_vars.fini (); + tuple_vars = std::move (new_vars); + } + } + + /* merge tuple variations with overlapping tents */ + void merge_tuple_variations () + { + hb_vector_t<tuple_delta_t> new_vars; + hb_hashmap_t<hb_hashmap_t<hb_tag_t, Triple>, unsigned> m; + unsigned i = 0; + for (const tuple_delta_t& var : tuple_vars) + { + /* if all axes are pinned, drop the tuple variation */ + if (var.axis_tuples.is_empty ()) continue; + + unsigned *idx; + if (m.has (var.axis_tuples, &idx)) + { + new_vars[*idx] += var; + } + else + { + new_vars.push (var); + m.set (var.axis_tuples, i); + i++; + } + } + tuple_vars.fini (); + tuple_vars = std::move (new_vars); + } + + byte_data_t compile_point_set (const hb_vector_t<bool> &point_indices) + { + unsigned num_points = 0; + for (bool i : point_indices) + if (i) num_points++; + + unsigned indices_length = point_indices.length; + /* If the points set consists of all points in the glyph, it's encoded with a + * single zero byte */ + if (num_points == indices_length) + { + char *p = (char *) hb_calloc (1, sizeof (char)); + if (unlikely (!p)) return byte_data_t (); + + return byte_data_t (p, 1); + } + + /* allocate enough memories: 2 bytes for count + 3 bytes for each point */ + unsigned num_bytes = 2 + 3 *num_points; + char *p = (char *) hb_calloc (num_bytes, sizeof (char)); + if (unlikely (!p)) return byte_data_t (); + + unsigned pos = 0; + /* binary data starts with the total number of reference points */ + if (num_points < 0x80) + p[pos++] = num_points; + else + { + p[pos++] = ((num_points >> 8) | 0x80); + p[pos++] = num_points & 0xFF; + } + + const unsigned max_run_length = 0x7F; + unsigned i = 0; + unsigned last_value = 0; + unsigned num_encoded = 0; + while (i < indices_length && num_encoded < num_points) + { + unsigned run_length = 0; + unsigned header_pos = pos; + p[pos++] = 0; + + bool use_byte_encoding = false; + bool new_run = true; + while (i < indices_length && num_encoded < num_points && + run_length <= max_run_length) + { + // find out next referenced point index + while (i < indices_length && !point_indices[i]) + i++; + + if (i >= indices_length) break; + + unsigned cur_value = i; + unsigned delta = cur_value - last_value; + + if (new_run) + { + use_byte_encoding = (delta <= 0xFF); + new_run = false; + } + + if (use_byte_encoding && delta > 0xFF) + break; + + if (use_byte_encoding) + p[pos++] = delta; + else + { + p[pos++] = delta >> 8; + p[pos++] = delta & 0xFF; + } + i++; + last_value = cur_value; + run_length++; + num_encoded++; + } + + if (use_byte_encoding) + p[header_pos] = run_length - 1; + else + p[header_pos] = (run_length - 1) | 0x80; + } + return byte_data_t (p, pos); + } + + /* compile all point set and store byte data in a point_set->byte_data_t hashmap, + * also update point_set->count map, which will be used in finding shared + * point set*/ + bool compile_all_point_sets () + { + for (const auto& tuple: tuple_vars) + { + const hb_vector_t<bool>* points_set = &(tuple.indices); + if (point_data_map.has (points_set)) + { + unsigned *count; + if (unlikely (!point_set_count_map.has (points_set, &count) || + !point_set_count_map.set (points_set, (*count) + 1))) + return false; + continue; + } + + byte_data_t compiled_data = compile_point_set (*points_set); + if (unlikely (compiled_data == byte_data_t ())) + return false; + + if (!point_data_map.set (points_set, compiled_data) || + !point_set_count_map.set (points_set, 1)) + return false; + } + return true; + } + + /* find shared points set which saves most bytes */ + byte_data_t find_shared_points () + { + unsigned max_saved_bytes = 0; + byte_data_t res{}; + + for (const auto& _ : point_data_map.iter ()) + { + const hb_vector_t<bool>* points_set = _.first; + unsigned data_length = _.second.bytes.length; + unsigned *count; + if (unlikely (!point_set_count_map.has (points_set, &count) || + *count <= 1)) + return byte_data_t (); + + unsigned saved_bytes = data_length * ((*count) -1); + if (saved_bytes > max_saved_bytes) + { + max_saved_bytes = saved_bytes; + res = _.second; + } + } + return res; + } + + void instantiate (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location) + { + change_tuple_variations_axis_limits (&normalized_axes_location); + merge_tuple_variations (); + } + + bool compile_bytes (const hb_map_t& axes_index_map, + const hb_map_t& axes_old_index_tag_map) + { + // compile points set and store data in hashmap + if (!compile_all_point_sets ()) + return false; + // compile delta and tuple var header for each tuple variation + for (auto& tuple: tuple_vars) + { + const hb_vector_t<bool>* points_set = &(tuple.indices); + byte_data_t *points_data; + if (unlikely (!point_data_map.has (points_set, &points_data))) + return false; + + if (!tuple.compile_deltas ()) + return false; + + if (!tuple.compile_tuple_var_header (axes_index_map, points_data->bytes.length, axes_old_index_tag_map)) + return false; + } + return true; + } + + bool serialize_var_headers (hb_serialize_context_t *c, unsigned& total_header_len) const + { + TRACE_SERIALIZE (this); + for (const auto& tuple: tuple_vars) + { + byte_data_t compiled_bytes {tuple.compiled_tuple_header.arrayZ, tuple.compiled_tuple_header.length}; + compiled_bytes.copy (c); + if (c->in_error ()) return_trace (false); + total_header_len += tuple.compiled_tuple_header.length; + } + return_trace (true); + } + + bool serialize_var_data (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + for (const auto& tuple: tuple_vars) + { + const hb_vector_t<bool>* points_set = &(tuple.indices); + byte_data_t *point_data; + if (!point_data_map.has (points_set, &point_data)) + return_trace (false); + + point_data->copy (c); + byte_data_t compiled_bytes {tuple.compiled_deltas.arrayZ, tuple.compiled_deltas.length}; + compiled_bytes.copy (c); + if (c->in_error ()) return_trace (false); + } + return_trace (true); + } + }; + struct tuple_iterator_t { + unsigned get_axis_count () const { return axis_count; } + void init (hb_bytes_t var_data_bytes_, unsigned int axis_count_, const void *table_base_) { var_data_bytes = var_data_bytes_; @@ -517,13 +1381,6 @@ struct TupleVariationData hb_vector_t<int> &deltas /* IN/OUT */, const HBUINT8 *end) { - enum packed_delta_flag_t - { - DELTAS_ARE_ZERO = 0x80, - DELTAS_ARE_WORDS = 0x40, - DELTA_RUN_COUNT_MASK = 0x3F - }; - unsigned i = 0; unsigned count = deltas.length; while (i < count) @@ -561,11 +1418,50 @@ struct TupleVariationData bool has_data () const { return tupleVarCount; } + bool decompile_tuple_variations (unsigned point_count, + bool is_gvar, + tuple_iterator_t iterator, + const hb_map_t *axes_old_index_tag_map, + const hb_vector_t<unsigned> &shared_indices, + const hb_array_t<const F2DOT14> shared_tuples, + tuple_variations_t& tuple_variations /* OUT */) const + { + return tuple_variations.create_from_tuple_var_data (iterator, tupleVarCount, + point_count, is_gvar, + axes_old_index_tag_map, + shared_indices, + shared_tuples); + } + + bool serialize (hb_serialize_context_t *c, + bool is_gvar, + tuple_variations_t& tuple_variations) const + { + TRACE_SERIALIZE (this); + auto *out = c->start_embed (this); + if (unlikely (!c->extend_min (out))) return_trace (false); + + if (!c->check_assign (out->tupleVarCount, tuple_variations.get_var_count (), + HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); + + unsigned total_header_len = 0; + + if (!tuple_variations.serialize_var_headers (c, total_header_len)) + return_trace (false); + + unsigned data_offset = min_size + total_header_len; + if (!is_gvar) data_offset += 4; + if (!c->check_assign (out->data, data_offset, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); + + return tuple_variations.serialize_var_data (c); + } + protected: struct TupleVarCount : HBUINT16 { bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); } unsigned int get_count () const { return (*this) & CountMask; } + TupleVarCount& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; } protected: enum Flags diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh index 7fd0f1d79d6..de543393013 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-cvar-table.hh @@ -27,6 +27,7 @@ #define HB_OT_VAR_CVAR_TABLE_HH #include "hb-ot-var-common.hh" +#include "hb-ot-var-fvar-table.hh" namespace OT { @@ -51,6 +52,27 @@ struct cvar const TupleVariationData* get_tuple_var_data (void) const { return &tupleVariationData; } + bool decompile_tuple_variations (unsigned axis_count, + unsigned point_count, + bool is_gvar, + const hb_map_t *axes_old_index_tag_map, + TupleVariationData::tuple_variations_t& tuple_variations /* OUT */) const + { + hb_vector_t<unsigned> shared_indices; + TupleVariationData::tuple_iterator_t iterator; + unsigned var_data_length = tupleVariationData.get_size (axis_count); + hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast<const char*> (get_tuple_var_data ()), var_data_length); + if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, this, + shared_indices, &iterator)) + return false; + + return tupleVariationData.decompile_tuple_variations (point_count, is_gvar, iterator, + axes_old_index_tag_map, + shared_indices, + hb_array<const F2DOT14> (), + tuple_variations); + } + static bool calculate_cvt_deltas (unsigned axis_count, hb_array_t<int> coords, unsigned num_cvt_item, @@ -104,6 +126,53 @@ struct cvar return true; } + + bool serialize (hb_serialize_context_t *c, + TupleVariationData::tuple_variations_t& tuple_variations) const + { + TRACE_SERIALIZE (this); + if (unlikely (!c->embed (version))) return_trace (false); + + return_trace (tupleVariationData.serialize (c, false, tuple_variations)); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + if (c->plan->all_axes_pinned) + return_trace (false); + + /* subset() for cvar is called by partial instancing only, we always pass + * through cvar table in other cases */ + if (!c->plan->normalized_coords) + { + unsigned axis_count = c->plan->source->table.fvar->get_axis_count (); + unsigned total_size = min_size + tupleVariationData.get_size (axis_count); + char *out = c->serializer->allocate_size<char> (total_size); + if (unlikely (!out)) return_trace (false); + + hb_memcpy (out, this, total_size); + return_trace (true); + } + + OT::TupleVariationData::tuple_variations_t tuple_variations; + unsigned axis_count = c->plan->axes_old_index_tag_map.get_population (); + + const hb_tag_t cvt = HB_TAG('c','v','t',' '); + hb_blob_t *cvt_blob = hb_face_reference_table (c->plan->source, cvt); + unsigned point_count = hb_blob_get_length (cvt_blob) / FWORD::static_size; + + if (!decompile_tuple_variations (axis_count, point_count, false, + &(c->plan->axes_old_index_tag_map), + tuple_variations)) + return_trace (false); + + tuple_variations.instantiate (c->plan->axes_location); + if (!tuple_variations.compile_bytes (c->plan->axes_index_map, c->plan->axes_old_index_tag_map)) + return_trace (false); + + return_trace (serialize (c->serializer, tuple_variations)); + } static bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan, const TupleVariationData *tuple_var_data, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh index a384dfa531d..d8e789cb44b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh @@ -39,6 +39,24 @@ namespace OT { +static bool axis_coord_pinned_or_within_axis_range (const hb_array_t<const F16DOT16> coords, + unsigned axis_index, + Triple axis_limit) +{ + float axis_coord = coords[axis_index].to_float (); + if (axis_limit.is_point ()) + { + if (axis_limit.minimum != axis_coord) + return false; + } + else + { + if (axis_coord < axis_limit.minimum || + axis_coord > axis_limit.maximum) + return false; + } + return true; +} struct InstanceRecord { @@ -47,6 +65,27 @@ struct InstanceRecord hb_array_t<const F16DOT16> get_coordinates (unsigned int axis_count) const { return coordinatesZ.as_array (axis_count); } + bool keep_instance (unsigned axis_count, + const hb_map_t *axes_index_tag_map, + const hb_hashmap_t<hb_tag_t, Triple> *axes_location) const + { + if (axes_location->is_empty ()) return true; + const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count); + for (unsigned i = 0 ; i < axis_count; i++) + { + uint32_t *axis_tag; + if (!axes_index_tag_map->has (i, &axis_tag)) + return false; + if (!axes_location->has (*axis_tag)) + continue; + + Triple axis_limit = axes_location->get (*axis_tag); + if (!axis_coord_pinned_or_within_axis_range (coords, i, axis_limit)) + return false; + } + return true; + } + bool subset (hb_subset_context_t *c, unsigned axis_count, bool has_postscript_nameid) const @@ -56,19 +95,22 @@ struct InstanceRecord if (unlikely (!c->serializer->embed (flags))) return_trace (false); const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count); - const hb_hashmap_t<hb_tag_t, float> *axes_location = &c->plan->user_axes_location; + const hb_hashmap_t<hb_tag_t, Triple> *axes_location = &c->plan->user_axes_location; for (unsigned i = 0 ; i < axis_count; i++) { uint32_t *axis_tag; // only keep instances whose coordinates == pinned axis location if (!c->plan->axes_old_index_tag_map.has (i, &axis_tag)) continue; - - if (axes_location->has (*axis_tag) && - fabsf (axes_location->get (*axis_tag) - coords[i].to_float ()) > 0.001f) - return_trace (false); - - if (!c->plan->axes_index_map.has (i)) - continue; + if (axes_location->has (*axis_tag)) + { + Triple axis_limit = axes_location->get (*axis_tag); + if (!axis_coord_pinned_or_within_axis_range (coords, i, axis_limit)) + return_trace (false); + + //skip pinned axis + if (axis_limit.is_point ()) + continue; + } if (!c->serializer->embed (coords[i])) return_trace (false); @@ -216,7 +258,8 @@ struct fvar axisSize == 20 && /* Assumed in our code. */ instanceSize >= axisCount * 4 + 4 && get_axes ().sanitize (c) && - c->check_range (get_instance (0), instanceCount, instanceSize)); + c->check_range (&StructAfter<InstanceRecord> (get_axes ()), + instanceCount, instanceSize)); } unsigned int get_axis_count () const { return axisCount; } @@ -314,21 +357,19 @@ struct fvar return axisCount; } - void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location, + void collect_name_ids (hb_hashmap_t<hb_tag_t, Triple> *user_axes_location, + hb_map_t *axes_old_index_tag_map, hb_set_t *nameids /* IN/OUT */) const { if (!has_data ()) return; - hb_map_t pinned_axes; auto axis_records = get_axes (); for (unsigned i = 0 ; i < (unsigned)axisCount; i++) { hb_tag_t axis_tag = axis_records[i].get_axis_tag (); - if (user_axes_location->has (axis_tag)) - { - pinned_axes.set (i, axis_tag); + if (user_axes_location->has (axis_tag) && + user_axes_location->get (axis_tag).is_point ()) continue; - } nameids->add (axis_records[i].get_name_id ()); } @@ -337,16 +378,7 @@ struct fvar { const InstanceRecord *instance = get_instance (i); - if (hb_any (+ hb_enumerate (instance->get_coordinates (axisCount)) - | hb_filter (pinned_axes, hb_first) - | hb_map ([&] (const hb_pair_t<unsigned, const F16DOT16&>& _) - { - hb_tag_t axis_tag = pinned_axes.get (_.first); - float location = user_axes_location->get (axis_tag); - if (fabs ((double)location - (double)_.second.to_float ()) > 0.001) return true; - return false; - }) - )) + if (!instance->keep_instance (axisCount, axes_old_index_tag_map, user_axes_location)) continue; nameids->add (instance->subfamilyNameID); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh index ece892e1dd5..b5099ac0748 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh @@ -50,13 +50,14 @@ struct contour_point_t y = x * matrix[1] + y * matrix[3]; x = x_; } + HB_ALWAYS_INLINE void translate (const contour_point_t &p) { x += p.x; y += p.y; } - float x = 0.f; - float y = 0.f; - uint8_t flag = 0; - bool is_end_point = false; + float x; + float y; + uint8_t flag; + bool is_end_point; }; struct contour_point_vector_t : hb_vector_t<contour_point_t> @@ -110,20 +111,20 @@ struct gvar unsigned int num_glyphs = c->plan->num_output_glyphs (); out->glyphCountX = hb_min (0xFFFFu, num_glyphs); + auto it = hb_iter (c->plan->new_to_old_gid_list); + if (it->first == 0 && !(c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) + it++; unsigned int subset_data_size = 0; - for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1; - gid < num_glyphs; - gid++) + for (auto &_ : it) { - hb_codepoint_t old_gid; - if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue; + hb_codepoint_t old_gid = _.second; subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length; } bool long_offset = subset_data_size & ~0xFFFFu; out->flags = long_offset ? 1 : 0; - HBUINT8 *subset_offsets = c->serializer->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1)); + HBUINT8 *subset_offsets = c->serializer->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1), false); if (!subset_offsets) return_trace (false); /* shared tuples */ @@ -138,36 +139,61 @@ struct gvar hb_memcpy (tuples, this+sharedTuples, shared_tuple_size); } - char *subset_data = c->serializer->allocate_size<char> (subset_data_size); + char *subset_data = c->serializer->allocate_size<char> (subset_data_size, false); if (!subset_data) return_trace (false); out->dataZ = subset_data - (char *) out; + + if (long_offset) + { + ((HBUINT32 *) subset_offsets)[0] = 0; + subset_offsets += 4; + } + else + { + ((HBUINT16 *) subset_offsets)[0] = 0; + subset_offsets += 2; + } unsigned int glyph_offset = 0; - for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1; - gid < num_glyphs; - gid++) + + hb_codepoint_t last = 0; + it = hb_iter (c->plan->new_to_old_gid_list); + if (it->first == 0 && !(c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) + it++; + for (auto &_ : it) { - hb_codepoint_t old_gid; - hb_bytes_t var_data_bytes = c->plan->old_gid_for_new_gid (gid, &old_gid) - ? get_glyph_var_data_bytes (c->source_blob, + hb_codepoint_t gid = _.first; + hb_codepoint_t old_gid = _.second; + + if (long_offset) + for (; last < gid; last++) + ((HBUINT32 *) subset_offsets)[last] = glyph_offset; + else + for (; last < gid; last++) + ((HBUINT16 *) subset_offsets)[last] = glyph_offset / 2; + + hb_bytes_t var_data_bytes = get_glyph_var_data_bytes (c->source_blob, glyph_count, - old_gid) - : hb_bytes_t (); + old_gid); + + hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length); + subset_data += var_data_bytes.length; + glyph_offset += var_data_bytes.length; if (long_offset) ((HBUINT32 *) subset_offsets)[gid] = glyph_offset; else ((HBUINT16 *) subset_offsets)[gid] = glyph_offset / 2; - if (var_data_bytes.length > 0) - hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length); - subset_data += var_data_bytes.length; - glyph_offset += var_data_bytes.length; + last++; // Skip over gid } + if (long_offset) - ((HBUINT32 *) subset_offsets)[num_glyphs] = glyph_offset; + for (; last < num_glyphs; last++) + ((HBUINT32 *) subset_offsets)[last] = glyph_offset; else - ((HBUINT16 *) subset_offsets)[num_glyphs] = glyph_offset / 2; + for (; last < num_glyphs; last++) + ((HBUINT16 *) subset_offsets)[last] = glyph_offset / 2; return_trace (true); } @@ -216,21 +242,24 @@ struct gvar for (unsigned i = 0; i < count; i++) { hb_array_t<const F2DOT14> tuple = shared_tuples.sub_array (axis_count * i, axis_count); - int idx = -1; + int idx1 = -1, idx2 = -1; for (unsigned j = 0; j < axis_count; j++) { const F2DOT14 &peak = tuple.arrayZ[j]; if (peak.to_int () != 0) { - if (idx != -1) + if (idx1 == -1) + idx1 = j; + else if (idx2 == -1) + idx2 = j; + else { - idx = -1; + idx1 = idx2 = -1; break; } - idx = j; } } - shared_tuple_active_idx.arrayZ[i] = idx; + shared_tuple_active_idx.arrayZ[i] = {idx1, idx2}; } } ~accelerator_t () { table.destroy (); } @@ -266,10 +295,9 @@ struct gvar public: bool apply_deltas_to_points (hb_codepoint_t glyph, hb_array_t<int> coords, - const hb_array_t<contour_point_t> points) const + const hb_array_t<contour_point_t> points, + bool phantom_only = false) const { - if (!coords) return true; - if (unlikely (glyph >= glyphCount)) return true; hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyphCount, glyph); @@ -297,6 +325,7 @@ struct gvar hb_vector_t<unsigned int> private_indices; hb_vector_t<int> x_deltas; hb_vector_t<int> y_deltas; + unsigned count = points.length; bool flush = false; do { @@ -310,9 +339,10 @@ struct gvar if (!deltas) { - if (unlikely (!deltas_vec.resize (points.length, false))) return false; + if (unlikely (!deltas_vec.resize (count, false))) return false; deltas = deltas_vec.as_array (); - hb_memset (deltas.arrayZ, 0, deltas.get_size ()); // Faster than vector resize + hb_memset (deltas.arrayZ + (phantom_only ? count - 4 : 0), 0, + (phantom_only ? 4 : count) * sizeof (deltas[0])); } const HBUINT8 *end = p + length; @@ -332,7 +362,7 @@ struct gvar if (!apply_to_all) { - if (!orig_points) + if (!orig_points && !phantom_only) { orig_points_vec.extend (points); if (unlikely (orig_points_vec.in_error ())) return false; @@ -341,13 +371,13 @@ struct gvar if (flush) { - unsigned count = points.length; - for (unsigned int i = 0; i < count; i++) + for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++) points.arrayZ[i].translate (deltas.arrayZ[i]); flush = false; } - hb_memset (deltas.arrayZ, 0, deltas.get_size ()); + hb_memset (deltas.arrayZ + (phantom_only ? count - 4 : 0), 0, + (phantom_only ? 4 : count) * sizeof (deltas[0])); } if (HB_OPTIMIZE_SIZE_VAL) @@ -362,6 +392,7 @@ struct gvar pt_index = indices[i]; if (unlikely (pt_index >= deltas.length)) continue; } + if (phantom_only && pt_index < count - 4) continue; auto &delta = deltas.arrayZ[pt_index]; delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */ delta.x += x_deltas.arrayZ[i] * scalar; @@ -374,7 +405,7 @@ struct gvar if (scalar != 1.0f) { if (apply_to_all) - for (unsigned int i = 0; i < num_deltas; i++) + for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++) { unsigned int pt_index = i; auto &delta = deltas.arrayZ[pt_index]; @@ -386,6 +417,7 @@ struct gvar { unsigned int pt_index = indices[i]; if (unlikely (pt_index >= deltas.length)) continue; + if (phantom_only && pt_index < count - 4) continue; auto &delta = deltas.arrayZ[pt_index]; delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */ delta.x += x_deltas.arrayZ[i] * scalar; @@ -395,7 +427,7 @@ struct gvar else { if (apply_to_all) - for (unsigned int i = 0; i < num_deltas; i++) + for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++) { unsigned int pt_index = i; auto &delta = deltas.arrayZ[pt_index]; @@ -407,6 +439,7 @@ struct gvar { unsigned int pt_index = indices[i]; if (unlikely (pt_index >= deltas.length)) continue; + if (phantom_only && pt_index < count - 4) continue; auto &delta = deltas.arrayZ[pt_index]; delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */ delta.x += x_deltas.arrayZ[i]; @@ -416,11 +449,10 @@ struct gvar } /* infer deltas for unreferenced points */ - if (!apply_to_all) + if (!apply_to_all && !phantom_only) { if (!end_points) { - unsigned count = points.length; for (unsigned i = 0; i < count; ++i) if (points.arrayZ[i].is_end_point) end_points.push (i); @@ -482,8 +514,7 @@ struct gvar if (flush) { - unsigned count = points.length; - for (unsigned int i = 0; i < count; i++) + for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++) points.arrayZ[i].translate (deltas.arrayZ[i]); } @@ -495,7 +526,7 @@ struct gvar private: hb_blob_ptr_t<gvar> table; unsigned glyphCount; - hb_vector_t<signed> shared_tuple_active_idx; + hb_vector_t<hb_pair_t<int, int>> shared_tuple_active_idx; }; protected: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh index 461b2b9cdbc..943d376bdfc 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh @@ -56,52 +56,56 @@ struct index_map_subset_plan_t if (&index_map == &Null (DeltaSetIndexMap)) return; unsigned int last_val = (unsigned int)-1; - hb_codepoint_t last_gid = (hb_codepoint_t)-1; - hb_codepoint_t gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ()); + hb_codepoint_t last_gid = HB_CODEPOINT_INVALID; + hb_codepoint_t num_gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ()); outer_bit_count = (index_map.get_width () * 8) - index_map.get_inner_bit_count (); max_inners.resize (inner_sets.length); for (unsigned i = 0; i < inner_sets.length; i++) max_inners[i] = 0; /* Search backwards for a map value different from the last map value */ - for (; gid > 0; gid--) + auto &new_to_old_gid_list = plan->new_to_old_gid_list; + unsigned count = new_to_old_gid_list.length; + for (unsigned j = count; j; j--) { - hb_codepoint_t old_gid; - if (!plan->old_gid_for_new_gid (gid - 1, &old_gid)) - { - if (last_gid == (hb_codepoint_t) -1) - continue; - else - break; - } + hb_codepoint_t gid = new_to_old_gid_list[j - 1].first; + if (gid >= num_gid) continue; + + hb_codepoint_t old_gid = new_to_old_gid_list[j - 1].second; unsigned int v = index_map.map (old_gid); - if (last_gid == (hb_codepoint_t) -1) + if (last_gid == HB_CODEPOINT_INVALID) { + if (gid + 1 != num_gid) + { + last_gid = gid + 1; + break; + } last_val = v; last_gid = gid; continue; } - if (v != last_val) break; + if (v != last_val || gid + 1 != last_gid) + break; last_gid = gid; } if (unlikely (last_gid == (hb_codepoint_t)-1)) return; - map_count = last_gid; - for (gid = 0; gid < map_count; gid++) + map_count = last_gid + 1; + for (auto _ : plan->new_to_old_gid_list) { - hb_codepoint_t old_gid; - if (plan->old_gid_for_new_gid (gid, &old_gid)) - { - unsigned int v = index_map.map (old_gid); - unsigned int outer = v >> 16; - unsigned int inner = v & 0xFFFF; - outer_map.add (outer); - if (inner > max_inners[outer]) max_inners[outer] = inner; - if (outer >= inner_sets.length) return; - inner_sets[outer]->add (inner); - } + hb_codepoint_t gid = _.first; + if (gid >= map_count) break; + + hb_codepoint_t old_gid = _.second; + unsigned int v = index_map.map (old_gid); + unsigned int outer = v >> 16; + unsigned int inner = v & 0xFFFF; + outer_map.add (outer); + if (inner > max_inners[outer]) max_inners[outer] = inner; + if (outer >= inner_sets.length) return; + inner_sets[outer]->add (inner); } } @@ -197,7 +201,8 @@ struct hvarvvar_subset_plan_t if (retain_adv_map) { - for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++) + unsigned num_glyphs = plan->num_output_glyphs (); + for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) { if (inner_sets[0]->has (gid)) inner_maps[0].add (gid); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh index 811e13919e9..671b6d2c290 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh @@ -90,7 +90,7 @@ struct VORG bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - VORG *vorg_prime = c->serializer->start_embed<VORG> (); + auto *vorg_prime = c->serializer->start_embed<VORG> (); if (unlikely (!c->serializer->check_success (vorg_prime))) return_trace (false); auto it = diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh index d6eb778f5dd..fcf10666b09 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh @@ -58,7 +58,7 @@ struct hb_pool_t if (unlikely (!next)) { if (unlikely (!chunks.alloc (chunks.length + 1))) return nullptr; - chunk_t *chunk = (chunk_t *) hb_calloc (1, sizeof (chunk_t)); + chunk_t *chunk = (chunk_t *) hb_malloc (sizeof (chunk_t)); if (unlikely (!chunk)) return nullptr; chunks.push (chunk); next = chunk->thread (); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh index 5259891b7e0..2d338c51c8a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh @@ -122,12 +122,14 @@ struct hb_sanitize_context_t : { hb_sanitize_context_t () : start (nullptr), end (nullptr), + length (0), max_ops (0), max_subtables (0), recursion_depth (0), writable (false), edit_count (0), blob (nullptr), num_glyphs (65536), - num_glyphs_set (false) {} + num_glyphs_set (false), + lazy_some_gpos (false) {} const char *get_name () { return "SANITIZE"; } template <typename T, typename F> @@ -155,6 +157,19 @@ struct hb_sanitize_context_t : dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) ) + hb_sanitize_context_t (hb_blob_t *b) : hb_sanitize_context_t () + { + init (b); + + if (blob) + start_processing (); + } + + ~hb_sanitize_context_t () + { + if (blob) + end_processing (); + } void init (hb_blob_t *b) { @@ -180,11 +195,15 @@ struct hb_sanitize_context_t : const char *obj_start = (const char *) obj; if (unlikely (obj_start < this->start || this->end <= obj_start)) + { this->start = this->end = nullptr; + this->length = 0; + } else { this->start = obj_start; this->end = obj_start + hb_min (size_t (this->end - obj_start), obj->get_size ()); + this->length = this->end - this->start; } } @@ -192,6 +211,7 @@ struct hb_sanitize_context_t : { this->start = this->blob->data; this->end = this->start + this->blob->length; + this->length = this->end - this->start; assert (this->start <= this->end); /* Must not overflow. */ } @@ -224,6 +244,7 @@ struct hb_sanitize_context_t : hb_blob_destroy (this->blob); this->blob = nullptr; this->start = this->end = nullptr; + this->length = 0; } unsigned get_edit_count () { return edit_count; } @@ -240,15 +261,16 @@ struct hb_sanitize_context_t : return (this->max_ops -= (int) count) > 0; } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool check_range (const void *base, unsigned int len) const { const char *p = (const char *) base; - bool ok = !len || - (this->start <= p && - p <= this->end && - (unsigned int) (this->end - p) >= len && - (this->max_ops -= len) > 0); + bool ok = (uintptr_t) (p - this->start) <= this->length && + (unsigned int) (this->end - p) >= len && + ((this->max_ops -= len) > 0); DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, "check_range [%p..%p]" @@ -259,6 +281,43 @@ struct hb_sanitize_context_t : return likely (ok); } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif + bool check_range_fast (const void *base, + unsigned int len) const + { + const char *p = (const char *) base; + bool ok = ((uintptr_t) (p - this->start) <= this->length && + (unsigned int) (this->end - p) >= len); + + DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, + "check_range_fast [%p..%p]" + " (%u bytes) in [%p..%p] -> %s", + p, p + len, len, + this->start, this->end, + ok ? "OK" : "OUT-OF-RANGE"); + + return likely (ok); + } + +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif + bool check_point (const void *base) const + { + const char *p = (const char *) base; + bool ok = (uintptr_t) (p - this->start) <= this->length; + + DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, + "check_point [%p]" + " in [%p..%p] -> %s", + p, + this->start, this->end, + ok ? "OK" : "OUT-OF-RANGE"); + + return likely (ok); + } template <typename T> bool check_range (const T *base, @@ -282,6 +341,20 @@ struct hb_sanitize_context_t : } template <typename T> + HB_ALWAYS_INLINE + bool check_array_sized (const T *base, unsigned int len, unsigned len_size) const + { + if (len_size >= 4) + { + if (unlikely (hb_unsigned_mul_overflows (len, hb_static_size (T), &len))) + return false; + } + else + len = len * hb_static_size (T); + return this->check_range (base, len); + } + + template <typename T> bool check_array (const T *base, unsigned int len) const { return this->check_range (base, len, hb_static_size (T)); @@ -292,7 +365,7 @@ struct hb_sanitize_context_t : unsigned int a, unsigned int b) const { - return this->check_range (base, a, b, hb_static_size (T)); + return this->check_range (base, hb_static_size (T), a, b); } bool check_start_recursion (int max_depth) @@ -309,7 +382,12 @@ struct hb_sanitize_context_t : template <typename Type> bool check_struct (const Type *obj) const - { return likely (this->check_range (obj, obj->min_size)); } + { + if (sizeof (uintptr_t) == sizeof (uint32_t)) + return likely (this->check_range_fast (obj, obj->min_size)); + else + return likely (this->check_point ((const char *) obj + obj->min_size)); + } bool may_edit (const void *base, unsigned int len) { @@ -416,6 +494,7 @@ struct hb_sanitize_context_t : } const char *start, *end; + unsigned length; mutable int max_ops, max_subtables; private: int recursion_depth; @@ -424,6 +503,8 @@ struct hb_sanitize_context_t : hb_blob_t *blob; unsigned int num_glyphs; bool num_glyphs_set; + public: + bool lazy_some_gpos; }; struct hb_sanitize_with_object_t diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh index 61ec0253a0e..f852f07ba61 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh @@ -113,7 +113,7 @@ struct hb_serialize_context_t { // Virtual links aren't considered for equality since they don't affect the functionality // of the object. - return hb_bytes_t (head, tail - head).hash () ^ + return hb_bytes_t (head, hb_min (128, tail - head)).hash () ^ real_links.as_bytes ().hash (); } @@ -172,8 +172,14 @@ struct hb_serialize_context_t }; snapshot_t snapshot () - { return snapshot_t { - head, tail, current, current->real_links.length, current->virtual_links.length, errors }; } + { + return snapshot_t { + head, tail, current, + current ? current->real_links.length : 0, + current ? current->virtual_links.length : 0, + errors + }; + } hb_serialize_context_t (void *start_, unsigned int size) : start ((char *) start_), @@ -261,6 +267,7 @@ struct hb_serialize_context_t /* To be called around main operation. */ template <typename Type> + __attribute__((returns_nonnull)) Type *start_serialize () { DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1, @@ -303,6 +310,7 @@ struct hb_serialize_context_t } template <typename Type = void> + __attribute__((returns_nonnull)) Type *push () { if (unlikely (in_error ())) return start_embed<Type> (); @@ -323,6 +331,8 @@ struct hb_serialize_context_t { object_t *obj = current; if (unlikely (!obj)) return; + // Allow cleanup when we've error'd out on int overflows which don't compromise + // the serializer state. if (unlikely (in_error() && !only_overflow ())) return; current = current->next; @@ -340,7 +350,9 @@ struct hb_serialize_context_t { object_t *obj = current; if (unlikely (!obj)) return 0; - if (unlikely (in_error())) return 0; + // Allow cleanup when we've error'd out on int overflows which don't compromise + // the serializer state. + if (unlikely (in_error() && !only_overflow ())) return 0; current = current->next; obj->tail = head; @@ -405,8 +417,11 @@ struct hb_serialize_context_t // Overflows that happened after the snapshot will be erased by the revert. if (unlikely (in_error () && !only_overflow ())) return; assert (snap.current == current); - current->real_links.shrink (snap.num_real_links); - current->virtual_links.shrink (snap.num_virtual_links); + if (current) + { + current->real_links.shrink (snap.num_real_links); + current->virtual_links.shrink (snap.num_virtual_links); + } errors = snap.errors; revert (snap.head, snap.tail); } @@ -563,13 +578,15 @@ struct hb_serialize_context_t { unsigned int l = length () % alignment; if (l) - allocate_size<void> (alignment - l); + (void) allocate_size<void> (alignment - l); } template <typename Type = void> + __attribute__((returns_nonnull)) Type *start_embed (const Type *obj HB_UNUSED = nullptr) const { return reinterpret_cast<Type *> (this->head); } template <typename Type> + __attribute__((returns_nonnull)) Type *start_embed (const Type &obj) const { return start_embed (std::addressof (obj)); } @@ -597,6 +614,7 @@ struct hb_serialize_context_t } template <typename Type> + HB_NODISCARD Type *allocate_size (size_t size, bool clear = true) { if (unlikely (in_error ())) return nullptr; @@ -618,6 +636,7 @@ struct hb_serialize_context_t { return this->allocate_size<Type> (Type::min_size); } template <typename Type> + HB_NODISCARD Type *embed (const Type *obj) { unsigned int size = obj->get_size (); @@ -627,6 +646,7 @@ struct hb_serialize_context_t return ret; } template <typename Type> + HB_NODISCARD Type *embed (const Type &obj) { return embed (std::addressof (obj)); } char *embed (const char *obj, unsigned size) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh index dab713729b7..5681641baab 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh @@ -88,14 +88,19 @@ struct hb_set_digest_bits_pattern_t bool add_range (hb_codepoint_t a, hb_codepoint_t b) { + if (mask == (mask_t) -1) return false; if ((b >> shift) - (a >> shift) >= mask_bits - 1) + { mask = (mask_t) -1; - else { + return false; + } + else + { mask_t ma = mask_for (a); mask_t mb = mask_for (b); mask |= mb + (mb - ma) - (mb < ma); + return true; } - return true; } template <typename T> @@ -154,8 +159,7 @@ struct hb_set_digest_combiner_t bool add_range (hb_codepoint_t a, hb_codepoint_t b) { - return head.add_range (a, b) && - tail.add_range (a, b); + return (int) head.add_range (a, b) | (int) tail.add_range (a, b); } template <typename T> void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.h index de532310306..192abf6f63e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.h @@ -43,7 +43,7 @@ HB_BEGIN_DECLS * * Since: 0.9.21 */ -#define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1) +#define HB_SET_VALUE_INVALID HB_CODEPOINT_INVALID /** * hb_set_t: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh index 604802381b9..7d1c941e4dc 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh @@ -115,7 +115,7 @@ struct hb_sparseset_t /* Sink interface. */ hb_sparseset_t& operator << (hb_codepoint_t v) { add (v); return *this; } - hb_sparseset_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range) + hb_sparseset_t& operator << (const hb_codepoint_pair_t& range) { add_range (range.first, range.second); return *this; } bool intersects (hb_codepoint_t first, hb_codepoint_t last) const @@ -174,7 +174,7 @@ struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t> hb_set_t& operator << (hb_codepoint_t v) { sparseset::operator<< (v); return *this; } - hb_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range) + hb_set_t& operator << (const hb_codepoint_pair_t& range) { sparseset::operator<< (range); return *this; } }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc index d9598fc7044..844f7b9e806 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc @@ -220,7 +220,7 @@ reset_buffer (hb_buffer_t *buffer, assert (buffer->ensure (text.length)); buffer->have_positions = false; buffer->len = text.length; - memcpy (buffer->info, text.arrayZ, text.length * sizeof (buffer->info[0])); + hb_memcpy (buffer->info, text.arrayZ, text.length * sizeof (buffer->info[0])); hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_UNICODE); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh index 4158b7094c9..f079caf4d35 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper-list.hh @@ -33,6 +33,11 @@ /* v--- Add new shapers in the right place here. */ +#ifdef HAVE_WASM +/* Only picks up fonts that have a "Wasm" table. */ +HB_SHAPER_IMPLEMENT (wasm) +#endif + #ifdef HAVE_GRAPHITE2 /* Only picks up fonts that have a "Silf" table. */ HB_SHAPER_IMPLEMENT (graphite2) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc index a1a2522edf9..c9bd0a61bf8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc @@ -31,6 +31,7 @@ #include "hb-aat-layout-common.hh" #include "hb-aat-layout-feat-table.hh" +#include "hb-cff-interp-common.hh" #include "hb-ot-layout-common.hh" #include "hb-ot-cmap-table.hh" #include "OT/Color/COLR/COLR.hh" @@ -58,6 +59,8 @@ DEFINE_NULL_NAMESPACE_BYTES (AAT, Lookup) = {0xFF,0xFF}; /* hb_map_t */ const hb_codepoint_t minus_1 = -1; +static const unsigned char static_endchar_str[] = {OpCode_endchar}; +const unsigned char *endchar_str = static_endchar_str; /* hb_face_t */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-accelerator.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-accelerator.hh index bb7c62d064f..9258383d28d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-accelerator.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-accelerator.hh @@ -42,7 +42,9 @@ struct cff_subset_accelerator_t; namespace OT { struct SubtableUnicodesCache; -}; +struct cff1_subset_accelerator_t; +struct cff2_subset_accelerator_t; +} struct hb_subset_accelerator_t { @@ -51,8 +53,8 @@ struct hb_subset_accelerator_t return &_hb_subset_accelerator_user_data_key; } - static hb_subset_accelerator_t* create(const hb_map_t& unicode_to_gid_, - const hb_multimap_t gid_to_unicodes_, + static hb_subset_accelerator_t* create(hb_face_t *source, + const hb_map_t& unicode_to_gid_, const hb_set_t& unicodes_, bool has_seac_) { hb_subset_accelerator_t* accel = @@ -60,8 +62,8 @@ struct hb_subset_accelerator_t if (unlikely (!accel)) return accel; - new (accel) hb_subset_accelerator_t (unicode_to_gid_, - gid_to_unicodes_, + new (accel) hb_subset_accelerator_t (source, + unicode_to_gid_, unicodes_, has_seac_); @@ -79,36 +81,36 @@ struct hb_subset_accelerator_t hb_free (accel); } - hb_subset_accelerator_t (const hb_map_t& unicode_to_gid_, - const hb_multimap_t& gid_to_unicodes_, + hb_subset_accelerator_t (hb_face_t *source, + const hb_map_t& unicode_to_gid_, const hb_set_t& unicodes_, bool has_seac_) : unicode_to_gid(unicode_to_gid_), - gid_to_unicodes (gid_to_unicodes_), unicodes(unicodes_), cmap_cache(nullptr), destroy_cmap_cache(nullptr), has_seac(has_seac_), - cff_accelerator(nullptr), - destroy_cff_accelerator(nullptr) {} - - ~hb_subset_accelerator_t () + source(hb_face_reference (source)) { - if (cff_accelerator && destroy_cff_accelerator) - destroy_cff_accelerator ((void*) cff_accelerator); - - if (cmap_cache && destroy_cmap_cache) - destroy_cmap_cache ((void*) cmap_cache); + gid_to_unicodes.alloc (unicode_to_gid.get_population ()); + for (const auto &_ : unicode_to_gid) + { + auto unicode = _.first; + auto gid = _.second; + gid_to_unicodes.add (gid, unicode); + } } + HB_INTERNAL ~hb_subset_accelerator_t (); + // Generic mutable hb_mutex_t sanitized_table_cache_lock; mutable hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>> sanitized_table_cache; - const hb_map_t unicode_to_gid; - const hb_multimap_t gid_to_unicodes; - const hb_set_t unicodes; + hb_map_t unicode_to_gid; + hb_multimap_t gid_to_unicodes; + hb_set_t unicodes; // cmap const OT::SubtableUnicodesCache* cmap_cache; @@ -116,8 +118,6 @@ struct hb_subset_accelerator_t // CFF bool has_seac; - const CFF::cff_subset_accelerator_t* cff_accelerator; - hb_destroy_func_t destroy_cff_accelerator; // TODO(garretrieger): cumulative glyf checksum map @@ -128,6 +128,13 @@ struct hb_subset_accelerator_t unicodes.in_error () || sanitized_table_cache.in_error (); } + + hb_face_t *source; +#ifndef HB_NO_SUBSET_CFF + // These have to be immediately after source: + mutable hb_face_lazy_loader_t<OT::cff1_subset_accelerator_t, 1> cff1_accel; + mutable hb_face_lazy_loader_t<OT::cff2_subset_accelerator_t, 2> cff2_accel; +#endif }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc index 6e1b6f713d2..5e4ea5fe7c1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc @@ -68,24 +68,35 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, /* use hb_set to determine the subset of font dicts */ hb_set_t set; hb_codepoint_t prev_fd = CFF_UNDEF_CODE; - for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++) + hb_pair_t<unsigned, hb_codepoint_t> last_range {0, 0}; + auto it = hb_iter (plan->new_to_old_gid_list); + auto _ = *it; + for (hb_codepoint_t gid = 0; gid < subset_num_glyphs; gid++) { - hb_codepoint_t glyph; - hb_codepoint_t fd; - if (!plan->old_gid_for_new_gid (i, &glyph)) + hb_codepoint_t old_glyph; + if (gid == _.first) + { + old_glyph = _.second; + _ = *++it; + } + else { /* fonttools retains FDSelect & font dicts for missing glyphs. do the same */ - glyph = i; + old_glyph = gid; } - fd = src.get_fd (glyph); - set.add (fd); + if (old_glyph >= last_range.second) + last_range = src.get_fd_range (old_glyph); + unsigned fd = last_range.first; if (fd != prev_fd) { + set.add (fd); num_ranges++; prev_fd = fd; - code_pair_t pair = { fd, i }; - fdselect_ranges.push (pair); + fdselect_ranges.push (code_pair_t { fd, gid }); + + if (gid == old_glyph) + gid = hb_min (_.first - 1, last_range.second - 1); } } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh index ff50b0e5185..f54792648d8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh @@ -480,6 +480,7 @@ struct cff_subset_accelerator_t const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs) { cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t)); + if (unlikely (!accel)) return nullptr; new (accel) cff_subset_accelerator_t (original_blob, parsed_charstrings, parsed_global_subrs, @@ -510,15 +511,21 @@ struct cff_subset_accelerator_t original_blob = hb_blob_reference (original_blob_); } - ~cff_subset_accelerator_t() { + ~cff_subset_accelerator_t() + { hb_blob_destroy (original_blob); - hb_map_destroy (glyph_to_sid_map.get_relaxed ()); + auto *mapping = glyph_to_sid_map.get_relaxed (); + if (mapping) + { + mapping->~glyph_to_sid_map_t (); + hb_free (mapping); + } } parsed_cs_str_vec_t parsed_charstrings; parsed_cs_str_vec_t parsed_global_subrs; hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs; - mutable hb_atomic_ptr_t<hb_map_t> glyph_to_sid_map = nullptr; + mutable hb_atomic_ptr_t<glyph_to_sid_map_t> glyph_to_sid_map; private: hb_blob_t* original_blob; @@ -600,9 +607,8 @@ struct subr_remap_t : hb_inc_bimap_t * no optimization based on usage counts. fonttools doesn't appear doing that either. */ - resize (closure->get_population ()); - hb_codepoint_t old_num = HB_SET_VALUE_INVALID; - while (hb_set_next (closure, &old_num)) + alloc (closure->get_population ()); + for (auto old_num : *closure) add (old_num); if (get_population () < 1240) @@ -672,8 +678,8 @@ struct subr_subsetter_t { unsigned fd_count = acc.fdCount; const cff_subset_accelerator_t* cff_accelerator = nullptr; - if (plan->accelerator && plan->accelerator->cff_accelerator) { - cff_accelerator = plan->accelerator->cff_accelerator; + if (acc.cff_accelerator) { + cff_accelerator = acc.cff_accelerator; fd_count = cff_accelerator->parsed_local_subrs.length; } @@ -709,14 +715,13 @@ struct subr_subsetter_t } /* phase 1 & 2 */ - for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) + for (auto _ : plan->new_to_old_gid_list) { - hb_codepoint_t glyph; - if (!plan->old_gid_for_new_gid (i, &glyph)) - continue; + hb_codepoint_t new_glyph = _.first; + hb_codepoint_t old_glyph = _.second; - const hb_ubytes_t str = (*acc.charStrings)[glyph]; - unsigned int fd = acc.fdSelect->get_fd (glyph); + const hb_ubytes_t str = (*acc.charStrings)[old_glyph]; + unsigned int fd = acc.fdSelect->get_fd (old_glyph); if (unlikely (fd >= acc.fdCount)) return false; @@ -725,9 +730,9 @@ struct subr_subsetter_t // parsed string already exists in accelerator, copy it and move // on. if (cached_charstrings) - cached_charstrings[i] = &cff_accelerator->parsed_charstrings[glyph]; + cached_charstrings[new_glyph] = &cff_accelerator->parsed_charstrings[old_glyph]; else - parsed_charstrings[i] = cff_accelerator->parsed_charstrings[glyph]; + parsed_charstrings[new_glyph] = cff_accelerator->parsed_charstrings[old_glyph]; continue; } @@ -735,8 +740,8 @@ struct subr_subsetter_t ENV env (str, acc, fd); cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env); - parsed_charstrings[i].alloc (str.length); - subr_subset_param_t param (&parsed_charstrings[i], + parsed_charstrings[new_glyph].alloc (str.length); + subr_subset_param_t param (&parsed_charstrings[new_glyph], &parsed_global_subrs_storage, &parsed_local_subrs_storage[fd], &closures.global_closure, @@ -747,12 +752,12 @@ struct subr_subsetter_t return false; /* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */ - SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]); + SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[new_glyph]); /* mark hint ops and arguments for drop */ if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING) || plan->inprogress_accelerator) { - subr_subset_param_t param (&parsed_charstrings[i], + subr_subset_param_t param (&parsed_charstrings[new_glyph], &parsed_global_subrs_storage, &parsed_local_subrs_storage[fd], &closures.global_closure, @@ -760,11 +765,11 @@ struct subr_subsetter_t plan->flags & HB_SUBSET_FLAGS_NO_HINTING); drop_hints_param_t drop; - if (drop_hints_in_str (parsed_charstrings[i], param, drop)) + if (drop_hints_in_str (parsed_charstrings[new_glyph], param, drop)) { - parsed_charstrings[i].set_hint_dropped (); + parsed_charstrings[new_glyph].set_hint_dropped (); if (drop.vsindex_dropped) - parsed_charstrings[i].set_vsindex_dropped (); + parsed_charstrings[new_glyph].set_vsindex_dropped (); } } @@ -774,7 +779,7 @@ struct subr_subsetter_t * The compacting both saves memory and makes further operations * faster. */ - parsed_charstrings[i].compact (); + parsed_charstrings[new_glyph].compact (); } /* Since parsed strings were loaded from accelerator, we still need @@ -797,23 +802,40 @@ struct subr_subsetter_t bool encode_charstrings (str_buff_vec_t &buffArray, bool encode_prefix = true) const { - if (unlikely (!buffArray.resize_exact (plan->num_output_glyphs ()))) + unsigned num_glyphs = plan->num_output_glyphs (); + if (unlikely (!buffArray.resize_exact (num_glyphs))) return false; - for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) + hb_codepoint_t last = 0; + for (auto _ : plan->new_to_old_gid_list) { - hb_codepoint_t glyph; - if (!plan->old_gid_for_new_gid (i, &glyph)) - { - /* add an endchar only charstring for a missing glyph if CFF1 */ - if (endchar_op != OpCode_Invalid) buffArray.arrayZ[i].push (endchar_op); - continue; - } - unsigned int fd = acc.fdSelect->get_fd (glyph); + hb_codepoint_t gid = _.first; + hb_codepoint_t old_glyph = _.second; + + if (endchar_op != OpCode_Invalid) + for (; last < gid; last++) + { + // Hack to point vector to static string. + auto &b = buffArray.arrayZ[last]; + b.length = 1; + b.arrayZ = const_cast<unsigned char *>(endchar_str); + } + + last++; // Skip over gid + unsigned int fd = acc.fdSelect->get_fd (old_glyph); if (unlikely (fd >= acc.fdCount)) return false; - if (unlikely (!encode_str (get_parsed_charstring (i), fd, buffArray.arrayZ[i], encode_prefix))) + if (unlikely (!encode_str (get_parsed_charstring (gid), fd, buffArray.arrayZ[gid], encode_prefix))) return false; } + if (endchar_op != OpCode_Invalid) + for (; last < num_glyphs; last++) + { + // Hack to point vector to static string. + auto &b = buffArray.arrayZ[last]; + b.length = 1; + b.arrayZ = const_cast<unsigned char *>(endchar_str); + } + return true; } @@ -980,24 +1002,23 @@ struct subr_subsetter_t const hb_vector_t<parsed_cs_str_vec_t>& local_subrs) { closures.reset (); - for (unsigned int i = 0; i < plan->num_output_glyphs (); i++) + for (auto _ : plan->new_to_old_gid_list) { - hb_codepoint_t glyph; - if (!plan->old_gid_for_new_gid (i, &glyph)) - continue; - unsigned int fd = acc.fdSelect->get_fd (glyph); + hb_codepoint_t new_glyph = _.first; + hb_codepoint_t old_glyph = _.second; + unsigned int fd = acc.fdSelect->get_fd (old_glyph); if (unlikely (fd >= acc.fdCount)) return false; // Note: const cast is safe here because the collect_subr_refs_in_str only performs a // closure and does not modify any of the charstrings. - subr_subset_param_t param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (i)), + subr_subset_param_t param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (new_glyph)), const_cast<parsed_cs_str_vec_t*> (&global_subrs), const_cast<parsed_cs_str_vec_t*> (&local_subrs[fd]), &closures.global_closure, &closures.local_closures[fd], plan->flags & HB_SUBSET_FLAGS_NO_HINTING); - collect_subr_refs_in_str (get_parsed_charstring (i), param); + collect_subr_refs_in_str (get_parsed_charstring (new_glyph), param); } return true; @@ -1105,14 +1126,11 @@ struct subr_subsetter_t compact_parsed_subrs (); - plan->inprogress_accelerator->cff_accelerator = + acc.cff_accelerator = cff_subset_accelerator_t::create(acc.blob, parsed_charstrings, parsed_global_subrs_storage, parsed_local_subrs_storage); - plan->inprogress_accelerator->destroy_cff_accelerator = - cff_subset_accelerator_t::destroy; - } const parsed_cs_str_t& get_parsed_charstring (unsigned i) const diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc index 1d7ed6444ac..e80d18d0970 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc @@ -32,36 +32,59 @@ #include "hb-ot-cff1-table.hh" #include "hb-set.h" #include "hb-bimap.hh" -#include "hb-subset-cff1.hh" #include "hb-subset-plan.hh" #include "hb-subset-cff-common.hh" #include "hb-cff1-interp-cs.hh" using namespace CFF; -struct remap_sid_t : hb_inc_bimap_t +struct remap_sid_t { + unsigned get_population () const { return vector.length; } + + void alloc (unsigned size) + { + map.alloc (size); + vector.alloc (size, true); + } + + bool in_error () const + { return map.in_error () || vector.in_error (); } + unsigned int add (unsigned int sid) { - if ((sid != CFF_UNDEF_SID) && !is_std_std (sid)) - return offset_sid (hb_inc_bimap_t::add (unoffset_sid (sid))); - else + if (is_std_str (sid) || (sid == CFF_UNDEF_SID)) return sid; + + sid = unoffset_sid (sid); + unsigned v = next; + if (map.set (sid, v, false)) + { + vector.push (sid); + next++; + } + else + v = map.get (sid); // already exists + return offset_sid (v); } unsigned int operator[] (unsigned int sid) const { - if (is_std_std (sid) || (sid == CFF_UNDEF_SID)) + if (is_std_str (sid) || (sid == CFF_UNDEF_SID)) return sid; - else - return offset_sid (get (unoffset_sid (sid))); + + return offset_sid (map.get (unoffset_sid (sid))); } static const unsigned int num_std_strings = 391; - static bool is_std_std (unsigned int sid) { return sid < num_std_strings; } + static bool is_std_str (unsigned int sid) { return sid < num_std_strings; } static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; } static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; } + unsigned next = 0; + + hb_map_t map; + hb_vector_t<unsigned> vector; }; struct cff1_sub_table_info_t : cff_sub_table_info_t @@ -271,16 +294,17 @@ struct range_list_t : hb_vector_t<code_pair_t> /* replace the first glyph ID in the "glyph" field each range with a nLeft value */ bool complete (unsigned int last_glyph) { - bool two_byte = false; + hb_codepoint_t all_glyphs = 0; unsigned count = this->length; for (unsigned int i = count; i; i--) { code_pair_t &pair = arrayZ[i - 1]; unsigned int nLeft = last_glyph - pair.glyph - 1; - two_byte |= nLeft >= 0x100; + all_glyphs |= nLeft; last_glyph = pair.glyph; pair.glyph = nLeft; } + bool two_byte = all_glyphs >= 0x100; return two_byte; } }; @@ -391,8 +415,10 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs } }; -struct cff_subset_plan { - cff_subset_plan () +namespace OT { +struct cff1_subset_plan +{ + cff1_subset_plan () { for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++) topDictModSIDs[i] = CFF_UNDEF_SID; @@ -402,7 +428,7 @@ struct cff_subset_plan { { const Encoding *encoding = acc.encoding; unsigned int size0, size1; - hb_codepoint_t code, last_code = CFF_UNDEF_CODE; + unsigned code, last_code = CFF_UNDEF_CODE - 1; hb_vector_t<hb_codepoint_t> supp_codes; if (unlikely (!subset_enc_code_ranges.resize (0))) @@ -413,39 +439,42 @@ struct cff_subset_plan { supp_codes.init (); + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; subset_enc_num_codes = plan->num_output_glyphs () - 1; unsigned int glyph; - for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++) + auto it = hb_iter (plan->new_to_old_gid_list); + if (it->first == 0) it++; + auto _ = *it; + for (glyph = 1; glyph < num_glyphs; glyph++) { - hb_codepoint_t old_glyph; - if (!plan->old_gid_for_new_gid (glyph, &old_glyph)) + hb_codepoint_t old_glyph; + if (glyph == _.first) + { + old_glyph = _.second; + _ = *++it; + } + else { - /* Retain the code for the old missing glyph ID */ + /* Retain the SID for the old missing glyph ID */ old_glyph = glyph; } - code = acc.glyph_to_code (old_glyph); + code = acc.glyph_to_code (old_glyph, &glyph_to_sid_cache); if (code == CFF_UNDEF_CODE) { subset_enc_num_codes = glyph - 1; break; } - if ((last_code == CFF_UNDEF_CODE) || (code != last_code + 1)) - { - code_pair_t pair = { code, glyph }; - subset_enc_code_ranges.push (pair); - } + if (code != last_code + 1) + subset_enc_code_ranges.push (code_pair_t {code, glyph}); last_code = code; if (encoding != &Null (Encoding)) { - hb_codepoint_t sid = acc.glyph_to_sid (old_glyph); + hb_codepoint_t sid = acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache); encoding->get_supplement_codes (sid, supp_codes); for (unsigned int i = 0; i < supp_codes.length; i++) - { - code_pair_t pair = { supp_codes[i], sid }; - subset_enc_supp_codes.push (pair); - } + subset_enc_supp_codes.push (code_pair_t {supp_codes[i], sid}); } } supp_codes.fini (); @@ -462,65 +491,95 @@ struct cff_subset_plan { subset_enc_format = 1; } - void plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan) + bool plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan) { unsigned int size0, size_ranges; - hb_codepoint_t sid, last_sid = CFF_UNDEF_CODE; + unsigned last_sid = CFF_UNDEF_CODE - 1; if (unlikely (!subset_charset_ranges.resize (0))) { plan->check_success (false); - return; + return false; } - hb_map_t *glyph_to_sid_map = (plan->accelerator && plan->accelerator->cff_accelerator) ? - plan->accelerator->cff_accelerator->glyph_to_sid_map : - nullptr; + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; + + unsigned num_glyphs = plan->num_output_glyphs (); + + if (unlikely (!subset_charset_ranges.alloc (hb_min (num_glyphs, + acc.num_charset_entries)))) + { + plan->check_success (false); + return false; + } + + glyph_to_sid_map_t *glyph_to_sid_map = acc.cff_accelerator ? + acc.cff_accelerator->glyph_to_sid_map.get_acquire () : + nullptr; bool created_map = false; - if (!glyph_to_sid_map && - ((plan->accelerator && plan->accelerator->cff_accelerator) || - plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.)) + if (!glyph_to_sid_map && acc.cff_accelerator) { created_map = true; glyph_to_sid_map = acc.create_glyph_to_sid_map (); } - unsigned int glyph; - for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++) + auto it = hb_iter (plan->new_to_old_gid_list); + if (it->first == 0) it++; + auto _ = *it; + bool not_is_cid = !acc.is_CID (); + bool skip = !not_is_cid && glyph_to_sid_map; + if (not_is_cid) + sidmap.alloc (num_glyphs); + for (hb_codepoint_t glyph = 1; glyph < num_glyphs; glyph++) { - hb_codepoint_t old_glyph; - if (!plan->old_gid_for_new_gid (glyph, &old_glyph)) + hb_codepoint_t old_glyph; + if (glyph == _.first) + { + old_glyph = _.second; + _ = *++it; + } + else { /* Retain the SID for the old missing glyph ID */ old_glyph = glyph; } - sid = glyph_to_sid_map ? glyph_to_sid_map->get (old_glyph) : acc.glyph_to_sid (old_glyph); + unsigned sid = glyph_to_sid_map ? + glyph_to_sid_map->arrayZ[old_glyph].code : + acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache); - if (!acc.is_CID ()) + if (not_is_cid) sid = sidmap.add (sid); - if ((last_sid == CFF_UNDEF_CODE) || (sid != last_sid + 1)) + if (sid != last_sid + 1) { - code_pair_t pair = { sid, glyph }; - subset_charset_ranges.push (pair); + subset_charset_ranges.push (code_pair_t {sid, glyph}); + + if (glyph == old_glyph && skip) + { + glyph = hb_min (_.first - 1, glyph_to_sid_map->arrayZ[old_glyph].glyph); + sid += glyph - old_glyph; + } } last_sid = sid; } if (created_map) { - if (!(plan->accelerator && plan->accelerator->cff_accelerator) || - !plan->accelerator->cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map)) - hb_map_destroy (glyph_to_sid_map); + if ((!plan->accelerator && acc.cff_accelerator) || + !acc.cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map)) + { + glyph_to_sid_map->~glyph_to_sid_map_t (); + hb_free (glyph_to_sid_map); + } } - bool two_byte = subset_charset_ranges.complete (glyph); + bool two_byte = subset_charset_ranges.complete (num_glyphs); - size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1); + size0 = Charset0::get_size (plan->num_output_glyphs ()); if (!two_byte) - size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length; + size_ranges = Charset1::get_size_for_ranges (subset_charset_ranges.length); else - size_ranges = Charset2::min_size + Charset2_Range::static_size * subset_charset_ranges.length; + size_ranges = Charset2::get_size_for_ranges (subset_charset_ranges.length); if (size0 < size_ranges) subset_charset_format = 0; @@ -528,19 +587,18 @@ struct cff_subset_plan { subset_charset_format = 1; else subset_charset_format = 2; + + return true; } bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc) { - sidmap.reset (); - for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++) { unsigned int sid = acc.topDict.nameSIDs[i]; if (sid != CFF_UNDEF_SID) { - (void)sidmap.add (sid); - topDictModSIDs[i] = sidmap[sid]; + topDictModSIDs[i] = sidmap.add (sid); } } @@ -564,19 +622,18 @@ struct cff_subset_plan { drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING; desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE; - /* check whether the subset renumbers any glyph IDs */ - gid_renum = false; - for (hb_codepoint_t new_glyph = 0; new_glyph < plan->num_output_glyphs (); new_glyph++) - { - if (!plan->old_gid_for_new_gid(new_glyph, &old_glyph)) - continue; - if (new_glyph != old_glyph) { - gid_renum = true; - break; + subset_charset = !acc.is_predef_charset (); + if (!subset_charset) + /* check whether the subset renumbers any glyph IDs */ + for (const auto &_ : plan->new_to_old_gid_list) + { + if (_.first != _.second) + { + subset_charset = true; + break; + } } - } - subset_charset = gid_renum || !acc.is_predef_charset (); subset_encoding = !acc.is_CID() && !acc.is_predef_encoding (); /* top dict INDEX */ @@ -618,7 +675,8 @@ struct cff_subset_plan { if (unlikely (sidmap.get_population () > 0x8000)) /* assumption: a dict won't reference that many strings */ return false; - if (subset_charset) plan_subset_charset (acc, plan); + if (subset_charset && !plan_subset_charset (acc, plan)) + return false; topdict_mod.reassignSIDs (sidmap); } @@ -682,8 +740,9 @@ struct cff_subset_plan { ; } - return ((subset_charstrings.length == plan->num_output_glyphs ()) - && (fontdicts_mod.length == subset_fdcount)); + return !plan->in_error () && + (subset_charstrings.length == plan->num_output_glyphs ()) && + (fontdicts_mod.length == subset_fdcount); } cff1_top_dict_values_mod_t topdict_mod; @@ -722,24 +781,22 @@ struct cff_subset_plan { bool desubroutinize = false; }; +} // namespace OT -static bool _serialize_cff1 (hb_serialize_context_t *c, - cff_subset_plan &plan, - const OT::cff1::accelerator_subset_t &acc, - unsigned int num_glyphs) +bool +OT::cff1::accelerator_subset_t::serialize (hb_serialize_context_t *c, + struct OT::cff1_subset_plan &plan) const { /* private dicts & local subrs */ - for (int i = (int)acc.privateDicts.length; --i >= 0 ;) + for (int i = (int) privateDicts.length; --i >= 0 ;) { if (plan.fdmap.has (i)) { objidx_t subrs_link = 0; if (plan.subset_localsubrs[i].length > 0) { - CFF1Subrs *dest = c->start_embed <CFF1Subrs> (); - if (unlikely (!dest)) return false; - c->push (); - if (likely (dest && dest->serialize (c, plan.subset_localsubrs[i]))) + auto *dest = c->push <CFF1Subrs> (); + if (likely (dest->serialize (c, plan.subset_localsubrs[i]))) subrs_link = c->pop_pack (); else { @@ -748,12 +805,10 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, } } - PrivateDict *pd = c->start_embed<PrivateDict> (); - if (unlikely (!pd)) return false; - c->push (); + auto *pd = c->push<PrivateDict> (); cff1_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ - if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link))) + if (likely (pd->serialize (c, privateDicts[i], privSzr, subrs_link))) { unsigned fd = plan.fdmap[i]; plan.fontdicts_mod[fd].privateDictInfo.size = c->length (); @@ -767,21 +822,20 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, } } - if (!acc.is_CID ()) + if (!is_CID ()) plan.info.privateDictInfo = plan.fontdicts_mod[0].privateDictInfo; /* CharStrings */ { c->push<CFF1CharStrings> (); - unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings); + unsigned data_size = 0; + unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size); if (unlikely (!c->start_zerocopy (total_size))) return false; - CFF1CharStrings *cs = c->start_embed<CFF1CharStrings> (); - if (unlikely (!cs)) return false; - - if (likely (cs->serialize (c, plan.subset_charstrings))) + auto *cs = c->start_embed<CFF1CharStrings> (); + if (likely (cs->serialize (c, plan.subset_charstrings, &data_size))) plan.info.char_strings_link = c->pop_pack (false); else { @@ -791,11 +845,9 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, } /* FDArray (FD Index) */ - if (acc.fdArray != &Null (CFF1FDArray)) + if (fdArray != &Null (CFF1FDArray)) { - CFF1FDArray *fda = c->start_embed<CFF1FDArray> (); - if (unlikely (!fda)) return false; - c->push (); + auto *fda = c->push<CFF1FDArray> (); cff1_font_dict_op_serializer_t fontSzr; auto it = + hb_zip (+ hb_iter (plan.fontdicts_mod), + hb_iter (plan.fontdicts_mod)); if (likely (fda->serialize (c, it, fontSzr))) @@ -808,10 +860,10 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, } /* FDSelect */ - if (acc.fdSelect != &Null (CFF1FDSelect)) + if (fdSelect != &Null (CFF1FDSelect)) { c->push (); - if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *acc.fdSelect, acc.fdCount, + if (likely (hb_serialize_cff_fdselect (c, plan.num_glyphs, *fdSelect, fdCount, plan.subset_fdselect_format, plan.info.fd_select.size, plan.subset_fdselect_ranges))) plan.info.fd_select.link = c->pop_pack (); @@ -825,9 +877,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, /* Charset */ if (plan.subset_charset) { - Charset *dest = c->start_embed<Charset> (); - if (unlikely (!dest)) return false; - c->push (); + auto *dest = c->push<Charset> (); if (likely (dest->serialize (c, plan.subset_charset_format, plan.num_glyphs, @@ -843,9 +893,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, /* Encoding */ if (plan.subset_encoding) { - Encoding *dest = c->start_embed<Encoding> (); - if (unlikely (!dest)) return false; - c->push (); + auto *dest = c->push<Encoding> (); if (likely (dest->serialize (c, plan.subset_enc_format, plan.subset_enc_num_codes, @@ -861,9 +909,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, /* global subrs */ { - c->push (); - CFF1Subrs *dest = c->start_embed <CFF1Subrs> (); - if (unlikely (!dest)) return false; + auto *dest = c->push <CFF1Subrs> (); if (likely (dest->serialize (c, plan.subset_globalsubrs))) c->pop_pack (false); else @@ -875,10 +921,9 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, /* String INDEX */ { - CFF1StringIndex *dest = c->start_embed<CFF1StringIndex> (); - if (unlikely (!dest)) return false; - c->push (); - if (likely (dest->serialize (c, *acc.stringIndex, plan.sidmap))) + auto *dest = c->push<CFF1StringIndex> (); + if (likely (!plan.sidmap.in_error () && + dest->serialize (c, *stringIndex, plan.sidmap.vector))) c->pop_pack (); else { @@ -898,14 +943,12 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, cff->offSize = 4; /* unused? */ /* name INDEX */ - if (unlikely (!(*acc.nameIndex).copy (c))) return false; + if (unlikely (!c->embed (*nameIndex))) return false; /* top dict INDEX */ { /* serialize singleton TopDict */ - TopDict *top = c->start_embed<TopDict> (); - if (!top) return false; - c->push (); + auto *top = c->push<TopDict> (); cff1_top_dict_op_serializer_t topSzr; unsigned top_size = 0; top_dict_modifiers_t modifier (plan.info, plan.topDictModSIDs); @@ -920,36 +963,23 @@ static bool _serialize_cff1 (hb_serialize_context_t *c, return false; } /* serialize INDEX header for above */ - CFF1Index *dest = c->start_embed<CFF1Index> (); - if (!dest) return false; - return dest->serialize_header (c, hb_iter (hb_array_t<unsigned> (&top_size, 1))); + auto *dest = c->start_embed<CFF1Index> (); + return dest->serialize_header (c, hb_iter (&top_size, 1), top_size); } } -static bool -_hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc, - hb_subset_context_t *c) +bool +OT::cff1::accelerator_subset_t::subset (hb_subset_context_t *c) const { - cff_subset_plan cff_plan; + cff1_subset_plan cff_plan; - if (unlikely (!cff_plan.create (acc, c->plan))) + if (unlikely (!cff_plan.create (*this, c->plan))) { DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan."); return false; } - return _serialize_cff1 (c->serializer, cff_plan, acc, c->plan->num_output_glyphs ()); -} - -bool -hb_subset_cff1 (hb_subset_context_t *c) -{ - OT::cff1::accelerator_subset_t acc; - acc.init (c->plan->source); - bool result = likely (acc.is_valid ()) && _hb_subset_cff1 (acc, c); - acc.fini (); - - return result; + return serialize (c->serializer, cff_plan); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc index 8ab4620194b..3c52fb9c2c3 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc @@ -31,7 +31,6 @@ #include "hb-open-type.hh" #include "hb-ot-cff2-table.hh" #include "hb-set.h" -#include "hb-subset-cff2.hh" #include "hb-subset-plan.hh" #include "hb-subset-cff-common.hh" #include "hb-cff2-interp-cs.hh" @@ -422,11 +421,17 @@ struct cff2_private_dict_op_serializer_t : op_serializer_t }; +namespace OT { struct cff2_subset_plan { bool create (const OT::cff2::accelerator_subset_t &acc, hb_subset_plan_t *plan) { + /* make sure notdef is first */ + hb_codepoint_t old_glyph; + if (!plan->old_gid_for_new_gid (0, &old_glyph) || (old_glyph != 0)) return false; + + num_glyphs = plan->num_output_glyphs (); orig_fdcount = acc.fdArray->count; drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING; @@ -489,6 +494,7 @@ struct cff2_subset_plan cff2_sub_table_info_t info; + unsigned int num_glyphs; unsigned int orig_fdcount = 0; unsigned int subset_fdcount = 1; unsigned int subset_fdselect_size = 0; @@ -505,18 +511,18 @@ struct cff2_subset_plan bool drop_hints = false; bool desubroutinize = false; }; +} // namespace OT -static bool _serialize_cff2 (hb_serialize_context_t *c, - cff2_subset_plan &plan, - const OT::cff2::accelerator_subset_t &acc, - unsigned int num_glyphs, - hb_array_t<int> normalized_coords) +bool +OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c, + struct cff2_subset_plan &plan, + hb_array_t<int> normalized_coords) const { /* private dicts & local subrs */ hb_vector_t<table_info_t> private_dict_infos; if (unlikely (!private_dict_infos.resize (plan.subset_fdcount))) return false; - for (int i = (int)acc.privateDicts.length; --i >= 0 ;) + for (int i = (int)privateDicts.length; --i >= 0 ;) { if (plan.fdmap.has (i)) { @@ -524,9 +530,7 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, if (plan.subset_localsubrs[i].length > 0) { - CFF2Subrs *dest = c->start_embed <CFF2Subrs> (); - if (unlikely (!dest)) return false; - c->push (); + auto *dest = c->push <CFF2Subrs> (); if (likely (dest->serialize (c, plan.subset_localsubrs[i]))) subrs_link = c->pop_pack (false); else @@ -535,12 +539,10 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, return false; } } - PrivateDict *pd = c->start_embed<PrivateDict> (); - if (unlikely (!pd)) return false; - c->push (); + auto *pd = c->push<PrivateDict> (); cff2_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints, plan.pinned, - acc.varStore, normalized_coords); - if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link))) + varStore, normalized_coords); + if (likely (pd->serialize (c, privateDicts[i], privSzr, subrs_link))) { unsigned fd = plan.fdmap[i]; private_dict_infos[fd].size = c->length (); @@ -558,14 +560,13 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, { c->push (); - unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings); + unsigned data_size = 0; + unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings, &data_size); if (unlikely (!c->start_zerocopy (total_size))) return false; - CFF2CharStrings *cs = c->start_embed<CFF2CharStrings> (); - if (unlikely (!cs)) return false; - - if (likely (cs->serialize (c, plan.subset_charstrings))) + auto *cs = c->start_embed<CFF2CharStrings> (); + if (likely (cs->serialize (c, plan.subset_charstrings, &data_size))) plan.info.char_strings_link = c->pop_pack (false); else { @@ -575,10 +576,10 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, } /* FDSelect */ - if (acc.fdSelect != &Null (CFF2FDSelect)) + if (fdSelect != &Null (CFF2FDSelect)) { c->push (); - if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect, + if (likely (hb_serialize_cff_fdselect (c, plan.num_glyphs, *(const FDSelect *)fdSelect, plan.orig_fdcount, plan.subset_fdselect_format, plan.subset_fdselect_size, plan.subset_fdselect_ranges))) @@ -592,27 +593,32 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, /* FDArray (FD Index) */ { - c->push (); - CFF2FDArray *fda = c->start_embed<CFF2FDArray> (); - if (unlikely (!fda)) return false; + auto *fda = c->push<CFF2FDArray> (); cff_font_dict_op_serializer_t fontSzr; auto it = - + hb_zip (+ hb_iter (acc.fontDicts) + + hb_zip (+ hb_iter (fontDicts) | hb_filter ([&] (const cff2_font_dict_values_t &_) - { return plan.fdmap.has (&_ - &acc.fontDicts[0]); }), + { return plan.fdmap.has (&_ - &fontDicts[0]); }), hb_iter (private_dict_infos)) ; - if (unlikely (!fda->serialize (c, it, fontSzr))) return false; + if (unlikely (!fda->serialize (c, it, fontSzr))) + { + c->pop_discard (); + return false; + } plan.info.fd_array_link = c->pop_pack (false); } /* variation store */ - if (acc.varStore != &Null (CFF2VariationStore) && + if (varStore != &Null (CFF2VariationStore) && !plan.pinned) { - c->push (); - CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> (); - if (unlikely (!dest || !dest->serialize (c, acc.varStore))) return false; + auto *dest = c->push<CFF2VariationStore> (); + if (unlikely (!dest->serialize (c, varStore))) + { + c->pop_discard (); + return false; + } plan.info.var_store_link = c->pop_pack (false); } @@ -628,34 +634,25 @@ static bool _serialize_cff2 (hb_serialize_context_t *c, { TopDict &dict = cff2 + cff2->topDict; cff2_top_dict_op_serializer_t topSzr; - if (unlikely (!dict.serialize (c, acc.topDict, topSzr, plan.info))) return false; + if (unlikely (!dict.serialize (c, topDict, topSzr, plan.info))) return false; cff2->topDictSize = c->head - (const char *)&dict; } /* global subrs */ { - CFF2Subrs *dest = c->start_embed <CFF2Subrs> (); - if (unlikely (!dest)) return false; + auto *dest = c->start_embed <CFF2Subrs> (); return dest->serialize (c, plan.subset_globalsubrs); } } -static bool -_hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc, - hb_subset_context_t *c) +bool +OT::cff2::accelerator_subset_t::subset (hb_subset_context_t *c) const { cff2_subset_plan cff2_plan; - if (unlikely (!cff2_plan.create (acc, c->plan))) return false; - return _serialize_cff2 (c->serializer, cff2_plan, acc, c->plan->num_output_glyphs (), - c->plan->normalized_coords.as_array ()); -} - -bool -hb_subset_cff2 (hb_subset_context_t *c) -{ - OT::cff2::accelerator_subset_t acc (c->plan->source); - return acc.is_valid () && _hb_subset_cff2 (acc, c); + if (unlikely (!cff2_plan.create (*this, c->plan))) return false; + return serialize (c->serializer, cff2_plan, + c->plan->normalized_coords.as_array ()); } #endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc index 465af508141..e6b23df7043 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc @@ -438,7 +438,8 @@ hb_subset_input_pin_axis_to_default (hb_subset_input_t *input, if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) return false; - return input->axes_location.set (axis_tag, axis_info.default_value); + float default_val = axis_info.default_value; + return input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val)); } /** @@ -468,8 +469,52 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, return false; float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value); - return input->axes_location.set (axis_tag, val); + return input->axes_location.set (axis_tag, Triple (val, val, val)); } + +#ifdef HB_EXPERIMENTAL_API +/** + * hb_subset_input_set_axis_range: (skip) + * @input: a #hb_subset_input_t object. + * @face: a #hb_face_t object. + * @axis_tag: Tag of the axis + * @axis_min_value: Minimum value of the axis variation range to set + * @axis_max_value: Maximum value of the axis variation range to set + * + * Restricting the range of variation on an axis in the given subset input object. + * New min/max values will be clamped if they're not within the fvar axis range. + * If the fvar axis default value is not within the new range, the new default + * value will be changed to the new min or max value, whichever is closer to the fvar + * axis default. + * + * Note: input min value can not be bigger than input max value + * Note: currently this API does not support changing axis limits yet.It'd be only + * used internally for setting axis limits in the internal data structures + * + * Return value: `true` if success, `false` otherwise + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_bool_t +hb_subset_input_set_axis_range (hb_subset_input_t *input, + hb_face_t *face, + hb_tag_t axis_tag, + float axis_min_value, + float axis_max_value) +{ + if (axis_min_value > axis_max_value) + return false; + + hb_ot_var_axis_info_t axis_info; + if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) + return false; + + float new_min_val = hb_clamp(axis_min_value, axis_info.min_value, axis_info.max_value); + float new_max_val = hb_clamp(axis_max_value, axis_info.min_value, axis_info.max_value); + float new_default_val = hb_clamp(axis_info.default_value, new_min_val, new_max_val); + return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val)); +} +#endif #endif /** diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh index 1970f795b98..6ae311e613d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh @@ -35,6 +35,7 @@ #include "hb-set.hh" #include "hb-cplusplus.hh" #include "hb-font.hh" +#include "hb-subset-instancer-solver.hh" struct hb_ot_name_record_ids_t { @@ -118,7 +119,7 @@ struct hb_subset_input_t // If set loca format will always be the long version. bool force_long_loca = false; - hb_hashmap_t<hb_tag_t, float> axes_location; + hb_hashmap_t<hb_tag_t, Triple> axes_location; hb_map_t glyph_map; #ifdef HB_EXPERIMENTAL_API hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> name_table_overrides; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.cc index 7a2735c529e..c698d944cec 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.cc @@ -22,7 +22,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#include "hb.hh" +#include "hb-subset-instancer-solver.hh" /* This file is a straight port of the following: * @@ -35,26 +35,6 @@ constexpr static float EPSILON = 1.f / (1 << 14); constexpr static float MAX_F2DOT14 = float (0x7FFF) / (1 << 14); -struct Triple { - - Triple () : - minimum (0.f), middle (0.f), maximum (0.f) {} - - Triple (float minimum_, float middle_, float maximum_) : - minimum (minimum_), middle (middle_), maximum (maximum_) {} - - bool operator == (const Triple &o) const - { - return minimum == o.minimum && - middle == o.middle && - maximum == o.maximum; - } - - float minimum; - float middle; - float maximum; -}; - static inline Triple _reverse_negate(const Triple &v) { return {-v.maximum, -v.middle, -v.minimum}; } @@ -82,10 +62,6 @@ static inline float supportScalar (float coord, const Triple &tent) return (end - coord) / (end - peak); } - -using result_item_t = hb_pair_t<float, Triple>; -using result_t = hb_vector_t<result_item_t>; - static inline result_t _solve (Triple tent, Triple axisLimit, bool negative = false) { @@ -195,9 +171,9 @@ _solve (Triple tent, Triple axisLimit, bool negative = false) if (gain > outGain) { // Crossing point on the axis. - float crossing = peak + ((1 - gain) * (upper - peak) / (1 - outGain)); + float crossing = peak + (1 - gain) * (upper - peak); - Triple loc{peak, peak, crossing}; + Triple loc{axisDef, peak, crossing}; float scalar = 1.f; // The part before the crossing point. @@ -213,7 +189,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false) if (upper >= axisMax) { Triple loc {crossing, axisMax, axisMax}; - float scalar = supportScalar (axisMax, tent); + float scalar = outGain; out.push (hb_pair (scalar - gain, loc)); } @@ -247,89 +223,83 @@ _solve (Triple tent, Triple axisLimit, bool negative = false) // Eternity justify. Triple loc2 {upper, axisMax, axisMax}; - float scalar2 = 1.f; // supportScalar({"tag": axisMax}, {"tag": tent}) + float scalar2 = 0.f; out.push (hb_pair (scalar1 - gain, loc1)); out.push (hb_pair (scalar2 - gain, loc2)); } } - /* Case 3: Outermost limit still fits within F2Dot14 bounds; - * we keep deltas as is and only scale the axes bounds. Deltas beyond -1.0 - * or +1.0 will never be applied as implementations must clamp to that range. - * - * A second tent is needed for cases when gain is positive, though we add it - * unconditionally and it will be dropped because scalar ends up 0. - * - * TODO: See if we can just move upper closer to adjust the slope, instead of - * second tent. - * - * | peak | - * 1.........|............o...|.................. - * | /x\ | - * | /xxx\ | - * | /xxxxx\| - * | /xxxxxxx+ - * | /xxxxxxxx|\ - * 0---|-----|------oxxxxxxxxx|xo---------------1 - * axisMin | lower | upper - * | | - * axisDef axisMax - */ - else if (axisDef + (axisMax - axisDef) * 2 >= upper) + else { - if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper) - { - // we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience - upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14; - assert (peak < upper); - } - // Special-case if peak is at axisMax. if (axisMax == peak) upper = peak; - Triple loc1 {hb_max (axisDef, lower), peak, upper}; - float scalar1 = 1.f; + /* Case 3: + * we keep deltas as is and only scale the axis upper to achieve + * the desired new tent if feasible. + * + * peak + * 1.....................o.................... + * / \_| + * ..................../....+_.........outGain + * / | \ + * gain..............+......|..+_............. + * /| | | \ + * 0---|-----------o | | | o----------1 + * axisMin lower| | | upper + * | | newUpper + * axisDef axisMax + */ + float newUpper = peak + (1 - gain) * (upper - peak); + // I feel like the first condition is always true because + // outGain >= gain. + if (axisMax <= newUpper && newUpper <= axisDef + (axisMax - axisDef) * 2) + { + upper = newUpper; + if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper) + { + // we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience + upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14; + assert (peak < upper); + } - Triple loc2 {peak, upper, upper}; - float scalar2 = 0.f; + Triple loc {hb_max (axisDef, lower), peak, upper}; + float scalar = 1.f; - // Don't add a dirac delta! - if (axisDef < upper) - out.push (hb_pair (scalar1 - gain, loc1)); - if (peak < upper) - out.push (hb_pair (scalar2 - gain, loc2)); - } + out.push (hb_pair (scalar - gain, loc)); + } - /* Case 4: New limit doesn't fit; we need to chop into two tents, - * because the shape of a triangle with part of one side cut off - * cannot be represented as a triangle itself. - * - * | peak | - * 1.........|......o.|................... - * | /x\| - * | |xxy|\_ - * | /xxxy| \_ - * | |xxxxy| \_ - * | /xxxxy| \_ - * 0---|-----|-oxxxxxx| o----------1 - * axisMin | lower | upper - * | | - * axisDef axisMax - */ - else - { - Triple loc1 {hb_max (axisDef, lower), peak, axisMax}; - float scalar1 = 1.f; + /* Case 4: New limit doesn't fit; we need to chop into two tents, + * because the shape of a triangle with part of one side cut off + * cannot be represented as a triangle itself. + * + * | peak | + * 1.........|......o.|.................... + * ..........|...../x\|.............outGain + * | |xxy|\_ + * | /xxxy| \_ + * | |xxxxy| \_ + * | /xxxxy| \_ + * 0---|-----|-oxxxxxx| o----------1 + * axisMin | lower | upper + * | | + * axisDef axisMax + */ + else + { + Triple loc1 {hb_max (axisDef, lower), peak, axisMax}; + float scalar1 = 1.f; - Triple loc2 {peak, axisMax, axisMax}; - float scalar2 = supportScalar (axisMax, tent); + Triple loc2 {peak, axisMax, axisMax}; + float scalar2 = outGain; - out.push (hb_pair (scalar1 - gain, loc1)); - // Don't add a dirac delta! - if (peak < axisMax) - out.push (hb_pair (scalar2 - gain, loc2)); + out.push (hb_pair (scalar1 - gain, loc1)); + // Don't add a dirac delta! + if (peak < axisMax) + out.push (hb_pair (scalar2 - gain, loc2)); + } } /* Now, the negative side @@ -422,19 +392,6 @@ static inline float normalizeValue (float v, const Triple &triple, bool extrapol } } -/* Given a tuple (lower,peak,upper) "tent" and new axis limits - * (axisMin,axisDefault,axisMax), solves how to represent the tent - * under the new axis configuration. All values are in normalized - * -1,0,+1 coordinate system. Tent values can be outside this range. - * - * Return value: a list of tuples. Each tuple is of the form - * (scalar,tent), where scalar is a multipler to multiply any - * delta-sets by, and tent is a new tent for that output delta-set. - * If tent value is Triple{}, that is a special deltaset that should - * be always-enabled (called "gain"). - */ -HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit); - result_t rebase_tent (Triple tent, Triple axisLimit) { @@ -460,5 +417,5 @@ rebase_tent (Triple tent, Triple axisLimit) Triple{n (t.minimum), n (t.middle), n (t.maximum)})); } - return sols; + return out; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.hh new file mode 100644 index 00000000000..b1f85949375 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-instancer-solver.hh @@ -0,0 +1,90 @@ +/* + * Copyright © 2023 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_SUBSET_INSTANCER_SOLVER_HH +#define HB_SUBSET_INSTANCER_SOLVER_HH + +#include "hb.hh" + +struct Triple { + + Triple () : + minimum (0.f), middle (0.f), maximum (0.f) {} + + Triple (float minimum_, float middle_, float maximum_) : + minimum (minimum_), middle (middle_), maximum (maximum_) {} + + bool operator == (const Triple &o) const + { + return minimum == o.minimum && + middle == o.middle && + maximum == o.maximum; + } + + bool operator != (const Triple o) const + { return !(*this == o); } + + bool is_point () const + { return minimum == middle && middle == maximum; } + + bool contains (float point) const + { return minimum <= point && point <= maximum; } + + /* from hb_array_t hash ()*/ + uint32_t hash () const + { + uint32_t current = /*cbf29ce4*/0x84222325; + current = current ^ hb_hash (minimum); + current = current * 16777619; + + current = current ^ hb_hash (middle); + current = current * 16777619; + + current = current ^ hb_hash (maximum); + current = current * 16777619; + return current; + } + + float minimum; + float middle; + float maximum; +}; + +using result_item_t = hb_pair_t<float, Triple>; +using result_t = hb_vector_t<result_item_t>; + +/* Given a tuple (lower,peak,upper) "tent" and new axis limits + * (axisMin,axisDefault,axisMax), solves how to represent the tent + * under the new axis configuration. All values are in normalized + * -1,0,+1 coordinate system. Tent values can be outside this range. + * + * Return value: a list of tuples. Each tuple is of the form + * (scalar,tent), where scalar is a multipler to multiply any + * delta-sets by, and tent is a new tent for that output delta-set. + * If tent value is Triple{}, that is a special deltaset that should + * be always-enabled (called "gain"). + */ +HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit); + +#endif /* HB_SUBSET_INSTANCER_SOLVER_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan-member-list.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan-member-list.hh index acf508c32da..be29e67ecb6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan-member-list.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan-member-list.hh @@ -33,7 +33,9 @@ // For each cp that we'd like to retain maps to the corresponding gid. HB_SUBSET_PLAN_MEMBER (hb_set_t, unicodes) -HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t E(<hb_pair_t<hb_codepoint_t, hb_codepoint_t>>), unicode_to_new_gid_list) +HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t<hb_codepoint_pair_t>, unicode_to_new_gid_list) + +HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t<hb_codepoint_pair_t>, new_to_old_gid_list) // name_ids we would like to retain HB_SUBSET_PLAN_MEMBER (hb_set_t, name_ids) @@ -97,12 +99,12 @@ HB_SUBSET_PLAN_MEMBER (hb_vector_t<hb_inc_bimap_t>, gdef_varstore_inner_maps) HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, hb::unique_ptr<hb_blob_t>>), sanitized_table_cache) -//normalized axes location map -HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, int>), axes_location) +//normalized axes range map +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, Triple>), axes_location) HB_SUBSET_PLAN_MEMBER (hb_vector_t<int>, normalized_coords) -//user specified axes location map -HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, float>), user_axes_location) +//user specified axes range map +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, Triple>), user_axes_location) //retained old axis index -> new axis index mapping in fvar axis array HB_SUBSET_PLAN_MEMBER (hb_map_t, axes_index_map) @@ -115,9 +117,9 @@ HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<hb_codepoint_t, hb_pair_t E(<unsi //vmtx metrics map: new gid->(advance, lsb) HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<hb_codepoint_t, hb_pair_t E(<unsigned, int>)>), vmtx_map) //boundsWidth map: new gid->boundsWidth, boundWidth=xMax - xMin -HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_width_map) +HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_width_vec) //boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin -HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_height_map) +HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_height_vec) #ifdef HB_EXPERIMENTAL_API // name table overrides map: hb_ot_name_record_ids_t-> name string new value or diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc index 791f92d02d5..9a00de3e60a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc @@ -48,10 +48,24 @@ using OT::Layout::GSUB; using OT::Layout::GPOS; + +hb_subset_accelerator_t::~hb_subset_accelerator_t () +{ + if (cmap_cache && destroy_cmap_cache) + destroy_cmap_cache ((void*) cmap_cache); + +#ifndef HB_NO_SUBSET_CFF + cff1_accel.fini (); + cff2_accel.fini (); +#endif + hb_face_destroy (source); +} + + typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map; #ifndef HB_NO_SUBSET_CFF static inline bool -_add_cff_seac_components (const OT::cff1::accelerator_t &cff, +_add_cff_seac_components (const OT::cff1::accelerator_subset_t &cff, hb_codepoint_t gid, hb_set_t *gids_to_retain) { @@ -135,7 +149,8 @@ static void _collect_layout_indices (hb_subset_plan_t *plan, hb_set_t *lookup_indices, /* OUT */ hb_set_t *feature_indices, /* OUT */ hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */ - hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map /* OUT */) + hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, /* OUT */ + bool& insert_catch_all_feature_variation_record) { unsigned num_features = table.get_feature_count (); hb_vector_t<hb_tag_t> features; @@ -171,8 +186,11 @@ static void _collect_layout_indices (hb_subset_plan_t *plan, &plan->axes_location, feature_record_cond_idx_map, feature_substitutes_map, + insert_catch_all_feature_variation_record, feature_indices, - true, + false, + false, + false, 0, &conditionset_map }; @@ -283,7 +301,8 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan, hb_map_t *features, script_langsys_map *langsys_map, hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, - hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map) + hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, + bool& insert_catch_all_feature_variation_record) { hb_blob_ptr_t<T> table = plan->source_table<T> (); hb_tag_t table_tag = table->tableTag; @@ -293,7 +312,8 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan, &lookup_indices, &feature_indices, feature_record_cond_idx_map, - feature_substitutes_map); + feature_substitutes_map, + insert_catch_all_feature_variation_record); if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE)) hb_ot_layout_lookups_substitute_closure (plan->source, @@ -329,7 +349,7 @@ _generate_varstore_inner_maps (const hb_set_t& varidx_set, { if (varidx_set.is_empty () || subtable_count == 0) return; - inner_maps.resize (subtable_count); + if (unlikely (!inner_maps.resize (subtable_count))) return; for (unsigned idx : varidx_set) { uint16_t major = idx >> 16; @@ -356,7 +376,7 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan) { hb_variation_t var; var.tag = _.first; - var.value = _.second; + var.value = _.second.middle; vars.push (var); } @@ -541,6 +561,8 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, unicodes->get_population () < cmap_unicodes->get_population () && glyphs->get_population () < cmap_unicodes->get_population ()) { + plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ()); + auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes; for (hb_codepoint_t gid : *glyphs) { @@ -569,6 +591,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, } else { + plan->codepoint_to_glyph->alloc (cmap_unicodes->get_population ()); for (hb_codepoint_t cp : *cmap_unicodes) { hb_codepoint_t gid = (*unicode_glyphid_map)[cp]; @@ -581,9 +604,10 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes, } /* Add gids which where requested, but not mapped in cmap */ + unsigned num_glyphs = plan->source->get_num_glyphs (); for (hb_codepoint_t gid : *glyphs) { - if (gid >= plan->source->get_num_glyphs ()) + if (gid >= num_glyphs) break; plan->_glyphset_gsub.add (gid); } @@ -616,7 +640,9 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf, if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count; if (unlikely (--operation_count < 0)) return operation_count; - for (auto &item : glyf.glyph_for_gid (gid).get_composite_iterator ()) + auto glyph = glyf.glyph_for_gid (gid); + + for (auto &item : glyph.get_composite_iterator ()) operation_count = _glyf_add_gid_and_children (glyf, item.get_gid (), @@ -625,7 +651,7 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf, depth); #ifndef HB_NO_VAR_COMPOSITES - for (auto &item : glyf.glyph_for_gid (gid).get_var_composite_iterator ()) + for (auto &item : glyph.get_var_composite_iterator ()) { operation_count = _glyf_add_gid_and_children (glyf, @@ -648,7 +674,7 @@ _nameid_closure (hb_subset_plan_t* plan, #endif #ifndef HB_NO_VAR if (!plan->all_axes_pinned) - plan->source->table.fvar->collect_name_ids (&plan->user_axes_location, &plan->name_ids); + plan->source->table.fvar->collect_name_ids (&plan->user_axes_location, &plan->axes_old_index_tag_map, &plan->name_ids); #endif #ifndef HB_NO_COLOR if (!drop_tables->has (HB_OT_TAG_CPAL)) @@ -677,7 +703,11 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, { OT::glyf_accelerator_t glyf (plan->source); #ifndef HB_NO_SUBSET_CFF - OT::cff1::accelerator_t cff (plan->source); + // Note: we cannot use inprogress_accelerator here, since it has not been + // created yet. So in case of preprocessed-face (and otherwise), we do an + // extra sanitize pass here, which is not ideal. + OT::cff1::accelerator_subset_t stack_cff (plan->accelerator ? nullptr : plan->source); + const OT::cff1::accelerator_subset_t *cff (plan->accelerator ? plan->accelerator->cff1_accel.get () : &stack_cff); #endif plan->_glyphset_gsub.add (0); // Not-def @@ -694,7 +724,8 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, &plan->gsub_features, &plan->gsub_langsys, &plan->gsub_feature_record_cond_idx_map, - &plan->gsub_feature_substitutes_map); + &plan->gsub_feature_substitutes_map, + plan->gsub_insert_catch_all_feature_variation_rec); if (!drop_tables->has (HB_OT_TAG_GPOS)) _closure_glyphs_lookups_features<GPOS> ( @@ -704,7 +735,8 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, &plan->gpos_features, &plan->gpos_langsys, &plan->gpos_feature_record_cond_idx_map, - &plan->gpos_feature_substitutes_map); + &plan->gpos_feature_substitutes_map, + plan->gpos_insert_catch_all_feature_variation_rec); #endif _remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ()); @@ -737,9 +769,9 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, if (!plan->accelerator || plan->accelerator->has_seac) { bool has_seac = false; - if (cff.is_valid ()) + if (cff->is_valid ()) for (hb_codepoint_t gid : cur_glyphset) - if (_add_cff_seac_components (cff, gid, &plan->_glyphset)) + if (_add_cff_seac_components (*cff, gid, &plan->_glyphset)) has_seac = true; plan->has_seac = has_seac; } @@ -747,7 +779,6 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, _remove_invalid_gids (&plan->_glyphset, plan->source->get_num_glyphs ()); - #ifndef HB_NO_VAR if (!drop_tables->has (HB_OT_TAG_GDEF)) _collect_layout_variation_indices (plan); @@ -759,10 +790,10 @@ _create_glyph_map_gsub (const hb_set_t* glyph_set_gsub, const hb_map_t* glyph_map, hb_map_t* out) { + out->alloc (glyph_set_gsub->get_population ()); + hb_iter (glyph_set_gsub) | hb_map ([&] (hb_codepoint_t gid) { - return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, - glyph_map->get (gid)); + return hb_codepoint_pair_t (gid, glyph_map->get (gid)); }) | hb_sink (out) ; @@ -775,11 +806,13 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, const hb_map_t *requested_glyph_map, hb_map_t *glyph_map, /* OUT */ hb_map_t *reverse_glyph_map, /* OUT */ + hb_sorted_vector_t<hb_codepoint_pair_t> *new_to_old_gid_list /* OUT */, unsigned int *num_glyphs /* OUT */) { unsigned pop = all_gids_to_retain->get_population (); - reverse_glyph_map->resize (pop); - glyph_map->resize (pop); + reverse_glyph_map->alloc (pop); + glyph_map->alloc (pop); + new_to_old_gid_list->alloc (pop); if (*requested_glyph_map) { @@ -803,45 +836,44 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, for (auto old_gid : all_gids_to_retain->iter ()) { if (old_gid == 0) { - reverse_glyph_map->set(0, 0); + new_to_old_gid_list->push (hb_pair<hb_codepoint_t, hb_codepoint_t> (0u, 0u)); continue; } hb_codepoint_t* new_gid; if (!requested_glyph_map->has (old_gid, &new_gid)) { - remaining.add(old_gid); + remaining.add(old_gid); continue; } if (*new_gid > max_glyph) max_glyph = *new_gid; - reverse_glyph_map->set (*new_gid, old_gid); + new_to_old_gid_list->push (hb_pair (*new_gid, old_gid)); } + new_to_old_gid_list->qsort (); // Anything that wasn't mapped by the requested mapping should // be placed after the requested mapping. for (auto old_gid : remaining) - { - reverse_glyph_map->set(++max_glyph, old_gid); - } + new_to_old_gid_list->push (hb_pair (++max_glyph, old_gid)); *num_glyphs = max_glyph + 1; } else if (!retain_gids) { + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0) - | hb_sink (reverse_glyph_map) + | hb_sink (new_to_old_gid_list) ; - *num_glyphs = reverse_glyph_map->get_population (); + *num_glyphs = new_to_old_gid_list->length; } else { + hb_iter (all_gids_to_retain) | hb_map ([] (hb_codepoint_t _) { - return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, _); + return hb_codepoint_pair_t (_, _); }) - | hb_sink (reverse_glyph_map) + | hb_sink (new_to_old_gid_list) ; hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID; @@ -850,8 +882,11 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, *num_glyphs = max_glyph + 1; } - + reverse_glyph_map->iter () - | hb_map (&hb_pair_t<hb_codepoint_t, hb_codepoint_t>::reverse) + + hb_iter (new_to_old_gid_list) + | hb_sink (reverse_glyph_map) + ; + + hb_iter (new_to_old_gid_list) + | hb_map (&hb_codepoint_pair_t::reverse) | hb_sink (glyph_map) ; @@ -884,24 +919,35 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan) hb_tag_t axis_tag = axis.get_axis_tag (); plan->axes_old_index_tag_map.set (old_axis_idx, axis_tag); - if (!plan->user_axes_location.has (axis_tag)) + if (!plan->user_axes_location.has (axis_tag) || + !plan->user_axes_location.get (axis_tag).is_point ()) { axis_not_pinned = true; plan->axes_index_map.set (old_axis_idx, new_axis_idx); new_axis_idx++; } - else + + if (plan->user_axes_location.has (axis_tag)) { - int normalized_v = axis.normalize_axis_value (plan->user_axes_location.get (axis_tag)); + Triple axis_range = plan->user_axes_location.get (axis_tag); + int normalized_min = axis.normalize_axis_value (axis_range.minimum); + int normalized_default = axis.normalize_axis_value (axis_range.middle); + int normalized_max = axis.normalize_axis_value (axis_range.maximum); + if (has_avar && old_axis_idx < avar_axis_count) { - normalized_v = seg_maps->map (normalized_v); + normalized_min = seg_maps->map (normalized_min); + normalized_default = seg_maps->map (normalized_default); + normalized_max = seg_maps->map (normalized_max); } - plan->axes_location.set (axis_tag, normalized_v); - if (normalized_v != 0) + plan->axes_location.set (axis_tag, Triple (static_cast<float> (normalized_min), + static_cast<float> (normalized_default), + static_cast<float> (normalized_max))); + + if (normalized_default != 0) plan->pinned_at_default = false; - plan->normalized_coords[old_axis_idx] = normalized_v; + plan->normalized_coords[old_axis_idx] = normalized_default; } old_axis_idx++; @@ -968,7 +1014,7 @@ _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan) continue; } plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb)); - plan->bounds_width_map.set (new_gid, extents.width); + plan->bounds_width_vec[new_gid] = extents.width; } if (_vmtx.has_data ()) @@ -985,7 +1031,7 @@ _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan) continue; } plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb)); - plan->bounds_height_map.set (new_gid, extents.height); + plan->bounds_height_vec[new_gid] = extents.height; } } hb_font_destroy (font); @@ -1018,6 +1064,8 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, glyph_map = hb_map_create (); reverse_glyph_map = hb_map_create (); + gsub_insert_catch_all_feature_variation_rec = false; + gpos_insert_catch_all_feature_variation_rec = false; gdef_varstore_inner_maps.init (); user_axes_location = input->axes_location; @@ -1065,6 +1113,7 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, &input->glyph_map, glyph_map, reverse_glyph_map, + &new_to_old_gid_list, &_num_output_glyphs))) { return; } @@ -1082,6 +1131,13 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, glyph_map->get(unicode_to_new_gid_list.arrayZ[i].second); } + bounds_width_vec.resize (_num_output_glyphs, false); + for (auto &v : bounds_width_vec) + v = 0xFFFFFFFF; + bounds_height_vec.resize (_num_output_glyphs, false); + for (auto &v : bounds_height_vec) + v = 0xFFFFFFFF; + if (unlikely (in_error ())) return; @@ -1091,19 +1147,9 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, if (attach_accelerator_data) { - hb_multimap_t gid_to_unicodes; - - hb_map_t &unicode_to_gid = *codepoint_to_glyph; - - for (auto unicode : unicodes) - { - auto gid = unicode_to_gid[unicode]; - gid_to_unicodes.add (gid, unicode); - } - inprogress_accelerator = - hb_subset_accelerator_t::create (*codepoint_to_glyph, - gid_to_unicodes, + hb_subset_accelerator_t::create (source, + *codepoint_to_glyph, unicodes, has_seac); @@ -1115,6 +1161,29 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, #undef HB_SUBSET_PLAN_MEMBER } +hb_subset_plan_t::~hb_subset_plan_t() +{ + hb_face_destroy (dest); + + hb_map_destroy (codepoint_to_glyph); + hb_map_destroy (glyph_map); + hb_map_destroy (reverse_glyph_map); +#ifndef HB_NO_SUBSET_CFF + cff1_accel.fini (); + cff2_accel.fini (); +#endif + hb_face_destroy (source); + +#ifdef HB_EXPERIMENTAL_API + for (auto _ : name_table_overrides.iter_ref ()) + _.second.fini (); +#endif + + if (inprogress_accelerator) + hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator); +} + + /** * hb_subset_plan_create_or_fail: * @face: font face to create the plan for. diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh index 19470ff83e9..d156de05d79 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh @@ -67,28 +67,17 @@ struct head_maxp_info_t typedef struct head_maxp_info_t head_maxp_info_t; +namespace OT { + struct cff1_subset_accelerator_t; + struct cff2_subset_accelerator_t; +} + struct hb_subset_plan_t { HB_INTERNAL hb_subset_plan_t (hb_face_t *, const hb_subset_input_t *input); - ~hb_subset_plan_t() - { - hb_face_destroy (source); - hb_face_destroy (dest); - - hb_map_destroy (codepoint_to_glyph); - hb_map_destroy (glyph_map); - hb_map_destroy (reverse_glyph_map); - -#ifdef HB_EXPERIMENTAL_API - for (auto _ : name_table_overrides) - _.second.fini (); -#endif - - if (inprogress_accelerator) - hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator); - } + HB_INTERNAL ~hb_subset_plan_t(); hb_object_header_t header; @@ -106,6 +95,12 @@ struct hb_subset_plan_t // Plan is only good for a specific source/dest so keep them with it hb_face_t *source; +#ifndef HB_NO_SUBSET_CFF + // These have to be immediately after source: + hb_face_lazy_loader_t<OT::cff1_subset_accelerator_t, 1> cff1_accel; + hb_face_lazy_loader_t<OT::cff2_subset_accelerator_t, 2> cff2_accel; +#endif + hb_face_t *dest; unsigned int _num_output_glyphs; @@ -114,6 +109,10 @@ struct hb_subset_plan_t bool pinned_at_default; bool has_seac; + // whether to insert a catch-all FeatureVariationRecord + bool gsub_insert_catch_all_feature_variation_rec; + bool gpos_insert_catch_all_feature_variation_rec; + #define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name; #include "hb-subset-plan-member-list.hh" #undef HB_SUBSET_PLAN_MEMBER @@ -127,25 +126,31 @@ struct hb_subset_plan_t public: template<typename T> - hb_blob_ptr_t<T> source_table() + struct source_table_loader { - hb_lock_t lock (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr); + hb_blob_ptr_t<T> operator () (hb_subset_plan_t *plan) + { + hb_lock_t lock (plan->accelerator ? &plan->accelerator->sanitized_table_cache_lock : nullptr); - auto *cache = accelerator ? &accelerator->sanitized_table_cache : &sanitized_table_cache; - if (cache - && !cache->in_error () - && cache->has (+T::tableTag)) { - return hb_blob_reference (cache->get (+T::tableTag).get ()); - } + auto *cache = plan->accelerator ? &plan->accelerator->sanitized_table_cache : &plan->sanitized_table_cache; + if (cache + && !cache->in_error () + && cache->has (+T::tableTag)) { + return hb_blob_reference (cache->get (+T::tableTag).get ()); + } - hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)}; - hb_blob_t* ret = hb_blob_reference (table_blob.get ()); + hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (plan->source)}; + hb_blob_t* ret = hb_blob_reference (table_blob.get ()); - if (likely (cache)) - cache->set (+T::tableTag, std::move (table_blob)); + if (likely (cache)) + cache->set (+T::tableTag, std::move (table_blob)); - return ret; - } + return ret; + } + }; + + template<typename T> + auto source_table() HB_AUTO_RETURN (source_table_loader<T> {} (this)) bool in_error () const { return !successful; } @@ -184,15 +189,6 @@ struct hb_subset_plan_t return _num_output_glyphs; } - /* - * Given an output gid , returns true if that glyph id is an empty - * glyph (ie. it's a gid that we are dropping all data for). - */ - inline bool is_empty_glyph (hb_codepoint_t gid) const - { - return !_glyphset.has (gid); - } - inline bool new_gid_for_codepoint (hb_codepoint_t codepoint, hb_codepoint_t *new_gid) const { @@ -242,4 +238,5 @@ struct hb_subset_plan_t } }; + #endif /* HB_SUBSET_PLAN_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc index 9c066e6d782..8e8a5eb0bdd 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc @@ -62,6 +62,27 @@ using OT::Layout::GSUB; using OT::Layout::GPOS; + +#ifndef HB_NO_SUBSET_CFF +template<> +struct hb_subset_plan_t::source_table_loader<const OT::cff1> +{ + auto operator () (hb_subset_plan_t *plan) + HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff1_accel : + plan->inprogress_accelerator ? plan->inprogress_accelerator->cff1_accel : + plan->cff1_accel) +}; +template<> +struct hb_subset_plan_t::source_table_loader<const OT::cff2> +{ + auto operator () (hb_subset_plan_t *plan) + HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff2_accel : + plan->inprogress_accelerator ? plan->inprogress_accelerator->cff2_accel : + plan->cff2_accel) +}; +#endif + + /** * SECTION:hb-subset * @title: hb-subset @@ -192,15 +213,36 @@ _get_table_tags (const hb_subset_plan_t* plan, static unsigned _plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len, - bool same_size) + hb_tag_t table_tag) { unsigned src_glyphs = plan->source->get_num_glyphs (); unsigned dst_glyphs = plan->glyphset ()->get_population (); + unsigned bulk = 8192; + /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's + * because those are expensive to subset, so giving them more room is fine. */ + bool same_size = table_tag == HB_OT_TAG_GSUB || + table_tag == HB_OT_TAG_GPOS || + table_tag == HB_OT_TAG_name; + + if (plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS) + { + if (table_tag == HB_OT_TAG_CFF1) + { + /* Add some extra room for the CFF charset. */ + bulk += src_glyphs * 16; + } + else if (table_tag == HB_OT_TAG_CFF2) + { + /* Just extra CharString offsets. */ + bulk += src_glyphs * 4; + } + } + if (unlikely (!src_glyphs) || same_size) - return 512 + table_len; + return bulk + table_len; - return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs)); + return bulk + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs)); } /* @@ -262,45 +304,46 @@ _try_subset (const TableType *table, return _try_subset (table, buf, c); } +template <typename T> +static auto _do_destroy (T &t, hb_priority<1>) HB_RETURN (void, t.destroy ()) + +template <typename T> +static void _do_destroy (T &t, hb_priority<0>) {} + template<typename TableType> static bool _subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf) { - hb_blob_ptr_t<TableType> source_blob = plan->source_table<TableType> (); - const TableType *table = source_blob.get (); + auto &&source_blob = plan->source_table<TableType> (); + auto *table = source_blob.get (); hb_tag_t tag = TableType::tableTag; - if (!source_blob.get_blob()->data) + hb_blob_t *blob = source_blob.get_blob(); + if (unlikely (!blob || !blob->data)) { DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag)); - source_blob.destroy (); + _do_destroy (source_blob, hb_prioritize); return false; } - /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's - * because those are expensive to subset, so giving them more room is fine. */ - bool same_size_table = TableType::tableTag == HB_OT_TAG_GSUB || - TableType::tableTag == HB_OT_TAG_GPOS || - TableType::tableTag == HB_OT_TAG_name; - - unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob.get_length (), same_size_table); + unsigned buf_size = _plan_estimate_subset_table_size (plan, blob->length, TableType::tableTag); DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size); if (unlikely (!buf.alloc (buf_size))) { DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size); - source_blob.destroy (); + _do_destroy (source_blob, hb_prioritize); return false; } bool needed = false; hb_serialize_context_t serializer (buf.arrayZ, buf.allocated); { - hb_subset_context_t c (source_blob.get_blob (), plan, &serializer, tag); + hb_subset_context_t c (blob, plan, &serializer, tag); needed = _try_subset (table, &buf, &c); } - source_blob.destroy (); + _do_destroy (source_blob, hb_prioritize); if (serializer.in_error () && !serializer.only_offset_overflow ()) { @@ -587,46 +630,49 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan) offset += num_tables; } - hb_vector_t<char> buf; - buf.alloc (4096 - 16); - - bool success = true; - while (!pending_subset_tags.is_empty ()) { - if (subsetted_tags.in_error () - || pending_subset_tags.in_error ()) { - success = false; - goto end; - } + // Grouping to deallocate buf before calling hb_face_reference (plan->dest). - bool made_changes = false; - for (hb_tag_t tag : pending_subset_tags) + hb_vector_t<char> buf; + buf.alloc (8192 - 16); + + while (!pending_subset_tags.is_empty ()) { - if (!_dependencies_satisfied (plan, tag, - subsetted_tags, - pending_subset_tags)) - { - // delayed subsetting for some tables since they might have dependency on other tables - // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated - // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values - continue; + if (subsetted_tags.in_error () + || pending_subset_tags.in_error ()) { + success = false; + goto end; } - pending_subset_tags.del (tag); - subsetted_tags.add (tag); - made_changes = true; - - success = _subset_table (plan, buf, tag); - if (unlikely (!success)) goto end; - } + bool made_changes = false; + for (hb_tag_t tag : pending_subset_tags) + { + if (!_dependencies_satisfied (plan, tag, + subsetted_tags, + pending_subset_tags)) + { + // delayed subsetting for some tables since they might have dependency on other tables + // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated + // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values + continue; + } + + pending_subset_tags.del (tag); + subsetted_tags.add (tag); + made_changes = true; + + success = _subset_table (plan, buf, tag); + if (unlikely (!success)) goto end; + } - if (!made_changes) - { - DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed."); - success = false; - goto end; + if (!made_changes) + { + DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed."); + success = false; + goto end; + } } } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h index 6368ff93f02..93f1f7f10c2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h @@ -177,6 +177,13 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, #ifdef HB_EXPERIMENTAL_API HB_EXTERN hb_bool_t +hb_subset_input_set_axis_range (hb_subset_input_t *input, + hb_face_t *face, + hb_tag_t axis_tag, + float axis_min_value, + float axis_max_value); + +HB_EXTERN hb_bool_t hb_subset_input_override_name_table (hb_subset_input_t *input, hb_ot_name_id_t name_id, unsigned platform_id, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh index d61ce48c01e..23a96d70810 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh @@ -54,7 +54,7 @@ struct hb_vector_t hb_vector_t (const Iterable &o) : hb_vector_t () { auto iter = hb_iter (o); - if (iter.is_random_access_iterator) + if (iter.is_random_access_iterator || iter.has_fast_len) alloc (hb_len (iter), true); hb_copy (iter, *this); } @@ -62,7 +62,19 @@ struct hb_vector_t { alloc (o.length, true); if (unlikely (in_error ())) return; - copy_vector (o); + copy_array (o.as_array ()); + } + hb_vector_t (array_t o) : hb_vector_t () + { + alloc (o.length, true); + if (unlikely (in_error ())) return; + copy_array (o); + } + hb_vector_t (c_array_t o) : hb_vector_t () + { + alloc (o.length, true); + if (unlikely (in_error ())) return; + copy_array (o); } hb_vector_t (hb_vector_t &&o) { @@ -74,7 +86,7 @@ struct hb_vector_t ~hb_vector_t () { fini (); } public: - int allocated = 0; /* == -1 means allocation failed. */ + int allocated = 0; /* < 0 means allocation failed. */ unsigned int length = 0; public: Type *arrayZ = nullptr; @@ -90,19 +102,21 @@ struct hb_vector_t void fini () { - shrink_vector (0); - hb_free (arrayZ); + /* We allow a hack to make the vector point to a foriegn array + * by the user. In that case length/arrayZ are non-zero but + * allocated is zero. Don't free anything. */ + if (allocated) + { + shrink_vector (0); + hb_free (arrayZ); + } init (); } void reset () { if (unlikely (in_error ())) - /* Big Hack! We don't know the true allocated size before - * an allocation failure happened. But we know it was at - * least as big as length. Restore it to that and continue - * as if error did not happen. */ - allocated = length; + reset_error (); resize (0); } @@ -119,7 +133,7 @@ struct hb_vector_t alloc (o.length, true); if (unlikely (in_error ())) return *this; - copy_vector (o); + copy_array (o.as_array ()); return *this; } @@ -191,7 +205,7 @@ struct hb_vector_t Type *push () { if (unlikely (!resize (length + 1))) - return &Crap (Type); + return std::addressof (Crap (Type)); return std::addressof (arrayZ[length - 1]); } template <typename T, @@ -201,7 +215,7 @@ struct hb_vector_t Type *push (T&& v) { Type *p = push (); - if (p == &Crap (Type)) + if (p == std::addressof (Crap (Type))) // If push failed to allocate then don't copy v, since this may cause // the created copy to leak memory since we won't have stored a // reference to it. @@ -214,24 +228,33 @@ struct hb_vector_t hb_enable_if (std::is_copy_constructible<T2>::value)> Type *push (T&& v) { - if (unlikely (!alloc (length + 1))) + if (unlikely ((int) length >= allocated && !alloc (length + 1))) // If push failed to allocate then don't copy v, since this may cause // the created copy to leak memory since we won't have stored a // reference to it. - return &Crap (Type); + return std::addressof (Crap (Type)); /* Emplace. */ - length++; - Type *p = std::addressof (arrayZ[length - 1]); + Type *p = std::addressof (arrayZ[length++]); return new (p) Type (std::forward<T> (v)); } bool in_error () const { return allocated < 0; } + void set_error () + { + assert (allocated >= 0); + allocated = -allocated - 1; + } + void reset_error () + { + assert (allocated < 0); + allocated = -(allocated + 1); + } template <typename T = Type, hb_enable_if (hb_is_trivially_copy_assignable(T))> Type * - realloc_vector (unsigned new_allocated) + realloc_vector (unsigned new_allocated, hb_priority<0>) { if (!new_allocated) { @@ -243,7 +266,7 @@ struct hb_vector_t template <typename T = Type, hb_enable_if (!hb_is_trivially_copy_assignable(T))> Type * - realloc_vector (unsigned new_allocated) + realloc_vector (unsigned new_allocated, hb_priority<0>) { if (!new_allocated) { @@ -263,31 +286,52 @@ struct hb_vector_t } return new_array; } + /* Specialization for hb_vector_t<hb_{vector,array}_t<U>> to speed up. */ + template <typename T = Type, + hb_enable_if (hb_is_same (T, hb_vector_t<typename T::item_t>) || + hb_is_same (T, hb_array_t <typename T::item_t>))> + Type * + realloc_vector (unsigned new_allocated, hb_priority<1>) + { + if (!new_allocated) + { + hb_free (arrayZ); + return nullptr; + } + return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type)); + } template <typename T = Type, hb_enable_if (hb_is_trivially_constructible(T))> void - grow_vector (unsigned size) + grow_vector (unsigned size, hb_priority<0>) { - memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ)); + hb_memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ)); length = size; } template <typename T = Type, hb_enable_if (!hb_is_trivially_constructible(T))> void - grow_vector (unsigned size) + grow_vector (unsigned size, hb_priority<0>) { - while (length < size) - { - length++; - new (std::addressof (arrayZ[length - 1])) Type (); - } + for (; length < size; length++) + new (std::addressof (arrayZ[length])) Type (); + } + /* Specialization for hb_vector_t<hb_{vector,array}_t<U>> to speed up. */ + template <typename T = Type, + hb_enable_if (hb_is_same (T, hb_vector_t<typename T::item_t>) || + hb_is_same (T, hb_array_t <typename T::item_t>))> + void + grow_vector (unsigned size, hb_priority<1>) + { + hb_memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ)); + length = size; } template <typename T = Type, hb_enable_if (hb_is_trivially_copyable (T))> void - copy_vector (const hb_vector_t &other) + copy_array (hb_array_t<const Type> other) { length = other.length; if (!HB_OPTIMIZE_SIZE_VAL && sizeof (T) >= sizeof (long long)) @@ -301,7 +345,7 @@ struct hb_vector_t hb_enable_if (!hb_is_trivially_copyable (T) && std::is_copy_constructible<T>::value)> void - copy_vector (const hb_vector_t &other) + copy_array (hb_array_t<const Type> other) { length = 0; while (length < other.length) @@ -316,7 +360,7 @@ struct hb_vector_t std::is_default_constructible<T>::value && std::is_copy_assignable<T>::value)> void - copy_vector (const hb_vector_t &other) + copy_array (hb_array_t<const Type> other) { length = 0; while (length < other.length) @@ -330,11 +374,15 @@ struct hb_vector_t void shrink_vector (unsigned size) { - while ((unsigned) length > size) + assert (size <= length); + if (!std::is_trivially_destructible<Type>::value) { - arrayZ[(unsigned) length - 1].~Type (); - length--; + unsigned count = length - size; + Type *p = arrayZ + length - 1; + while (count--) + p--->~Type (); } + length = size; } void @@ -381,18 +429,18 @@ struct hb_vector_t if (unlikely (overflows)) { - allocated = -1; + set_error (); return false; } - Type *new_array = realloc_vector (new_allocated); + Type *new_array = realloc_vector (new_allocated, hb_prioritize); if (unlikely (new_allocated && !new_array)) { if (new_allocated <= (unsigned) allocated) return true; // shrinking failed; it's okay; happens in our fuzzer - allocated = -1; + set_error (); return false; } @@ -411,7 +459,7 @@ struct hb_vector_t if (size > length) { if (initialize) - grow_vector (size); + grow_vector (size, hb_prioritize); } else if (size < length) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-blob.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-blob.hh new file mode 100644 index 00000000000..310f4023fcc --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-blob.hh @@ -0,0 +1,50 @@ +/* + * Copyright © 2023 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_WASM_API_BLOB_HH +#define HB_WASM_API_BLOB_HH + +#include "hb-wasm-api.hh" + +namespace hb { +namespace wasm { + + +HB_WASM_API (void, blob_free) (HB_WASM_EXEC_ENV + ptr_d(blob_t, blob)) +{ + HB_PTR_PARAM (blob_t, blob); + if (unlikely (!blob)) + return; + + module_free (blob->data); + + blob->data = nullref; + blob->length = 0; +} + + +}} + +#endif /* HB_WASM_API_BLOB_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-buffer.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-buffer.hh new file mode 100644 index 00000000000..64217a041f4 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-buffer.hh @@ -0,0 +1,217 @@ +/* + * Copyright © 2023 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_WASM_API_BUFFER_HH +#define HB_WASM_API_BUFFER_HH + +#include "hb-wasm-api.hh" + +#include "hb-buffer.hh" + +namespace hb { +namespace wasm { + +static_assert (sizeof (glyph_info_t) == sizeof (hb_glyph_info_t), ""); +static_assert (sizeof (glyph_position_t) == sizeof (hb_glyph_position_t), ""); + +HB_WASM_API (bool_t, buffer_contents_realloc) (HB_WASM_EXEC_ENV + ptr_d(buffer_contents_t, contents), + uint32_t size) +{ + HB_PTR_PARAM (buffer_contents_t, contents); + if (unlikely (!contents)) + return false; + + if (size <= contents->length) + return true; + + unsigned bytes; + if (hb_unsigned_mul_overflows (size, sizeof (glyph_info_t), &bytes)) + return false; + + glyph_info_t *info = HB_ARRAY_APP2NATIVE (glyph_info_t, contents->info, contents->length); + glyph_position_t *pos = HB_ARRAY_APP2NATIVE (glyph_position_t, contents->pos, contents->length); + + if (unlikely (!info || !pos)) + return false; + + glyph_info_t *new_info = nullptr; + uint32_t new_inforef = module_malloc (bytes, (void **) &new_info); + glyph_position_t *new_pos = nullptr; + uint32_t new_posref = module_malloc (bytes, (void **) &new_pos); + + unsigned old_bytes = contents->length * sizeof (glyph_info_t); + if (likely (new_inforef)) + { + hb_memcpy (new_info, info, old_bytes); + module_free (contents->info); + contents->info = new_inforef; + } + if (likely (new_posref)) + { + hb_memcpy (new_pos, pos, old_bytes); + module_free (contents->pos); + contents->pos = new_posref; + } + + if (likely (new_info && new_pos)) + { + contents->length = size; + return true; + } + + return false; +} + +HB_WASM_API (void, buffer_contents_free) (HB_WASM_EXEC_ENV + ptr_d(buffer_contents_t, contents)) +{ + HB_PTR_PARAM (buffer_contents_t, contents); + if (unlikely (!contents)) + return; + + module_free (contents->info); + module_free (contents->pos); + + contents->info = nullref; + contents->pos = nullref; + contents->length = 0; +} + +HB_WASM_API (bool_t, buffer_copy_contents) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer), + ptr_d(buffer_contents_t, contents)) +{ + HB_REF2OBJ (buffer); + HB_PTR_PARAM (buffer_contents_t, contents); + if (unlikely (!contents)) + return false; + + if (buffer->have_output) + buffer->sync (); + if (!buffer->have_positions) + buffer->clear_positions (); + + unsigned length = buffer->len; + + if (length <= contents->length) + { + glyph_info_t *info = HB_ARRAY_APP2NATIVE (glyph_info_t, contents->info, length); + glyph_position_t *pos = HB_ARRAY_APP2NATIVE (glyph_position_t, contents->pos, length); + + if (unlikely (!info || !pos)) + { + contents->length = 0; + return false; + } + + unsigned bytes = length * sizeof (hb_glyph_info_t); + hb_memcpy (info, buffer->info, bytes); + hb_memcpy (pos, buffer->pos, bytes); + + return true; + } + + module_free (contents->info); + module_free (contents->pos); + + contents->length = length; + unsigned bytes = length * sizeof (hb_glyph_info_t); + contents->info = wasm_runtime_module_dup_data (module_inst, (const char *) buffer->info, bytes); + contents->pos = wasm_runtime_module_dup_data (module_inst, (const char *) buffer->pos, bytes); + + if (length && (!contents->info || !contents->pos)) + { + contents->length = 0; + return false; + } + + return true; +} + +HB_WASM_API (bool_t, buffer_set_contents) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer), + ptr_d(const buffer_contents_t, contents)) +{ + HB_REF2OBJ (buffer); + HB_PTR_PARAM (buffer_contents_t, contents); + if (unlikely (!contents)) + return false; + + unsigned length = contents->length; + unsigned bytes; + if (unlikely (hb_unsigned_mul_overflows (length, sizeof (buffer->info[0]), &bytes))) + return false; + + if (unlikely (!buffer->resize (length))) + return false; + + glyph_info_t *info = (glyph_info_t *) (validate_app_addr (contents->info, bytes) ? addr_app_to_native (contents->info) : nullptr); + glyph_position_t *pos = (glyph_position_t *) (validate_app_addr (contents->pos, bytes) ? addr_app_to_native (contents->pos) : nullptr); + + if (!buffer->have_positions) + buffer->clear_positions (); /* This is wasteful. */ + + hb_memcpy (buffer->info, info, bytes); + hb_memcpy (buffer->pos, pos, bytes); + buffer->len = length; + + return true; +} + +HB_WASM_API (direction_t, buffer_get_direction) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer)) +{ + HB_REF2OBJ (buffer); + + return (direction_t) hb_buffer_get_direction (buffer); +} + +HB_WASM_API (script_t, buffer_get_script) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer)) +{ + HB_REF2OBJ (buffer); + + return hb_script_to_iso15924_tag (hb_buffer_get_script (buffer)); +} + +HB_WASM_API (void, buffer_reverse) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer)) +{ + HB_REF2OBJ (buffer); + + hb_buffer_reverse (buffer); +} + +HB_WASM_API (void, buffer_reverse_clusters) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer)) +{ + HB_REF2OBJ (buffer); + + hb_buffer_reverse_clusters (buffer); +} + +}} + +#endif /* HB_WASM_API_BUFFER_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-common.hh index f10556ddd74..c38ca9ceddf 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-common.hh @@ -1,5 +1,5 @@ /* - * Copyright © 2018 Adobe Inc. + * Copyright © 2023 Behdad Esfahbod * * This is part of HarfBuzz, a text shaping library. * @@ -20,18 +20,25 @@ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Adobe Author(s): Michiharu Ariza */ -#ifndef HB_SUBSET_CFF2_HH -#define HB_SUBSET_CFF2_HH +#ifndef HB_WASM_API_COMMON_HH +#define HB_WASM_API_COMMON_HH + +#include "hb-wasm-api.hh" + +namespace hb { +namespace wasm { + -#include "hb.hh" +HB_WASM_API (direction_t, script_get_horizontal_direction) (HB_WASM_EXEC_ENV + script_t script) +{ + return (direction_t) + hb_script_get_horizontal_direction (hb_script_from_iso15924_tag (script)); +} -#include "hb-subset-plan.hh" -HB_INTERNAL bool -hb_subset_cff2 (hb_subset_context_t *c); +}} -#endif /* HB_SUBSET_CFF2_HH */ +#endif /* HB_WASM_API_COMMON_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-face.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-face.hh new file mode 100644 index 00000000000..22e50e94467 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-face.hh @@ -0,0 +1,109 @@ +/* + * Copyright © 2023 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_WASM_API_FACE_HH +#define HB_WASM_API_FACE_HH + +#include "hb-wasm-api.hh" + +namespace hb { +namespace wasm { + + +HB_WASM_API (ptr_t(face_t), face_create) (HB_WASM_EXEC_ENV + ptr_d(blob_t, blob), + unsigned int index) +{ + HB_PTR_PARAM (blob_t, blob); + hb_blob_t *hb_blob = hb_blob_create( + HB_ARRAY_APP2NATIVE (char, blob->data, blob->length), + blob->length, + HB_MEMORY_MODE_DUPLICATE, + NULL, + NULL); + + hb_face_t *face = hb_face_create(hb_blob, index); + + HB_OBJ2REF (face); + return faceref; +} + +HB_WASM_API (bool_t, face_copy_table) (HB_WASM_EXEC_ENV + ptr_d(face_t, face), + tag_t table_tag, + ptr_d(blob_t, blob)) +{ + HB_REF2OBJ (face); + HB_PTR_PARAM (blob_t, blob); + if (unlikely (!blob)) + return false; + + hb_blob_t *hb_blob = hb_face_reference_table (face, table_tag); + + unsigned length; + const char *hb_data = hb_blob_get_data (hb_blob, &length); + + if (length <= blob->length) + { + char *data = HB_ARRAY_APP2NATIVE (char, blob->data, length); + + if (unlikely (!data)) + { + blob->length = 0; + return false; + } + + hb_memcpy (data, hb_data, length); + + return true; + } + + module_free (blob->data); + + blob->length = length; + blob->data = wasm_runtime_module_dup_data (module_inst, hb_data, length); + + hb_blob_destroy (hb_blob); + + if (blob->length && !blob->data) + { + blob->length = 0; + return false; + } + + return true; +} + +HB_WASM_API (unsigned, face_get_upem) (HB_WASM_EXEC_ENV + ptr_d(face_t, face)) +{ + HB_REF2OBJ (face); + + return hb_face_get_upem (face); +} + + +}} + +#endif /* HB_WASM_API_FACE_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-font.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-font.hh new file mode 100644 index 00000000000..2d85db4aac7 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-font.hh @@ -0,0 +1,263 @@ +/* + * Copyright © 2023 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_WASM_API_FONT_HH +#define HB_WASM_API_FONT_HH + +#include "hb-wasm-api.hh" + +#include "hb-outline.hh" + +namespace hb { +namespace wasm { + + +HB_WASM_API (ptr_t(font_t), font_create) (HB_WASM_EXEC_ENV + ptr_d(face_t, face)) +{ + HB_REF2OBJ (face); + + hb_font_t *font = hb_font_create (face); + + HB_OBJ2REF (font); + return fontref; +} + +HB_WASM_API (ptr_t(face_t), font_get_face) (HB_WASM_EXEC_ENV + ptr_d(font_t, font)) +{ + HB_REF2OBJ (font); + + hb_face_t *face = hb_font_get_face (font); + + HB_OBJ2REF (face); + return faceref; +} + +HB_WASM_API (void, font_get_scale) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + ptr_d(int32_t, x_scale), + ptr_d(int32_t, y_scale)) +{ + HB_REF2OBJ (font); + + HB_PTR_PARAM(int32_t, x_scale); + HB_PTR_PARAM(int32_t, y_scale); + + hb_font_get_scale (font, x_scale, y_scale); +} + +HB_WASM_API (codepoint_t, font_get_glyph) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t unicode, + codepoint_t variation_selector) +{ + HB_REF2OBJ (font); + codepoint_t glyph; + + hb_font_get_glyph (font, unicode, variation_selector, &glyph); + return glyph; +} + +HB_WASM_API (position_t, font_get_glyph_h_advance) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph) +{ + HB_REF2OBJ (font); + return hb_font_get_glyph_h_advance (font, glyph); +} + +HB_WASM_API (position_t, font_get_glyph_v_advance) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph) +{ + HB_REF2OBJ (font); + return hb_font_get_glyph_v_advance (font, glyph); +} + +static_assert (sizeof (glyph_extents_t) == sizeof (hb_glyph_extents_t), ""); + +HB_WASM_API (bool_t, font_get_glyph_extents) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph, + ptr_d(glyph_extents_t, extents)) +{ + HB_REF2OBJ (font); + HB_PTR_PARAM (glyph_extents_t, extents); + if (unlikely (!extents)) + return false; + + return hb_font_get_glyph_extents (font, glyph, + (hb_glyph_extents_t *) extents); +} + +HB_WASM_API (void, font_glyph_to_string) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph, + char *s, uint32_t size) +{ + HB_REF2OBJ (font); + + hb_font_glyph_to_string (font, glyph, s, size); +} + +static_assert (sizeof (glyph_outline_point_t) == sizeof (hb_outline_point_t), ""); +static_assert (sizeof (uint32_t) == sizeof (hb_outline_t::contours[0]), ""); + +HB_WASM_API (bool_t, font_copy_glyph_outline) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph, + ptr_d(glyph_outline_t, outline)) +{ + HB_REF2OBJ (font); + HB_PTR_PARAM (glyph_outline_t, outline); + if (unlikely (!outline)) + return false; + + hb_outline_t hb_outline; + auto *funcs = hb_outline_recording_pen_get_funcs (); + + hb_font_draw_glyph (font, glyph, funcs, &hb_outline); + + if (unlikely (hb_outline.points.in_error () || + hb_outline.contours.in_error ())) + { + outline->n_points = outline->n_contours = 0; + return false; + } + + // TODO Check two buffers separately + if (hb_outline.points.length <= outline->n_points && + hb_outline.contours.length <= outline->n_contours) + { + glyph_outline_point_t *points = HB_ARRAY_APP2NATIVE (glyph_outline_point_t, outline->points, hb_outline.points.length); + uint32_t *contours = HB_ARRAY_APP2NATIVE (uint32_t, outline->contours, hb_outline.contours.length); + + if (unlikely (!points || !contours)) + { + outline->n_points = outline->n_contours = 0; + return false; + } + + hb_memcpy (points, hb_outline.points.arrayZ, hb_outline.points.get_size ()); + hb_memcpy (contours, hb_outline.contours.arrayZ, hb_outline.contours.get_size ()); + + return true; + } + + outline->n_points = hb_outline.points.length; + outline->points = wasm_runtime_module_dup_data (module_inst, + (const char *) hb_outline.points.arrayZ, + hb_outline.points.get_size ()); + outline->n_contours = hb_outline.contours.length; + outline->contours = wasm_runtime_module_dup_data (module_inst, + (const char *) hb_outline.contours.arrayZ, + hb_outline.contours.get_size ()); + + if ((outline->n_points && !outline->points) || + (!outline->n_contours && !outline->contours)) + { + outline->n_points = outline->n_contours = 0; + return false; + } + + return true; +} + +HB_WASM_API (void, glyph_outline_free) (HB_WASM_EXEC_ENV + ptr_d(glyph_outline_t, outline)) +{ + HB_PTR_PARAM (glyph_outline_t, outline); + if (unlikely (!outline)) + return; + + module_free (outline->points); + module_free (outline->contours); + + outline->n_points = 0; + outline->points = nullref; + outline->n_contours = 0; + outline->contours = nullref; +} + +HB_WASM_API (bool_t, font_copy_coords) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + ptr_d(coords_t, coords)) +{ + HB_REF2OBJ (font); + HB_PTR_PARAM (coords_t, coords); + if (unlikely (!coords)) + return false; + + unsigned our_length; + const int* our_coords = hb_font_get_var_coords_normalized(font, &our_length); + + if (our_length <= coords->length) { + int *their_coords = HB_ARRAY_APP2NATIVE (int, coords->coords, our_length); + if (unlikely(!their_coords)) { + coords->length = 0; + return false; + } + unsigned bytes = our_length * sizeof (int); + hb_memcpy (their_coords, our_coords, bytes); + + return true; + } + + module_free (coords->coords); + coords->length = our_length; + unsigned bytes = our_length * sizeof (int); + coords->coords = wasm_runtime_module_dup_data (module_inst, (const char *) our_coords, bytes); + if (our_length && !coords->coords) + { + coords->length = 0; + return false; + } + + return true; +} + +HB_WASM_API (bool_t, font_set_coords) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + ptr_d(coords_t, coords)) +{ + HB_REF2OBJ (font); + HB_PTR_PARAM (coords_t, coords); + if (unlikely (!coords)) + return false; + + unsigned length = coords->length; + unsigned bytes; + if (unlikely (hb_unsigned_mul_overflows (length, sizeof (int), &bytes))) + return false; + + const int *our_coords = (const int *) (validate_app_addr (coords->coords, bytes) ? addr_app_to_native (coords->coords) : nullptr); + hb_font_set_var_coords_normalized(font, our_coords, length); + return true; +} + + +}} + +#endif /* HB_WASM_API_FONT_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-shape.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-shape.hh new file mode 100644 index 00000000000..622ff052b2b --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api-shape.hh @@ -0,0 +1,70 @@ +/* + * Copyright © 2023 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_WASM_API_SHAPE_HH +#define HB_WASM_API_SHAPE_HH + +#include "hb-wasm-api.hh" + +namespace hb { +namespace wasm { + + +static_assert (sizeof (feature_t) == sizeof (hb_feature_t), ""); + +HB_WASM_INTERFACE (bool_t, shape_with) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + ptr_d(buffer_t, buffer), + ptr_d(const feature_t, features), + uint32_t num_features, + const char *shaper) +{ + if (unlikely (0 == strcmp (shaper, "wasm"))) + return false; + + HB_REF2OBJ (font); + HB_REF2OBJ (buffer); + + /* Pre-conditions that make hb_shape_full() crash should be checked here. */ + + if (unlikely (!buffer->ensure_unicode ())) + return false; + + if (unlikely (!HB_DIRECTION_IS_VALID (buffer->props.direction))) + return false; + + HB_ARRAY_PARAM (const feature_t, features, num_features); + if (unlikely (!features && num_features)) + return false; + + const char * shaper_list[] = {shaper, nullptr}; + return hb_shape_full (font, buffer, + (hb_feature_t *) features, num_features, + shaper_list); +} + + +}} + +#endif /* HB_WASM_API_SHAPE_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.cc index aaf5def1ed5..1da8347a086 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.cc @@ -1,5 +1,5 @@ /* - * Copyright © 2018 Adobe Inc. + * Copyright © 2023 Behdad Esfahbod * * This is part of HarfBuzz, a text shaping library. * @@ -20,18 +20,27 @@ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Adobe Author(s): Michiharu Ariza */ -#ifndef HB_SUBSET_CFF1_HH -#define HB_SUBSET_CFF1_HH - #include "hb.hh" -#include "hb-subset-plan.hh" +#ifdef HAVE_WASM + +#include "hb-wasm-api.hh" + +#define module_inst wasm_runtime_get_module_inst (exec_env) + + +#include "hb-wasm-api-blob.hh" +#include "hb-wasm-api-buffer.hh" +#include "hb-wasm-api-common.hh" +#include "hb-wasm-api-face.hh" +#include "hb-wasm-api-font.hh" +#include "hb-wasm-api-shape.hh" + + +#undef module_inst -HB_INTERNAL bool -hb_subset_cff1 (hb_subset_context_t *c); +hb_user_data_key_t _hb_wasm_ref_type_key = {}; -#endif /* HB_SUBSET_CFF1_HH */ +#endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.h new file mode 100644 index 00000000000..f9bd98e5ea0 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.h @@ -0,0 +1,319 @@ +/* + * Copyright © 2023 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_WASM_API_H +#define HB_WASM_API_H + +/* +#include "hb.h" +*/ + +#include <stdint.h> + + +#ifndef HB_WASM_BEGIN_DECLS +# ifdef __cplusplus +# define HB_WASM_BEGIN_DECLS extern "C" { +# define HB_WASM_END_DECLS } +# else /* !__cplusplus */ +# define HB_WASM_BEGIN_DECLS +# define HB_WASM_END_DECLS +# endif /* !__cplusplus */ +#endif + + +HB_WASM_BEGIN_DECLS + +#ifndef HB_WASM_API +#define HB_WASM_API(ret_t, name) ret_t name +#endif +#ifndef HB_WASM_API_COMPOUND /* compound return type */ +#define HB_WASM_API_COMPOUND(ret_t, name) HB_WASM_API(ret_t, name) +#endif +#ifndef HB_WASM_INTERFACE +#define HB_WASM_INTERFACE(ret_t, name) ret_t name +#endif +#ifndef HB_WASM_EXEC_ENV +#define HB_WASM_EXEC_ENV +#endif +#ifndef HB_WASM_EXEC_ENV_COMPOUND +#define HB_WASM_EXEC_ENV_COMPOUND HB_WASM_EXEC_ENV +#endif + + +#ifndef bool_t +#define bool_t uint32_t +#endif +#ifndef ptr_t +#define ptr_t(type_t) type_t * +#endif +#ifndef ptr_d +#define ptr_d(type_t, name) type_t *name +#endif + +typedef uint32_t codepoint_t; +typedef int32_t position_t; +typedef uint32_t mask_t; +typedef uint32_t tag_t; +#define TAG(c1,c2,c3,c4) ((tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF))) + +typedef enum { + DIRECTION_INVALID = 0, + DIRECTION_LTR = 4, + DIRECTION_RTL, + DIRECTION_TTB, + DIRECTION_BTT +} direction_t; +#define DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4) +#define DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 4) +#define DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 6) +#define DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 4) +#define DIRECTION_IS_BACKWARD(dir) ((((unsigned int) (dir)) & ~2U) == 5) +#define DIRECTION_REVERSE(dir) ((direction_t) (((unsigned int) (dir)) ^ 1)) + +typedef tag_t script_t; /* ISO 15924 representation of Unicode scripts. */ + + +/* common */ + +HB_WASM_API (direction_t, script_get_horizontal_direction) (HB_WASM_EXEC_ENV + script_t script); + + +/* blob */ + +typedef struct +{ + uint32_t length; + ptr_t(char) data; +} blob_t; +#define BLOB_INIT {0, 0} + +HB_WASM_API (void, blob_free) (HB_WASM_EXEC_ENV + ptr_d(blob_t, blob)); + +/* buffer */ + +typedef struct +{ + uint32_t codepoint; + uint32_t mask; + uint32_t cluster; + uint32_t var1; + uint32_t var2; +} glyph_info_t; + +typedef struct +{ + position_t x_advance; + position_t y_advance; + position_t x_offset; + position_t y_offset; + uint32_t var; +} glyph_position_t; + +typedef struct +{ + uint32_t length; + ptr_t(glyph_info_t) info; + ptr_t(glyph_position_t) pos; +} buffer_contents_t; +#define BUFFER_CONTENTS_INIT {0, 0, 0} + +HB_WASM_API (bool_t, buffer_contents_realloc) (HB_WASM_EXEC_ENV + ptr_d(buffer_contents_t, contents), + uint32_t size); + +HB_WASM_API (void, buffer_contents_free) (HB_WASM_EXEC_ENV + ptr_d(buffer_contents_t, contents)); + +typedef struct buffer_t buffer_t; + +HB_WASM_API (bool_t, buffer_copy_contents) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer), + ptr_d(buffer_contents_t, contents)); + +HB_WASM_API (bool_t, buffer_set_contents) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer), + ptr_d(const buffer_contents_t, contents)); + +HB_WASM_API (direction_t, buffer_get_direction) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer)); + +HB_WASM_API (script_t, buffer_get_script) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer)); + +HB_WASM_API (void, buffer_reverse) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer)); + +HB_WASM_API (void, buffer_reverse_clusters) (HB_WASM_EXEC_ENV + ptr_d(buffer_t, buffer)); + +/* face */ + +typedef struct face_t face_t; + +HB_WASM_API (ptr_t(face_t), face_create) (HB_WASM_EXEC_ENV + ptr_d(blob_t, blob), + unsigned int); + +HB_WASM_API (bool_t, face_copy_table) (HB_WASM_EXEC_ENV + ptr_d(face_t, face), + tag_t table_tag, + ptr_d(blob_t, blob)); + +HB_WASM_API (unsigned, face_get_upem) (HB_WASM_EXEC_ENV + ptr_d(face_t, face)); + +/* font */ + +typedef struct font_t font_t; + +HB_WASM_API (ptr_t(font_t), font_create) (HB_WASM_EXEC_ENV + ptr_d(face_t, face)); + +HB_WASM_API (ptr_t(face_t), font_get_face) (HB_WASM_EXEC_ENV + ptr_d(font_t, font)); + +HB_WASM_API (void, font_get_scale) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + ptr_d(int32_t, x_scale), + ptr_d(int32_t, y_scale)); + +HB_WASM_API (codepoint_t, font_get_glyph) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t unicode, + codepoint_t variation_selector); + +HB_WASM_API (position_t, font_get_glyph_h_advance) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph); + +HB_WASM_API (position_t, font_get_glyph_v_advance) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph); + +typedef struct +{ + position_t x_bearing; + position_t y_bearing; + position_t width; + position_t height; +} glyph_extents_t; + +HB_WASM_API (bool_t, font_get_glyph_extents) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph, + ptr_d(glyph_extents_t, extents)); + +HB_WASM_API (void, font_glyph_to_string) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph, + char *s, uint32_t size); + + +typedef struct +{ + unsigned int length; + ptr_t(int) coords; +} coords_t; + +HB_WASM_API (bool_t, font_copy_coords) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + ptr_d(coords_t, coords)); + +HB_WASM_API (bool_t, font_set_coords) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + ptr_d(coords_t, coords)); + +/* outline */ + +enum glyph_outline_point_type_t +{ + MOVE_TO, + LINE_TO, + QUADRATIC_TO, + CUBIC_TO, +}; + +typedef struct +{ + float x; + float y; + uint32_t type; +} glyph_outline_point_t; + +typedef struct +{ + uint32_t n_points; + ptr_t(glyph_outline_point_t) points; + uint32_t n_contours; + ptr_t(uint32_t) contours; +} glyph_outline_t; +#define GLYPH_OUTLINE_INIT {0, 0, 0, 0} + +HB_WASM_API (void, glyph_outline_free) (HB_WASM_EXEC_ENV + ptr_d(glyph_outline_t, outline)); + +HB_WASM_API (bool_t, font_copy_glyph_outline) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + codepoint_t glyph, + ptr_d(glyph_outline_t, outline)); + + +/* shape */ + +typedef struct +{ + tag_t tag; + uint32_t value; + uint32_t start; + uint32_t end; +} feature_t; +#define FEATURE_GLOBAL_START 0 +#define FEATURE_GLOBAL_END ((uint32_t) -1) + +HB_WASM_API (bool_t, shape_with) (HB_WASM_EXEC_ENV + ptr_d(font_t, font), + ptr_d(buffer_t, buffer), + ptr_d(const feature_t, features), + uint32_t num_features, + const char *shaper); + +/* Implement these in your shaper. */ + +HB_WASM_INTERFACE (ptr_t(void), shape_plan_create) (ptr_d(face_t, face)); + +HB_WASM_INTERFACE (bool_t, shape) (ptr_d(void, shape_plan), + ptr_d(font_t, font), + ptr_d(buffer_t, buffer), + ptr_d(const feature_t, features), + uint32_t num_features); + +HB_WASM_INTERFACE (void, shape_plan_destroy) (ptr_d(void, shape_plan)); + + +HB_WASM_END_DECLS + +#endif /* HB_WASM_API_H */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.hh new file mode 100644 index 00000000000..4ead01c1f7f --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-api.hh @@ -0,0 +1,117 @@ +/* + * Copyright © 2023 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_WASM_API_HH +#define HB_WASM_API_HH + +#include "hb.hh" + +#include <wasm_export.h> + +#define HB_WASM_BEGIN_DECLS namespace hb { namespace wasm { +#define HB_WASM_END_DECLS }} + +#define HB_WASM_API(ret_t, name) HB_INTERNAL ret_t name +#define HB_WASM_API_COMPOUND(ret_t, name) HB_INTERNAL void name + +#define HB_WASM_EXEC_ENV wasm_exec_env_t exec_env, +#define HB_WASM_EXEC_ENV_COMPOUND wasm_exec_env_t exec_env, ptr_t() retptr, + +#define ptr_t(type_t) uint32_t +#define ptr_d(type_t, name) uint32_t name##ptr + +#include "hb-wasm-api.h" + +#undef HB_WASM_BEGIN_DECLS +#undef HB_WASM_END_DECLS + + +enum { + hb_wasm_ref_type_none, + hb_wasm_ref_type_face, + hb_wasm_ref_type_font, + hb_wasm_ref_type_buffer, +}; + +HB_INTERNAL extern hb_user_data_key_t _hb_wasm_ref_type_key; + +#define nullref 0 + +#define HB_REF2OBJ(obj) \ + hb_##obj##_t *obj = nullptr; \ + HB_STMT_START { \ + (void) wasm_externref_ref2obj (obj##ptr, (void **) &obj); \ + /* Check object type. */ \ + /* This works because all our objects have the same hb_object_t layout. */ \ + if (unlikely (hb_##obj##_get_user_data (obj, &_hb_wasm_ref_type_key) != \ + (void *) hb_wasm_ref_type_##obj)) \ + obj = hb_##obj##_get_empty (); \ + } HB_STMT_END + +#define HB_OBJ2REF(obj) \ + uint32_t obj##ref = nullref; \ + HB_STMT_START { \ + hb_##obj##_set_user_data (obj, &_hb_wasm_ref_type_key, \ + (void *) hb_wasm_ref_type_##obj, \ + nullptr, false); \ + (void) wasm_externref_obj2ref (module_inst, obj, &obj##ref); \ + } HB_STMT_END + +#define HB_RETURN_STRUCT(type, name) \ + type *_name_ptr = nullptr; \ + { \ + if (likely (wasm_runtime_validate_app_addr (module_inst, \ + retptr, sizeof (type)))) \ + { \ + _name_ptr = (type *) wasm_runtime_addr_app_to_native (module_inst, retptr); \ + if (unlikely (!_name_ptr)) \ + return; \ + } \ + } \ + type &name = *_name_ptr + +#define HB_PTR_PARAM(type, name) \ + type *name = nullptr; \ + HB_STMT_START { \ + if (likely (wasm_runtime_validate_app_addr (module_inst, \ + name##ptr, sizeof (type)))) \ + name = (type *) wasm_runtime_addr_app_to_native (module_inst, name##ptr); \ + } HB_STMT_END + +#define HB_ARRAY_PARAM(type, name, length) \ + type *name = nullptr; \ + HB_STMT_START { \ + if (likely (!hb_unsigned_mul_overflows (length, sizeof (type)) && \ + wasm_runtime_validate_app_addr (module_inst, \ + name##ptr, length * sizeof (type)))) \ + name = (type *) wasm_runtime_addr_app_to_native (module_inst, name##ptr); \ + } HB_STMT_END + +#define HB_ARRAY_APP2NATIVE(type, name, length) \ + ((type *) (!hb_unsigned_mul_overflows (length, sizeof (type)) && \ + validate_app_addr (name, (length) * sizeof (type)) ? \ + addr_app_to_native (name) : nullptr)) + + +#endif /* HB_WASM_API_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc new file mode 100644 index 00000000000..79442e99ed7 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-wasm-shape.cc @@ -0,0 +1,470 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#undef HB_DEBUG_WASM +#define HB_DEBUG_WASM 1 + +#include "hb-shaper-impl.hh" + +#ifdef HAVE_WASM + +/* Compile wasm-micro-runtime with: + * + * $ cmake -DWAMR_BUILD_MULTI_MODULE=1 -DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_FAST_JIT=1 + * $ make + * + * If you manage to build a wasm shared module successfully and want to use it, + * do the following: + * + * - Add -DWAMR_BUILD_MULTI_MODULE=1 to your cmake build for wasm-micro-runtime, + * + * - Remove the #define HB_WASM_NO_MODULES line below, + * + * - Install your shared module with name ending in .wasm in + * $(prefix)/$(libdir)/harfbuzz/wasm/ + * + * - Build your font's wasm code importing the shared modules with the desired + * name. This can be done eg.: __attribute__((import_module("graphite2"))) + * before each symbol in the the shared-module's headers. + * + * - Try shaping your font and hope for the best... + * + * I haven't been able to get this to work since emcc's support for shared libraries + * requires support from the host that seems to be missing from wasm-micro-runtime? + */ + +#include "hb-wasm-api.hh" +#include "hb-wasm-api-list.hh" + +#ifndef HB_WASM_NO_MODULES +#define HB_WASM_NO_MODULES +#endif + + +#ifndef HB_WASM_NO_MODULES +static bool HB_UNUSED +_hb_wasm_module_reader (const char *module_name, + uint8_t **p_buffer, uint32_t *p_size) +{ + char path[sizeof (HB_WASM_MODULE_DIR) + 64] = HB_WASM_MODULE_DIR "/"; + strncat (path, module_name, sizeof (path) - sizeof (HB_WASM_MODULE_DIR) - 16); + strncat (path, ".wasm", 6); + + auto *blob = hb_blob_create_from_file (path); + + unsigned length; + auto *data = hb_blob_get_data (blob, &length); + + *p_buffer = (uint8_t *) hb_malloc (length); + + if (length && !p_buffer) + return false; + + memcpy (*p_buffer, data, length); + *p_size = length; + + hb_blob_destroy (blob); + + return true; +} + +static void HB_UNUSED +_hb_wasm_module_destroyer (uint8_t *buffer, uint32_t size) +{ + hb_free (buffer); +} +#endif + +/* + * shaper face data + */ + +#define HB_WASM_TAG_WASM HB_TAG('W','a','s','m') + +struct hb_wasm_shape_plan_t { + wasm_module_inst_t module_inst; + wasm_exec_env_t exec_env; + ptr_d(void, wasm_shape_plan); +}; + +struct hb_wasm_face_data_t { + hb_blob_t *wasm_blob; + wasm_module_t wasm_module; + mutable hb_atomic_ptr_t<hb_wasm_shape_plan_t> plan; +}; + +static bool +_hb_wasm_init () +{ + /* XXX + * + * Umm. Make this threadsafe. How?! + * It's clunky that we can't allocate a static mutex. + * So we have to first allocate one on the heap atomically... + * + * Do we also need to lock around module creation? + * + * Also, wasm-micro-runtime uses a singleton instance. So if + * another library or client uses it, all bets are off. :-( + * If nothing else, around HB_REF2OBJ(). + */ + + static bool initialized; + if (initialized) + return true; + + RuntimeInitArgs init_args; + hb_memset (&init_args, 0, sizeof (RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *) hb_malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *) hb_realloc; + init_args.mem_alloc_option.allocator.free_func = (void *) hb_free; + + // Native symbols need below registration phase + init_args.n_native_symbols = ARRAY_LENGTH (_hb_wasm_native_symbols); + init_args.native_module_name = "env"; + init_args.native_symbols = _hb_wasm_native_symbols; + + if (unlikely (!wasm_runtime_full_init (&init_args))) + { + DEBUG_MSG (WASM, nullptr, "Init runtime environment failed."); + return false; + } + +#ifndef HB_WASM_NO_MODULES + wasm_runtime_set_module_reader (_hb_wasm_module_reader, + _hb_wasm_module_destroyer); +#endif + + initialized = true; + return true; +} + +hb_wasm_face_data_t * +_hb_wasm_shaper_face_data_create (hb_face_t *face) +{ + char error[128]; + hb_wasm_face_data_t *data = nullptr; + hb_blob_t *wasm_blob = nullptr; + wasm_module_t wasm_module = nullptr; + + wasm_blob = hb_face_reference_table (face, HB_WASM_TAG_WASM); + unsigned length = hb_blob_get_length (wasm_blob); + if (!length) + goto fail; + + if (!_hb_wasm_init ()) + goto fail; + + wasm_module = wasm_runtime_load ((uint8_t *) hb_blob_get_data_writable (wasm_blob, nullptr), + length, error, sizeof (error)); + if (unlikely (!wasm_module)) + { + DEBUG_MSG (WASM, nullptr, "Load wasm module failed: %s", error); + goto fail; + } + + data = (hb_wasm_face_data_t *) hb_calloc (1, sizeof (hb_wasm_face_data_t)); + if (unlikely (!data)) + goto fail; + + data->wasm_blob = wasm_blob; + data->wasm_module = wasm_module; + + return data; + +fail: + if (wasm_module) + wasm_runtime_unload (wasm_module); + hb_blob_destroy (wasm_blob); + hb_free (data); + return nullptr; +} + +static hb_wasm_shape_plan_t * +acquire_shape_plan (hb_face_t *face, + const hb_wasm_face_data_t *face_data) +{ + char error[128]; + + /* Fetch cached one if available. */ + hb_wasm_shape_plan_t *plan = face_data->plan.get_acquire (); + if (likely (plan && face_data->plan.cmpexch (plan, nullptr))) + return plan; + + plan = (hb_wasm_shape_plan_t *) hb_calloc (1, sizeof (hb_wasm_shape_plan_t)); + + wasm_module_inst_t module_inst = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_function_inst_t func = nullptr; + + constexpr uint32_t stack_size = 32 * 1024, heap_size = 2 * 1024 * 1024; + + module_inst = plan->module_inst = wasm_runtime_instantiate (face_data->wasm_module, + stack_size, heap_size, + error, sizeof (error)); + if (unlikely (!module_inst)) + { + DEBUG_MSG (WASM, face_data, "Create wasm module instance failed: %s", error); + goto fail; + } + + exec_env = plan->exec_env = wasm_runtime_create_exec_env (module_inst, + stack_size); + if (unlikely (!exec_env)) { + DEBUG_MSG (WASM, face_data, "Create wasm execution environment failed."); + goto fail; + } + + func = wasm_runtime_lookup_function (module_inst, "shape_plan_create", nullptr); + if (func) + { + wasm_val_t results[1]; + wasm_val_t arguments[1]; + + HB_OBJ2REF (face); + if (unlikely (!faceref)) + { + DEBUG_MSG (WASM, face_data, "Failed to register face object."); + goto fail; + } + + results[0].kind = WASM_I32; + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = faceref; + bool ret = wasm_runtime_call_wasm_a (exec_env, func, + ARRAY_LENGTH (results), results, + ARRAY_LENGTH (arguments), arguments); + + if (unlikely (!ret)) + { + DEBUG_MSG (WASM, module_inst, "Calling shape_plan_create() failed: %s", + wasm_runtime_get_exception (module_inst)); + goto fail; + } + plan->wasm_shape_planptr = results[0].of.i32; + } + + return plan; + +fail: + + if (exec_env) + wasm_runtime_destroy_exec_env (exec_env); + if (module_inst) + wasm_runtime_deinstantiate (module_inst); + hb_free (plan); + return nullptr; +} + +static void +release_shape_plan (const hb_wasm_face_data_t *face_data, + hb_wasm_shape_plan_t *plan, + bool cache = false) +{ + if (cache && face_data->plan.cmpexch (nullptr, plan)) + return; + + auto *module_inst = plan->module_inst; + auto *exec_env = plan->exec_env; + + /* Is there even any point to having a shape_plan_destroy function + * and calling it? */ + if (plan->wasm_shape_planptr) + { + + auto *func = wasm_runtime_lookup_function (module_inst, "shape_plan_destroy", nullptr); + if (func) + { + wasm_val_t arguments[1]; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = plan->wasm_shape_planptr; + bool ret = wasm_runtime_call_wasm_a (exec_env, func, + 0, nullptr, + ARRAY_LENGTH (arguments), arguments); + + if (unlikely (!ret)) + { + DEBUG_MSG (WASM, module_inst, "Calling shape_plan_destroy() failed: %s", + wasm_runtime_get_exception (module_inst)); + } + } + } + + wasm_runtime_destroy_exec_env (exec_env); + wasm_runtime_deinstantiate (module_inst); + hb_free (plan); +} + +void +_hb_wasm_shaper_face_data_destroy (hb_wasm_face_data_t *data) +{ + if (data->plan.get_relaxed ()) + release_shape_plan (data, data->plan); + wasm_runtime_unload (data->wasm_module); + hb_blob_destroy (data->wasm_blob); + hb_free (data); +} + + +/* + * shaper font data + */ + +struct hb_wasm_font_data_t {}; + +hb_wasm_font_data_t * +_hb_wasm_shaper_font_data_create (hb_font_t *font HB_UNUSED) +{ + return (hb_wasm_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; +} + +void +_hb_wasm_shaper_font_data_destroy (hb_wasm_font_data_t *data HB_UNUSED) +{ +} + + +/* + * shaper + */ + +hb_bool_t +_hb_wasm_shape (hb_shape_plan_t *shape_plan, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features) +{ + if (unlikely (buffer->in_error ())) + return false; + + bool ret = true; + hb_face_t *face = font->face; + const hb_wasm_face_data_t *face_data = face->data.wasm; + + bool retried = false; + if (0) + { +retry: + DEBUG_MSG (WASM, font, "Retrying..."); + } + + wasm_function_inst_t func = nullptr; + + hb_wasm_shape_plan_t *plan = acquire_shape_plan (face, face_data); + if (unlikely (!plan)) + { + DEBUG_MSG (WASM, face_data, "Acquiring shape-plan failed."); + return false; + } + + auto *module_inst = plan->module_inst; + auto *exec_env = plan->exec_env; + + HB_OBJ2REF (font); + HB_OBJ2REF (buffer); + if (unlikely (!fontref || !bufferref)) + { + DEBUG_MSG (WASM, module_inst, "Failed to register objects."); + goto fail; + } + + func = wasm_runtime_lookup_function (module_inst, "shape", nullptr); + if (unlikely (!func)) + { + DEBUG_MSG (WASM, module_inst, "Shape function not found."); + goto fail; + } + + wasm_val_t results[1]; + wasm_val_t arguments[5]; + + results[0].kind = WASM_I32; + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = plan->wasm_shape_planptr; + arguments[1].kind = WASM_I32; + arguments[1].of.i32 = fontref; + arguments[2].kind = WASM_I32; + arguments[2].of.i32 = bufferref; + arguments[3].kind = WASM_I32; + arguments[3].of.i32 = num_features ? wasm_runtime_module_dup_data (module_inst, + (const char *) features, + num_features * sizeof (features[0])) : 0; + arguments[4].kind = WASM_I32; + arguments[4].of.i32 = num_features; + + ret = wasm_runtime_call_wasm_a (exec_env, func, + ARRAY_LENGTH (results), results, + ARRAY_LENGTH (arguments), arguments); + + if (num_features) + wasm_runtime_module_free (module_inst, arguments[2].of.i32); + + if (unlikely (!ret || !results[0].of.i32)) + { + DEBUG_MSG (WASM, module_inst, "Calling shape() failed: %s", + wasm_runtime_get_exception (module_inst)); + if (!buffer->ensure_unicode ()) + { + DEBUG_MSG (WASM, font, "Shape failed but buffer is not in Unicode; failing..."); + goto fail; + } + if (retried) + { + DEBUG_MSG (WASM, font, "Giving up..."); + goto fail; + } + buffer->successful = true; + retried = true; + release_shape_plan (face_data, plan); + plan = nullptr; + goto retry; + } + + /* TODO Regularize clusters according to direction & cluster level, + * such that client doesn't crash with unmet expectations. */ + + if (!results[0].of.i32) + { +fail: + ret = false; + } + + release_shape_plan (face_data, plan, ret); + + if (ret) + { + buffer->clear_glyph_flags (); + buffer->unsafe_to_break (); + } + + return ret; +} + +#endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh index 205f8cf1964..49119b8f82d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh @@ -315,6 +315,14 @@ extern "C" void hb_free_impl(void *ptr); #define __restrict #endif +#ifndef HB_ALWAYS_INLINE +#if defined(_MSC_VER) +#define HB_ALWAYS_INLINE __forceinline +#else +#define HB_ALWAYS_INLINE __attribute__((always_inline)) inline +#endif +#endif + /* * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411 * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc index edc9872eed6..4af9569d110 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc @@ -245,7 +245,7 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index if (hb_color_get_alpha (color) != 255) fprintf (f, "fill-opacity=\"%.3f\"", (double) hb_color_get_alpha (color) / 255.); fprintf (f, "d=\""); - hb_font_get_glyph_shape (font, layers[layer].glyph, funcs, &draw_data); + hb_font_draw_glyph (font, layers[layer].glyph, funcs, &draw_data); fprintf (f, "\"/>\n"); } @@ -284,7 +284,7 @@ dump_glyphs (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index) draw_data_t draw_data; draw_data.ascender = font_extents.ascender; draw_data.f = f; - hb_font_get_glyph_shape (font, gid, funcs, &draw_data); + hb_font_draw_glyph (font, gid, funcs, &draw_data); fprintf (f, "\"/></svg>"); fclose (f); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build b/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build index 90735cb7e9b..4d63ecf90ae 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build @@ -324,6 +324,19 @@ hb_glib_headers = files('hb-glib.h') hb_graphite2_sources = files('hb-graphite2.cc') hb_graphite2_headers = files('hb-graphite2.h') +hb_wasm_sources = files( + 'hb-wasm-api.cc', + 'hb-wasm-api.hh', + 'hb-wasm-api-blob.hh', + 'hb-wasm-api-buffer.hh', + 'hb-wasm-api-common.hh', + 'hb-wasm-api-face.hh', + 'hb-wasm-api-font.hh', + 'hb-wasm-api-shape.hh', + 'hb-wasm-shape.cc', +) +hb_wasm_headers = files() + # System-dependent sources and headers hb_coretext_sources = files('hb-coretext.cc') @@ -353,11 +366,10 @@ hb_subset_sources = files( 'hb-subset-cff-common.cc', 'hb-subset-cff-common.hh', 'hb-subset-cff1.cc', - 'hb-subset-cff1.hh', 'hb-subset-cff2.cc', - 'hb-subset-cff2.hh', 'hb-subset-input.cc', 'hb-subset-input.hh', + 'hb-subset-instancer-solver.hh', 'hb-subset-instancer-solver.cc', 'hb-subset-plan.cc', 'hb-subset-plan.hh', @@ -417,7 +429,7 @@ custom_target('harfbuzz.cc', output: 'harfbuzz.cc', input: hb_base_sources + hb_glib_sources + hb_ft_sources + hb_graphite2_sources + hb_uniscribe_sources + hb_gdi_sources + - hb_directwrite_sources + hb_coretext_sources, + hb_directwrite_sources + hb_coretext_sources + hb_wasm_sources, command: [find_program('gen-harfbuzzcc.py'), '@OUTPUT@', meson.current_source_dir(), '@INPUT@'], ) @@ -460,6 +472,13 @@ if conf.get('HAVE_GRAPHITE2', 0) == 1 harfbuzz_deps += [graphite2_dep, graphite_dep] endif +if conf.get('HAVE_WASM', 0) == 1 + hb_sources += hb_wasm_sources + hb_headers += hb_wasm_headers + harfbuzz_deps += wasm_dep + #harfbuzz_deps += llvm_dep +endif + if conf.get('HAVE_UNISCRIBE', 0) == 1 hb_sources += hb_uniscribe_sources hb_headers += hb_uniscribe_headers @@ -497,6 +516,7 @@ features = [ 'GRAPHITE', 'ICU', 'UNISCRIBE', + 'WASM', ] hb_enabled_features = configuration_data() @@ -700,6 +720,8 @@ if get_option('tests').enabled() 'test-unicode-ranges': ['test-unicode-ranges.cc'], 'test-vector': ['test-vector.cc', 'hb-static.cc'], 'test-bimap': ['test-bimap.cc', 'hb-static.cc'], + 'test-instancer-solver': ['test-subset-instancer-solver.cc', 'hb-subset-instancer-solver.cc', 'hb-static.cc'], + 'test-tuple-varstore': ['test-tuple-varstore.cc', 'hb-subset-instancer-solver.cc', 'hb-static.cc'], } foreach name, source : compiled_tests if cpp.get_argument_syntax() == 'msvc' and source.contains('hb-static.cc') @@ -846,7 +868,7 @@ if have_gobject if build_gir conf.set('HAVE_INTROSPECTION', 1) - hb_gen_files_gir = gnome.generate_gir(libharfbuzz_gobject, + hb_gen_files_gir = gnome.generate_gir([libharfbuzz_gobject, libharfbuzz], sources: [gir_headers, gir_sources, gobject_enums_h], dependencies: libharfbuzz_dep, namespace: 'HarfBuzz', @@ -854,7 +876,7 @@ if have_gobject identifier_prefix: 'hb_', symbol_prefix: ['hb', 'hb_gobject'], includes: ['GObject-2.0', 'freetype2-2.0'], - export_packages: ['harfbuzz-gobject'], + export_packages: ['harfbuzz-gobject', 'harfbuzz'], header: 'hb-gobject.h', install: true, extra_args: ['--cflags-begin', @@ -910,7 +932,10 @@ if get_option('tests').enabled() env.set('HBHEADERS', ' '.join(HBHEADERS)) if cpp.get_argument_syntax() != 'msvc' and not meson.is_cross_build() # ensure the local tools are usable - dist_check_script += ['check-libstdc++', 'check-static-inits', 'check-symbols'] + dist_check_script += ['check-static-inits', 'check-symbols'] + if get_option('wasm').disabled() + dist_check_script += ['check-libstdc++'] + endif endif foreach name : dist_check_script diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-get-alternates.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-get-alternates.cc index c9f3b4edb53..555440c590d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-get-alternates.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-gsub-get-alternates.cc @@ -65,7 +65,7 @@ main (int argc, char **argv) for (unsigned i = 0; i < count; i++) { unsigned alt_count = 0; - for (unsigned lookup_index = HB_SET_VALUE_INVALID; + for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookup_indexes, &lookup_index);) if ((alt_count = hb_ot_layout_lookup_get_glyph_alternates (face, lookup_index, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc index 61cc8bfb32f..cb722eb92b0 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc @@ -79,7 +79,7 @@ main (int argc, char **argv) s.set (1, 2); s.set (3, 4); - hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> v (s); + hb_vector_t<hb_codepoint_pair_t> v (s); hb_map_t v0 (v); hb_map_t v1 (s); hb_map_t v2 (std::move (s)); @@ -112,7 +112,7 @@ main (int argc, char **argv) /* Test initializing from initializer list and swapping. */ { - using pair_t = hb_pair_t<hb_codepoint_t, hb_codepoint_t>; + using pair_t = hb_codepoint_pair_t; hb_map_t v1 {pair_t{1,2}, pair_t{4,5}}; hb_map_t v2 {pair_t{3,4}}; hb_swap (v1, v2); @@ -149,7 +149,7 @@ main (int argc, char **argv) /* Test hashing maps. */ { - using pair = hb_pair_t<hb_codepoint_t, hb_codepoint_t>; + using pair = hb_codepoint_pair_t; hb_hashmap_t<hb_map_t, hb_map_t> m1; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc index 5f13ab3225c..853aed406b7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc @@ -91,7 +91,7 @@ main (int argc, char **argv) s << 12; /* Sink a range. */ - s << hb_pair_t<hb_codepoint_t, hb_codepoint_t> {1, 3}; + s << hb_codepoint_pair_t {1, 3}; hb_set_t v (hb_iter (s)); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc new file mode 100644 index 00000000000..ca473d94f62 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-subset-instancer-solver.cc @@ -0,0 +1,395 @@ +/* + * Copyright © 2023 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Qunxin Liu + */ + +#include "hb-subset-instancer-solver.hh" + +static inline bool approx (Triple a, Triple b) +{ + return fabsf (a.minimum - b.minimum) < 0.000001f && + fabsf (a.middle - b.middle) < 0.000001f && + fabsf (a.maximum - b.maximum) < 0.000001f; +} + +static inline bool approx (float a, float b) +{ return fabsf (a - b) < 0.000001f; } + +/* tests ported from + * https://github.com/fonttools/fonttools/blob/main/Tests/varLib/instancer/solver_test.py */ +int +main (int argc, char **argv) +{ + /* Case 1 */ + { + /* pin axis*/ + Triple tent (0.f, 1.f, 1.f); + Triple axis_range (0.f, 0.f, 0.f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 0); + } + + { + /* pin axis*/ + Triple tent (0.f, 1.f, 1.f); + Triple axis_range (0.5f, 0.5f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 0.5f); + assert (out[0].second == Triple ()); + } + + { + /* tent falls outside the new axis range */ + Triple tent (0.3f, 0.5f, 0.8f); + Triple axis_range (0.1f, 0.2f, 0.3f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 0); + } + + /* Case 2 */ + { + Triple tent (0.f, 1.f, 1.f); + Triple axis_range (-1.f, 0.f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 0.5f); + assert (out[0].second == Triple (0.f, 1.f, 1.f)); + } + + /* Case 2 */ + { + Triple tent (0.f, 1.f, 1.f); + Triple axis_range (-1.f, 0.f, 0.75f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 0.75f); + assert (out[0].second == Triple (0.f, 1.f, 1.f)); + } + + /* Without gain: */ + /* Case 3 */ + { + Triple tent (0.f, 0.2f, 1.f); + Triple axis_range (-1.f, 0.f, 0.8f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 1.f); + assert (out[0].second == Triple (0.f, 0.25f, 1.25f)); + } + + /* Case 3 boundary */ + { + Triple tent (0.f, 0.4f, 1.f); + Triple axis_range (-1.f, 0.f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 1.f); + assert (out[0].second == Triple (0.f, 0.8f, 32767/(float) (1 << 14))); + } + + /* Case 4 */ + { + Triple tent (0.f, 0.25f, 1.f); + Triple axis_range (-1.f, 0.f, 0.4f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 2); + assert (out[0].first == 1.f); + assert (out[0].second == Triple (0.f, 0.625f, 1.f)); + assert (approx (out[1].first, 0.8f)); + assert (out[1].second == Triple (0.625f, 1.f, 1.f)); + } + + /* Case 4 */ + { + Triple tent (0.25f, 0.3f, 1.05f); + Triple axis_range (0.f, 0.2f, 0.4f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 2); + assert (out[0].first == 1.f); + assert (approx (out[0].second, Triple (0.25f, 0.5f, 1.f))); + assert (approx (out[1].first, 2.6f/3)); + assert (approx (out[1].second, Triple (0.5f, 1.f, 1.f))); + } + + /* Case 4 boundary */ + { + Triple tent (0.25f, 0.5f, 1.f); + Triple axis_range (0.f, 0.25f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 1.f); + assert (out[0].second == Triple (0.f, 1.f, 1.f)); + } + + /* With gain */ + /* Case 3a/1neg */ + { + Triple tent (0.f, 0.5f, 1.f); + Triple axis_range (0.f, 0.5f, 1.f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 3); + assert (out[0].first == 1.f); + assert (out[0].second == Triple ()); + assert (out[1].first == -1.f); + assert (out[1].second == Triple (0.f, 1.f, 1.f)); + assert (out[2].first == -1.f); + assert (out[2].second == Triple (-1.f, -1.f, 0.f)); + } + + { + Triple tent (0.f, 0.5f, 1.f); + Triple axis_range (0.f, 0.5f, 0.75f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 3); + assert (out[0].first == 1.f); + assert (out[0].second == Triple ()); + assert (out[1].first == -0.5f); + assert (out[1].second == Triple (0.f, 1.f, 1.f)); + assert (out[2].first == -1.f); + assert (out[2].second == Triple (-1.f, -1.f, 0.f)); + } + + { + Triple tent (0.f, 0.5f, 1.f); + Triple axis_range (0.f, 0.25f, 0.8f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 4); + assert (out[0].first == 0.5f); + assert (out[0].second == Triple ()); + assert (out[1].first == 0.5f); + assert (approx (out[1].second, Triple (0.f, 0.454545f, 0.909091f))); + assert (approx (out[2].first, -0.1f)); + assert (approx (out[2].second, Triple (0.909091f, 1.f, 1.f))); + assert (out[3].first == -0.5f); + assert (out[3].second == Triple (-1.f, -1.f, 0.f)); + } + + /* Case 3a/1neg */ + { + Triple tent (0.f, 0.5f, 2.f); + Triple axis_range (0.2f, 0.5f, 0.8f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 3); + assert (out[0].first == 1.f); + assert (out[0].second == Triple ()); + assert (approx (out[1].first, -0.2f)); + assert (out[1].second == Triple (0.f, 1.f, 1.f)); + assert (approx (out[2].first, -0.6f)); + assert (out[2].second == Triple (-1.f, -1.f, 0.f)); + } + + /* Case 3a/1neg */ + { + Triple tent (0.f, 0.5f, 2.f); + Triple axis_range (0.2f, 0.5f, 1.f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 3); + assert (out[0].first == 1.f); + assert (out[0].second == Triple ()); + assert (approx (out[1].first, -1.f/3)); + assert (out[1].second == Triple (0.f, 1.f, 1.f)); + assert (approx (out[2].first, -0.6f)); + assert (out[2].second == Triple (-1.f, -1.f, 0.f)); + } + + /* Case 3 */ + { + Triple tent (0.f, 0.5f, 1.f); + Triple axis_range (0.25f, 0.25f, 0.75f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 2); + assert (out[0].first == 0.5f); + assert (out[0].second == Triple ()); + assert (out[1].first == 0.5f); + assert (out[1].second == Triple (0.f, 0.5f, 1.0f)); + } + + /* Case 1neg */ + { + Triple tent (0.f, 0.5f, 1.f); + Triple axis_range (0.f, 0.25f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 3); + assert (out[0].first == 0.5f); + assert (out[0].second == Triple ()); + assert (out[1].first == 0.5f); + assert (out[1].second == Triple (0.f, 1.f, 1.f)); + assert (out[2].first == -0.5f); + assert (out[2].second == Triple (-1.f, -1.f, 0.f)); + } + + /* Case 2neg */ + { + Triple tent (0.05f, 0.55f, 1.f); + Triple axis_range (0.f, 0.25f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 4); + assert (approx (out[0].first, 0.4f)); + assert (out[0].second == Triple ()); + assert (approx (out[1].first, 0.5f)); + assert (out[1].second == Triple (0.f, 1.f, 1.f)); + assert (approx (out[2].first, -0.4f)); + assert (out[2].second == Triple (-1.f, -0.8f, 0.f)); + assert (approx (out[3].first, -0.4f)); + assert (out[3].second == Triple (-1.f, -1.f, -0.8f)); + } + + /* Case 2neg, other side */ + { + Triple tent (-1.f, -0.55f, -0.05f); + Triple axis_range (-0.5f, -0.25f, 0.f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 4); + assert (approx (out[0].first, 0.4f)); + assert (out[0].second == Triple ()); + assert (approx (out[1].first, 0.5f)); + assert (out[1].second == Triple (-1.f, -1.f, 0.f)); + assert (approx (out[2].first, -0.4f)); + assert (out[2].second == Triple (0.f, 0.8f, 1.f)); + assert (approx (out[3].first, -0.4f)); + assert (out[3].second == Triple (0.8f, 1.f, 1.f)); + } + + /* Misc corner cases */ + { + Triple tent (0.5f, 0.5f, 0.5f); + Triple axis_range (0.5f, 0.5f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 1.f); + assert (out[0].second == Triple ()); + } + + { + Triple tent (0.3f, 0.5f, 0.7f); + Triple axis_range (0.1f, 0.5f, 0.9f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 5); + assert (out[0].first == 1.f); + assert (out[0].second == Triple ()); + assert (out[1].first == -1.f); + assert (out[1].second == Triple (0.f, 0.5f, 1.f)); + assert (out[2].first == -1.f); + assert (out[2].second == Triple (0.5f, 1.f, 1.f)); + assert (out[3].first == -1.f); + assert (approx (out[3].second, Triple (-1.f, -0.5f, 0.f))); + assert (out[4].first == -1.f); + assert (approx (out[4].second, Triple (-1.f, -1.f, -0.5f))); + } + + { + Triple tent (0.5f, 0.5f, 0.5f); + Triple axis_range (0.25f, 0.25f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 1.f); + assert (out[0].second == Triple (1.f, 1.f, 1.f)); + } + + { + Triple tent (0.5f, 0.5f, 0.5f); + Triple axis_range (0.25f, 0.35f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 1.f); + assert (out[0].second == Triple (1.f, 1.f, 1.f)); + } + + { + Triple tent (0.5f, 0.5f, 0.55f); + Triple axis_range (0.25f, 0.35f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 1.f); + assert (out[0].second == Triple (1.f, 1.f, 1.f)); + } + + { + Triple tent (0.5f, 0.5f, 1.f); + Triple axis_range (0.5f, 0.5f, 1.f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 2); + assert (out[0].first == 1.f); + assert (out[0].second == Triple ()); + assert (out[1].first == -1.f); + assert (out[1].second == Triple (0.f, 1.f, 1.f)); + } + + { + Triple tent (0.25f, 0.5f, 1.f); + Triple axis_range (0.5f, 0.5f, 1.f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 2); + assert (out[0].first == 1.f); + assert (out[0].second == Triple ()); + assert (out[1].first == -1.f); + assert (out[1].second == Triple (0.f, 1.f, 1.f)); + } + + { + Triple tent (0.f, 0.2f, 1.f); + Triple axis_range (0.f, 0.f, 0.5f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 1); + assert (out[0].first == 1.f); + assert (out[0].second == Triple (0.f, 0.4f, 32767/(float) (1 << 14))); + } + + + { + Triple tent (0.f, 0.5f, 1.f); + Triple axis_range (-1.f, 0.25f, 1.f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 5); + assert (out[0].first == 0.5f); + assert (out[0].second == Triple ()); + assert (out[1].first == 0.5f); + assert (out[1].second == Triple (0.f, 1.f/3, 2.f/3)); + assert (out[2].first == -0.5f); + assert (out[2].second == Triple (2.f/3, 1.f, 1.f)); + assert (out[3].first == -0.5f); + assert (out[3].second == Triple (-1.f, -0.2f, 0.f)); + assert (out[4].first == -0.5f); + assert (out[4].second == Triple (-1.f, -1.f, -0.2f)); + } + + { + Triple tent (0.5f, 0.5f, 0.5f); + Triple axis_range (0.f, 0.5f, 1.f); + result_t out = rebase_tent (tent, axis_range); + assert (out.length == 5); + assert (out[0].first == 1.f); + assert (out[0].second == Triple ()); + assert (out[1].first == -1.f); + assert (out[1].second == Triple (0.f, 2/(float) (1 << 14), 1.f)); + assert (out[2].first == -1.f); + assert (out[2].second == Triple (2/(float) (1 << 14), 1.f, 1.f)); + assert (out[3].first == -1.f); + assert (out[3].second == Triple (-1.f, -2/(float) (1 << 14), 0.f)); + assert (out[4].first == -1.f); + assert (out[4].second == Triple (-1.f, -1.f, -2/(float) (1 << 14))); + } +} + diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc new file mode 100644 index 00000000000..c1fb747e574 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-tuple-varstore.cc @@ -0,0 +1,142 @@ +/* + * Copyright © 2020 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + */ +#include "hb-ot-var-cvar-table.hh" + +// cvar table data from Multi-ABC.ttf +const char cvar_data[] = "\x0\x1\x0\x0\x0\x2\x0\x14\x0\x51\xa0\x0\xc0\x0\x0\x54\xa0\x0\x40\x0\x2a\x29\x17\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\xd\xff\x0\xfd\x1\x0\xff\x0\xfd\x1\x0\xdb\xdb\xe6\xe6\x82\x0\xfd\x84\x6\xfd\x0\x2\xe3\xe3\xec\xec\x82\x4\x1\xe3\xe3\xec\xec\x82\x0\x1\x2a\x29\x17\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\xd\x1\x0\x5\xfd\x0\x1\x0\x5\xfd\x0\x61\x61\x44\x44\x82\x0\x5\x81\x9\x1\xff\x1\x7\xff\xfb\x49\x49\x35\x35\x82\x4\xff\x49\x49\x35\x35\x82\x0\xff"; + +static void +test_decompile_cvar () +{ + const OT::cvar* cvar_table = reinterpret_cast<const OT::cvar*> (cvar_data); + unsigned point_count = 65; + unsigned axis_count = 1; + + hb_tag_t axis_tag = HB_TAG ('w', 'g', 'h', 't'); + hb_map_t axis_idx_tag_map; + axis_idx_tag_map.set (0, axis_tag); + + OT::TupleVariationData::tuple_variations_t tuple_variations; + bool result = cvar_table->decompile_tuple_variations (axis_count, point_count, false, &axis_idx_tag_map, tuple_variations); + assert (result); + assert (tuple_variations.tuple_vars.length == 2); + for (unsigned i = 0; i < 2; i++) + { + assert (tuple_variations.tuple_vars[i].axis_tuples.get_population () == 1); + assert (!tuple_variations.tuple_vars[i].deltas_y); + assert (tuple_variations.tuple_vars[i].indices.length == 65); + assert (tuple_variations.tuple_vars[i].indices.length == tuple_variations.tuple_vars[i].deltas_x.length); + } + assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.f, -1.f, 0.f)); + assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.f, 1.f, 1.f)); + + hb_vector_t<float> deltas_1 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, -3.f, 1.f, 0.f, -1.f, 0.f, -3.f, 1.f, 0.f, -37.f, -37.f, -26.f, -26.f, 0.f, 0.f, 0.f, -3.f, 0.f, 0.f, 0.f, 0.f, 0.f, -3.f, 0.f, 2.f, -29.f, -29.f, -20.f, -20.f, 0.f, 0.f, 0.f, 1.f, -29.f, -29.f, -20.f, -20.f, 0.f, 0.f, 0.f, 1.f}; + for (unsigned i = 0; i < 65; i++) + { + if (i < 23) + assert (tuple_variations.tuple_vars[0].indices[i] == 0); + else + { + assert (tuple_variations.tuple_vars[0].indices[i] == 1); + assert (tuple_variations.tuple_vars[0].deltas_x[i] == deltas_1[i]); + } + } + + hb_vector_t<float> deltas_2 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 5.f, -3.f, 0.f, 1.f, 0.f, 5.f, -3.f, 0.f, 97.f, 97.f, 68.f, 68.f, 0.f, 0.f, 0.f, 5.f, 0.f, 0.f, 1.f, -1.f, 1.f, 7.f, -1.f, -5.f, 73.f, 73.f, 53.f, 53.f, 0.f, 0.f, 0.f, -1.f, 73.f, 73.f, 53.f, 53.f, 0.f, 0.f, 0.f, -1.f}; + for (unsigned i = 0 ; i < 65; i++) + { + if (i < 23) + assert (tuple_variations.tuple_vars[1].indices[i] == 0); + else + { + assert (tuple_variations.tuple_vars[1].indices[i] == 1); + assert (tuple_variations.tuple_vars[1].deltas_x[i] == deltas_2[i]); + } + } + + /* partial instancing wght=300:800 */ + hb_hashmap_t<hb_tag_t, Triple> normalized_axes_location; + normalized_axes_location.set (axis_tag, Triple (-0.512817f, 0.f, 0.700012f)); + + tuple_variations.change_tuple_variations_axis_limits (&normalized_axes_location); + tuple_variations.merge_tuple_variations (); + + assert (tuple_variations.tuple_vars[0].indices.length == 65); + assert (tuple_variations.tuple_vars[1].indices.length == 65); + assert (!tuple_variations.tuple_vars[0].deltas_y); + assert (!tuple_variations.tuple_vars[1].deltas_y); + assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.f, -1.f, 0.f)); + assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.f, 1.f, 1.f)); + + hb_vector_t<float> rounded_deltas_1 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -1, 0.f, -2, 1, 0.f, -1, 0.f, -2, 1, 0.f, -19, -19, -13, -13, 0.f, 0.f, 0.f, -2, 0.f, 0.f, 0.f, 0.f, 0.f, -2, 0.f, 1, -15, -15, -10.f, -10.f, 0.f, 0.f, 0.f, 1, -15, -15, -10.f, -10.f, 0.f, 0.f, 0.f, 1}; + + hb_vector_t<float> rounded_deltas_2 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1, 0.f, 4, -2, 0.f, 1, 0.f, 4, -2, 0.f, 68, 68, 48, 48, 0.f, 0.f, 0.f, 4, 0.f, 0.f, 1, -1, 1, 5, -1, -4, 51, 51, 37, 37, 0.f, 0.f, 0.f, -1, 51, 51, 37, 37, 0.f, 0.f, 0.f, -1}; + + for (unsigned i = 0; i < 65; i++) + { + if (i < 23) + { + assert (tuple_variations.tuple_vars[0].indices[i] == 0); + assert (tuple_variations.tuple_vars[1].indices[i] == 0); + } + else + { + assert (tuple_variations.tuple_vars[0].indices[i] == 1); + assert (tuple_variations.tuple_vars[1].indices[i] == 1); + assert (roundf (tuple_variations.tuple_vars[0].deltas_x[i]) == rounded_deltas_1[i]); + assert (roundf (tuple_variations.tuple_vars[1].deltas_x[i]) == rounded_deltas_2[i]); + } + } + + hb_map_t axes_index_map; + axes_index_map.set (0, 0); + bool res = tuple_variations.compile_bytes (axes_index_map, axis_idx_tag_map); + assert (res); + assert (tuple_variations.tuple_vars[0].compiled_tuple_header.length == 6); + const char tuple_var_header_1[] = "\x0\x51\xa0\x0\xc0\x0"; + for (unsigned i = 0; i < 6; i++) + assert(tuple_variations.tuple_vars[0].compiled_tuple_header.arrayZ[i] == tuple_var_header_1[i]); + + assert (tuple_variations.tuple_vars[1].compiled_tuple_header.length == 6); + const char tuple_var_header_2[] = "\x0\x54\xa0\x0\x40\x0"; + for (unsigned i = 0; i < 6; i++) + assert(tuple_variations.tuple_vars[1].compiled_tuple_header.arrayZ[i] == tuple_var_header_2[i]); + + assert (tuple_variations.tuple_vars[0].compiled_deltas.length == 37); + assert (tuple_variations.tuple_vars[1].compiled_deltas.length == 40); + const char compiled_deltas_1[] = "\x0d\xff\x00\xfe\x01\x00\xff\x00\xfe\x01\x00\xed\xed\xf3\xf3\x82\x00\xfe\x84\x06\xfe\x00\x01\xf1\xf1\xf6\xf6\x82\x04\x01\xf1\xf1\xf6\xf6\x82\x00\x01"; + for (unsigned i = 0; i < 37; i++) + assert (tuple_variations.tuple_vars[0].compiled_deltas.arrayZ[i] == compiled_deltas_1[i]); + + const char compiled_deltas_2[] = "\x0d\x01\x00\x04\xfe\x00\x01\x00\x04\xfe\x00\x44\x44\x30\x30\x82\x00\x04\x81\x09\x01\xff\x01\x05\xff\xfc\x33\x33\x25\x25\x82\x04\xff\x33\x33\x25\x25\x82\x00\xff"; + for (unsigned i = 0; i < 40; i++) + assert (tuple_variations.tuple_vars[1].compiled_deltas.arrayZ[i] == compiled_deltas_2[i]); +} + +int +main (int argc, char **argv) +{ + test_decompile_cvar (); +} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc index 65e51c65720..cc8ceabd102 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc @@ -181,6 +181,11 @@ main (int argc, char **argv) hb_map_t m; v.push (m); } + { + hb_vector_t<hb_map_t> v; + hb_map_t m; + v.push (m); + } return 0; } diff --git a/Build/source/libs/harfbuzz/version.ac b/Build/source/libs/harfbuzz/version.ac index c0cefd37cd1..ed6a07cdd6c 100644 --- a/Build/source/libs/harfbuzz/version.ac +++ b/Build/source/libs/harfbuzz/version.ac @@ -8,4 +8,4 @@ dnl dnl -------------------------------------------------------- dnl dnl m4-include this file to define the current harfbuzz version -m4_define([harfbuzz_version], [7.3.0]) +m4_define([harfbuzz_version], [8.0.0]) |