diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2021-12-12 23:55:43 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2021-12-12 23:55:43 +0000 |
commit | 69b272e1942e68fba0faf21c21e09a974ac68a5f (patch) | |
tree | ae15dbadd0c207c25d7f653ded5b5fb708065147 /Build/source/libs/harfbuzz | |
parent | 9d4b1fda1b468db18f8f70ece19f42e4e1a69f58 (diff) |
harfbuzz 3.2.0
git-svn-id: svn://tug.org/texlive/trunk@61290 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/harfbuzz')
46 files changed, 1666 insertions, 547 deletions
diff --git a/Build/source/libs/harfbuzz/ChangeLog b/Build/source/libs/harfbuzz/ChangeLog index 51407f54f97..518171e553a 100644 --- a/Build/source/libs/harfbuzz/ChangeLog +++ b/Build/source/libs/harfbuzz/ChangeLog @@ -1,3 +1,8 @@ +2021-12-13 Akira Kakuto <kakuto@jcom.zaq.ne.jp> + + Import harfbuzz-3.2.0. + * version.ac: Adjusted. + 2021-11-27 Akira Kakuto <kakuto@jcom.zaq.ne.jp> Import harfbuzz-3.1.2. diff --git a/Build/source/libs/harfbuzz/TLpatches/ChangeLog b/Build/source/libs/harfbuzz/TLpatches/ChangeLog index 64d1a4e3d70..6ff575858df 100644 --- a/Build/source/libs/harfbuzz/TLpatches/ChangeLog +++ b/Build/source/libs/harfbuzz/TLpatches/ChangeLog @@ -1,3 +1,8 @@ +2021-12-13 Akira Kakuto <kakuto@jcom.zaq.ne.jp> + + Imported harfbuzz-3.2.0 source tree from: + https://github.com/harfbuzz/harfbuzz/releases/download/3.2.0/ + 2021-11-27 Akira Kakuto <kakuto@jcom.zaq.ne.jp> Imported harfbuzz-3.1.2 source tree from: diff --git a/Build/source/libs/harfbuzz/TLpatches/TL-Changes b/Build/source/libs/harfbuzz/TLpatches/TL-Changes index 69eac2df310..a6c7adffe06 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-3.1.2/ tree as obtained from: - https://github.com/harfbuzz/harfbuzz/releases/download/3.1.2/ +Changes applied to the harfbuzz-3.2.0/ tree as obtained from: + https://github.com/harfbuzz/harfbuzz/releases/download/3.2.0/ Removed: COPYING diff --git a/Build/source/libs/harfbuzz/configure b/Build/source/libs/harfbuzz/configure index 0507f0a6b0b..7ba9b97d4de 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) 3.1.2. +# Generated by GNU Autoconf 2.71 for harfbuzz (TeX Live) 3.2.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='3.1.2' -PACKAGE_STRING='harfbuzz (TeX Live) 3.1.2' +PACKAGE_VERSION='3.2.0' +PACKAGE_STRING='harfbuzz (TeX Live) 3.2.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) 3.1.2 to adapt to many kinds of systems. +\`configure' configures harfbuzz (TeX Live) 3.2.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) 3.1.2:";; + short | recursive ) echo "Configuration of harfbuzz (TeX Live) 3.2.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 3.1.2 +harfbuzz (TeX Live) configure 3.2.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 3.1.2, which was +It was created by harfbuzz (TeX Live) $as_me 3.2.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='3.1.2' + VERSION='3.2.0' # Some tools Automake needs. @@ -5034,9 +5034,9 @@ WARNING_CFLAGS=$kpse_cv_warning_cflags HB_VERSION_MAJOR=3 -HB_VERSION_MINOR=1 -HB_VERSION_MICRO=2 -HB_VERSION=3.1.2 +HB_VERSION_MINOR=2 +HB_VERSION_MICRO=0 +HB_VERSION=3.2.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 3.1.2, which was +This file was extended by harfbuzz (TeX Live) $as_me 3.2.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 3.1.2 +harfbuzz (TeX Live) config.status 3.2.0 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/CONFIG.md b/Build/source/libs/harfbuzz/harfbuzz-src/CONFIG.md index 2ca02935c57..15b4ffa3cb2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/CONFIG.md +++ b/Build/source/libs/harfbuzz/harfbuzz-src/CONFIG.md @@ -135,10 +135,17 @@ The pre-defined configurations are: Most of the time, one of the pre-defined configuration is exactly what one needs. Sometimes, however, the pre-defined configuration cuts out features that might be desired in the library. Unfortunately there is no quick way to undo those -configurations from the command-line. But one can add a header file called -`config-override.h` to undefine certain `HB_NO_*` symbols as desired. Then -define `HAVE_CONFIG_OVERRIDE_H` to make `hb-config.hh` include your configuration -overrides at the end. +configurations from the command-line. + +However, configuration can still be overridden from a file. To do that, add your +override instructions (mostly `undef` instructions) to a header file and define +the macro `HB_CONFIG_OVERRIDE_H` to the string containing to that header file's +name. HarfBuzz will then include that file at appropriate right place during +configuration. + +Up until HarfBuzz 3.1.2 the the configuration override header file's name was +fixed and called `config-override.h`, and was activated by defining the macro +`HAVE_CONFIG_OVERRIDE_H`. That still works. ## Notes diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog index 6695b505896..7e19c3defcd 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog +++ b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog @@ -1,3 +1,602 @@ +commit be91d2917d9860326cb5fd1d03ffe1042a72f6d3 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun Dec 12 04:45:54 2021 +0200 + + 3.2.0 + + NEWS | 16 ++++++++++++++++ + configure.ac | 2 +- + meson.build | 2 +- + src/hb-version.h | 6 +++--- + 4 files changed, 21 insertions(+), 5 deletions(-) + +commit 77507a1d8d872d8cd4f62b807e933cd3e2cdb110 +Author: Garret Rieger <grieger@google.com> +Date: Fri Dec 10 14:10:04 2021 -0800 + + [subset] Don't double count visit lookups in closure_lookups + + Each recursed lookup was getting counted once in closure_lookups() and then again in hb_closure_lookups_context_t::recurse. + + src/hb-ot-layout-gsubgpos.hh | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +commit d67025705f0c4993cdd756bc47d942e14ceed0a1 +Author: Garret Rieger <grieger@google.com> +Date: Fri Dec 10 13:52:05 2021 -0800 + + [subset] reset the visited lookup count before each closure iteration. + + src/hb-ot-layout-gsubgpos.hh | 3 +++ + src/hb-ot-layout.cc | 1 + + 2 files changed, 4 insertions(+) + +commit 23159084b43c1ce429d9e98035bf845919fd8a89 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Dec 10 15:00:16 2021 -0700 + + [morx] Reverse graphemese, not whole buffer + + Fixes https://github.com/harfbuzz/harfbuzz/issues/3314 + Supersedes https://github.com/harfbuzz/harfbuzz/pull/3315 + + src/hb-aat-layout-morx-table.hh | 4 ++-- + src/hb-ot-layout.hh | 6 ++++++ + src/hb-ot-shape.cc | 15 +-------------- + test/shape/data/in-house/tests/macos.tests | 3 +++ + 4 files changed, 12 insertions(+), 16 deletions(-) + +commit 5b995526f7d0d1e688f68005b410a93cf1685544 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Dec 10 14:59:56 2021 -0700 + + [buffer] Fix reverse_group() to reverse() at the end + + src/hb-buffer.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 21c4fc1011854547edf564573fdbec4687e76e04 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Dec 10 13:02:43 2021 -0700 + + [buffer] Add optional merge_clusters arg to reverse_groups() + + src/hb-buffer.hh | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +commit e949e512181d04da1add14f6133a6d68f7a60fc2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Dec 10 12:58:27 2021 -0700 + + [ot-layout] Port foreach_grapheme to buffer foreach_group + + src/hb-ot-layout.hh | 22 ++++++---------------- + 1 file changed, 6 insertions(+), 16 deletions(-) + +commit eb96e69d18aa45a623c05bf69e562b3918724f6f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Dec 10 12:55:29 2021 -0700 + + [buffer] Add foreach_group() + + src/hb-buffer.hh | 40 ++++++++++++++++++++-------------------- + 1 file changed, 20 insertions(+), 20 deletions(-) + +commit 1b78e04c78338266c200226bccb21188355046ca +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Dec 10 12:45:43 2021 -0700 + + [buffer] Add ::reverse_groups() + + src/hb-buffer.cc | 23 ----------------------- + src/hb-buffer.hh | 26 +++++++++++++++++++++++++- + 2 files changed, 25 insertions(+), 24 deletions(-) + +commit 4cd96e73e40acfa65b7d0726a7186bf31c169b2a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Dec 10 12:33:21 2021 -0700 + + [buffer] Inline revers_range() / reverse() + + src/hb-buffer.cc | 23 ----------------------- + src/hb-buffer.hh | 10 ++++++++-- + 2 files changed, 8 insertions(+), 25 deletions(-) + +commit 5914acb3cbb3634e9e94e0e571d96b806b7ecacf +Author: Garret Rieger <grieger@google.com> +Date: Fri Dec 10 10:05:47 2021 -0800 + + [repacker] Clear distance and position cache when assigning a new space. + + A change in space will effect the distance assigned to the node and any of it's children so clear the distance cache. + + src/hb-repacker.hh | 2 ++ + 1 file changed, 2 insertions(+) + +commit 706014f69dc2cde140e17faf32d32a1cbd5d0000 +Author: Qunxin Liu <qxliu@google.com> +Date: Wed Dec 1 20:20:12 2021 -0800 + + [subset] (Chain)ContextSubst glyph_closure fix + + - When pos_glyphs is empty, use current full glyphs set as input for + subsequent recursive closure process + - Also increase max_lookup_visit_count to 35000 cause a real font file hit + previous limit 20000 and some lookups are dropped unexpectedly + + src/hb-ot-layout-common.hh | 6 +++--- + src/hb-ot-layout-gsubgpos.hh | 24 +++++++++++++-------- + ...Bold.default.627,644,623,62D,644,627,645,2E.ttf | Bin 11372 -> 19032 bytes + ...toNastaliqUrdu-Bold.default.627,644,62D,628.ttf | Bin 17640 -> 25608 bytes + .../NotoNastaliqUrdu-Bold.default.627,644.ttf | Bin 3512 -> 8040 bytes + ...rdu-Bold.default.633,645,627,621,20,644,627.ttf | Bin 12360 -> 22776 bytes + .../NotoNastaliqUrdu-Bold.default.63A,64A,631.ttf | Bin 19340 -> 27772 bytes + ...taliqUrdu-Bold.default.retain-all-codepoint.ttf | Bin 0 -> 543364 bytes + ....retain-gids.627,644,623,62D,644,627,645,2E.ttf | Bin 18208 -> 25868 bytes + ...staliqUrdu-Bold.retain-gids.627,644,62D,628.ttf | Bin 23704 -> 31676 bytes + .../NotoNastaliqUrdu-Bold.retain-gids.627,644.ttf | Bin 9160 -> 13688 bytes + ...Bold.retain-gids.633,645,627,621,20,644,627.ttf | Bin 18164 -> 28580 bytes + ...toNastaliqUrdu-Bold.retain-gids.63A,64A,631.ttf | Bin 25392 -> 33824 bytes + ...qUrdu-Bold.retain-gids.retain-all-codepoint.ttf | Bin 0 -> 543364 bytes + test/subset/data/fonts/NotoNastaliqUrdu-Bold.ttf | Bin 459600 -> 589224 bytes + .../data/tests/layout.notonastaliqurdu.tests | 1 + + 16 files changed, 19 insertions(+), 12 deletions(-) + +commit 441877f56aa09bc848a8860007232a7be5e179d9 +Author: Garret Rieger <grieger@google.com> +Date: Thu Dec 9 16:38:05 2021 -0800 + + [repacker] add test case for using max priority to resolve an overflow. + + src/test-repacker.cc | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 73 insertions(+) + +commit be2c488e5d20db18e3ee82dee6a22056ed526add +Author: Garret Rieger <grieger@google.com> +Date: Thu Dec 9 15:44:06 2021 -0800 + + [repacker] Improve vertex priority packing. + + Previous priority implementation would move a node further back within it's layer, but at max priority was unable to move any further up than that. This updates the implementation to have 3 priority levels: + 1. Distance is reduced by half of table size. + 2. Distance is reduced by full table size (move to beginning of the layer). + 3. Distance is set to 0. Vertex will be packed as soon as possible. + + Also makes the iterative resolutions aware of max priority, so it won't keep trying to raise priority beyond the maximum. + + src/hb-repacker.hh | 38 +++++++++++++++++++++++++++++--------- + 1 file changed, 29 insertions(+), 9 deletions(-) + +commit 2404617a605cd8c419fe67afa012ddc90a24c685 +Author: David Corbett <corbett.dav@northeastern.edu> +Date: Wed Dec 8 21:10:22 2021 -0500 + + Update language system tag registry to OT 1.9 + + src/gen-tag-table.py | 11 +++++++++-- + src/hb-ot-tag-table.hh | 14 +++++++++++++- + 2 files changed, 22 insertions(+), 3 deletions(-) + +commit 002a1f70b81d56b882bd5a68ebdc22c015e88f7f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Dec 8 10:45:30 2021 -0800 + + [ft] Disable vertical funcs if HB_NO_VERTICAL + + src/hb-ft.cc | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +commit ef14cad736e499f42281e09d3835ad667245e4be +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Dec 8 10:43:52 2021 -0800 + + [GPOS] Disable vertical advance if HB_NO_VERTICAL + + src/hb-ot-layout-gpos-table.hh | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +commit 6ed22de1279f7e68666bd9f024a80a4a48a1a467 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Dec 8 10:40:40 2021 -0800 + + [CONFIG] Fix HB_NO_VERTICAL build without HB_TINY + + src/hb-ot-glyf-table.hh | 12 ++++++++++-- + src/hb-ot-metrics.cc | 2 ++ + 2 files changed, 12 insertions(+), 2 deletions(-) + +commit 53eebc7cd2680a41c3e7c7ac363b7ecc1355d655 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Dec 8 08:32:41 2021 -0800 + + [CONFIG] Add HB_NO_VERTICAL + + src/hb-ot-face-table-list.hh | 2 ++ + src/hb-ot-font.cc | 18 +++++++++++++++--- + src/hb-ot-glyf-table.hh | 25 ++++++++++++++++++++++--- + src/hb-ot-hmtx-table.hh | 9 ++++++++- + src/hb-ot-metrics.cc | 5 +++++ + src/hb-ot-shape.cc | 4 ++++ + 6 files changed, 56 insertions(+), 7 deletions(-) + +commit 9bc5d2903a6c1669a3bd8aa47f42d34c6bbcf763 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Dec 8 08:16:17 2021 -0800 + + [TINY] Don't disable VORG table in any config profile + + Is needed for vertical layout of CFF fonts. + + Fixes https://github.com/harfbuzz/harfbuzz/discussions/3294#discussioncomment-1770313 + + src/hb-ot-face-table-list.hh | 2 +- + src/hb-ot-font.cc | 2 -- + 2 files changed, 1 insertion(+), 3 deletions(-) + +commit 3e4a25098df348c459f57829d84c4b0ebb3efc97 +Author: Garret Rieger <grieger@google.com> +Date: Mon Dec 6 16:00:15 2021 -0800 + + [repacker] add a maximum number of roots that can be moved in one iteration. + + Set to half of the roots in a space. This prevents the repacker from moving all roots in a space to a new space if their are overflows in every root. + + src/hb-repacker.hh | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +commit 02b12d7965710de93fa4b42617113e66ddf19add +Author: Garret Rieger <grieger@google.com> +Date: Mon Dec 6 15:23:35 2021 -0800 + + [repacker] Move all overflowing roots to a new space simultaneously. + + src/hb-repacker.hh | 69 +++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 47 insertions(+), 22 deletions(-) + +commit fa966bcc29e84a579fc32af7663a50bfe7814b1a +Author: Garret Rieger <grieger@google.com> +Date: Mon Dec 6 12:54:19 2021 -0800 + + [repacker] create repacker output buffer after final length is known. + + Don't rely on a buffer provided by the caller, as it may not be large enough. + + src/hb-repacker.hh | 60 ++++++++++++++++++++++++++---------- + src/hb-subset.cc | 18 +++++------ + src/test-repacker.cc | 87 ++++++++++++++++++---------------------------------- + 3 files changed, 80 insertions(+), 85 deletions(-) + +commit 51655a078e599c532b739c1e58556d873dabf6b0 +Author: Qunxin Liu <qxliu@google.com> +Date: Sun Dec 5 19:27:57 2021 -0800 + + [subset] COLR : only include glyphs after COLR closure + + src/hb-ot-color-colr-table.hh | 18 ++++++++++++------ + src/hb-subset-plan.cc | 4 +++- + src/hb-subset-plan.hh | 1 + + test/subset/data/Makefile.am | 1 + + test/subset/data/Makefile.sources | 1 + + .../colr_glyphs/BungeeColor-Regular.default.41.ttf | Bin 0 -> 1664 bytes + .../BungeeColor-Regular.drop-hints-retain-gids.41.ttf | Bin 0 -> 3384 bytes + .../colr_glyphs/BungeeColor-Regular.drop-hints.41.ttf | Bin 0 -> 1656 bytes + .../BungeeColor-Regular.retain-gids.41.ttf | Bin 0 -> 3392 bytes + test/subset/data/fonts/BungeeColor-Regular.ttf | Bin 0 -> 75348 bytes + test/subset/data/tests/colr_glyphs.tests | 11 +++++++++++ + test/subset/meson.build | 1 + + 12 files changed, 30 insertions(+), 7 deletions(-) + +commit 70f8c57e5c72697bdd2dc84b3573e1e90a94d681 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Dec 4 19:49:23 2021 -0800 + + [buffer] Rename find_min_cluster + + src/hb-buffer.cc | 7 ++++--- + src/hb-buffer.hh | 8 ++++---- + 2 files changed, 8 insertions(+), 7 deletions(-) + +commit 94d43c008ab4ec2281b693af1f4014b1ebce1b14 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Sat Dec 4 16:56:39 2021 -0800 + + [buffer] Merge and rename clear_glyph_flags() + + src/hb-buffer.hh | 5 ++--- + src/hb-coretext.cc | 2 +- + src/hb-directwrite.cc | 2 +- + src/hb-fallback-shape.cc | 2 +- + src/hb-graphite2.cc | 2 +- + src/hb-ot-layout-gsub-table.hh | 2 +- + src/hb-uniscribe.cc | 2 +- + 7 files changed, 8 insertions(+), 9 deletions(-) + +commit b95d252fabca73ded3c7529ba726499ec6dcda5d +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Dec 3 11:49:55 2021 -0700 + + [CONFIG] Add HB_CONFIG_OVERRIDE_H to simplify config overrides + + CONFIG.md | 15 +++++++++++---- + src/hb-config.hh | 7 +++++-- + 2 files changed, 16 insertions(+), 6 deletions(-) + +commit 74b46b29e7ebb8521fdbf92325a3798083381237 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Dec 2 19:50:16 2021 -0800 + + [subset] MATH: don't serialize coverage table when iterator is empty + + when iterator is empty, just set coverage offset to 0. + serialize() in coverage will at lease write out a 16-bit format header. + + src/hb-ot-math-table.hh | 10 +++++++--- + test/subset/data/Makefile.am | 1 + + test/subset/data/Makefile.sources | 1 + + .../Caudex-Regular.default.retain-all-codepoint.ttf | Bin 0 -> 417604 bytes + ...Caudex-Regular.glyph-names.retain-all-codepoint.ttf | Bin 0 -> 436712 bytes + ...r.keep-all-layout-features.retain-all-codepoint.ttf | Bin 0 -> 417604 bytes + ...dex-Regular.notdef-outline.retain-all-codepoint.ttf | Bin 0 -> 417780 bytes + ...Caudex-Regular.retain-gids.retain-all-codepoint.ttf | Bin 0 -> 417620 bytes + test/subset/data/fonts/Caudex-Regular.ttf | Bin 0 -> 466324 bytes + test/subset/data/tests/math_coverage_offset.tests | 12 ++++++++++++ + test/subset/meson.build | 1 + + 11 files changed, 22 insertions(+), 3 deletions(-) + +commit 1d9ef3a75a445a52d084e805d4abdbaaa4c782d7 +Author: Garret Rieger <grieger@google.com> +Date: Wed Dec 1 10:30:27 2021 -0800 + + [subset] Actually fix end_cp unitialized warning. + + src/hb-ot-cmap-table.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit d8635dfe5a06d1112ea563dcef788097b7b124af +Author: Garret Rieger <grieger@google.com> +Date: Wed Dec 1 10:14:10 2021 -0800 + + [subset] Fix warning about uninitialized use of end_cp. + + src/hb-ot-cmap-table.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 6c81cd9543f35cbc54e938b402355990a3b0859c +Author: Khaled Hosny <khaled@aliftype.com> +Date: Wed Dec 1 19:29:34 2021 +0200 + + [tests] Add tests for platform shapers + + Fixes https://github.com/harfbuzz/harfbuzz/issues/3115 + + test/shape/data/in-house/meson.build | 14 +++++++++++++- + test/shape/data/in-house/tests/coretext.tests | 1 + + test/shape/data/in-house/tests/directwrite.tests | 1 + + test/shape/data/in-house/tests/uniscribe.tests | 1 + + test/shape/meson.build | 11 +++++++++++ + 5 files changed, 27 insertions(+), 1 deletion(-) + +commit 7608b191672972efdc69ce49c22001346f5470c0 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Wed Dec 1 18:57:21 2021 +0200 + + [directwrite] Set unsafe to break flag + + Like the rest of platform shapers. Otherwise hb-shape --verify goes + crazy. + + src/hb-directwrite.cc | 2 ++ + 1 file changed, 2 insertions(+) + +commit 361a438658dcddea29d7c8b9c68bf2bc88109bde +Author: Khaled Hosny <khaled@aliftype.com> +Date: Wed Dec 1 03:16:46 2021 +0200 + + Revert "Revert "[hb-directwrite] Don't load dwrit.dll dynamically"" + + This reverts commit ecbe224743c205c99aa459b27e7fb241cc4b1dc5. + + It was causing directwrite shaper to crash in MSVC builds. + + src/hb-directwrite.cc | 36 ++---------------------------------- + 1 file changed, 2 insertions(+), 34 deletions(-) + +commit 549e2b7038282e34f83b54b36fabf02de0cbfcae +Author: Khaled Hosny <khaled@aliftype.com> +Date: Wed Dec 1 03:16:26 2021 +0200 + + Revert "Remove direct link to dwrite from meson scripts" + + This reverts commit 6ea6c581edb3cecf1b4b42854e37b40d6d067cd3. + + meson.build | 7 ++++++- + src/meson.build | 1 + + 2 files changed, 7 insertions(+), 1 deletion(-) + +commit 071aea42c28e84e89b550de03cbd0094382f634c +Author: Garret Rieger <grieger@google.com> +Date: Tue Nov 30 16:16:06 2021 -0800 + + [iter] add specialized implementation for hb_concat forward when iterators are not random access. + + src/hb-iter.hh | 20 +++++++++++++++----- + src/test-iter.cc | 19 +++++++++++++++++++ + 2 files changed, 34 insertions(+), 5 deletions(-) + +commit 2e935514d9790f6f8a7f6639c9564b3d7237d6d3 +Author: Garret Rieger <grieger@google.com> +Date: Tue Nov 30 16:02:05 2021 -0800 + + [iter] fix forward implementation in hb_concat(). + + Add test coverage for forward. + + src/hb-iter.hh | 6 ++++-- + src/test-iter.cc | 22 ++++++++++++++++++++++ + 2 files changed, 26 insertions(+), 2 deletions(-) + +commit 39e76af19ed6ab798d4671ff3e7a4b71e2abe6cf +Author: Garret Rieger <grieger@google.com> +Date: Tue Nov 30 15:25:40 2021 -0800 + + [subset] add all_links () to object_t. + + Helper to provide easy access to concatenated real and virtual links iterator. + + src/hb-repacker.hh | 44 +++++++++++++++----------------------------- + src/hb-serialize.hh | 5 +++++ + 2 files changed, 20 insertions(+), 29 deletions(-) + +commit 9121ed0cecab2296ee2a18042ed89c0ce95dbbaa +Author: Garret Rieger <grieger@google.com> +Date: Tue Nov 30 13:45:22 2021 -0800 + + [subset] Improve sharing of Ligature subtables. + + Ligature subtables use virtual links to enforce an ordering constraint between the subtables and the coverage table. Unfortunately this has the sideeffect of prevent the subtables from being shared by another Ligature with a different coverage table since object equality compares all links real and virtual. This change makes virtual links stored separately from real links and updates the equality check to only check real links. If an object is de-duped any virtual links it has are merged into the object that replaces it. + + src/hb-repacker.hh | 84 +++++++----- + src/hb-serialize.hh | 50 ++++--- + src/test-repacker.cc | 150 +++++++++++++-------- + ...ic-Regular.layout-test.retain-all-codepoint.ttf | Bin 46544 -> 46524 bytes + ...Howrah-Regular.default.retain-all-codepoint.ttf | Bin 174024 -> 173756 bytes + ...rah-Regular.drop-hints.retain-all-codepoint.ttf | Bin 99288 -> 99020 bytes + ...ah-Regular.retain-gids.retain-all-codepoint.ttf | Bin 174324 -> 174056 bytes + ...toNastaliqUrdu-Bold.default.627,644,62D,628.ttf | Bin 17732 -> 17640 bytes + .../NotoNastaliqUrdu-Bold.default.63A,64A,631.ttf | Bin 19432 -> 19340 bytes + ...staliqUrdu-Bold.retain-gids.627,644,62D,628.ttf | Bin 23792 -> 23704 bytes + ...toNastaliqUrdu-Bold.retain-gids.63A,64A,631.ttf | Bin 25484 -> 25392 bytes + ...hnadevaraya-Regular.default.c30,c36,c40,c4d.ttf | Bin 10860 -> 10848 bytes + ...varaya-Regular.default.retain-all-codepoint.ttf | Bin 572812 -> 572104 bytes + ...evaraya-Regular.glyph-names.c30,c36,c40,c4d.ttf | Bin 11292 -> 11280 bytes + ...ya-Regular.glyph-names.retain-all-codepoint.ttf | Bin 608460 -> 607752 bytes + ...raya-Regular.notdef-outline.c30,c36,c40,c4d.ttf | Bin 10940 -> 10928 bytes + ...Regular.notdef-outline.retain-all-codepoint.ttf | Bin 572892 -> 572184 bytes + ...evaraya-Regular.retain-gids.c30,c36,c40,c4d.ttf | Bin 16880 -> 16868 bytes + ...ya-Regular.retain-gids.retain-all-codepoint.ttf | Bin 572824 -> 572116 bytes + 19 files changed, 181 insertions(+), 103 deletions(-) + +commit ca227411102b615edb40a78d2355d2f6cf5291c5 +Author: Garret Rieger <grieger@google.com> +Date: Tue Nov 30 12:53:15 2021 -0800 + + [iter] add hb_concat (a, b). + + Iterates over a, and then over b. + + src/hb-iter.hh | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/test-iter.cc | 33 +++++++++++++++++++++++++ + 2 files changed, 106 insertions(+) + +commit 95329081c2c6e7f763b466ea3cfc9630ddb23dcf +Author: Garret Rieger <grieger@google.com> +Date: Fri Nov 26 16:18:42 2021 -0800 + + [subset] further optimize cmap4 packing. + + src/hb-ot-cmap-table.hh | 48 +++++++++++++++------ + ...aa-Regular-new.default.retain-all-codepoint.ttf | Bin 222692 -> 222684 bytes + ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 191568 -> 191560 bytes + ...Regular-new.drop-hints.retain-all-codepoint.ttf | Bin 191520 -> 191512 bytes + ...ortaa-Regular-new.gids.retain-all-codepoint.ttf | Bin 222692 -> 222684 bytes + ...egular-new.glyph-names.retain-all-codepoint.ttf | Bin 229684 -> 229676 bytes + ...ep-all-layout-features.retain-all-codepoint.ttf | Bin 223388 -> 223380 bytes + ...ar-new.layout-features.retain-all-codepoint.ttf | Bin 220884 -> 220876 bytes + ...a-Regular-new.name-ids.retain-all-codepoint.ttf | Bin 222432 -> 222424 bytes + ...lar-new.name-languages.retain-all-codepoint.ttf | Bin 222692 -> 222684 bytes + ...egular-new.name-legacy.retain-all-codepoint.ttf | Bin 222692 -> 222684 bytes + ...o-prune-unicode-ranges.retain-all-codepoint.ttf | Bin 222692 -> 222684 bytes + ...lar-new.notdef-outline.retain-all-codepoint.ttf | Bin 223288 -> 223280 bytes + ...egular-new.retain-gids.retain-all-codepoint.ttf | Bin 222740 -> 222732 bytes + ...tu-Regular.glyph-names.retain-all-codepoint.ttf | Bin 280064 -> 280056 bytes + ...traLightItalic.default.retain-all-codepoint.ttf | Bin 134364 -> 134344 bytes + ...ightItalic.glyph-names.retain-all-codepoint.ttf | Bin 145640 -> 145620 bytes + ...tItalic.notdef-outline.retain-all-codepoint.ttf | Bin 134492 -> 134472 bytes + ...ns-BlackItalic.default.retain-all-codepoint.ttf | Bin 120040 -> 120020 bytes + ...lackItalic.glyph-names.retain-all-codepoint.ttf | Bin 132284 -> 132264 bytes + ...kItalic.notdef-outline.retain-all-codepoint.ttf | Bin 120040 -> 120020 bytes + .../Tinos-Italic.default.retain-all-codepoint.ttf | Bin 410180 -> 410092 bytes + ...nos-Italic.glyph-names.retain-all-codepoint.ttf | Bin 435008 -> 434920 bytes + ...-Italic.notdef-outline.retain-all-codepoint.ttf | Bin 410180 -> 410092 bytes + ...nos-Italic.retain-gids.retain-all-codepoint.ttf | Bin 412556 -> 412468 bytes + ...wLatin-Regular.default.retain-all-codepoint.ttf | Bin 130076 -> 129952 bytes + ...in-Regular.layout-test.retain-all-codepoint.ttf | Bin 152052 -> 151928 bytes + ...in-Regular.retain-gids.retain-all-codepoint.ttf | Bin 133180 -> 133056 bytes + ...woMath-Regular.default.retain-all-codepoint.ttf | Bin 1033572 -> 1033528 bytes + ...th-Regular.glyph-names.retain-all-codepoint.ttf | Bin 1086348 -> 1086304 bytes + ...Regular.notdef-outline.retain-all-codepoint.ttf | Bin 1033820 -> 1033776 bytes + ...th-Regular.retain-gids.retain-all-codepoint.ttf | Bin 1048752 -> 1048716 bytes + 32 files changed, 36 insertions(+), 12 deletions(-) + +commit 599143824c39b3cf37c3cb714364b58d45fc0d3d +Author: Garret Rieger <grieger@google.com> +Date: Fri Nov 26 14:19:39 2021 -0800 + + [subset] Don't pad glyphs when using long loca. + + src/hb-ot-glyf-table.hh | 36 +++++++++++++-------- + ...tu-Regular.glyph-names.retain-all-codepoint.ttf | Bin 280296 -> 280064 bytes + ...Howrah-Regular.default.retain-all-codepoint.ttf | Bin 174308 -> 174024 bytes + ...ah-Regular.retain-gids.retain-all-codepoint.ttf | Bin 174608 -> 174324 bytes + .../Tinos-Italic.default.retain-all-codepoint.ttf | Bin 410932 -> 410180 bytes + ...nos-Italic.glyph-names.retain-all-codepoint.ttf | Bin 435760 -> 435008 bytes + ...-Italic.notdef-outline.retain-all-codepoint.ttf | Bin 410932 -> 410180 bytes + ...nos-Italic.retain-gids.retain-all-codepoint.ttf | Bin 413308 -> 412556 bytes + ...woMath-Regular.default.retain-all-codepoint.ttf | Bin 1035756 -> 1033572 bytes + ...th-Regular.glyph-names.retain-all-codepoint.ttf | Bin 1088532 -> 1086348 bytes + ...Regular.notdef-outline.retain-all-codepoint.ttf | Bin 1036004 -> 1033820 bytes + ...th-Regular.retain-gids.retain-all-codepoint.ttf | Bin 1050936 -> 1048752 bytes + ...varaya-Regular.default.retain-all-codepoint.ttf | Bin 573428 -> 572812 bytes + ...ya-Regular.glyph-names.retain-all-codepoint.ttf | Bin 609076 -> 608460 bytes + ...Regular.notdef-outline.retain-all-codepoint.ttf | Bin 573508 -> 572892 bytes + ...ya-Regular.retain-gids.retain-all-codepoint.ttf | Bin 573440 -> 572824 bytes + 16 files changed, 22 insertions(+), 14 deletions(-) + +commit d9660fd58a3ade1c8962e5cd3f7538a5b5189262 +Author: Garret Rieger <grieger@google.com> +Date: Thu Nov 25 18:15:35 2021 -0800 + + [subset] Make cmap4 packing more optimal. + + The current CMAP4 implementation uses whatever the current codepoint ranges are and then encodes them as indivudal glyph ids or as a delta if possible. However, it's often possible to save bytes by splitting up existing ranges and encoding parts of them using deltas where the cost of splitting the range is less than encoding each glyph individual. + + src/hb-ot-cmap-table.hh | 246 ++++++++++++--------- + ...aa-Regular-new.default.retain-all-codepoint.ttf | Bin 222756 -> 222692 bytes + ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 191632 -> 191568 bytes + ...Regular-new.drop-hints.retain-all-codepoint.ttf | Bin 191584 -> 191520 bytes + ...ortaa-Regular-new.gids.retain-all-codepoint.ttf | Bin 222756 -> 222692 bytes + ...egular-new.glyph-names.retain-all-codepoint.ttf | Bin 229748 -> 229684 bytes + ...ep-all-layout-features.retain-all-codepoint.ttf | Bin 223452 -> 223388 bytes + ...ar-new.layout-features.retain-all-codepoint.ttf | Bin 220948 -> 220884 bytes + ...a-Regular-new.name-ids.retain-all-codepoint.ttf | Bin 222496 -> 222432 bytes + ...lar-new.name-languages.retain-all-codepoint.ttf | Bin 222756 -> 222692 bytes + ...egular-new.name-legacy.retain-all-codepoint.ttf | Bin 222756 -> 222692 bytes + ...o-prune-unicode-ranges.retain-all-codepoint.ttf | Bin 222756 -> 222692 bytes + ...lar-new.notdef-outline.retain-all-codepoint.ttf | Bin 223352 -> 223288 bytes + ...egular-new.retain-gids.retain-all-codepoint.ttf | Bin 222804 -> 222740 bytes + ...tu-Regular.glyph-names.retain-all-codepoint.ttf | Bin 281092 -> 280296 bytes + ...Gothic-Regular.default.retain-all-codepoint.ttf | Bin 44584 -> 44544 bytes + ...ic-Regular.layout-test.retain-all-codepoint.ttf | Bin 46584 -> 46544 bytes + ...ic-Regular.retain-gids.retain-all-codepoint.ttf | Bin 44592 -> 44552 bytes + ...traLightItalic.default.retain-all-codepoint.ttf | Bin 134520 -> 134364 bytes + ...ightItalic.glyph-names.retain-all-codepoint.ttf | Bin 145796 -> 145640 bytes + ...tItalic.notdef-outline.retain-all-codepoint.ttf | Bin 134648 -> 134492 bytes + ...ns-BlackItalic.default.retain-all-codepoint.ttf | Bin 120236 -> 120040 bytes + ...lackItalic.glyph-names.retain-all-codepoint.ttf | Bin 132480 -> 132284 bytes + ...kItalic.notdef-outline.retain-all-codepoint.ttf | Bin 120236 -> 120040 bytes + .../Tinos-Italic.default.retain-all-codepoint.ttf | Bin 412764 -> 410932 bytes + ...nos-Italic.glyph-names.retain-all-codepoint.ttf | Bin 437592 -> 435760 bytes + ...-Italic.notdef-outline.retain-all-codepoint.ttf | Bin 412764 -> 410932 bytes + ...nos-Italic.retain-gids.retain-all-codepoint.ttf | Bin 415140 -> 413308 bytes + ...wLatin-Regular.default.retain-all-codepoint.ttf | Bin 131672 -> 130076 bytes + ...in-Regular.layout-test.retain-all-codepoint.ttf | Bin 153648 -> 152052 bytes + ...in-Regular.retain-gids.retain-all-codepoint.ttf | Bin 134776 -> 133180 bytes + ...woMath-Regular.default.retain-all-codepoint.ttf | Bin 1038580 -> 1035756 bytes + ...th-Regular.glyph-names.retain-all-codepoint.ttf | Bin 1091356 -> 1088532 bytes + ...Regular.notdef-outline.retain-all-codepoint.ttf | Bin 1038828 -> 1036004 bytes + ...th-Regular.retain-gids.retain-all-codepoint.ttf | Bin 1053656 -> 1050936 bytes + 35 files changed, 143 insertions(+), 103 deletions(-) + commit 8aed5c21a31eece6a9f3cd775fda8facb6c28b9b Author: Khaled Hosny <khaled@aliftype.com> Date: Fri Nov 26 17:54:18 2021 +0200 diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS index 5e4368ebe37..13a3b51413a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS +++ b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS @@ -1,3 +1,19 @@ +Overview of changes leading to 3.2.0 +Friday, November 26, 2021 +==================================== + +“harfbuzz” library improvements: +- Fixed shaping of Apple Color Emoji flags in right-to-left context. (Behdad Esfahbod) +- Fixed positioning of CFF fonts in HB_TINY profile. (Behdad Esfahbod) +- OpenType 1.9 language tags update. (David Corbett) +- Add HB_NO_VERTICAL config option. +- Add HB_CONFIG_OVERRIDE_H for easier configuration. (Behdad Esfahbod) + +“harfbuzz-subset” library improvements: +- Improved packing of cmap, loca, and Ligature tables. (Garret Rieger) +- Significantly improved overflow-resolution strategy in the repacker. (Garret Rieger) + + Overview of changes leading to 3.1.2 Friday, November 26, 2021 ==================================== diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac b/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac index af72ff9ea39..605cfbe7d4f 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], - [3.1.2], + [3.2.0], [https://github.com/harfbuzz/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/meson.build b/Build/source/libs/harfbuzz/harfbuzz-src/meson.build index 53b721febe4..5dd936ced75 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: '3.1.2', + version: '3.2.0', default_options: [ 'cpp_rtti=false', # Just to support msvc, we are passing -fno-exceptions also anyway 'cpp_std=c++11', @@ -239,12 +239,17 @@ if host_machine.system() == 'windows' and not get_option('gdi').disabled() endif # DirectWrite (Windows) +directwrite_dep = null_dep if host_machine.system() == 'windows' and not get_option('directwrite').disabled() if get_option('directwrite').enabled() and not cpp.has_header('dwrite_1.h') error('DirectWrite was enabled explicitly, but required header is missing.') endif - conf.set('HAVE_DIRECTWRITE', 1) + directwrite_dep = cpp.find_library('dwrite', required: get_option('directwrite')) + + if directwrite_dep.found() + conf.set('HAVE_DIRECTWRITE', 1) + endif endif # CoreText (macOS) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py index d1b5d4342ec..cb612b98290 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py @@ -340,11 +340,15 @@ class OpenTypeRegistryParser (HTMLParser): self.from_bcp_47 = collections.defaultdict (set) # Whether the parser is in a <td> element self._td = False + # Whether the parser is after a <br> element within the current <tr> element + self._br = False # The text of the <td> elements of the current <tr> element. self._current_tr = [] def handle_starttag (self, tag, attrs): - if tag == 'meta': + if tag == 'br': + self._br = True + elif tag == 'meta': for attr, value in attrs: if attr == 'name' and value == 'updated_at': self.header = self.get_starttag_text () @@ -353,6 +357,7 @@ class OpenTypeRegistryParser (HTMLParser): self._td = True self._current_tr.append ('') elif tag == 'tr': + self._br = False self._current_tr = [] def handle_endtag (self, tag): @@ -377,7 +382,7 @@ class OpenTypeRegistryParser (HTMLParser): self.ranks[tag] = rank def handle_data (self, data): - if self._td: + if self._td and not self._br: self._current_tr[-1] += data def handle_charref (self, name): @@ -704,6 +709,8 @@ ot.ranks['MLR'] += 1 bcp_47.names['mhv'] = 'Arakanese' bcp_47.scopes['mhv'] = ' (retired code)' +ot.add_language ('mnw-TH', 'MONT') + ot.add_language ('no', 'NOR') ot.add_language ('oc-provenc', 'PRO') diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh index b77c1f4d449..2f99510925d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh @@ -1038,12 +1038,12 @@ struct Chain goto skip; if (reverse) - c->buffer->reverse (); + _hb_ot_layout_reverse_graphemes (c->buffer); subtable->apply (c); if (reverse) - c->buffer->reverse (); + _hb_ot_layout_reverse_graphemes (c->buffer); (void) c->buffer->message (c->font, "end chainsubtable %d", c->lookup_index); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc index b4f7f723749..be3161a54d0 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc @@ -396,52 +396,6 @@ hb_buffer_t::set_masks (hb_mask_t value, } void -hb_buffer_t::reverse_range (unsigned int start, - unsigned int end) -{ - if (end - start < 2) - return; - - hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end); - - if (have_positions) { - hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end); - } -} - -void -hb_buffer_t::reverse () -{ - if (unlikely (!len)) - return; - - reverse_range (0, len); -} - -void -hb_buffer_t::reverse_clusters () -{ - unsigned int i, start, count, last_cluster; - - if (unlikely (!len)) - return; - - reverse (); - - count = len; - start = 0; - last_cluster = info[0].cluster; - for (i = 1; i < count; i++) { - if (last_cluster != info[i].cluster) { - reverse_range (start, i); - start = i; - last_cluster = info[i].cluster; - } - } - reverse_range (start, i); -} - -void hb_buffer_t::merge_clusters_impl (unsigned int start, unsigned int end) { @@ -543,7 +497,7 @@ void hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end) { unsigned int cluster = UINT_MAX; - cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster); + cluster = _infos_find_min_cluster (info, start, end, cluster); _unsafe_to_break_set_mask (info, start, end, cluster); } void @@ -559,8 +513,9 @@ hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int en assert (idx <= end); unsigned int cluster = UINT_MAX; - cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster); - cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster); + cluster = _infos_find_min_cluster (out_info, start, out_len, cluster); + cluster = _infos_find_min_cluster (info, idx, end, cluster); + _unsafe_to_break_set_mask (out_info, start, out_len, cluster); _unsafe_to_break_set_mask (info, idx, end, cluster); } 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 bde28933e44..0f8140f1b32 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh @@ -201,9 +201,55 @@ struct hb_buffer_t unsigned int cluster); HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info); - HB_INTERNAL void reverse_range (unsigned int start, unsigned int end); - HB_INTERNAL void reverse (); - HB_INTERNAL void reverse_clusters (); + void reverse_range (unsigned start, unsigned end) + { + hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end); + if (have_positions) + hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end); + } + void reverse () { reverse_range (0, len); } + + template <typename FuncType> + void reverse_groups (const FuncType& group, + bool merge_clusters = false) + { + if (unlikely (!len)) + return; + + unsigned start = 0; + unsigned i; + for (i = 1; i < len; i++) + { + if (!group (info[i - 1], info[i])) + { + if (merge_clusters) + this->merge_clusters (start, i); + reverse_range (start, i); + start = i; + } + } + if (merge_clusters) + this->merge_clusters (start, i); + reverse_range (start, i); + + reverse (); + } + + template <typename FuncType> + unsigned group_end (unsigned start, const FuncType& group) const + { + while (++start < len && group (info[start - 1], info[start])) + ; + + return start; + } + + static bool _cluster_group_func (const hb_glyph_info_t& a, + const hb_glyph_info_t& b) + { return a.cluster == b.cluster; } + + void reverse_clusters () { reverse_groups (_cluster_group_func); } + HB_INTERNAL void guess_segment_properties (); HB_INTERNAL void swap_buffers (); @@ -428,10 +474,10 @@ struct hb_buffer_t inf.cluster = cluster; } - unsigned int - _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos, - unsigned int start, unsigned int end, - unsigned int cluster) const + static unsigned + _infos_find_min_cluster (const hb_glyph_info_t *infos, + unsigned start, unsigned end, + unsigned cluster) { for (unsigned int i = start; i < end; i++) cluster = hb_min (cluster, infos[i].cluster); @@ -450,36 +496,24 @@ struct hb_buffer_t } } - void unsafe_to_break_all () { unsafe_to_break_impl (0, len); } - void safe_to_break_all () + void clear_glyph_flags (hb_mask_t mask = 0) { for (unsigned int i = 0; i < len; i++) - info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + info[i].mask = (info[i].mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED); } }; DECLARE_NULL_INSTANCE (hb_buffer_t); -/* Loop over clusters. Duplicated in foreach_syllable(). */ -#define foreach_cluster(buffer, start, end) \ +#define foreach_group(buffer, start, end, group_func) \ for (unsigned int \ _count = buffer->len, \ - start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \ + start = 0, end = _count ? buffer->group_end (0, group_func) : 0; \ start < _count; \ - start = end, end = _next_cluster (buffer, start)) - -static inline unsigned int -_next_cluster (hb_buffer_t *buffer, unsigned int start) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; - - unsigned int cluster = info[start].cluster; - while (++start < count && cluster == info[start].cluster) - ; + start = end, end = buffer->group_end (start, group_func)) - return start; -} +#define foreach_cluster(buffer, start, end) \ + foreach_group (buffer, start, end, hb_buffer_t::_cluster_group_func) #define HB_BUFFER_XALLOCATE_VAR(b, func, var) \ 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 ad800f0f74d..7d00d9088a9 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh @@ -86,8 +86,11 @@ #define HB_NO_LEGACY #endif -#ifdef HAVE_CONFIG_OVERRIDE_H -#include "config-override.h" +#if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H) +#ifndef HB_CONFIG_OVERRIDE_H +#define HB_CONFIG_OVERRIDE_H "config-override.h" +#endif +#include HB_CONFIG_OVERRIDE_H #endif /* Closure of options. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc index 4b6c67c1ee2..a512f3b8b7d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc @@ -1213,7 +1213,7 @@ resize_and_retry: } } - buffer->unsafe_to_break_all (); + buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK); #undef FAIL diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc index db7b53b2591..dea87b8cd0c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc @@ -43,14 +43,6 @@ * Functions for using HarfBuzz with DirectWrite fonts. **/ -/* Declare object creator for dynamic support of DWRITE */ -typedef HRESULT (* WINAPI t_DWriteCreateFactory)( - DWRITE_FACTORY_TYPE factoryType, - REFIID iid, - IUnknown **factory -); - - /* * DirectWrite font stream helpers */ @@ -145,7 +137,6 @@ public: struct hb_directwrite_face_data_t { - HMODULE dwrite_dll; IDWriteFactory *dwriteFactory; IDWriteFontFile *fontFile; DWriteFontFileStream *fontFileStream; @@ -167,33 +158,12 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) return nullptr; \ } HB_STMT_END - data->dwrite_dll = LoadLibrary (TEXT ("DWRITE")); - if (unlikely (!data->dwrite_dll)) - FAIL ("Cannot find DWrite.DLL"); - - t_DWriteCreateFactory p_DWriteCreateFactory; - -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-function-type" -#endif - - p_DWriteCreateFactory = (t_DWriteCreateFactory) - GetProcAddress (data->dwrite_dll, "DWriteCreateFactory"); - -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - - if (unlikely (!p_DWriteCreateFactory)) - FAIL ("Cannot find DWriteCreateFactory()."); - HRESULT hr; // TODO: factory and fontFileLoader should be cached separately IDWriteFactory* dwriteFactory; - hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), - (IUnknown**) &dwriteFactory); + hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), + (IUnknown**) &dwriteFactory); if (unlikely (hr != S_OK)) FAIL ("Failed to run DWriteCreateFactory()."); @@ -257,8 +227,6 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data) delete data->fontFileStream; if (data->faceBlob) hb_blob_destroy (data->faceBlob); - if (data->dwrite_dll) - FreeLibrary (data->dwrite_dll); if (data) delete data; } @@ -794,6 +762,8 @@ retry_getglyphs: if (isRightToLeft) hb_buffer_reverse (buffer); + buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK); + delete [] clusterMap; delete [] glyphIndices; delete [] textProperties; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fallback-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fallback-shape.cc index c5b7c2c2307..f8524ecc8e7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fallback-shape.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-fallback-shape.cc @@ -117,7 +117,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, if (HB_DIRECTION_IS_BACKWARD (direction)) hb_buffer_reverse (buffer); - buffer->safe_to_break_all (); + buffer->clear_glyph_flags (); return true; } 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 97a2c82e683..67691e3ff33 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc @@ -361,6 +361,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data, } } +#ifndef HB_NO_VERTICAL static hb_position_t hb_ft_get_glyph_v_advance (hb_font_t *font, void *font_data, @@ -381,7 +382,9 @@ hb_ft_get_glyph_v_advance (hb_font_t *font, * have a Y growing upward. Hence the extra negation. */ return (-v + (1<<9)) >> 10; } +#endif +#ifndef HB_NO_VERTICAL static hb_bool_t hb_ft_get_glyph_v_origin (hb_font_t *font, void *font_data, @@ -409,6 +412,7 @@ hb_ft_get_glyph_v_origin (hb_font_t *font, return true; } +#endif #ifndef HB_NO_OT_SHAPE_FALLBACK static hb_position_t @@ -569,15 +573,20 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft { hb_font_funcs_t *funcs = hb_font_funcs_create (); - hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr); - //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr); hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr); hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr); hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr); + + hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr); hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr); - hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr); + +#ifndef HB_NO_VERTICAL + //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr); + hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr); hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr); +#endif + #ifndef HB_NO_OT_SHAPE_FALLBACK hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr); #endif 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 209207f1e51..42420ac0b07 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc @@ -439,7 +439,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, if (feats) gr_featureval_destroy (feats); gr_seg_destroy (seg); - buffer->unsafe_to_break_all (); + buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK); return true; } 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 87b8ed880d2..ad2e45e3c59 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-iter.hh @@ -581,6 +581,91 @@ struct } HB_FUNCOBJ (hb_zip); +/* hb_concat() */ + +template <typename A, typename B> +struct hb_concat_iter_t : + hb_iter_t<hb_concat_iter_t<A, B>, typename A::item_t> +{ + hb_concat_iter_t () {} + hb_concat_iter_t (A& a, B& b) : a (a), b (b) {} + hb_concat_iter_t (const A& a, const B& b) : a (a), b (b) {} + + + typedef typename A::item_t __item_t__; + static constexpr bool is_random_access_iterator = + A::is_random_access_iterator && + B::is_random_access_iterator; + static constexpr bool is_sorted_iterator = false; + + __item_t__ __item__ () const + { + if (!a) + return *b; + return *a; + } + + __item_t__ __item_at__ (unsigned i) const + { + unsigned a_len = a.len (); + if (i < a_len) + return a[i]; + return b[i - a_len]; + } + + bool __more__ () const { return bool (a) || bool (b); } + + unsigned __len__ () const { return a.len () + b.len (); } + + void __next__ () + { + if (a) + ++a; + else + ++b; + } + + void __forward__ (unsigned n) + { + if (!n) return; + if (!is_random_access_iterator) { + while (n-- && *this) { + (*this)++; + } + return; + } + + unsigned a_len = a.len (); + if (n > a_len) { + n -= a_len; + a.__forward__ (a_len); + b.__forward__ (n); + } else { + a.__forward__ (n); + } + } + + hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); } + bool operator != (const hb_concat_iter_t& o) const + { + return a != o.a + || b != o.b; + } + + private: + A a; + B b; +}; +struct +{ HB_PARTIALIZE(2); + template <typename A, typename B, + hb_requires (hb_is_iterable (A) && hb_is_iterable (B))> + hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>> + operator () (A&& a, B&& b) const + { return hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); } +} +HB_FUNCOBJ (hb_concat); + /* hb_apply() */ template <typename Appl> 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 c8a2af1e828..d837adc7883 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 @@ -93,120 +93,192 @@ struct CmapSubtableFormat0 struct CmapSubtableFormat4 { + template<typename Iterator, + typename Writer, hb_requires (hb_is_iterator (Iterator))> - HBUINT16* serialize_endcode_array (hb_serialize_context_t *c, - Iterator it) - { - HBUINT16 *endCode = c->start_embed<HBUINT16> (); - hb_codepoint_t prev_endcp = 0xFFFF; + void to_ranges (Iterator it, Writer& range_writer) + { + hb_codepoint_t start_cp = 0, prev_run_start_cp = 0, run_start_cp = 0, end_cp = 0, last_gid = 0; + int run_length = 0 , delta = 0, prev_delta = 0; + + enum { + FIRST_SUB_RANGE, + FOLLOWING_SUB_RANGE, + } mode; + + while (it) { + // Start a new range + start_cp = (*it).first; + prev_run_start_cp = (*it).first; + run_start_cp = (*it).first; + end_cp = (*it).first; + last_gid = (*it).second; + run_length = 1; + prev_delta = 0; + + delta = (*it).second - (*it).first; + mode = FIRST_SUB_RANGE; + it++; + + while (it) { + // Process range + hb_codepoint_t next_cp = (*it).first; + hb_codepoint_t next_gid = (*it).second; + if (next_cp != end_cp + 1) { + // Current range is over, stop processing. + break; + } - for (const auto& _ : +it) - { - if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first) - { - HBUINT16 end_code; - end_code = prev_endcp; - c->copy<HBUINT16> (end_code); - } - prev_endcp = _.first; - } + if (next_gid == last_gid + 1) { + // The current run continues. + end_cp = next_cp; + run_length++; + last_gid = next_gid; + it++; + continue; + } - { - // last endCode - HBUINT16 endcode; - endcode = prev_endcp; - if (unlikely (!c->copy<HBUINT16> (endcode))) return nullptr; - // There must be a final entry with end_code == 0xFFFF. - if (prev_endcp != 0xFFFF) - { - HBUINT16 finalcode; - finalcode = 0xFFFF; - if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr; + // A new run is starting, decide if we want to commit the current run. + int split_cost = (mode == FIRST_SUB_RANGE) ? 8 : 16; + int run_cost = run_length * 2; + if (run_cost >= split_cost) { + commit_current_range(start_cp, + prev_run_start_cp, + run_start_cp, + end_cp, + delta, + prev_delta, + split_cost, + range_writer); + start_cp = next_cp; + } + + // Start the new run + mode = FOLLOWING_SUB_RANGE; + prev_run_start_cp = run_start_cp; + run_start_cp = next_cp; + end_cp = next_cp; + prev_delta = delta; + delta = next_gid - run_start_cp; + run_length = 1; + last_gid = next_gid; + it++; } + + // Finalize range + commit_current_range (start_cp, + prev_run_start_cp, + run_start_cp, + end_cp, + delta, + prev_delta, + 8, + range_writer); } - return endCode; + if (likely (end_cp != 0xFFFF)) { + range_writer (0xFFFF, 0xFFFF, 1); + } } - template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> - HBUINT16* serialize_startcode_array (hb_serialize_context_t *c, - Iterator it) - { - HBUINT16 *startCode = c->start_embed<HBUINT16> (); - hb_codepoint_t prev_cp = 0xFFFF; - - for (const auto& _ : +it) - { - if (prev_cp == 0xFFFF || prev_cp + 1u != _.first) - { - HBUINT16 start_code; - start_code = _.first; - c->copy<HBUINT16> (start_code); + /* + * Writes the current range as either one or two ranges depending on what is most efficient. + */ + template<typename Writer> + void commit_current_range (hb_codepoint_t start, + hb_codepoint_t prev_run_start, + hb_codepoint_t run_start, + hb_codepoint_t end, + int run_delta, + int previous_run_delta, + int split_cost, + Writer& range_writer) { + bool should_split = false; + if (start < run_start && run_start < end) { + int run_cost = (end - run_start + 1) * 2; + if (run_cost >= split_cost) { + should_split = true; } + } - prev_cp = _.first; + // TODO(grieger): handle case where delta is legitimately 0, mark range offset array instead? + if (should_split) { + if (start == prev_run_start) + range_writer (start, run_start - 1, previous_run_delta); + else + range_writer (start, run_start - 1, 0); + range_writer (run_start, end, run_delta); + return; } - // There must be a final entry with end_code == 0xFFFF. - if (it.len () == 0 || prev_cp != 0xFFFF) - { - HBUINT16 finalcode; - finalcode = 0xFFFF; - if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr; + + if (start == run_start) { + // Range is only a run + range_writer (start, end, run_delta); + return; } - return startCode; + // Write only a single non-run range. + range_writer (start, end, 0); } template<typename Iterator, hb_requires (hb_is_iterator (Iterator))> - HBINT16* serialize_idDelta_array (hb_serialize_context_t *c, - Iterator it, - HBUINT16 *endCode, - HBUINT16 *startCode, - unsigned segcount) - { - unsigned i = 0; - hb_codepoint_t last_gid = 0, start_gid = 0, last_cp = 0xFFFF; - bool use_delta = true; - - HBINT16 *idDelta = c->start_embed<HBINT16> (); - if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size) - return nullptr; - - for (const auto& _ : +it) - { - if (_.first == startCode[i]) - { - use_delta = true; - start_gid = _.second; + unsigned serialize_find_segcount (Iterator it) { + struct Counter { + unsigned segcount = 0; + + void operator() (hb_codepoint_t start, + hb_codepoint_t end, + int delta) { + segcount++; } - else if (_.second != last_gid + 1) use_delta = false; + } counter; - if (_.first == endCode[i]) - { - HBINT16 delta; - if (use_delta) delta = (int)start_gid - (int)startCode[i]; - else delta = 0; - c->copy<HBINT16> (delta); + to_ranges (+it, counter); + return counter.segcount; + } - i++; + + template<typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + bool serialize_start_end_delta_arrays (hb_serialize_context_t *c, + Iterator it, + int segcount) + { + struct Writer { + hb_serialize_context_t *serializer_; + HBUINT16* end_code_; + HBUINT16* start_code_; + HBINT16* id_delta_; + int index_; + + Writer(hb_serialize_context_t *serializer) + : serializer_(serializer), + end_code_(nullptr), + start_code_(nullptr), + id_delta_(nullptr), + index_ (0) {} + void operator() (hb_codepoint_t start, + hb_codepoint_t end, + int delta) { + start_code_[index_] = start; + end_code_[index_] = end; + id_delta_[index_] = delta; + index_++; } + } writer(c); - last_gid = _.second; - last_cp = _.first; - } + 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); - if (it.len () == 0 || last_cp != 0xFFFF) - { - HBINT16 delta; - delta = 1; - if (unlikely (!c->copy<HBINT16> (delta))) return nullptr; - } + if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false; - return idDelta; + to_ranges (+it, writer); + return true; } template<typename Iterator, @@ -257,22 +329,14 @@ struct CmapSubtableFormat4 if (unlikely (!c->extend_min (this))) return; this->format = 4; - //serialize endCode[] - HBUINT16 *endCode = serialize_endcode_array (c, format4_iter); - if (unlikely (!endCode)) return; - - unsigned segcount = (c->length () - min_size) / HBUINT16::static_size; - - // 2 bytes of padding. - if (unlikely (!c->allocate_size<HBUINT16> (HBUINT16::static_size))) return; // 2 bytes of padding. - - // serialize startCode[] - HBUINT16 *startCode = serialize_startcode_array (c, format4_iter); - if (unlikely (!startCode)) return; + //serialize endCode[], startCode[], idDelta[] + HBUINT16* endCode = c->start_embed<HBUINT16> (); + unsigned segcount = serialize_find_segcount (format4_iter); + if (unlikely (!serialize_start_end_delta_arrays (c, format4_iter, segcount))) + return; - //serialize idDelta[] - HBINT16 *idDelta = serialize_idDelta_array (c, format4_iter, endCode, startCode, segcount); - if (unlikely (!idDelta)) return; + HBUINT16 *startCode = endCode + segcount + 1; + HBINT16 *idDelta = ((HBINT16*)startCode) + segcount; HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount); if (unlikely (!c->check_success (idRangeOffset))) return; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh index a3c55fa8f40..008422d0891 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh @@ -1025,7 +1025,7 @@ struct ClipList if (unlikely (!c->serializer->extend_min (out))) return_trace (false); if (!c->serializer->check_assign (out->format, format, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); - const hb_set_t& glyphset = *c->plan->_glyphset; + const hb_set_t& glyphset = *c->plan->_glyphset_colred; const hb_map_t &glyph_map = *c->plan->glyph_map; hb_map_t new_gid_offset_map; @@ -1193,7 +1193,7 @@ struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord> TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - const hb_set_t* glyphset = c->plan->_glyphset; + const hb_set_t* glyphset = c->plan->_glyphset_colred; for (const auto& _ : as_array ()) { @@ -1411,10 +1411,9 @@ struct COLR const BaseGlyphRecord* get_base_glyph_record (hb_codepoint_t gid) const { - if ((unsigned int) gid == 0) // Ignore notdef. - return nullptr; const BaseGlyphRecord* record = &(this+baseGlyphsZ).bsearch (numBaseGlyphs, (unsigned int) gid); - if ((record && (hb_codepoint_t) record->glyphId != gid)) + if (record == &Null (BaseGlyphRecord) || + (record && (hb_codepoint_t) record->glyphId != gid)) record = nullptr; return record; } @@ -1432,9 +1431,16 @@ struct COLR TRACE_SUBSET (this); const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map; + const hb_set_t& glyphset = *c->plan->_glyphset_colred; auto base_it = + hb_range (c->plan->num_output_glyphs ()) + | hb_filter ([&](hb_codepoint_t new_gid) + { + hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid); + if (glyphset.has (old_gid)) return true; + return false; + }) | hb_map_retains_sorting ([&](hb_codepoint_t new_gid) { hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid); @@ -1442,7 +1448,6 @@ struct COLR const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid); if (unlikely (!old_record)) return hb_pair_t<bool, BaseGlyphRecord> (false, Null (BaseGlyphRecord)); - BaseGlyphRecord new_record = {}; new_record.glyphId = new_gid; new_record.numLayers = old_record->numLayers; @@ -1455,6 +1460,7 @@ struct COLR auto layer_it = + hb_range (c->plan->num_output_glyphs ()) | hb_map (reverse_glyph_map) + | hb_filter (glyphset) | hb_map_retains_sorting ([&](hb_codepoint_t old_gid) { const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh index ffbbb1bc539..eff09838af1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh @@ -67,8 +67,11 @@ HB_OT_ACCELERATOR (OT, meta) #endif /* Vertical layout. */ +#ifndef HB_NO_VERTICAL HB_OT_TABLE (OT, vhea) HB_OT_ACCELERATOR (OT, vmtx) +HB_OT_TABLE (OT, VORG) +#endif /* TrueType outlines. */ HB_OT_ACCELERATOR (OT, glyf) @@ -77,7 +80,6 @@ HB_OT_ACCELERATOR (OT, glyf) #ifndef HB_NO_CFF HB_OT_ACCELERATOR (OT, cff1) HB_OT_ACCELERATOR (OT, cff2) -HB_OT_TABLE (OT, VORG) #endif /* OpenType variations. */ 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 5c044c1c4fd..9f0359a773c 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 @@ -118,6 +118,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, } } +#ifndef HB_NO_VERTICAL static void hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, unsigned count, @@ -137,7 +138,9 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); } } +#endif +#ifndef HB_NO_VERTICAL static hb_bool_t hb_ot_get_glyph_v_origin (hb_font_t *font, void *font_data, @@ -150,14 +153,12 @@ hb_ot_get_glyph_v_origin (hb_font_t *font, *x = font->get_glyph_h_advance (glyph) / 2; -#ifndef HB_NO_OT_FONT_CFF const OT::VORG &VORG = *ot_face->VORG; if (VORG.has_data ()) { *y = font->em_scale_y (VORG.get_y_origin (glyph)); return true; } -#endif hb_glyph_extents_t extents = {0}; if (ot_face->glyf->get_extents (font, glyph, &extents)) @@ -174,6 +175,7 @@ hb_ot_get_glyph_v_origin (hb_font_t *font, return true; } +#endif static hb_bool_t hb_ot_get_glyph_extents (hb_font_t *font, @@ -242,6 +244,7 @@ hb_ot_get_font_h_extents (hb_font_t *font, _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap); } +#ifndef HB_NO_VERTICAL static hb_bool_t hb_ot_get_font_v_extents (hb_font_t *font, void *font_data HB_UNUSED, @@ -252,6 +255,7 @@ hb_ot_get_font_v_extents (hb_font_t *font, _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) && _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap); } +#endif static inline void free_static_ot_funcs (); @@ -261,17 +265,23 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot { hb_font_funcs_t *funcs = hb_font_funcs_create (); - hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr); - hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr); hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr); hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr); hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr); + + hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr); hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr); - hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr); + +#ifndef HB_NO_VERTICAL + hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr); + hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr); hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr); +#endif + hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); + #ifndef HB_NO_OT_FONT_GLYPH_NAMES hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr); hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh index 6b419ea1ac0..6aa34295c77 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh @@ -93,22 +93,16 @@ struct glyf 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) + _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca) { - unsigned max_offset = - + padded_offsets - | hb_reduce (hb_add, 0) - ; unsigned num_offsets = padded_offsets.len () + 1; - bool use_short_loca = max_offset < 0x1FFFF; unsigned entry_size = use_short_loca ? 2 : 4; char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets); if (unlikely (!loca_prime_data)) return false; - DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d " - "max_offset %d size %d", - entry_size, num_offsets, max_offset, entry_size * num_offsets); + DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d", + entry_size, num_offsets, entry_size * num_offsets); if (use_short_loca) _write_loca (padded_offsets, 1, hb_array ((HBUINT16 *) loca_prime_data, num_offsets)); @@ -151,11 +145,12 @@ struct glyf template <typename Iterator> bool serialize (hb_serialize_context_t *c, Iterator it, + bool use_short_loca, const hb_subset_plan_t *plan) { TRACE_SERIALIZE (this); unsigned init_len = c->length (); - for (const auto &_ : it) _.serialize (c, plan); + for (const auto &_ : it) _.serialize (c, use_short_loca, plan); /* As a special case when all glyph in the font are empty, add a zero byte * to the table, so that OTS doesn’t reject it, and to make the table work @@ -183,16 +178,28 @@ struct glyf hb_vector_t<SubsetGlyph> glyphs; _populate_subset_glyphs (c->plan, &glyphs); - glyf_prime->serialize (c->serializer, hb_iter (glyphs), c->plan); - auto padded_offsets = + hb_iter (glyphs) | hb_map (&SubsetGlyph::padded_size) ; + unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0); + bool use_short_loca = max_offset < 0x1FFFF; + + + glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan); + if (!use_short_loca) { + padded_offsets = + + hb_iter (glyphs) + | hb_map (&SubsetGlyph::length) + ; + } + + if (unlikely (c->serializer->in_error ())) return_trace (false); return_trace (c->serializer->check_success (_add_loca_and_head (c->plan, - padded_offsets))); + padded_offsets, + use_short_loca))); } template <typename SubsetGlyph> @@ -792,10 +799,23 @@ struct glyf hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT); { for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init (); - int h_delta = (int) header->xMin - glyf_accelerator.hmtx->get_side_bearing (gid); - int v_orig = (int) header->yMax + glyf_accelerator.vmtx->get_side_bearing (gid); + int h_delta = (int) header->xMin - + glyf_accelerator.hmtx->get_side_bearing (gid); + int v_orig = (int) header->yMax + +#ifndef HB_NO_VERTICAL + glyf_accelerator.vmtx->get_side_bearing (gid) +#else + 0 +#endif + ; unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid); - unsigned v_adv = glyf_accelerator.vmtx->get_advance (gid); + unsigned v_adv = +#ifndef HB_NO_VERTICAL + glyf_accelerator.vmtx->get_advance (gid) +#else + - font->face->get_upem () +#endif + ; phantoms[PHANTOM_LEFT].x = h_delta; phantoms[PHANTOM_RIGHT].x = h_adv + h_delta; phantoms[PHANTOM_TOP].y = v_orig; @@ -910,7 +930,9 @@ struct glyf gvar = nullptr; #endif hmtx = nullptr; +#ifndef HB_NO_VERTICAL vmtx = nullptr; +#endif face = face_; const OT::head &head = *face->table.head; if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0) @@ -924,7 +946,9 @@ struct glyf gvar = face->table.gvar; #endif hmtx = face->table.hmtx; +#ifndef HB_NO_VERTICAL vmtx = face->table.vmtx; +#endif num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1; num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ()); @@ -1037,7 +1061,11 @@ struct glyf success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms)); if (unlikely (!success)) - return is_vertical ? vmtx->get_advance (gid) : hmtx->get_advance (gid); + return +#ifndef HB_NO_VERTICAL + is_vertical ? vmtx->get_advance (gid) : +#endif + hmtx->get_advance (gid); float result = is_vertical ? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y @@ -1053,7 +1081,11 @@ struct glyf contour_point_t phantoms[PHANTOM_COUNT]; if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms)))) - return is_vertical ? vmtx->get_side_bearing (gid) : hmtx->get_side_bearing (gid); + return +#ifndef HB_NO_VERTICAL + is_vertical ? vmtx->get_side_bearing (gid) : +#endif + hmtx->get_side_bearing (gid); return is_vertical ? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing @@ -1250,7 +1282,9 @@ struct glyf const gvar_accelerator_t *gvar; #endif const hmtx_accelerator_t *hmtx; +#ifndef HB_NO_VERTICAL const vmtx_accelerator_t *vmtx; +#endif private: bool short_offset; @@ -1269,13 +1303,14 @@ struct glyf hb_bytes_t dest_end; /* region of source_glyph to copy second */ bool serialize (hb_serialize_context_t *c, + bool use_short_loca, const hb_subset_plan_t *plan) const { TRACE_SERIALIZE (this); hb_bytes_t dest_glyph = dest_start.copy (c); dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length); - unsigned int pad_length = padding (); + unsigned int pad_length = use_short_loca ? padding () : 0; DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length); HBUINT8 pad; 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 40383299382..7d2d2d3eb8b 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 @@ -165,7 +165,14 @@ struct hmtxvmtx { default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face); - num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics; + num_advances = T::is_horizontal ? + face->table.hhea->numberOfLongMetrics : +#ifndef HB_NO_VERTICAL + face->table.vhea->numberOfLongMetrics +#else + 0 +#endif + ; table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag); 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 882c3ae96f4..4fb1893435f 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 @@ -68,8 +68,8 @@ #define HB_MAX_FEATURE_INDICES 1500 #endif -#ifndef HB_MAX_LOOKUP_INDICES -#define HB_MAX_LOOKUP_INDICES 20000 +#ifndef HB_MAX_LOOKUP_VISIT_COUNT +#define HB_MAX_LOOKUP_VISIT_COUNT 35000 #endif @@ -173,7 +173,7 @@ struct hb_subset_layout_context_t : bool visitLookupIndex() { lookup_index_count++; - return lookup_index_count < HB_MAX_LOOKUP_INDICES; + return lookup_index_count < HB_MAX_LOOKUP_VISIT_COUNT; } hb_subset_context_t *subset_context; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh index a8fb5c7acb9..6db3e08940f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh @@ -118,7 +118,13 @@ struct ValueFormat : HBUINT16 if (!format) return ret; hb_font_t *font = c->font; - bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction); + bool horizontal = +#ifndef HB_NO_VERTICAL + HB_DIRECTION_IS_HORIZONTAL (c->direction) +#else + true +#endif + ; if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret)); if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret)); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh index 710c5fbbb92..b7ce30135e9 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh @@ -566,7 +566,7 @@ struct AlternateSet { /* Maybe we can do better than unsafe-to-break all; but since we are * changing random state, it would be hard to track that. Good 'nough. */ - c->buffer->unsafe_to_break_all (); + c->buffer->unsafe_to_break (0, c->buffer->len); alt_index = c->random_number () % count + 1; } 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 6bc06b50eda..191d3bebc59 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 @@ -81,12 +81,15 @@ struct hb_closure_context_t : nesting_level_left++; } + void reset_lookup_visit_count () + { lookup_count = 0; } + bool lookup_limit_exceeded () - { return lookup_count > HB_MAX_LOOKUP_INDICES; } + { return lookup_count > HB_MAX_LOOKUP_VISIT_COUNT; } bool should_visit_lookup (unsigned int lookup_index) { - if (lookup_count++ > HB_MAX_LOOKUP_INDICES) + if (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT) return false; if (is_lookup_done (lookup_index)) @@ -211,7 +214,11 @@ struct hb_closure_lookups_context_t : return; /* Return if new lookup was recursed to before. */ - if (is_lookup_visited (lookup_index)) + if (lookup_limit_exceeded () + || visited_lookups->in_error () + || visited_lookups->has (lookup_index)) + // Don't increment lookup count here, that will be done in the call to closure_lookups() + // made by recurse_func. return; nesting_level_left--; @@ -226,12 +233,20 @@ struct hb_closure_lookups_context_t : { inactive_lookups->add (lookup_index); } bool lookup_limit_exceeded () - { return lookup_count > HB_MAX_LOOKUP_INDICES; } + { + bool ret = lookup_count > HB_MAX_LOOKUP_VISIT_COUNT; + if (ret) + DEBUG_MSG (SUBSET, nullptr, "lookup visit count limit exceeded in lookup closure!"); + return ret; } bool is_lookup_visited (unsigned lookup_index) { - if (unlikely (lookup_count++ > HB_MAX_LOOKUP_INDICES)) + if (unlikely (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT)) + { + DEBUG_MSG (SUBSET, nullptr, "total visited lookup count %u exceeds max limit, lookup %u is dropped.", + lookup_count, lookup_index); return true; + } if (unlikely (visited_lookups->in_error ())) return true; @@ -1303,8 +1318,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, } hb_set_add (covered_seq_indicies, seqIndex); - if (pos_glyphs) - c->push_cur_active_glyphs (pos_glyphs); + c->push_cur_active_glyphs (pos_glyphs ? pos_glyphs : c->glyphs); unsigned endIndex = inputCount; if (context_format == ContextFormat::CoverageBasedContext) @@ -1312,10 +1326,9 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c, c->recurse (lookupRecord[i].lookupListIndex, covered_seq_indicies, seqIndex, endIndex); - if (pos_glyphs) { - c->pop_cur_done_glyphs (); + c->pop_cur_done_glyphs (); + if (pos_glyphs) hb_set_destroy (pos_glyphs); - } } hb_set_destroy (covered_seq_indicies); 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 4e1d23eba5c..60733648c19 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 @@ -1530,6 +1530,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, unsigned int glyphs_length; do { + c.reset_lookup_visit_count (); glyphs_length = glyphs->get_population (); if (lookups) { 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 b15d0538359..2c825e0c81e 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 @@ -350,24 +350,20 @@ _hb_glyph_info_is_continuation (const hb_glyph_info_t *info) { return info->unicode_props() & UPROPS_MASK_CONTINUATION; } -/* Loop over grapheme. Based on foreach_cluster(). */ -#define foreach_grapheme(buffer, start, end) \ - for (unsigned int \ - _count = buffer->len, \ - start = 0, end = _count ? _hb_next_grapheme (buffer, 0) : 0; \ - start < _count; \ - start = end, end = _hb_next_grapheme (buffer, start)) -static inline unsigned int -_hb_next_grapheme (hb_buffer_t *buffer, unsigned int start) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; +static inline bool +_hb_grapheme_group_func (const hb_glyph_info_t& a HB_UNUSED, + const hb_glyph_info_t& b) +{ return _hb_glyph_info_is_continuation (&b); } - while (++start < count && _hb_glyph_info_is_continuation (&info[start])) - ; +#define foreach_grapheme(buffer, start, end) \ + foreach_group (buffer, start, end, _hb_grapheme_group_func) - return start; +static inline void +_hb_ot_layout_reverse_graphemes (hb_buffer_t *buffer) +{ + buffer->reverse_groups (_hb_grapheme_group_func, + buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); } static inline bool 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 c2e365dbd6d..8d0b4317c35 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 @@ -511,7 +511,8 @@ struct MathGlyphInfo | hb_map_retains_sorting (glyph_map) ; - out->extendedShapeCoverage.serialize_serialize (c->serializer, it); + if (it) out->extendedShapeCoverage.serialize_serialize (c->serializer, it); + else out->extendedShapeCoverage = 0; out->mathKernInfo.serialize_subset (c, mathKernInfo, this); return_trace (true); @@ -884,8 +885,11 @@ struct MathVariants if (!o) return_trace (false); o->serialize_subset (c, glyphConstruction[i], this); } - - out->vertGlyphCoverage.serialize_serialize (c->serializer, new_vert_coverage.iter ()); + + 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-metrics.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-metrics.cc index 72aeff82d60..dbd4a1ffbe1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-metrics.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-metrics.cc @@ -77,6 +77,7 @@ _hb_ot_metrics_get_position_common (hb_font_t *font, (face->table.TABLE->has_data () && \ (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \ face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true)) + case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER: return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) || GET_METRIC_Y (hhea, ascender); @@ -86,9 +87,13 @@ _hb_ot_metrics_get_position_common (hb_font_t *font, case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP: return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoLineGap)) || GET_METRIC_Y (hhea, lineGap); + +#ifndef HB_NO_VERTICAL case HB_OT_METRICS_TAG_VERTICAL_ASCENDER: return GET_METRIC_X (vhea, ascender); case HB_OT_METRICS_TAG_VERTICAL_DESCENDER: return GET_METRIC_X (vhea, descender); case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP: return GET_METRIC_X (vhea, lineGap); +#endif + #undef GET_METRIC_Y #undef GET_METRIC_X #undef GET_VAR @@ -158,9 +163,11 @@ hb_ot_metrics_get_position (hb_font_t *font, case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: return GET_METRIC_Y (hhea, caretSlopeRise); case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: return GET_METRIC_X (hhea, caretSlopeRun); case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET: return GET_METRIC_X (hhea, caretOffset); +#ifndef HB_NO_VERTICAL case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE: return GET_METRIC_X (vhea, caretSlopeRise); case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN: return GET_METRIC_Y (vhea, caretSlopeRun); case HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET: return GET_METRIC_Y (vhea, caretOffset); +#endif case HB_OT_METRICS_TAG_X_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sxHeight); case HB_OT_METRICS_TAG_CAP_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sCapHeight); case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE: return GET_METRIC_X (OS2, ySubscriptXSize); 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 4e8a4bc3d17..4dde3520d8b 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 @@ -628,20 +628,7 @@ hb_ensure_native_direction (hb_buffer_t *buffer) (HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB)) { - - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) - foreach_grapheme (buffer, start, end) - { - buffer->merge_clusters (start, end); - buffer->reverse_range (start, end); - } - else - foreach_grapheme (buffer, start, end) - /* form_clusters() merged clusters already, we don't merge. */ - buffer->reverse_range (start, end); - - buffer->reverse (); - + _hb_ot_layout_reverse_graphemes (buffer); buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction); } } @@ -651,6 +638,7 @@ hb_ensure_native_direction (hb_buffer_t *buffer) * Substitute */ +#ifndef HB_NO_VERTICAL static hb_codepoint_t hb_vert_char_for (hb_codepoint_t u) { @@ -701,6 +689,7 @@ hb_vert_char_for (hb_codepoint_t u) return u; } +#endif static inline void hb_ot_rotate_chars (const hb_ot_shape_context_t *c) @@ -723,6 +712,7 @@ hb_ot_rotate_chars (const hb_ot_shape_context_t *c) } } +#ifndef HB_NO_VERTICAL if (HB_DIRECTION_IS_VERTICAL (c->target_direction) && !c->plan->has_vert) { for (unsigned int i = 0; i < count; i++) { @@ -731,6 +721,7 @@ hb_ot_rotate_chars (const hb_ot_shape_context_t *c) info[i].codepoint = codepoint; } } +#endif } static inline void diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh index fc9bffc23f5..2c6316df4f8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh @@ -6,7 +6,7 @@ * * on files with these headers: * - * <meta name="updated_at" content="2021-09-02 09:40 PM" /> + * <meta name="updated_at" content="2021-12-09 12:01 AM" /> * File-Date: 2021-08-06 */ @@ -933,6 +933,7 @@ static const LangTag ot_languages[] = { {"mnp", HB_TAG('Z','H','S',' ')}, /* Min Bei Chinese -> Chinese, Simplified */ {"mns", HB_TAG('M','A','N',' ')}, /* Mansi */ {"mnw", HB_TAG('M','O','N',' ')}, /* Mon */ + {"mnw", HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */ {"mnx", HB_TAG_NONE }, /* Manikion != Manx */ {"mo", HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */ {"mod", HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */ @@ -1422,6 +1423,7 @@ static const LangTag ot_languages[] = { {"tia", HB_TAG('B','B','R',' ')}, /* Tidikelt Tamazight -> Berber */ {"tig", HB_TAG('T','G','R',' ')}, /* Tigre */ /*{"tiv", HB_TAG('T','I','V',' ')},*/ /* Tiv */ +/*{"tjl", HB_TAG('T','J','L',' ')},*/ /* Tai Laing */ {"tjo", HB_TAG('B','B','R',' ')}, /* Temacine Tamazight -> Berber */ {"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */ {"tkg", HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */ @@ -2521,6 +2523,14 @@ hb_ot_tags_from_complex_language (const char *lang_str, *count = 1; return true; } + if (0 == strncmp (&lang_str[1], "nw-", 3) + && subtag_matches (lang_str, limit, "-th")) + { + /* Mon; Thailand */ + tags[0] = HB_TAG('M','O','N','T'); /* Thailand Mon */ + *count = 1; + return true; + } break; case 'n': if (lang_matches (&lang_str[1], "an-hant-hk")) @@ -2884,6 +2894,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("man", -1); /* Mandingo [macrolanguage] */ case HB_TAG('M','O','L',' '): /* Moldavian */ return hb_language_from_string ("ro-MD", -1); /* Romanian; Moldova */ + case HB_TAG('M','O','N','T'): /* Thailand Mon */ + return hb_language_from_string ("mnw-TH", -1); /* Mon; Thailand */ case HB_TAG('M','Y','N',' '): /* Mayan */ return hb_language_from_string ("myn", -1); /* Mayan [family] */ case HB_TAG('N','A','H',' '): /* Nahuatl */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh index 26faa56ea85..5c46b4cccca 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh @@ -100,12 +100,18 @@ struct graph_t bool is_leaf () const { - return !obj.links.length; + return !obj.real_links.length && !obj.virtual_links.length; } - void raise_priority () + bool raise_priority () { + if (has_max_priority ()) return false; priority++; + return true; + } + + bool has_max_priority () const { + return priority >= 3; } int64_t modified_distance (unsigned order) const @@ -115,15 +121,22 @@ struct graph_t // it's parent where possible. int64_t modified_distance = - hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFF); - return (modified_distance << 22) | (0x003FFFFF & order); + hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF); + if (has_max_priority ()) { + modified_distance = 0; + } + return (modified_distance << 18) | (0x003FFFF & order); } int64_t distance_modifier () const { if (!priority) return 0; int64_t table_size = obj.tail - obj.head; - return -(table_size - table_size / (1 << hb_min(priority, 16u))); + + if (priority == 1) + return -table_size / 2; + + return -table_size; } }; @@ -164,9 +177,10 @@ struct graph_t if (check_success (!vertices_.in_error ())) v->obj = *objects[i]; if (!removed_nil) continue; - for (unsigned i = 0; i < v->obj.links.length; i++) - // Fix indices to account for removed nil object. - v->obj.links[i].objidx--; + // Fix indices to account for removed nil object. + for (auto& l : v->obj.all_links_writer ()) { + l.objidx--; + } } } @@ -203,26 +217,46 @@ struct graph_t /* * serialize graph into the provided serialization buffer. */ - void serialize (hb_serialize_context_t* c) const + hb_blob_t* serialize () const { - c->start_serialize<void> (); + hb_vector_t<char> buffer; + size_t size = serialized_length (); + if (!buffer.alloc (size)) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer."); + return nullptr; + } + hb_serialize_context_t c((void *) buffer, size); + + c.start_serialize<void> (); for (unsigned i = 0; i < vertices_.length; i++) { - c->push (); + c.push (); size_t size = vertices_[i].obj.tail - vertices_[i].obj.head; - char* start = c->allocate_size <char> (size); - if (!start) return; + char* start = c.allocate_size <char> (size); + if (!start) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space."); + return nullptr; + } memcpy (start, vertices_[i].obj.head, size); - for (const auto& link : vertices_[i].obj.links) - serialize_link (link, start, c); + // Only real links needs to be serialized. + for (const auto& link : vertices_[i].obj.real_links) + serialize_link (link, start, &c); // All duplications are already encoded in the graph, so don't // enable sharing during packing. - c->pop_pack (false); + c.pop_pack (false); } - c->end_serialize (); + c.end_serialize (); + + if (c.in_error ()) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d", + c.errors); + return nullptr; + } + + return c.copy_blob (); } /* @@ -260,7 +294,7 @@ struct graph_t sorted_graph[new_id] = next; id_map[next_id] = new_id--; - for (const auto& link : next.obj.links) { + for (const auto& link : next.obj.all_links ()) { removed_edges[link.objidx]++; if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx])) queue.push (link.objidx); @@ -314,7 +348,7 @@ struct graph_t sorted_graph[new_id] = next; id_map[next_id] = new_id--; - for (const auto& link : next.obj.links) { + for (const auto& link : next.obj.all_links ()) { removed_edges[link.objidx]++; if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx])) // Add the order that the links were encountered to the priority. @@ -348,7 +382,8 @@ struct graph_t hb_set_t roots; for (unsigned i = 0; i <= root_index; i++) { - for (auto& l : vertices_[i].obj.links) + // Only real links can form 32 bit spaces + for (auto& l : vertices_[i].obj.real_links) { if (l.width == 4 && !l.is_signed) { @@ -466,7 +501,7 @@ struct graph_t void find_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& subgraph) { - for (const auto& link : vertices_[node_idx].obj.links) + for (const auto& link : vertices_[node_idx].obj.all_links ()) { if (subgraph.has (link.objidx)) { @@ -482,7 +517,7 @@ struct graph_t { if (subgraph.has (node_idx)) return; subgraph.add (node_idx); - for (const auto& link : vertices_[node_idx].obj.links) + for (const auto& link : vertices_[node_idx].obj.all_links ()) find_subgraph (link.objidx, subgraph); } @@ -497,7 +532,7 @@ struct graph_t return; index_map.set (node_idx, duplicate (node_idx)); - for (const auto& l : object (node_idx).links) { + for (const auto& l : object (node_idx).all_links ()) { duplicate_subgraph (l.objidx, index_map); } } @@ -523,13 +558,19 @@ struct graph_t clone->parents.reset (); unsigned clone_idx = vertices_.length - 2; - for (const auto& l : child.obj.links) + for (const auto& l : child.obj.real_links) { - clone->obj.links.push (l); + clone->obj.real_links.push (l); + vertices_[l.objidx].parents.push (clone_idx); + } + for (const auto& l : child.obj.virtual_links) + { + clone->obj.virtual_links.push (l); vertices_[l.objidx].parents.push (clone_idx); } - check_success (!clone->obj.links.in_error ()); + check_success (!clone->obj.real_links.in_error ()); + check_success (!clone->obj.virtual_links.in_error ()); // The last object is the root of the graph, so swap back the root to the end. // The root's obj idx does change, however since it's root nothing else refers to it. @@ -539,7 +580,7 @@ struct graph_t vertices_[vertices_.length - 1] = root; // Since the root moved, update the parents arrays of all children on the root. - for (const auto& l : root.obj.links) + for (const auto& l : root.obj.all_links ()) vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ()); return clone_idx; @@ -555,7 +596,7 @@ struct graph_t update_parents (); unsigned links_to_child = 0; - for (const auto& l : vertices_[parent_idx].obj.links) + for (const auto& l : vertices_[parent_idx].obj.all_links ()) { if (l.objidx == child_idx) links_to_child++; } @@ -578,9 +619,8 @@ struct graph_t if (parent_idx == clone_idx) parent_idx++; auto& parent = vertices_[parent_idx]; - for (unsigned i = 0; i < parent.obj.links.length; i++) + for (auto& l : parent.obj.all_links_writer ()) { - auto& l = parent.obj.links[i]; if (l.objidx != child_idx) continue; @@ -593,7 +633,7 @@ struct graph_t /* * Raises the sorting priority of all children. */ - void raise_childrens_priority (unsigned parent_idx) + bool raise_childrens_priority (unsigned parent_idx) { DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d", parent_idx); @@ -601,8 +641,10 @@ struct graph_t // to invalidate positions. It does not change graph structure so no need // to update distances or edge counts. auto& parent = vertices_[parent_idx].obj; - for (unsigned i = 0; i < parent.links.length; i++) - vertices_[parent.links[i].objidx].raise_priority (); + bool made_change = false; + for (auto& l : parent.all_links_writer ()) + made_change |= vertices_[l.objidx].raise_priority (); + return made_change; } /* @@ -615,7 +657,8 @@ struct graph_t for (int parent_idx = vertices_.length - 1; parent_idx >= 0; parent_idx--) { - for (const auto& link : vertices_[parent_idx].obj.links) + // Don't need to check virtual links for overflow + for (const auto& link : vertices_[parent_idx].obj.real_links) { int64_t offset = compute_offset (parent_idx, link); if (is_valid_offset (offset, link)) @@ -655,8 +698,10 @@ struct graph_t if (!DEBUG_ENABLED(SUBSET_REPACK)) return; update_parents (); + int limit = 10; for (const auto& o : overflows) { + if (!limit--) break; const auto& parent = vertices_[o.parent]; const auto& child = vertices_[o.child]; DEBUG_MSG (SUBSET_REPACK, nullptr, @@ -665,13 +710,16 @@ struct graph_t "%4d (%4d in, %4d out, space %2d)", o.parent, parent.incoming_edges (), - parent.obj.links.length, + parent.obj.real_links.length + parent.obj.virtual_links.length, space_for (o.parent), o.child, child.incoming_edges (), - child.obj.links.length, + child.obj.real_links.length + child.obj.virtual_links.length, space_for (o.child)); } + if (overflows.length > 10) { + DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10); + } } unsigned num_roots_for_space (unsigned space) const @@ -684,12 +732,19 @@ struct graph_t return num_roots_for_space_.length; } - void move_to_new_space (unsigned index) + void move_to_new_space (const hb_set_t& indices) { - auto& node = vertices_[index]; - num_roots_for_space_.push (1); - num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1; - node.space = num_roots_for_space_.length - 1; + num_roots_for_space_.push (0); + unsigned new_space = num_roots_for_space_.length - 1; + + for (unsigned index : indices) { + auto& node = vertices_[index]; + num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1; + num_roots_for_space_[new_space] = num_roots_for_space_[new_space] + 1; + node.space = new_space; + distance_invalid = true; + positions_invalid = true; + } } unsigned space_for (unsigned index, unsigned* root = nullptr) const @@ -716,6 +771,15 @@ struct graph_t private: + size_t serialized_length () const { + size_t total_size = 0; + for (unsigned i = 0; i < vertices_.length; i++) { + size_t size = vertices_[i].obj.tail - vertices_[i].obj.head; + total_size += size; + } + return total_size; + } + /* * Returns the numbers of incoming edges that are 32bits wide. */ @@ -728,7 +792,8 @@ struct graph_t if (visited.has (p)) continue; visited.add (p); - for (const auto& l : vertices_[p].obj.links) + // Only real links can be wide + for (const auto& l : vertices_[p].obj.real_links) { if (l.objidx == node_idx && l.width == 4 && !l.is_signed) { @@ -755,7 +820,7 @@ struct graph_t for (unsigned p = 0; p < vertices_.length; p++) { - for (auto& l : vertices_[p].obj.links) + for (auto& l : vertices_[p].obj.all_links ()) { vertices_[l.objidx].parents.push (p); } @@ -823,7 +888,7 @@ struct graph_t int64_t next_distance = vertices_[next_idx].distance; visited[next_idx] = true; - for (const auto& link : next.obj.links) + for (const auto& link : next.obj.all_links ()) { if (visited[link.objidx]) continue; @@ -922,9 +987,8 @@ struct graph_t if (!id_map) return; for (unsigned i : subgraph) { - for (unsigned j = 0; j < vertices_[i].obj.links.length; j++) + for (auto& link : vertices_[i].obj.all_links_writer ()) { - auto& link = vertices_[i].obj.links[j]; if (!id_map.has (link.objidx)) continue; if (only_wide && !(link.width == 4 && !link.is_signed)) continue; @@ -942,9 +1006,8 @@ struct graph_t for (unsigned i = 0; i < sorted_graph->length; i++) { (*sorted_graph)[i].remap_parents (id_map); - for (unsigned j = 0; j < (*sorted_graph)[i].obj.links.length; j++) + for (auto& link : (*sorted_graph)[i].obj.all_links_writer ()) { - auto& link = (*sorted_graph)[i].obj.links[j]; link.objidx = id_map[link.objidx]; } } @@ -1023,7 +1086,7 @@ struct graph_t const auto& v = vertices_[start_idx]; // Graph is treated as undirected so search children and parents of start_idx - for (const auto& l : v.obj.links) + for (const auto& l : v.obj.all_links ()) find_connected_nodes (l.objidx, targets, visited, connected); for (unsigned p : v.parents) @@ -1044,27 +1107,50 @@ struct graph_t static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows, graph_t& sorted_graph) { + unsigned space = 0; + hb_set_t roots_to_isolate; + for (int i = overflows.length - 1; i >= 0; i--) { const graph_t::overflow_record_t& r = overflows[i]; - unsigned root = 0; - unsigned space = sorted_graph.space_for (r.parent, &root); - if (!space) continue; - if (sorted_graph.num_roots_for_space (space) <= 1) continue; - DEBUG_MSG (SUBSET_REPACK, nullptr, "Overflow in space %d moving subgraph %d to space %d.", - space, - root, - sorted_graph.next_space ()); + unsigned root; + unsigned overflow_space = sorted_graph.space_for (r.parent, &root); + if (!overflow_space) continue; + if (sorted_graph.num_roots_for_space (overflow_space) <= 1) continue; - hb_set_t roots; - roots.add (root); - sorted_graph.isolate_subgraph (roots); - for (unsigned new_root : roots) - sorted_graph.move_to_new_space (new_root); - return true; + if (!space) { + space = overflow_space; + } + + if (space == overflow_space) + roots_to_isolate.add(root); } - return false; + + if (!roots_to_isolate) return false; + + unsigned maximum_to_move = hb_max ((sorted_graph.num_roots_for_space (space) / 2u), 1u); + if (roots_to_isolate.get_population () > maximum_to_move) { + // Only move at most half of the roots in a space at a time. + unsigned extra = roots_to_isolate.get_population () - maximum_to_move; + while (extra--) { + unsigned root = HB_SET_VALUE_INVALID; + roots_to_isolate.previous (&root); + roots_to_isolate.del (root); + } + } + + DEBUG_MSG (SUBSET_REPACK, nullptr, + "Overflow in space %d (%d roots). Moving %d roots to space %d.", + space, + sorted_graph.num_roots_for_space (space), + roots_to_isolate.get_population (), + sorted_graph.next_space ()); + + sorted_graph.isolate_subgraph (roots_to_isolate); + sorted_graph.move_to_new_space (roots_to_isolate); + + return true; } static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows, @@ -1093,16 +1179,16 @@ static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& o // TODO(garretrieger): initially limiting this to leaf's since they can be // moved closer with fewer consequences. However, this can // likely can be used for non-leafs as well. - // TODO(garretrieger): add a maximum priority, don't try to raise past this. // TODO(garretrieger): also try lowering priority of the parent. Make it // get placed further up in the ordering, closer to it's children. // this is probably preferable if the total size of the parent object // is < then the total size of the children (and the parent can be moved). // Since in that case moving the parent will cause a smaller increase in // the length of other offsets. - sorted_graph.raise_childrens_priority (r.parent); - priority_bumped_parents.add (r.parent); - resolution_attempted = true; + if (sorted_graph.raise_childrens_priority (r.parent)) { + priority_bumped_parents.add (r.parent); + resolution_attempted = true; + } continue; } @@ -1127,19 +1213,17 @@ static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& o * For a detailed writeup describing how the algorithm operates see: * docs/repacker.md */ -inline void +inline hb_blob_t* hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed, hb_tag_t table_tag, - hb_serialize_context_t* c, - unsigned max_rounds = 10) { + unsigned max_rounds = 20) { // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts // so try it first to save time. graph_t sorted_graph (packed); sorted_graph.sort_kahn (); if (!sorted_graph.will_overflow ()) { - sorted_graph.serialize (c); - return; + return sorted_graph.serialize (); } sorted_graph.sort_shortest_distance (); @@ -1178,17 +1262,17 @@ hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& pac if (sorted_graph.in_error ()) { - c->err (HB_SERIALIZE_ERROR_OTHER); - return; + DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state."); + return nullptr; } if (sorted_graph.will_overflow ()) { - c->err (HB_SERIALIZE_ERROR_OFFSET_OVERFLOW); DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed."); - return; + return nullptr; } - sorted_graph.serialize (c); + + return sorted_graph.serialize (); } #endif /* HB_REPACKER_HH */ 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 d22ae06087f..823c0be8b56 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh @@ -65,19 +65,26 @@ struct hb_serialize_context_t struct object_t { - void fini () { links.fini (); } + void fini () { + real_links.fini (); + virtual_links.fini (); + } bool operator == (const object_t &o) const { + // Virtual links aren't considered for equality since they don't affect the functionality + // of the object. return (tail - head == o.tail - o.head) - && (links.length == o.links.length) + && (real_links.length == o.real_links.length) && 0 == hb_memcmp (head, o.head, tail - head) - && links.as_bytes () == o.links.as_bytes (); + && real_links.as_bytes () == o.real_links.as_bytes (); } uint32_t hash () const { + // 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 () ^ - links.as_bytes ().hash (); + real_links.as_bytes ().hash (); } struct link_t @@ -92,8 +99,14 @@ struct hb_serialize_context_t char *head; char *tail; - hb_vector_t<link_t> links; + hb_vector_t<link_t> real_links; + hb_vector_t<link_t> virtual_links; object_t *next; + + auto all_links () const HB_AUTO_RETURN + (( hb_concat (this->real_links, this->virtual_links) )); + auto all_links_writer () HB_AUTO_RETURN + (( hb_concat (this->real_links.writer (), this->virtual_links.writer ()) )); }; struct snapshot_t @@ -101,12 +114,14 @@ struct hb_serialize_context_t char *head; char *tail; object_t *current; // Just for sanity check - unsigned num_links; + unsigned num_real_links; + unsigned num_virtual_links; hb_serialize_error_t errors; }; snapshot_t snapshot () - { return snapshot_t { head, tail, current, current->links.length, errors }; } + { return snapshot_t { + head, tail, current, current->real_links.length, current->virtual_links.length, errors }; } hb_serialize_context_t (void *start_, unsigned int size) : start ((char *) start_), @@ -282,7 +297,8 @@ struct hb_serialize_context_t if (!len) { - assert (!obj->links.length); + assert (!obj->real_links.length); + assert (!obj->virtual_links.length); return 0; } @@ -292,6 +308,7 @@ struct hb_serialize_context_t objidx = packed_map.get (obj); if (objidx) { + merge_virtual_links (obj, objidx); obj->fini (); return objidx; } @@ -327,7 +344,8 @@ 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->links.shrink (snap.num_links); + current->real_links.shrink (snap.num_real_links); + current->virtual_links.shrink (snap.num_virtual_links); errors = snap.errors; revert (snap.head, snap.tail); } @@ -375,8 +393,8 @@ struct hb_serialize_context_t assert (current); - auto& link = *current->links.push (); - if (current->links.in_error ()) + auto& link = *current->virtual_links.push (); + if (current->virtual_links.in_error ()) err (HB_SERIALIZE_ERROR_OTHER); link.width = 0; @@ -400,8 +418,8 @@ struct hb_serialize_context_t assert (current); assert (current->head <= (const char *) &ofs); - auto& link = *current->links.push (); - if (current->links.in_error ()) + auto& link = *current->real_links.push (); + if (current->real_links.in_error ()) err (HB_SERIALIZE_ERROR_OTHER); link.width = sizeof (T); @@ -440,10 +458,8 @@ struct hb_serialize_context_t assert (packed.length > 1); for (const object_t* parent : ++hb_iter (packed)) - for (const object_t::link_t &link : parent->links) + for (const object_t::link_t &link : parent->real_links) { - if (unlikely (!link.width)) continue; // Don't need to resolve virtual offsets - const object_t* child = packed[link.objidx]; if (unlikely (!child)) { err (HB_SERIALIZE_ERROR_OTHER); return; } unsigned offset = 0; @@ -642,6 +658,13 @@ struct hb_serialize_context_t private: + void merge_virtual_links (const object_t* from, objidx_t to_idx) { + object_t* to = packed[to_idx]; + for (const auto& l : from->virtual_links) { + to->virtual_links.push (l); + } + } + /* Object memory pool. */ hb_pool_t<object_t> object_pool; 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 53f8664d92e..883ab82093c 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 @@ -248,7 +248,6 @@ static void _colr_closure (hb_face_t *face, unsigned glyphs_num; { glyphs_num = glyphs_colred->get_population (); - // Collect all glyphs referenced by COLRv0 hb_set_t glyphset_colrv0; for (hb_codepoint_t gid : glyphs_colred->iter ()) @@ -397,6 +396,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset); _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ()); + hb_set_set (plan->_glyphset_colred, &cur_glyphset); // Populate a full set of glyphs to retain by adding all referenced // composite glyphs. for (hb_codepoint_t gid : cur_glyphset.iter ()) @@ -511,6 +511,7 @@ hb_subset_plan_create (hb_face_t *face, plan->_glyphset = hb_set_create (); plan->_glyphset_gsub = hb_set_create (); plan->_glyphset_mathed = hb_set_create (); + plan->_glyphset_colred = hb_set_create (); plan->codepoint_to_glyph = hb_map_create (); plan->glyph_map = hb_map_create (); plan->reverse_glyph_map = hb_map_create (); @@ -579,6 +580,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan) hb_set_destroy (plan->_glyphset); hb_set_destroy (plan->_glyphset_gsub); hb_set_destroy (plan->_glyphset_mathed); + hb_set_destroy (plan->_glyphset_colred); hb_map_destroy (plan->gsub_lookups); hb_map_destroy (plan->gpos_lookups); hb_map_destroy (plan->gsub_features); 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 c0232480bff..b9244e5cb2c 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 @@ -78,6 +78,7 @@ struct hb_subset_plan_t hb_set_t *_glyphset; hb_set_t *_glyphset_gsub; hb_set_t *_glyphset_mathed; + hb_set_t *_glyphset_colred; //active lookups we'd like to retain hb_map_t *gsub_lookups; 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 048bdf1888c..bb46e5b97f1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc @@ -104,20 +104,16 @@ _repack (hb_tag_t tag, const hb_serialize_context_t& c) if (!c.offset_overflow ()) return c.copy_blob (); - hb_vector_t<char> buf; - int buf_size = c.end - c.start; - if (unlikely (!buf.alloc (buf_size))) - return nullptr; - - hb_serialize_context_t repacked ((void *) buf, buf_size); - hb_resolve_overflows (c.object_graph (), tag, &repacked); + hb_blob_t* result = hb_resolve_overflows (c.object_graph (), tag); - if (unlikely (repacked.in_error ())) - // TODO(garretrieger): refactor so we can share the resize/retry logic with the subset - // portion. + if (unlikely (!result)) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c offset overflow resolution failed.", + HB_UNTAG (tag)); return nullptr; + } - return repacked.copy_blob (); + return result; } template<typename TableType> diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc index 3dc4c0937d1..0e5a114f7d7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc @@ -878,7 +878,7 @@ retry: if (backward) hb_buffer_reverse (buffer); - buffer->unsafe_to_break_all (); + buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK); /* Wow, done! */ return true; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build b/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build index 1a114f6d433..2652783d821 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build @@ -363,6 +363,7 @@ endif if conf.get('HAVE_DIRECTWRITE', 0) == 1 hb_sources += hb_directwrite_sources hb_headers += hb_directwrite_headers + harfbuzz_deps += directwrite_dep # hb-directwrite needs a C++ linker libharfbuzz_link_language = 'cpp' endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc index fd201c85e88..dc85b721479 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc @@ -114,6 +114,78 @@ test_iterable (const Iterable &lst = Null (Iterable)) test_iterator (lst.iter ()); } +template <typename It> +static void check_sequential (It it) +{ + int i = 1; + for (int v : +it) { + assert (v == i++); + } +} + +static void test_concat () +{ + hb_vector_t<int> a = {1, 2, 3}; + hb_vector_t<int> b = {4, 5}; + + hb_vector_t<int> c = {}; + hb_vector_t<int> d = {1, 2, 3, 4, 5}; + + auto it1 = hb_concat (a, b); + assert (it1.len () == 5); + assert (it1.is_random_access_iterator); + auto it2 = hb_concat (c, d); + assert (it2.len () == 5); + auto it3 = hb_concat (d, c); + assert (it3.len () == 5); + for (int i = 0; i < 5; i++) { + assert(it1[i] == i + 1); + assert(it2[i] == i + 1); + assert(it3[i] == i + 1); + } + + check_sequential (it1); + check_sequential (it2); + check_sequential (it3); + + auto it4 = +it1; + it4 += 0; + assert (*it4 == 1); + + it4 += 2; + assert (*it4 == 3); + assert (it4); + assert (it4.len () == 3); + + it4 += 2; + assert (*it4 == 5); + assert (it4); + assert (it4.len () == 1); + + it4++; + assert (!it4); + assert (it4.len () == 0); + + auto it5 = +it1; + it5 += 3; + assert (*it5 == 4); + + hb_set_t s_a = {1, 2, 3}; + hb_set_t s_b = {4, 5}; + auto it6 = hb_concat (s_a, s_b); + assert (!it6.is_random_access_iterator); + check_sequential (it6); + assert (it6.len () == 5); + + it6 += 0; + assert (*it6 == 1); + + it6 += 3; + assert (*it6 == 4); + assert (it6); + assert (it6.len () == 2); +} + int main (int argc, char **argv) { @@ -282,5 +354,7 @@ main (int argc, char **argv) assert (hb_range (-2, -8, -3).len () == 2); assert (hb_range (-2, -7, -3).len () == 2); + test_concat (); + return 0; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc index 4df0636296a..3a2536a29a4 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc @@ -74,14 +74,13 @@ static void run_resolve_overflow_test (const char* name, graph_t graph (overflowing.object_graph ()); - unsigned buffer_size = overflowing.end - overflowing.start; - void* out_buffer = malloc (buffer_size); - hb_serialize_context_t out (out_buffer, buffer_size); assert (overflowing.offset_overflow ()); - hb_resolve_overflows (overflowing.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), &out, num_iterations); - assert (!out.offset_overflow ()); - hb_bytes_t result = out.copy_bytes (); + hb_blob_t* out = hb_resolve_overflows (overflowing.object_graph (), + HB_TAG ('G', 'S', 'U', 'B'), num_iterations); + assert (out); + + hb_bytes_t result = out->as_bytes (); assert (!expected.offset_overflow ()); hb_bytes_t expected_result = expected.copy_bytes (); @@ -92,9 +91,8 @@ static void run_resolve_overflow_test (const char* name, assert (result[i] == expected_result[i]); } - result.fini (); expected_result.fini (); - free (out_buffer); + hb_blob_destroy (out); } static void add_virtual_offset (unsigned id, @@ -139,6 +137,58 @@ populate_serializer_with_overflow (hb_serialize_context_t* c) } static void +populate_serializer_with_priority_overflow (hb_serialize_context_t* c) +{ + std::string large_string(50000, 'a'); + c->start_serialize<char> (); + + unsigned obj_e = add_object ("e", 1, c); + unsigned obj_d = add_object ("d", 1, c); + + start_object (large_string.c_str (), 50000, c); + add_offset (obj_e, c); + unsigned obj_c = c->pop_pack (false); + + start_object (large_string.c_str (), 20000, c); + add_offset (obj_d, c); + unsigned obj_b = c->pop_pack (false); + + start_object ("a", 1, c); + add_offset (obj_b, c); + add_offset (obj_c, c); + c->pop_pack (false); + + c->end_serialize(); +} + +static void +populate_serializer_with_priority_overflow_expected (hb_serialize_context_t* c) +{ + std::string large_string(50000, 'a'); + c->start_serialize<char> (); + + unsigned obj_e = add_object ("e", 1, c); + + start_object (large_string.c_str (), 50000, c); + add_offset (obj_e, c); + unsigned obj_c = c->pop_pack (false); + + unsigned obj_d = add_object ("d", 1, c); + + start_object (large_string.c_str (), 20000, c); + add_offset (obj_d, c); + unsigned obj_b = c->pop_pack (false); + + start_object ("a", 1, c); + add_offset (obj_b, c); + add_offset (obj_c, c); + c->pop_pack (false); + + c->end_serialize(); +} + + +static void populate_serializer_with_dedup_overflow (hb_serialize_context_t* c) { std::string large_string(70000, 'a'); @@ -763,20 +813,20 @@ populate_serializer_virtual_link (hb_serialize_context_t* c) start_object ("b", 1, c); add_offset (obj_d, c); - unsigned obj_b = c->pop_pack (); + unsigned obj_b = c->pop_pack (false); start_object ("e", 1, c); add_virtual_offset (obj_b, c); - unsigned obj_e = c->pop_pack(); + unsigned obj_e = c->pop_pack (false); start_object ("c", 1, c); add_offset (obj_e, c); - unsigned obj_c = c->pop_pack (); + unsigned obj_c = c->pop_pack (false); start_object ("a", 1, c); add_offset (obj_b, c); add_offset (obj_c, c); - c->pop_pack (); + c->pop_pack (false); c->end_serialize(); } @@ -792,19 +842,19 @@ static void test_sort_kahn_1 () graph.sort_kahn (); assert(strncmp (graph.object (3).head, "abc", 3) == 0); - assert(graph.object (3).links.length == 2); - assert(graph.object (3).links[0].objidx == 2); - assert(graph.object (3).links[1].objidx == 1); + assert(graph.object (3).real_links.length == 2); + assert(graph.object (3).real_links[0].objidx == 2); + assert(graph.object (3).real_links[1].objidx == 1); assert(strncmp (graph.object (2).head, "def", 3) == 0); - assert(graph.object (2).links.length == 1); - assert(graph.object (2).links[0].objidx == 0); + assert(graph.object (2).real_links.length == 1); + assert(graph.object (2).real_links[0].objidx == 0); assert(strncmp (graph.object (1).head, "jkl", 3) == 0); - assert(graph.object (1).links.length == 0); + assert(graph.object (1).real_links.length == 0); assert(strncmp (graph.object (0).head, "ghi", 3) == 0); - assert(graph.object (0).links.length == 0); + assert(graph.object (0).real_links.length == 0); free (buffer); } @@ -821,24 +871,24 @@ static void test_sort_kahn_2 () assert(strncmp (graph.object (4).head, "abc", 3) == 0); - assert(graph.object (4).links.length == 3); - assert(graph.object (4).links[0].objidx == 3); - assert(graph.object (4).links[1].objidx == 0); - assert(graph.object (4).links[2].objidx == 2); + assert(graph.object (4).real_links.length == 3); + assert(graph.object (4).real_links[0].objidx == 3); + assert(graph.object (4).real_links[1].objidx == 0); + assert(graph.object (4).real_links[2].objidx == 2); assert(strncmp (graph.object (3).head, "def", 3) == 0); - assert(graph.object (3).links.length == 1); - assert(graph.object (3).links[0].objidx == 1); + assert(graph.object (3).real_links.length == 1); + assert(graph.object (3).real_links[0].objidx == 1); assert(strncmp (graph.object (2).head, "mn", 2) == 0); - assert(graph.object (2).links.length == 0); + assert(graph.object (2).real_links.length == 0); assert(strncmp (graph.object (1).head, "ghi", 3) == 0); - assert(graph.object (1).links.length == 1); - assert(graph.object (1).links[0].objidx == 0); + assert(graph.object (1).real_links.length == 1); + assert(graph.object (1).real_links[0].objidx == 0); assert(strncmp (graph.object (0).head, "jkl", 3) == 0); - assert(graph.object (0).links.length == 0); + assert(graph.object (0).real_links.length == 0); free (buffer); } @@ -854,24 +904,24 @@ static void test_sort_shortest () graph.sort_shortest_distance (); assert(strncmp (graph.object (4).head, "abc", 3) == 0); - assert(graph.object (4).links.length == 3); - assert(graph.object (4).links[0].objidx == 2); - assert(graph.object (4).links[1].objidx == 0); - assert(graph.object (4).links[2].objidx == 3); + assert(graph.object (4).real_links.length == 3); + assert(graph.object (4).real_links[0].objidx == 2); + assert(graph.object (4).real_links[1].objidx == 0); + assert(graph.object (4).real_links[2].objidx == 3); assert(strncmp (graph.object (3).head, "mn", 2) == 0); - assert(graph.object (3).links.length == 0); + assert(graph.object (3).real_links.length == 0); assert(strncmp (graph.object (2).head, "def", 3) == 0); - assert(graph.object (2).links.length == 1); - assert(graph.object (2).links[0].objidx == 1); + assert(graph.object (2).real_links.length == 1); + assert(graph.object (2).real_links[0].objidx == 1); assert(strncmp (graph.object (1).head, "ghi", 3) == 0); - assert(graph.object (1).links.length == 1); - assert(graph.object (1).links[0].objidx == 0); + assert(graph.object (1).real_links.length == 1); + assert(graph.object (1).real_links[0].objidx == 0); assert(strncmp (graph.object (0).head, "jkl", 3) == 0); - assert(graph.object (0).links.length == 0); + assert(graph.object (0).real_links.length == 0); free (buffer); } @@ -887,27 +937,27 @@ static void test_duplicate_leaf () graph.duplicate (4, 1); assert(strncmp (graph.object (5).head, "abc", 3) == 0); - assert(graph.object (5).links.length == 3); - assert(graph.object (5).links[0].objidx == 3); - assert(graph.object (5).links[1].objidx == 4); - assert(graph.object (5).links[2].objidx == 0); + assert(graph.object (5).real_links.length == 3); + assert(graph.object (5).real_links[0].objidx == 3); + assert(graph.object (5).real_links[1].objidx == 4); + assert(graph.object (5).real_links[2].objidx == 0); assert(strncmp (graph.object (4).head, "jkl", 3) == 0); - assert(graph.object (4).links.length == 0); + assert(graph.object (4).real_links.length == 0); assert(strncmp (graph.object (3).head, "def", 3) == 0); - assert(graph.object (3).links.length == 1); - assert(graph.object (3).links[0].objidx == 2); + assert(graph.object (3).real_links.length == 1); + assert(graph.object (3).real_links[0].objidx == 2); assert(strncmp (graph.object (2).head, "ghi", 3) == 0); - assert(graph.object (2).links.length == 1); - assert(graph.object (2).links[0].objidx == 1); + assert(graph.object (2).real_links.length == 1); + assert(graph.object (2).real_links[0].objidx == 1); assert(strncmp (graph.object (1).head, "jkl", 3) == 0); - assert(graph.object (1).links.length == 0); + assert(graph.object (1).real_links.length == 0); assert(strncmp (graph.object (0).head, "mn", 2) == 0); - assert(graph.object (0).links.length == 0); + assert(graph.object (0).real_links.length == 0); free (buffer); } @@ -923,32 +973,32 @@ static void test_duplicate_interior () graph.duplicate (3, 2); assert(strncmp (graph.object (6).head, "abc", 3) == 0); - assert(graph.object (6).links.length == 3); - assert(graph.object (6).links[0].objidx == 4); - assert(graph.object (6).links[1].objidx == 2); - assert(graph.object (6).links[2].objidx == 1); + assert(graph.object (6).real_links.length == 3); + assert(graph.object (6).real_links[0].objidx == 4); + assert(graph.object (6).real_links[1].objidx == 2); + assert(graph.object (6).real_links[2].objidx == 1); assert(strncmp (graph.object (5).head, "jkl", 3) == 0); - assert(graph.object (5).links.length == 1); - assert(graph.object (5).links[0].objidx == 0); + assert(graph.object (5).real_links.length == 1); + assert(graph.object (5).real_links[0].objidx == 0); assert(strncmp (graph.object (4).head, "def", 3) == 0); - assert(graph.object (4).links.length == 1); - assert(graph.object (4).links[0].objidx == 3); + assert(graph.object (4).real_links.length == 1); + assert(graph.object (4).real_links[0].objidx == 3); assert(strncmp (graph.object (3).head, "ghi", 3) == 0); - assert(graph.object (3).links.length == 1); - assert(graph.object (3).links[0].objidx == 5); + assert(graph.object (3).real_links.length == 1); + assert(graph.object (3).real_links[0].objidx == 5); assert(strncmp (graph.object (2).head, "jkl", 3) == 0); - assert(graph.object (2).links.length == 1); - assert(graph.object (2).links[0].objidx == 0); + assert(graph.object (2).real_links.length == 1); + assert(graph.object (2).real_links[0].objidx == 0); assert(strncmp (graph.object (1).head, "mn", 2) == 0); - assert(graph.object (1).links.length == 0); + assert(graph.object (1).real_links.length == 0); assert(strncmp (graph.object (0).head, "opqrst", 6) == 0); - assert(graph.object (0).links.length == 0); + assert(graph.object (0).real_links.length == 0); free (buffer); } @@ -962,19 +1012,14 @@ test_serialize () populate_serializer_simple (&c1); hb_bytes_t expected = c1.copy_bytes (); - void* buffer_2 = malloc (buffer_size); - hb_serialize_context_t c2 (buffer_2, buffer_size); - graph_t graph (c1.object_graph ()); - graph.serialize (&c2); - hb_bytes_t actual = c2.copy_bytes (); + hb_blob_t* out = graph.serialize (); + free (buffer_1); + hb_bytes_t actual = out->as_bytes (); assert (actual == expected); - - actual.fini (); expected.fini (); - free (buffer_1); - free (buffer_2); + hb_blob_destroy (out); } static void test_will_overflow_1 () @@ -1024,17 +1069,13 @@ static void test_resolve_overflows_via_sort () populate_serializer_with_overflow (&c); graph_t graph (c.object_graph ()); - void* out_buffer = malloc (buffer_size); - hb_serialize_context_t out (out_buffer, buffer_size); - - hb_resolve_overflows (c.object_graph (), HB_TAG_NONE, &out); - assert (!out.offset_overflow ()); - hb_bytes_t result = out.copy_bytes (); + hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE); + assert (out); + hb_bytes_t result = out->as_bytes (); assert (result.length == (80000 + 3 + 3 * 2)); - result.fini (); free (buffer); - free (out_buffer); + hb_blob_destroy (out); } static void test_resolve_overflows_via_duplication () @@ -1045,17 +1086,13 @@ static void test_resolve_overflows_via_duplication () populate_serializer_with_dedup_overflow (&c); graph_t graph (c.object_graph ()); - void* out_buffer = malloc (buffer_size); - hb_serialize_context_t out (out_buffer, buffer_size); - - hb_resolve_overflows (c.object_graph (), HB_TAG_NONE, &out); - assert (!out.offset_overflow ()); - hb_bytes_t result = out.copy_bytes (); + hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE); + assert (out); + hb_bytes_t result = out->as_bytes (); assert (result.length == (10000 + 2 * 2 + 60000 + 2 + 3 * 2)); - result.fini (); free (buffer); - free (out_buffer); + hb_blob_destroy (out); } static void test_resolve_overflows_via_space_assignment () @@ -1085,19 +1122,15 @@ static void test_resolve_overflows_via_isolation () populate_serializer_with_isolation_overflow (&c); graph_t graph (c.object_graph ()); - void* out_buffer = malloc (buffer_size); - hb_serialize_context_t out (out_buffer, buffer_size); - assert (c.offset_overflow ()); - hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), &out, 0); - assert (!out.offset_overflow ()); - hb_bytes_t result = out.copy_bytes (); + hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0); + assert (out); + hb_bytes_t result = out->as_bytes (); assert (result.length == (1 + 10000 + 60000 + 1 + 1 + 4 + 3 * 2)); - result.fini (); free (buffer); - free (out_buffer); + hb_blob_destroy (out); } static void test_resolve_overflows_via_isolation_with_recursive_duplication () @@ -1164,21 +1197,17 @@ static void test_resolve_overflows_via_isolation_spaces () populate_serializer_with_isolation_overflow_spaces (&c); graph_t graph (c.object_graph ()); - void* out_buffer = malloc (buffer_size); - hb_serialize_context_t out (out_buffer, buffer_size); - assert (c.offset_overflow ()); - hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), &out, 0); - assert (!out.offset_overflow ()); - hb_bytes_t result = out.copy_bytes (); + hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0); + assert (out); + hb_bytes_t result = out->as_bytes (); unsigned expected_length = 3 + 2 * 60000; // objects expected_length += 2 * 4 + 2 * 2; // links assert (result.length == expected_length); - result.fini (); free (buffer); - free (out_buffer); + hb_blob_destroy (out); } static void test_resolve_overflows_via_splitting_spaces () @@ -1221,6 +1250,26 @@ static void test_resolve_overflows_via_splitting_spaces_2 () free (expected_buffer); } +static void test_resolve_overflows_via_priority () +{ + size_t buffer_size = 160000; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + populate_serializer_with_priority_overflow (&c); + + void* expected_buffer = malloc (buffer_size); + hb_serialize_context_t e (expected_buffer, buffer_size); + populate_serializer_with_priority_overflow_expected (&e); + + run_resolve_overflow_test ("test_resolve_overflows_via_priority", + c, + e, + 3); + free (buffer); + free (expected_buffer); +} + + static void test_virtual_link () { size_t buffer_size = 100; @@ -1228,13 +1277,10 @@ static void test_virtual_link () hb_serialize_context_t c (buffer, buffer_size); populate_serializer_virtual_link (&c); - void* out_buffer = malloc (buffer_size); - hb_serialize_context_t out (out_buffer, buffer_size); - - hb_resolve_overflows (c.object_graph (), HB_TAG_NONE, &out); - assert (!out.offset_overflow ()); + hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE); + assert (out); - hb_bytes_t result = out.copy_bytes (); + hb_bytes_t result = out->as_bytes (); assert (result.length == 5 + 4 * 2); assert (result[0] == 'a'); assert (result[5] == 'c'); @@ -1242,11 +1288,47 @@ static void test_virtual_link () assert (result[9] == 'b'); assert (result[12] == 'd'); - result.fini (); free (buffer); - free (out_buffer); + hb_blob_destroy (out); } +static void +test_shared_node_with_virtual_links () +{ + size_t buffer_size = 100; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + + c.start_serialize<char> (); + + unsigned obj_b = add_object ("b", 1, &c); + unsigned obj_c = add_object ("c", 1, &c); + + start_object ("d", 1, &c); + add_virtual_offset (obj_b, &c); + unsigned obj_d_1 = c.pop_pack (); + + start_object ("d", 1, &c); + add_virtual_offset (obj_c, &c); + unsigned obj_d_2 = c.pop_pack (); + + assert (obj_d_1 == obj_d_2); + + start_object ("a", 1, &c); + add_offset (obj_b, &c); + add_offset (obj_c, &c); + add_offset (obj_d_1, &c); + add_offset (obj_d_2, &c); + c.pop_pack (); + c.end_serialize (); + + assert(c.object_graph() [obj_d_1]->virtual_links.length == 2); + assert(c.object_graph() [obj_d_1]->virtual_links[0].objidx == obj_b); + assert(c.object_graph() [obj_d_1]->virtual_links[1].objidx == obj_c); + free(buffer); +} + + // TODO(garretrieger): update will_overflow tests to check the overflows array. // TODO(garretrieger): add tests for priority raising. @@ -1262,6 +1344,7 @@ main (int argc, char **argv) test_will_overflow_3 (); test_resolve_overflows_via_sort (); test_resolve_overflows_via_duplication (); + test_resolve_overflows_via_priority (); test_resolve_overflows_via_space_assignment (); test_resolve_overflows_via_isolation (); test_resolve_overflows_via_isolation_with_recursive_duplication (); @@ -1273,4 +1356,5 @@ main (int argc, char **argv) test_duplicate_leaf (); test_duplicate_interior (); test_virtual_link (); + test_shared_node_with_virtual_links (); } diff --git a/Build/source/libs/harfbuzz/version.ac b/Build/source/libs/harfbuzz/version.ac index 351ea234a00..7d709f0f547 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], [3.1.2]) +m4_define([harfbuzz_version], [3.2.0]) |