diff options
Diffstat (limited to 'Build/source/libs/harfbuzz')
83 files changed, 6641 insertions, 906 deletions
diff --git a/Build/source/libs/harfbuzz/ChangeLog b/Build/source/libs/harfbuzz/ChangeLog index 99f03797515..c38c37f7b1a 100644 --- a/Build/source/libs/harfbuzz/ChangeLog +++ b/Build/source/libs/harfbuzz/ChangeLog @@ -1,3 +1,8 @@ +2021-05-06 Akira Kakuto <kakuto@w32tex.org> + + Import harfbuzz-2.8.1. + * version.ac: Adjusted. + 2021-04-18 Akira Kakuto <kakuto@w32tex.org> Import harfbuzz-2.8.0. diff --git a/Build/source/libs/harfbuzz/TLpatches/ChangeLog b/Build/source/libs/harfbuzz/TLpatches/ChangeLog index abe2e9aba4f..1ed5e9e0802 100644 --- a/Build/source/libs/harfbuzz/TLpatches/ChangeLog +++ b/Build/source/libs/harfbuzz/TLpatches/ChangeLog @@ -1,3 +1,8 @@ +2021-05-06 Akira Kakuto <kakuto@w32tex.org> + + Imported harfbuzz-2.8.1 source tree from: + https://github.com/harfbuzz/harfbuzz/releases/download/2.8.1/ + 2021-04-18 Akira Kakuto <kakuto@w32tex.org> Imported harfbuzz-2.8.0 source tree from: diff --git a/Build/source/libs/harfbuzz/TLpatches/TL-Changes b/Build/source/libs/harfbuzz/TLpatches/TL-Changes index f516637bf5f..8ca09c39fc3 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-2.8.0/ tree as obtained from: - https://github.com/harfbuzz/harfbuzz/releases/download/2.8.0/ +Changes applied to the harfbuzz-2.8.1/ tree as obtained from: + https://github.com/harfbuzz/harfbuzz/releases/download/2.8.1/ Removed: COPYING @@ -22,7 +22,6 @@ Removed: unused dirs: docs m4 - meson-cc-tests perf subprojects test diff --git a/Build/source/libs/harfbuzz/configure b/Build/source/libs/harfbuzz/configure index 90604243ed3..797bbe2fc50 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.69 for harfbuzz (TeX Live) 2.8.0. +# Generated by GNU Autoconf 2.69 for harfbuzz (TeX Live) 2.8.1. # # Report bugs to <tex-k@tug.org>. # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='harfbuzz (TeX Live)' PACKAGE_TARNAME='harfbuzz--tex-live-' -PACKAGE_VERSION='2.8.0' -PACKAGE_STRING='harfbuzz (TeX Live) 2.8.0' +PACKAGE_VERSION='2.8.1' +PACKAGE_STRING='harfbuzz (TeX Live) 2.8.1' PACKAGE_BUGREPORT='tex-k@tug.org' PACKAGE_URL='' @@ -1311,7 +1311,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) 2.8.0 to adapt to many kinds of systems. +\`configure' configures harfbuzz (TeX Live) 2.8.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1382,7 +1382,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of harfbuzz (TeX Live) 2.8.0:";; + short | recursive ) echo "Configuration of harfbuzz (TeX Live) 2.8.1:";; esac cat <<\_ACEOF @@ -1487,7 +1487,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -harfbuzz (TeX Live) configure 2.8.0 +harfbuzz (TeX Live) configure 2.8.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2123,7 +2123,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 2.8.0, which was +It was created by harfbuzz (TeX Live) $as_me 2.8.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4042,7 +4042,7 @@ fi # Define the identity of the package. PACKAGE='harfbuzz--tex-live-' - VERSION='2.8.0' + VERSION='2.8.1' # Some tools Automake needs. @@ -4236,8 +4236,8 @@ WARNING_CFLAGS=$kpse_cv_warning_cflags HB_VERSION_MAJOR=2 HB_VERSION_MINOR=8 -HB_VERSION_MICRO=0 -HB_VERSION=2.8.0 +HB_VERSION_MICRO=1 +HB_VERSION=2.8.1 ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -7914,7 +7914,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 2.8.0, which was +This file was extended by harfbuzz (TeX Live) $as_me 2.8.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7980,7 +7980,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -harfbuzz (TeX Live) config.status 2.8.0 +harfbuzz (TeX Live) config.status 2.8.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt b/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt index 285ae1043bf..37909190771 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt +++ b/Build/source/libs/harfbuzz/harfbuzz-src/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.0) +cmake_minimum_required(VERSION 3.0.0) project(harfbuzz) message(WARN "HarfBuzz has a Meson port and tries to migrate all the other build systems to it, please consider using it as we might remove our cmake port soon.") @@ -414,7 +414,9 @@ endif () ## Define harfbuzz library add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers}) target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS}) - +target_include_directories(harfbuzz PUBLIC + "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>" + "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz>") ## Define harfbuzz-icu library if (HB_HAVE_ICU) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog index 741d677a03a..ca3bf2018d4 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog +++ b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog @@ -1,3 +1,2611 @@ +commit b37f03f16b39d397a626f097858e9ae550234ca0 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Tue May 4 02:07:06 2021 +0200 + + 2.8.1 + + NEWS | 9 +++++++++ + configure.ac | 2 +- + meson.build | 2 +- + src/hb-version.h | 4 ++-- + 4 files changed, 13 insertions(+), 4 deletions(-) + +commit d3e84413fd512441e62e5200eab6a24d34282e9a +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun May 2 01:03:21 2021 +0200 + + [ci] Drop macos-10_13_6-aat-fonts job + + This version of macOS is no longer supported by Homebrew, it takes 26 + minutes to brew the dependencies before it fails. + + .circleci/config.yml | 14 -------------- + 1 file changed, 14 deletions(-) + +commit 517d68b26e04be63a306cdacec20218a18ede3a4 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sat May 1 23:50:39 2021 +0200 + + [ci] Pin fedora 33 docker image + + g-ir-scanner is broken on 34 image: + + FAILED: src/HarfBuzz-0.0.gir + /usr/bin/g-ir-scanner --no-libtool --namespace=HarfBuzz --nsversion=0.0 --warn-all --output src/HarfBuzz-0.0.gir --c-include=hb-gobject.h --cflags-begin -DHB_NO_SINGLE_HEADER_ERROR -DHAVE_GOBJECT -DHB_EXTERN= --cflags-end -I/root/project/src -I/root/project/build/src -I./. -I../. --filelist=/root/project/build/src/libharfbuzz-gobject.so.0.20800.0.p/HarfBuzz_0.0_gir_filelist --include=GObject-2.0 --symbol-prefix=hb --symbol-prefix=hb_gobject --identifier-prefix=hb_ --pkg-export=harfbuzz-gobject --cflags-begin -DHAVE_CONFIG_H -I./. -I../. -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/sysprof-4 -I./src/. -I../src/. -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/gobject-introspection-1.0 --cflags-end --add-include-path=/usr/share/gir-1.0 -L/root/project/build/src --extra-library=harfbuzz --library harfbuzz-gobject -L/root/project/build/src -L/root/project/build/src --extra-library=glib-2.0 --extra-library=gobject-2.0 --extra-library=m --extra-library=freetype --extra-library=girepository-1.0 --sources-top-dirs /root/project/subprojects/ --sources-top-dirs /root/project/build/subprojects/ + ../src/hb-buffer.cc:641: Warning: HarfBuzz: unknown annotation: xconstructor + ../src/hb-face.cc:192: Warning: HarfBuzz: unknown annotation: xconstructor + ../src/hb-font.cc:551: Warning: HarfBuzz: unknown annotation: xconstructor + ../src/hb-font.cc:1519: Warning: HarfBuzz: unknown annotation: xconstructor + ../src/hb-map.cc:43: Warning: HarfBuzz: unknown annotation: xconstructor + ../src/hb-ot-name.cc:55: Warning: HarfBuzz: unexpected annotation: out + ../src/hb-set.cc:43: Warning: HarfBuzz: unknown annotation: xconstructor + ../src/hb-shape-plan.cc:173: Warning: HarfBuzz: unknown annotation: xconstructor + ../src/hb-shape-plan.cc:201: Warning: HarfBuzz: unknown annotation: xconstructor + ../src/hb-unicode.cc:172: Warning: HarfBuzz: unknown annotation: xconstructor + g-ir-scanner: link: gcc -pthread -o /root/project/build/tmp-introspecta9rymai3/HarfBuzz-0.0 /root/project/build/tmp-introspecta9rymai3/HarfBuzz-0.0.o -L. -Wl,-rpath,. -Wl,--no-as-needed -L/root/project/build/src -Wl,-rpath,/root/project/build/src -L/root/project/build/src -Wl,-rpath,/root/project/build/src -L/root/project/build/src -Wl,-rpath,/root/project/build/src -lharfbuzz-gobject -lharfbuzz -lglib-2.0 -lgobject-2.0 -lm -lfreetype -lgirepository-1.0 -lgio-2.0 -lgobject-2.0 -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0 -lglib-2.0 + ldd: error: you do not have read permission for `/root/project/build/tmp-introspecta9rymai3/HarfBuzz-0.0' + Traceback (most recent call last): + File "/usr/bin/g-ir-scanner", line 99, in <module> + sys.exit(scanner_main(sys.argv)) + File "/usr/lib64/gobject-introspection/giscanner/scannermain.py", line 599, in scanner_main + shlibs = create_binary(transformer, options, args) + File "/usr/lib64/gobject-introspection/giscanner/scannermain.py", line 428, in create_binary + shlibs = resolve_shlibs(options, binary, options.libraries) + File "/usr/lib64/gobject-introspection/giscanner/shlibs.py", line 170, in resolve_shlibs + _resolve_non_libtool(options, binary, non_libtool)) + File "/usr/lib64/gobject-introspection/giscanner/shlibs.py", line 106, in _resolve_non_libtool + output = subprocess.check_output(args) + File "/usr/lib64/python3.9/subprocess.py", line 424, in check_output + return run(*popenargs, stdout=PIPE, timeout=timeout, check=True, + File "/usr/lib64/python3.9/subprocess.py", line 528, in run + raise CalledProcessError(retcode, process.args, + subprocess.CalledProcessError: Command '['ldd', '/root/project/build/tmp-introspecta9rymai3/HarfBuzz-0.0']' returned non-zero exit status 1. + ninja: build stopped: subcommand failed. + + .circleci/config.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 2b7647649a2016e1f10a0eacc2bf2285e1207954 +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 30 13:34:16 2021 -0700 + + [subset] update test-subset-gpos expected files. + + test/api/fonts/AdobeVFPrototype.WA.gpos.otf | Bin 4148 -> 4096 bytes + test/api/fonts/Roboto-Regular-gpos-aw.ttf | Bin 2236 -> 2228 bytes + 2 files changed, 0 insertions(+), 0 deletions(-) + +commit be50779cda64d6b7bc8422d6b428892ca829733f +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 30 12:59:17 2021 -0700 + + [subset] correct ClassDef format determination. + + It was possible for glyph_min to be a glyph mapped to class zero which threw off the number of glyph calculation. + + src/hb-ot-layout-common.hh | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +commit 90713f270eeb8286067c141245209814b9e7e706 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Fri Apr 30 16:56:39 2021 +0200 + + [hb-ot-layout] Document some return values + + src/hb-ot-layout.cc | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +commit 46362a954c1408f8e4046d1c2069f2f9d7f80dcd +Merge: 42bf8e3d4 e25efb31f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Apr 30 11:39:47 2021 -0600 + + Merge pull request #2958 from googlefonts/layout_by_default_gr + + [subset] Enable layout subsetting by default. + +commit 42bf8e3d49b789adc00c6d7602ba8c73757ebfaf +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Apr 26 12:31:44 2021 -0600 + + [util] Disable chafa's truecolor mode + + See https://github.com/harfbuzz/harfbuzz/pull/2959#issuecomment-827056111 + + util/helper-cairo-ansi.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit c571a96eb0866093f6bece1069f292e34f933421 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun Apr 25 15:43:30 2021 +0200 + + [ci] Disable Chafa on jobs that enables all auto features + + No suitable versions are available on these setups. + + .circleci/config.yml | 2 +- + .github/workflows/linux-ci.yml | 2 +- + .github/workflows/msys2-ci.yml | 3 ++- + 3 files changed, 4 insertions(+), 3 deletions(-) + +commit 8298c2f93b0dbe39eae66455c80e68e812213a2f +Author: Hans Petter Jansson <hpj@hpjansson.org> +Date: Fri Apr 23 18:37:58 2021 +0200 + + [hb-view] Use Chafa for terminal graphics if available + + This produces high-quality terminal graphics using symbols or sixels + according to the detected terminal capabilities. + + Fixes #2430. + + configure.ac | 19 +++++++++ + meson.build | 7 ++++ + meson_options.txt | 2 + + util/Makefile.am | 2 + + util/helper-cairo-ansi.cc | 104 +++++++++++++++++++++++++++++++++++++++++++++- + util/meson.build | 2 +- + 6 files changed, 133 insertions(+), 3 deletions(-) + +commit e25efb31f21441d29866a2be866abb835b77d7c8 +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 23 19:09:37 2021 -0700 + + [subset] consider all value formats when computing effective format. + + src/hb-ot-layout-gpos-table.hh | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +commit 84dbfacfec3818478a1e5ac2b9922d25917493ef +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Apr 15 16:52:11 2021 -0700 + + [subset] fix collect_variation_idx in PairPosFormat2 + + src/hb-ot-layout-common.hh | 15 ++++++++++----- + src/hb-ot-layout-gdef-table.hh | 4 ++-- + src/hb-ot-layout-gpos-table.hh | 22 ++++++++++++++++++---- + 3 files changed, 30 insertions(+), 11 deletions(-) + +commit d356d0f79c6086e913722a8f40cbc0e59a365c1b +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 23 17:41:09 2021 -0700 + + [subset] optimize ValueRecord's for PairPosFormat1. + + src/hb-ot-layout-gpos-table.hh | 53 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 52 insertions(+), 1 deletion(-) + +commit f9fbe4817ebcb0c88865dc19b7a6e616842a7be6 +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 23 17:06:06 2021 -0700 + + [subset] implement value record optimization for PairPosFormat2. + + src/hb-ot-layout-gpos-table.hh | 59 ++++++++++++++++++++++++++++-------------- + 1 file changed, 40 insertions(+), 19 deletions(-) + +commit badb8e409bf65a7a0a1f73af735c86870c5c7899 +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 23 16:32:56 2021 -0700 + + [subset] use copy_values for PairPos serialize. + + src/hb-ot-layout-gpos-table.hh | 111 +++++++++++++++++++++++------------------ + 1 file changed, 62 insertions(+), 49 deletions(-) + +commit 2f50283cd33f20b41a9efd5e851272edacf1d8c1 +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 23 15:21:30 2021 -0700 + + [subset] Begin implementing ValueRecord optimization: + + remove value records which have a zero value. + + src/hb-ot-layout-gpos-table.hh | 91 +++++++++++++++++++++++++++++++++++------- + 1 file changed, 76 insertions(+), 15 deletions(-) + +commit 5df7c668ba530fb5b27e6eed482aa286db3add23 +Author: Garret Rieger <grieger@google.com> +Date: Thu Apr 22 16:45:14 2021 -0700 + + [subset] In SinglePosFormat1 serialize only 1 value record. + + Previously one record per glyph in the subset was serialized. + + src/hb-ot-layout-gpos-table.hh | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +commit 92757f68097aaae74043a5030789289cc3ce514e +Author: Garret Rieger <grieger@google.com> +Date: Thu Apr 22 15:18:35 2021 -0700 + + [subset] Don't drop anchor device tables when dropping hints. These may contain variation data. + + Update subseting expected files to match latest version of fontTools. + + src/hb-ot-layout-gpos-table.hh | 20 +++++++++----------- + .../Comfortaa-Regular-new.default.61,62,63.ttf | Bin 8100 -> 8100 bytes + .../basics/Comfortaa-Regular-new.default.61,63.ttf | Bin 7736 -> 7736 bytes + .../basics/Comfortaa-Regular-new.default.61.ttf | Bin 7360 -> 7360 bytes + .../basics/Comfortaa-Regular-new.default.62.ttf | Bin 6796 -> 6796 bytes + ...aa-Regular-new.default.retain-all-codepoint.ttf | Bin 222212 -> 222212 bytes + ...Regular-new.drop-hints-retain-gids.61,62,63.ttf | Bin 7032 -> 7012 bytes + ...aa-Regular-new.drop-hints-retain-gids.61,63.ttf | Bin 6724 -> 6712 bytes + ...ortaa-Regular-new.drop-hints-retain-gids.61.ttf | Bin 6396 -> 6388 bytes + ...ortaa-Regular-new.drop-hints-retain-gids.62.ttf | Bin 4396 -> 4396 bytes + ...ortaa-Regular-new.drop-hints-retain-gids.63.ttf | Bin 4472 -> 4468 bytes + ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 187952 -> 190920 bytes + .../Comfortaa-Regular-new.drop-hints.61,62,63.ttf | Bin 3444 -> 3424 bytes + .../Comfortaa-Regular-new.drop-hints.61,63.ttf | Bin 3140 -> 3128 bytes + .../basics/Comfortaa-Regular-new.drop-hints.61.ttf | Bin 2804 -> 2800 bytes + .../basics/Comfortaa-Regular-new.drop-hints.62.ttf | Bin 2396 -> 2396 bytes + .../basics/Comfortaa-Regular-new.drop-hints.63.ttf | Bin 2464 -> 2460 bytes + ...Regular-new.drop-hints.retain-all-codepoint.ttf | Bin 187944 -> 190908 bytes + .../basics/Comfortaa-Regular-new.gids.61,62,63.ttf | Bin 9036 -> 9036 bytes + .../basics/Comfortaa-Regular-new.gids.61,63.ttf | Bin 8668 -> 8668 bytes + .../basics/Comfortaa-Regular-new.gids.61.ttf | Bin 8304 -> 8304 bytes + .../basics/Comfortaa-Regular-new.gids.62.ttf | Bin 8236 -> 8236 bytes + .../basics/Comfortaa-Regular-new.gids.63.ttf | Bin 8220 -> 8220 bytes + ...ortaa-Regular-new.gids.retain-all-codepoint.ttf | Bin 222212 -> 222212 bytes + .../Comfortaa-Regular-new.name-ids.61,62,63.ttf | Bin 7840 -> 7840 bytes + .../Comfortaa-Regular-new.name-ids.61,63.ttf | Bin 7476 -> 7476 bytes + .../basics/Comfortaa-Regular-new.name-ids.61.ttf | Bin 7100 -> 7100 bytes + .../basics/Comfortaa-Regular-new.name-ids.62.ttf | Bin 6536 -> 6536 bytes + ...a-Regular-new.name-ids.retain-all-codepoint.ttf | Bin 221952 -> 221952 bytes + ...mfortaa-Regular-new.name-languages.61,62,63.ttf | Bin 8100 -> 8100 bytes + .../Comfortaa-Regular-new.name-languages.61,63.ttf | Bin 7736 -> 7736 bytes + .../Comfortaa-Regular-new.name-languages.61.ttf | Bin 7360 -> 7360 bytes + .../Comfortaa-Regular-new.name-languages.62.ttf | Bin 6796 -> 6796 bytes + ...lar-new.name-languages.retain-all-codepoint.ttf | Bin 222212 -> 222212 bytes + .../Comfortaa-Regular-new.name-legacy.61,62,63.ttf | Bin 8100 -> 8100 bytes + .../Comfortaa-Regular-new.name-legacy.61,63.ttf | Bin 7736 -> 7736 bytes + .../Comfortaa-Regular-new.name-legacy.61.ttf | Bin 7360 -> 7360 bytes + .../Comfortaa-Regular-new.name-legacy.62.ttf | Bin 6796 -> 6796 bytes + ...egular-new.name-legacy.retain-all-codepoint.ttf | Bin 222212 -> 222212 bytes + .../Comfortaa-Regular-new.retain-gids.61,62,63.ttf | Bin 11688 -> 11688 bytes + .../Comfortaa-Regular-new.retain-gids.61,63.ttf | Bin 11320 -> 11320 bytes + .../Comfortaa-Regular-new.retain-gids.61.ttf | Bin 10952 -> 10952 bytes + .../Comfortaa-Regular-new.retain-gids.62.ttf | Bin 8796 -> 8796 bytes + ...egular-new.retain-gids.retain-all-codepoint.ttf | Bin 222224 -> 222224 bytes + ...Regular.abc.drop-hints-retain-gids.61,62,63.ttf | Bin 1208 -> 1192 bytes + ...to-Regular.abc.drop-hints-retain-gids.61,63.ttf | Bin 1136 -> 1124 bytes + ...oboto-Regular.abc.drop-hints-retain-gids.61.ttf | Bin 988 -> 984 bytes + ...oboto-Regular.abc.drop-hints-retain-gids.63.ttf | Bin 972 -> 968 bytes + ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 1208 -> 1192 bytes + .../Roboto-Regular.abc.drop-hints.61,62,63.ttf | Bin 1208 -> 1192 bytes + .../basics/Roboto-Regular.abc.drop-hints.61,63.ttf | Bin 1120 -> 1108 bytes + .../basics/Roboto-Regular.abc.drop-hints.61.ttf | Bin 988 -> 984 bytes + .../basics/Roboto-Regular.abc.drop-hints.63.ttf | Bin 960 -> 956 bytes + ...Regular.abc.drop-hints.retain-all-codepoint.ttf | Bin 1208 -> 1192 bytes + ...subroutinize-retain-gids.1FC,21,41,20,62,63.otf | Bin 30500 -> 30488 bytes + ...rop-hints-desubroutinize.1FC,21,41,20,62,63.otf | Bin 3680 -> 3668 bytes + ...r.drop-hints-retain-gids.1FC,21,41,20,62,63.otf | Bin 30636 -> 30624 bytes + ...nsPro-Regular.drop-hints.1FC,21,41,20,62,63.otf | Bin 3820 -> 3808 bytes + .../Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf | Bin 2192 -> 2184 bytes + ...ifVariable-Roman.default.1FC,21,41,20,62,63.ttf | Bin 6876 -> 6876 bytes + .../SourceSerifVariable-Roman.default.61,62,63.ttf | Bin 6552 -> 6552 bytes + ...ariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf | Bin 6612 -> 6832 bytes + ...urceSerifVariable-Roman.drop-hints.61,62,63.ttf | Bin 6356 -> 6552 bytes + ...rifVariable-Roman.drop-hints.D7,D8,D9,DA,DE.ttf | Bin 5880 -> 6136 bytes + .../AdobeVFPrototype.drop-hints.41,42,43,57.otf | Bin 5180 -> 5272 bytes + .../AdobeVFPrototype.drop-hints.41,42,43.otf | Bin 4688 -> 4744 bytes + .../AdobeVFPrototype.drop-hints.41,42.otf | Bin 4236 -> 4264 bytes + .../AdobeVFPrototype.drop-hints.41,56,57.otf | Bin 4348 -> 4408 bytes + .../AdobeVFPrototype.drop-hints.41.otf | Bin 3552 -> 3560 bytes + .../AdobeVFPrototype.drop-hints.42,57.otf | Bin 4364 -> 4396 bytes + .../Roboto-Regular.drop-hints.1E00,303.ttf | Bin 1468 -> 1464 bytes + .../expected/layout.khmer/Khmer.default.1780.ttf | Bin 0 -> 4204 bytes + ...ult.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 0 -> 6412 bytes + .../expected/layout.khmer/Khmer.default.31.ttf | Bin 0 -> 4140 bytes + .../layout.khmer/Khmer.retain-gids.1780.ttf | Bin 0 -> 4464 bytes + ...ids.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 0 -> 7848 bytes + .../expected/layout.khmer/Khmer.retain-gids.31.ttf | Bin 0 -> 4256 bytes + .../variable/Fraunces.default.26,66,69,124,125.ttf | Bin 0 -> 18448 bytes + .../data/expected/variable/Fraunces.default.61.ttf | Bin 0 -> 5880 bytes + 79 files changed, 9 insertions(+), 11 deletions(-) + +commit 6fddc2bbf9224bde4327e1792a683de637ad5613 +Author: Garret Rieger <grieger@google.com> +Date: Thu Apr 1 15:34:17 2021 -0700 + + [subset] subset layout tables (G*) by default. + + src/hb-subset-input.cc | 3 --- + .../Comfortaa-Regular-new.default.61,62,63.ttf | Bin 7392 -> 8100 bytes + .../basics/Comfortaa-Regular-new.default.61,63.ttf | Bin 7036 -> 7736 bytes + .../basics/Comfortaa-Regular-new.default.61.ttf | Bin 6684 -> 7360 bytes + .../basics/Comfortaa-Regular-new.default.62.ttf | Bin 6628 -> 6796 bytes + .../basics/Comfortaa-Regular-new.default.63.ttf | Bin 6608 -> 6844 bytes + ...aa-Regular-new.default.retain-all-codepoint.ttf | Bin 182876 -> 222212 bytes + ...Regular-new.drop-hints-retain-gids.61,62,63.ttf | Bin 4844 -> 7032 bytes + ...aa-Regular-new.drop-hints-retain-gids.61,63.ttf | Bin 4552 -> 6724 bytes + ...ortaa-Regular-new.drop-hints-retain-gids.61.ttf | Bin 3988 -> 6396 bytes + ...ortaa-Regular-new.drop-hints-retain-gids.62.ttf | Bin 4228 -> 4396 bytes + ...ortaa-Regular-new.drop-hints-retain-gids.63.ttf | Bin 4236 -> 4472 bytes + ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 151672 -> 187952 bytes + .../Comfortaa-Regular-new.drop-hints.61,62,63.ttf | Bin 2852 -> 3444 bytes + .../Comfortaa-Regular-new.drop-hints.61,63.ttf | Bin 2552 -> 3140 bytes + .../basics/Comfortaa-Regular-new.drop-hints.61.ttf | Bin 2240 -> 2804 bytes + .../basics/Comfortaa-Regular-new.drop-hints.62.ttf | Bin 2228 -> 2396 bytes + .../basics/Comfortaa-Regular-new.drop-hints.63.ttf | Bin 2228 -> 2464 bytes + ...Regular-new.drop-hints.retain-all-codepoint.ttf | Bin 151608 -> 187944 bytes + .../basics/Comfortaa-Regular-new.gids.61,62,63.ttf | Bin 8296 -> 9036 bytes + .../basics/Comfortaa-Regular-new.gids.61,63.ttf | Bin 7944 -> 8668 bytes + .../basics/Comfortaa-Regular-new.gids.61.ttf | Bin 7588 -> 8304 bytes + .../basics/Comfortaa-Regular-new.gids.62.ttf | Bin 7528 -> 8236 bytes + .../basics/Comfortaa-Regular-new.gids.63.ttf | Bin 7516 -> 8220 bytes + ...ortaa-Regular-new.gids.retain-all-codepoint.ttf | Bin 182876 -> 222212 bytes + ...Regular-new.keep-layout-drop-hints.61,62,63.ttf | Bin 3444 -> 0 bytes + ...aa-Regular-new.keep-layout-drop-hints.61,63.ttf | Bin 3140 -> 0 bytes + ...ortaa-Regular-new.keep-layout-drop-hints.61.ttf | Bin 2804 -> 0 bytes + ...ortaa-Regular-new.keep-layout-drop-hints.62.ttf | Bin 2396 -> 0 bytes + ...ortaa-Regular-new.keep-layout-drop-hints.63.ttf | Bin 2464 -> 0 bytes + ...keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 187944 -> 0 bytes + .../Comfortaa-Regular-new.keep-layout.61,62,63.ttf | Bin 8100 -> 0 bytes + .../Comfortaa-Regular-new.keep-layout.61,63.ttf | Bin 7736 -> 0 bytes + .../Comfortaa-Regular-new.keep-layout.61.ttf | Bin 7360 -> 0 bytes + .../Comfortaa-Regular-new.keep-layout.62.ttf | Bin 6796 -> 0 bytes + .../Comfortaa-Regular-new.keep-layout.63.ttf | Bin 6844 -> 0 bytes + ...egular-new.keep-layout.retain-all-codepoint.ttf | Bin 222212 -> 0 bytes + .../Comfortaa-Regular-new.name-ids.61,62,63.ttf | Bin 7132 -> 7840 bytes + .../Comfortaa-Regular-new.name-ids.61,63.ttf | Bin 6776 -> 7476 bytes + .../basics/Comfortaa-Regular-new.name-ids.61.ttf | Bin 6424 -> 7100 bytes + .../basics/Comfortaa-Regular-new.name-ids.62.ttf | Bin 6368 -> 6536 bytes + .../basics/Comfortaa-Regular-new.name-ids.63.ttf | Bin 6348 -> 6584 bytes + ...a-Regular-new.name-ids.retain-all-codepoint.ttf | Bin 182616 -> 221952 bytes + ...mfortaa-Regular-new.name-languages.61,62,63.ttf | Bin 7392 -> 8100 bytes + .../Comfortaa-Regular-new.name-languages.61,63.ttf | Bin 7036 -> 7736 bytes + .../Comfortaa-Regular-new.name-languages.61.ttf | Bin 6684 -> 7360 bytes + .../Comfortaa-Regular-new.name-languages.62.ttf | Bin 6628 -> 6796 bytes + .../Comfortaa-Regular-new.name-languages.63.ttf | Bin 6608 -> 6844 bytes + ...lar-new.name-languages.retain-all-codepoint.ttf | Bin 182876 -> 222212 bytes + .../Comfortaa-Regular-new.name-legacy.61,62,63.ttf | Bin 7392 -> 8100 bytes + .../Comfortaa-Regular-new.name-legacy.61,63.ttf | Bin 7036 -> 7736 bytes + .../Comfortaa-Regular-new.name-legacy.61.ttf | Bin 6684 -> 7360 bytes + .../Comfortaa-Regular-new.name-legacy.62.ttf | Bin 6628 -> 6796 bytes + .../Comfortaa-Regular-new.name-legacy.63.ttf | Bin 6608 -> 6844 bytes + ...egular-new.name-legacy.retain-all-codepoint.ttf | Bin 182876 -> 222212 bytes + .../Comfortaa-Regular-new.retain-gids.61,62,63.ttf | Bin 9384 -> 11688 bytes + .../Comfortaa-Regular-new.retain-gids.61,63.ttf | Bin 9036 -> 11320 bytes + .../Comfortaa-Regular-new.retain-gids.61.ttf | Bin 8432 -> 10952 bytes + .../Comfortaa-Regular-new.retain-gids.62.ttf | Bin 8628 -> 8796 bytes + .../Comfortaa-Regular-new.retain-gids.63.ttf | Bin 8616 -> 8852 bytes + ...egular-new.retain-gids.retain-all-codepoint.ttf | Bin 182940 -> 222224 bytes + ...ular-subset.keep-layout-drop-hints.61,62,63.ttf | Bin 1452 -> 0 bytes + ...Regular-subset.keep-layout-drop-hints.61,63.ttf | Bin 1276 -> 0 bytes + ...jo-Regular-subset.keep-layout-drop-hints.61.ttf | Bin 1128 -> 0 bytes + ...jo-Regular-subset.keep-layout-drop-hints.62.ttf | Bin 1140 -> 0 bytes + ...jo-Regular-subset.keep-layout-drop-hints.63.ttf | Bin 1104 -> 0 bytes + ...keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 3536 -> 0 bytes + ...yeongjo-Regular-subset.keep-layout.61,62,63.ttf | Bin 4128 -> 0 bytes + ...umMyeongjo-Regular-subset.keep-layout.61,63.ttf | Bin 3580 -> 0 bytes + ...NanumMyeongjo-Regular-subset.keep-layout.61.ttf | Bin 3156 -> 0 bytes + ...NanumMyeongjo-Regular-subset.keep-layout.62.ttf | Bin 3180 -> 0 bytes + ...NanumMyeongjo-Regular-subset.keep-layout.63.ttf | Bin 3048 -> 0 bytes + ...lar-subset.keep-layout.retain-all-codepoint.ttf | Bin 9524 -> 0 bytes + .../basics/Roboto-Regular.abc.default.61,62,63.ttf | Bin 2168 -> 2452 bytes + .../basics/Roboto-Regular.abc.default.61,63.ttf | Bin 1988 -> 2260 bytes + .../basics/Roboto-Regular.abc.default.61.ttf | Bin 1792 -> 2048 bytes + .../basics/Roboto-Regular.abc.default.62.ttf | Bin 1740 -> 1916 bytes + .../basics/Roboto-Regular.abc.default.63.ttf | Bin 1716 -> 1972 bytes + ...to-Regular.abc.default.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes + ...Regular.abc.drop-hints-retain-gids.61,62,63.ttf | Bin 924 -> 1208 bytes + ...to-Regular.abc.drop-hints-retain-gids.61,63.ttf | Bin 856 -> 1136 bytes + ...oboto-Regular.abc.drop-hints-retain-gids.61.ttf | Bin 732 -> 988 bytes + ...oboto-Regular.abc.drop-hints-retain-gids.62.ttf | Bin 704 -> 880 bytes + ...oboto-Regular.abc.drop-hints-retain-gids.63.ttf | Bin 716 -> 972 bytes + ...drop-hints-retain-gids.retain-all-codepoint.ttf | Bin 924 -> 1208 bytes + .../Roboto-Regular.abc.drop-hints.61,62,63.ttf | Bin 924 -> 1208 bytes + .../basics/Roboto-Regular.abc.drop-hints.61,63.ttf | Bin 848 -> 1120 bytes + .../basics/Roboto-Regular.abc.drop-hints.61.ttf | Bin 732 -> 988 bytes + .../basics/Roboto-Regular.abc.drop-hints.62.ttf | Bin 700 -> 876 bytes + .../basics/Roboto-Regular.abc.drop-hints.63.ttf | Bin 704 -> 960 bytes + ...Regular.abc.drop-hints.retain-all-codepoint.ttf | Bin 924 -> 1208 bytes + .../basics/Roboto-Regular.abc.gids.61,62,63.ttf | Bin 2168 -> 2452 bytes + .../basics/Roboto-Regular.abc.gids.61,63.ttf | Bin 2168 -> 2452 bytes + .../expected/basics/Roboto-Regular.abc.gids.61.ttf | Bin 2168 -> 2452 bytes + .../expected/basics/Roboto-Regular.abc.gids.62.ttf | Bin 2168 -> 2452 bytes + .../expected/basics/Roboto-Regular.abc.gids.63.ttf | Bin 2168 -> 2452 bytes + ...oboto-Regular.abc.gids.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes + ...Regular.abc.keep-layout-drop-hints.61,62,63.ttf | Bin 1208 -> 0 bytes + ...to-Regular.abc.keep-layout-drop-hints.61,63.ttf | Bin 1120 -> 0 bytes + ...oboto-Regular.abc.keep-layout-drop-hints.61.ttf | Bin 988 -> 0 bytes + ...oboto-Regular.abc.keep-layout-drop-hints.62.ttf | Bin 876 -> 0 bytes + ...oboto-Regular.abc.keep-layout-drop-hints.63.ttf | Bin 960 -> 0 bytes + ...keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 1208 -> 0 bytes + .../Roboto-Regular.abc.keep-layout.61,62,63.ttf | Bin 2452 -> 0 bytes + .../Roboto-Regular.abc.keep-layout.61,63.ttf | Bin 2260 -> 0 bytes + .../basics/Roboto-Regular.abc.keep-layout.61.ttf | Bin 2048 -> 0 bytes + .../basics/Roboto-Regular.abc.keep-layout.62.ttf | Bin 1916 -> 0 bytes + .../basics/Roboto-Regular.abc.keep-layout.63.ttf | Bin 1972 -> 0 bytes + ...egular.abc.keep-layout.retain-all-codepoint.ttf | Bin 2452 -> 0 bytes + .../Roboto-Regular.abc.name-ids.61,62,63.ttf | Bin 2168 -> 2452 bytes + .../basics/Roboto-Regular.abc.name-ids.61,63.ttf | Bin 1988 -> 2260 bytes + .../basics/Roboto-Regular.abc.name-ids.61.ttf | Bin 1792 -> 2048 bytes + .../basics/Roboto-Regular.abc.name-ids.62.ttf | Bin 1740 -> 1916 bytes + .../basics/Roboto-Regular.abc.name-ids.63.ttf | Bin 1716 -> 1972 bytes + ...o-Regular.abc.name-ids.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes + .../Roboto-Regular.abc.name-languages.61,62,63.ttf | Bin 2168 -> 2452 bytes + .../Roboto-Regular.abc.name-languages.61,63.ttf | Bin 1988 -> 2260 bytes + .../Roboto-Regular.abc.name-languages.61.ttf | Bin 1792 -> 2048 bytes + .../Roboto-Regular.abc.name-languages.62.ttf | Bin 1740 -> 1916 bytes + .../Roboto-Regular.abc.name-languages.63.ttf | Bin 1716 -> 1972 bytes + ...lar.abc.name-languages.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes + .../Roboto-Regular.abc.name-legacy.61,62,63.ttf | Bin 2168 -> 2452 bytes + .../Roboto-Regular.abc.name-legacy.61,63.ttf | Bin 1988 -> 2260 bytes + .../basics/Roboto-Regular.abc.name-legacy.61.ttf | Bin 1792 -> 2048 bytes + .../basics/Roboto-Regular.abc.name-legacy.62.ttf | Bin 1740 -> 1916 bytes + .../basics/Roboto-Regular.abc.name-legacy.63.ttf | Bin 1716 -> 1972 bytes + ...egular.abc.name-legacy.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes + .../Roboto-Regular.abc.retain-gids.61,62,63.ttf | Bin 2168 -> 2452 bytes + .../Roboto-Regular.abc.retain-gids.61,63.ttf | Bin 1996 -> 2276 bytes + .../basics/Roboto-Regular.abc.retain-gids.61.ttf | Bin 1792 -> 2048 bytes + .../basics/Roboto-Regular.abc.retain-gids.62.ttf | Bin 1748 -> 1924 bytes + .../basics/Roboto-Regular.abc.retain-gids.63.ttf | Bin 1732 -> 1988 bytes + ...egular.abc.retain-gids.retain-all-codepoint.ttf | Bin 2168 -> 2452 bytes + ...olorEmoji.subset.index_format3.default.2049.ttf | Bin 3112 -> 3108 bytes + ...rEmoji.subset.index_format3.default.38,2049.ttf | Bin 4080 -> 4076 bytes + ...rEmoji.subset.index_format3.default.38,20E3.ttf | Bin 3564 -> 3560 bytes + ...index_format3.default.38,39,AE,2049,38,20E3.ttf | Bin 10112 -> 10112 bytes + ...oji.subset.index_format3.default.38,AE,2049.ttf | Bin 7536 -> 7536 bytes + ...oColorEmoji.subset.index_format3.default.39.ttf | Bin 1920 -> 1916 bytes + ...oColorEmoji.subset.index_format3.default.AE.ttf | Bin 4412 -> 4408 bytes + ...t.index_format3.drop-hints-retain-gids.2049.ttf | Bin 3136 -> 3132 bytes + ...ndex_format3.drop-hints-retain-gids.38,2049.ttf | Bin 4104 -> 4100 bytes + ...ndex_format3.drop-hints-retain-gids.38,20E3.ttf | Bin 3596 -> 3592 bytes + ...rop-hints-retain-gids.38,39,AE,2049,38,20E3.ttf | Bin 10112 -> 10112 bytes + ...x_format3.drop-hints-retain-gids.38,AE,2049.ttf | Bin 7556 -> 7552 bytes + ...set.index_format3.drop-hints-retain-gids.39.ttf | Bin 1928 -> 1924 bytes + ...set.index_format3.drop-hints-retain-gids.AE.ttf | Bin 4428 -> 4424 bytes + ...rEmoji.subset.index_format3.drop-hints.2049.ttf | Bin 3112 -> 3108 bytes + ...oji.subset.index_format3.drop-hints.38,2049.ttf | Bin 4080 -> 4076 bytes + ...oji.subset.index_format3.drop-hints.38,20E3.ttf | Bin 3564 -> 3560 bytes + ...ex_format3.drop-hints.38,39,AE,2049,38,20E3.ttf | Bin 10112 -> 10112 bytes + ....subset.index_format3.drop-hints.38,AE,2049.ttf | Bin 7536 -> 7536 bytes + ...lorEmoji.subset.index_format3.drop-hints.39.ttf | Bin 1920 -> 1916 bytes + ...lorEmoji.subset.index_format3.drop-hints.AE.ttf | Bin 4412 -> 4408 bytes + ...Emoji.subset.index_format3.retain-gids.2049.ttf | Bin 3136 -> 3132 bytes + ...ji.subset.index_format3.retain-gids.38,2049.ttf | Bin 4104 -> 4100 bytes + ...ji.subset.index_format3.retain-gids.38,20E3.ttf | Bin 3596 -> 3592 bytes + ...x_format3.retain-gids.38,39,AE,2049,38,20E3.ttf | Bin 10112 -> 10112 bytes + ...subset.index_format3.retain-gids.38,AE,2049.ttf | Bin 7556 -> 7552 bytes + ...orEmoji.subset.index_format3.retain-gids.39.ttf | Bin 1928 -> 1924 bytes + ...orEmoji.subset.index_format3.retain-gids.AE.ttf | Bin 4428 -> 4424 bytes + ...eSansPro-Regular.default.1FC,21,41,20,62,63.otf | Bin 2180 -> 4192 bytes + .../SourceSansPro-Regular.default.61,62,63.otf | Bin 1892 -> 3856 bytes + ...ourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf | Bin 2008 -> 3144 bytes + ...subroutinize-retain-gids.1FC,21,41,20,62,63.otf | Bin 19796 -> 30788 bytes + ...Regular.desubroutinize-retain-gids.61,62,63.otf | Bin 1992 -> 30908 bytes + ...r.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf | Bin 30208 -> 31336 bytes + ...o-Regular.desubroutinize.1FC,21,41,20,62,63.otf | Bin 2036 -> 3968 bytes + ...urceSansPro-Regular.desubroutinize.61,62,63.otf | Bin 1796 -> 3556 bytes + ...nsPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf | Bin 1992 -> 3168 bytes + ...subroutinize-retain-gids.1FC,21,41,20,62,63.otf | Bin 19636 -> 30500 bytes + ...p-hints-desubroutinize-retain-gids.61,62,63.otf | Bin 1868 -> 30668 bytes + ...s-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf | Bin 30060 -> 31124 bytes + ...rop-hints-desubroutinize.1FC,21,41,20,62,63.otf | Bin 1876 -> 3680 bytes + ...-Regular.drop-hints-desubroutinize.61,62,63.otf | Bin 1672 -> 3320 bytes + ...ar.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf | Bin 1844 -> 2952 bytes + ...r.drop-hints-retain-gids.1FC,21,41,20,62,63.otf | Bin 19728 -> 30636 bytes + ...Pro-Regular.drop-hints-retain-gids.61,62,63.otf | Bin 1904 -> 30888 bytes + ...gular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf | Bin 30072 -> 31104 bytes + ...nsPro-Regular.drop-hints.1FC,21,41,20,62,63.otf | Bin 1960 -> 3820 bytes + .../SourceSansPro-Regular.drop-hints.61,62,63.otf | Bin 1736 -> 3524 bytes + ...ceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf | Bin 1860 -> 2932 bytes + ...sPro-Regular.retain-gids.1FC,21,41,20,62,63.otf | Bin 19948 -> 31012 bytes + .../SourceSansPro-Regular.retain-gids.61,62,63.otf | Bin 2060 -> 31208 bytes + ...eSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf | Bin 30224 -> 31312 bytes + ...ubset.default.3042,3044,3046,3048,304A,304B.otf | Bin 3036 -> 4884 bytes + ...ubset.default.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 3248 -> 6276 bytes + ...eHanSans-Regular_subset.default.61,63,65,6B.otf | Bin 2208 -> 2588 bytes + ...ubset.default.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 3468 -> 6736 bytes + .../SourceHanSans-Regular_subset.default.660E.otf | Bin 1928 -> 2456 bytes + ...e-retain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 8932 -> 129876 bytes + ...e-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 116080 -> 130920 bytes + ...bset.desubroutinize-retain-gids.61,63,65,6B.otf | Bin 3016 -> 3412 bytes + ...e-retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 116264 -> 122048 bytes + ...ular_subset.desubroutinize-retain-gids.660E.otf | Bin 50224 -> 50760 bytes + ...esubroutinize.3042,3044,3046,3048,304A,304B.otf | Bin 2960 -> 4724 bytes + ...esubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 3144 -> 5928 bytes + ...s-Regular_subset.desubroutinize.61,63,65,6B.otf | Bin 2140 -> 2520 bytes + ...esubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 3264 -> 6232 bytes + ...eHanSans-Regular_subset.desubroutinize.660E.otf | Bin 1904 -> 2440 bytes + ...e-retain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 8672 -> 129448 bytes + ...e-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 115768 -> 130312 bytes + ...ints-desubroutinize-retain-gids.61,63,65,6B.otf | Bin 2892 -> 3288 bytes + ...e-retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 115884 -> 121284 bytes + ....drop-hints-desubroutinize-retain-gids.660E.otf | Bin 50040 -> 50540 bytes + ...esubroutinize.3042,3044,3046,3048,304A,304B.otf | Bin 2800 -> 4420 bytes + ...esubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 2904 -> 5416 bytes + ...ubset.drop-hints-desubroutinize.61,63,65,6B.otf | Bin 2036 -> 2416 bytes + ...esubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 2972 -> 5556 bytes + ...gular_subset.drop-hints-desubroutinize.660E.otf | Bin 1812 -> 2308 bytes + ...s-retain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 8740 -> 129576 bytes + ...s-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 115864 -> 130604 bytes + ...r_subset.drop-hints-retain-gids.61,63,65,6B.otf | Bin 2852 -> 3248 bytes + ...s-retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 116084 -> 121776 bytes + ...-Regular_subset.drop-hints-retain-gids.660E.otf | Bin 50060 -> 50552 bytes + ...et.drop-hints.3042,3044,3046,3048,304A,304B.otf | Bin 2856 -> 4548 bytes + ...et.drop-hints.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 2996 -> 5708 bytes + ...nSans-Regular_subset.drop-hints.61,63,65,6B.otf | Bin 2068 -> 2448 bytes + ...et.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 3172 -> 6048 bytes + ...ourceHanSans-Regular_subset.drop-hints.660E.otf | Bin 1832 -> 2316 bytes + ...t.retain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 9016 -> 130036 bytes + ...t.retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 116184 -> 131272 bytes + ...Sans-Regular_subset.retain-gids.61,63,65,6B.otf | Bin 3012 -> 3408 bytes + ...t.retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 116468 -> 122552 bytes + ...urceHanSans-Regular_subset.retain-gids.660E.otf | Bin 50244 -> 50776 bytes + .../TwemojiMozilla.subset.default.32,3297,3299.ttf | Bin 5624 -> 5712 bytes + .../colr/TwemojiMozilla.subset.default.32,3297.ttf | Bin 5088 -> 5176 bytes + .../colr/TwemojiMozilla.subset.default.32,3299.ttf | Bin 5264 -> 5352 bytes + .../colr/TwemojiMozilla.subset.default.32.ttf | Bin 4664 -> 4748 bytes + .../TwemojiMozilla.subset.default.3297,3299.ttf | Bin 5604 -> 5692 bytes + .../colr/TwemojiMozilla.subset.default.3297.ttf | Bin 5068 -> 5152 bytes + .../colr/TwemojiMozilla.subset.default.3299.ttf | Bin 5244 -> 5328 bytes + ....subset.drop-hints-retain-gids.32,3297,3299.ttf | Bin 5604 -> 5692 bytes + ...zilla.subset.drop-hints-retain-gids.32,3297.ttf | Bin 5084 -> 5172 bytes + ...zilla.subset.drop-hints-retain-gids.32,3299.ttf | Bin 5264 -> 5352 bytes + ...ojiMozilla.subset.drop-hints-retain-gids.32.ttf | Bin 4644 -> 4728 bytes + ...lla.subset.drop-hints-retain-gids.3297,3299.ttf | Bin 5588 -> 5676 bytes + ...iMozilla.subset.drop-hints-retain-gids.3297.ttf | Bin 5064 -> 5148 bytes + ...iMozilla.subset.drop-hints-retain-gids.3299.ttf | Bin 5244 -> 5328 bytes + ...emojiMozilla.subset.drop-hints.32,3297,3299.ttf | Bin 5604 -> 5692 bytes + .../TwemojiMozilla.subset.drop-hints.32,3297.ttf | Bin 5068 -> 5156 bytes + .../TwemojiMozilla.subset.drop-hints.32,3299.ttf | Bin 5244 -> 5332 bytes + .../colr/TwemojiMozilla.subset.drop-hints.32.ttf | Bin 4644 -> 4728 bytes + .../TwemojiMozilla.subset.drop-hints.3297,3299.ttf | Bin 5584 -> 5672 bytes + .../colr/TwemojiMozilla.subset.drop-hints.3297.ttf | Bin 5048 -> 5132 bytes + .../colr/TwemojiMozilla.subset.drop-hints.3299.ttf | Bin 5224 -> 5308 bytes + ...mojiMozilla.subset.retain-gids.32,3297,3299.ttf | Bin 5624 -> 5712 bytes + .../TwemojiMozilla.subset.retain-gids.32,3297.ttf | Bin 5104 -> 5192 bytes + .../TwemojiMozilla.subset.retain-gids.32,3299.ttf | Bin 5284 -> 5372 bytes + .../colr/TwemojiMozilla.subset.retain-gids.32.ttf | Bin 4664 -> 4748 bytes + ...TwemojiMozilla.subset.retain-gids.3297,3299.ttf | Bin 5608 -> 5696 bytes + .../TwemojiMozilla.subset.retain-gids.3297.ttf | Bin 5084 -> 5168 bytes + .../TwemojiMozilla.subset.retain-gids.3299.ttf | Bin 5264 -> 5348 bytes + .../Roboto-Regular.default.1FC,21,41,20,62,63.ttf | Bin 2984 -> 4656 bytes + .../full-font/Roboto-Regular.default.61,62,63.ttf | Bin 2580 -> 3904 bytes + .../Roboto-Regular.default.D7,D8,D9,DA,DE.ttf | Bin 2944 -> 3976 bytes + ...oboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf | Bin 1436 -> 2532 bytes + .../Roboto-Regular.drop-hints.61,62,63.ttf | Bin 1228 -> 2116 bytes + .../Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf | Bin 1464 -> 2192 bytes + ...ifVariable-Roman.default.1FC,21,41,20,62,63.ttf | Bin 3572 -> 6876 bytes + .../SourceSerifVariable-Roman.default.61,62,63.ttf | Bin 3540 -> 6552 bytes + ...eSerifVariable-Roman.default.D7,D8,D9,DA,DE.ttf | Bin 4032 -> 6136 bytes + ...ariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf | Bin 3572 -> 6612 bytes + ...urceSerifVariable-Roman.drop-hints.61,62,63.ttf | Bin 3540 -> 6356 bytes + ...rifVariable-Roman.drop-hints.D7,D8,D9,DA,DE.ttf | Bin 4032 -> 5880 bytes + .../Mplus1p-Regular.default.1D715,1D7D8,41,42.ttf | Bin 2108 -> 2344 bytes + .../japanese/Mplus1p-Regular.default.25771.ttf | Bin 1824 -> 1992 bytes + ...gular.default.3042,3044,3046,3048,304A,304B.ttf | Bin 2532 -> 2704 bytes + ...gular.default.3042,3044,3046,73E0,5EA6,8F38.ttf | Bin 2776 -> 2948 bytes + .../Mplus1p-Regular.default.61,63,65,6B.ttf | Bin 2076 -> 2324 bytes + ...gular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf | Bin 3072 -> 3244 bytes + .../japanese/Mplus1p-Regular.default.660E.ttf | Bin 1816 -> 1984 bytes + ...plus1p-Regular.drop-hints.1D715,1D7D8,41,42.ttf | Bin 1380 -> 1616 bytes + .../japanese/Mplus1p-Regular.drop-hints.25771.ttf | Bin 1096 -> 1264 bytes + ...ar.drop-hints.3042,3044,3046,3048,304A,304B.ttf | Bin 1804 -> 1976 bytes + ...ar.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf | Bin 2048 -> 2220 bytes + .../Mplus1p-Regular.drop-hints.61,63,65,6B.ttf | Bin 1348 -> 1596 bytes + ...ar.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf | Bin 2344 -> 2516 bytes + .../japanese/Mplus1p-Regular.drop-hints.660E.ttf | Bin 1088 -> 1256 bytes + ...Mplus1p-Regular.keep-gdef.1D715,1D7D8,41,42.ttf | Bin 2148 -> 2344 bytes + .../japanese/Mplus1p-Regular.keep-gdef.25771.ttf | Bin 1860 -> 1992 bytes + ...lar.keep-gdef.3042,3044,3046,3048,304A,304B.ttf | Bin 2572 -> 2704 bytes + ...lar.keep-gdef.3042,3044,3046,73E0,5EA6,8F38.ttf | Bin 2816 -> 2948 bytes + .../Mplus1p-Regular.keep-gdef.61,63,65,6B.ttf | Bin 2116 -> 2324 bytes + ...lar.keep-gdef.660E,6975,73E0,5EA6,8F38,6E05.ttf | Bin 3112 -> 3244 bytes + .../japanese/Mplus1p-Regular.keep-gdef.660E.ttf | Bin 1852 -> 1984 bytes + ...ext1_multiple_subrules_f1.default.41,42,43.otf} | Bin + ...ontext1_multiple_subrules_f1.default.41,42.otf} | Bin + ...ontext1_multiple_subrules_f1.default.41,43.otf} | Bin + ...s_context1_multiple_subrules_f1.default.41.otf} | Bin + ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin + ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin + ...xt1_multiple_subrules_f1.retain-gids.41,42.otf} | Bin + ...xt1_multiple_subrules_f1.retain-gids.41,43.otf} | Bin + ...ntext1_multiple_subrules_f1.retain-gids.41.otf} | Bin + ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin + ...ext2_multiple_subrules_f1.default.41,42,43.otf} | Bin + ...ontext2_multiple_subrules_f1.default.41,42.otf} | Bin + ...ontext2_multiple_subrules_f1.default.41,43.otf} | Bin + ...s_context2_multiple_subrules_f1.default.41.otf} | Bin + ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin + ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin + ...xt2_multiple_subrules_f1.retain-gids.41,42.otf} | Bin + ...xt2_multiple_subrules_f1.retain-gids.41,43.otf} | Bin + ...ntext2_multiple_subrules_f1.retain-gids.41.otf} | Bin + ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin + ...> gpos_context3_simple_f1.default.41,42,43.otf} | Bin + ...f => gpos_context3_simple_f1.default.41,42.otf} | Bin + ...f => gpos_context3_simple_f1.default.41,43.otf} | Bin + ....otf => gpos_context3_simple_f1.default.41.otf} | Bin + ...xt3_simple_f1.default.retain-all-codepoint.otf} | Bin + ...os_context3_simple_f1.retain-gids.41,42,43.otf} | Bin + ... gpos_context3_simple_f1.retain-gids.41,42.otf} | Bin + ... gpos_context3_simple_f1.retain-gids.41,43.otf} | Bin + ... => gpos_context3_simple_f1.retain-gids.41.otf} | Bin + ...simple_f1.retain-gids.retain-all-codepoint.otf} | Bin + .../IndicTestJalandhar-Regular.default.A01.ttf | Bin 4088 -> 4220 bytes + .../IndicTestJalandhar-Regular.default.A05,A06.ttf | Bin 4652 -> 4796 bytes + .../IndicTestJalandhar-Regular.default.A07,A1B.ttf | Bin 4620 -> 4768 bytes + ...andhar-Regular.default.retain-all-codepoint.ttf | Bin 28176 -> 49288 bytes + .../IndicTestJalandhar-Regular.drop-hints.A01.ttf | Bin 948 -> 1080 bytes + ...dicTestJalandhar-Regular.drop-hints.A05,A06.ttf | Bin 1244 -> 1388 bytes + ...dicTestJalandhar-Regular.drop-hints.A07,A1B.ttf | Bin 1240 -> 1388 bytes + ...har-Regular.drop-hints.retain-all-codepoint.ttf | Bin 15200 -> 29504 bytes + .../IndicTestJalandhar-Regular.keep-gdef.A01.ttf | Bin 4140 -> 4220 bytes + ...ndicTestJalandhar-Regular.keep-gdef.A05,A06.ttf | Bin 4716 -> 4796 bytes + ...ndicTestJalandhar-Regular.keep-gdef.A07,A1B.ttf | Bin 4688 -> 4768 bytes + ...dhar-Regular.keep-gdef.retain-all-codepoint.ttf | Bin 28604 -> 49288 bytes + .../AdobeVFPrototype.default.41,42,43,57.otf | Bin 4960 -> 5460 bytes + .../AdobeVFPrototype.default.41,42,43.otf | Bin 4540 -> 4932 bytes + .../AdobeVFPrototype.default.41,42.otf | Bin 4132 -> 4452 bytes + .../AdobeVFPrototype.default.41,56,57.otf | Bin 4152 -> 4600 bytes + .../AdobeVFPrototype.default.41.otf | Bin 3468 -> 3748 bytes + .../AdobeVFPrototype.default.42,57.otf | Bin 4208 -> 4584 bytes + .../AdobeVFPrototype.drop-hints.41,42,43,57.otf | Bin 4772 -> 5180 bytes + .../AdobeVFPrototype.drop-hints.41,42,43.otf | Bin 4352 -> 4688 bytes + .../AdobeVFPrototype.drop-hints.41,42.otf | Bin 3944 -> 4236 bytes + .../AdobeVFPrototype.drop-hints.41,56,57.otf | Bin 3964 -> 4348 bytes + .../AdobeVFPrototype.drop-hints.41.otf | Bin 3280 -> 3552 bytes + .../AdobeVFPrototype.drop-hints.42,57.otf | Bin 4020 -> 4364 bytes + ...AdobeVFPrototype.keep-gdef-gpos.41,42,43,57.otf | Bin 5400 -> 5460 bytes + .../AdobeVFPrototype.keep-gdef-gpos.41,42,43.otf | Bin 4872 -> 4932 bytes + .../AdobeVFPrototype.keep-gdef-gpos.41,42.otf | Bin 4392 -> 4452 bytes + .../AdobeVFPrototype.keep-gdef-gpos.41,56,57.otf | Bin 4540 -> 4600 bytes + .../AdobeVFPrototype.keep-gdef-gpos.41.otf | Bin 3688 -> 3748 bytes + .../AdobeVFPrototype.keep-gdef-gpos.42,57.otf | Bin 4524 -> 4584 bytes + .../Roboto-Regular.default.1E00,303.ttf | Bin 2456 -> 2720 bytes + .../layout.gdef/Roboto-Regular.default.303.ttf | Bin 2128 -> 2312 bytes + .../Roboto-Regular.default.309,20,30F.ttf | Bin 2220 -> 2408 bytes + .../layout.gdef/Roboto-Regular.default.323.ttf | Bin 2020 -> 2204 bytes + .../Roboto-Regular.default.41,42,43.ttf | Bin 2480 -> 3668 bytes + .../Roboto-Regular.drop-hints.1E00,303.ttf | Bin 1204 -> 1468 bytes + .../layout.gdef/Roboto-Regular.drop-hints.303.ttf | Bin 1012 -> 1196 bytes + .../Roboto-Regular.drop-hints.309,20,30F.ttf | Bin 1068 -> 1256 bytes + .../layout.gdef/Roboto-Regular.drop-hints.323.ttf | Bin 952 -> 1136 bytes + .../Roboto-Regular.drop-hints.41,42,43.ttf | Bin 1188 -> 2036 bytes + .../Roboto-Regular.keep-gdef-gpos.1E00,303.ttf | Bin 2648 -> 2720 bytes + .../Roboto-Regular.keep-gdef-gpos.303.ttf | Bin 2240 -> 2312 bytes + .../Roboto-Regular.keep-gdef-gpos.309,20,30F.ttf | Bin 2336 -> 2408 bytes + .../Roboto-Regular.keep-gdef-gpos.323.ttf | Bin 2132 -> 2204 bytes + .../Roboto-Regular.keep-gdef-gpos.41,42,43.ttf | Bin 2728 -> 3668 bytes + ...ut.41,43.otf => gpos1_2_font.default.41,43.otf} | Bin + ...ut.41,46.otf => gpos1_2_font.default.41,46.otf} | Bin + ...p-layout.41.otf => gpos1_2_font.default.41.otf} | Bin + ...ut.42,44.otf => gpos1_2_font.default.42,44.otf} | Bin + ...ut.43,46.otf => gpos1_2_font.default.43,46.otf} | Bin + ... gpos1_2_font.default.retain-all-codepoint.otf} | Bin + ...1,43.otf => gpos1_2_font.retain-gids.41,43.otf} | Bin + ...1,46.otf => gpos1_2_font.retain-gids.41,46.otf} | Bin + ...gids.41.otf => gpos1_2_font.retain-gids.41.otf} | Bin + ...2,44.otf => gpos1_2_font.retain-gids.42,44.otf} | Bin + ...3,46.otf => gpos1_2_font.retain-gids.43,46.otf} | Bin + ...s1_2_font.retain-gids.retain-all-codepoint.otf} | Bin + ...3,25.otf => gpos2_1_font7.default.21,23,25.otf} | Bin + ...t.21,23.otf => gpos2_1_font7.default.21,23.otf} | Bin + ...t.2E,23.otf => gpos2_1_font7.default.2E,23.otf} | Bin + ...2,43.otf => gpos2_1_font7.default.41,42,43.otf} | Bin + ...gpos2_1_font7.default.retain-all-codepoint.otf} | Bin + ....otf => gpos2_1_font7.retain-gids.21,23,25.otf} | Bin + ...,23.otf => gpos2_1_font7.retain-gids.21,23.otf} | Bin + ...,23.otf => gpos2_1_font7.retain-gids.2E,23.otf} | Bin + ....otf => gpos2_1_font7.retain-gids.41,42,43.otf} | Bin + ...2_1_font7.retain-gids.retain-all-codepoint.otf} | Bin + ...3,25.otf => gpos2_2_font5.default.21,23,25.otf} | Bin + ...t.21,23.otf => gpos2_2_font5.default.21,23.otf} | Bin + ...t.2E,23.otf => gpos2_2_font5.default.2E,23.otf} | Bin + ...2,43.otf => gpos2_2_font5.default.41,42,43.otf} | Bin + ...gpos2_2_font5.default.retain-all-codepoint.otf} | Bin + ....otf => gpos2_2_font5.retain-gids.21,23,25.otf} | Bin + ...,23.otf => gpos2_2_font5.retain-gids.21,23.otf} | Bin + ...,23.otf => gpos2_2_font5.retain-gids.2E,23.otf} | Bin + ....otf => gpos2_2_font5.retain-gids.41,42,43.otf} | Bin + ...2_2_font5.retain-gids.retain-all-codepoint.otf} | Bin + ...out.28,29.otf => gpos3_font3.default.28,29.otf} | Bin + ...out.28,2B.otf => gpos3_font3.default.28,2B.otf} | Bin + ...out.29,2B.otf => gpos3_font3.default.29,2B.otf} | Bin + ...,42,43.otf => gpos3_font3.default.41,42,43.otf} | Bin + ...> gpos3_font3.default.retain-all-codepoint.otf} | Bin + ...28,29.otf => gpos3_font3.retain-gids.28,29.otf} | Bin + ...28,2B.otf => gpos3_font3.retain-gids.28,2B.otf} | Bin + ...29,2B.otf => gpos3_font3.retain-gids.29,2B.otf} | Bin + ...43.otf => gpos3_font3.retain-gids.41,42,43.otf} | Bin + ...os3_font3.retain-gids.retain-all-codepoint.otf} | Bin + ...os4_multiple_anchors_1.default.41,42,43,44.otf} | Bin + ...os4_multiple_anchors_1.default.41,42,43,45.otf} | Bin + ... gpos4_multiple_anchors_1.default.41,42,43.otf} | Bin + ... => gpos4_multiple_anchors_1.default.41,42.otf} | Bin + ..._multiple_anchors_1.default.41,43,44,45,46.otf} | Bin + ... gpos4_multiple_anchors_1.default.41,43,44.otf} | Bin + ... gpos4_multiple_anchors_1.default.41,43,45.otf} | Bin + ... => gpos4_multiple_anchors_1.default.41,43.otf} | Bin + ...otf => gpos4_multiple_anchors_1.default.41.otf} | Bin + ...ple_anchors_1.default.retain-all-codepoint.otf} | Bin + ...multiple_anchors_1.retain-gids.41,42,43,44.otf} | Bin + ...multiple_anchors_1.retain-gids.41,42,43,45.otf} | Bin + ...s4_multiple_anchors_1.retain-gids.41,42,43.otf} | Bin + ...gpos4_multiple_anchors_1.retain-gids.41,42.otf} | Bin + ...tiple_anchors_1.retain-gids.41,43,44,45,46.otf} | Bin + ...s4_multiple_anchors_1.retain-gids.41,43,44.otf} | Bin + ...s4_multiple_anchors_1.retain-gids.41,43,45.otf} | Bin + ...gpos4_multiple_anchors_1.retain-gids.41,43.otf} | Bin + ...=> gpos4_multiple_anchors_1.retain-gids.41.otf} | Bin + ...anchors_1.retain-gids.retain-all-codepoint.otf} | Bin + ...,44.otf => gpos5_font1.default.41,42,43,44.otf} | Bin + ...,45.otf => gpos5_font1.default.41,42,43,45.otf} | Bin + ...,42,43.otf => gpos5_font1.default.41,42,43.otf} | Bin + ...,42,44.otf => gpos5_font1.default.41,42,44.otf} | Bin + ...,42,45.otf => gpos5_font1.default.41,42,45.otf} | Bin + ...out.41,42.otf => gpos5_font1.default.41,42.otf} | Bin + ...out.41,43.otf => gpos5_font1.default.41,43.otf} | Bin + ...ep-layout.41.otf => gpos5_font1.default.41.otf} | Bin + ...ep-layout.42.otf => gpos5_font1.default.42.otf} | Bin + ...> gpos5_font1.default.retain-all-codepoint.otf} | Bin + ...otf => gpos5_font1.retain-gids.41,42,43,44.otf} | Bin + ...otf => gpos5_font1.retain-gids.41,42,43,45.otf} | Bin + ...43.otf => gpos5_font1.retain-gids.41,42,43.otf} | Bin + ...44.otf => gpos5_font1.retain-gids.41,42,44.otf} | Bin + ...45.otf => gpos5_font1.retain-gids.41,42,45.otf} | Bin + ...41,42.otf => gpos5_font1.retain-gids.41,42.otf} | Bin + ...41,43.otf => gpos5_font1.retain-gids.41,43.otf} | Bin + ...-gids.41.otf => gpos5_font1.retain-gids.41.otf} | Bin + ...-gids.42.otf => gpos5_font1.retain-gids.42.otf} | Bin + ...os5_font1.retain-gids.retain-all-codepoint.otf} | Bin + ...,44.otf => gpos6_font1.default.41,42,43,44.otf} | Bin + ...,45.otf => gpos6_font1.default.41,42,43,45.otf} | Bin + ...,42,43.otf => gpos6_font1.default.41,42,43.otf} | Bin + ...out.41,42.otf => gpos6_font1.default.41,42.otf} | Bin + ....otf => gpos6_font1.default.41,43,44,45,46.otf} | Bin + ...,43,44.otf => gpos6_font1.default.41,43,44.otf} | Bin + ...,43,45.otf => gpos6_font1.default.41,43,45.otf} | Bin + ...out.41,43.otf => gpos6_font1.default.41,43.otf} | Bin + ...ep-layout.41.otf => gpos6_font1.default.41.otf} | Bin + ...> gpos6_font1.default.retain-all-codepoint.otf} | Bin + ...otf => gpos6_font1.retain-gids.41,42,43,44.otf} | Bin + ...otf => gpos6_font1.retain-gids.41,42,43,45.otf} | Bin + ...43.otf => gpos6_font1.retain-gids.41,42,43.otf} | Bin + ...41,42.otf => gpos6_font1.retain-gids.41,42.otf} | Bin + ... => gpos6_font1.retain-gids.41,43,44,45,46.otf} | Bin + ...44.otf => gpos6_font1.retain-gids.41,43,44.otf} | Bin + ...45.otf => gpos6_font1.retain-gids.41,43,45.otf} | Bin + ...41,43.otf => gpos6_font1.retain-gids.41,43.otf} | Bin + ...-gids.41.otf => gpos6_font1.retain-gids.41.otf} | Bin + ...os6_font1.retain-gids.retain-all-codepoint.otf} | Bin + ...lar.default.627,644,623,62D,644,627,645,2E.ttf} | Bin + ...f => Amiri-Regular.default.627,644,62D,628.ttf} | Bin + ...7,644.ttf => Amiri-Regular.default.627,644.ttf} | Bin + ...Regular.default.633,645,627,621,20,644,627.ttf} | Bin + ...1.ttf => Amiri-Regular.default.63A,64A,631.ttf} | Bin + ...retain-gids.627,644,623,62D,644,627,645,2E.ttf} | Bin + ... Amiri-Regular.retain-gids.627,644,62D,628.ttf} | Bin + ...4.ttf => Amiri-Regular.retain-gids.627,644.ttf} | Bin + ...lar.retain-gids.633,645,627,621,20,644,627.ttf} | Bin + ...f => Amiri-Regular.retain-gids.63A,64A,631.ttf} | Bin + ...1_multiple_subrules_f1.default.30,31,32,33.otf} | Bin + ...ing1_multiple_subrules_f1.default.41,42,43.otf} | Bin + ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin + ...ltiple_subrules_f1.retain-gids.30,31,32,33.otf} | Bin + ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin + ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin + ...2_multiple_subrules_f1.default.30,31,32,33.otf} | Bin + ...ing2_multiple_subrules_f1.default.41,42,43.otf} | Bin + ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin + ...ltiple_subrules_f1.retain-gids.30,31,32,33.otf} | Bin + ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin + ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin + ...os_chaining3_simple_f1.default.30,31,32,33.otf} | Bin + ... gpos_chaining3_simple_f1.default.41,42,43.otf} | Bin + ...ng3_simple_f1.default.retain-all-codepoint.otf} | Bin + ...haining3_simple_f1.retain-gids.30,31,32,33.otf} | Bin + ...s_chaining3_simple_f1.retain-gids.41,42,43.otf} | Bin + ...simple_f1.retain-gids.retain-all-codepoint.otf} | Bin + ...out.41,42.otf => gpos9_font2.default.41,42.otf} | Bin + ...ep-layout.41.otf => gpos9_font2.default.41.otf} | Bin + ...ep-layout.42.otf => gpos9_font2.default.42.otf} | Bin + ...41,42.otf => gpos9_font2.retain-gids.41,42.otf} | Bin + ...-gids.41.otf => gpos9_font2.retain-gids.41.otf} | Bin + ...-gids.42.otf => gpos9_font2.retain-gids.42.otf} | Bin + ...b_alternate_substitution.default.53A9,53F1.otf} | Bin + ...> gsub_alternate_substitution.default.53A9.otf} | Bin + ...> gsub_alternate_substitution.default.53F1.otf} | Bin + ..._substitution.default.retain-all-codepoint.otf} | Bin + ...ternate_substitution.retain-gids.53A9,53F1.otf} | Bin + ...ub_alternate_substitution.retain-gids.53A9.otf} | Bin + ...ub_alternate_substitution.retain-gids.53F1.otf} | Bin + ...stitution.retain-gids.retain-all-codepoint.otf} | Bin + ...ext1_multiple_subrules_f2.default.41,42,43.otf} | Bin + ...ontext1_multiple_subrules_f2.default.41,42.otf} | Bin + ...ontext1_multiple_subrules_f2.default.41,43.otf} | Bin + ...b_context1_multiple_subrules_f2.default.41.otf} | Bin + ...e_subrules_f2.default.retain-all-codepoint.otf} | Bin + ..._multiple_subrules_f2.retain-gids.41,42,43.otf} | Bin + ...xt1_multiple_subrules_f2.retain-gids.41,42.otf} | Bin + ...xt1_multiple_subrules_f2.retain-gids.41,43.otf} | Bin + ...ntext1_multiple_subrules_f2.retain-gids.41.otf} | Bin + ...brules_f2.retain-gids.retain-all-codepoint.otf} | Bin + ...ext2_multiple_subrules_f2.default.41,42,43.otf} | Bin + ...ontext2_multiple_subrules_f2.default.41,42.otf} | Bin + ...ontext2_multiple_subrules_f2.default.41,43.otf} | Bin + ...b_context2_multiple_subrules_f2.default.41.otf} | Bin + ...e_subrules_f2.default.retain-all-codepoint.otf} | Bin + ..._multiple_subrules_f2.retain-gids.41,42,43.otf} | Bin + ...xt2_multiple_subrules_f2.retain-gids.41,42.otf} | Bin + ...xt2_multiple_subrules_f2.retain-gids.41,43.otf} | Bin + ...ntext2_multiple_subrules_f2.retain-gids.41.otf} | Bin + ...brules_f2.retain-gids.retain-all-codepoint.otf} | Bin + ...ub_context3_successive_f1.default.41,42,43.otf} | Bin + ... gsub_context3_successive_f1.default.41,42.otf} | Bin + ... gsub_context3_successive_f1.default.41,43.otf} | Bin + ... => gsub_context3_successive_f1.default.41.otf} | Bin + ...successive_f1.default.retain-all-codepoint.otf} | Bin + ...ontext3_successive_f1.retain-gids.41,42,43.otf} | Bin + ...b_context3_successive_f1.retain-gids.41,42.otf} | Bin + ...b_context3_successive_f1.retain-gids.41,43.otf} | Bin + ...gsub_context3_successive_f1.retain-gids.41.otf} | Bin + ...essive_f1.retain-gids.retain-all-codepoint.otf} | Bin + ...1_multiple_subrules_f1.default.30,31,32,33.otf} | Bin + ...ing1_multiple_subrules_f1.default.41,42,43.otf} | Bin + ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin + ...ltiple_subrules_f1.retain-gids.30,31,32,33.otf} | Bin + ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin + ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin + ...2_multiple_subrules_f1.default.30,31,32,33.otf} | Bin + ...ing2_multiple_subrules_f1.default.41,42,43.otf} | Bin + ...e_subrules_f1.default.retain-all-codepoint.otf} | Bin + ...ltiple_subrules_f1.retain-gids.30,31,32,33.otf} | Bin + ..._multiple_subrules_f1.retain-gids.41,42,43.otf} | Bin + ...brules_f1.retain-gids.retain-all-codepoint.otf} | Bin + ...ub_chaining3_simple_f2.default.30,31,32,33.otf} | Bin + ... gsub_chaining3_simple_f2.default.41,42,43.otf} | Bin + ...ng3_simple_f2.default.retain-all-codepoint.otf} | Bin + ...haining3_simple_f2.retain-gids.30,31,32,33.otf} | Bin + ...b_chaining3_simple_f2.retain-gids.41,42,43.otf} | Bin + ...simple_f2.retain-gids.retain-all-codepoint.otf} | Bin + ...created.default.41,42,43,44,45,46,47,48,49.otf} | Bin + ...ually_created.default.41,42,43,44,45,46,47.otf} | Bin + ...ually_created.default.41,42,43,44,45,46,4D.otf} | Bin + ...ually_created.default.41,42,43,44,45,46,51.otf} | Bin + ...manually_created.default.41,42,43,44,45,46.otf} | Bin + ...=> gsub8_manually_created.default.41,42,43.otf} | Bin + ...1.otf => gsub8_manually_created.default.41.otf} | Bin + ...1.otf => gsub8_manually_created.default.61.otf} | Bin + ...ually_created.default.retain-all-codepoint.otf} | Bin + ...ted.retain-gids.41,42,43,44,45,46,47,48,49.otf} | Bin + ...y_created.retain-gids.41,42,43,44,45,46,47.otf} | Bin + ...y_created.retain-gids.41,42,43,44,45,46,4D.otf} | Bin + ...y_created.retain-gids.41,42,43,44,45,46,51.otf} | Bin + ...ally_created.retain-gids.41,42,43,44,45,46.otf} | Bin + ...sub8_manually_created.retain-gids.41,42,43.otf} | Bin + ...f => gsub8_manually_created.retain-gids.41.otf} | Bin + ...f => gsub8_manually_created.retain-gids.61.otf} | Bin + ...y_created.retain-gids.retain-all-codepoint.otf} | Bin + .../Khmer.keep-layout-retain-gids.1780.ttf | Bin 4464 -> 0 bytes + ...ids.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 7848 -> 0 bytes + .../Khmer.keep-layout-retain-gids.31.ttf | Bin 4256 -> 0 bytes + .../layout.khmer/Khmer.keep-layout.1780.ttf | Bin 4204 -> 0 bytes + ...out.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 6412 -> 0 bytes + .../expected/layout.khmer/Khmer.keep-layout.31.ttf | Bin 4140 -> 0 bytes + ...oNastaliqUrdu-Bold.retain-gids.627,644,62D.ttf} | Bin + ... Roboto-Regular.smallcaps.default.41,42,43.ttf} | Bin + ... => Roboto-Regular.smallcaps.default.41,43.ttf} | Bin + ...ttf => Roboto-Regular.smallcaps.default.41.ttf} | Bin + ...ttf => Roboto-Regular.smallcaps.default.43.ttf} | Bin + ... => Roboto-Regular.smallcaps.default.CA,CB.ttf} | Bin + ...oto-Regular.smallcaps.retain-gids.41,42,43.ttf} | Bin + ...Roboto-Regular.smallcaps.retain-gids.41,43.ttf} | Bin + ...=> Roboto-Regular.smallcaps.retain-gids.41.ttf} | Bin + ...=> Roboto-Regular.smallcaps.retain-gids.43.ttf} | Bin + ...Roboto-Regular.smallcaps.retain-gids.CA,CB.ttf} | Bin + .../Fraunces.keep-layout.26,66,69,124,125.ttf | Bin 18496 -> 0 bytes + .../expected/variable/Fraunces.keep-layout.61.ttf | Bin 5880 -> 0 bytes + .../data/profiles/keep-layout-drop-hints.txt | 2 -- + .../data/profiles/keep-layout-retain-gids.txt | 2 -- + test/subset/data/profiles/keep-layout.txt | 1 - + test/subset/data/tests/basics.tests | 2 -- + test/subset/data/tests/layout.context.tests | 4 ++-- + test/subset/data/tests/layout.gpos.tests | 4 ++-- + test/subset/data/tests/layout.gpos2.tests | 4 ++-- + test/subset/data/tests/layout.gpos3.tests | 4 ++-- + test/subset/data/tests/layout.gpos4.tests | 4 ++-- + test/subset/data/tests/layout.gpos5.tests | 4 ++-- + test/subset/data/tests/layout.gpos6.tests | 4 ++-- + test/subset/data/tests/layout.gpos8.amiri.tests | 4 ++-- + test/subset/data/tests/layout.gpos8.tests | 4 ++-- + test/subset/data/tests/layout.gpos9.tests | 4 ++-- + test/subset/data/tests/layout.gsub3.tests | 4 ++-- + test/subset/data/tests/layout.gsub5.tests | 4 ++-- + test/subset/data/tests/layout.gsub6.tests | 4 ++-- + test/subset/data/tests/layout.gsub8.tests | 4 ++-- + test/subset/data/tests/layout.khmer.tests | 4 ++-- + .../data/tests/layout.notonastaliqurdu.tests | 2 +- + test/subset/data/tests/layout.tests | 4 ++-- + test/subset/data/tests/variable.tests | 2 +- + test/subset/generate-expected-outputs.py | 2 +- + test/subset/run-tests.py | 2 +- + 614 files changed, 36 insertions(+), 46 deletions(-) + +commit 425ba1f4ab4fd1ee0245bc822336d26bd1755c52 +Author: Garret Rieger <grieger@google.com> +Date: Mon Apr 19 18:01:24 2021 -0700 + + [subset] fixes infinite loop in hb_set_get_max(). + + Fixes https://oss-fuzz.com/testcase-detail/5363902507515904 + + src/hb-set.hh | 2 +- + test/api/test-set.c | 7 ++++++- + ...-testcase-minimized-hb-subset-fuzzer-5363902507515904 | Bin 0 -> 1683 bytes + 3 files changed, 7 insertions(+), 2 deletions(-) + +commit ec4321068b9de1ea2730b8a62dda7cb23d064303 +Author: Garret Rieger <grieger@google.com> +Date: Mon Apr 19 17:18:05 2021 -0700 + + [subset] fix infinite loop caused by alloc failure in repacker. + + Fixes: https://oss-fuzz.com/testcase-detail/5609112151916544. + + src/hb-repacker.hh | 8 ++++---- + ...testcase-minimized-hb-subset-fuzzer-5609112151916544 | Bin 0 -> 80225 bytes + 2 files changed, 4 insertions(+), 4 deletions(-) + +commit 0e845d973e2bf15b56cf68af9db778d1258b7709 +Author: Garret Rieger <grieger@google.com> +Date: Mon Apr 19 16:09:37 2021 -0700 + + [subset] fix memory leak in repacker caused by failed alloc. + + Fixes: https://oss-fuzz.com/testcase-detail/5616763250278400. + + src/hb-repacker.hh | 4 +++- + ...testcase-minimized-hb-subset-fuzzer-5616763250278400 | Bin 0 -> 97363 bytes + 2 files changed, 3 insertions(+), 1 deletion(-) + +commit 3fb62cdc141d2d30ba0fc4a173dd50e7c1d56466 +Author: Garret Rieger <grieger@google.com> +Date: Mon Apr 5 15:48:34 2021 -0700 + + [subset] fail on offset overflow in tables that we don't repack. + + Fixes: https://oss-fuzz.com/testcase-detail/5229304507138048 + + src/hb-subset.cc | 5 ++++- + ...testcase-minimized-hb-subset-fuzzer-5229304507138048 | Bin 0 -> 56552 bytes + 2 files changed, 4 insertions(+), 1 deletion(-) + +commit 19e096aa97b1b3af21313df5250a937ddfece7fb +Merge: ed2ee8a8c 23a28f5ad +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Apr 16 14:35:04 2021 -0600 + + Merge pull request #2067 from harfbuzz/null-size + + Avoid undefined-behavior, another try + +commit ed2ee8a8c26dc39e39172c169d8a0d434083fefe +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Apr 16 13:53:43 2021 -0600 + + Revert "Disable -Wunused-macros under GCC" + + This reverts commit 1b1413246b8b4a9c6f7e0aac16afd6d110c142cf. + + Err. It wasn't working. We already have that disabled in the files it + is warning about. Doesn't work. + + src/hb.hh | 1 - + 1 file changed, 1 deletion(-) + +commit 47cbf8f2c49ae82b85bf1edb211ade257f009800 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Mar 30 21:01:44 2021 -0600 + + [test] Silence more compiler warnings + + test/api/test-unicode.c | 3 +++ + 1 file changed, 3 insertions(+) + +commit 1b1413246b8b4a9c6f7e0aac16afd6d110c142cf +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Mar 30 20:54:20 2021 -0600 + + Disable -Wunused-macros under GCC + + Since the pragram in hb-ot-shape-complex-indic-table.cc didn't seem to + silence GCC, eg: + + ../../src/hb-ot-shape-complex-indic-table.cc:55: warning: macro "ISC_TL" is not used [-Wunused-macros] + 55 | #define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */ + + disable it at compiler level. + + src/hb.hh | 1 + + 1 file changed, 1 insertion(+) + +commit 23a28f5ad059a45ff861a06a63d8537dab7f81b7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Apr 16 13:22:05 2021 -0600 + + Avoid undefined-behavior + + If a struct had (because it's a union) sizeof that is larger than the null_size, + we were providing only null_size bytes for its Null object. We know we'd never + access beyond that, but is undefined-behavior nonetheless according to the + standard. + + The alternative fix would have required use of flexible-arrays, which are not + standard and have their own issues in various compiler. We've discussed that + extensively in the follow Mozilla issue (currently locked; I've asked that it + be opened): + + https://bugzilla.mozilla.org/show_bug.cgi?id=1577584 + + Part of + https://github.com/harfbuzz/harfbuzz/pull/2067 + + src/hb-null.hh | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +commit 499248c533eaf88f20920bc438a939989a359956 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Apr 16 13:14:48 2021 -0600 + + [blob] Use min_size, instead of null_size in .as<T>() + + Part of https://github.com/harfbuzz/harfbuzz/pull/2067 + + src/hb-array.hh | 2 +- + src/hb-null.hh | 9 ++++++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +commit a4fb5da984d1dc50e419298a6212a0f53b4f761f +Author: Khaled Hosny <khaled@aliftype.com> +Date: Fri Apr 16 14:10:37 2021 +0200 + + [ci] Enable DirectWrite in win32 tarballs + + .ci/build-win32.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit f2240d12c2a847afda0eb2da635694ca2346de65 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Fri Apr 16 02:37:11 2021 +0200 + + [ci] Use -j2 for make and ninja in distcheck job + + Lets see if this makes it faster without crashing gcc. + + .circleci/config.yml | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit f5c922b7091b9919cd6dbe17db663edb366aea52 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Fri Apr 16 01:47:34 2021 +0200 + + [ci] Try to stop distcheck job from crashing gcc + + .circleci/config.yml | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit e116058bba1f5eb667d211c0c6c0be1bbffc6213 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Thu Apr 15 13:52:19 2021 +0200 + + [directwrite] Use correct UTF-16 string length + + Fixes https://github.com/harfbuzz/harfbuzz/issues/2474 + + src/hb-directwrite.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 668acff1f07ed6bb1472467e59d16399befa68ae +Author: Ben Denckla <bdenckla@alum.mit.edu> +Date: Mon Apr 12 14:25:19 2021 -0400 + + similarly improve comments on Hebrew ccc 18 & 19 + + Should have committed this along with commit 9658435a25c2ba82 but forgot. + + src/hb-ot-shape-fallback.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 43d955207bcfcddbf5a5e3d35819fddb81605be3 +Author: Ben Denckla <bdenckla@alum.mit.edu> +Date: Mon Apr 12 14:01:56 2021 -0400 + + improve comments on Hebrew ccc 18 & 19 + + improve comments to reflect that: + ccc 18 includes both "flavors" of qamats: qamats [gadol] and qamats qatan + ccc 19 includes both "flavors" of holam: holam [not haser for vav] and holam haser for vav + This code and its comments may have been written before these code points were added to Unicode. + I.e. originally, these comments may have been complete, but they may have become incomplete in the meantime. + + src/hb-unicode.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 4cc4cd3b24ded40cfff651ebf63d20d19253c505 +Author: Ambient Lighter <victor@opennodecloud.com> +Date: Sat Apr 10 14:11:23 2021 +0300 + + [docs] Fix spelling typo (#2945) + + docs/usermanual-object-model.xml | 2 +- + perf/texts/en-words.txt | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +commit 9dc9f0385dce05456d48730bf5dc7cac52eaa4da +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Apr 8 11:00:17 2021 -0700 + + [subset] fix for fuzzer testcase: https://oss-fuzz.com/testcase-detail/5858518134554624 + + src/hb-ot-layout-gpos-table.hh | 4 ++++ + ...z-testcase-minimized-hb-subset-fuzzer-5858518134554624 | Bin 0 -> 802 bytes + 2 files changed, 4 insertions(+) + +commit 430a67ceaba5896c850c0a0da80f1bc211c022d8 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Apr 1 12:01:19 2021 -0700 + + [subset] COLRv1 struct definitions + + src/hb-ot-color-colr-table.hh | 479 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 474 insertions(+), 5 deletions(-) + +commit 553ffaf6823040bf4a91bcd4c8e42592cd4d13c2 +Author: Qunxin Liu <qxliu@google.com> +Date: Wed Apr 7 17:15:32 2021 -0700 + + [subset] fix for fuzzer testcase: https://oss-fuzz.com/testcase-detail/6382598554255360 + avoid writing to null pointer + + src/hb-ot-layout-gpos-table.hh | 1 + + 1 file changed, 1 insertion(+) + +commit 4af5dacedc8d45c701c8a559962f1b071419ca50 +Author: Qunxin Liu <qxliu@google.com> +Date: Wed Apr 7 10:56:49 2021 -0700 + + [subset] add fuzzer testcase + + ...z-testcase-minimized-hb-subset-fuzzer-6382598554255360 | Bin 0 -> 766 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +commit 8b686afeb5a7f959d98c0f85844d782c1cbc489f +Author: Garret Rieger <grieger@google.com> +Date: Tue Apr 6 11:33:38 2021 -0700 + + [subset] add unlikely(). + + src/hb-ot-layout-gsubgpos.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 64122b5a443d78cc1c4c0c94fa2e489e1f22dd3e +Author: Garret Rieger <grieger@google.com> +Date: Mon Apr 5 12:53:08 2021 -0700 + + [subset] don't visit lookup if covered glyph set has failed. + + If covered glyph set is in error then the same lookup can be recursed into repeatedly potentially causing a fuzzer timeout. Fixes: https://oss-fuzz.com/testcase-detail/5416421032067072. + + src/hb-ot-layout-gsubgpos.hh | 2 ++ + ...z-testcase-minimized-hb-subset-fuzzer-5416421032067072 | Bin 0 -> 114 bytes + 2 files changed, 2 insertions(+) + +commit 4ec18c85e6eebc0948c29df36fc13b5467fce86b +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 2 15:33:54 2021 -0700 + + [subset] add subsetting tests with drop hints and layout subsetting enabled. + + ...taa-Regular-new.keep-layout-drop-hints.61,62,63.ttf | Bin 0 -> 3444 bytes + ...fortaa-Regular-new.keep-layout-drop-hints.61,63.ttf | Bin 0 -> 3140 bytes + ...Comfortaa-Regular-new.keep-layout-drop-hints.61.ttf | Bin 0 -> 2804 bytes + ...Comfortaa-Regular-new.keep-layout-drop-hints.62.ttf | Bin 0 -> 2396 bytes + ...Comfortaa-Regular-new.keep-layout-drop-hints.63.ttf | Bin 0 -> 2464 bytes + ...new.keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 0 -> 187944 bytes + ...-Regular-subset.keep-layout-drop-hints.61,62,63.ttf | Bin 0 -> 1452 bytes + ...gjo-Regular-subset.keep-layout-drop-hints.61,63.ttf | Bin 0 -> 1276 bytes + ...eongjo-Regular-subset.keep-layout-drop-hints.61.ttf | Bin 0 -> 1128 bytes + ...eongjo-Regular-subset.keep-layout-drop-hints.62.ttf | Bin 0 -> 1140 bytes + ...eongjo-Regular-subset.keep-layout-drop-hints.63.ttf | Bin 0 -> 1104 bytes + ...set.keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 0 -> 3536 bytes + ...oto-Regular.abc.keep-layout-drop-hints.61,62,63.ttf | Bin 0 -> 1208 bytes + ...Roboto-Regular.abc.keep-layout-drop-hints.61,63.ttf | Bin 0 -> 1120 bytes + .../Roboto-Regular.abc.keep-layout-drop-hints.61.ttf | Bin 0 -> 988 bytes + .../Roboto-Regular.abc.keep-layout-drop-hints.62.ttf | Bin 0 -> 876 bytes + .../Roboto-Regular.abc.keep-layout-drop-hints.63.ttf | Bin 0 -> 960 bytes + ...abc.keep-layout-drop-hints.retain-all-codepoint.ttf | Bin 0 -> 1208 bytes + test/subset/data/profiles/keep-layout-drop-hints.txt | 2 ++ + test/subset/data/tests/basics.tests | 1 + + 20 files changed, 3 insertions(+) + +commit 6f98a8ed4627b662d9591649328d2d302fc01987 +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 2 14:37:10 2021 -0700 + + [subset] Anchor should only use format 1 when hints are dropped. + + Refactor Anchor to have a subset method instead of copy. This also allows + use to use serialize_subset in several places which simplifies calculating + offset bases. + + src/hb-ot-layout-gpos-table.hh | 189 +++++++++++++++++++++-------------------- + 1 file changed, 95 insertions(+), 94 deletions(-) + +commit 71d6d1560035619ee685dc9aa626eeefabe5e9f1 +Author: Garret Rieger <grieger@google.com> +Date: Mon Apr 5 12:03:17 2021 -0700 + + [subset] clamp distance to prevent shifting outside of the limits of int64. + + Fixes https://oss-fuzz.com/testcase-detail/4961171477233664. + + src/hb-repacker.hh | 3 ++- + ...testcase-minimized-hb-subset-fuzzer-4961171477233664 | Bin 0 -> 39793 bytes + 2 files changed, 2 insertions(+), 1 deletion(-) + +commit fcacd17748b85a56ff0c1d822295bfcbd8e175a2 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Mon Apr 5 22:27:39 2021 +0200 + + [ot] Update _hb_glyph_info_is_default_ignorable_and_not_hidden() + + Used _hb_glyph_info_substituted() similar to the change made to + _hb_glyph_info_is_default_ignorable() in + 7686ff854bbb9698bb1469dcfe6d288c695a76b7. + + src/hb-ot-layout.hh | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 596f4258d0b6464a8186263625a2da1b16014bdd +Author: Garret Rieger <grieger@google.com> +Date: Fri Apr 2 12:41:09 2021 -0700 + + [subset] copy Lookup::markFilteringSet when subseting. + + src/hb-ot-layout-common.hh | 8 ++++++++ + .../Comfortaa-Regular-new.keep-layout.61,62,63.ttf | Bin 0 -> 8100 bytes + .../basics/Comfortaa-Regular-new.keep-layout.61,63.ttf | Bin 0 -> 7736 bytes + .../basics/Comfortaa-Regular-new.keep-layout.61.ttf | Bin 0 -> 7360 bytes + .../basics/Comfortaa-Regular-new.keep-layout.62.ttf | Bin 0 -> 6796 bytes + .../basics/Comfortaa-Regular-new.keep-layout.63.ttf | Bin 0 -> 6844 bytes + ...aa-Regular-new.keep-layout.retain-all-codepoint.ttf | Bin 0 -> 222212 bytes + ...numMyeongjo-Regular-subset.keep-layout.61,62,63.ttf | Bin 0 -> 4128 bytes + .../NanumMyeongjo-Regular-subset.keep-layout.61,63.ttf | Bin 0 -> 3580 bytes + .../NanumMyeongjo-Regular-subset.keep-layout.61.ttf | Bin 0 -> 3156 bytes + .../NanumMyeongjo-Regular-subset.keep-layout.62.ttf | Bin 0 -> 3180 bytes + .../NanumMyeongjo-Regular-subset.keep-layout.63.ttf | Bin 0 -> 3048 bytes + ...Regular-subset.keep-layout.retain-all-codepoint.ttf | Bin 0 -> 9524 bytes + .../basics/Roboto-Regular.abc.keep-layout.61,62,63.ttf | Bin 0 -> 2452 bytes + .../basics/Roboto-Regular.abc.keep-layout.61,63.ttf | Bin 0 -> 2260 bytes + .../basics/Roboto-Regular.abc.keep-layout.61.ttf | Bin 0 -> 2048 bytes + .../basics/Roboto-Regular.abc.keep-layout.62.ttf | Bin 0 -> 1916 bytes + .../basics/Roboto-Regular.abc.keep-layout.63.ttf | Bin 0 -> 1972 bytes + ...to-Regular.abc.keep-layout.retain-all-codepoint.ttf | Bin 0 -> 2452 bytes + test/subset/data/tests/basics.tests | 1 + + 20 files changed, 9 insertions(+) + +commit d3a2f999e4d5c83e14f6380b780aab170d9cbd39 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Apr 2 08:32:41 2021 -0600 + + Fix up build + + This was left out; oops. + + src/hb-set-digest.hh | 8 ++++++++ + 1 file changed, 8 insertions(+) + +commit c35d7863979f2395140d70cda49a19857b98f515 +Author: Garret Rieger <grieger@google.com> +Date: Thu Apr 1 14:32:38 2021 -0700 + + [subset] never drop the 'pref' feature. + + Never ever drop feature 'pref', even if it's empty. Harfbuzz uses it to choose the shaper for Khmer. + + src/hb-ot-layout-gsubgpos.hh | 7 +++++++ + test/subset/data/Makefile.am | 1 + + test/subset/data/Makefile.sources | 1 + + .../layout.khmer/Khmer.keep-layout-retain-gids.1780.ttf | Bin 0 -> 4464 bytes + ...ain-gids.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 0 -> 7848 bytes + .../layout.khmer/Khmer.keep-layout-retain-gids.31.ttf | Bin 0 -> 4256 bytes + .../expected/layout.khmer/Khmer.keep-layout.1780.ttf | Bin 0 -> 4204 bytes + ...p-layout.1789,17BB,17C6,1794,17B6,1793,1798,17BE.ttf | Bin 0 -> 6412 bytes + .../data/expected/layout.khmer/Khmer.keep-layout.31.ttf | Bin 0 -> 4140 bytes + test/subset/data/fonts/Khmer.ttf | Bin 0 -> 75368 bytes + test/subset/data/tests/layout.khmer.tests | 11 +++++++++++ + test/subset/meson.build | 1 + + 12 files changed, 21 insertions(+) + +commit 092094f7055c1632e9bdf2c07f16e984a88a65ec +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Apr 1 15:47:21 2021 -0600 + + Use as_array() and range loops in a few places + + src/hb-ot-cmap-table.hh | 17 +++++++---------- + src/hb-ot-layout-common.hh | 26 +++++++++----------------- + src/hb-set.hh | 4 ++++ + 3 files changed, 20 insertions(+), 27 deletions(-) + +commit 55e7f3fe329021c77c880f1f3fd6d082f4ac27da +Author: Garret Rieger <grieger@google.com> +Date: Thu Apr 1 13:35:30 2021 -0700 + + [subset] Match FeatureVariationRecord dropping from fontTools. + + Only drop records with no matching features that are at the end of the list. See: https://github.com/fonttools/fonttools/commit/cab7d13dc0883765cde435215c7d65e9212f152d + + src/hb-ot-layout-common.hh | 36 ++++++++++++++++++++++++++++++------ + 1 file changed, 30 insertions(+), 6 deletions(-) + +commit f0c78e028261a7823194cccc7be241aa9ddbac25 +Author: Garret Rieger <grieger@google.com> +Date: Thu Mar 25 12:57:12 2021 -0700 + + [subset] don't drop features referenced in a feature variation substitution. + + src/hb-ot-layout-common.hh | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +commit dae99b7769616d354e8cce41fbd7cf780353cb44 +Author: Garret Rieger <grieger@google.com> +Date: Thu Mar 25 12:33:51 2021 -0700 + + [subset] don't keep FeatureVariationRecord's with no subsittutions. + + src/hb-ot-layout-common.hh | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +commit 85b07287838440e000622c53cee9cc911ad0de6d +Author: Garret Rieger <grieger@google.com> +Date: Thu Mar 25 12:17:18 2021 -0700 + + Add full variable font subsetting test. + + test/subset/data/Makefile.am | 1 + + test/subset/data/Makefile.sources | 1 + + .../variable/Fraunces.keep-layout.26,66,69,124,125.ttf | Bin 0 -> 18496 bytes + .../data/expected/variable/Fraunces.keep-layout.61.ttf | Bin 0 -> 5880 bytes + test/subset/data/fonts/Fraunces.ttf | Bin 0 -> 360440 bytes + test/subset/data/tests/variable.tests | 9 +++++++++ + test/subset/meson.build | 1 + + 7 files changed, 12 insertions(+) + +commit c4b49075f62eaa11799c95099a70acbb70e566c9 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Apr 1 10:47:18 2021 -0700 + + Update CMakeLists.txt + + Keep the warning. + + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 9945f327463066957f2677237d468651235a1f3d +Author: Timo Suoranta <timo.suoranta@varjo.com> +Date: Sat Feb 6 14:24:25 2021 +0200 + + Test fix to export target include directories + + CMakeLists.txt | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +commit b10741ca7f4cd55526f303c47c72f0a5c1a932fe +Author: Garret Rieger <grieger@google.com> +Date: Thu Mar 25 19:14:48 2021 -0700 + + [subset] when closing glyphs in context lookups don't use a current glyph set if a lookup is already applied. + + src/hb-ot-layout-gsubgpos.hh | 12 ++++++++---- + ...ayout-retain-gids.627,644,623,62D,644,627,645,2E.ttf | Bin 18272 -> 0 bytes + ...rdu-Bold.keep-layout-retain-gids.627,644,62D,628.ttf | Bin 24416 -> 0 bytes + ...liqUrdu-Bold.keep-layout-retain-gids.627,644,62D.ttf | Bin 0 -> 11532 bytes + ...astaliqUrdu-Bold.keep-layout-retain-gids.627,644.ttf | Bin 9216 -> 0 bytes + ...ep-layout-retain-gids.633,645,627,621,20,644,627.ttf | Bin 18212 -> 0 bytes + ...liqUrdu-Bold.keep-layout-retain-gids.63A,64A,631.ttf | Bin 26628 -> 0 bytes + ...-Bold.keep-layout.627,644,623,62D,644,627,645,2E.ttf | Bin 11436 -> 0 bytes + ...otoNastaliqUrdu-Bold.keep-layout.627,644,62D,628.ttf | Bin 18288 -> 0 bytes + .../NotoNastaliqUrdu-Bold.keep-layout.627,644.ttf | Bin 3568 -> 0 bytes + ...Urdu-Bold.keep-layout.633,645,627,621,20,644,627.ttf | Bin 12408 -> 0 bytes + .../NotoNastaliqUrdu-Bold.keep-layout.63A,64A,631.ttf | Bin 20408 -> 0 bytes + test/subset/data/tests/layout.notonastaliqurdu.tests | 7 +------ + 13 files changed, 9 insertions(+), 10 deletions(-) + +commit 2773d057403292e4a13e13ca12912437607b9d86 +Author: Garret Rieger <grieger@google.com> +Date: Wed Nov 4 11:11:16 2020 -0800 + + [subset] Add a test case using NotoNastaliqUrdu. + + test/subset/data/Makefile.am | 1 + + test/subset/data/Makefile.sources | 1 + + ...ayout-retain-gids.627,644,623,62D,644,627,645,2E.ttf | Bin 0 -> 18272 bytes + ...rdu-Bold.keep-layout-retain-gids.627,644,62D,628.ttf | Bin 0 -> 24416 bytes + ...astaliqUrdu-Bold.keep-layout-retain-gids.627,644.ttf | Bin 0 -> 9216 bytes + ...ep-layout-retain-gids.633,645,627,621,20,644,627.ttf | Bin 0 -> 18212 bytes + ...liqUrdu-Bold.keep-layout-retain-gids.63A,64A,631.ttf | Bin 0 -> 26628 bytes + ...-Bold.keep-layout.627,644,623,62D,644,627,645,2E.ttf | Bin 0 -> 11436 bytes + ...otoNastaliqUrdu-Bold.keep-layout.627,644,62D,628.ttf | Bin 0 -> 18288 bytes + .../NotoNastaliqUrdu-Bold.keep-layout.627,644.ttf | Bin 0 -> 3568 bytes + ...Urdu-Bold.keep-layout.633,645,627,621,20,644,627.ttf | Bin 0 -> 12408 bytes + .../NotoNastaliqUrdu-Bold.keep-layout.63A,64A,631.ttf | Bin 0 -> 20408 bytes + test/subset/data/tests/layout.notonastaliqurdu.tests | 13 +++++++++++++ + test/subset/meson.build | 1 + + 14 files changed, 16 insertions(+) + +commit 8ef4257dc8d6b59b55d0169b66c8de135d5f199b +Author: Garret Rieger <grieger@google.com> +Date: Wed Mar 31 15:00:46 2021 -0700 + + [sanitize] change max ops to track number of bytes processed. + + Counting bytes as the operations is likely to be a better proxy for how + much work processing the table will cost vs. the current approach of + counting the number of sub-objects. + + This should allow checks for max features, max scripts, etc. to be removed. + + I tested this change against the full collection of fonts at https://github.com/google/fonts + and a max ops factor of 3 was sufficient to successfully sanitize all of them. + + src/hb-sanitize.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 70110f6aaac541bc157eb5612b476d3b906b5d2a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 17:04:02 2021 -0600 + + Modify OffsetTo<>::sanitize() overflow check + + The code in question was introduced in 70eb2ff682. + Rewrite it to not call sanitizer check_range() as we want to use + check_range() for byte accounting. + + Part of https://github.com/harfbuzz/harfbuzz/pull/2923 + + src/hb-open-type.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 4dba749d833491ec0c73fb4647f55236be1caee3 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 16:09:39 2021 -0600 + + Add SortedArray{16,32}Of<> + + src/hb-open-type.hh | 5 ++++- + src/hb-ot-cmap-table.hh | 10 +++++----- + src/hb-ot-color-svg-table.hh | 2 +- + src/hb-ot-layout-base-table.hh | 8 ++++---- + src/hb-ot-layout-common.hh | 8 ++++---- + src/hb-ot-layout-jstf-table.hh | 2 +- + src/hb-ot-vorg-table.hh | 2 +- + 7 files changed, 20 insertions(+), 17 deletions(-) + +commit 5639e253f91bd71cdb626719ebc5b8d68631cc73 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 16:04:43 2021 -0600 + + Add Array16Of<> + + src/hb-aat-layout-common.hh | 2 +- + src/hb-aat-layout-just-table.hh | 2 +- + src/hb-open-type.hh | 6 ++-- + src/hb-ot-gasp-table.hh | 2 +- + src/hb-ot-layout-common.hh | 12 +++---- + src/hb-ot-layout-gdef-table.hh | 4 +-- + src/hb-ot-layout-gpos-table.hh | 8 ++--- + src/hb-ot-layout-gsub-table.hh | 20 +++++------ + src/hb-ot-layout-gsubgpos.hh | 54 +++++++++++++++--------------- + src/hb-ot-math-table.hh | 10 +++--- + src/hb-ot-post-table.hh | 4 +-- + src/hb-ot-shape-complex-arabic-fallback.hh | 2 +- + src/hb-ot-var-avar-table.hh | 2 +- + 13 files changed, 64 insertions(+), 64 deletions(-) + +commit 2520a82df9116fbc287cec1be66d05874c467bbb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 15:34:26 2021 -0600 + + s/LArrayOf/Array32Of/g + + src/hb-aat-layout-ankr-table.hh | 2 +- + src/hb-aat-layout-just-table.hh | 2 +- + src/hb-aat-ltag-table.hh | 2 +- + src/hb-open-file.hh | 4 ++-- + src/hb-open-type.hh | 4 ++-- + src/hb-ot-color-cbdt-table.hh | 8 ++++---- + src/hb-ot-layout-common.hh | 2 +- + src/hb-ot-meta-table.hh | 2 +- + 8 files changed, 13 insertions(+), 13 deletions(-) + +commit 5efe3609865b450305474b9abe672905bd25cc06 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 15:33:22 2021 -0600 + + Rename (Unsized)OffsetListOf + + src/hb-aat-layout-morx-table.hh | 4 ++-- + src/hb-open-type.hh | 6 +++--- + src/hb-ot-layout-common.hh | 8 ++++---- + src/hb-ot-layout-gpos-table.hh | 2 +- + src/hb-ot-layout-gsubgpos.hh | 2 +- + src/hb-ot-layout-jstf-table.hh | 6 +++--- + 6 files changed, 14 insertions(+), 14 deletions(-) + +commit 6c4e0491d7ebdc41318db59c4b0911212b299341 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 15:31:32 2021 -0600 + + s/OffsetArrayOf/Array16OfOffset16To/g + + src/hb-open-type.hh | 6 ++--- + src/hb-ot-layout-base-table.hh | 2 +- + src/hb-ot-layout-common.hh | 8 +++---- + src/hb-ot-layout-gdef-table.hh | 6 ++--- + src/hb-ot-layout-gpos-table.hh | 2 +- + src/hb-ot-layout-gsub-table.hh | 26 ++++++++++---------- + src/hb-ot-layout-gsubgpos.hh | 54 +++++++++++++++++++++--------------------- + 7 files changed, 52 insertions(+), 52 deletions(-) + +commit 1fc6b69aed28aa768b65a8cf0825b79aa851a71f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 15:30:35 2021 -0600 + + s/UnsizedOffsetArrayOf/UnsizedArray16OfOffsetTo/g + + src/hb-open-type.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 2a54c9f744b195bb1412573afcc36db806d20a4b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 15:26:42 2021 -0600 + + . + + src/hb-open-type.hh | 9 +++------ + src/hb-ot-color-sbix-table.hh | 4 ++-- + src/hb-ot-layout-common.hh | 4 ++-- + 3 files changed, 7 insertions(+), 10 deletions(-) + +commit c539afb08b1b698216541087b1eec222472699ea +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 13:28:25 2021 -0600 + + [CFF] Use NNOffsetTo<> instead of OffsetTo<> + + I'm pretty sure that's what is intended. + + src/hb-ot-cff1-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 9b4b58493b7e4c15565e4a47118181d96f517fae +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 13:27:21 2021 -0600 + + Fixup for recent OffsetTo<> changes + + src/hb-open-type.hh | 2 +- + src/hb-ot-layout-gsubgpos.hh | 8 ++++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +commit ad28f973f3ec6184b4c405efc0e17fba87b51062 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 12:49:14 2021 -0600 + + Rename offset types to be explicit about their size + + Add Offset16To<>, Offset24To<>, and Offset32To<> for most use-cases. + + src/hb-aat-layout-ankr-table.hh | 6 +-- + src/hb-aat-layout-common.hh | 2 +- + src/hb-aat-layout-feat-table.hh | 2 +- + src/hb-aat-layout-just-table.hh | 12 ++--- + src/hb-aat-layout-kerx-table.hh | 14 +++--- + src/hb-aat-layout-opbd-table.hh | 8 ++-- + src/hb-aat-layout-trak-table.hh | 8 ++-- + src/hb-aat-ltag-table.hh | 2 +- + src/hb-open-file.hh | 12 ++--- + src/hb-open-type.hh | 14 +++--- + src/hb-ot-cmap-table.hh | 6 +-- + src/hb-ot-color-cbdt-table.hh | 4 +- + src/hb-ot-color-colr-table.hh | 4 +- + src/hb-ot-color-cpal-table.hh | 8 ++-- + src/hb-ot-color-sbix-table.hh | 4 +- + src/hb-ot-color-svg-table.hh | 4 +- + src/hb-ot-layout-base-table.hh | 28 ++++++------ + src/hb-ot-layout-common.hh | 22 +++++----- + src/hb-ot-layout-gdef-table.hh | 24 +++++----- + src/hb-ot-layout-gpos-table.hh | 70 +++++++++++++++--------------- + src/hb-ot-layout-gsub-table.hh | 14 +++--- + src/hb-ot-layout-gsubgpos.hh | 64 +++++++++++++-------------- + src/hb-ot-layout-jstf-table.hh | 24 +++++----- + src/hb-ot-math-table.hh | 34 +++++++-------- + src/hb-ot-meta-table.hh | 2 +- + src/hb-ot-name-table.hh | 4 +- + src/hb-ot-shape-complex-arabic-fallback.hh | 2 +- + src/hb-ot-stat-table.hh | 8 ++-- + src/hb-ot-var-fvar-table.hh | 2 +- + src/hb-ot-var-gvar-table.hh | 6 +-- + src/hb-ot-var-hvar-table.hh | 10 ++--- + src/hb-ot-var-mvar-table.hh | 2 +- + 32 files changed, 214 insertions(+), 212 deletions(-) + +commit c5c13006a1f8e5fb9b28a3c2081e93eb4e5d4c98 +Author: Garret Rieger <grieger@google.com> +Date: Wed Mar 31 11:23:46 2021 -0700 + + [subset] fix memory leaks found in https://oss-fuzz.com/testcase-detail/5179935334465536 + + src/hb-repacker.hh | 3 ++- + src/hb-vector.hh | 5 +++++ + ...testcase-minimized-hb-subset-fuzzer-5179935334465536 | Bin 0 -> 50501 bytes + 3 files changed, 7 insertions(+), 1 deletion(-) + +commit bd2950b3939d88fed998717b05367651153dc21b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 11:36:36 2021 -0600 + + Make VariationStore::get_delta(outer, inner) private + + src/hb-ot-layout-common.hh | 2 ++ + 1 file changed, 2 insertions(+) + +commit 934675a42958ba2e4e3e10aa4b55a9e772977399 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 11:34:41 2021 -0600 + + Use VarIdx in VariationDevice + + src/hb-ot-layout-common.hh | 17 +++++++---------- + 1 file changed, 7 insertions(+), 10 deletions(-) + +commit 0f7f7536b9d98e65f345398529da9c6bc365a3fb +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 11:31:49 2021 -0600 + + [hvar] Change variation-index types from "unsigned int" to uint32_t + + src/hb-ot-var-hvar-table.hh | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +commit 9ffc46b8ff5546998fc9b74cb54dec8618ed0ac7 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 11:26:18 2021 -0600 + + Add VarIdx + + src/hb-open-type.hh | 6 ++++++ + src/hb-static.cc | 1 + + 2 files changed, 7 insertions(+) + +commit 2179281c406452392a2d9c7e17b81e02735fe50b +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 31 11:20:21 2021 -0600 + + Add Offset24 + + src/hb-open-type.hh | 1 + + 1 file changed, 1 insertion(+) + +commit b3159ed8d2dbe4af584d05298448e6de62d394d6 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Mar 30 20:52:56 2021 -0600 + + [util] Silence compiler warning + + util/helper-cairo.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit cab9d5a57dc56c47ba4db51b813fac618694c9a9 +Author: Andrzej Perczak <kartapolska@gmail.com> +Date: Fri Mar 19 22:10:50 2021 +0100 + + hb-config: Include config-override earlier + + Currently config-override.h is included at the end of this file. This caused a problem for me while undefing HB_DISABLE_DEPRECATED, namely HB_IF_NOT_DEPRECATED was defined before actual undef took place and broke the whole build. I believe it would break builds for some other defines, too. Moving config-override.h include right after predefined configs is more sane and fixes all potential problems with includes. + + src/hb-config.hh | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +commit adca4ce071d12998deea6bb53b223daa3aa163c5 +Author: Garret Rieger <grieger@google.com> +Date: Tue Mar 30 13:20:50 2021 -0700 + + [subset] fixes https://oss-fuzz.com/testcase-detail/6173520787800064. + + Caused by incorrect bounds check in glyph closure for context lookups. + + src/hb-ot-layout-gsubgpos.hh | 2 +- + ...-testcase-minimized-hb-subset-fuzzer-6173520787800064 | Bin 0 -> 1731 bytes + 2 files changed, 1 insertion(+), 1 deletion(-) + +commit 9f77a0c1ff02765862d6d2bfed6b9aab78db6fff +Author: Garret Rieger <grieger@google.com> +Date: Tue Mar 30 14:10:45 2021 -0700 + + [subset] use hb_set_clear to avoid calling clear() on null pool set. + + src/hb-ot-layout-gsubgpos.hh | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 752e393ad2f5ec4f7faae84f5322fbef41ddb2ab +Author: Garret Rieger <grieger@google.com> +Date: Mon Mar 29 17:23:33 2021 -0700 + + [subset] avoid calling clear on null pool set. + + src/hb-ot-layout-gsubgpos.hh | 3 ++- + ...z-testcase-minimized-hb-subset-fuzzer-5617065093365760 | Bin 0 -> 160 bytes + 2 files changed, 2 insertions(+), 1 deletion(-) + +commit 9ed5f04a7092c76744076ba65673b250aee22dcd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Mar 29 18:14:30 2021 -0600 + + [subset] Simplify recent out-of-memory fixes + + By checking return status of map->set(). + + src/hb-ot-layout-common.hh | 8 ++++---- + src/hb-ot-layout-gsubgpos.hh | 12 ++++++------ + 2 files changed, 10 insertions(+), 10 deletions(-) + +commit a8f9f85a919543ce79b5a7d5df90c132830ae772 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Mar 29 18:12:05 2021 -0600 + + [map] Return success from ->set() + + src/hb-map.hh | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +commit 8741914a8043757d4800b14192980fbc1ea24492 +Author: Garret Rieger <grieger@google.com> +Date: Mon Mar 29 16:39:44 2021 -0700 + + [subset] fix memory leak when map insert fails. + + src/hb-ot-layout-common.hh | 17 ++++++++++++----- + ...estcase-minimized-hb-subset-fuzzer-6421315436281856 | Bin 0 -> 59 bytes + 2 files changed, 12 insertions(+), 5 deletions(-) + +commit 2397689387419f9a86b928ea5084b2318d136ac6 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Mar 29 17:34:23 2021 -0600 + + Remove hb_success_t + + Was not rolled-out yet. So just expand. + + src/hb-open-type.hh | 4 ++-- + src/hb.hh | 1 - + 2 files changed, 2 insertions(+), 3 deletions(-) + +commit 7a2eda7817a26e017c9da3db4700a24dde550dde +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Mar 29 17:32:29 2021 -0600 + + Move code around + + src/hb-open-type.hh | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +commit bcb57dccaabad4275ab96b14123413bbec6d0fec +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Mar 29 17:31:09 2021 -0600 + + [sanitize] Add short-circuit to ArrayOfM1 + + Like the sibling ArrayOf types. + + src/hb-open-type.hh | 1 + + 1 file changed, 1 insertion(+) + +commit 5b6da6d2f0bcaeb7768705e6891f575ae73c8b41 +Author: Garret Rieger <grieger@google.com> +Date: Mon Mar 29 16:19:17 2021 -0700 + + [subset] add fuzzer test case. + + ...z-testcase-minimized-hb-subset-fuzzer-5250795600740352 | Bin 0 -> 409 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +commit 52df6b9fd8cf075f416372f0469a6915e814b0d6 +Author: Garret Rieger <grieger@google.com> +Date: Mon Mar 29 16:17:27 2021 -0700 + + [subset] check for set insertion success. + + src/hb-ot-layout-gsubgpos.hh | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +commit c6adb90a273f22159b0775f798724d36d552d36c +Author: Garret Rieger <grieger@google.com> +Date: Mon Mar 29 16:08:44 2021 -0700 + + [subset] fix nullptr deref. + + src/hb-ot-layout-gsubgpos.hh | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +commit 9a3537e5f688637a2ac2ced57de9e2b7c21d90a5 +Author: Garret Rieger <grieger@google.com> +Date: Mon Mar 29 14:34:24 2021 -0700 + + [subset] invert err() return value. Undo previous change to check_success. + + src/hb-serialize.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit a804a0c903f6dd230954ff5855ed7ff1dd92844d +Author: Garret Rieger <grieger@google.com> +Date: Mon Mar 29 14:25:20 2021 -0700 + + [subset] add fuzzer test case. + + ...-testcase-minimized-hb-subset-fuzzer-5887968763052032 | Bin 0 -> 3889 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +commit cdba5d44c28a97ab8d9298a3bef60fcbd0845000 +Author: Garret Rieger <grieger@google.com> +Date: Mon Mar 29 14:23:59 2021 -0700 + + [subset] fix incorrect handling of return value in check_success in the error case. + + src/hb-serialize.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 05e845c49ad2eebf110dcc6cb0ee48a7f68ca233 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Mar 29 16:02:10 2021 -0700 + + Make previous commit gcc-only + + src/hb.hh | 2 ++ + 1 file changed, 2 insertions(+) + +commit b5e40323921566ce8a15aa7808d22d36acac4edd +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Mar 29 15:54:40 2021 -0700 + + -Wno-unused-result + + GCC doesn't let one turn off the warning using "(void) foo()". + People have introduced macros that do "unused << foo()" instead. + Until we do something similar, silence gcc. + + Clang on the other hand understands "(void) foo()". + + src/hb.hh | 1 + + 1 file changed, 1 insertion(+) + +commit c30349d54e67c1ee7e1ea759e8378fcf6a6c9ff4 +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun Mar 21 20:12:59 2021 +0200 + + [hb-view] Support kitty inline images protocol + + https://github.com/harfbuzz/harfbuzz/issues/2758 + + util/helper-cairo.cc | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +commit f7d5889b3ea9012d23407b83a176bcd54a94e21b +Author: Khaled Hosny <khaled@aliftype.com> +Date: Sun Mar 21 18:16:33 2021 +0200 + + [hb-view] Support iTerm2 inline images protocol + + https://github.com/harfbuzz/harfbuzz/issues/2758 + + util/helper-cairo.cc | 85 +++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 78 insertions(+), 7 deletions(-) + +commit 743baf35436d8de937984e09467f453cdfba102e +Author: Khaled Hosny <khaled@aliftype.com> +Date: Mon Mar 22 15:51:17 2021 +0200 + + [build] Don’t look for FontConfig + + We don’t currently use it anywhere. It was used briefly for the + hb-fc-list tool, but this tool have not been built since 2015: + + commit cd042fc8c4a3984c3647cd22a27c34f00636f6e8 + Author: Behdad Esfahbod <behdad@behdad.org> + Date: Thu Jun 18 10:55:13 2015 -0700 + + [util] Disable hb-fc-list for now + + Until I figure out what to do about the API, and finalize + the tool. + + .circleci/config.yml | 2 +- + Makefile.am | 1 - + configure.ac | 19 ------------------- + docs/usermanual-install-harfbuzz.xml | 20 -------------------- + meson.build | 7 ------- + meson_options.txt | 2 -- + subprojects/.gitignore | 1 - + subprojects/fontconfig.wrap | 6 ------ + 8 files changed, 1 insertion(+), 57 deletions(-) + +commit 95230e291dddc20185e6a34b69836631d894c0d8 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Mar 18 17:41:25 2021 -0700 + + [subset] support subsetting GSUB8 + + src/hb-ot-layout-gsub-table.hh | 73 ++++++++++++++++++++- + test/subset/data/Makefile.am | 1 + + test/subset/data/Makefile.sources | 1 + + ...yout-retain-gids.41,42,43,44,45,46,47,48,49.otf | Bin 0 -> 3172 bytes + ...eep-layout-retain-gids.41,42,43,44,45,46,47.otf | Bin 0 -> 2796 bytes + ...eep-layout-retain-gids.41,42,43,44,45,46,4D.otf | Bin 0 -> 2860 bytes + ...eep-layout-retain-gids.41,42,43,44,45,46,51.otf | Bin 0 -> 2864 bytes + ...d.keep-layout-retain-gids.41,42,43,44,45,46.otf | Bin 0 -> 2540 bytes + ...ly_created.keep-layout-retain-gids.41,42,43.otf | Bin 0 -> 1984 bytes + ...manually_created.keep-layout-retain-gids.41.otf | Bin 0 -> 1872 bytes + ...manually_created.keep-layout-retain-gids.61.otf | Bin 0 -> 2584 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3832 bytes + ...ated.keep-layout.41,42,43,44,45,46,47,48,49.otf | Bin 0 -> 2384 bytes + ...ly_created.keep-layout.41,42,43,44,45,46,47.otf | Bin 0 -> 1996 bytes + ...ly_created.keep-layout.41,42,43,44,45,46,4D.otf | Bin 0 -> 1996 bytes + ...ly_created.keep-layout.41,42,43,44,45,46,51.otf | Bin 0 -> 2044 bytes + ...ually_created.keep-layout.41,42,43,44,45,46.otf | Bin 0 -> 1832 bytes + ...gsub8_manually_created.keep-layout.41,42,43.otf | Bin 0 -> 1284 bytes + .../gsub8_manually_created.keep-layout.41.otf | Bin 0 -> 1172 bytes + .../gsub8_manually_created.keep-layout.61.otf | Bin 0 -> 1540 bytes + ...ly_created.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3832 bytes + test/subset/data/fonts/gsub8_manually_created.otf | Bin 0 -> 4824 bytes + test/subset/data/tests/layout.gsub8.tests | 17 +++++ + test/subset/meson.build | 1 + + 24 files changed, 91 insertions(+), 2 deletions(-) + +commit d18915f920a0d9ab7ce5cfec4654d3d610b1d082 +Author: David Corbett <corbett.dav@northeastern.edu> +Date: Sun Mar 28 10:09:13 2021 -0400 + + Reformat gen-tag-table.py + + src/gen-tag-table.py | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +commit 3c8273ab68e37ed5b08b4edacac995fc451d5732 +Author: Garret Rieger <grieger@google.com> +Date: Thu Mar 25 11:39:57 2021 -0700 + + Check for alloc failures on the gsub/gpos_langsys maps in subset plan creation. + + src/hb-subset-plan.cc | 46 ++++++++++++++++++++++++++++------------------ + src/hb-subset.cc | 4 +++- + 2 files changed, 31 insertions(+), 19 deletions(-) + +commit 29708e959a04ee003b9c0738f0c5330584f15b4f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Mar 22 15:22:15 2021 -0700 + + [aat] Fix offsetToIndex math for out-of-bounds values + + Previously, some bad font data was accidentally being interpretted as + legit if it happened to not fall out of memory bounds. The intention + of the code was what this commit does. I'm surprised we weren't getting + a "arithmetic between signed and unsigned values" warning / error + before. + + src/hb-aat-layout-common.hh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit c5d6bdb4bf2d8d595f5c762c3e618444621803ae +Merge: a7d120aea 46bf03d69 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Thu Mar 18 14:38:55 2021 -0700 + + Merge pull request #2857 from googlefonts/repacker + + [subset] add a GSUB/GPOS table repacker to resolve offset overflows. + +commit 46bf03d6919087e4ce8f0626a3d342380346dc97 +Author: Garret Rieger <grieger@google.com> +Date: Thu Mar 18 14:35:36 2021 -0700 + + [subset] add NODISCARD to error checking methods on serializer. + + src/hb-serialize.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 3827a3eb567b424e8144564a42a22df74a20a7c6 +Author: Garret Rieger <grieger@google.com> +Date: Thu Mar 18 11:20:03 2021 -0700 + + [subset] rename serializer::set_error() to err(). + + src/hb-repacker.hh | 4 ++-- + src/hb-serialize.hh | 15 +++++++-------- + 2 files changed, 9 insertions(+), 10 deletions(-) + +commit f561fa6e4c5572c60c8fcf40e617919e531e6ee3 +Author: Garret Rieger <grieger@google.com> +Date: Thu Mar 18 11:13:47 2021 -0700 + + Change priority queue to use (priority, value) instead of (value, priority). + + src/Makefile.sources | 2 +- + src/hb-priority-queue.hh | 24 +++++++++++++----------- + src/hb-repacker.hh | 14 +++++++------- + src/test-priority-queue.cc | 40 ++++++++++++++++++++-------------------- + 4 files changed, 41 insertions(+), 39 deletions(-) + +commit b14475d2ae488acf3c2a169126a4901796401157 +Author: Garret Rieger <grieger@google.com> +Date: Thu Mar 18 10:51:26 2021 -0700 + + [subset] further changes to serializer error handling. + + - Rename enum type and enum members. + - in_errors() now returns true for any error having been set. hb-subset now looks for offset overflow only errors to divert to repacker. + - Added INT_OVERFLOW and ARRAY_OVERFLOW enum values. + + src/hb-cff-interp-common.hh | 2 +- + src/hb-open-type.hh | 8 +++---- + src/hb-ot-cmap-table.hh | 11 +++++----- + src/hb-ot-hmtx-table.hh | 2 +- + src/hb-ot-layout-gpos-table.hh | 8 +++---- + src/hb-ot-layout-gsub-table.hh | 2 +- + src/hb-repacker.hh | 4 ++-- + src/hb-serialize.hh | 50 ++++++++++++++++++++++++------------------ + src/hb-subset.cc | 4 ++-- + 9 files changed, 50 insertions(+), 41 deletions(-) + +commit 73ed59f7a68fc5363ef444b6de131c92cc5ca836 +Author: Garret Rieger <grieger@google.com> +Date: Wed Mar 17 15:53:10 2021 -0700 + + [subset] store errors in the serializer as a flag set. + + Make check_assign/check_equal specify the type of error to set. + + src/hb-cff-interp-common.hh | 2 +- + src/hb-open-type.hh | 10 ++++--- + src/hb-ot-cmap-table.hh | 17 +++++++---- + src/hb-ot-hdmx-table.hh | 2 +- + src/hb-ot-hmtx-table.hh | 2 +- + src/hb-ot-layout-gpos-table.hh | 8 +++--- + src/hb-ot-layout-gsub-table.hh | 4 +-- + src/hb-ot-name-table.hh | 3 +- + src/hb-repacker.hh | 4 +-- + src/hb-serialize.hh | 64 +++++++++++++++++++++++++----------------- + src/hb-subset.cc | 8 +++--- + src/test-repacker.cc | 4 +-- + 12 files changed, 76 insertions(+), 52 deletions(-) + +commit b9ecc7420df811e94413d77e6d70140e18d6ebe6 +Author: Garret Rieger <grieger@google.com> +Date: Tue Feb 16 13:39:10 2021 -0800 + + [subset] init offset_overflow in hb_serialize_context_t. + + src/hb-serialize.hh | 1 + + 1 file changed, 1 insertion(+) + +commit cf79fc342d7e59966fc7ba3e8460d58083b33966 +Author: Garret Rieger <grieger@google.com> +Date: Tue Feb 16 13:24:43 2021 -0800 + + [subset] limit priority bumps to 16. + + src/hb-repacker.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 0104409959b15ca8dc344df4a60ce36fc7f40105 +Author: Garret Rieger <grieger@google.com> +Date: Tue Feb 16 11:38:14 2021 -0800 + + Fix repack_tests for distcheck. + + test/subset/data/repack_tests/Makefile.am | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +commit e2f14e81bd20cc944bdecba7fcea20a4b4eddec0 +Author: Garret Rieger <grieger@google.com> +Date: Wed Nov 11 13:55:35 2020 -0800 + + [subset] fix memory leaks in test-repacker. + + src/test-repacker.cc | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +commit d3e2ba7c01b26da9cc5fac49a204fae8a54a3eb1 +Author: Garret Rieger <grieger@google.com> +Date: Wed Nov 11 13:50:18 2020 -0800 + + [subset] comment cleanup in hb-repacker.hh + + src/hb-repacker.hh | 35 ++++++++++++++++++++++++----------- + 1 file changed, 24 insertions(+), 11 deletions(-) + +commit 832f2b599b3d4fad5eea6d0eeef77377d3e0bad0 +Author: Garret Rieger <grieger@google.com> +Date: Tue Nov 10 16:15:37 2020 -0800 + + [subset] Refactor _subset () to reduce nesting and eliminate the use of 'goto'. + + src/hb-serialize.hh | 9 ++++ + src/hb-subset.cc | 134 +++++++++++++++++++++++++++++++--------------------- + src/meson.build | 1 + + 3 files changed, 90 insertions(+), 54 deletions(-) + +commit bb5c80a7c2d2454bba745a155146e7eaad912474 +Author: Garret Rieger <grieger@google.com> +Date: Tue Nov 10 14:11:57 2020 -0800 + + [subset] add error tracking to the repacker. + Also check for allocation failures as needed. + + src/hb-repacker.hh | 93 ++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 62 insertions(+), 31 deletions(-) + +commit b8b8c58b9ff9b51108caf47f5d98a15801b39058 +Author: Garret Rieger <grieger@google.com> +Date: Tue Nov 10 11:56:09 2020 -0800 + + [subset] add tests that check for successful repacking of a real font file. + + configure.ac | 1 + + test/subset/Makefile.am | 2 + + test/subset/data/Makefile.am | 2 +- + test/subset/data/fonts/NotoNastaliqUrdu-Bold.ttf | Bin 0 -> 459600 bytes + test/subset/data/repack_tests/Makefile.am | 22 +++++ + test/subset/data/repack_tests/Makefile.sources | 12 +++ + .../repack_tests/advanced_prioritization.tests | 72 ++++++++++++++ + test/subset/data/repack_tests/basic.tests | 52 +++++++++++ + test/subset/data/repack_tests/prioritization.tests | 77 +++++++++++++++ + .../data/repack_tests/table_duplication.tests | 97 +++++++++++++++++++ + test/subset/meson.build | 22 +++++ + test/subset/repack_test.py | 36 +++++++ + test/subset/run-repack-tests.py | 104 +++++++++++++++++++++ + 13 files changed, 498 insertions(+), 1 deletion(-) + +commit 6e9468fcfb71c731b0ec5a5e9c434119f16245e9 +Author: Garret Rieger <grieger@google.com> +Date: Mon Nov 9 16:52:36 2020 -0800 + + [subset] cleanup memory leaks in the repacker. + + src/hb-repacker.hh | 7 ++++++- + src/hb-subset.cc | 12 ++++++++---- + 2 files changed, 14 insertions(+), 5 deletions(-) + +commit a7a86a6eb4da25822cf0d42d7dd1668a15325a8f +Author: Garret Rieger <grieger@google.com> +Date: Fri Nov 6 16:22:48 2020 -0800 + + [subset] Add prioritization offset resolution. + Vertices can now be prioritized to force them to sort closer to their parent. The resolver will attempt to use this for overflows on non-shared vertices. + + src/hb-repacker.hh | 107 +++++++++++++++++++++++++++++++++++++++++---------- + src/test-repacker.cc | 1 + + 2 files changed, 88 insertions(+), 20 deletions(-) + +commit b452b2c76c9f76c9ea3501e8eb6534cb172f59ce +Author: Garret Rieger <grieger@google.com> +Date: Fri Nov 6 15:37:05 2020 -0800 + + [subset] refactor repacker graph to cache edge count and distances of vertices. + + src/hb-repacker.hh | 315 ++++++++++++++++++++++++++++++--------------------- + src/test-repacker.cc | 158 +++++++++++++------------- + 2 files changed, 265 insertions(+), 208 deletions(-) + +commit 75414e82b52d5a3adeb1eb48e64f43472913cba2 +Author: Garret Rieger <grieger@google.com> +Date: Thu Nov 5 16:39:23 2020 -0800 + + [subset] Add table duplication overflow resolution. + + src/hb-debug.hh | 4 ++ + src/hb-repacker.hh | 181 ++++++++++++++++++++++++++++++++++++++++------- + src/test-repacker.cc | 196 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 347 insertions(+), 34 deletions(-) + +commit 8286bd80940a7d136ee503dd1b1142190c6695ff +Author: Garret Rieger <grieger@google.com> +Date: Thu Nov 5 14:23:29 2020 -0800 + + [subset] use vectors instead of hashmaps throughout the repacker since all keys will be mapped for these use cases. + + src/hb-repacker.hh | 65 ++++++++++++++++++++++++++---------------------------- + 1 file changed, 31 insertions(+), 34 deletions(-) + +commit 519ae96617e1e2867122c5dbbdc8f1bbce89cb24 +Author: Garret Rieger <grieger@google.com> +Date: Thu Nov 5 11:22:16 2020 -0800 + + [subset] switch sort_shortest_distance() to use priority queue. + + src/hb-repacker.hh | 35 +++++++++++++---------------------- + 1 file changed, 13 insertions(+), 22 deletions(-) + +commit 5d3511e5b13eb825ea9914aa2400cc040edef8a7 +Author: Garret Rieger <grieger@google.com> +Date: Thu Nov 5 10:34:26 2020 -0800 + + [subset] Change compute_distances() to use a priority queue. + + src/hb-repacker.hh | 38 ++++++++++++++++++++++++++++---------- + src/meson.build | 1 + + 2 files changed, 29 insertions(+), 10 deletions(-) + +commit 59ac0a0d0a99e91a75d18a3884ae276309370997 +Author: Garret Rieger <grieger@google.com> +Date: Thu Nov 5 10:29:56 2020 -0800 + + [subset] Use priority for comparison in heap. + + src/hb-priority-queue.hh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 4c8dd41ed90292d4516c539be23c16d625d69a41 +Author: Garret Rieger <grieger@google.com> +Date: Thu Nov 5 09:21:25 2020 -0800 + + [subset] re-write compute distances to use an array lookup for the distance map. + + src/hb-priority-queue.hh | 4 ++-- + src/hb-repacker.hh | 55 ++++++++++++++++++++---------------------------- + src/test-repacker.cc | 2 ++ + 3 files changed, 27 insertions(+), 34 deletions(-) + +commit 5c4e0ffd9768de0c51a42baa35d9c29636fdd99a +Author: Garret Rieger <grieger@google.com> +Date: Wed Nov 4 16:08:01 2020 -0800 + + [subset] Add a basic priority queue datastructure (binary heap). + + src/Makefile.am | 6 +- + src/Makefile.sources | 1 + + src/hb-priority-queue.hh | 149 +++++++++++++++++++++++++++++++++++++++++++++ + src/test-priority-queue.cc | 89 +++++++++++++++++++++++++++ + 4 files changed, 244 insertions(+), 1 deletion(-) + +commit dd8e5d0e1b0c52190bf16ab091ee3756b30d4d97 +Author: Garret Rieger <grieger@google.com> +Date: Tue Nov 3 14:01:42 2020 -0800 + + [subset] Only run the repacker for GSUB/GPOS. + + src/hb-subset.cc | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +commit aaa7873d425a6267b1df16f5a1f3750578b438f0 +Author: Garret Rieger <grieger@google.com> +Date: Mon Nov 2 16:16:27 2020 -0800 + + [subset] add topological sort by closest distance via Dijkstra's algorithm. + + src/hb-repacker.hh | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ + src/test-repacker.cc | 37 ++++++++++++++- + 2 files changed, 160 insertions(+), 2 deletions(-) + +commit 8ebe5d734f3543b7a1266f252fe96188efc69531 +Author: Garret Rieger <grieger@google.com> +Date: Mon Nov 2 14:51:39 2020 -0800 + + Implement will_overflow (). + + src/hb-repacker.hh | 73 +++++++++++++++++++++++++++++++++++++++++++++++++--- + src/test-repacker.cc | 45 ++++++++++++++++++++++++++++++++ + 2 files changed, 114 insertions(+), 4 deletions(-) + +commit 6b1ea4cbe724af10309763b708abc36c968f14a7 +Author: Garret Rieger <grieger@google.com> +Date: Fri Oct 30 12:16:26 2020 -0700 + + [subset] hook up the repacker to run if offset overflows are encountered during subsetting. + + src/hb-serialize.hh | 13 +++++++++++-- + src/hb-subset.cc | 30 +++++++++++++++++++++++++++++- + 2 files changed, 40 insertions(+), 3 deletions(-) + +commit f4c78cc7dd11c83aa3f3a3516e75f4fe689aff19 +Author: Garret Rieger <grieger@google.com> +Date: Fri Oct 30 10:29:51 2020 -0700 + + [subset] Implement Kahn's algo for topological sorting instead of BFS. + + src/hb-repacker.hh | 88 +++++++++++++++++++++++++++++++++++----------------- + src/test-repacker.cc | 69 +++++++++++++++++++++++++++++++++++++--- + 2 files changed, 124 insertions(+), 33 deletions(-) + +commit 00f393dc3fdd40a761df4fe988745ecb0e62df4b +Author: Garret Rieger <grieger@google.com> +Date: Thu Oct 29 14:58:34 2020 -0700 + + [subset] finish up BFS sort implementation. + + src/hb-repacker.hh | 93 +++++++++++++++++++++++++++++++++++++++----------- + src/test-repacker.cc | 95 ++++++++++++++++++++++++++++++++++++++++++---------- + 2 files changed, 151 insertions(+), 37 deletions(-) + +commit 1584d3cb8faf244ae439cd59eac5f3d006d7a106 +Author: Garret Rieger <grieger@google.com> +Date: Wed Oct 28 17:49:09 2020 -0700 + + [subset] Start a proof of concept implementation of the GSUB/GPOS offset overflow resolver. + + src/Makefile.am | 6 +- + src/Makefile.sources | 1 + + src/hb-repacker.hh | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++ + src/hb-serialize.hh | 3 + + src/test-repacker.cc | 87 +++++++++++++++++++++++++ + 5 files changed, 276 insertions(+), 1 deletion(-) + +commit a7d120aeabbae6a08f3cdd39a5ef1d435c3a4854 +Merge: 69d772e52 56ca43578 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 17 14:33:33 2021 -0700 + + Merge pull request #2835 from googlefonts/remove_redundant_sys + + [subset] Remove redundant LangSys + +commit 56ca435787c1686fcfe01bf4db822bb91d9ba769 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Jan 28 15:21:26 2021 -0800 + + [subset] fix for collect_features and remove_redundant_lamngsys + + previously remove_redundant_sys () is missing in harfbuzz, after + redundant langsys removal, some features are removed as well in + prune_features() in fonttools. This change is trying to get the same + result between harfbuzz and fonttools. + + src/hb-ot-layout-common.hh | 182 +++++++++++++++++++-- + src/hb-ot-layout-gpos-table.hh | 2 +- + src/hb-ot-layout-gsub-table.hh | 2 +- + src/hb-ot-layout-gsubgpos.hh | 75 ++++++++- + src/hb-subset-plan.cc | 43 ++++- + src/hb-subset-plan.hh | 6 +- + ...-retain-gids.627,644,623,62D,644,627,645,2E.ttf | Bin 48640 -> 48596 bytes + ...lar.keep-layout-retain-gids.627,644,62D,628.ttf | Bin 42884 -> 42836 bytes + ...iri-Regular.keep-layout-retain-gids.627,644.ttf | Bin 36940 -> 36892 bytes + ...yout-retain-gids.633,645,627,621,20,644,627.ttf | Bin 46724 -> 46680 bytes + ...Regular.keep-layout-retain-gids.63A,64A,631.ttf | Bin 42896 -> 42896 bytes + ....keep-layout.627,644,623,62D,644,627,645,2E.ttf | Bin 13332 -> 13288 bytes + .../Amiri-Regular.keep-layout.627,644,62D,628.ttf | Bin 10232 -> 10188 bytes + .../Amiri-Regular.keep-layout.627,644.ttf | Bin 4412 -> 4364 bytes + ...ular.keep-layout.633,645,627,621,20,644,627.ttf | Bin 10372 -> 10324 bytes + .../Amiri-Regular.keep-layout.63A,64A,631.ttf | Bin 7824 -> 7824 bytes + test/subset/data/fonts/Amiri-Regular.ttf | Bin 562684 -> 562980 bytes + 17 files changed, 284 insertions(+), 26 deletions(-) + +commit 69d772e522c60aa9d73b6ccd550f4a834e7bd9b8 +Author: Garret Rieger <grieger@google.com> +Date: Wed Mar 17 14:11:16 2021 -0700 + + [subset] Fixed test gsub5 test files. + + ...2.keep-layout-retain-gids.retain-all-codepoint.otf | Bin 3752 -> 3808 bytes + ...e_subrules_f2.keep-layout.retain-all-codepoint.otf | Bin 3752 -> 3808 bytes + ...2.keep-layout-retain-gids.retain-all-codepoint.otf | Bin 3768 -> 3824 bytes + ...e_subrules_f2.keep-layout.retain-all-codepoint.otf | Bin 3768 -> 3824 bytes + ...1.keep-layout-retain-gids.retain-all-codepoint.otf | Bin 3772 -> 3828 bytes + ...successive_f1.keep-layout.retain-all-codepoint.otf | Bin 3772 -> 3828 bytes + 6 files changed, 0 insertions(+), 0 deletions(-) + +commit 0e1c0fa404e2ad087265dc59130dbec1c4682258 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jan 12 10:17:14 2021 -0800 + + [subset] optimize glyph closure method: step 5 + + add testcase and some fixes + + src/hb-ot-layout-common.hh | 35 ++++---- + src/hb-ot-layout-gsub-table.hh | 10 +-- + src/hb-ot-layout-gsubgpos.hh | 95 +++++++++++++++------ + src/hb-ot-layout.cc | 18 +++- + test/subset/data/Makefile.am | 1 + + test/subset/data/Makefile.sources | 1 + + ...ubrules_f2.keep-layout-retain-gids.41,42,43.otf | Bin 0 -> 2248 bytes + ...e_subrules_f2.keep-layout-retain-gids.41,42.otf | Bin 0 -> 2224 bytes + ...e_subrules_f2.keep-layout-retain-gids.41,43.otf | Bin 0 -> 2060 bytes + ...iple_subrules_f2.keep-layout-retain-gids.41.otf | Bin 0 -> 1928 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3752 bytes + ...1_multiple_subrules_f2.keep-layout.41,42,43.otf | Bin 0 -> 1460 bytes + ...ext1_multiple_subrules_f2.keep-layout.41,42.otf | Bin 0 -> 1420 bytes + ...ext1_multiple_subrules_f2.keep-layout.41,43.otf | Bin 0 -> 1344 bytes + ...ontext1_multiple_subrules_f2.keep-layout.41.otf | Bin 0 -> 1228 bytes + ...ubrules_f2.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3752 bytes + ...ubrules_f2.keep-layout-retain-gids.41,42,43.otf | Bin 0 -> 2264 bytes + ...e_subrules_f2.keep-layout-retain-gids.41,42.otf | Bin 0 -> 2236 bytes + ...e_subrules_f2.keep-layout-retain-gids.41,43.otf | Bin 0 -> 2060 bytes + ...iple_subrules_f2.keep-layout-retain-gids.41.otf | Bin 0 -> 1928 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3768 bytes + ...2_multiple_subrules_f2.keep-layout.41,42,43.otf | Bin 0 -> 1476 bytes + ...ext2_multiple_subrules_f2.keep-layout.41,42.otf | Bin 0 -> 1432 bytes + ...ext2_multiple_subrules_f2.keep-layout.41,43.otf | Bin 0 -> 1344 bytes + ...ontext2_multiple_subrules_f2.keep-layout.41.otf | Bin 0 -> 1228 bytes + ...ubrules_f2.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3768 bytes + ...cessive_f1.keep-layout-retain-gids.41,42,43.otf | Bin 0 -> 2028 bytes + ...successive_f1.keep-layout-retain-gids.41,42.otf | Bin 0 -> 1932 bytes + ...successive_f1.keep-layout-retain-gids.41,43.otf | Bin 0 -> 2048 bytes + ...t3_successive_f1.keep-layout-retain-gids.41.otf | Bin 0 -> 1916 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3772 bytes + ...context3_successive_f1.keep-layout.41,42,43.otf | Bin 0 -> 1328 bytes + ...ub_context3_successive_f1.keep-layout.41,42.otf | Bin 0 -> 1228 bytes + ...ub_context3_successive_f1.keep-layout.41,43.otf | Bin 0 -> 1332 bytes + .../gsub_context3_successive_f1.keep-layout.41.otf | Bin 0 -> 1216 bytes + ...cessive_f1.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3772 bytes + .../fonts/gsub_context1_multiple_subrules_f2.otf | Bin 0 -> 4776 bytes + .../fonts/gsub_context2_multiple_subrules_f2.otf | Bin 0 -> 4796 bytes + .../data/fonts/gsub_context3_successive_f1.otf | Bin 0 -> 4760 bytes + test/subset/data/tests/layout.gsub5.tests | 15 ++++ + test/subset/meson.build | 1 + + 41 files changed, 124 insertions(+), 52 deletions(-) + +commit b8a58a0c0b7d62c33b106ad119a567b6d86d1d36 +Author: Qunxin Liu <qxliu@google.com> +Date: Sun Jan 10 15:50:04 2021 -0800 + + [subset] optimize glyph closure method: step 4 + + optimize recurse_lookups in Context/ChainContext + glyph closure, only the glyphs that the parent lookup + can apply the recursion to can participate in recursing + the lookup. + + src/hb-ot-layout-gsub-table.hh | 84 ++++------------ + src/hb-ot-layout-gsubgpos.hh | 219 +++++++++++++++++++++++++++++++---------- + 2 files changed, 186 insertions(+), 117 deletions(-) + +commit 62423504ee6dcf282177ea0b91268df4e7a1e30b +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jan 5 14:54:40 2021 -0800 + + [subset] optimize glyph closure method: step 3 + + Add function intersects_coverage_glyphs that collects + set of matching glyphs in Coverage table + + src/hb-ot-layout-common.hh | 39 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 34 insertions(+), 5 deletions(-) + +commit ef78d0f92345eb452e94c73301bc929822755b27 +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Jan 5 10:16:50 2021 -0800 + + [subset] optimize glyph closure method: step 2 + Add function intersects_class_glyphs that collects + set of glyphs matching class in ClassDef table + + src/hb-ot-layout-common.hh | 75 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 75 insertions(+) + +commit b4fc593c3c34c45521c684cb6d0d24079d553e3a +Author: Qunxin Liu <qxliu@google.com> +Date: Wed Dec 9 10:44:18 2020 -0800 + + [subset] optimize glyph closure method: step1 + + Previous GSUB glyph closure is done by recursively visiting + all reachable lookup tables that apply to any glyphs in the + current/input glyph set, but actually only the glyphs that + the parent lookup can apply the recursion to can participate + in recursing the lookup. This is step 1 for glyph closure + optimization: + 1. Add stack of currently active glyph set pointers into hb_closure_context_t + 2. Update closure() method in simple GSUB tables to use + this stack in order not to change current glyph set at different stages + of recursion + 3. Add function may_have_non_1to1() to GSUB tables + + src/hb-ot-layout-gsub-table.hh | 100 ++++++++++++++++++++++++++++++++++++++--- + src/hb-ot-layout-gsubgpos.hh | 57 ++++++++++++++++++++++- + 2 files changed, 150 insertions(+), 7 deletions(-) + +commit 5f4c321d4aae659f83178143d5a4df0d2d6b4d02 +Merge: 03538e872 1b79b8cd2 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Mar 17 10:20:59 2021 -0700 + + Merge pull request #2894 from googlefonts/gpos_2 + + [subset] Update PairPosFormat2 subsetting to match fontTools + +commit 1b79b8cd2daebc99acd9310742755f02162e5ed0 +Author: Garret Rieger <grieger@google.com> +Date: Tue Mar 16 15:23:11 2021 -0700 + + [subset] update gpos tests to reflect updated behaviour. + + test/api/fonts/AdobeVFPrototype.WA.gpos.otf | Bin 3948 -> 4148 bytes + test/api/fonts/Roboto-Regular-gpos-aw.ttf | Bin 2232 -> 2236 bytes + test/api/test-subset-gpos.c | 5 ----- + 3 files changed, 5 deletions(-) + +commit 2df39bcae7e34630361a49c44e9d295233367ce0 +Author: Garret Rieger <grieger@google.com> +Date: Tue Mar 16 14:20:49 2021 -0700 + + [subset] don't allocate a set to use as a glyph filter for PairPosFormat2. + + src/hb-ot-layout-common.hh | 34 ++++++++++++++++++++++------------ + src/hb-ot-layout-gpos-table.hh | 7 +------ + 2 files changed, 23 insertions(+), 18 deletions(-) + +commit b1b1486d07f8fe3c7a1fb4bc87e6f037ff5b47d3 +Author: Garret Rieger <grieger@google.com> +Date: Tue Mar 16 13:32:23 2021 -0700 + + [subset] update expected files to not include cmap12 pruning. + + .../Roboto-Regular.keep-gdef-gpos.1E00,303.ttf | Bin 2648 -> 2648 bytes + .../Roboto-Regular.keep-gdef-gpos.41,42,43.ttf | Bin 2736 -> 2728 bytes + ...os2_2_font5.keep-layout-retain-gids.21,23,25.otf | Bin 1824 -> 1816 bytes + .../gpos2_2_font5.keep-layout-retain-gids.21,23.otf | Bin 1692 -> 1684 bytes + .../gpos2_2_font5.keep-layout-retain-gids.2E,23.otf | Bin 2024 -> 1944 bytes + ...keep-layout-retain-gids.retain-all-codepoint.otf | Bin 3732 -> 3724 bytes + .../gpos2_2_font5.keep-layout.21,23,25.otf | Bin 1488 -> 1480 bytes + .../gpos2_2_font5.keep-layout.21,23.otf | Bin 1368 -> 1360 bytes + .../gpos2_2_font5.keep-layout.2E,23.otf | Bin 1588 -> 1508 bytes + ...os2_2_font5.keep-layout.retain-all-codepoint.otf | Bin 3732 -> 3724 bytes + ...t-retain-gids.627,644,623,62D,644,627,645,2E.ttf | Bin 48640 -> 48640 bytes + ...r.keep-layout.627,644,623,62D,644,627,645,2E.ttf | Bin 13332 -> 13332 bytes + 12 files changed, 0 insertions(+), 0 deletions(-) + +commit bb54e1047d2d501459bb366e47f24f51824c8db7 +Author: Garret Rieger <grieger@google.com> +Date: Tue Mar 16 13:19:26 2021 -0700 + + [subset] Also filter class1 by coverage when collecting variation indices for PairPosFormat2. + + src/hb-ot-layout-gpos-table.hh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 190b7a98f8af54cc42d3ccdb6979e432dfd41aa9 +Author: Garret Rieger <grieger@google.com> +Date: Thu Oct 8 14:44:54 2020 -0700 + + [subset] Update PairPosFormat2 subsetting to match fontTools updated subsetting (https://github.com/fonttools/fonttools/pull/2221) + + - subset class def 1 against the coverage table. + - Don't re-use class 0 in class def 2. + - Ignore class 0 glyphs for the purposes of determing format 1 vs format 2 encoding for ClassDef. + + Add an additional test case which demonstrates these issues. + + src/hb-ot-layout-common.hh | 43 +++++++++++++-------- + src/hb-ot-layout-gpos-table.hh | 14 +++++-- + ...AdobeVFPrototype.keep-gdef-gpos.41,42,43,57.otf | Bin 5444 -> 5400 bytes + .../AdobeVFPrototype.keep-gdef-gpos.41,42,43.otf | Bin 4916 -> 4872 bytes + .../AdobeVFPrototype.keep-gdef-gpos.41,42.otf | Bin 4436 -> 4392 bytes + .../AdobeVFPrototype.keep-gdef-gpos.41,56,57.otf | Bin 4556 -> 4540 bytes + .../AdobeVFPrototype.keep-gdef-gpos.41.otf | Bin 3692 -> 3688 bytes + .../AdobeVFPrototype.keep-gdef-gpos.42,57.otf | Bin 4556 -> 4524 bytes + ...gpos2_1_font7.keep-layout-retain-gids.2E,23.otf | Bin 0 -> 1944 bytes + .../gpos2_1_font7.keep-layout.2E,23.otf | Bin 0 -> 1508 bytes + ...s2_2_font5.keep-layout-retain-gids.21,23,25.otf | Bin 1776 -> 1824 bytes + ...gpos2_2_font5.keep-layout-retain-gids.21,23.otf | Bin 1644 -> 1692 bytes + ...gpos2_2_font5.keep-layout-retain-gids.2E,23.otf | Bin 0 -> 2024 bytes + ...s2_2_font5.keep-layout-retain-gids.41,42,43.otf | Bin 1988 -> 1988 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 3684 -> 3732 bytes + .../gpos2_2_font5.keep-layout.21,23,25.otf | Bin 1440 -> 1488 bytes + .../gpos2_2_font5.keep-layout.21,23.otf | Bin 1320 -> 1368 bytes + .../gpos2_2_font5.keep-layout.2E,23.otf | Bin 0 -> 1588 bytes + .../gpos2_2_font5.keep-layout.41,42,43.otf | Bin 1288 -> 1288 bytes + ...s2_2_font5.keep-layout.retain-all-codepoint.otf | Bin 3684 -> 3732 bytes + test/subset/data/fonts/gpos2_2_font5.otf | Bin 4580 -> 4632 bytes + test/subset/data/tests/layout.gpos2.tests | 1 + + 22 files changed, 38 insertions(+), 20 deletions(-) + commit 03538e872a0610a65fad692b33d3646f387cf578 Author: Khaled Hosny <khaled@aliftype.com> Date: Tue Mar 16 19:28:35 2021 +0200 diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am b/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am index 9f34c5f1a4c..aee0f530c77 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am +++ b/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am @@ -20,7 +20,6 @@ EXTRA_DIST = \ meson.build \ meson_options.txt \ subprojects/expat.wrap \ - subprojects/fontconfig.wrap \ subprojects/freetype2.wrap \ subprojects/glib.wrap \ subprojects/libffi.wrap \ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS index 321c550188f..a05ff67cfee 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS +++ b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS @@ -1,3 +1,12 @@ +Overview of changes leading to 2.8.1 +Tuesday, May 4, 2021 +==================================== +- Subsetter now fully supports GSUB/GPOS/GDEF tables (including variations); as + such, layout tables are retained by subsetter by default. (Garret Rieger, Qunxin Liu) +- Build scripts no longer check for FontConfig as HarfBuzz does not use it. +- hb-view supports iTerm2 and kitty inline image protocols (Khaled Hosny), + it can also use Chafa for terminal graphics if available (Hans Petter Jansson). + Overview of changes leading to 2.8.0 Tuesday, March 16, 2021 ==================================== diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in b/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in index 8d49f028084..c3d447db23d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in +++ b/Build/source/libs/harfbuzz/harfbuzz-src/config.h.in @@ -12,6 +12,9 @@ /* Have cairo-ft support in cairo graphics library */ #undef HAVE_CAIRO_FT +/* Have chafa terminal graphics library */ +#undef HAVE_CHAFA + /* Have Core Text backend */ #undef HAVE_CORETEXT @@ -27,9 +30,6 @@ /* Define to 1 if you have the <dwrite.h> header file. */ #undef HAVE_DWRITE_H -/* Have fontconfig library */ -#undef HAVE_FONTCONFIG - /* Have FreeType 2 library */ #undef HAVE_FREETYPE diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac b/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac index d7f1e2673e2..043f6ed61b5 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], - [2.8.0], + [2.8.1], [https://github.com/harfbuzz/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) @@ -214,21 +214,21 @@ AM_CONDITIONAL(HAVE_CAIRO_FT, $have_cairo_ft) dnl ========================================================================== -AC_ARG_WITH(fontconfig, - [AS_HELP_STRING([--with-fontconfig=@<:@yes/no/auto@:>@], - [Use fontconfig @<:@default=auto@:>@])],, - [with_fontconfig=auto]) -have_fontconfig=false -if test "x$with_fontconfig" = "xyes" -o "x$with_fontconfig" = "xauto"; then - PKG_CHECK_MODULES(FONTCONFIG, fontconfig, have_fontconfig=true, :) +AC_ARG_WITH(chafa, + [AS_HELP_STRING([--with-chafa=@<:@yes/no/auto@:>@], + [Use chafa @<:@default=auto@:>@])],, + [with_chafa=auto]) +have_chafa=false +if test "x$with_chafa" = "xyes" -o "x$with_chafa" = "xauto"; then + PKG_CHECK_MODULES(CHAFA, chafa >= 1.6.0, have_chafa=true, :) fi -if test "x$with_fontconfig" = "xyes" -a "x$have_fontconfig" != "xtrue"; then - AC_MSG_ERROR([fontconfig support requested but not found]) +if test "x$with_chafa" = "xyes" -a "x$have_chafa" != "xtrue"; then + AC_MSG_ERROR([chafa support requested but not found]) fi -if $have_fontconfig; then - AC_DEFINE(HAVE_FONTCONFIG, 1, [Have fontconfig library]) +if $have_chafa; then + AC_DEFINE(HAVE_CHAFA, 1, [Have chafa terminal graphics library]) fi -AM_CONDITIONAL(HAVE_FONTCONFIG, $have_fontconfig) +AM_CONDITIONAL(HAVE_CHAFA, $have_chafa) dnl ========================================================================== @@ -432,6 +432,7 @@ test/shaping/data/in-house/Makefile test/shaping/data/text-rendering-tests/Makefile test/subset/Makefile test/subset/data/Makefile +test/subset/data/repack_tests/Makefile docs/Makefile docs/version.xml ]) @@ -465,7 +466,7 @@ Font callbacks (the more the merrier): Tools used for command-line utilities: Cairo: ${have_cairo} - Fontconfig: ${have_fontconfig} + Chafa: ${have_chafa} Additional shapers: Graphite2: ${have_graphite2} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/meson.build b/Build/source/libs/harfbuzz/harfbuzz-src/meson.build index f08720f19e1..4d5cd0ca51d 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.47.0', - version: '2.8.0', + version: '2.8.1', default_options: [ 'cpp_eh=none', # Just to support msvc, we are passing -fno-rtti also anyway 'cpp_rtti=false', # Just to support msvc, we are passing -fno-exceptions also anyway @@ -95,8 +95,6 @@ glib_dep = dependency('glib-2.0', required: get_option('glib'), fallback: ['glib', 'libglib_dep']) gobject_dep = dependency('gobject-2.0', required: get_option('gobject'), fallback: ['glib', 'libgobject_dep']) -fontconfig_dep = dependency('fontconfig', required: get_option('fontconfig'), - fallback: ['fontconfig', 'fontconfig_dep']) graphite2_dep = dependency('graphite2', required: get_option('graphite')) icu_dep = null_dep @@ -156,6 +154,8 @@ if not get_option('cairo').disabled() endif endif +chafa_dep = dependency('chafa', version: '>= 1.6.0', required: get_option('chafa')) + conf = configuration_data() incconfig = include_directories('.') @@ -183,6 +183,10 @@ if cairo_ft_dep.found() conf.set('HAVE_CAIRO_FT', 1) endif +if chafa_dep.found() + conf.set('HAVE_CHAFA', 1) +endif + if graphite2_dep.found() conf.set('HAVE_GRAPHITE2', 1) endif @@ -217,10 +221,6 @@ if freetype_dep.found() endif endif -if fontconfig_dep.found() - conf.set('HAVE_FONTCONFIG', 1) -endif - gdi_uniscribe_deps = [] # GDI (Uniscribe) (Windows) if host_machine.system() == 'windows' and not get_option('gdi').disabled() @@ -369,7 +369,7 @@ build_summary = { }, 'Dependencies used for command-line utilities': {'Cairo': conf.get('HAVE_CAIRO', 0) == 1, - 'Fontconfig': conf.get('HAVE_FONTCONFIG', 0) == 1, + 'Chafa': conf.get('HAVE_CHAFA', 0) == 1, }, 'Additional shapers': {'Graphite2': conf.get('HAVE_GRAPHITE2', 0) == 1, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt b/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt index 980099f5111..602d053b77b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt +++ b/Build/source/libs/harfbuzz/harfbuzz-src/meson_options.txt @@ -5,8 +5,8 @@ option('gobject', type: 'feature', value: 'auto', description: 'Enable GObject bindings') option('cairo', type: 'feature', value: 'auto', description: 'Use Cairo graphics library') -option('fontconfig', type: 'feature', value: 'auto', - description: 'Use fontconfig') +option('chafa', type: 'feature', value: 'auto', + description: 'Use Chafa terminal graphics library') option('icu', type: 'feature', value: 'auto', description: 'Enable ICU library unicode functions') option('graphite', type: 'feature', value: 'disabled', diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am index e10068e9487..7a0ca29851a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am @@ -342,7 +342,7 @@ test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) -COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-unicode-ranges test-bimap +COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-priority-queue test-unicode-ranges test-bimap test-repacker COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS) check_PROGRAMS += $(COMPILED_TESTS) @@ -356,6 +356,14 @@ test_array_SOURCES = test-array.cc test_array_CPPFLAGS = $(HBCFLAGS) test_array_LDADD = libharfbuzz.la $(HBLIBS) +test_priority_queue_SOURCES = test-priority-queue.cc hb-static.cc +test_priority_queue_CPPFLAGS = $(HBCFLAGS) +test_priority_queue_LDADD = libharfbuzz.la $(HBLIBS) + +test_repacker_SOURCES = test-repacker.cc hb-static.cc +test_repacker_CPPFLAGS = $(HBCFLAGS) +test_repacker_LDADD = libharfbuzz.la libharfbuzz-subset.la $(HBLIBS) + test_iter_SOURCES = test-iter.cc hb-static.cc test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) test_iter_LDADD = $(COMPILED_TESTS_LDADD) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources index 6a6d3018bd4..14c97996b00 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources @@ -167,6 +167,7 @@ HB_BASE_sources = \ hb-unicode.hh \ hb-utf.hh \ hb-vector.hh \ + hb-priority-queue.hh \ hb.hh \ $(NULL) @@ -268,6 +269,7 @@ HB_SUBSET_sources = \ hb-subset-plan.hh \ hb-subset.cc \ hb-subset.hh \ + hb-repacker.hh \ $(NULL) HB_SUBSET_headers = \ 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 62d79c7ffc3..d1b5d4342ec 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 @@ -25,10 +25,8 @@ Input files: """ import collections +import html from html.parser import HTMLParser -def write (s): - sys.stdout.flush () - sys.stdout.buffer.write (s.encode ('utf-8')) import itertools import re import sys @@ -37,16 +35,16 @@ import unicodedata if len (sys.argv) != 3: sys.exit (__doc__) -from html import unescape -def html_unescape (parser, entity): - return unescape (entity) - def expect (condition, message=None): if not condition: if message is None: raise AssertionError raise AssertionError (message) +def write (s): + sys.stdout.flush () + sys.stdout.buffer.write (s.encode ('utf-8')) + DEFAULT_LANGUAGE_SYSTEM = '' # from https://www-01.sil.org/iso639-3/iso-639-3.tab @@ -383,10 +381,10 @@ class OpenTypeRegistryParser (HTMLParser): self._current_tr[-1] += data def handle_charref (self, name): - self.handle_data (html_unescape (self, '&#%s;' % name)) + self.handle_data (html.unescape ('&#%s;' % name)) def handle_entityref (self, name): - self.handle_data (html_unescape (self, '&%s;' % name)) + self.handle_data (html.unescape ('&%s;' % name)) def parse (self, filename): """Parse the OpenType language system tag registry. diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh index f2785a6f588..63fac84524f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh @@ -54,7 +54,7 @@ struct Anchor DEFINE_SIZE_STATIC (4); }; -typedef LArrayOf<Anchor> GlyphAnchors; +typedef Array32Of<Anchor> GlyphAnchors; struct ankr { @@ -64,7 +64,7 @@ struct ankr unsigned int i, unsigned int num_glyphs) const { - const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs); + const NNOffset16To<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs); if (!offset) return Null (Anchor); const GlyphAnchors &anchors = &(this+anchorData) + *offset; @@ -83,9 +83,9 @@ struct ankr protected: HBUINT16 version; /* Version number (set to zero) */ HBUINT16 flags; /* Flags (currently unused; set to zero) */ - LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors>>> + Offset32To<Lookup<NNOffset16To<GlyphAnchors>>> lookupTable; /* Offset to the table's lookup table */ - LNNOffsetTo<HBUINT8> + NNOffset32To<HBUINT8> anchorData; /* Offset to the glyph data table */ public: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh index 98ed20d8ebc..8e7b7b52909 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh @@ -164,7 +164,7 @@ struct LookupSegmentArray HBGlyphID last; /* Last GlyphID in this segment */ HBGlyphID first; /* First GlyphID in this segment */ - NNOffsetTo<UnsizedArrayOf<T>> + NNOffset16To<UnsizedArrayOf<T>> valuesZ; /* A 16-bit offset from the start of * the table to the data. */ public: @@ -659,7 +659,7 @@ struct ClassTable } protected: HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */ - ArrayOf<HBUCHAR> classArray; /* The class codes (indexed by glyph index minus + Array16Of<HBUCHAR> classArray; /* The class codes (indexed by glyph index minus * firstGlyph). */ public: DEFINE_SIZE_ARRAY (4, classArray); @@ -678,7 +678,8 @@ struct ObsoleteTypes const void *base, const T *array) { - return (offset - ((const char *) array - (const char *) base)) / T::static_size; + /* https://github.com/harfbuzz/harfbuzz/issues/2816 */ + return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size; } template <typename T> static unsigned int byteOffsetToIndex (unsigned int offset, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh index 359e859cfc6..573f0cf9f6b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh @@ -144,7 +144,7 @@ struct FeatureName protected: HBUINT16 feature; /* Feature type. */ HBUINT16 nSettings; /* The number of records in the setting name array. */ - LNNOffsetTo<UnsizedArrayOf<SettingName>> + NNOffset32To<UnsizedArrayOf<SettingName>> settingTableZ; /* Offset in bytes from the beginning of this table to * this feature's setting name array. The actual type of * record this offset refers to will depend on the diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh index 49506e9f5ab..556d4ad75b1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh @@ -79,7 +79,7 @@ struct DecompositionAction * to decompose before more frequent ones. The ligatures * on the line of text will decompose in increasing * value of this field. */ - ArrayOf<HBUINT16> + Array16Of<HBUINT16> decomposedglyphs; /* Number of 16-bit glyph indexes that follow; * the ligature will be decomposed into these glyphs. @@ -310,7 +310,7 @@ struct WidthDeltaPair DEFINE_SIZE_STATIC (24); }; -typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster; +typedef OT::Array32Of<WidthDeltaPair> WidthDeltaCluster; struct JustificationCategory { @@ -358,20 +358,20 @@ struct JustificationHeader } protected: - OffsetTo<JustificationCategory> + Offset16To<JustificationCategory> justClassTable; /* Offset to the justification category state table. */ - OffsetTo<WidthDeltaCluster> + Offset16To<WidthDeltaCluster> wdcTable; /* Offset from start of justification table to start * of the subtable containing the width delta factors * for the glyphs in your font. * * The width delta clusters table. */ - OffsetTo<PostcompensationActionChain> + Offset16To<PostcompensationActionChain> pcTable; /* Offset from start of justification table to start * of postcompensation subtable (set to zero if none). * * The postcompensation subtable, if present in the font. */ - Lookup<OffsetTo<WidthDeltaCluster>> + Lookup<Offset16To<WidthDeltaCluster>> lookupTable; /* Lookup table associating glyphs with width delta * clusters. See the description of Width Delta Clusters * table for details on how to interpret the lookup values. */ @@ -398,13 +398,13 @@ struct just FixedVersion<>version; /* Version of the justification table * (0x00010000u for version 1.0). */ HBUINT16 format; /* Format of the justification table (set to 0). */ - OffsetTo<JustificationHeader> + Offset16To<JustificationHeader> horizData; /* Byte offset from the start of the justification table * to the header for tables that contain justification * information for horizontal text. * If you are not including this information, * store 0. */ - OffsetTo<JustificationHeader> + Offset16To<JustificationHeader> vertData; /* ditto, vertical */ public: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh index 1cd412164e7..d0eacf0e61c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh @@ -710,18 +710,18 @@ struct KerxSubTableFormat6 { struct Long { - LNNOffsetTo<Lookup<HBUINT32>> rowIndexTable; - LNNOffsetTo<Lookup<HBUINT32>> columnIndexTable; - LNNOffsetTo<UnsizedArrayOf<FWORD32>> array; + NNOffset32To<Lookup<HBUINT32>> rowIndexTable; + NNOffset32To<Lookup<HBUINT32>> columnIndexTable; + NNOffset32To<UnsizedArrayOf<FWORD32>> array; } l; struct Short { - LNNOffsetTo<Lookup<HBUINT16>> rowIndexTable; - LNNOffsetTo<Lookup<HBUINT16>> columnIndexTable; - LNNOffsetTo<UnsizedArrayOf<FWORD>> array; + NNOffset32To<Lookup<HBUINT16>> rowIndexTable; + NNOffset32To<Lookup<HBUINT16>> columnIndexTable; + NNOffset32To<UnsizedArrayOf<FWORD>> array; } s; } u; - LNNOffsetTo<UnsizedArrayOf<FWORD>> vector; + NNOffset32To<UnsizedArrayOf<FWORD>> vector; public: DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24); }; 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 e3bc268d26a..dea69c9ab87 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 @@ -304,7 +304,7 @@ struct ContextualSubtable bool mark_set; unsigned int mark; const ContextualSubtable *table; - const UnsizedOffsetListOf<Lookup<HBGlyphID>, HBUINT, false> &subs; + const UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false> &subs; }; bool apply (hb_aat_apply_context_t *c) const @@ -348,7 +348,7 @@ struct ContextualSubtable protected: StateTable<Types, EntryData> machine; - NNOffsetTo<UnsizedOffsetListOf<Lookup<HBGlyphID>, HBUINT, false>, HBUINT> + NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false>, HBUINT> substitutionTables; public: DEFINE_SIZE_STATIC (20); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh index 8c04a6482ff..b1a1512821d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh @@ -58,7 +58,7 @@ struct opbdFormat0 bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id, hb_glyph_extents_t *extents, const void *base) const { - const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); + const Offset16To<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); if (!bounds_offset) return false; const OpticalBounds &bounds = base+*bounds_offset; @@ -79,7 +79,7 @@ struct opbdFormat0 } protected: - Lookup<OffsetTo<OpticalBounds>> + Lookup<Offset16To<OpticalBounds>> lookupTable; /* Lookup table associating glyphs with the four * int16 values for the left-side, top-side, * right-side, and bottom-side optical bounds. */ @@ -92,7 +92,7 @@ struct opbdFormat1 bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id, hb_glyph_extents_t *extents, const void *base) const { - const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); + const Offset16To<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); if (!bounds_offset) return false; const OpticalBounds &bounds = base+*bounds_offset; @@ -116,7 +116,7 @@ struct opbdFormat1 } protected: - Lookup<OffsetTo<OpticalBounds>> + Lookup<Offset16To<OpticalBounds>> lookupTable; /* Lookup table associating glyphs with the four * int16 values for the left-side, top-side, * right-side, and bottom-side optical bounds. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh index baa1c72020f..68bcb2396f5 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh @@ -66,7 +66,7 @@ struct TrackTableEntry NameID trackNameID; /* The 'name' table index for this track. * (a short word or phrase like "loose" * or "very tight") */ - NNOffsetTo<UnsizedArrayOf<FWORD>> + NNOffset16To<UnsizedArrayOf<FWORD>> valuesZ; /* Offset from start of tracking table to * per-size tracking values for this track. */ @@ -141,7 +141,7 @@ struct TrackData protected: HBUINT16 nTracks; /* Number of separate tracks included in this table. */ HBUINT16 nSizes; /* Number of point sizes included in this table. */ - LNNOffsetTo<UnsizedArrayOf<HBFixed>> + NNOffset32To<UnsizedArrayOf<HBFixed>> sizeTable; /* Offset from start of the tracking table to * Array[nSizes] of size values.. */ UnsizedArrayOf<TrackTableEntry> @@ -212,10 +212,10 @@ struct trak FixedVersion<>version; /* Version of the tracking table * (0x00010000u for version 1.0). */ HBUINT16 format; /* Format of the tracking table (set to 0). */ - OffsetTo<TrackData> + Offset16To<TrackData> horizData; /* Offset from start of tracking table to TrackData * for horizontal text (or 0 if none). */ - OffsetTo<TrackData> + Offset16To<TrackData> vertData; /* Offset from start of tracking table to TrackData * for vertical text (or 0 if none). */ HBUINT16 reserved; /* Reserved. Set to 0. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh index 711f9aa6c18..6d771e1513e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh @@ -50,7 +50,7 @@ struct FTStringRange } protected: - NNOffsetTo<UnsizedArrayOf<HBUINT8>> + NNOffset16To<UnsizedArrayOf<HBUINT8>> tag; /* Offset from the start of the table to * the beginning of the string */ HBUINT16 length; /* String length (in bytes) */ @@ -80,7 +80,7 @@ struct ltag protected: HBUINT32 version; /* Table version; currently 1 */ HBUINT32 flags; /* Table flags; currently none defined */ - LArrayOf<FTStringRange> + Array32Of<FTStringRange> tagRanges; /* Range for each tag's string */ public: DEFINE_SIZE_ARRAY (12, tagRanges); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh index 02bd8d81c2f..9af98b103c0 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh @@ -219,7 +219,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> unsigned P = sizeof (Type), hb_enable_if (P == 1)> const T *as () const - { return length < hb_null_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); } + { return length < hb_min_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); } template <typename T, unsigned P = sizeof (Type), diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh index 91a9b7d0d16..c251e2d0ed1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh @@ -263,7 +263,7 @@ struct UnsizedByteStr : UnsizedArrayOf <HBUINT8> T *ip = c->allocate_size<T> (T::static_size); if (unlikely (!ip)) return_trace (false); - return_trace (c->check_assign (*ip, value)); + return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } template <typename V> 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 fc8d424bfb0..111058c8e6e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh @@ -86,6 +86,9 @@ #define HB_NO_LEGACY #endif +#ifdef HAVE_CONFIG_OVERRIDE_H +#include "config-override.h" +#endif /* Closure of options. */ @@ -155,9 +158,5 @@ #endif #endif -#ifdef HAVE_CONFIG_OVERRIDE_H -#include "config-override.h" -#endif - #endif /* HB_CONFIG_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh index ec3a1ff2111..a92614d01d4 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh @@ -438,6 +438,10 @@ struct hb_no_trace_t { #define TRACE_SUBSET(this) hb_no_trace_t<bool> trace #endif +#ifndef HB_DEBUG_SUBSET_REPACK +#define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0) +#endif + #ifndef HB_DEBUG_DISPATCH #define HB_DEBUG_DISPATCH ( \ HB_DEBUG_APPLY + \ 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 a07302159ce..aebe9e05419 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc @@ -623,7 +623,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan, * but we never attempt to shape a word longer than 64K characters * in a single gfxShapedWord, so we cannot exceed that limit. */ - uint32_t textLength = buffer->len; + uint32_t textLength = chars_len; TextAnalysis analysis (textString, textLength, nullptr, readingDirection); TextAnalysis::Run *runHead; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh index 84fe1d549bd..ab9c17eb1c7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh @@ -140,9 +140,9 @@ struct hb_hashmap_t return true; } - void set (K key, V value) + bool set (K key, V value) { - set_with_hash (key, hb_hash (key), value); + return set_with_hash (key, hb_hash (key), value); } V get (K key) const @@ -211,15 +211,15 @@ struct hb_hashmap_t protected: - void set_with_hash (K key, uint32_t hash, V value) + bool set_with_hash (K key, uint32_t hash, V value) { - if (unlikely (!successful)) return; - if (unlikely (key == kINVALID)) return; - if ((occupancy + occupancy / 2) >= mask && !resize ()) return; + if (unlikely (!successful)) return false; + if (unlikely (key == kINVALID)) return true; + if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; unsigned int i = bucket_for_hash (key, hash); if (value == vINVALID && items[i].key != key) - return; /* Trying to delete non-existent key. */ + return true; /* Trying to delete non-existent key. */ if (!items[i].is_unused ()) { @@ -235,6 +235,8 @@ struct hb_hashmap_t occupancy++; if (!items[i].is_tombstone ()) population++; + + return true; } unsigned int bucket_for (K key) const diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh index d09f858cde3..db38a4dfd24 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh @@ -39,8 +39,11 @@ #define HB_NULL_POOL_SIZE 384 -/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size, - * otherwise return sizeof(T). */ +/* Use SFINAE to sniff whether T has min_size; in which case return the larger + * of sizeof(T) and T::null_size, otherwise return sizeof(T). + * + * The main purpose of this is to let structs communicate that they are not nullable, + * by defining min_size but *not* null_size. */ /* The hard way... * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol @@ -49,8 +52,9 @@ template <typename T, typename> struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {}; template <typename T> -struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::null_size> {}; - +struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>> + : hb_integral_constant<unsigned, + (sizeof (T) > T::null_size ? sizeof (T) : T::null_size)> {}; template <typename T> using hb_null_size = _hb_null_size<T, void>; #define hb_null_size(T) hb_null_size<T>::value @@ -68,6 +72,14 @@ template <typename T> using hb_static_size = _hb_static_size<T, void>; #define hb_static_size(T) hb_static_size<T>::value +template <typename T, typename> +struct _hb_min_size : hb_integral_constant<unsigned, sizeof (T)> {}; +template <typename T> +struct _hb_min_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::min_size> {}; +template <typename T> +using hb_min_size = _hb_min_size<T, void>; +#define hb_min_size(T) hb_min_size<T>::value + /* * Null() diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh index 54c07ff13cb..66ca03076ba 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh @@ -218,7 +218,7 @@ struct TTCHeaderVersion1 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ FixedVersion<>version; /* Version of the TTC Header (1.0), * 0x00010000u */ - LArrayOf<LOffsetTo<OpenTypeOffsetTable>> + Array32Of<Offset32To<OpenTypeOffsetTable>> table; /* Array of offsets to the OffsetTable for each font * from the beginning of the file */ public: @@ -295,7 +295,7 @@ struct ResourceRecord HBINT16 nameOffset; /* Offset from beginning of resource name list * to resource name, -1 means there is none. */ HBUINT8 attrs; /* Resource attributes */ - NNOffsetTo<LArrayOf<HBUINT8>, HBUINT24> + NNOffset24To<Array32Of<HBUINT8>> offset; /* Offset from beginning of data block to * data for this resource */ HBUINT32 reserved; /* Reserved for handle to resource */ @@ -330,7 +330,7 @@ struct ResourceTypeRecord protected: Tag tag; /* Resource type. */ HBUINT16 resCountM1; /* Number of resources minus 1. */ - NNOffsetTo<UnsizedArrayOf<ResourceRecord>> + NNOffset16To<UnsizedArrayOf<ResourceRecord>> resourcesZ; /* Offset from beginning of resource type list * to reference item list for this type. */ public: @@ -386,7 +386,7 @@ struct ResourceMap HBUINT32 reserved1; /* Reserved for handle to next resource map */ HBUINT16 resreved2; /* Reserved for file reference number */ HBUINT16 attrs; /* Resource fork attribute */ - NNOffsetTo<ArrayOfM1<ResourceTypeRecord>> + NNOffset16To<ArrayOfM1<ResourceTypeRecord>> typeList; /* Offset from beginning of map to * resource type list */ Offset16 nameList; /* Offset from beginning of map to @@ -418,10 +418,10 @@ struct ResourceForkHeader } protected: - LNNOffsetTo<UnsizedArrayOf<HBUINT8>> + NNOffset32To<UnsizedArrayOf<HBUINT8>> data; /* Offset from beginning of resource fork * to resource data */ - LNNOffsetTo<ResourceMap > + NNOffset32To<ResourceMap > map; /* Offset from beginning of resource fork * to resource map */ HBUINT32 dataLen; /* Length of resource data */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh index dc0ae1d9899..42eb8af05a9 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh @@ -196,6 +196,12 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, Index); typedef Index NameID; +struct VarIdx : HBUINT32 { + static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu; + VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; } +}; +DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx); + /* Offset, Null offset = 0 */ template <typename Type, bool has_null=true> struct Offset : Type @@ -209,7 +215,9 @@ struct Offset : Type void *serialize (hb_serialize_context_t *c, const void *base) { void *t = c->start_embed<void> (); - c->check_assign (*this, (unsigned) ((char *) t - (char *) base)); + c->check_assign (*this, + (unsigned) ((char *) t - (char *) base), + HB_SERIALIZE_ERROR_OFFSET_OVERFLOW); return t; } @@ -218,6 +226,7 @@ struct Offset : Type }; typedef Offset<HBUINT16> Offset16; +typedef Offset<HBUINT24> Offset24; typedef Offset<HBUINT32> Offset32; @@ -287,7 +296,7 @@ struct _hb_has_null<Type, true> static Type *get_crap () { return &Crap (Type); } }; -template <typename Type, typename OffsetType=HBUINT16, bool has_null=true> +template <typename Type, typename OffsetType, bool has_null=true> struct OffsetTo : Offset<OffsetType, has_null> { HB_DELETE_COPY_ASSIGN (OffsetTo); @@ -378,7 +387,7 @@ struct OffsetTo : Offset<OffsetType, has_null> TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); if (unlikely (this->is_null ())) return_trace (true); - if (unlikely (!c->check_range (base, *this))) return_trace (false); + if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false); return_trace (true); } @@ -401,12 +410,14 @@ struct OffsetTo : Offset<OffsetType, has_null> DEFINE_SIZE_STATIC (sizeof (OffsetType)); }; /* Partial specializations. */ -template <typename Type, bool has_null=true> -using LOffsetTo = OffsetTo<Type, HBUINT32, has_null>; -template <typename Type, typename OffsetType=HBUINT16> -using NNOffsetTo = OffsetTo<Type, OffsetType, false>; -template <typename Type> -using LNNOffsetTo = LOffsetTo<Type, false>; +template <typename Type, bool has_null=true> using Offset16To = OffsetTo<Type, HBUINT16, has_null>; +template <typename Type, bool has_null=true> using Offset24To = OffsetTo<Type, HBUINT24, has_null>; +template <typename Type, bool has_null=true> using Offset32To = OffsetTo<Type, HBUINT32, has_null>; + +template <typename Type, typename OffsetType> using NNOffsetTo = OffsetTo<Type, OffsetType, false>; +template <typename Type> using NNOffset16To = Offset16To<Type, false>; +template <typename Type> using NNOffset24To = Offset24To<Type, false>; +template <typename Type> using NNOffset32To = Offset32To<Type, false>; /* @@ -513,11 +524,11 @@ struct UnsizedArrayOf /* Unsized array of offset's */ template <typename Type, typename OffsetType, bool has_null=true> -using UnsizedOffsetArrayOf = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>; +using UnsizedArray16OfOffsetTo = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>; /* Unsized array of offsets relative to the beginning of the array itself. */ template <typename Type, typename OffsetType, bool has_null=true> -struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null> +struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_null> { const Type& operator [] (int i_) const { @@ -538,7 +549,7 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null> bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const { TRACE_SANITIZE (this); - return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null> + return_trace ((UnsizedArray16OfOffsetTo<Type, OffsetType, has_null> ::sanitize (c, count, this, hb_forward<Ts> (ds)...))); } }; @@ -569,7 +580,7 @@ struct SortedUnsizedArrayOf : UnsizedArrayOf<Type> /* An array with a number of elements. */ -template <typename Type, typename LenType=HBUINT16> +template <typename Type, typename LenType> struct ArrayOf { typedef Type item_t; @@ -617,17 +628,30 @@ struct ArrayOf hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) { return as_array ().sub_array (start_offset, count); } - hb_success_t serialize (hb_serialize_context_t *c, unsigned items_len) + template <typename T> + Type &lsearch (const T &x, Type ¬_found = Crap (Type)) + { return *as_array ().lsearch (x, ¬_found); } + template <typename T> + const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const + { return *as_array ().lsearch (x, ¬_found); } + template <typename T> + bool lfind (const T &x, unsigned *pos = nullptr) const + { return as_array ().lfind (x, pos); } + + void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) + { as_array ().qsort (start, end); } + + HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - c->check_assign (len, items_len); + c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); if (unlikely (!c->extend (*this))) return_trace (false); return_trace (true); } template <typename Iterator, hb_requires (hb_is_source_of (Iterator, Type))> - hb_success_t serialize (hb_serialize_context_t *c, Iterator items) + HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items) { TRACE_SERIALIZE (this); unsigned count = items.len (); @@ -656,7 +680,7 @@ struct ArrayOf TRACE_SERIALIZE (this); auto *out = c->start_embed (this); if (unlikely (!c->extend_min (out))) return_trace (nullptr); - c->check_assign (out->len, len); + c->check_assign (out->len, len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); if (unlikely (!as_array ().copy (c))) return_trace (nullptr); return_trace (out); } @@ -674,19 +698,6 @@ struct ArrayOf return_trace (true); } - template <typename T> - Type &lsearch (const T &x, Type ¬_found = Crap (Type)) - { return *as_array ().lsearch (x, ¬_found); } - template <typename T> - const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const - { return *as_array ().lsearch (x, ¬_found); } - template <typename T> - bool lfind (const T &x, unsigned *pos = nullptr) const - { return as_array ().lfind (x, pos); } - - void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) - { as_array ().qsort (start, end); } - bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -699,21 +710,18 @@ struct ArrayOf public: DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); }; -template <typename Type> -using LArrayOf = ArrayOf<Type, HBUINT32>; +template <typename Type> using Array16Of = ArrayOf<Type, HBUINT16>; +template <typename Type> using Array32Of = ArrayOf<Type, HBUINT32>; using PString = ArrayOf<HBUINT8, HBUINT8>; /* Array of Offset's */ -template <typename Type> -using OffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT16>>; -template <typename Type> -using LOffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>>; -template <typename Type> -using LOffsetLArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>; +template <typename Type> using Array16OfOffset16To = ArrayOf<OffsetTo<Type, HBUINT16>, HBUINT16>; +template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT16>; +template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>; /* Array of offsets relative to the beginning of the array itself. */ template <typename Type> -struct OffsetListOf : OffsetArrayOf<Type> +struct List16OfOffset16To : Array16OfOffset16To<Type> { const Type& operator [] (int i_) const { @@ -731,7 +739,7 @@ struct OffsetListOf : OffsetArrayOf<Type> bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct OffsetListOf<Type> *out = c->serializer->embed (*this); + struct List16OfOffset16To<Type> *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); unsigned int count = this->len; for (unsigned int i = 0; i < count; i++) @@ -743,7 +751,7 @@ struct OffsetListOf : OffsetArrayOf<Type> bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); - return_trace (OffsetArrayOf<Type>::sanitize (c, this, hb_forward<Ts> (ds)...)); + return_trace (Array16OfOffset16To<Type>::sanitize (c, this, hb_forward<Ts> (ds)...)); } }; @@ -787,7 +795,7 @@ struct HeadlessArrayOf { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - c->check_assign (lenP1, items_len + 1); + c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); if (unlikely (!c->extend (*this))) return_trace (false); return_trace (true); } @@ -859,6 +867,7 @@ struct ArrayOfM1 { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); + if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); unsigned int count = lenM1 + 1; for (unsigned int i = 0; i < count; i++) if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...))) @@ -882,7 +891,7 @@ struct ArrayOfM1 }; /* An array with sorted elements. Supports binary searching. */ -template <typename Type, typename LenType=HBUINT16> +template <typename Type, typename LenType> struct SortedArrayOf : ArrayOf<Type, LenType> { hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->len); } @@ -933,6 +942,9 @@ struct SortedArrayOf : ArrayOf<Type, LenType> { return as_array ().bfind (x, i, not_found, to_store); } }; +template <typename Type> using SortedArray16Of = SortedArrayOf<Type, HBUINT16>; +template <typename Type> using SortedArray32Of = SortedArrayOf<Type, HBUINT32>; + /* * Binary-search arrays */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh index 7228f777272..157483b7f65 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh @@ -1390,7 +1390,7 @@ struct cff1 public: FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */ - OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */ + NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */ HBUINT8 offSize; /* offset size (unused?) */ public: 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 878e02ff177..add21f11550 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 @@ -276,7 +276,9 @@ struct CmapSubtableFormat4 HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount); if (unlikely (!c->check_success (idRangeOffset))) return; - if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return; + if (unlikely (!c->check_assign(this->length, + c->length () - table_initpos, + HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; this->segCountX2 = segcount * 2; this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1; this->searchRange = 2 * (1u << this->entrySelector); @@ -670,7 +672,7 @@ struct CmapSubtableLongSegmented HBUINT16 reserved; /* Reserved; set to 0. */ HBUINT32 length; /* Byte length of this subtable. */ HBUINT32 language; /* Ignore. */ - SortedArrayOf<CmapSubtableLongGroup, HBUINT32> + SortedArray32Of<CmapSubtableLongGroup> groups; /* Groupings. */ public: DEFINE_SIZE_ARRAY (16, groups); @@ -784,7 +786,7 @@ struct UnicodeValueRange DEFINE_SIZE_STATIC (4); }; -struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32> +struct DefaultUVS : SortedArray32Of<UnicodeValueRange> { void collect_unicodes (hb_set_t *out) const { @@ -850,7 +852,9 @@ struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32> } else { - if (unlikely (!c->check_assign (out->len, (c->length () - init_len) / UnicodeValueRange::static_size))) return nullptr; + if (unlikely (!c->check_assign (out->len, + (c->length () - init_len) / UnicodeValueRange::static_size, + HB_SERIALIZE_ERROR_INT_OVERFLOW))) return nullptr; return out; } } @@ -876,23 +880,21 @@ struct UVSMapping DEFINE_SIZE_STATIC (5); }; -struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32> +struct NonDefaultUVS : SortedArray32Of<UVSMapping> { void collect_unicodes (hb_set_t *out) const { - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - out->add (arrayZ[i].unicodeValue); + for (const auto& a : as_array ()) + out->add (a.unicodeValue); } void collect_mapping (hb_set_t *unicodes, /* OUT */ hb_map_t *mapping /* OUT */) const { - unsigned count = len; - for (unsigned i = 0; i < count; i++) + for (const auto& a : as_array ()) { - hb_codepoint_t unicode = arrayZ[i].unicodeValue; - hb_codepoint_t glyphid = arrayZ[i].glyphID; + hb_codepoint_t unicode = a.unicodeValue; + hb_codepoint_t glyphid = a.glyphID; unicodes->add (unicode); mapping->set (unicode, glyphid); } @@ -1041,9 +1043,9 @@ struct VariationSelectorRecord } HBUINT24 varSelector; /* Variation selector. */ - LOffsetTo<DefaultUVS> + Offset32To<DefaultUVS> defaultUVS; /* Offset to Default UVS Table. May be 0. */ - LOffsetTo<NonDefaultUVS> + Offset32To<NonDefaultUVS> nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */ public: DEFINE_SIZE_STATIC (11); @@ -1058,9 +1060,8 @@ struct CmapSubtableFormat14 void collect_variation_selectors (hb_set_t *out) const { - unsigned int count = record.len; - for (unsigned int i = 0; i < count; i++) - out->add (record.arrayZ[i].varSelector); + for (const auto& a : record.as_array ()) + out->add (a.varSelector); } void collect_variation_unicodes (hb_codepoint_t variation_selector, hb_set_t *out) const @@ -1112,10 +1113,12 @@ struct CmapSubtableFormat14 return; int tail_len = init_tail - c->tail; - c->check_assign (this->length, c->length () - table_initpos + tail_len); + c->check_assign (this->length, c->length () - table_initpos + tail_len, + HB_SERIALIZE_ERROR_INT_OVERFLOW); c->check_assign (this->record.len, (c->length () - table_initpos - CmapSubtableFormat14::min_size) / - VariationSelectorRecord::static_size); + VariationSelectorRecord::static_size, + HB_SERIALIZE_ERROR_INT_OVERFLOW); /* Correct the incorrect write order by reversing the order of the variation records array. */ @@ -1180,7 +1183,7 @@ struct CmapSubtableFormat14 protected: HBUINT16 format; /* Format number is set to 14. */ HBUINT32 length; /* Byte length of this subtable. */ - SortedArrayOf<VariationSelectorRecord, HBUINT32> + SortedArray32Of<VariationSelectorRecord> record; /* Variation selector records; sorted * in increasing order of `varSelector'. */ public: @@ -1338,7 +1341,7 @@ struct EncodingRecord HBUINT16 platformID; /* Platform ID. */ HBUINT16 encodingID; /* Platform-specific encoding ID. */ - LOffsetTo<CmapSubtable> + Offset32To<CmapSubtable> subtable; /* Byte offset from beginning of table to the subtable for this encoding. */ public: DEFINE_SIZE_STATIC (8); @@ -1401,7 +1404,9 @@ struct cmap } } - c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size); + c->check_assign(this->encodingRecord.len, + (c->length () - cmap::min_size)/EncodingRecord::static_size, + HB_SERIALIZE_ERROR_INT_OVERFLOW); } void closure_glyphs (const hb_set_t *unicodes, @@ -1697,7 +1702,7 @@ struct cmap protected: HBUINT16 version; /* Table version number (0). */ - SortedArrayOf<EncodingRecord> + SortedArray16Of<EncodingRecord> encodingRecord; /* Encoding tables. */ public: DEFINE_SIZE_ARRAY (4, encodingRecord); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh index e285acec3d5..265d8309daa 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh @@ -510,7 +510,7 @@ struct IndexSubtableRecord HBGlyphID firstGlyphIndex; HBGlyphID lastGlyphIndex; - LOffsetTo<IndexSubtable> offsetToSubtable; + Offset32To<IndexSubtable> offsetToSubtable; public: DEFINE_SIZE_STATIC (8); }; @@ -672,7 +672,7 @@ struct BitmapSizeTable } protected: - LNNOffsetTo<IndexSubtableArray> + NNOffset32To<IndexSubtableArray> indexSubtableArrayOffset; HBUINT32 indexTablesSize; HBUINT32 numberOfIndexSubtables; @@ -697,7 +697,7 @@ struct BitmapSizeTable struct GlyphBitmapDataFormat17 { SmallGlyphMetrics glyphMetrics; - LArrayOf<HBUINT8> data; + Array32Of<HBUINT8> data; public: DEFINE_SIZE_ARRAY (9, data); }; @@ -705,14 +705,14 @@ struct GlyphBitmapDataFormat17 struct GlyphBitmapDataFormat18 { BigGlyphMetrics glyphMetrics; - LArrayOf<HBUINT8> data; + Array32Of<HBUINT8> data; public: DEFINE_SIZE_ARRAY (12, data); }; struct GlyphBitmapDataFormat19 { - LArrayOf<HBUINT8> data; + Array32Of<HBUINT8> data; public: DEFINE_SIZE_ARRAY (4, data); }; @@ -798,7 +798,7 @@ struct CBLC protected: FixedVersion<> version; - LArrayOf<BitmapSizeTable> sizeTables; + Array32Of<BitmapSizeTable> sizeTables; public: DEFINE_SIZE_ARRAY (8, sizeTables); }; 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 e2a1ff46624..c792147095a 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 @@ -29,6 +29,7 @@ #define HB_OT_COLOR_COLR_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-layout-common.hh" /* * COLR -- Color @@ -39,7 +40,6 @@ namespace OT { - struct LayerRecord { operator hb_ot_color_layer_t () const { return {glyphId, colorIdx}; } @@ -90,6 +90,467 @@ struct BaseGlyphRecord DEFINE_SIZE_STATIC (6); }; +template <typename T> +struct Variable +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + T value; + VarIdx varIdx; + public: + DEFINE_SIZE_STATIC (4 + T::static_size); +}; + +template <typename T> +struct NoVariable +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + T value; + public: + DEFINE_SIZE_STATIC (T::static_size); +}; + +// Color structures + +template <template<typename> class Var> +struct ColorIndex +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT16 paletteIndex; + Var<F2DOT14> alpha; + public: + DEFINE_SIZE_STATIC (2 + Var<F2DOT14>::static_size); +}; + +template <template<typename> class Var> +struct ColorStop +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + Var<F2DOT14> stopOffset; + ColorIndex<Var> color; + public: + DEFINE_SIZE_STATIC (Var<F2DOT14>::static_size + ColorIndex<Var>::static_size); +}; + +struct Extend : HBUINT8 +{ + enum { + EXTEND_PAD = 0, + EXTEND_REPEAT = 1, + EXTEND_REFLECT = 2, + }; + public: + DEFINE_SIZE_STATIC (1); +}; + +template <template<typename> class Var> +struct ColorLine +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + stops.sanitize (c)); + } + + Extend extend; + Array16Of<ColorStop<Var>> stops; + public: + DEFINE_SIZE_ARRAY_SIZED (3, stops); +}; + +// Composition modes + +// Compositing modes are taken from https://www.w3.org/TR/compositing-1/ +// NOTE: a brief audit of major implementations suggests most support most +// or all of the specified modes. +struct CompositeMode : HBUINT8 +{ + enum { + // Porter-Duff modes + // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators + COMPOSITE_CLEAR = 0, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_clear + COMPOSITE_SRC = 1, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_src + COMPOSITE_DEST = 2, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dst + COMPOSITE_SRC_OVER = 3, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcover + COMPOSITE_DEST_OVER = 4, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstover + COMPOSITE_SRC_IN = 5, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin + COMPOSITE_DEST_IN = 6, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstin + COMPOSITE_SRC_OUT = 7, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcout + COMPOSITE_DEST_OUT = 8, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstout + COMPOSITE_SRC_ATOP = 9, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcatop + COMPOSITE_DEST_ATOP = 10, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstatop + COMPOSITE_XOR = 11, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_xor + COMPOSITE_PLUS = 12, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_plus + + // Blend modes + // https://www.w3.org/TR/compositing-1/#blending + COMPOSITE_SCREEN = 13, // https://www.w3.org/TR/compositing-1/#blendingscreen + COMPOSITE_OVERLAY = 14, // https://www.w3.org/TR/compositing-1/#blendingoverlay + COMPOSITE_DARKEN = 15, // https://www.w3.org/TR/compositing-1/#blendingdarken + COMPOSITE_LIGHTEN = 16, // https://www.w3.org/TR/compositing-1/#blendinglighten + COMPOSITE_COLOR_DODGE = 17, // https://www.w3.org/TR/compositing-1/#blendingcolordodge + COMPOSITE_COLOR_BURN = 18, // https://www.w3.org/TR/compositing-1/#blendingcolorburn + COMPOSITE_HARD_LIGHT = 19, // https://www.w3.org/TR/compositing-1/#blendinghardlight + COMPOSITE_SOFT_LIGHT = 20, // https://www.w3.org/TR/compositing-1/#blendingsoftlight + COMPOSITE_DIFFERENCE = 21, // https://www.w3.org/TR/compositing-1/#blendingdifference + COMPOSITE_EXCLUSION = 22, // https://www.w3.org/TR/compositing-1/#blendingexclusion + COMPOSITE_MULTIPLY = 23, // https://www.w3.org/TR/compositing-1/#blendingmultiply + + // Modes that, uniquely, do not operate on components + // https://www.w3.org/TR/compositing-1/#blendingnonseparable + COMPOSITE_HSL_HUE = 24, // https://www.w3.org/TR/compositing-1/#blendinghue + COMPOSITE_HSL_SATURATION = 25, // https://www.w3.org/TR/compositing-1/#blendingsaturation + COMPOSITE_HSL_COLOR = 26, // https://www.w3.org/TR/compositing-1/#blendingcolor + COMPOSITE_HSL_LUMINOSITY = 27, // https://www.w3.org/TR/compositing-1/#blendingluminosity + }; + public: + DEFINE_SIZE_STATIC (1); +}; + +template <template<typename> class Var> +struct Affine2x3 +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + Var<HBFixed> xx; + Var<HBFixed> yx; + Var<HBFixed> xy; + Var<HBFixed> yy; + Var<HBFixed> dx; + Var<HBFixed> dy; + public: + DEFINE_SIZE_STATIC (6 * Var<HBFixed>::static_size); +}; + +struct PaintColrLayers +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT8 format; /* format = 1 */ + HBUINT8 numLayers; + HBUINT32 firstLayerIndex; /* index into COLRv1::layersV1 */ + public: + DEFINE_SIZE_STATIC (6); +}; + +template <template<typename> class Var> +struct PaintSolid +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT8 format; /* format = 2(noVar) or 3(Var)*/ + ColorIndex<Var> color; + public: + DEFINE_SIZE_STATIC (1 + ColorIndex<Var>::static_size); +}; + +template <template<typename> class Var> +struct PaintLinearGradient +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && colorLine.sanitize (c, this)); + } + + HBUINT8 format; /* format = 4(noVar) or 5 (Var) */ + Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintLinearGradient + * table) to ColorLine subtable. */ + Var<FWORD> x0; + Var<FWORD> y0; + Var<FWORD> x1; + Var<FWORD> y1; + Var<FWORD> x2; + Var<FWORD> y2; + public: + DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size); +}; + +template <template<typename> class Var> +struct PaintRadialGradient +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && colorLine.sanitize (c, this)); + } + + HBUINT8 format; /* format = 6(noVar) or 7 (Var) */ + Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintRadialGradient + * table) to ColorLine subtable. */ + Var<FWORD> x0; + Var<FWORD> y0; + Var<UFWORD> radius0; + Var<FWORD> x1; + Var<FWORD> y1; + Var<UFWORD> radius1; + public: + DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size); +}; + +template <template<typename> class Var> +struct PaintSweepGradient +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && colorLine.sanitize (c, this)); + } + + HBUINT8 format; /* format = 8(noVar) or 9 (Var) */ + Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintSweepGradient + * table) to ColorLine subtable. */ + Var<FWORD> centerX; + Var<FWORD> centerY; + Var<HBFixed> startAngle; + Var<HBFixed> endAngle; + public: + DEFINE_SIZE_STATIC (2 * Var<FWORD>::static_size + 2 * Var<HBFixed>::static_size); +}; + +struct Paint; +// Paint a non-COLR glyph, filled as indicated by paint. +struct PaintGlyph +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && paint.sanitize (c, this)); + } + + HBUINT8 format; /* format = 10 */ + Offset24To<Paint> paint; /* Offset (from beginning of PaintGlyph table) to Paint subtable. */ + HBUINT16 gid; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct PaintColrGlyph +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT8 format; /* format = 11 */ + HBUINT16 gid; + public: + DEFINE_SIZE_STATIC (3); +}; + +template <template<typename> class Var> +struct PaintTransform +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 12(noVar) or 13 (Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */ + Affine2x3<Var> transform; + public: + DEFINE_SIZE_STATIC (4 + Affine2x3<Var>::static_size); +}; + +template <template<typename> class Var> +struct PaintTranslate +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 14(noVar) or 15 (Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */ + Var<HBFixed> dx; + Var<HBFixed> dy; + public: + DEFINE_SIZE_STATIC (4 + Var<HBFixed>::static_size); +}; + +template <template<typename> class Var> +struct PaintRotate +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 16 (noVar) or 17(Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */ + Var<HBFixed> angle; + Var<HBFixed> centerX; + Var<HBFixed> centerY; + public: + DEFINE_SIZE_STATIC (4 + 3 * Var<HBFixed>::static_size); +}; + +template <template<typename> class Var> +struct PaintSkew +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 18(noVar) or 19 (Var) */ + Offset24To<Paint> src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */ + Var<HBFixed> xSkewAngle; + Var<HBFixed> ySkewAngle; + Var<HBFixed> centerX; + Var<HBFixed> centerY; + public: + DEFINE_SIZE_STATIC (4 + 4 * Var<HBFixed>::static_size); +}; + +struct PaintComposite +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + src.sanitize (c, this) && + backdrop.sanitize (c, this)); + } + + HBUINT8 format; /* format = 20 */ + Offset24To<Paint> src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */ + CompositeMode mode; /* If mode is unrecognized use COMPOSITE_CLEAR */ + Offset24To<Paint> backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */ + public: + DEFINE_SIZE_STATIC (8); +}; + +struct Paint +{ + template <typename context_t, typename ...Ts> + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + TRACE_DISPATCH (this, u.format); + if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { + case 1: return_trace (c->dispatch (u.paintformat1, hb_forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.paintformat2, hb_forward<Ts> (ds)...)); + case 3: return_trace (c->dispatch (u.paintformat3, hb_forward<Ts> (ds)...)); + case 4: return_trace (c->dispatch (u.paintformat4, hb_forward<Ts> (ds)...)); + case 5: return_trace (c->dispatch (u.paintformat5, hb_forward<Ts> (ds)...)); + case 6: return_trace (c->dispatch (u.paintformat6, hb_forward<Ts> (ds)...)); + case 7: return_trace (c->dispatch (u.paintformat7, hb_forward<Ts> (ds)...)); + case 8: return_trace (c->dispatch (u.paintformat8, hb_forward<Ts> (ds)...)); + case 9: return_trace (c->dispatch (u.paintformat9, hb_forward<Ts> (ds)...)); + case 10: return_trace (c->dispatch (u.paintformat10, hb_forward<Ts> (ds)...)); + case 11: return_trace (c->dispatch (u.paintformat11, hb_forward<Ts> (ds)...)); + case 12: return_trace (c->dispatch (u.paintformat12, hb_forward<Ts> (ds)...)); + case 13: return_trace (c->dispatch (u.paintformat13, hb_forward<Ts> (ds)...)); + case 14: return_trace (c->dispatch (u.paintformat14, hb_forward<Ts> (ds)...)); + case 15: return_trace (c->dispatch (u.paintformat15, hb_forward<Ts> (ds)...)); + case 16: return_trace (c->dispatch (u.paintformat16, hb_forward<Ts> (ds)...)); + case 17: return_trace (c->dispatch (u.paintformat17, hb_forward<Ts> (ds)...)); + case 18: return_trace (c->dispatch (u.paintformat18, hb_forward<Ts> (ds)...)); + case 19: return_trace (c->dispatch (u.paintformat19, hb_forward<Ts> (ds)...)); + case 20: return_trace (c->dispatch (u.paintformat20, hb_forward<Ts> (ds)...)); + default:return_trace (c->default_return_value ()); + } + } + + protected: + union { + HBUINT8 format; + PaintColrLayers paintformat1; + PaintSolid<NoVariable> paintformat2; + PaintSolid<Variable> paintformat3; + PaintLinearGradient<NoVariable> paintformat4; + PaintLinearGradient<Variable> paintformat5; + PaintRadialGradient<NoVariable> paintformat6; + PaintRadialGradient<Variable> paintformat7; + PaintSweepGradient<NoVariable> paintformat8; + PaintSweepGradient<Variable> paintformat9; + PaintGlyph paintformat10; + PaintColrGlyph paintformat11; + PaintTransform<NoVariable> paintformat12; + PaintTransform<Variable> paintformat13; + PaintTranslate<NoVariable> paintformat14; + PaintTranslate<Variable> paintformat15; + PaintRotate<NoVariable> paintformat16; + PaintRotate<Variable> paintformat17; + PaintSkew<NoVariable> paintformat18; + PaintSkew<Variable> paintformat19; + PaintComposite paintformat20; + } u; +}; + +struct BaseGlyphV1Record +{ + int cmp (hb_codepoint_t g) const + { return g < glyphId ? -1 : g > glyphId ? 1 : 0; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && paint.sanitize (c, this))); + } + + public: + HBGlyphID glyphId; /* Glyph ID of reference glyph */ + Offset32To<Paint> paint; /* Offset (from beginning of BaseGlyphV1Record) to Paint, + * Typically PaintColrLayers */ + public: + DEFINE_SIZE_STATIC (6); +}; + +typedef SortedArray32Of<BaseGlyphV1Record> BaseGlyphV1List; + +struct LayerV1List : Array32OfOffset32To<Paint> +{ + const Paint& get_paint (unsigned i) const + { return this+(*this)[i]; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (Array32OfOffset32To<Paint>::sanitize (c, this)); + } +}; + struct COLR { static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR; @@ -150,9 +611,13 @@ struct COLR bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && - (this+layersZ).sanitize (c, numLayers))); + return_trace (c->check_struct (this) && + (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && + (this+layersZ).sanitize (c, numLayers) && + (version == 0 || (version == 1 && + baseGlyphsV1List.sanitize (c, this) && + layersV1.sanitize (c, this) && + varStore.sanitize (c, this)))); } template<typename BaseIterator, typename LayerIterator, @@ -263,13 +728,17 @@ struct COLR protected: HBUINT16 version; /* Table version number (starts at 0). */ HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */ - LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord>> + NNOffset32To<SortedUnsizedArrayOf<BaseGlyphRecord>> baseGlyphsZ; /* Offset to Base Glyph records. */ - LNNOffsetTo<UnsizedArrayOf<LayerRecord>> + NNOffset32To<UnsizedArrayOf<LayerRecord>> layersZ; /* Offset to Layer Records. */ HBUINT16 numLayers; /* Number of Layer Records. */ + // Version-1 additions + Offset32To<BaseGlyphV1List> baseGlyphsV1List; + Offset32To<LayerV1List> layersV1; + Offset32To<VariationStore> varStore; public: - DEFINE_SIZE_STATIC (14); + DEFINE_SIZE_MIN (14); }; } /* namespace OT */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh index fa7d3207be6..2fa99dead74 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh @@ -87,15 +87,15 @@ struct CPALV1Tail } protected: - LNNOffsetTo<UnsizedArrayOf<HBUINT32>> + NNOffset32To<UnsizedArrayOf<HBUINT32>> paletteFlagsZ; /* Offset from the beginning of CPAL table to * the Palette Type Array. Set to 0 if no array * is provided. */ - LNNOffsetTo<UnsizedArrayOf<NameID>> + NNOffset32To<UnsizedArrayOf<NameID>> paletteLabelsZ; /* Offset from the beginning of CPAL table to * the palette labels array. Set to 0 if no * array is provided. */ - LNNOffsetTo<UnsizedArrayOf<NameID>> + NNOffset32To<UnsizedArrayOf<NameID>> colorLabelsZ; /* Offset from the beginning of CPAL table to * the color labels array. Set to 0 * if no array is provided. */ @@ -173,7 +173,7 @@ struct CPAL HBUINT16 numPalettes; /* Number of palettes in the table. */ HBUINT16 numColorRecords; /* Total number of color records, combined for * all palettes. */ - LNNOffsetTo<UnsizedArrayOf<BGRAColor>> + NNOffset32To<UnsizedArrayOf<BGRAColor>> colorRecordsZ; /* Offset from the beginning of CPAL table to * the first ColorRecord. */ UnsizedArrayOf<HBUINT16> diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh index 09da11597da..af1e4a5dbeb 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh @@ -185,7 +185,7 @@ struct SBIXStrike HBUINT16 resolution; /* The device pixel density (in PPI) for which this * strike was designed. (E.g., 96 PPI, 192 PPI.) */ protected: - UnsizedArrayOf<LOffsetTo<SBIXGlyph>> + UnsizedArrayOf<Offset32To<SBIXGlyph>> imageOffsetsZ; /* Offset from the beginning of the strike data header * to bitmap data for an individual glyph ID. */ public: @@ -352,11 +352,11 @@ struct sbix { TRACE_SERIALIZE (this); - auto *out = c->serializer->start_embed<LOffsetLArrayOf<SBIXStrike>> (); + auto *out = c->serializer->start_embed<Array32OfOffset32To<SBIXStrike>> (); if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - hb_vector_t<LOffsetTo<SBIXStrike>*> new_strikes; + hb_vector_t<Offset32To<SBIXStrike>*> new_strikes; hb_vector_t<hb_serialize_context_t::objidx_t> objidxs; for (int i = strikes.len - 1; i >= 0; --i) { @@ -400,7 +400,7 @@ struct sbix HBUINT16 version; /* Table version number — set to 1 */ HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines. * Bits 2 to 15: reserved (set to 0). */ - LOffsetLArrayOf<SBIXStrike> + Array32OfOffset32To<SBIXStrike> strikes; /* Offsets from the beginning of the 'sbix' * table to data for each individual bitmap strike. */ public: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh index 1cc40ae53fa..e022ef43b79 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh @@ -62,7 +62,7 @@ struct SVGDocumentIndexEntry * this index entry. */ HBUINT16 endGlyphID; /* The last glyph ID in the range described by * this index entry. Must be >= startGlyphID. */ - LNNOffsetTo<UnsizedArrayOf<HBUINT8>> + NNOffset32To<UnsizedArrayOf<HBUINT8>> svgDoc; /* Offset from the beginning of the SVG Document Index * to an SVG document. Must be non-zero. */ HBUINT32 svgDocLength; /* Length of the SVG document. @@ -107,7 +107,7 @@ struct SVG protected: HBUINT16 version; /* Table version (starting at 0). */ - LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry>> + Offset32To<SortedArray16Of<SVGDocumentIndexEntry>> svgDocEntries; /* Offset (relative to the start of the SVG table) to the * SVG Documents Index. Must be non-zero. */ /* Array of SVG Document Index Entries. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh index 4f291924afd..f2a9cad464b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh @@ -71,7 +71,7 @@ struct gasp protected: HBUINT16 version; /* Version number (set to 1) */ - ArrayOf<GaspRange> + Array16Of<GaspRange> gaspRanges; /* Number of records to follow * Sorted by ppem */ public: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh index c9c391bad5f..590fa154ba1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh @@ -110,7 +110,7 @@ struct hdmx for (const hb_item_type<Iterator>& _ : +it) c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second); - return_trace (c->successful); + return_trace (c->successful ()); } 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 d06c0fa4a46..40383299382 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 @@ -146,7 +146,7 @@ struct hmtxvmtx _mtx.fini (); - if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ())) + if (unlikely (c->serializer->in_error ())) return_trace (false); // Amend header num hmetrics diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh index 4df0d942ceb..492947751e6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-base-table.hh @@ -103,7 +103,7 @@ struct BaseCoordFormat3 protected: HBUINT16 format; /* Format identifier--format = 3 */ FWORD coordinate; /* X or Y value, in design units */ - OffsetTo<Device> + Offset16To<Device> deviceTable; /* Offset to Device table for X or * Y value, from beginning of * BaseCoord table (may be NULL). */ @@ -173,11 +173,11 @@ struct FeatMinMaxRecord protected: Tag tag; /* 4-byte feature identification tag--must * match feature tag in FeatureList */ - OffsetTo<BaseCoord> + Offset16To<BaseCoord> minCoord; /* Offset to BaseCoord table that defines * the minimum extent value, from beginning * of MinMax table (may be NULL) */ - OffsetTo<BaseCoord> + Offset16To<BaseCoord> maxCoord; /* Offset to BaseCoord table that defines * the maximum extent value, from beginning * of MinMax table (may be NULL) */ @@ -212,15 +212,15 @@ struct MinMax } protected: - OffsetTo<BaseCoord> + Offset16To<BaseCoord> minCoord; /* Offset to BaseCoord table that defines * minimum extent value, from the beginning * of MinMax table (may be NULL) */ - OffsetTo<BaseCoord> + Offset16To<BaseCoord> maxCoord; /* Offset to BaseCoord table that defines * maximum extent value, from the beginning * of MinMax table (may be NULL) */ - SortedArrayOf<FeatMinMaxRecord> + SortedArray16Of<FeatMinMaxRecord> featMinMaxRecords; /* Array of FeatMinMaxRecords, in alphabetical * order by featureTableTag */ @@ -247,7 +247,7 @@ struct BaseValues Index defaultIndex; /* Index number of default baseline for this * script — equals index position of baseline tag * in baselineTags array of the BaseTagList */ - OffsetArrayOf<BaseCoord> + Array16OfOffset16To<BaseCoord> baseCoords; /* Number of BaseCoord tables defined — should equal * baseTagCount in the BaseTagList * @@ -275,7 +275,7 @@ struct BaseLangSysRecord protected: Tag baseLangSysTag; /* 4-byte language system identification tag */ - OffsetTo<MinMax> + Offset16To<MinMax> minMax; /* Offset to MinMax table, from beginning * of BaseScript table */ public: @@ -305,13 +305,13 @@ struct BaseScript } protected: - OffsetTo<BaseValues> + Offset16To<BaseValues> baseValues; /* Offset to BaseValues table, from beginning * of BaseScript table (may be NULL) */ - OffsetTo<MinMax> + Offset16To<MinMax> defaultMinMax; /* Offset to MinMax table, from beginning of * BaseScript table (may be NULL) */ - SortedArrayOf<BaseLangSysRecord> + SortedArray16Of<BaseLangSysRecord> baseLangSysRecords; /* Number of BaseLangSysRecords * defined — may be zero (0) */ @@ -339,7 +339,7 @@ struct BaseScriptRecord protected: Tag baseScriptTag; /* 4-byte script identification tag */ - OffsetTo<BaseScript> + Offset16To<BaseScript> baseScript; /* Offset to BaseScript table, from beginning * of BaseScriptList */ @@ -364,7 +364,7 @@ struct BaseScriptList } protected: - SortedArrayOf<BaseScriptRecord> + SortedArray16Of<BaseScriptRecord> baseScriptRecords; public: @@ -426,12 +426,12 @@ struct Axis } protected: - OffsetTo<SortedArrayOf<Tag>> + Offset16To<SortedArray16Of<Tag>> baseTagList; /* Offset to BaseTagList table, from beginning * of Axis table (may be NULL) * Array of 4-byte baseline identification tags — must * be in alphabetical order */ - OffsetTo<BaseScriptList> + Offset16To<BaseScriptList> baseScriptList; /* Offset to BaseScriptList table, from beginning * of Axis table * Array of BaseScriptRecords, in alphabetical order @@ -501,11 +501,11 @@ struct BASE protected: FixedVersion<>version; /* Version of the BASE table */ - OffsetTo<Axis>hAxis; /* Offset to horizontal Axis table, from beginning + Offset16To<Axis>hAxis; /* Offset to horizontal Axis table, from beginning * of BASE table (may be NULL) */ - OffsetTo<Axis>vAxis; /* Offset to vertical Axis table, from beginning + Offset16To<Axis>vAxis; /* Offset to vertical Axis table, from beginning * of BASE table (may be NULL) */ - LOffsetTo<VariationStore> + Offset32To<VariationStore> varStore; /* Offset to the table of Item Variation * Store--from beginning of BASE * header (may be NULL). Introduced 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 0ba7e3c0618..0fc66d2cbd1 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 @@ -88,12 +88,66 @@ static inline void ClassDef_serialize (hb_serialize_context_t *c, Iterator it); static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, - const hb_set_t &glyphset, const hb_map_t &gid_klass_map, hb_sorted_vector_t<HBGlyphID> &glyphs, const hb_set_t &klasses, + bool use_class_zero, hb_map_t *klass_map /*INOUT*/); + +struct hb_prune_langsys_context_t +{ + hb_prune_langsys_context_t (const void *table_, + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_, + const hb_map_t *duplicate_feature_map_, + hb_set_t *new_collected_feature_indexes_) + :table (table_), + script_langsys_map (script_langsys_map_), + duplicate_feature_map (duplicate_feature_map_), + new_feature_indexes (new_collected_feature_indexes_), + script_count (0),langsys_count (0) {} + + bool visitedScript (const void *s) + { + if (script_count++ > HB_MAX_SCRIPTS) + return true; + + return visited (s, visited_script); + } + + bool visitedLangsys (const void *l) + { + if (langsys_count++ > HB_MAX_LANGSYS) + return true; + + return visited (l, visited_langsys); + } + + private: + template <typename T> + bool visited (const T *p, hb_set_t &visited_set) + { + hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) p - (uintptr_t) table); + if (visited_set.has (delta)) + return true; + + visited_set.add (delta); + return false; + } + + public: + const void *table; + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map; + const hb_map_t *duplicate_feature_map; + hb_set_t *new_feature_indexes; + + private: + hb_set_t visited_script; + hb_set_t visited_langsys; + unsigned script_count; + unsigned langsys_count; +}; + struct hb_subset_layout_context_t : hb_dispatch_context_t<hb_subset_layout_context_t, hb_empty_t, HB_DEBUG_SUBSET> { @@ -125,16 +179,21 @@ struct hb_subset_layout_context_t : hb_subset_context_t *subset_context; const hb_tag_t table_tag; const hb_map_t *lookup_index_map; + const hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map; const hb_map_t *feature_index_map; + unsigned cur_script_index; hb_subset_layout_context_t (hb_subset_context_t *c_, hb_tag_t tag_, hb_map_t *lookup_map_, - hb_map_t *feature_map_) : + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_, + hb_map_t *feature_index_map_) : subset_context (c_), table_tag (tag_), lookup_index_map (lookup_map_), - feature_index_map (feature_map_), + script_langsys_map (script_langsys_map_), + feature_index_map (feature_index_map_), + cur_script_index (0xFFFFu), script_count (0), langsys_count (0), feature_index_count (0), @@ -325,7 +384,7 @@ struct Record } Tag tag; /* 4-byte Tag identifier */ - OffsetTo<Type> + Offset16To<Type> offset; /* Offset from beginning of object holding * the Record */ public: @@ -333,11 +392,11 @@ struct Record }; template <typename Type> -struct RecordArrayOf : SortedArrayOf<Record<Type>> +struct RecordArrayOf : SortedArray16Of<Record<Type>> { - const OffsetTo<Type>& get_offset (unsigned int i) const + const Offset16To<Type>& get_offset (unsigned int i) const { return (*this)[i].offset; } - OffsetTo<Type>& get_offset (unsigned int i) + Offset16To<Type>& get_offset (unsigned int i) { return (*this)[i].offset; } const Tag& get_tag (unsigned int i) const { return (*this)[i].tag; } @@ -407,6 +466,30 @@ struct RecordListOfFeature : RecordListOf<Feature> } }; +struct Script; +struct RecordListOfScript : RecordListOf<Script> +{ + bool subset (hb_subset_context_t *c, + hb_subset_layout_context_t *l) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + unsigned count = this->len; + for (auto _ : + hb_zip (*this, hb_range (count))) + { + auto snap = c->serializer->snapshot (); + l->cur_script_index = _.second; + bool ret = _.first.subset (l, this); + if (!ret) c->serializer->revert (snap); + else out->len++; + } + + return_trace (true); + } +}; + struct RangeRecord { int cmp (hb_codepoint_t g) const @@ -434,7 +517,7 @@ struct RangeRecord DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord); -struct IndexArray : ArrayOf<Index> +struct IndexArray : Array16Of<Index> { bool intersects (const hb_map_t *indexes) const { return hb_any (*this, indexes); } @@ -474,7 +557,7 @@ struct IndexArray : ArrayOf<Index> void add_indexes_to (hb_set_t* output /* OUT */) const { - output->add_array (arrayZ, len); + output->add_array (as_array ()); } }; @@ -506,18 +589,46 @@ struct LangSys return_trace (c->embed (*this)); } - bool operator == (const LangSys& o) const + bool compare (const LangSys& o, const hb_map_t *feature_index_map) const { - if (featureIndex.len != o.featureIndex.len || - reqFeatureIndex != o.reqFeatureIndex) + if (reqFeatureIndex != o.reqFeatureIndex) return false; - for (const auto _ : + hb_zip (featureIndex, o.featureIndex)) + auto iter = + + hb_iter (featureIndex) + | hb_filter (feature_index_map) + | hb_map (feature_index_map) + ; + + auto o_iter = + + hb_iter (o.featureIndex) + | hb_filter (feature_index_map) + | hb_map (feature_index_map) + ; + + if (iter.len () != o_iter.len ()) + return false; + + for (const auto _ : + hb_zip (iter, o_iter)) if (_.first != _.second) return false; return true; } + void collect_features (hb_prune_langsys_context_t *c) const + { + if (!has_required_feature () && !get_feature_count ()) return; + if (c->visitedLangsys (this)) return; + if (has_required_feature () && + c->duplicate_feature_map->has (reqFeatureIndex)) + c->new_feature_indexes->add (get_required_feature_index ()); + + + hb_iter (featureIndex) + | hb_filter (c->duplicate_feature_map) + | hb_sink (c->new_feature_indexes) + ; + } + bool subset (hb_subset_context_t *c, hb_subset_layout_context_t *l, const Tag *tag = nullptr) const @@ -581,6 +692,49 @@ struct Script bool has_default_lang_sys () const { return defaultLangSys != 0; } const LangSys& get_default_lang_sys () const { return this+defaultLangSys; } + void prune_langsys (hb_prune_langsys_context_t *c, + unsigned script_index) const + { + if (!has_default_lang_sys () && !get_lang_sys_count ()) return; + if (c->visitedScript (this)) return; + + if (!c->script_langsys_map->has (script_index)) + { + hb_set_t* empty_set = hb_set_create (); + if (unlikely (!c->script_langsys_map->set (script_index, empty_set))) + { + hb_set_destroy (empty_set); + return; + } + } + + unsigned langsys_count = get_lang_sys_count (); + if (has_default_lang_sys ()) + { + //only collect features from non-redundant langsys + const LangSys& d = get_default_lang_sys (); + d.collect_features (c); + + for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) + { + const LangSys& l = this+_.first.offset; + if (l.compare (d, c->duplicate_feature_map)) continue; + + l.collect_features (c); + c->script_langsys_map->get (script_index)->add (_.second); + } + } + else + { + for (auto _ : + hb_zip (langSys, hb_range (langsys_count))) + { + const LangSys& l = this+_.first.offset; + l.collect_features (c); + c->script_langsys_map->get (script_index)->add (_.second); + } + } + } + bool subset (hb_subset_context_t *c, hb_subset_layout_context_t *l, const Tag *tag) const @@ -609,16 +763,17 @@ struct Script } } - + langSys.iter () - | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); }) - | hb_filter ([&] (const Record<LangSys>& record) - { - const LangSys& d = this+defaultLangSys; - const LangSys& l = this+record.offset; - return !(l == d); - }) - | hb_apply (subset_record_array (l, &(out->langSys), this)) - ; + const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index); + if (active_langsys) + { + unsigned count = langSys.len; + + hb_zip (langSys, hb_range (count)) + | hb_filter (active_langsys, hb_second) + | hb_map (hb_first) + | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); }) + | hb_apply (subset_record_array (l, &(out->langSys), this)) + ; + } return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB); } @@ -631,7 +786,7 @@ struct Script } protected: - OffsetTo<LangSys> + Offset16To<LangSys> defaultLangSys; /* Offset to DefaultLangSys table--from * beginning of Script table--may be Null */ RecordArrayOf<LangSys> @@ -641,7 +796,7 @@ struct Script DEFINE_SIZE_ARRAY_SIZED (4, langSys); }; -typedef RecordListOf<Script> ScriptList; +typedef RecordListOfScript ScriptList; /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */ @@ -856,7 +1011,7 @@ struct FeatureParamsCharacterVariants * user-interface labels for the * feature parameters. (Must be zero * if numParameters is zero.) */ - ArrayOf<HBUINT24> + Array16Of<HBUINT24> characters; /* Array of the Unicode Scalar Value * of the characters for which this * feature provides glyph variants. @@ -953,7 +1108,7 @@ struct Feature auto *out = c->serializer->start_embed (*this); if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); - bool subset_featureParams = out->featureParams.serialize_subset (c, featureParams, this, tag); + out->featureParams.serialize_subset (c, featureParams, this, tag); auto it = + hb_iter (lookupIndex) @@ -962,8 +1117,9 @@ struct Feature ; out->lookupIndex.serialize (c->serializer, l, it); - return_trace (bool (it) || subset_featureParams - || (tag && *tag == HB_TAG ('p', 'r', 'e', 'f'))); + // The decision to keep or drop this feature is already made before we get here + // so always retain it. + return_trace (true); } bool sanitize (hb_sanitize_context_t *c, @@ -998,7 +1154,7 @@ struct Feature unsigned int new_offset_int = orig_offset - (((char *) this) - ((char *) closure->list_base)); - OffsetTo<FeatureParams> new_offset; + Offset16To<FeatureParams> new_offset; /* Check that it would not overflow. */ new_offset = new_offset_int; if (new_offset == new_offset_int && @@ -1010,7 +1166,7 @@ struct Feature return_trace (true); } - OffsetTo<FeatureParams> + Offset16To<FeatureParams> featureParams; /* Offset to Feature Parameters table (if one * has been defined for the feature), relative * to the beginning of the Feature Table; = Null @@ -1049,11 +1205,11 @@ struct Lookup unsigned int get_subtable_count () const { return subTable.len; } template <typename TSubTable> - const OffsetArrayOf<TSubTable>& get_subtables () const - { return reinterpret_cast<const OffsetArrayOf<TSubTable> &> (subTable); } + const Array16OfOffset16To<TSubTable>& get_subtables () const + { return reinterpret_cast<const Array16OfOffset16To<TSubTable> &> (subTable); } template <typename TSubTable> - OffsetArrayOf<TSubTable>& get_subtables () - { return reinterpret_cast<OffsetArrayOf<TSubTable> &> (subTable); } + Array16OfOffset16To<TSubTable>& get_subtables () + { return reinterpret_cast<Array16OfOffset16To<TSubTable> &> (subTable); } template <typename TSubTable> const TSubTable& get_subtable (unsigned int i) const @@ -1131,10 +1287,18 @@ struct Lookup const hb_set_t *glyphset = c->plan->glyphset_gsub (); unsigned int lookup_type = get_type (); + hb_iter (get_subtables <TSubTable> ()) - | hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); }) + | hb_filter ([this, glyphset, lookup_type] (const Offset16To<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); }) | hb_apply (subset_offset_array (c, out->get_subtables<TSubTable> (), this, lookup_type)) ; + if (lookupFlag & LookupFlag::UseMarkFilteringSet) + { + if (unlikely (!c->serializer->extend (out))) return_trace (false); + const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable); + HBUINT16 &outMarkFilteringSet = StructAfter<HBUINT16> (out->subTable); + outMarkFilteringSet = markFilteringSet; + } + return_trace (true); } @@ -1179,7 +1343,7 @@ struct Lookup private: HBUINT16 lookupType; /* Different enumerations for GSUB and GPOS */ HBUINT16 lookupFlag; /* Lookup qualifiers */ - ArrayOf<Offset16> + Array16Of<Offset16> subTable; /* Array of SubTables */ /*HBUINT16 markFilteringSetX[HB_VAR_ARRAY];*//* Index (base 0) into GDEF mark glyph sets * structure. This field is only present if bit @@ -1188,10 +1352,10 @@ struct Lookup DEFINE_SIZE_ARRAY (6, subTable); }; -typedef OffsetListOf<Lookup> LookupList; +typedef List16OfOffset16To<Lookup> LookupList; template <typename TLookup> -struct LookupOffsetList : OffsetListOf<TLookup> +struct LookupOffsetList : List16OfOffset16To<TLookup> { bool subset (hb_subset_context_t *c, hb_subset_layout_context_t *l) const @@ -1212,7 +1376,7 @@ struct LookupOffsetList : OffsetListOf<TLookup> bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (OffsetListOf<TLookup>::sanitize (c, this)); + return_trace (List16OfOffset16To<TLookup>::sanitize (c, this)); } }; @@ -1250,19 +1414,25 @@ struct CoverageFormat1 bool intersects (const hb_set_t *glyphs) const { /* TODO Speed up, using hb_set_next() and bsearch()? */ - unsigned int count = glyphArray.len; - const HBGlyphID *arr = glyphArray.arrayZ; - for (unsigned int i = 0; i < count; i++) - if (glyphs->has (arr[i])) + for (const auto& g : glyphArray.as_array ()) + if (glyphs->has (g)) return true; return false; } bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const { return glyphs->has (glyphArray[index]); } + void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const + { + unsigned count = glyphArray.len; + for (unsigned i = 0; i < count; i++) + if (glyphs->has (glyphArray[i])) + intersect_glyphs->add (glyphArray[i]); + } + template <typename set_t> bool collect_coverage (set_t *glyphs) const - { return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len); } + { return glyphs->add_sorted_array (glyphArray.as_array ()); } public: /* Older compilers need this to be public. */ @@ -1284,7 +1454,7 @@ struct CoverageFormat1 protected: HBUINT16 coverageFormat; /* Format identifier--format = 1 */ - SortedArrayOf<HBGlyphID> + SortedArray16Of<HBGlyphID> glyphArray; /* Array of GlyphIDs--in numerical order */ public: DEFINE_SIZE_ARRAY (4, glyphArray); @@ -1358,20 +1528,16 @@ struct CoverageFormat2 { /* TODO Speed up, using hb_set_next() and bsearch()? */ /* TODO(iter) Rewrite as dagger. */ - unsigned count = rangeRecord.len; - const RangeRecord *arr = rangeRecord.arrayZ; - for (unsigned i = 0; i < count; i++) - if (arr[i].intersects (glyphs)) + for (const auto& range : rangeRecord.as_array ()) + if (range.intersects (glyphs)) return true; return false; } bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const { /* TODO(iter) Rewrite as dagger. */ - unsigned count = rangeRecord.len; - const RangeRecord *arr = rangeRecord.arrayZ; - for (unsigned i = 0; i < count; i++) { - const RangeRecord &range = arr[i]; + for (const auto& range : rangeRecord.as_array ()) + { if (range.value <= index && index < (unsigned int) range.value + (range.last - range.first) && range.intersects (glyphs)) @@ -1382,6 +1548,16 @@ struct CoverageFormat2 return false; } + void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const + { + for (const auto& range : rangeRecord.as_array ()) + { + if (!range.intersects (glyphs)) continue; + for (hb_codepoint_t g = range.first; g <= range.last; g++) + if (glyphs->has (g)) intersect_glyphs->add (g); + } + } + template <typename set_t> bool collect_coverage (set_t *glyphs) const { @@ -1448,7 +1624,7 @@ struct CoverageFormat2 protected: HBUINT16 coverageFormat; /* Format identifier--format = 2 */ - SortedArrayOf<RangeRecord> + SortedArray16Of<RangeRecord> rangeRecord; /* Array of glyph ranges--ordered by * Start GlyphID. rangeCount entries * long */ @@ -1564,6 +1740,16 @@ struct Coverage } } + void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const + { + switch (u.format) + { + case 1: return u.format1.intersected_coverage_glyphs (glyphs, intersect_glyphs); + case 2: return u.format2.intersected_coverage_glyphs (glyphs, intersect_glyphs); + default:return ; + } + } + struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t> { static constexpr bool is_sorted_iterator = true; @@ -1645,10 +1831,10 @@ Coverage_serialize (hb_serialize_context_t *c, { c->start_embed<Coverage> ()->serialize (c, it); } static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, - const hb_set_t &glyphset, const hb_map_t &gid_klass_map, hb_sorted_vector_t<HBGlyphID> &glyphs, const hb_set_t &klasses, + bool use_class_zero, hb_map_t *klass_map /*INOUT*/) { if (!klass_map) @@ -1660,7 +1846,7 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, /* any glyph not assigned a class value falls into Class zero (0), * if any glyph assigned to class 0, remapping must start with 0->0*/ - if (glyphset.get_population () > gid_klass_map.get_population ()) + if (!use_class_zero) klass_map->set (0, 0); unsigned idx = klass_map->has (0) ? 1 : 0; @@ -1708,6 +1894,7 @@ struct ClassDefFormat1 if (unlikely (!it)) { + classFormat = 1; startGlyph = 0; classValue.len = 0; return_trace (true); @@ -1730,7 +1917,10 @@ struct ClassDefFormat1 } bool subset (hb_subset_context_t *c, - hb_map_t *klass_map = nullptr /*OUT*/) const + hb_map_t *klass_map = nullptr /*OUT*/, + bool keep_empty_table = true, + bool use_class_zero = true, + const Coverage* glyph_filter = nullptr) const { TRACE_SUBSET (this); const hb_set_t &glyphset = *c->plan->glyphset_gsub (); @@ -1742,9 +1932,12 @@ struct ClassDefFormat1 hb_codepoint_t start = startGlyph; hb_codepoint_t end = start + classValue.len; + for (const hb_codepoint_t gid : + hb_range (start, end) - | hb_filter (glyphset)) + | hb_filter (glyphset)) { + if (glyph_filter && !glyph_filter->has(gid)) continue; + unsigned klass = classValue[gid - start]; if (!klass) continue; @@ -1753,9 +1946,13 @@ struct ClassDefFormat1 orig_klasses.add (klass); } - ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map, - glyphs, orig_klasses, klass_map); - return_trace ((bool) glyphs); + unsigned glyph_count = glyph_filter + ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter)) + : glyphset.get_population (); + use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population (); + ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map, + glyphs, orig_klasses, use_class_zero, klass_map); + return_trace (keep_empty_table || (bool) glyphs); } bool sanitize (hb_sanitize_context_t *c) const @@ -1829,10 +2026,28 @@ struct ClassDefFormat1 return false; } + void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const + { + unsigned count = classValue.len; + if (klass == 0) + { + hb_codepoint_t endGlyph = startGlyph + count -1; + for (hb_codepoint_t g : glyphs->iter ()) + if (g < startGlyph || g > endGlyph) + intersect_glyphs->add (g); + + return; + } + + for (unsigned i = 0; i < count; i++) + if (classValue[i] == klass && glyphs->has (startGlyph + i)) + intersect_glyphs->add (startGlyph + i); + } + protected: HBUINT16 classFormat; /* Format identifier--format = 1 */ HBGlyphID startGlyph; /* First GlyphID of the classValueArray */ - ArrayOf<HBUINT16> + Array16Of<HBUINT16> classValue; /* Array of Class Values--one per GlyphID */ public: DEFINE_SIZE_ARRAY (6, classValue); @@ -1858,6 +2073,7 @@ struct ClassDefFormat2 if (unlikely (!it)) { + classFormat = 2; rangeRecord.len = 0; return_trace (true); } @@ -1903,7 +2119,10 @@ struct ClassDefFormat2 } bool subset (hb_subset_context_t *c, - hb_map_t *klass_map = nullptr /*OUT*/) const + hb_map_t *klass_map = nullptr /*OUT*/, + bool keep_empty_table = true, + bool use_class_zero = true, + const Coverage* glyph_filter = nullptr) const { TRACE_SUBSET (this); const hb_set_t &glyphset = *c->plan->glyphset_gsub (); @@ -1923,15 +2142,20 @@ struct ClassDefFormat2 for (hb_codepoint_t g = start; g < end; g++) { if (!glyphset.has (g)) continue; + if (glyph_filter && !glyph_filter->has (g)) continue; glyphs.push (glyph_map[g]); gid_org_klass_map.set (glyph_map[g], klass); orig_klasses.add (klass); } } - ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map, - glyphs, orig_klasses, klass_map); - return_trace ((bool) glyphs); + unsigned glyph_count = glyph_filter + ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter)) + : glyphset.get_population (); + use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population (); + ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map, + glyphs, orig_klasses, use_class_zero, klass_map); + return_trace (keep_empty_table || (bool) glyphs); } bool sanitize (hb_sanitize_context_t *c) const @@ -2005,9 +2229,57 @@ struct ClassDefFormat2 return false; } + void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const + { + unsigned count = rangeRecord.len; + if (klass == 0) + { + hb_codepoint_t g = HB_SET_VALUE_INVALID; + for (unsigned int i = 0; i < count; i++) + { + if (!hb_set_next (glyphs, &g)) + break; + while (g != HB_SET_VALUE_INVALID && g < rangeRecord[i].first) + { + intersect_glyphs->add (g); + hb_set_next (glyphs, &g); + } + g = rangeRecord[i].last; + } + while (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g)) + intersect_glyphs->add (g); + + return; + } + + hb_codepoint_t g = HB_SET_VALUE_INVALID; + for (unsigned int i = 0; i < count; i++) + { + if (rangeRecord[i].value != klass) continue; + + if (g != HB_SET_VALUE_INVALID) + { + if (g >= rangeRecord[i].first && + g <= rangeRecord[i].last) + intersect_glyphs->add (g); + if (g > rangeRecord[i].last) + continue; + } + + g = rangeRecord[i].first - 1; + while (hb_set_next (glyphs, &g)) + { + if (g >= rangeRecord[i].first && g <= rangeRecord[i].last) + intersect_glyphs->add (g); + else if (g > rangeRecord[i].last) + break; + } + } + } + protected: HBUINT16 classFormat; /* Format identifier--format = 2 */ - SortedArrayOf<RangeRecord> + SortedArray16Of<RangeRecord> rangeRecord; /* Array of glyph ranges--ordered by * Start GlyphID */ public: @@ -2036,19 +2308,20 @@ struct ClassDef template<typename Iterator, hb_requires (hb_is_iterator (Iterator))> - bool serialize (hb_serialize_context_t *c, Iterator it) + bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); + auto it = + it_with_class_zero | hb_filter (hb_second); + unsigned format = 2; if (likely (it)) { hb_codepoint_t glyph_min = (*it).first; - hb_codepoint_t glyph_max = + it - | hb_map (hb_first) - | hb_reduce (hb_max, 0u); + hb_codepoint_t glyph_max = glyph_min; + unsigned num_glyphs = 0; unsigned num_ranges = 1; hb_codepoint_t prev_gid = glyph_min; unsigned prev_klass = (*it).second; @@ -2057,7 +2330,9 @@ struct ClassDef { hb_codepoint_t cur_gid = gid_klass_pair.first; unsigned cur_klass = gid_klass_pair.second; - if (cur_gid == glyph_min || !cur_klass) continue; + num_glyphs++; + if (cur_gid == glyph_min) continue; + if (cur_gid > glyph_max) glyph_max = cur_gid; if (cur_gid != prev_gid + 1 || cur_klass != prev_klass) num_ranges++; @@ -2066,7 +2341,7 @@ struct ClassDef prev_klass = cur_klass; } - if (1 + (glyph_max - glyph_min + 1) <= num_ranges * 3) + if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3) format = 1; } u.format = format; @@ -2080,12 +2355,15 @@ struct ClassDef } bool subset (hb_subset_context_t *c, - hb_map_t *klass_map = nullptr /*OUT*/) const + hb_map_t *klass_map = nullptr /*OUT*/, + bool keep_empty_table = true, + bool use_class_zero = true, + const Coverage* glyph_filter = nullptr) const { TRACE_SUBSET (this); switch (u.format) { - case 1: return_trace (u.format1.subset (c, klass_map)); - case 2: return_trace (u.format2.subset (c, klass_map)); + case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); + case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); default:return_trace (false); } } @@ -2142,6 +2420,15 @@ struct ClassDef } } + void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const + { + switch (u.format) { + case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs); + case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs); + default:return; + } + } + protected: union { HBUINT16 format; /* Format identifier */ @@ -2439,7 +2726,7 @@ struct VarData protected: HBUINT16 itemCount; HBUINT16 shortCount; - ArrayOf<HBUINT16> regionIndices; + Array16Of<HBUINT16> regionIndices; /*UnsizedArrayOf<HBUINT8>bytesX;*/ public: DEFINE_SIZE_ARRAY (6, regionIndices); @@ -2447,6 +2734,7 @@ struct VarData struct VariationStore { + private: float get_delta (unsigned int outer, unsigned int inner, const int *coords, unsigned int coord_count) const { @@ -2462,6 +2750,7 @@ struct VariationStore this+regions); } + public: float get_delta (unsigned int index, const int *coords, unsigned int coord_count) const { @@ -2505,7 +2794,7 @@ struct VariationStore .serialize (c, &(src+src->regions), region_map))) return_trace (false); /* TODO: The following code could be simplified when - * OffsetListOf::subset () can take a custom param to be passed to VarData::serialize () + * List16OfOffset16To::subset () can take a custom param to be passed to VarData::serialize () */ dataSets.len = set_count; unsigned int set_index = 0; @@ -2580,8 +2869,8 @@ struct VariationStore protected: HBUINT16 format; - LOffsetTo<VarRegionList> regions; - LOffsetArrayOf<VarData> dataSets; + Offset32To<VarRegionList> regions; + Array16OfOffset32To<VarData> dataSets; public: DEFINE_SIZE_ARRAY (8, dataSets); }; @@ -2684,7 +2973,8 @@ struct ConditionSet + conditions.iter () | hb_apply (subset_offset_array (c, out->conditions, this)) ; - return_trace (true); + + return_trace (bool (out->conditions)); } bool sanitize (hb_sanitize_context_t *c) const @@ -2694,7 +2984,7 @@ struct ConditionSet } protected: - LOffsetArrayOf<Condition> conditions; + Array16OfOffset32To<Condition> conditions; public: DEFINE_SIZE_ARRAY (2, conditions); }; @@ -2719,6 +3009,12 @@ struct FeatureTableSubstitutionRecord bool subset (hb_subset_layout_context_t *c, const void *base) const { TRACE_SUBSET (this); + if (!c->feature_index_map->has (featureIndex)) { + // Feature that is being substituted is not being retained, so we don't + // need this. + return_trace (false); + } + auto *out = c->subset_context->serializer->embed (this); if (unlikely (!out)) return_trace (false); @@ -2735,7 +3031,7 @@ struct FeatureTableSubstitutionRecord protected: HBUINT16 featureIndex; - LOffsetTo<Feature> feature; + Offset32To<Feature> feature; public: DEFINE_SIZE_STATIC (6); }; @@ -2771,6 +3067,15 @@ struct FeatureTableSubstitution record.closure_features (this, lookup_indexes, feature_indexes); } + bool intersects_features (const hb_map_t *feature_index_map) const + { + for (const FeatureTableSubstitutionRecord& record : substitutions) + { + if (feature_index_map->has (record.featureIndex)) return true; + } + return false; + } + bool subset (hb_subset_context_t *c, hb_subset_layout_context_t *l) const { @@ -2784,7 +3089,8 @@ struct FeatureTableSubstitution + substitutions.iter () | hb_apply (subset_record_array (l, &(out->substitutions), this)) ; - return_trace (true); + + return_trace (bool (out->substitutions)); } bool sanitize (hb_sanitize_context_t *c) const @@ -2797,7 +3103,7 @@ struct FeatureTableSubstitution protected: FixedVersion<> version; /* Version--0x00010000u */ - ArrayOf<FeatureTableSubstitutionRecord> + Array16Of<FeatureTableSubstitutionRecord> substitutions; public: DEFINE_SIZE_ARRAY (6, substitutions); @@ -2821,6 +3127,11 @@ struct FeatureVariationRecord (base+substitutions).closure_features (lookup_indexes, feature_indexes); } + bool intersects_features (const void *base, const hb_map_t *feature_index_map) const + { + return (base+substitutions).intersects_features (feature_index_map); + } + bool subset (hb_subset_layout_context_t *c, const void *base) const { TRACE_SUBSET (this); @@ -2841,9 +3152,9 @@ struct FeatureVariationRecord } protected: - LOffsetTo<ConditionSet> + Offset32To<ConditionSet> conditions; - LOffsetTo<FeatureTableSubstitution> + Offset32To<FeatureTableSubstitution> substitutions; public: DEFINE_SIZE_STATIC (8); @@ -2907,9 +3218,18 @@ struct FeatureVariations out->version.major = version.major; out->version.minor = version.minor; - + varRecords.iter () - | hb_apply (subset_record_array (l, &(out->varRecords), this)) - ; + int keep_up_to = -1; + for (int i = varRecords.len - 1; i >= 0; i--) { + if (varRecords[i].intersects_features (this, l->feature_index_map)) { + keep_up_to = i; + break; + } + } + + unsigned count = (unsigned) (keep_up_to + 1); + for (unsigned i = 0; i < count; i++) { + subset_record_array (l, &(out->varRecords), this) (varRecords[i]); + } return_trace (bool (out->varRecords)); } @@ -2923,7 +3243,7 @@ struct FeatureVariations protected: FixedVersion<> version; /* Version--0x00010000u */ - LArrayOf<FeatureVariationRecord> + Array32Of<FeatureVariationRecord> varRecords; public: DEFINE_SIZE_ARRAY_SIZED (8, varRecords); @@ -3036,22 +3356,20 @@ struct VariationDevice if (unlikely (!out)) return_trace (nullptr); if (!layout_variation_idx_map || layout_variation_idx_map->is_empty ()) return_trace (out); - unsigned org_idx = (outerIndex << 16) + innerIndex; - if (!layout_variation_idx_map->has (org_idx)) + /* TODO Just get() and bail if NO_VARIATION. Needs to setup the map to return that. */ + if (!layout_variation_idx_map->has (varIdx)) { c->revert (snap); return_trace (nullptr); } - unsigned new_idx = layout_variation_idx_map->get (org_idx); - out->outerIndex = new_idx >> 16; - out->innerIndex = new_idx & 0xFFFF; + unsigned new_idx = layout_variation_idx_map->get (varIdx); + out->varIdx = new_idx; return_trace (out); } void record_variation_index (hb_set_t *layout_variation_indices) const { - unsigned var_idx = (outerIndex << 16) + innerIndex; - layout_variation_indices->add (var_idx); + layout_variation_indices->add (varIdx); } bool sanitize (hb_sanitize_context_t *c) const @@ -3064,12 +3382,11 @@ struct VariationDevice float get_delta (hb_font_t *font, const VariationStore &store) const { - return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords); + return store.get_delta (varIdx, font->coords, font->num_coords); } protected: - HBUINT16 outerIndex; - HBUINT16 innerIndex; + VarIdx varIdx; HBUINT16 deltaFormat; /* Format identifier for this table: 0x0x8000 */ public: DEFINE_SIZE_STATIC (6); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh index 437e760f64d..edb35dabf94 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh @@ -42,7 +42,7 @@ namespace OT { */ /* Array of contour point indices--in increasing numerical order */ -struct AttachPoint : ArrayOf<HBUINT16> +struct AttachPoint : Array16Of<HBUINT16> { bool subset (hb_subset_context_t *c) const { @@ -110,10 +110,10 @@ struct AttachList } protected: - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table -- from * beginning of AttachList table */ - OffsetArrayOf<AttachPoint> + Array16OfOffset16To<AttachPoint> attachPoint; /* Array of AttachPoint tables * in Coverage Index order */ public: @@ -220,7 +220,7 @@ struct CaretValueFormat3 protected: HBUINT16 caretValueFormat; /* Format identifier--format = 3 */ FWORD coordinate; /* X or Y value, in design units */ - OffsetTo<Device> + Offset16To<Device> deviceTable; /* Offset to Device table for X or Y * value--from beginning of CaretValue * table */ @@ -329,7 +329,7 @@ struct LigGlyph void collect_variation_indices (hb_collect_variation_indices_context_t *c) const { - for (const OffsetTo<CaretValue>& offset : carets.iter ()) + for (const Offset16To<CaretValue>& offset : carets.iter ()) (this+offset).collect_variation_indices (c->layout_variation_indices); } @@ -340,7 +340,7 @@ struct LigGlyph } protected: - OffsetArrayOf<CaretValue> + Array16OfOffset16To<CaretValue> carets; /* Offset array of CaretValue tables * --from beginning of LigGlyph table * --in increasing coordinate order */ @@ -408,10 +408,10 @@ struct LigCaretList } protected: - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of LigCaretList table */ - OffsetArrayOf<LigGlyph> + Array16OfOffset16To<LigGlyph> ligGlyph; /* Array of LigGlyph tables * in Coverage Index order */ public: @@ -432,7 +432,7 @@ struct MarkGlyphSetsFormat1 out->format = format; bool ret = true; - for (const LOffsetTo<Coverage>& offset : coverage.iter ()) + for (const Offset32To<Coverage>& offset : coverage.iter ()) { auto *o = out->coverage.serialize_append (c->serializer); if (unlikely (!o)) @@ -460,7 +460,7 @@ struct MarkGlyphSetsFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - ArrayOf<LOffsetTo<Coverage>> + Array16Of<Offset32To<Coverage>> coverage; /* Array of long offsets to mark set * coverage tables */ public: @@ -643,10 +643,10 @@ struct GDEF auto *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); - bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this); + bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this); - bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this); + bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); bool subset_markglyphsetsdef = true; if (version.to_int () >= 0x00010002u) @@ -687,28 +687,28 @@ struct GDEF protected: FixedVersion<>version; /* Version of the GDEF table--currently * 0x00010003u */ - OffsetTo<ClassDef> + Offset16To<ClassDef> glyphClassDef; /* Offset to class definition table * for glyph type--from beginning of * GDEF header (may be Null) */ - OffsetTo<AttachList> + Offset16To<AttachList> attachList; /* Offset to list of glyphs with * attachment points--from beginning * of GDEF header (may be Null) */ - OffsetTo<LigCaretList> + Offset16To<LigCaretList> ligCaretList; /* Offset to list of positioning points * for ligature carets--from beginning * of GDEF header (may be Null) */ - OffsetTo<ClassDef> + Offset16To<ClassDef> markAttachClassDef; /* Offset to class definition table for * mark attachment type--from beginning * of GDEF header (may be Null) */ - OffsetTo<MarkGlyphSets> + Offset16To<MarkGlyphSets> markGlyphSetsDef; /* Offset to the table of mark set * definitions--from beginning of GDEF * header (may be NULL). Introduced * in version 0x00010002. */ - LOffsetTo<VariationStore> + Offset32To<VariationStore> varStore; /* Offset to the table of Item Variation * Store--from beginning of GDEF * header (may be NULL). Introduced 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 f523e35c003..4354f8f0d9b 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 @@ -89,20 +89,22 @@ struct ValueFormat : HBUINT16 HBINT16 yAdvance; /* Vertical adjustment for advance--in * design units (only used for vertical * writing) */ - OffsetTo<Device> xPlaDevice; /* Offset to Device table for + Offset16To<Device> xPlaDevice; /* Offset to Device table for * horizontal placement--measured from * beginning of PosTable (may be NULL) */ - OffsetTo<Device> yPlaDevice; /* Offset to Device table for vertical + Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical * placement--measured from beginning * of PosTable (may be NULL) */ - OffsetTo<Device> xAdvDevice; /* Offset to Device table for + Offset16To<Device> xAdvDevice; /* Offset to Device table for * horizontal advance--measured from * beginning of PosTable (may be NULL) */ - OffsetTo<Device> yAdvDevice; /* Offset to Device table for vertical + Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical * advance--measured from beginning of * PosTable (may be NULL) */ #endif + IntType& operator = (uint16_t i) { v = i; return *this; } + unsigned int get_len () const { return hb_popcount ((unsigned int) *this); } unsigned int get_size () const { return get_len () * Value::static_size; } @@ -160,16 +162,40 @@ struct ValueFormat : HBUINT16 return ret; } - void serialize_copy (hb_serialize_context_t *c, const void *base, - const Value *values, const hb_map_t *layout_variation_idx_map) const + unsigned int get_effective_format (const Value *values) const + { + unsigned int format = *this; + for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) { + if (format & flag) should_drop (*values++, (Flags) flag, &format); + } + + return format; + } + + template<typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + unsigned int get_effective_format (Iterator it) const { + unsigned int new_format = 0; + + for (const hb_array_t<const Value>& values : it) + new_format = new_format | get_effective_format (&values); + + return new_format; + } + + void copy_values (hb_serialize_context_t *c, + unsigned int new_format, + const void *base, + const Value *values, + const hb_map_t *layout_variation_idx_map) const { unsigned int format = *this; if (!format) return; - if (format & xPlacement) c->copy (*values++); - if (format & yPlacement) c->copy (*values++); - if (format & xAdvance) c->copy (*values++); - if (format & yAdvance) c->copy (*values++); + if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++); + if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++); + if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++); + if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++); if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); @@ -177,6 +203,16 @@ struct ValueFormat : HBUINT16 if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map); } + void copy_value (hb_serialize_context_t *c, + unsigned int new_format, + Flags flag, + Value value) const + { + // Filter by new format. + if (!(new_format & flag)) return; + c->copy (value); + } + void collect_variation_indices (hb_collect_variation_indices_context_t *c, const void *base, const hb_array_t<const Value>& values) const @@ -232,14 +268,14 @@ struct ValueFormat : HBUINT16 return true; } - static inline OffsetTo<Device>& get_device (Value* value) + static inline Offset16To<Device>& get_device (Value* value) { - return *static_cast<OffsetTo<Device> *> (value); + return *static_cast<Offset16To<Device> *> (value); } - static inline const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr) + static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr) { if (worked) *worked |= bool (*value); - return *static_cast<const OffsetTo<Device> *> (value); + return *static_cast<const Offset16To<Device> *> (value); } bool copy_device (hb_serialize_context_t *c, const void *base, @@ -317,13 +353,21 @@ struct ValueFormat : HBUINT16 return_trace (true); } + + private: + + void should_drop (Value value, Flags flag, unsigned int* format) const + { + if (value) return; + *format = *format & ~flag; + } + }; -template<typename Iterator> +template<typename Iterator, typename SrcLookup> static void SinglePos_serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup *src, Iterator it, - ValueFormat valFormat, const hb_map_t *layout_variation_idx_map); @@ -346,7 +390,10 @@ struct AnchorFormat1 AnchorFormat1* copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); - return_trace (c->embed<AnchorFormat1> (this)); + AnchorFormat1* out = c->embed<AnchorFormat1> (this); + if (!out) return_trace (out); + out->format = 1; + return_trace (out); } protected: @@ -447,11 +494,11 @@ struct AnchorFormat3 HBUINT16 format; /* Format identifier--format = 3 */ FWORD xCoordinate; /* Horizontal value--in design units */ FWORD yCoordinate; /* Vertical value--in design units */ - OffsetTo<Device> + Offset16To<Device> xDeviceTable; /* Offset to Device table for X * coordinate-- from beginning of * Anchor table (may be NULL) */ - OffsetTo<Device> + Offset16To<Device> yDeviceTable; /* Offset to Device table for Y * coordinate-- from beginning of * Anchor table (may be NULL) */ @@ -485,14 +532,22 @@ struct Anchor } } - Anchor* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const + bool subset (hb_subset_context_t *c) const { - TRACE_SERIALIZE (this); + TRACE_SUBSET (this); switch (u.format) { - case 1: return_trace (reinterpret_cast<Anchor *> (u.format1.copy (c))); - case 2: return_trace (reinterpret_cast<Anchor *> (u.format2.copy (c))); - case 3: return_trace (reinterpret_cast<Anchor *> (u.format3.copy (c, layout_variation_idx_map))); - default:return_trace (nullptr); + case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer)))); + case 2: + if (c->plan->drop_hints) + { + // AnchorFormat 2 just containins extra hinting information, so + // if hints are being dropped convert to format 1. + return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer)))); + } + return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer)))); + case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer, + c->plan->layout_variation_idx_map)))); + default:return_trace (false); } } @@ -541,51 +596,29 @@ struct AnchorMatrix } template <typename Iterator, - hb_requires (hb_is_iterator (Iterator))> - bool serialize (hb_serialize_context_t *c, - unsigned num_rows, - AnchorMatrix const *offset_matrix, - const hb_map_t *layout_variation_idx_map, - Iterator index_iter) + hb_requires (hb_is_iterator (Iterator))> + bool subset (hb_subset_context_t *c, + unsigned num_rows, + Iterator index_iter) const { - TRACE_SERIALIZE (this); + TRACE_SUBSET (this); + + auto *out = c->serializer->start_embed (this); + if (!index_iter) return_trace (false); - if (unlikely (!c->extend_min ((*this)))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - this->rows = num_rows; + out->rows = num_rows; for (const unsigned i : index_iter) { - auto *offset = c->embed (offset_matrix->matrixZ[i]); + auto *offset = c->serializer->embed (matrixZ[i]); if (!offset) return_trace (false); - offset->serialize_copy (c, offset_matrix->matrixZ[i], - offset_matrix, c->to_bias (this), - hb_serialize_context_t::Head, - layout_variation_idx_map); + offset->serialize_subset (c, matrixZ[i], this); } return_trace (true); } - bool subset (hb_subset_context_t *c, - unsigned cols, - const hb_map_t *klass_mapping) const - { - TRACE_SUBSET (this); - auto *out = c->serializer->start_embed (*this); - - auto indexes = - + hb_range (rows * cols) - | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % cols); }) - ; - - out->serialize (c->serializer, - (unsigned) rows, - this, - c->plan->layout_variation_idx_map, - indexes); - return_trace (true); - } - bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const { TRACE_SANITIZE (this); @@ -599,7 +632,7 @@ struct AnchorMatrix } HBUINT16 rows; /* Number of rows */ - UnsizedArrayOf<OffsetTo<Anchor>> + UnsizedArrayOf<Offset16To<Anchor>> matrixZ; /* Matrix of offsets to Anchor tables-- * from beginning of AnchorMatrix table */ public: @@ -618,18 +651,16 @@ struct MarkRecord return_trace (c->check_struct (this) && markAnchor.sanitize (c, base)); } - MarkRecord *copy (hb_serialize_context_t *c, - const void *src_base, - unsigned dst_bias, - const hb_map_t *klass_mapping, - const hb_map_t *layout_variation_idx_map) const + MarkRecord *subset (hb_subset_context_t *c, + const void *src_base, + const hb_map_t *klass_mapping) const { - TRACE_SERIALIZE (this); - auto *out = c->embed (this); + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); if (unlikely (!out)) return_trace (nullptr); out->klass = klass_mapping->get (klass); - out->markAnchor.serialize_copy (c, markAnchor, src_base, dst_bias, hb_serialize_context_t::Head, layout_variation_idx_map); + out->markAnchor.serialize_subset (c, markAnchor, src_base); return_trace (out); } @@ -641,14 +672,14 @@ struct MarkRecord protected: HBUINT16 klass; /* Class defined for this mark */ - OffsetTo<Anchor> + Offset16To<Anchor> markAnchor; /* Offset to Anchor table--from * beginning of MarkArray table */ public: DEFINE_SIZE_STATIC (4); }; -struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage order */ +struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */ { bool apply (hb_ot_apply_context_t *c, unsigned int mark_index, unsigned int glyph_index, @@ -657,7 +688,7 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; - const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index); + const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index); unsigned int mark_class = record.klass; const Anchor& mark_anchor = this + record.markAnchor; @@ -684,25 +715,42 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde return_trace (true); } - template<typename Iterator, - hb_requires (hb_is_source_of (Iterator, MarkRecord))> - bool serialize (hb_serialize_context_t *c, - const hb_map_t *klass_mapping, - const hb_map_t *layout_variation_idx_map, - const void *base, - Iterator it) + template <typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + bool subset (hb_subset_context_t *c, + Iterator coverage, + const hb_map_t *klass_mapping) const { - TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!c->check_assign (len, it.len ()))) return_trace (false); - c->copy_all (it, base, c->to_bias (this), klass_mapping, layout_variation_idx_map); + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + + auto* out = c->serializer->start_embed (this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + auto mark_iter = + + hb_zip (coverage, this->iter ()) + | hb_filter (glyphset, hb_first) + | hb_map (hb_second) + ; + + unsigned new_length = 0; + for (const auto& mark_record : mark_iter) { + if (unlikely (!mark_record.subset (c, this, klass_mapping))) + return_trace (false); + new_length++; + } + + if (unlikely (!c->serializer->check_assign (out->len, new_length, + HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) + return_trace (false); + return_trace (true); } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (ArrayOf<MarkRecord>::sanitize (c, this)); + return_trace (Array16Of<MarkRecord>::sanitize (c, this)); } }; @@ -733,6 +781,8 @@ struct SinglePosFormat1 const Coverage &get_coverage () const { return this+coverage; } + ValueFormat get_value_format () const { return valueFormat; } + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); @@ -747,28 +797,33 @@ struct SinglePosFormat1 } template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> + typename SrcLookup, + hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup *src, Iterator it, - ValueFormat valFormat, + ValueFormat newFormat, const hb_map_t *layout_variation_idx_map) { - auto out = c->extend_min (*this); - if (unlikely (!out)) return; - if (unlikely (!c->check_assign (valueFormat, valFormat))) return; + if (unlikely (!c->extend_min (*this))) return; + if (unlikely (!c->check_assign (valueFormat, + newFormat, + HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; - + it - | hb_map (hb_second) - | hb_apply ([&] (hb_array_t<const Value> _) - { valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); }) - ; + for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second)) + { + src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); + // Only serialize the first entry in the iterator, the rest are assumed to + // be the same. + break; + } auto glyphs = + it | hb_map_retains_sorting (hb_first) ; + // TODO(garretrieger): serialize_subset this. coverage.serialize (c, this).serialize (c, glyphs); } @@ -786,7 +841,7 @@ struct SinglePosFormat1 ; bool ret = bool (it); - SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map); + SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map); return_trace (ret); } @@ -800,7 +855,7 @@ struct SinglePosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat; /* Defines the types of data in the @@ -843,6 +898,8 @@ struct SinglePosFormat2 const Coverage &get_coverage () const { return this+coverage; } + ValueFormat get_value_format () const { return valueFormat; } + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); @@ -861,22 +918,23 @@ struct SinglePosFormat2 } template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> + typename SrcLookup, + hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup *src, Iterator it, - ValueFormat valFormat, + ValueFormat newFormat, const hb_map_t *layout_variation_idx_map) { auto out = c->extend_min (*this); if (unlikely (!out)) return; - if (unlikely (!c->check_assign (valueFormat, valFormat))) return; - if (unlikely (!c->check_assign (valueCount, it.len ()))) return; + if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; + if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return; + it | hb_map (hb_second) | hb_apply ([&] (hb_array_t<const Value> _) - { valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); }) + { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); }) ; auto glyphs = @@ -908,7 +966,7 @@ struct SinglePosFormat2 ; bool ret = bool (it); - SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map); + SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map); return_trace (ret); } @@ -922,7 +980,7 @@ struct SinglePosFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat; /* Defines the types of data in the @@ -952,24 +1010,37 @@ struct SinglePos template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> + typename SrcLookup, + hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup* src, Iterator glyph_val_iter_pairs, - ValueFormat valFormat, const hb_map_t *layout_variation_idx_map) { if (unlikely (!c->extend_min (u.format))) return; unsigned format = 2; + ValueFormat new_format = src->get_value_format (); - if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs); + if (glyph_val_iter_pairs) + { + format = get_format (glyph_val_iter_pairs); + new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second)); + } u.format = format; switch (u.format) { - case 1: u.format1.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map); - return; - case 2: u.format2.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map); - return; + case 1: u.format1.serialize (c, + src, + glyph_val_iter_pairs, + new_format, + layout_variation_idx_map); + return; + case 2: u.format2.serialize (c, + src, + glyph_val_iter_pairs, + new_format, + layout_variation_idx_map); + return; default:return; } } @@ -994,14 +1065,13 @@ struct SinglePos } u; }; -template<typename Iterator> +template<typename Iterator, typename SrcLookup> static void SinglePos_serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup *src, Iterator it, - ValueFormat valFormat, const hb_map_t *layout_variation_idx_map) -{ c->start_embed<SinglePos> ()->serialize (c, src, it, valFormat, layout_variation_idx_map); } +{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); } struct PairValueRecord @@ -1011,26 +1081,35 @@ struct PairValueRecord int cmp (hb_codepoint_t k) const { return secondGlyph.cmp (k); } - struct serialize_closure_t + struct context_t { const void *base; const ValueFormat *valueFormats; + const ValueFormat *newFormats; unsigned len1; /* valueFormats[0].get_len() */ const hb_map_t *glyph_map; const hb_map_t *layout_variation_idx_map; }; - bool serialize (hb_serialize_context_t *c, - serialize_closure_t *closure) const + bool subset (hb_subset_context_t *c, + context_t *closure) const { TRACE_SERIALIZE (this); - auto *out = c->start_embed (*this); - if (unlikely (!c->extend_min (out))) return_trace (false); + auto *s = c->serializer; + auto *out = s->start_embed (*this); + if (unlikely (!s->extend_min (out))) return_trace (false); out->secondGlyph = (*closure->glyph_map)[secondGlyph]; - closure->valueFormats[0].serialize_copy (c, closure->base, &values[0], closure->layout_variation_idx_map); - closure->valueFormats[1].serialize_copy (c, closure->base, &values[closure->len1], closure->layout_variation_idx_map); + closure->valueFormats[0].copy_values (s, + closure->newFormats[0], + closure->base, &values[0], + closure->layout_variation_idx_map); + closure->valueFormats[1].copy_values (s, + closure->newFormats[1], + closure->base, + &values[closure->len1], + closure->layout_variation_idx_map); return_trace (true); } @@ -1050,6 +1129,21 @@ struct PairValueRecord valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len)); } + bool intersects (const hb_set_t& glyphset) const + { + return glyphset.has(secondGlyph); + } + + const Value* get_values_1 () const + { + return &values[0]; + } + + const Value* get_values_2 (ValueFormat format1) const + { + return &values[format1.get_len ()]; + } + protected: HBGlyphID secondGlyph; /* GlyphID of second glyph in the * pair--first glyph is listed in the @@ -1140,7 +1234,8 @@ struct PairSet } bool subset (hb_subset_context_t *c, - const ValueFormat valueFormats[2]) const + const ValueFormat valueFormats[2], + const ValueFormat newFormats[2]) const { TRACE_SUBSET (this); auto snap = c->serializer->snapshot (); @@ -1156,10 +1251,11 @@ struct PairSet unsigned len2 = valueFormats[1].get_len (); unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); - PairValueRecord::serialize_closure_t closure = + PairValueRecord::context_t context = { this, valueFormats, + newFormats, len1, &glyph_map, c->plan->layout_variation_idx_map @@ -1170,7 +1266,7 @@ struct PairSet for (unsigned i = 0; i < count; i++) { if (glyphset.has (record->secondGlyph) - && record->serialize (c->serializer, &closure)) num++; + && record->subset (c, &context)) num++; record = &StructAtOffset<const PairValueRecord> (record, record_size); } @@ -1218,7 +1314,7 @@ struct PairPosFormat1 + hb_zip (this+coverage, pairSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([glyphs, this] (const OffsetTo<PairSet> &_) + | hb_map ([glyphs, this] (const Offset16To<PairSet> &_) { return (this+_).intersects (glyphs, valueFormat); }) | hb_any ; @@ -1278,17 +1374,23 @@ struct PairPosFormat1 out->format = format; out->valueFormat[0] = valueFormat[0]; out->valueFormat[1] = valueFormat[1]; + if (c->plan->drop_hints) + { + hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset); + out->valueFormat[0] = newFormats.first; + out->valueFormat[1] = newFormats.second; + } hb_sorted_vector_t<hb_codepoint_t> new_coverage; + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) - | hb_filter ([this, c, out] (const OffsetTo<PairSet>& _) + | hb_filter ([this, c, out] (const Offset16To<PairSet>& _) { auto *o = out->pairSet.serialize_append (c->serializer); if (unlikely (!o)) return false; auto snap = c->serializer->snapshot (); - bool ret = o->serialize_subset (c, _, this, valueFormat); + bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat); if (!ret) { out->pairSet.pop (); @@ -1308,6 +1410,36 @@ struct PairPosFormat1 return_trace (bool (new_coverage)); } + + hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const + { + unsigned len1 = valueFormat[0].get_len (); + unsigned len2 = valueFormat[1].get_len (); + unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); + + unsigned format1 = 0; + unsigned format2 = 0; + for (const Offset16To<PairSet>& _ : + + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second)) + { + const PairSet& set = (this + _); + const PairValueRecord *record = &set.firstPairValueRecord; + + for (unsigned i = 0; i < set.len; i++) + { + if (record->intersects (glyphset)) + { + format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ()); + format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0])); + } + record = &StructAtOffset<const PairValueRecord> (record, record_size); + } + } + + return hb_pair (format1, format2); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1328,7 +1460,7 @@ struct PairPosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat[2]; /* [0] Defines the types of data in @@ -1337,7 +1469,7 @@ struct PairPosFormat1 /* [1] Defines the types of data in * ValueRecord2--for the second glyph * in the pair--may be zero (0) */ - OffsetArrayOf<PairSet> + Array16OfOffset16To<PairSet> pairSet; /* Array of PairSet tables * ordered by Coverage Index */ public: @@ -1355,18 +1487,35 @@ struct PairPosFormat2 void closure_lookups (hb_closure_lookups_context_t *c) const {} void collect_variation_indices (hb_collect_variation_indices_context_t *c) const { + if (!intersects (c->glyph_set)) return; if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return; + hb_set_t klass1_glyphs, klass2_glyphs; + if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return; + if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return; + hb_set_t class1_set, class2_set; - for (const unsigned cp : c->glyph_set->iter ()) + for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage)) + { + if (!klass1_glyphs.has (cp)) class1_set.add (0); + else + { + unsigned klass1 = (this+classDef1).get (cp); + class1_set.add (klass1); + } + } + + class2_set.add (0); + for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs)) { - unsigned klass1 = (this+classDef1).get (cp); unsigned klass2 = (this+classDef2).get (cp); - class1_set.add (klass1); class2_set.add (klass2); } - if (class1_set.is_empty () || class2_set.is_empty ()) return; + if (class1_set.is_empty () + || class2_set.is_empty () + || (class2_set.get_population() == 1 && class2_set.has(0))) + return; unsigned len1 = valueFormat1.get_len (); unsigned len2 = valueFormat2.get_len (); @@ -1431,35 +1580,34 @@ struct PairPosFormat2 auto *out = c->serializer->start_embed (*this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->format = format; - out->valueFormat1 = valueFormat1; - out->valueFormat2 = valueFormat2; hb_map_t klass1_map; - out->classDef1.serialize_subset (c, classDef1, this, &klass1_map); + out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage)); out->class1Count = klass1_map.get_population (); hb_map_t klass2_map; - out->classDef2.serialize_subset (c, classDef2, this, &klass2_map); + out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false); out->class2Count = klass2_map.get_population (); unsigned len1 = valueFormat1.get_len (); unsigned len2 = valueFormat2.get_len (); - + hb_range ((unsigned) class1Count) - | hb_filter (klass1_map) - | hb_apply ([&] (const unsigned class1_idx) - { - + hb_range ((unsigned) class2Count) - | hb_filter (klass2_map) - | hb_apply ([&] (const unsigned class2_idx) - { - unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); - valueFormat1.serialize_copy (c->serializer, this, &values[idx], c->plan->layout_variation_idx_map); - valueFormat2.serialize_copy (c->serializer, this, &values[idx + len1], c->plan->layout_variation_idx_map); - }) - ; - }) - ; + hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2); + if (c->plan->drop_hints) + newFormats = compute_effective_value_formats (klass1_map, klass2_map); + + out->valueFormat1 = newFormats.first; + out->valueFormat2 = newFormats.second; + + for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) + { + for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) + { + unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); + valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map); + valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map); + } + } const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; @@ -1474,6 +1622,30 @@ struct PairPosFormat2 return_trace (out->class1Count && out->class2Count && bool (it)); } + + hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map, + const hb_map_t& klass2_map) const + { + unsigned len1 = valueFormat1.get_len (); + unsigned len2 = valueFormat2.get_len (); + + unsigned format1 = 0; + unsigned format2 = 0; + + for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) + { + for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) + { + unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); + format1 = format1 | valueFormat1.get_effective_format (&values[idx]); + format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]); + } + } + + return hb_pair (format1, format2); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1496,7 +1668,7 @@ struct PairPosFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat1; /* ValueRecord definition--for the @@ -1505,11 +1677,11 @@ struct PairPosFormat2 ValueFormat valueFormat2; /* ValueRecord definition--for the * second glyph of the pair--may be * zero (0) */ - OffsetTo<ClassDef> + Offset16To<ClassDef> classDef1; /* Offset to ClassDef table--from * beginning of PairPos subtable--for * the first glyph of the pair */ - OffsetTo<ClassDef> + Offset16To<ClassDef> classDef2; /* Offset to ClassDef table--from * beginning of PairPos subtable--for * the second glyph of the pair */ @@ -1564,26 +1736,24 @@ struct EntryExitRecord (src_base+exitAnchor).collect_variation_indices (c); } - EntryExitRecord* copy (hb_serialize_context_t *c, - const void *src_base, - const void *dst_base, - const hb_map_t *layout_variation_idx_map) const + EntryExitRecord* subset (hb_subset_context_t *c, + const void *src_base) const { TRACE_SERIALIZE (this); - auto *out = c->embed (this); + auto *out = c->serializer->embed (this); if (unlikely (!out)) return_trace (nullptr); - out->entryAnchor.serialize_copy (c, entryAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map); - out->exitAnchor.serialize_copy (c, exitAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map); + out->entryAnchor.serialize_subset (c, entryAnchor, src_base); + out->exitAnchor.serialize_subset (c, exitAnchor, src_base); return_trace (out); } protected: - OffsetTo<Anchor> + Offset16To<Anchor> entryAnchor; /* Offset to EntryAnchor table--from * beginning of CursivePos * subtable--may be NULL */ - OffsetTo<Anchor> + Offset16To<Anchor> exitAnchor; /* Offset to ExitAnchor table--from * beginning of CursivePos * subtable--may be NULL */ @@ -1724,25 +1894,24 @@ struct CursivePosFormat1 template <typename Iterator, hb_requires (hb_is_iterator (Iterator))> - void serialize (hb_serialize_context_t *c, + void serialize (hb_subset_context_t *c, Iterator it, - const void *src_base, - const hb_map_t *layout_variation_idx_map) + const void *src_base) { - if (unlikely (!c->extend_min ((*this)))) return; + if (unlikely (!c->serializer->extend_min ((*this)))) return; this->format = 1; this->entryExitRecord.len = it.len (); for (const EntryExitRecord& entry_record : + it | hb_map (hb_second)) - c->copy (entry_record, src_base, this, layout_variation_idx_map); + entry_record.subset (c, src_base); auto glyphs = + it | hb_map_retains_sorting (hb_first) ; - coverage.serialize (c, this).serialize (c, glyphs); + coverage.serialize (c->serializer, this).serialize (c->serializer, glyphs); } bool subset (hb_subset_context_t *c) const @@ -1762,7 +1931,7 @@ struct CursivePosFormat1 ; bool ret = bool (it); - out->serialize (c->serializer, it, this, c->plan->layout_variation_idx_map); + out->serialize (c, it, this); return_trace (ret); } @@ -1774,10 +1943,10 @@ struct CursivePosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ - ArrayOf<EntryExitRecord> + Array16Of<EntryExitRecord> entryExitRecord; /* Array of EntryExit records--in * Coverage Index order */ public: @@ -1953,9 +2122,9 @@ struct MarkBasePosFormat1 .serialize (c->serializer, new_coverage.iter ())) return_trace (false); - out->markArray.serialize (c->serializer, out) - .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+markArray), + mark_iter - | hb_map (hb_second)); + out->markArray.serialize_subset (c, markArray, this, + (this+markCoverage).iter (), + &klass_mapping); unsigned basecount = (this+baseArray).rows; auto base_iter = @@ -1984,8 +2153,10 @@ struct MarkBasePosFormat1 | hb_sink (base_indexes) ; } - out->baseArray.serialize (c->serializer, out) - .serialize (c->serializer, base_iter.len (), &(this+baseArray), c->plan->layout_variation_idx_map, base_indexes.iter ()); + + out->baseArray.serialize_subset (c, baseArray, this, + base_iter.len (), + base_indexes.iter ()); return_trace (true); } @@ -2002,17 +2173,17 @@ struct MarkBasePosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> markCoverage; /* Offset to MarkCoverage table--from * beginning of MarkBasePos subtable */ - OffsetTo<Coverage> + Offset16To<Coverage> baseCoverage; /* Offset to BaseCoverage table--from * beginning of MarkBasePos subtable */ HBUINT16 classCount; /* Number of classes defined for marks */ - OffsetTo<MarkArray> + Offset16To<MarkArray> markArray; /* Offset to MarkArray table--from * beginning of MarkBasePos subtable */ - OffsetTo<BaseArray> + Offset16To<BaseArray> baseArray; /* Offset to BaseArray table--from * beginning of MarkBasePos subtable */ public: @@ -2046,12 +2217,12 @@ typedef AnchorMatrix LigatureAttach; /* component-major-- * ordered by class--zero-based. */ /* Array of LigatureAttach tables ordered by LigatureCoverage Index */ -struct LigatureArray : OffsetListOf<LigatureAttach> +struct LigatureArray : List16OfOffset16To<LigatureAttach> { template <typename Iterator, hb_requires (hb_is_iterator (Iterator))> bool subset (hb_subset_context_t *c, - Iterator coverage, + Iterator coverage, unsigned class_count, const hb_map_t *klass_mapping) const { @@ -2067,11 +2238,16 @@ struct LigatureArray : OffsetListOf<LigatureAttach> auto *matrix = out->serialize_append (c->serializer); if (unlikely (!matrix)) return_trace (false); + const LigatureAttach& src = (this + _.second); + auto indexes = + + hb_range (src.rows * class_count) + | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); }) + ; matrix->serialize_subset (c, _.second, this, - class_count, - klass_mapping); + src.rows, + indexes); } return_trace (this->len); } @@ -2205,13 +2381,9 @@ struct MarkLigPosFormat1 .serialize (c->serializer, new_mark_coverage)) return_trace (false); - out->markArray.serialize (c->serializer, out) - .serialize (c->serializer, - &klass_mapping, - c->plan->layout_variation_idx_map, - &(this+markArray), - + mark_iter - | hb_map (hb_second)); + out->markArray.serialize_subset (c, markArray, this, + (this+markCoverage).iter (), + &klass_mapping); auto new_ligature_coverage = + hb_iter (this + ligatureCoverage) @@ -2241,18 +2413,18 @@ struct MarkLigPosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> markCoverage; /* Offset to Mark Coverage table--from * beginning of MarkLigPos subtable */ - OffsetTo<Coverage> + Offset16To<Coverage> ligatureCoverage; /* Offset to Ligature Coverage * table--from beginning of MarkLigPos * subtable */ HBUINT16 classCount; /* Number of defined mark classes */ - OffsetTo<MarkArray> + Offset16To<MarkArray> markArray; /* Offset to MarkArray table--from * beginning of MarkLigPos subtable */ - OffsetTo<LigatureArray> + Offset16To<LigatureArray> ligatureArray; /* Offset to LigatureArray table--from * beginning of MarkLigPos subtable */ public: @@ -2413,9 +2585,9 @@ struct MarkMarkPosFormat1 .serialize (c->serializer, new_coverage.iter ())) return_trace (false); - out->mark1Array.serialize (c->serializer, out) - .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+mark1Array), + mark1_iter - | hb_map (hb_second)); + out->mark1Array.serialize_subset (c, mark1Array, this, + (this+mark1Coverage).iter (), + &klass_mapping); unsigned mark2count = (this+mark2Array).rows; auto mark2_iter = @@ -2444,8 +2616,8 @@ struct MarkMarkPosFormat1 | hb_sink (mark2_indexes) ; } - out->mark2Array.serialize (c->serializer, out) - .serialize (c->serializer, mark2_iter.len (), &(this+mark2Array), c->plan->layout_variation_idx_map, mark2_indexes.iter ()); + + out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ()); return_trace (true); } @@ -2462,19 +2634,19 @@ struct MarkMarkPosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> mark1Coverage; /* Offset to Combining Mark1 Coverage * table--from beginning of MarkMarkPos * subtable */ - OffsetTo<Coverage> + Offset16To<Coverage> mark2Coverage; /* Offset to Combining Mark2 Coverage * table--from beginning of MarkMarkPos * subtable */ HBUINT16 classCount; /* Number of defined mark classes */ - OffsetTo<MarkArray> + Offset16To<MarkArray> mark1Array; /* Offset to Mark1Array table--from * beginning of MarkMarkPos subtable */ - OffsetTo<Mark2Array> + Offset16To<Mark2Array> mark2Array; /* Offset to Mark2Array table--from * beginning of MarkMarkPos subtable */ public: @@ -2663,7 +2835,7 @@ struct GPOS : GSUBGPOS bool subset (hb_subset_context_t *c) const { - hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_features); + hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features); return GSUBGPOS::subset<PosLookup> (&l); } 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 5f10ecb7eef..25538d52f69 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 @@ -46,14 +46,19 @@ struct SingleSubstFormat1 bool intersects (const hb_set_t *glyphs) const { return (this+coverage).intersects (glyphs); } + bool may_have_non_1to1 () const + { return false; } + void closure (hb_closure_context_t *c) const { unsigned d = deltaGlyphID; + + hb_iter (this+coverage) - | hb_filter (*c->glyphs) + | hb_filter (c->parent_active_glyphs ()) | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) | hb_sink (c->output) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -97,7 +102,7 @@ struct SingleSubstFormat1 TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false); - c->check_assign (deltaGlyphID, delta); + c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW); return_trace (true); } @@ -133,7 +138,7 @@ struct SingleSubstFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ HBUINT16 deltaGlyphID; /* Add to original GlyphID to get @@ -147,13 +152,17 @@ struct SingleSubstFormat2 bool intersects (const hb_set_t *glyphs) const { return (this+coverage).intersects (glyphs); } + bool may_have_non_1to1 () const + { return false; } + void closure (hb_closure_context_t *c) const { + hb_zip (this+coverage, substitute) - | hb_filter (*c->glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_sink (c->output) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -233,10 +242,10 @@ struct SingleSubstFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - ArrayOf<HBGlyphID> + Array16Of<HBGlyphID> substitute; /* Array of substitute * GlyphIDs--ordered by Coverage Index */ public: @@ -377,7 +386,7 @@ struct Sequence } protected: - ArrayOf<HBGlyphID> + Array16Of<HBGlyphID> substitute; /* String of GlyphIDs to substitute */ public: DEFINE_SIZE_ARRAY (2, substitute); @@ -388,14 +397,18 @@ struct MultipleSubstFormat1 bool intersects (const hb_set_t *glyphs) const { return (this+coverage).intersects (glyphs); } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { + hb_zip (this+coverage, sequence) - | hb_filter (*c->glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) | hb_apply ([c] (const Sequence &_) { _.closure (c); }) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -475,10 +488,10 @@ struct MultipleSubstFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - OffsetArrayOf<Sequence> + Array16OfOffset16To<Sequence> sequence; /* Array of Sequence tables * ordered by Coverage Index */ public: @@ -603,7 +616,7 @@ struct AlternateSet } protected: - ArrayOf<HBGlyphID> + Array16Of<HBGlyphID> alternates; /* Array of alternate GlyphIDs--in * arbitrary order */ public: @@ -615,14 +628,18 @@ struct AlternateSubstFormat1 bool intersects (const hb_set_t *glyphs) const { return (this+coverage).intersects (glyphs); } + bool may_have_non_1to1 () const + { return false; } + void closure (hb_closure_context_t *c) const { + hb_zip (this+coverage, alternateSet) - | hb_filter (c->glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) | hb_apply ([c] (const AlternateSet &_) { _.closure (c); }) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -710,10 +727,10 @@ struct AlternateSubstFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - OffsetArrayOf<AlternateSet> + Array16OfOffset16To<AlternateSet> alternateSet; /* Array of AlternateSet tables * ordered by Coverage Index */ public: @@ -965,7 +982,7 @@ struct LigatureSet } protected: - OffsetArrayOf<Ligature> + Array16OfOffset16To<Ligature> ligature; /* Array LigatureSet tables * ordered by preference */ public: @@ -980,20 +997,24 @@ struct LigatureSubstFormat1 + hb_zip (this+coverage, ligatureSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([this, glyphs] (const OffsetTo<LigatureSet> &_) + | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_) { return (this+_).intersects (glyphs); }) | hb_any ; } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { + hb_zip (this+coverage, ligatureSet) - | hb_filter (*c->glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_map (hb_add (this)) | hb_apply ([c] (const LigatureSet &_) { _.closure (c); }) ; + } void closure_lookups (hb_closure_lookups_context_t *c) const {} @@ -1086,10 +1107,10 @@ struct LigatureSubstFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - OffsetArrayOf<LigatureSet> + Array16OfOffset16To<LigatureSet> ligatureSet; /* Array LigatureSet tables * ordered by Coverage Index */ public: @@ -1157,7 +1178,7 @@ struct ReverseChainSingleSubstFormat1 if (!(this+coverage).intersects (glyphs)) return false; - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); unsigned int count; @@ -1174,15 +1195,18 @@ struct ReverseChainSingleSubstFormat1 return true; } + bool may_have_non_1to1 () const + { return false; } + void closure (hb_closure_context_t *c) const { if (!intersects (c->glyphs)) return; - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); - const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); + hb_zip (this+coverage, substitute) - | hb_filter (*c->glyphs, hb_first) + | hb_filter (c->parent_active_glyphs (), hb_first) | hb_map (hb_second) | hb_sink (c->output) ; @@ -1200,12 +1224,12 @@ struct ReverseChainSingleSubstFormat1 for (unsigned int i = 0; i < count; i++) if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return; - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); count = lookahead.len; for (unsigned int i = 0; i < count; i++) if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return; - const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead); + const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); count = substitute.len; c->output->add_array (substitute.arrayZ, substitute.len); } @@ -1224,8 +1248,8 @@ struct ReverseChainSingleSubstFormat1 unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); - const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); if (unlikely (index >= substitute.len)) return_trace (false); @@ -1250,11 +1274,80 @@ struct ReverseChainSingleSubstFormat1 return_trace (false); } + template<typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const + { + TRACE_SERIALIZE (this); + auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> (); + + if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) + return_trace (false); + + for (auto& offset : it) { + auto *o = out->serialize_append (c->serializer); + if (unlikely (!o) || !o->serialize_subset (c, offset, this)) + return_trace (false); + } + + return_trace (true); + } + + template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator, + hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)), + hb_requires (hb_is_iterator (BacktrackIterator)), + hb_requires (hb_is_iterator (LookaheadIterator))> + bool serialize (hb_subset_context_t *c, + Iterator coverage_subst_iter, + BacktrackIterator backtrack_iter, + LookaheadIterator lookahead_iter) const + { + TRACE_SERIALIZE (this); + + auto *out = c->serializer->start_embed (this); + if (unlikely (!c->serializer->check_success (out))) return_trace (false); + if (unlikely (!c->serializer->embed (this->format))) return_trace (false); + if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false); + + if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false); + if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false); + + auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID>> (); + auto substitutes = + + coverage_subst_iter + | hb_map (hb_second) + ; + + auto glyphs = + + coverage_subst_iter + | hb_map_retains_sorting (hb_first) + ; + if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes)))) + return_trace (false); + + if (unlikely (!out->coverage.serialize (c->serializer, out).serialize (c->serializer, glyphs))) + return_trace (false); + return_trace (true); + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - // TODO(subset) - return_trace (false); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); + + auto it = + + hb_zip (this+coverage, substitute) + | hb_filter (glyphset, hb_first) + | hb_filter (glyphset, hb_second) + | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t + { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) + ; + + return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ())); } bool sanitize (hb_sanitize_context_t *c) const @@ -1262,27 +1355,27 @@ struct ReverseChainSingleSubstFormat1 TRACE_SANITIZE (this); if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) return_trace (false); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); if (!lookahead.sanitize (c, this)) return_trace (false); - const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead); + const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead); return_trace (substitute.sanitize (c)); } protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ - OffsetArrayOf<Coverage> + Array16OfOffset16To<Coverage> backtrack; /* Array of coverage tables * in backtracking sequence, in glyph * sequence order */ - OffsetArrayOf<Coverage> + Array16OfOffset16To<Coverage> lookaheadX; /* Array of coverage tables * in lookahead sequence, in glyph * sequence order */ - ArrayOf<HBGlyphID> + Array16Of<HBGlyphID> substituteX; /* Array of substitute * GlyphIDs--ordered by Coverage Index */ public: @@ -1388,6 +1481,12 @@ struct SubstLookup : Lookup return lookup_type_is_reverse (type); } + bool may_have_non_1to1 () const + { + hb_have_non_1to1_context_t c; + return dispatch (&c); + } + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); @@ -1522,12 +1621,14 @@ struct SubstLookup : Lookup template <typename context_t> static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); - static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index) + static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index); + + static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index) { if (!c->should_visit_lookup (lookup_index)) return hb_empty_t (); - hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index); + hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index); /* While in theory we should flush here, it will cause timeouts because a recursive * lookup can keep growing the glyph set. Skip, and outer loop will retry up to @@ -1564,7 +1665,7 @@ struct GSUB : GSUBGPOS bool subset (hb_subset_context_t *c) const { - hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_features); + hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features); return GSUBGPOS::subset<SubstLookup> (&l); } @@ -1600,6 +1701,14 @@ template <typename context_t> return l.dispatch (c); } +/*static*/ typename hb_closure_context_t::return_t SubstLookup::closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index) +{ + const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); + if (l.may_have_non_1to1 ()) + hb_set_add_range (covered_seq_indices, seq_index, end_index); + return l.dispatch (c); +} + /*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index) { const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index); 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 36a95ead15f..b537ba0055a 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 @@ -52,23 +52,32 @@ struct hb_intersects_context_t : const hb_set_t *glyphs; hb_intersects_context_t (const hb_set_t *glyphs_) : - glyphs (glyphs_) {} + glyphs (glyphs_) {} +}; + +struct hb_have_non_1to1_context_t : + hb_dispatch_context_t<hb_have_non_1to1_context_t, bool> +{ + template <typename T> + return_t dispatch (const T &obj) { return obj.may_have_non_1to1 (); } + static return_t default_return_value () { return false; } + bool stop_sublookup_iteration (return_t r) const { return r; } }; struct hb_closure_context_t : hb_dispatch_context_t<hb_closure_context_t> { - typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index); + typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indicies, unsigned seq_index, unsigned end_index); template <typename T> return_t dispatch (const T &obj) { obj.closure (this); return hb_empty_t (); } static return_t default_return_value () { return hb_empty_t (); } - void recurse (unsigned int lookup_index) + void recurse (unsigned lookup_index, hb_set_t *covered_seq_indicies, unsigned seq_index, unsigned end_index) { if (unlikely (nesting_level_left == 0 || !recurse_func)) return; nesting_level_left--; - recurse_func (this, lookup_index); + recurse_func (this, lookup_index, covered_seq_indicies, seq_index, end_index); nesting_level_left++; } @@ -83,36 +92,90 @@ struct hb_closure_context_t : if (is_lookup_done (lookup_index)) return false; - done_lookups->set (lookup_index, glyphs->get_population ()); return true; } bool is_lookup_done (unsigned int lookup_index) { - if (unlikely (done_lookups->in_error ())) + if (done_lookups_glyph_count->in_error () || + done_lookups_glyph_set->in_error ()) return true; /* Have we visited this lookup with the current set of glyphs? */ - return done_lookups->get (lookup_index) == glyphs->get_population (); + if (done_lookups_glyph_count->get (lookup_index) != glyphs->get_population ()) + { + done_lookups_glyph_count->set (lookup_index, glyphs->get_population ()); + + if (!done_lookups_glyph_set->get (lookup_index)) + { + hb_set_t* empty_set = hb_set_create (); + if (unlikely (!done_lookups_glyph_set->set (lookup_index, empty_set))) + { + hb_set_destroy (empty_set); + return true; + } + } + + hb_set_clear (done_lookups_glyph_set->get (lookup_index)); + } + + hb_set_t *covered_glyph_set = done_lookups_glyph_set->get (lookup_index); + if (unlikely (covered_glyph_set->in_error ())) + return true; + if (parent_active_glyphs ()->is_subset (covered_glyph_set)) + return true; + + hb_set_union (covered_glyph_set, parent_active_glyphs ()); + return false; + } + + hb_set_t* parent_active_glyphs () + { + if (active_glyphs_stack.length < 1) + return glyphs; + + return active_glyphs_stack.tail (); + } + + void push_cur_active_glyphs (hb_set_t* cur_active_glyph_set) + { + active_glyphs_stack.push (cur_active_glyph_set); + } + + bool pop_cur_done_glyphs () + { + if (active_glyphs_stack.length < 1) + return false; + + active_glyphs_stack.pop (); + return true; } hb_face_t *face; hb_set_t *glyphs; + hb_set_t *cur_intersected_glyphs; hb_set_t output[1]; + hb_vector_t<hb_set_t *> active_glyphs_stack; recurse_func_t recurse_func; unsigned int nesting_level_left; hb_closure_context_t (hb_face_t *face_, hb_set_t *glyphs_, - hb_map_t *done_lookups_, + hb_set_t *cur_intersected_glyphs_, + hb_map_t *done_lookups_glyph_count_, + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set_, unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : face (face_), glyphs (glyphs_), + cur_intersected_glyphs (cur_intersected_glyphs_), recurse_func (nullptr), nesting_level_left (nesting_level_left_), - done_lookups (done_lookups_), + done_lookups_glyph_count (done_lookups_glyph_count_), + done_lookups_glyph_set (done_lookups_glyph_set_), lookup_count (0) - {} + { + push_cur_active_glyphs (glyphs_); + } ~hb_closure_context_t () { flush (); } @@ -123,13 +186,18 @@ struct hb_closure_context_t : hb_set_del_range (output, face->get_num_glyphs (), hb_set_get_max (output)); /* Remove invalid glyphs. */ hb_set_union (glyphs, output); hb_set_clear (output); + active_glyphs_stack.pop (); + active_glyphs_stack.fini (); } private: - hb_map_t *done_lookups; + hb_map_t *done_lookups_glyph_count; + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set; unsigned int lookup_count; }; + + struct hb_closure_lookups_context_t : hb_dispatch_context_t<hb_closure_lookups_context_t> { @@ -737,12 +805,14 @@ struct hb_get_subtables_context_t : typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data); +typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs); typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data); typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data); struct ContextClosureFuncs { intersects_func_t intersects; + intersected_glyphs_func_t intersected_glyphs; }; struct ContextCollectGlyphsFuncs { @@ -765,10 +835,29 @@ static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &val } static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data) { - const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value; + const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value; return (data+coverage).intersects (glyphs); } + +static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs) +{ + unsigned g = reinterpret_cast<const HBUINT16 *>(data)[value]; + intersected_glyphs->add (g); +} +static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs) +{ + const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); + class_def.intersected_class_glyphs (glyphs, value, intersected_glyphs); +} +static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs) +{ + Offset16To<Coverage> coverage; + coverage = value; + (data+coverage).intersected_coverage_glyphs (glyphs, intersected_glyphs); +} + + static inline bool array_is_subset_of (const hb_set_t *glyphs, unsigned int count, const HBUINT16 values[], @@ -792,7 +881,7 @@ static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const } static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data) { - const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value; + const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value; (data+coverage).collect_coverage (glyphs); } static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED, @@ -820,7 +909,7 @@ static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, } static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data) { - const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value; + const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value; return (data+coverage).get_coverage (glyph_id) != NOT_COVERED; } @@ -1146,10 +1235,79 @@ struct LookupRecord DEFINE_SIZE_STATIC (4); }; +enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 }; + +static void context_closure_recurse_lookups (hb_closure_context_t *c, + unsigned inputCount, const HBUINT16 input[], + unsigned lookupCount, + const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */, + unsigned value, + ContextFormat context_format, + const void *data, + intersected_glyphs_func_t intersected_glyphs_func) +{ + hb_set_t *covered_seq_indicies = hb_set_create (); + for (unsigned int i = 0; i < lookupCount; i++) + { + unsigned seqIndex = lookupRecord[i].sequenceIndex; + if (seqIndex >= inputCount) continue; + + hb_set_t *pos_glyphs = nullptr; + + if (hb_set_is_empty (covered_seq_indicies) || !hb_set_has (covered_seq_indicies, seqIndex)) + { + pos_glyphs = hb_set_create (); + if (seqIndex == 0) + { + switch (context_format) { + case ContextFormat::SimpleContext: + pos_glyphs->add (value); + break; + case ContextFormat::ClassBasedContext: + intersected_glyphs_func (c->cur_intersected_glyphs, data, value, pos_glyphs); + break; + case ContextFormat::CoverageBasedContext: + hb_set_set (pos_glyphs, c->cur_intersected_glyphs); + break; + } + } + else + { + const void *input_data = input; + unsigned input_value = seqIndex - 1; + if (context_format != ContextFormat::SimpleContext) + { + input_data = data; + input_value = input[seqIndex - 1]; + } + + intersected_glyphs_func (c->glyphs, input_data, input_value, pos_glyphs); + } + } + + hb_set_add (covered_seq_indicies, seqIndex); + if (pos_glyphs) + c->push_cur_active_glyphs (pos_glyphs); + + unsigned endIndex = inputCount; + if (context_format == ContextFormat::CoverageBasedContext) + endIndex += 1; + + c->recurse (lookupRecord[i].lookupListIndex, covered_seq_indicies, seqIndex, endIndex); + + if (pos_glyphs) { + c->pop_cur_done_glyphs (); + hb_set_destroy (pos_glyphs); + } + } + + hb_set_destroy (covered_seq_indicies); +} + template <typename context_t> static inline void recurse_lookups (context_t *c, - unsigned int lookupCount, - const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */) + unsigned int lookupCount, + const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */) { for (unsigned int i = 0; i < lookupCount; i++) c->recurse (lookupRecord[i].lookupListIndex); @@ -1284,6 +1442,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c, struct ContextClosureLookupContext { ContextClosureFuncs funcs; + ContextFormat context_format; const void *intersects_data; }; @@ -1314,13 +1473,19 @@ static inline void context_closure_lookup (hb_closure_context_t *c, const HBUINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], + unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */ ContextClosureLookupContext &lookup_context) { if (context_intersects (c->glyphs, inputCount, input, lookup_context)) - recurse_lookups (c, - lookupCount, lookupRecord); + context_closure_recurse_lookups (c, + inputCount, input, + lookupCount, lookupRecord, + value, + lookup_context.context_format, + lookup_context.intersects_data, + lookup_context.funcs.intersected_glyphs); } static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, @@ -1377,7 +1542,7 @@ struct Rule lookup_context); } - void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const + void closure (hb_closure_context_t *c, unsigned value, ContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; @@ -1386,7 +1551,7 @@ struct Rule context_closure_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, - lookup_context); + value, lookup_context); } void closure_lookups (hb_closure_lookups_context_t *c, @@ -1511,7 +1676,7 @@ struct RuleSet ; } - void closure (hb_closure_context_t *c, + void closure (hb_closure_context_t *c, unsigned value, ContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; @@ -1519,7 +1684,7 @@ struct RuleSet return + hb_iter (rule) | hb_map (hb_add (this)) - | hb_apply ([&] (const Rule &_) { _.closure (c, lookup_context); }) + | hb_apply ([&] (const Rule &_) { _.closure (c, value, lookup_context); }) ; } @@ -1577,7 +1742,7 @@ struct RuleSet auto *out = c->serializer->start_embed (*this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - for (const OffsetTo<Rule>& _ : rule) + for (const Offset16To<Rule>& _ : rule) { if (!_) continue; auto *o = out->rule.serialize_append (c->serializer); @@ -1604,7 +1769,7 @@ struct RuleSet } protected: - OffsetArrayOf<Rule> + Array16OfOffset16To<Rule> rule; /* Array of Rule tables * ordered by preference */ public: @@ -1617,7 +1782,8 @@ struct ContextFormat1 bool intersects (const hb_set_t *glyphs) const { struct ContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, nullptr }; @@ -1631,25 +1797,32 @@ struct ContextFormat1 ; } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { + c->cur_intersected_glyphs->clear (); + get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + struct ContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, nullptr }; - + hb_zip (this+coverage, ruleSet) - | hb_filter (*c->glyphs, hb_first) - | hb_map (hb_second) - | hb_map (hb_add (this)) - | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); }) + + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len)) + | hb_filter (c->parent_active_glyphs (), hb_first) + | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const RuleSet&> (_.first, this+ruleSet[_.second]); }) + | hb_apply ([&] (const hb_pair_t<unsigned, const RuleSet&>& _) { _.second.closure (c, _.first, lookup_context); }) ; } void closure_lookups (hb_closure_lookups_context_t *c) const { struct ContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, nullptr }; @@ -1738,10 +1911,10 @@ struct ContextFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ - OffsetArrayOf<RuleSet> + Array16OfOffset16To<RuleSet> ruleSet; /* Array of RuleSet tables * ordered by Coverage Index */ public: @@ -1759,7 +1932,8 @@ struct ContextFormat2 const ClassDef &class_def = this+classDef; struct ContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, &class_def }; @@ -1774,26 +1948,35 @@ struct ContextFormat2 ; } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { if (!(this+coverage).intersects (c->glyphs)) return; + c->cur_intersected_glyphs->clear (); + get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + const ClassDef &class_def = this+classDef; struct ContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, &class_def }; return + hb_enumerate (ruleSet) | hb_filter ([&] (unsigned _) - { return class_def.intersects_class (c->glyphs, _); }, + { return class_def.intersects_class (c->cur_intersected_glyphs, _); }, hb_first) - | hb_map (hb_second) - | hb_map (hb_add (this)) - | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); }) + | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<RuleSet>&> _) + { + const RuleSet& rule_set = this+_.second; + rule_set.closure (c, _.first, lookup_context); + }) ; } @@ -1805,7 +1988,8 @@ struct ContextFormat2 const ClassDef &class_def = this+classDef; struct ContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, &class_def }; @@ -1919,13 +2103,13 @@ struct ContextFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ - OffsetTo<ClassDef> + Offset16To<ClassDef> classDef; /* Offset to glyph ClassDef table--from * beginning of table */ - OffsetArrayOf<RuleSet> + Array16OfOffset16To<RuleSet> ruleSet; /* Array of RuleSet tables * ordered by class */ public: @@ -1941,7 +2125,8 @@ struct ContextFormat3 return false; struct ContextClosureLookupContext lookup_context = { - {intersects_coverage}, + {intersects_coverage, intersected_coverage_glyphs}, + ContextFormat::CoverageBasedContext, this }; return context_intersects (glyphs, @@ -1949,20 +2134,27 @@ struct ContextFormat3 lookup_context); } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { if (!(this+coverageZ[0]).intersects (c->glyphs)) return; + c->cur_intersected_glyphs->clear (); + get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount)); struct ContextClosureLookupContext lookup_context = { - {intersects_coverage}, + {intersects_coverage, intersected_coverage_glyphs}, + ContextFormat::CoverageBasedContext, this }; context_closure_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, - lookup_context); + 0, lookup_context); } void closure_lookups (hb_closure_lookups_context_t *c) const @@ -2032,10 +2224,10 @@ struct ContextFormat3 auto coverages = coverageZ.as_array (glyphCount); - for (const OffsetTo<Coverage>& offset : coverages) + for (const Offset16To<Coverage>& offset : coverages) { /* TODO(subset) This looks like should not be necessary to write this way. */ - auto *o = c->serializer->allocate_size<OffsetTo<Coverage>> (OffsetTo<Coverage>::static_size); + auto *o = c->serializer->allocate_size<Offset16To<Coverage>> (Offset16To<Coverage>::static_size); if (unlikely (!o)) return_trace (false); if (!o->serialize_subset (c, offset, this)) return_trace (false); } @@ -2066,7 +2258,7 @@ struct ContextFormat3 HBUINT16 glyphCount; /* Number of glyphs in the input glyph * sequence */ HBUINT16 lookupCount; /* Number of LookupRecords */ - UnsizedArrayOf<OffsetTo<Coverage>> + UnsizedArrayOf<Offset16To<Coverage>> coverageZ; /* Array of offsets to Coverage * table in glyph sequence order */ /*UnsizedArrayOf<LookupRecord> @@ -2106,6 +2298,7 @@ struct Context struct ChainContextClosureLookupContext { ContextClosureFuncs funcs; + ContextFormat context_format; const void *intersects_data[3]; }; @@ -2150,6 +2343,7 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c, const HBUINT16 lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], + unsigned value, ChainContextClosureLookupContext &lookup_context) { if (chain_context_intersects (c->glyphs, @@ -2157,8 +2351,13 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c, inputCount, input, lookaheadCount, lookahead, lookup_context)) - recurse_lookups (c, - lookupCount, lookupRecord); + context_closure_recurse_lookups (c, + inputCount, input, + lookupCount, lookupRecord, + value, + lookup_context.context_format, + lookup_context.intersects_data[1], + lookup_context.funcs.intersected_glyphs); } static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, @@ -2239,7 +2438,7 @@ struct ChainRule bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const { const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); + const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); return chain_context_intersects (glyphs, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -2247,19 +2446,20 @@ struct ChainRule lookup_context); } - void closure (hb_closure_context_t *c, + void closure (hb_closure_context_t *c, unsigned value, ChainContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); chain_context_closure_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, lookahead.len, lookahead.arrayZ, lookup.len, lookup.arrayZ, + value, lookup_context); } @@ -2270,8 +2470,8 @@ struct ChainRule if (!intersects (c->glyphs, lookup_context)) return; const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); recurse_lookups (c, lookup.len, lookup.arrayZ); } @@ -2279,8 +2479,8 @@ struct ChainRule ChainContextCollectGlyphsLookupContext &lookup_context) const { const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); chain_context_collect_glyphs_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -2293,8 +2493,8 @@ struct ChainRule ChainContextApplyLookupContext &lookup_context) const { const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); return chain_context_would_apply_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -2306,8 +2506,8 @@ struct ChainRule { TRACE_APPLY (this); const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); return_trace (chain_context_apply_lookup (c, backtrack.len, backtrack.arrayZ, input.lenP1, input.arrayZ, @@ -2345,12 +2545,12 @@ struct ChainRule serialize_array (c, input.lenP1, + input.iter () | hb_map (mapping)); - const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); + const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); if (lookahead_map) mapping = lookahead_map; serialize_array (c, lookahead.len, + lookahead.iter () | hb_map (mapping)); - const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead); HBUINT16* lookupCount = c->embed (&(lookupRecord.len)); if (!lookupCount) return_trace (nullptr); @@ -2377,7 +2577,7 @@ struct ChainRule TRACE_SUBSET (this); const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); - const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); + const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); if (!backtrack_map) { @@ -2408,24 +2608,24 @@ struct ChainRule if (!backtrack.sanitize (c)) return_trace (false); const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); if (!input.sanitize (c)) return_trace (false); - const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); + const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input); if (!lookahead.sanitize (c)) return_trace (false); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); return_trace (lookup.sanitize (c)); } protected: - ArrayOf<HBUINT16> + Array16Of<HBUINT16> backtrack; /* Array of backtracking values * (to be matched before the input * sequence) */ HeadlessArrayOf<HBUINT16> inputX; /* Array of input values (start with * second glyph) */ - ArrayOf<HBUINT16> + Array16Of<HBUINT16> lookaheadX; /* Array of lookahead values's (to be * matched after the input sequence) */ - ArrayOf<LookupRecord> + Array16Of<LookupRecord> lookupX; /* Array of LookupRecords--in * design order) */ public: @@ -2443,14 +2643,14 @@ struct ChainRuleSet | hb_any ; } - void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const + void closure (hb_closure_context_t *c, unsigned value, ChainContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; return + hb_iter (rule) | hb_map (hb_add (this)) - | hb_apply ([&] (const ChainRule &_) { _.closure (c, lookup_context); }) + | hb_apply ([&] (const ChainRule &_) { _.closure (c, value, lookup_context); }) ; } @@ -2508,7 +2708,7 @@ struct ChainRuleSet auto *out = c->serializer->start_embed (*this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - for (const OffsetTo<ChainRule>& _ : rule) + for (const Offset16To<ChainRule>& _ : rule) { if (!_) continue; auto *o = out->rule.serialize_append (c->serializer); @@ -2539,7 +2739,7 @@ struct ChainRuleSet } protected: - OffsetArrayOf<ChainRule> + Array16OfOffset16To<ChainRule> rule; /* Array of ChainRule tables * ordered by preference */ public: @@ -2551,7 +2751,8 @@ struct ChainContextFormat1 bool intersects (const hb_set_t *glyphs) const { struct ChainContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, {nullptr, nullptr, nullptr} }; @@ -2565,25 +2766,32 @@ struct ChainContextFormat1 ; } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { + c->cur_intersected_glyphs->clear (); + get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + struct ChainContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, {nullptr, nullptr, nullptr} }; - + hb_zip (this+coverage, ruleSet) - | hb_filter (*c->glyphs, hb_first) - | hb_map (hb_second) - | hb_map (hb_add (this)) - | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); }) + + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len)) + | hb_filter (c->parent_active_glyphs (), hb_first) + | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const ChainRuleSet&> (_.first, this+ruleSet[_.second]); }) + | hb_apply ([&] (const hb_pair_t<unsigned, const ChainRuleSet&>& _) { _.second.closure (c, _.first, lookup_context); }) ; } void closure_lookups (hb_closure_lookups_context_t *c) const { struct ChainContextClosureLookupContext lookup_context = { - {intersects_glyph}, + {intersects_glyph, intersected_glyph}, + ContextFormat::SimpleContext, {nullptr, nullptr, nullptr} }; @@ -2671,10 +2879,10 @@ struct ChainContextFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ - OffsetArrayOf<ChainRuleSet> + Array16OfOffset16To<ChainRuleSet> ruleSet; /* Array of ChainRuleSet tables * ordered by Coverage Index */ public: @@ -2693,7 +2901,8 @@ struct ChainContextFormat2 const ClassDef &lookahead_class_def = this+lookaheadClassDef; struct ChainContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, {&backtrack_class_def, &input_class_def, &lookahead_class_def} @@ -2709,17 +2918,25 @@ struct ChainContextFormat2 | hb_any ; } + + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { if (!(this+coverage).intersects (c->glyphs)) return; + c->cur_intersected_glyphs->clear (); + get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + const ClassDef &backtrack_class_def = this+backtrackClassDef; const ClassDef &input_class_def = this+inputClassDef; const ClassDef &lookahead_class_def = this+lookaheadClassDef; struct ChainContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, {&backtrack_class_def, &input_class_def, &lookahead_class_def} @@ -2728,11 +2945,13 @@ struct ChainContextFormat2 return + hb_enumerate (ruleSet) | hb_filter ([&] (unsigned _) - { return input_class_def.intersects_class (c->glyphs, _); }, + { return input_class_def.intersects_class (c->cur_intersected_glyphs, _); }, hb_first) - | hb_map (hb_second) - | hb_map (hb_add (this)) - | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); }) + | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<ChainRuleSet>&> _) + { + const ChainRuleSet& chainrule_set = this+_.second; + chainrule_set.closure (c, _.first, lookup_context); + }) ; } @@ -2746,7 +2965,8 @@ struct ChainContextFormat2 const ClassDef &lookahead_class_def = this+lookaheadClassDef; struct ChainContextClosureLookupContext lookup_context = { - {intersects_class}, + {intersects_class, intersected_class_glyphs}, + ContextFormat::ClassBasedContext, {&backtrack_class_def, &input_class_def, &lookahead_class_def} @@ -2852,7 +3072,7 @@ struct ChainContextFormat2 bool ret = true; const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; auto last_non_zero = c->serializer->snapshot (); - for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet) + for (const Offset16To<ChainRuleSet>& _ : + hb_enumerate (ruleSet) | hb_filter (input_klass_map, hb_first) | hb_map (hb_second)) { @@ -2898,22 +3118,22 @@ struct ChainContextFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ - OffsetTo<ClassDef> + Offset16To<ClassDef> backtrackClassDef; /* Offset to glyph ClassDef table * containing backtrack sequence * data--from beginning of table */ - OffsetTo<ClassDef> + Offset16To<ClassDef> inputClassDef; /* Offset to glyph ClassDef * table containing input sequence * data--from beginning of table */ - OffsetTo<ClassDef> + Offset16To<ClassDef> lookaheadClassDef; /* Offset to glyph ClassDef table * containing lookahead sequence * data--from beginning of table */ - OffsetArrayOf<ChainRuleSet> + Array16OfOffset16To<ChainRuleSet> ruleSet; /* Array of ChainRuleSet tables * ordered by class */ public: @@ -2924,14 +3144,15 @@ struct ChainContextFormat3 { bool intersects (const hb_set_t *glyphs) const { - const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); if (!(this+input[0]).intersects (glyphs)) return false; - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); struct ChainContextClosureLookupContext lookup_context = { - {intersects_coverage}, + {intersects_coverage, intersected_coverage_glyphs}, + ContextFormat::CoverageBasedContext, {this, this, this} }; return chain_context_intersects (glyphs, @@ -2941,17 +3162,24 @@ struct ChainContextFormat3 lookup_context); } + bool may_have_non_1to1 () const + { return true; } + void closure (hb_closure_context_t *c) const { - const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); if (!(this+input[0]).intersects (c->glyphs)) return; - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + c->cur_intersected_glyphs->clear (); + get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs); + + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); struct ChainContextClosureLookupContext lookup_context = { - {intersects_coverage}, + {intersects_coverage, intersected_coverage_glyphs}, + ContextFormat::CoverageBasedContext, {this, this, this} }; chain_context_closure_lookup (c, @@ -2959,7 +3187,7 @@ struct ChainContextFormat3 input.len, (const HBUINT16 *) input.arrayZ + 1, lookahead.len, (const HBUINT16 *) lookahead.arrayZ, lookup.len, lookup.arrayZ, - lookup_context); + 0, lookup_context); } void closure_lookups (hb_closure_lookups_context_t *c) const @@ -2967,9 +3195,9 @@ struct ChainContextFormat3 if (!intersects (c->glyphs)) return; - const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); recurse_lookups (c, lookup.len, lookup.arrayZ); } @@ -2977,12 +3205,12 @@ struct ChainContextFormat3 void collect_glyphs (hb_collect_glyphs_context_t *c) const { - const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); (this+input[0]).collect_coverage (c->input); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); struct ChainContextCollectGlyphsLookupContext lookup_context = { {collect_coverage}, {this, this, this} @@ -2997,9 +3225,9 @@ struct ChainContextFormat3 bool would_apply (hb_would_apply_context_t *c) const { - const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); struct ChainContextApplyLookupContext lookup_context = { {match_coverage}, {this, this, this} @@ -3013,20 +3241,20 @@ struct ChainContextFormat3 const Coverage &get_coverage () const { - const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); return this+input[0]; } bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); - const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); struct ChainContextApplyLookupContext lookup_context = { {match_coverage}, {this, this, this} @@ -3043,7 +3271,7 @@ struct ChainContextFormat3 bool serialize_coverage_offsets (hb_subset_context_t *c, Iterator it, const void* base) const { TRACE_SERIALIZE (this); - auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> (); + auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> (); if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) return_trace (false); @@ -3068,15 +3296,15 @@ struct ChainContextFormat3 if (!serialize_coverage_offsets (c, backtrack.iter (), this)) return_trace (false); - const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); if (!serialize_coverage_offsets (c, input.iter (), this)) return_trace (false); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); if (!serialize_coverage_offsets (c, lookahead.iter (), this)) return_trace (false); - const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead); HBUINT16 lookupCount; lookupCount = lookupRecord.len; if (!c->serializer->copy (lookupCount)) return_trace (false); @@ -3092,30 +3320,30 @@ struct ChainContextFormat3 { TRACE_SANITIZE (this); if (!backtrack.sanitize (c, this)) return_trace (false); - const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); if (!input.sanitize (c, this)) return_trace (false); if (!input.len) return_trace (false); /* To be consistent with Context. */ - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); + const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input); if (!lookahead.sanitize (c, this)) return_trace (false); - const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead); return_trace (lookup.sanitize (c)); } protected: HBUINT16 format; /* Format identifier--format = 3 */ - OffsetArrayOf<Coverage> + Array16OfOffset16To<Coverage> backtrack; /* Array of coverage tables * in backtracking sequence, in glyph * sequence order */ - OffsetArrayOf<Coverage> + Array16OfOffset16To<Coverage> inputX ; /* Array of coverage * tables in input sequence, in glyph * sequence order */ - OffsetArrayOf<Coverage> + Array16OfOffset16To<Coverage> lookaheadX; /* Array of coverage tables * in lookahead sequence, in glyph * sequence order */ - ArrayOf<LookupRecord> + Array16Of<LookupRecord> lookupX; /* Array of LookupRecords--in * design order) */ public: @@ -3154,7 +3382,7 @@ struct ExtensionFormat1 template <typename X> const X& get_subtable () const - { return this + reinterpret_cast<const LOffsetTo<typename T::SubTable> &> (extensionOffset); } + { return this + reinterpret_cast<const Offset32To<typename T::SubTable> &> (extensionOffset); } template <typename context_t, typename ...Ts> typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const @@ -3186,9 +3414,9 @@ struct ExtensionFormat1 out->extensionLookupType = extensionLookupType; const auto& src_offset = - reinterpret_cast<const LOffsetTo<typename T::SubTable> &> (extensionOffset); + reinterpret_cast<const Offset32To<typename T::SubTable> &> (extensionOffset); auto& dest_offset = - reinterpret_cast<LOffsetTo<typename T::SubTable> &> (out->extensionOffset); + reinterpret_cast<Offset32To<typename T::SubTable> &> (out->extensionOffset); return_trace (dest_offset.serialize_subset (c, src_offset, this, get_type ())); } @@ -3372,6 +3600,20 @@ struct GSUBGPOS hb_set_subtract (lookup_indexes, &inactive_lookups); } + void prune_langsys (const hb_map_t *duplicate_feature_map, + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map, + hb_set_t *new_feature_indexes /* OUT */) const + { + hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes); + + unsigned count = get_script_count (); + for (unsigned script_index = 0; script_index < count; script_index++) + { + const Script& s = get_script (script_index); + s.prune_langsys (&c, script_index); + } + } + template <typename TLookup> bool subset (hb_subset_layout_context_t *c) const { @@ -3380,15 +3622,15 @@ struct GSUBGPOS if (unlikely (!out)) return_trace (false); typedef LookupOffsetList<TLookup> TLookupList; - reinterpret_cast<OffsetTo<TLookupList> &> (out->lookupList) + reinterpret_cast<Offset16To<TLookupList> &> (out->lookupList) .serialize_subset (c->subset_context, - reinterpret_cast<const OffsetTo<TLookupList> &> (lookupList), + reinterpret_cast<const Offset16To<TLookupList> &> (lookupList), this, c); - reinterpret_cast<OffsetTo<RecordListOfFeature> &> (out->featureList) + reinterpret_cast<Offset16To<RecordListOfFeature> &> (out->featureList) .serialize_subset (c->subset_context, - reinterpret_cast<const OffsetTo<RecordListOfFeature> &> (featureList), + reinterpret_cast<const Offset16To<RecordListOfFeature> &> (featureList), this, c); @@ -3412,8 +3654,65 @@ struct GSUBGPOS return_trace (true); } + void find_duplicate_features (const hb_map_t *lookup_indices, + const hb_set_t *feature_indices, + hb_map_t *duplicate_feature_map /* OUT */) const + { + //find out duplicate features after subset + unsigned prev = 0xFFFFu; + for (unsigned i : feature_indices->iter ()) + { + if (prev == 0xFFFFu) + { + duplicate_feature_map->set (i, i); + prev = i; + continue; + } + + hb_tag_t t = get_feature_tag (i); + hb_tag_t prev_t = get_feature_tag (prev); + if (t != prev_t) + { + duplicate_feature_map->set (i, i); + prev = i; + continue; + } + + const Feature& f = get_feature (i); + const Feature& prev_f = get_feature (prev); + + auto f_iter = + + hb_iter (f.lookupIndex) + | hb_filter (lookup_indices) + ; + + auto prev_iter = + + hb_iter (prev_f.lookupIndex) + | hb_filter (lookup_indices) + ; + + if (f_iter.len () != prev_iter.len ()) + { + duplicate_feature_map->set (i, i); + prev = i; + continue; + } + + bool is_equal = true; + for (auto _ : + hb_zip (f_iter, prev_iter)) + if (_.first != _.second) { is_equal = false; break; } + + if (is_equal == true) duplicate_feature_map->set (i, prev); + else + { + duplicate_feature_map->set (i, i); + prev = i; + } + } + } + void prune_features (const hb_map_t *lookup_indices, /* IN */ - hb_set_t *feature_indices /* IN/OUT */) const + hb_set_t *feature_indices /* IN/OUT */) const { #ifndef HB_NO_VAR // This is the set of feature indices which have alternate versions defined @@ -3431,6 +3730,13 @@ struct GSUBGPOS for (unsigned i : feature_indices->iter()) { const Feature& f = get_feature (i); + hb_tag_t tag = get_feature_tag (i); + if (tag == HB_TAG ('p', 'r', 'e', 'f')) + // Note: Never ever drop feature 'pref', even if it's empty. + // HarfBuzz chooses shaper for Khmer based on presence of this + // feature. See thread at: + // http://lists.freedesktop.org/archives/harfbuzz/2012-November/002660.html + continue; if (f.featureParams.is_null () && !f.intersects_lookup_indexes (lookup_indices) @@ -3452,12 +3758,12 @@ struct GSUBGPOS bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - typedef OffsetListOf<TLookup> TLookupList; + typedef List16OfOffset16To<TLookup> TLookupList; if (unlikely (!(version.sanitize (c) && likely (version.major == 1) && scriptList.sanitize (c, this) && featureList.sanitize (c, this) && - reinterpret_cast<const OffsetTo<TLookupList> &> (lookupList).sanitize (c, this)))) + reinterpret_cast<const Offset16To<TLookupList> &> (lookupList).sanitize (c, this)))) return_trace (false); #ifndef HB_NO_VAR @@ -3510,13 +3816,13 @@ struct GSUBGPOS protected: FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set * to 0x00010000u */ - OffsetTo<ScriptList> + Offset16To<ScriptList> scriptList; /* ScriptList table */ - OffsetTo<FeatureList> + Offset16To<FeatureList> featureList; /* FeatureList table */ - OffsetTo<LookupList> + Offset16To<LookupList> lookupList; /* LookupList table */ - LOffsetTo<FeatureVariations> + Offset32To<FeatureVariations> featureVars; /* Offset to Feature Variations table--from beginning of table * (may be NULL). Introduced diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh index ffd2bf45745..3b2293dff0a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh @@ -45,7 +45,7 @@ typedef IndexArray JstfModList; * JstfMax -- Justification Maximum Table */ -typedef OffsetListOf<PosLookup> JstfMax; +typedef List16OfOffset16To<PosLookup> JstfMax; /* @@ -71,43 +71,43 @@ struct JstfPriority } protected: - OffsetTo<JstfModList> + Offset16To<JstfModList> shrinkageEnableGSUB; /* Offset to Shrinkage Enable GSUB * JstfModList table--from beginning of * JstfPriority table--may be NULL */ - OffsetTo<JstfModList> + Offset16To<JstfModList> shrinkageDisableGSUB; /* Offset to Shrinkage Disable GSUB * JstfModList table--from beginning of * JstfPriority table--may be NULL */ - OffsetTo<JstfModList> + Offset16To<JstfModList> shrinkageEnableGPOS; /* Offset to Shrinkage Enable GPOS * JstfModList table--from beginning of * JstfPriority table--may be NULL */ - OffsetTo<JstfModList> + Offset16To<JstfModList> shrinkageDisableGPOS; /* Offset to Shrinkage Disable GPOS * JstfModList table--from beginning of * JstfPriority table--may be NULL */ - OffsetTo<JstfMax> + Offset16To<JstfMax> shrinkageJstfMax; /* Offset to Shrinkage JstfMax table-- * from beginning of JstfPriority table * --may be NULL */ - OffsetTo<JstfModList> + Offset16To<JstfModList> extensionEnableGSUB; /* Offset to Extension Enable GSUB * JstfModList table--from beginning of * JstfPriority table--may be NULL */ - OffsetTo<JstfModList> + Offset16To<JstfModList> extensionDisableGSUB; /* Offset to Extension Disable GSUB * JstfModList table--from beginning of * JstfPriority table--may be NULL */ - OffsetTo<JstfModList> + Offset16To<JstfModList> extensionEnableGPOS; /* Offset to Extension Enable GPOS * JstfModList table--from beginning of * JstfPriority table--may be NULL */ - OffsetTo<JstfModList> + Offset16To<JstfModList> extensionDisableGPOS; /* Offset to Extension Disable GPOS * JstfModList table--from beginning of * JstfPriority table--may be NULL */ - OffsetTo<JstfMax> + Offset16To<JstfMax> extensionJstfMax; /* Offset to Extension JstfMax table-- * from beginning of JstfPriority table * --may be NULL */ @@ -121,13 +121,13 @@ struct JstfPriority * JstfLangSys -- Justification Language System Table */ -struct JstfLangSys : OffsetListOf<JstfPriority> +struct JstfLangSys : List16OfOffset16To<JstfPriority> { bool sanitize (hb_sanitize_context_t *c, const Record_sanitize_closure_t * = nullptr) const { TRACE_SANITIZE (this); - return_trace (OffsetListOf<JstfPriority>::sanitize (c)); + return_trace (List16OfOffset16To<JstfPriority>::sanitize (c)); } }; @@ -136,7 +136,7 @@ struct JstfLangSys : OffsetListOf<JstfPriority> * ExtenderGlyphs -- Extender Glyph Table */ -typedef SortedArrayOf<HBGlyphID> ExtenderGlyphs; +typedef SortedArray16Of<HBGlyphID> ExtenderGlyphs; /* @@ -174,10 +174,10 @@ struct JstfScript } protected: - OffsetTo<ExtenderGlyphs> + Offset16To<ExtenderGlyphs> extenderGlyphs; /* Offset to ExtenderGlyph table--from beginning * of JstfScript table-may be NULL */ - OffsetTo<JstfLangSys> + Offset16To<JstfLangSys> defaultLangSys; /* Offset to DefaultJstfLangSys table--from * beginning of JstfScript table--may be Null */ RecordArrayOf<JstfLangSys> 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 89df949b260..55a6587cd05 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 @@ -331,6 +331,8 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face, * * Useful if the client program wishes to cache the list. * + * Return value: Total number of attachment points for @glyph. + * **/ unsigned int hb_ot_layout_get_attach_points (hb_face_t *face, @@ -357,6 +359,8 @@ hb_ot_layout_get_attach_points (hb_face_t *face, * Fetches a list of the caret positions defined for a ligature glyph in the GDEF * table of the font. The list returned will begin at the offset provided. * + * Return value: Total number of ligature caret positions for @glyph. + * **/ unsigned int hb_ot_layout_get_ligature_carets (hb_font_t *font, @@ -419,6 +423,8 @@ get_gsubgpos_table (hb_face_t *face, * Fetches a list of all scripts enumerated in the specified face's GSUB table * or GPOS table. The list returned will begin at the offset provided. * + * Return value: Total number of script tags. + * **/ unsigned int hb_ot_layout_table_get_script_tags (hb_face_t *face, @@ -585,6 +591,8 @@ hb_ot_layout_table_select_script (hb_face_t *face, * * Fetches a list of all feature tags in the given face's GSUB or GPOS table. * + * Return value: Total number of feature tags. + * **/ unsigned int hb_ot_layout_table_get_feature_tags (hb_face_t *face, @@ -647,6 +655,8 @@ hb_ot_layout_table_find_feature (hb_face_t *face, * Fetches a list of language tags in the given face's GSUB or GPOS table, underneath * the specified script index. The list returned will begin at the offset provided. * + * Return value: Total number of language tags. + * **/ unsigned int hb_ot_layout_script_get_language_tags (hb_face_t *face, @@ -818,6 +828,8 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face, * Fetches a list of all features in the specified face's GSUB table * or GPOS table, underneath the specified script and language. The list * returned will begin at the offset provided. + * + * Return value: Total number of features. **/ unsigned int hb_ot_layout_language_get_feature_indexes (hb_face_t *face, @@ -850,6 +862,7 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face, * or GPOS table, underneath the specified script and language. The list * returned will begin at the offset provided. * + * Return value: Total number of feature tags. **/ unsigned int hb_ot_layout_language_get_feature_tags (hb_face_t *face, @@ -932,6 +945,8 @@ hb_ot_layout_language_find_feature (hb_face_t *face, * the specified face's GSUB table or GPOS table. The list returned will * begin at the offset provided. * + * Return value: Total number of lookups. + * * Since: 0.9.7 **/ unsigned int @@ -960,6 +975,8 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, * Fetches the total number of lookups enumerated in the specified * face's GSUB table or GPOS table. * + * Return value: Total number of lookups. + * * Since: 0.9.22 **/ unsigned int @@ -1262,6 +1279,8 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, * Fetches a list of feature variations in the specified face's GSUB table * or GPOS table, at the specified variation coordinates. * + * Return value: %true if feature variations were found, %false otherwise. + * **/ hb_bool_t hb_ot_layout_table_find_feature_variations (hb_face_t *face, @@ -1291,6 +1310,8 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face, * the specified face's GSUB table or GPOS table, enabled at the specified * variations index. The list returned will begin at the offset provided. * + * Return value: Total number of lookups. + * **/ unsigned int hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, @@ -1443,12 +1464,17 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face, unsigned int lookup_index, hb_set_t *glyphs /* OUT */) { - hb_map_t done_lookups; - OT::hb_closure_context_t c (face, glyphs, &done_lookups); + hb_set_t cur_intersected_glyphs; + hb_map_t done_lookups_glyph_count; + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set; + OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index); l.closure (&c, lookup_index); + + for (auto _ : done_lookups_glyph_set.iter ()) + hb_set_destroy (_.second); } /** @@ -1467,8 +1493,10 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, const hb_set_t *lookups, hb_set_t *glyphs /* OUT */) { - hb_map_t done_lookups; - OT::hb_closure_context_t c (face, glyphs, &done_lookups); + hb_set_t cur_intersected_glyphs; + hb_map_t done_lookups_glyph_count; + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set; + OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); const OT::GSUB& gsub = *face->table.GSUB->table; unsigned int iteration_count = 0; @@ -1488,6 +1516,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, } } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES && glyphs_length != glyphs->get_population ()); + + for (auto _ : done_lookups_glyph_set.iter ()) + hb_set_destroy (_.second); } /* @@ -1925,7 +1956,7 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, * * Fetches a baseline value from the face. * - * Return value: if found baseline value in the font. + * Return value: %true if found baseline value in the font. * * Since: 2.6.0 **/ @@ -1984,7 +2015,7 @@ struct hb_get_glyph_alternates_dispatch_t : * * Fetches alternates of a glyph from a given GSUB lookup index. * - * Return value: total number of alternates found in the specific lookup index for the given glyph id. + * Return value: Total number of alternates found in the specific lookup index for the given glyph id. * * Since: 2.6.8 **/ 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 ac61bc70de1..bcc014ee981 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 @@ -314,7 +314,6 @@ _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info) hb_unicode_funcs_t::NOT_SPACE; } -static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info); static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info); static inline bool @@ -328,7 +327,7 @@ _hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info) { return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN)) == UPROPS_MASK_IGNORABLE) && - !_hb_glyph_info_ligated (info); + !_hb_glyph_info_substituted (info); } static inline void _hb_glyph_info_unhide (hb_glyph_info_t *info) 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 26aa0806031..5916ad29f2e 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 @@ -49,7 +49,7 @@ struct MathValueRecord protected: HBINT16 value; /* The X or Y value in design units */ - OffsetTo<Device> deviceTable; /* Offset to the device table - from the + Offset16To<Device> deviceTable; /* Offset to the device table - from the * beginning of parent table. May be NULL. * Suggested format for device table is 1. */ @@ -181,11 +181,11 @@ struct MathItalicsCorrectionInfo } protected: - OffsetTo<Coverage> coverage; /* Offset to Coverage table - + Offset16To<Coverage> coverage; /* Offset to Coverage table - * from the beginning of * MathItalicsCorrectionInfo * table. */ - ArrayOf<MathValueRecord> italicsCorrection; /* Array of MathValueRecords + Array16Of<MathValueRecord> italicsCorrection; /* Array of MathValueRecords * defining italics correction * values for each * covered glyph. */ @@ -214,11 +214,11 @@ struct MathTopAccentAttachment } protected: - OffsetTo<Coverage> topAccentCoverage; /* Offset to Coverage table - + Offset16To<Coverage> topAccentCoverage; /* Offset to Coverage table - * from the beginning of * MathTopAccentAttachment * table. */ - ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords + Array16Of<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords * defining top accent * attachment points for each * covered glyph. */ @@ -320,7 +320,7 @@ struct MathKernInfoRecord protected: /* Offset to MathKern table for each corner - * from the beginning of MathKernInfo table. May be NULL. */ - OffsetTo<MathKern> mathKern[4]; + Offset16To<MathKern> mathKern[4]; public: DEFINE_SIZE_STATIC (8); @@ -346,12 +346,12 @@ struct MathKernInfo } protected: - OffsetTo<Coverage> + Offset16To<Coverage> mathKernCoverage; /* Offset to Coverage table - * from the beginning of the * MathKernInfo table. */ - ArrayOf<MathKernInfoRecord> + Array16Of<MathKernInfoRecord> mathKernInfoRecords; /* Array of MathKernInfoRecords, * per-glyph information for @@ -395,22 +395,22 @@ struct MathGlyphInfo protected: /* Offset to MathItalicsCorrectionInfo table - * from the beginning of MathGlyphInfo table. */ - OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo; + Offset16To<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo; /* Offset to MathTopAccentAttachment table - * from the beginning of MathGlyphInfo table. */ - OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment; + Offset16To<MathTopAccentAttachment> mathTopAccentAttachment; /* Offset to coverage table for Extended Shape glyphs - * from the beginning of MathGlyphInfo table. When the left or right glyph of * a box is an extended shape variant, the (ink) box (and not the default * position defined by values in MathConstants table) should be used for * vertical positioning purposes. May be NULL.. */ - OffsetTo<Coverage> extendedShapeCoverage; + Offset16To<Coverage> extendedShapeCoverage; /* Offset to MathKernInfo table - * from the beginning of MathGlyphInfo table. */ - OffsetTo<MathKernInfo> mathKernInfo; + Offset16To<MathKernInfo> mathKernInfo; public: DEFINE_SIZE_STATIC (8); @@ -532,7 +532,7 @@ struct MathGlyphAssembly /* Italics correction of this * MathGlyphAssembly. Should not * depend on the assembly size. */ - ArrayOf<MathGlyphPartRecord> + Array16Of<MathGlyphPartRecord> partRecords; /* Array of part records, from * left to right and bottom to * top. */ @@ -572,10 +572,10 @@ struct MathGlyphConstruction protected: /* Offset to MathGlyphAssembly table for this shape - from the beginning of MathGlyphConstruction table. May be NULL. */ - OffsetTo<MathGlyphAssembly> glyphAssembly; + Offset16To<MathGlyphAssembly> glyphAssembly; /* MathGlyphVariantRecords for alternative variants of the glyphs. */ - ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord; + Array16Of<MathGlyphVariantRecord> mathGlyphVariantRecord; public: DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord); @@ -636,7 +636,7 @@ struct MathVariants { bool vertical = HB_DIRECTION_IS_VERTICAL (direction); unsigned int count = vertical ? vertGlyphCount : horizGlyphCount; - const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage + const Offset16To<Coverage> &coverage = vertical ? vertGlyphCoverage : horizGlyphCoverage; unsigned int index = (this+coverage).get_coverage (glyph); @@ -653,11 +653,11 @@ struct MathVariants /* Minimum overlap of connecting * glyphs during glyph construction, * in design units. */ - OffsetTo<Coverage> vertGlyphCoverage; + Offset16To<Coverage> vertGlyphCoverage; /* Offset to Coverage table - * from the beginning of MathVariants * table. */ - OffsetTo<Coverage> horizGlyphCoverage; + Offset16To<Coverage> horizGlyphCoverage; /* Offset to Coverage table - * from the beginning of MathVariants * table. */ @@ -671,7 +671,7 @@ struct MathVariants /* Array of offsets to MathGlyphConstruction tables - from the beginning of the MathVariants table, for shapes growing in vertical/horizontal direction. */ - UnsizedArrayOf<OffsetTo<MathGlyphConstruction>> + UnsizedArrayOf<Offset16To<MathGlyphConstruction>> glyphConstruction; public: @@ -711,11 +711,11 @@ struct MATH protected: FixedVersion<>version; /* Version of the MATH table * initially set to 0x00010000u */ - OffsetTo<MathConstants> + Offset16To<MathConstants> mathConstants; /* MathConstants table */ - OffsetTo<MathGlyphInfo> + Offset16To<MathGlyphInfo> mathGlyphInfo; /* MathGlyphInfo table */ - OffsetTo<MathVariants> + Offset16To<MathVariants> mathVariants; /* MathVariants table */ public: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh index 1225e26ce1e..e31447f8fcd 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh @@ -56,7 +56,7 @@ struct DataMap protected: Tag tag; /* A tag indicating the type of metadata. */ - LNNOffsetTo<UnsizedArrayOf<HBUINT8>> + NNOffset32To<UnsizedArrayOf<HBUINT8>> dataZ; /* Offset in bytes from the beginning of the * metadata table to the data for this tag. */ HBUINT32 dataLength; /* Length of the data. The data is not required to @@ -113,7 +113,7 @@ struct meta * Offset from the beginning of the table to the data. * Per OT specification: * Reserved. Not used; should be set to 0. */ - LArrayOf<DataMap> + Array32Of<DataMap> dataMaps;/* Array of data map records. */ public: DEFINE_SIZE_ARRAY (16, dataMaps); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh index ece3c28466b..5c5c58eac04 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh @@ -149,7 +149,7 @@ struct NameRecord HBUINT16 languageID; /* Language ID. */ HBUINT16 nameID; /* Name ID. */ HBUINT16 length; /* String length (in bytes). */ - NNOffsetTo<UnsizedArrayOf<HBUINT8>> + NNOffset16To<UnsizedArrayOf<HBUINT8>> offset; /* String offset from start of storage area (in bytes). */ public: DEFINE_SIZE_STATIC (12); @@ -230,7 +230,8 @@ struct name c->copy_all (records, src_string_pool); free (records.arrayZ); - if (unlikely (c->ran_out_of_room)) return_trace (false); + + if (unlikely (c->ran_out_of_room ())) return_trace (false); this->stringOffset = c->length (); @@ -357,7 +358,7 @@ struct name /* We only implement format 0 for now. */ HBUINT16 format; /* Format selector (=0/1). */ HBUINT16 count; /* Number of name records. */ - NNOffsetTo<UnsizedArrayOf<HBUINT8>> + NNOffset16To<UnsizedArrayOf<HBUINT8>> stringOffset; /* Offset to start of string storage (from start of table). */ UnsizedArrayOf<NameRecord> nameRecordZ; /* The name records where count is the number of records. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh index f22d6e244d5..d1462649414 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh @@ -56,7 +56,7 @@ struct postV2Tail } protected: - ArrayOf<HBUINT16> glyphNameIndex; /* This is not an offset, but is the + Array16Of<HBUINT16> glyphNameIndex; /* This is not an offset, but is the * ordinal number of the glyph in 'post' * string tables. */ /*UnsizedArrayOf<HBUINT8> @@ -236,7 +236,7 @@ struct post private: uint32_t version; - const ArrayOf<HBUINT16> *glyphNameIndex; + const Array16Of<HBUINT16> *glyphNameIndex; hb_vector_t<uint32_t> index_to_offset; const uint8_t *pool; hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh index 244e967b12d..a0401190202 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh @@ -208,11 +208,11 @@ struct ManifestLookup { public: OT::Tag tag; - OT::OffsetTo<OT::SubstLookup> lookupOffset; + OT::Offset16To<OT::SubstLookup> lookupOffset; public: DEFINE_SIZE_STATIC (6); }; -typedef OT::ArrayOf<ManifestLookup> Manifest; +typedef OT::Array16Of<ManifestLookup> Manifest; static bool arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc index 7d00a35ab97..eb1bc797680 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc @@ -92,7 +92,7 @@ recategorize_combining_class (hb_codepoint_t u, case HB_MODIFIED_COMBINING_CLASS_CCC15: /* tsere */ case HB_MODIFIED_COMBINING_CLASS_CCC16: /* segol */ case HB_MODIFIED_COMBINING_CLASS_CCC17: /* patah */ - case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats */ + case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats & qamats qatan */ case HB_MODIFIED_COMBINING_CLASS_CCC20: /* qubuts */ case HB_MODIFIED_COMBINING_CLASS_CCC22: /* meteg */ return HB_UNICODE_COMBINING_CLASS_BELOW; @@ -104,7 +104,7 @@ recategorize_combining_class (hb_codepoint_t u, return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT; case HB_MODIFIED_COMBINING_CLASS_CCC25: /* sin dot */ - case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam */ + case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam & holam haser for vav */ return HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT; case HB_MODIFIED_COMBINING_CLASS_CCC26: /* point varika */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh index 6aa4fa44928..41d1734b393 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh @@ -297,7 +297,7 @@ struct STAT unsigned int axis_index; if (!get_design_axes ().lfind (tag, &axis_index)) return false; - hb_array_t<const OffsetTo<AxisValue>> axis_values = get_axis_value_offsets (); + hb_array_t<const Offset16To<AxisValue>> axis_values = get_axis_value_offsets (); for (unsigned int i = 0; i < axis_values.length; i++) { const AxisValue& axis_value = this+axis_values[i]; @@ -359,7 +359,7 @@ struct STAT hb_array_t<const StatAxisRecord> const get_design_axes () const { return (this+designAxesOffset).as_array (designAxisCount); } - hb_array_t<const OffsetTo<AxisValue>> const get_axis_value_offsets () const + hb_array_t<const Offset16To<AxisValue>> const get_axis_value_offsets () const { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); } @@ -373,7 +373,7 @@ struct STAT * in the 'fvar' table. In all fonts, must * be greater than zero if axisValueCount * is greater than zero. */ - LNNOffsetTo<UnsizedArrayOf<StatAxisRecord>> + NNOffset32To<UnsizedArrayOf<StatAxisRecord>> designAxesOffset; /* Offset in bytes from the beginning of * the STAT table to the start of the design @@ -381,7 +381,7 @@ struct STAT * set to zero; if designAxisCount is greater * than zero, must be greater than zero. */ HBUINT16 axisValueCount; /* The number of axis value tables. */ - LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue>>> + NNOffset32To<UnsizedArrayOf<Offset16To<AxisValue>>> offsetToAxisValueOffsets; /* Offset in bytes from the beginning of * the STAT table to the start of the design diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh index 29219adb0a1..65f26c1d22d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh @@ -58,7 +58,7 @@ struct AxisValueMap DEFINE_SIZE_STATIC (4); }; -struct SegmentMaps : ArrayOf<AxisValueMap> +struct SegmentMaps : Array16Of<AxisValueMap> { int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh index f9e933fb2be..ceacb4f256e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh @@ -303,7 +303,7 @@ struct fvar protected: FixedVersion<>version; /* Version of the fvar table * initially set to 0x00010000u */ - OffsetTo<AxisRecord> + Offset16To<AxisRecord> firstAxis; /* Offset in bytes from the beginning of the table * to the start of the AxisRecord array. */ HBUINT16 reserved; /* This field is permanently reserved. Set to 2. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh index 7e4eaaad958..157dfd7a5da 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh @@ -374,7 +374,7 @@ struct GlyphVariationData * low 12 bits are the number of tuple variation tables * for this glyph. The number of tuple variation tables * can be any number between 1 and 4095. */ - OffsetTo<HBUINT8> + Offset16To<HBUINT8> data; /* Offset from the start of the GlyphVariationData table * to the serialized data. */ /* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */ @@ -676,7 +676,7 @@ no_more_gaps: * can be referenced within glyph variation data tables for * multiple glyphs, as opposed to other tuple records stored * directly within a glyph variation data table. */ - LNNOffsetTo<UnsizedArrayOf<F2DOT14>> + NNOffset32To<UnsizedArrayOf<F2DOT14>> sharedTuples; /* Offset from the start of this table to the shared tuple records. * Array of tuple records shared across all glyph variation data tables. */ HBUINT16 glyphCount; /* The number of glyphs in this font. This must match the number of @@ -684,7 +684,7 @@ no_more_gaps: HBUINT16 flags; /* Bit-field that gives the format of the offset array that follows. * If bit 0 is clear, the offsets are uint16; if bit 0 is set, the * offsets are uint32. */ - LOffsetTo<GlyphVariationData> + Offset32To<GlyphVariationData> dataZ; /* Offset from the start of this table to the array of * GlyphVariationData tables. */ UnsizedArrayOf<HBUINT8> diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh index fdcc88d6748..62bd1aa6868 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh @@ -49,7 +49,7 @@ struct DeltaSetIndexMap { unsigned int width = plan.get_width (); unsigned int inner_bit_count = plan.get_inner_bit_count (); - const hb_array_t<const unsigned int> output_map = plan.get_output_map (); + const hb_array_t<const uint32_t> output_map = plan.get_output_map (); TRACE_SERIALIZE (this); if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0)))) @@ -76,7 +76,7 @@ struct DeltaSetIndexMap return_trace (true); } - unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */ + uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */ { /* If count is zero, pass value unchanged. This takes * care of direct mapping for advance map. */ @@ -217,7 +217,7 @@ struct index_map_subset_plan_t hb_codepoint_t old_gid; if (plan->old_gid_for_new_gid (gid, &old_gid)) { - unsigned int v = input_map->map (old_gid); + uint32_t v = input_map->map (old_gid); unsigned int outer = v >> 16; output_map[gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]); } @@ -234,14 +234,14 @@ struct index_map_subset_plan_t { return (map_count? (DeltaSetIndexMap::min_size + get_width () * map_count): 0); } bool is_identity () const { return get_output_map ().length == 0; } - hb_array_t<const unsigned int> get_output_map () const { return output_map.as_array (); } + hb_array_t<const uint32_t> get_output_map () const { return output_map.as_array (); } protected: unsigned int map_count; hb_vector_t<unsigned int> max_inners; unsigned int outer_bit_count; unsigned int inner_bit_count; - hb_vector_t<unsigned int> output_map; + hb_vector_t<uint32_t> output_map; }; struct hvarvvar_subset_plan_t @@ -408,7 +408,7 @@ struct HVARVVAR float get_advance_var (hb_codepoint_t glyph, hb_font_t *font) const { - unsigned int varidx = (this+advMap).map (glyph); + uint32_t varidx = (this+advMap).map (glyph); return (this+varStore).get_delta (varidx, font->coords, font->num_coords); } @@ -416,7 +416,7 @@ struct HVARVVAR const int *coords, unsigned int coord_count) const { if (!has_side_bearing_deltas ()) return 0.f; - unsigned int varidx = (this+lsbMap).map (glyph); + uint32_t varidx = (this+lsbMap).map (glyph); return (this+varStore).get_delta (varidx, coords, coord_count); } @@ -425,13 +425,13 @@ struct HVARVVAR protected: FixedVersion<>version; /* Version of the metrics variation table * initially set to 0x00010000u */ - LOffsetTo<VariationStore> + Offset32To<VariationStore> varStore; /* Offset to item variation store table. */ - LOffsetTo<DeltaSetIndexMap> + Offset32To<DeltaSetIndexMap> advMap; /* Offset to advance var-idx mapping. */ - LOffsetTo<DeltaSetIndexMap> + Offset32To<DeltaSetIndexMap> lsbMap; /* Offset to lsb/tsb var-idx mapping. */ - LOffsetTo<DeltaSetIndexMap> + Offset32To<DeltaSetIndexMap> rsbMap; /* Offset to rsb/bsb var-idx mapping. */ public: @@ -475,7 +475,7 @@ struct VVAR : HVARVVAR { bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); } protected: - LOffsetTo<DeltaSetIndexMap> + Offset32To<DeltaSetIndexMap> vorgMap; /* Offset to vertical-origin var-idx mapping. */ public: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh index 1b7fad9cec4..208db467410 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh @@ -103,7 +103,7 @@ protected: HBUINT16 valueRecordSize;/* The size in bytes of each value record — * must be greater than zero. */ HBUINT16 valueRecordCount;/* The number of value records — may be zero. */ - OffsetTo<VariationStore> + Offset16To<VariationStore> varStore; /* Offset to item variation store table. */ UnsizedArrayOf<HBUINT8> valuesZ; /* Array of value records. The records must be diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh index c6803200f98..efa7737d6f7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh @@ -125,7 +125,7 @@ struct VORG FixedVersion<>version; /* Version of VORG table. Set to 0x00010000u. */ FWORD defaultVertOriginY; /* The default vertical origin. */ - SortedArrayOf<VertOriginMetric> + SortedArray16Of<VertOriginMetric> vertYOrigins; /* The array of vertical origins. */ public: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh new file mode 100644 index 00000000000..7d799ae9062 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh @@ -0,0 +1,151 @@ +/* + * Copyright © 2020 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#ifndef HB_PRIORITY_QUEUE_HH +#define HB_PRIORITY_QUEUE_HH + +#include "hb.hh" +#include "hb-vector.hh" + +/* + * hb_priority_queue_t + * + * Priority queue implemented as a binary heap. Supports extract minimum + * and insert operations. + */ +struct hb_priority_queue_t +{ + HB_DELETE_COPY_ASSIGN (hb_priority_queue_t); + hb_priority_queue_t () { init (); } + ~hb_priority_queue_t () { fini (); } + + private: + typedef hb_pair_t<int64_t, unsigned> item_t; + hb_vector_t<item_t> heap; + + public: + void init () { heap.init (); } + + void fini () { heap.fini (); } + + void reset () { heap.resize (0); } + + bool in_error () const { return heap.in_error (); } + + void insert (int64_t priority, unsigned value) + { + heap.push (item_t (priority, value)); + bubble_up (heap.length - 1); + } + + item_t pop_minimum () + { + item_t result = heap[0]; + + heap[0] = heap[heap.length - 1]; + heap.shrink (heap.length - 1); + bubble_down (0); + + return result; + } + + const item_t& minimum () + { + return heap[0]; + } + + bool is_empty () const { return heap.length == 0; } + explicit operator bool () const { return !is_empty (); } + unsigned int get_population () const { return heap.length; } + + /* Sink interface. */ + hb_priority_queue_t& operator << (item_t item) + { insert (item.first, item.second); return *this; } + + private: + + static constexpr unsigned parent (unsigned index) + { + return (index - 1) / 2; + } + + static constexpr unsigned left_child (unsigned index) + { + return 2 * index + 1; + } + + static constexpr unsigned right_child (unsigned index) + { + return 2 * index + 2; + } + + void bubble_down (unsigned index) + { + unsigned left = left_child (index); + unsigned right = right_child (index); + + bool has_left = left < heap.length; + if (!has_left) + // If there's no left, then there's also no right. + return; + + bool has_right = right < heap.length; + if (heap[index].first <= heap[left].first + && (!has_right || heap[index].first <= heap[right].first)) + return; + + if (!has_right || heap[left].first < heap[right].first) + { + swap (index, left); + bubble_down (left); + return; + } + + swap (index, right); + bubble_down (right); + } + + void bubble_up (unsigned index) + { + if (index == 0) return; + + unsigned parent_index = parent (index); + if (heap[parent_index].first <= heap[index].first) + return; + + swap (index, parent_index); + bubble_up (parent_index); + } + + void swap (unsigned a, unsigned b) + { + item_t temp = heap[a]; + heap[a] = heap[b]; + heap[b] = temp; + } +}; + +#endif /* HB_PRIORITY_QUEUE_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh new file mode 100644 index 00000000000..6211dedb9cc --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh @@ -0,0 +1,758 @@ +/* + * Copyright © 2020 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#ifndef HB_REPACKER_HH +#define HB_REPACKER_HH + +#include "hb-open-type.hh" +#include "hb-map.hh" +#include "hb-priority-queue.hh" +#include "hb-serialize.hh" +#include "hb-vector.hh" + + +struct graph_t +{ + struct vertex_t + { + vertex_t () : + distance (0), + incoming_edges (0), + start (0), + end (0), + priority(0) {} + + void fini () { obj.fini (); } + + hb_serialize_context_t::object_t obj; + int64_t distance; + unsigned incoming_edges; + unsigned start; + unsigned end; + unsigned priority; + + bool is_shared () const + { + return incoming_edges > 1; + } + + bool is_leaf () const + { + return !obj.links.length; + } + + void raise_priority () + { + priority++; + } + + int64_t modified_distance (unsigned order) const + { + // TODO(garretrieger): once priority is high enough, should try + // setting distance = 0 which will force to sort immediately after + // it's parent where possible. + + int64_t modified_distance = + hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFF); + return (modified_distance << 24) | (0x00FFFFFF & 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))); + } + }; + + struct overflow_record_t + { + unsigned parent; + const hb_serialize_context_t::object_t::link_t* link; + }; + + struct clone_buffer_t + { + clone_buffer_t () : head (nullptr), tail (nullptr) {} + + bool copy (const hb_serialize_context_t::object_t& object) + { + fini (); + unsigned size = object.tail - object.head; + head = (char*) malloc (size); + if (!head) return false; + + memcpy (head, object.head, size); + tail = head + size; + return true; + } + + char* head; + char* tail; + + void fini () + { + if (!head) return; + free (head); + head = nullptr; + } + }; + + /* + * A topological sorting of an object graph. Ordered + * in reverse serialization order (first object in the + * serialization is at the end of the list). This matches + * the 'packed' object stack used internally in the + * serializer + */ + graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects) + : edge_count_invalid (true), + distance_invalid (true), + positions_invalid (true), + successful (true) + { + bool removed_nil = false; + for (unsigned i = 0; i < objects.length; i++) + { + // TODO(grieger): check all links point to valid objects. + + // If this graph came from a serialization buffer object 0 is the + // nil object. We don't need it for our purposes here so drop it. + if (i == 0 && !objects[i]) + { + removed_nil = true; + continue; + } + + vertex_t* v = vertices_.push (); + 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--; + } + } + + ~graph_t () + { + vertices_.fini_deep (); + clone_buffers_.fini_deep (); + } + + bool in_error () const + { + return !successful || vertices_.in_error () || clone_buffers_.in_error (); + } + + const vertex_t& root () const + { + return vertices_[root_idx ()]; + } + + unsigned root_idx () const + { + // Object graphs are in reverse order, the first object is at the end + // of the vector. Since the graph is topologically sorted it's safe to + // assume the first object has no incoming edges. + return vertices_.length - 1; + } + + const hb_serialize_context_t::object_t& object(unsigned i) const + { + return vertices_[i].obj; + } + + /* + * serialize graph into the provided serialization buffer. + */ + void serialize (hb_serialize_context_t* c) const + { + c->start_serialize<void> (); + for (unsigned i = 0; i < vertices_.length; i++) { + c->push (); + + size_t size = vertices_[i].obj.tail - vertices_[i].obj.head; + char* start = c->allocate_size <char> (size); + if (!start) return; + + memcpy (start, vertices_[i].obj.head, size); + + for (const auto& link : vertices_[i].obj.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->end_serialize (); + } + + /* + * Generates a new topological sorting of graph using Kahn's + * algorithm: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms + */ + void sort_kahn () + { + positions_invalid = true; + + if (vertices_.length <= 1) { + // Graph of 1 or less doesn't need sorting. + return; + } + + hb_vector_t<unsigned> queue; + hb_vector_t<vertex_t> sorted_graph; + hb_vector_t<unsigned> id_map; + if (unlikely (!check_success (id_map.resize (vertices_.length)))) return; + + hb_vector_t<unsigned> removed_edges; + if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return; + update_incoming_edge_count (); + + queue.push (root_idx ()); + int new_id = vertices_.length - 1; + + while (!queue.in_error () && queue.length) + { + unsigned next_id = queue[0]; + queue.remove (0); + + vertex_t& next = vertices_[next_id]; + sorted_graph.push (next); + id_map[next_id] = new_id--; + + for (const auto& link : next.obj.links) { + removed_edges[link.objidx]++; + if (!(vertices_[link.objidx].incoming_edges - removed_edges[link.objidx])) + queue.push (link.objidx); + } + } + + check_success (!queue.in_error ()); + check_success (!sorted_graph.in_error ()); + if (!check_success (new_id == -1)) + DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected."); + + remap_obj_indices (id_map, &sorted_graph); + + sorted_graph.as_array ().reverse (); + + vertices_.fini_deep (); + vertices_ = sorted_graph; + sorted_graph.fini_deep (); + } + + /* + * Generates a new topological sorting of graph ordered by the shortest + * distance to each node. + */ + void sort_shortest_distance () + { + positions_invalid = true; + + if (vertices_.length <= 1) { + // Graph of 1 or less doesn't need sorting. + return; + } + + update_distances (); + + hb_priority_queue_t queue; + hb_vector_t<vertex_t> sorted_graph; + hb_vector_t<unsigned> id_map; + if (unlikely (!check_success (id_map.resize (vertices_.length)))) return; + + hb_vector_t<unsigned> removed_edges; + if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return; + update_incoming_edge_count (); + + queue.insert (root ().modified_distance (0), root_idx ()); + int new_id = root_idx (); + unsigned order = 1; + while (!queue.in_error () && !queue.is_empty ()) + { + unsigned next_id = queue.pop_minimum().second; + + vertex_t& next = vertices_[next_id]; + sorted_graph.push (next); + id_map[next_id] = new_id--; + + for (const auto& link : next.obj.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. + // This ensures that ties between priorities objects are broken in a consistent + // way. More specifically this is set up so that if a set of objects have the same + // distance they'll be added to the topological order in the order that they are + // referenced from the parent object. + queue.insert (vertices_[link.objidx].modified_distance (order++), + link.objidx); + } + } + + check_success (!queue.in_error ()); + check_success (!sorted_graph.in_error ()); + if (!check_success (new_id == -1)) + DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected."); + + remap_obj_indices (id_map, &sorted_graph); + + sorted_graph.as_array ().reverse (); + + vertices_.fini_deep (); + vertices_ = sorted_graph; + sorted_graph.fini_deep (); + } + + /* + * Creates a copy of child and re-assigns the link from + * parent to the clone. The copy is a shallow copy, objects + * linked from child are not duplicated. + */ + void duplicate (unsigned parent_idx, unsigned child_idx) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d", + parent_idx, child_idx); + + positions_invalid = true; + + auto* clone = vertices_.push (); + auto& child = vertices_[child_idx]; + clone_buffer_t* buffer = clone_buffers_.push (); + if (vertices_.in_error () + || clone_buffers_.in_error () + || !check_success (buffer->copy (child.obj))) { + return; + } + + clone->obj.head = buffer->head; + clone->obj.tail = buffer->tail; + clone->distance = child.distance; + + for (const auto& l : child.obj.links) + clone->obj.links.push (l); + + check_success (!clone->obj.links.in_error ()); + + auto& parent = vertices_[parent_idx]; + unsigned clone_idx = vertices_.length - 2; + for (unsigned i = 0; i < parent.obj.links.length; i++) + { + auto& l = parent.obj.links[i]; + if (l.objidx == child_idx) + { + l.objidx = clone_idx; + clone->incoming_edges++; + child.incoming_edges--; + } + } + + // 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. + // all other obj idx's will be unaffected. + vertex_t root = vertices_[vertices_.length - 2]; + vertices_[vertices_.length - 2] = *clone; + vertices_[vertices_.length - 1] = root; + } + + /* + * Raises the sorting priority of all children. + */ + void raise_childrens_priority (unsigned parent_idx) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d", + parent_idx); + // This operation doesn't change ordering until a sort is run, so no need + // 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 (); + } + + /* + * Will any offsets overflow on graph when it's serialized? + */ + bool will_overflow (hb_vector_t<overflow_record_t>* overflows = nullptr) + { + if (overflows) overflows->resize (0); + update_positions (); + + for (int parent_idx = vertices_.length - 1; parent_idx >= 0; parent_idx--) + { + for (const auto& link : vertices_[parent_idx].obj.links) + { + int64_t offset = compute_offset (parent_idx, link); + if (is_valid_offset (offset, link)) + continue; + + if (!overflows) return true; + + overflow_record_t r; + r.parent = parent_idx; + r.link = &link; + overflows->push (r); + } + } + + if (!overflows) return false; + return overflows->length; + } + + void print_overflows (const hb_vector_t<overflow_record_t>& overflows) + { + if (!DEBUG_ENABLED(SUBSET_REPACK)) return; + + update_incoming_edge_count (); + for (const auto& o : overflows) + { + const auto& child = vertices_[o.link->objidx]; + DEBUG_MSG (SUBSET_REPACK, nullptr, " overflow from %d => %d (%d incoming , %d outgoing)", + o.parent, + o.link->objidx, + child.incoming_edges, + child.obj.links.length); + } + } + + void err_other_error () { this->successful = false; } + + private: + + bool check_success (bool success) + { return this->successful && (success || (err_other_error (), false)); } + + /* + * Creates a map from objid to # of incoming edges. + */ + void update_incoming_edge_count () + { + if (!edge_count_invalid) return; + + for (unsigned i = 0; i < vertices_.length; i++) + vertices_[i].incoming_edges = 0; + + for (const vertex_t& v : vertices_) + { + for (auto& l : v.obj.links) + { + vertices_[l.objidx].incoming_edges++; + } + } + + edge_count_invalid = false; + } + + /* + * compute the serialized start and end positions for each vertex. + */ + void update_positions () + { + if (!positions_invalid) return; + + unsigned current_pos = 0; + for (int i = root_idx (); i >= 0; i--) + { + auto& v = vertices_[i]; + v.start = current_pos; + current_pos += v.obj.tail - v.obj.head; + v.end = current_pos; + } + + positions_invalid = false; + } + + /* + * Finds the distance to each object in the graph + * from the initial node. + */ + void update_distances () + { + if (!distance_invalid) return; + + // Uses Dijkstra's algorithm to find all of the shortest distances. + // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm + // + // Implementation Note: + // Since our priority queue doesn't support fast priority decreases + // we instead just add new entries into the queue when a priority changes. + // Redundant ones are filtered out later on by the visited set. + // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf + // for practical performance this is faster then using a more advanced queue + // (such as a fibonaacci queue) with a fast decrease priority. + for (unsigned i = 0; i < vertices_.length; i++) + { + if (i == vertices_.length - 1) + vertices_[i].distance = 0; + else + vertices_[i].distance = hb_int_max (int64_t); + } + + hb_priority_queue_t queue; + queue.insert (0, vertices_.length - 1); + + hb_set_t visited; + + while (!queue.in_error () && !queue.is_empty ()) + { + unsigned next_idx = queue.pop_minimum ().second; + if (visited.has (next_idx)) continue; + const auto& next = vertices_[next_idx]; + int64_t next_distance = vertices_[next_idx].distance; + visited.add (next_idx); + + for (const auto& link : next.obj.links) + { + if (visited.has (link.objidx)) continue; + + const auto& child = vertices_[link.objidx].obj; + int64_t child_weight = child.tail - child.head + + (!link.is_wide ? (1 << 16) : ((int64_t) 1 << 32)); + int64_t child_distance = next_distance + child_weight; + + if (child_distance < vertices_[link.objidx].distance) + { + vertices_[link.objidx].distance = child_distance; + queue.insert (child_distance, link.objidx); + } + } + } + + check_success (!queue.in_error ()); + if (!check_success (queue.is_empty ())) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected."); + return; + } + + distance_invalid = false; + } + + int64_t compute_offset ( + unsigned parent_idx, + const hb_serialize_context_t::object_t::link_t& link) const + { + const auto& parent = vertices_[parent_idx]; + const auto& child = vertices_[link.objidx]; + int64_t offset = 0; + switch ((hb_serialize_context_t::whence_t) link.whence) { + case hb_serialize_context_t::whence_t::Head: + offset = child.start - parent.start; break; + case hb_serialize_context_t::whence_t::Tail: + offset = child.start - parent.end; break; + case hb_serialize_context_t::whence_t::Absolute: + offset = child.start; break; + } + + assert (offset >= link.bias); + offset -= link.bias; + return offset; + } + + bool is_valid_offset (int64_t offset, + const hb_serialize_context_t::object_t::link_t& link) const + { + if (link.is_signed) + { + if (link.is_wide) + return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31); + else + return offset >= -(1 << 15) && offset < (1 << 15); + } + else + { + if (link.is_wide) + return offset >= 0 && offset < ((int64_t) 1 << 32); + else + return offset >= 0 && offset < (1 << 16); + } + } + + /* + * Updates all objidx's in all links using the provided mapping. + */ + void remap_obj_indices (const hb_vector_t<unsigned>& id_map, + hb_vector_t<vertex_t>* sorted_graph) const + { + for (unsigned i = 0; i < sorted_graph->length; i++) + { + for (unsigned j = 0; j < (*sorted_graph)[i].obj.links.length; j++) + { + auto& link = (*sorted_graph)[i].obj.links[j]; + link.objidx = id_map[link.objidx]; + } + } + } + + template <typename O> void + serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link, + char* head, + hb_serialize_context_t* c) const + { + OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position); + *offset = 0; + c->add_link (*offset, + // serializer has an extra nil object at the start of the + // object array. So all id's are +1 of what our id's are. + link.objidx + 1, + (hb_serialize_context_t::whence_t) link.whence, + link.bias); + } + + void serialize_link (const hb_serialize_context_t::object_t::link_t& link, + char* head, + hb_serialize_context_t* c) const + { + if (link.is_wide) + { + if (link.is_signed) + { + serialize_link_of_type<OT::HBINT32> (link, head, c); + } else { + serialize_link_of_type<OT::HBUINT32> (link, head, c); + } + } else { + if (link.is_signed) + { + serialize_link_of_type<OT::HBINT16> (link, head, c); + } else { + serialize_link_of_type<OT::HBUINT16> (link, head, c); + } + } + } + + public: + // TODO(garretrieger): make private, will need to move most of offset overflow code into graph. + hb_vector_t<vertex_t> vertices_; + private: + hb_vector_t<clone_buffer_t> clone_buffers_; + bool edge_count_invalid; + bool distance_invalid; + bool positions_invalid; + bool successful; +}; + + +/* + * Attempts to modify the topological sorting of the provided object graph to + * eliminate offset overflows in the links between objects of the graph. If a + * non-overflowing ordering is found the updated graph is serialized it into the + * provided serialization context. + * + * If necessary the structure of the graph may be modified in ways that do not + * affect the functionality of the graph. For example shared objects may be + * duplicated. + */ +inline void +hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed, + hb_serialize_context_t* c) { + // 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; + } + + sorted_graph.sort_shortest_distance (); + + unsigned round = 0; + hb_vector_t<graph_t::overflow_record_t> overflows; + // TODO(garretrieger): select a good limit for max rounds. + while (!sorted_graph.in_error () + && sorted_graph.will_overflow (&overflows) + && round++ < 10) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Over flow resolution round %d ===", round); + sorted_graph.print_overflows (overflows); + + bool resolution_attempted = false; + hb_set_t priority_bumped_parents; + // Try resolving the furthest overflows first. + for (int i = overflows.length - 1; i >= 0; i--) + { + const graph_t::overflow_record_t& r = overflows[i]; + const auto& child = sorted_graph.vertices_[r.link->objidx]; + if (child.is_shared ()) + { + // The child object is shared, we may be able to eliminate the overflow + // by duplicating it. + sorted_graph.duplicate (r.parent, r.link->objidx); + resolution_attempted = true; + + // Stop processing overflows for this round so that object order can be + // updated to account for the newly added object. + break; + } + + if (child.is_leaf () && !priority_bumped_parents.has (r.parent)) + { + // This object is too far from it's parent, attempt to move it closer. + // + // 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; + continue; + } + + // TODO(garretrieger): add additional offset resolution strategies + // - Promotion to extension lookups. + // - Table splitting. + } + + if (resolution_attempted) + { + sorted_graph.sort_shortest_distance (); + continue; + } + + DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :("); + c->err (HB_SERIALIZE_ERROR_OFFSET_OVERFLOW); + return; + } + + if (sorted_graph.in_error ()) + { + c->err (HB_SERIALIZE_ERROR_OTHER); + return; + } + sorted_graph.serialize (c); +} + + +#endif /* HB_REPACKER_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh index 1675e8448ac..56c46015a67 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh @@ -105,7 +105,7 @@ #define HB_SANITIZE_MAX_EDITS 32 #endif #ifndef HB_SANITIZE_MAX_OPS_FACTOR -#define HB_SANITIZE_MAX_OPS_FACTOR 8 +#define HB_SANITIZE_MAX_OPS_FACTOR 64 #endif #ifndef HB_SANITIZE_MAX_OPS_MIN #define HB_SANITIZE_MAX_OPS_MIN 16384 @@ -233,7 +233,7 @@ struct hb_sanitize_context_t : (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len && - this->max_ops-- > 0); + (this->max_ops -= len) > 0); DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, "check_range [%p..%p]" 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 fe29bdf96ee..3ec055b7b0b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh @@ -41,6 +41,16 @@ * Serialize */ +enum hb_serialize_error_t { + HB_SERIALIZE_ERROR_NONE = 0x00000000u, + HB_SERIALIZE_ERROR_OTHER = 0x00000001u, + HB_SERIALIZE_ERROR_OFFSET_OVERFLOW = 0x00000002u, + HB_SERIALIZE_ERROR_OUT_OF_ROOM = 0x00000004u, + HB_SERIALIZE_ERROR_INT_OVERFLOW = 0x00000008u, + HB_SERIALIZE_ERROR_ARRAY_OVERFLOW = 0x00000010u +}; +HB_MARK_AS_FLAG_T (hb_serialize_error_t); + struct hb_serialize_context_t { typedef unsigned objidx_t; @@ -51,6 +61,8 @@ struct hb_serialize_context_t Absolute /* Absolute: from the start of the serialize buffer. */ }; + + struct object_t { void fini () { links.fini (); } @@ -117,30 +129,54 @@ struct hb_serialize_context_t object_pool.fini (); } - bool in_error () const { return !this->successful; } + bool in_error () const { return bool (errors); } + + bool successful () const { return !bool (errors); } + + HB_NODISCARD bool ran_out_of_room () const { return errors & HB_SERIALIZE_ERROR_OUT_OF_ROOM; } + HB_NODISCARD bool offset_overflow () const { return errors & HB_SERIALIZE_ERROR_OFFSET_OVERFLOW; } + HB_NODISCARD bool only_offset_overflow () const { return errors == HB_SERIALIZE_ERROR_OFFSET_OVERFLOW; } + + void reset (void *start_, unsigned int size) + { + start = (char*) start_; + end = start + size; + reset (); + current = nullptr; + } void reset () { - this->successful = true; - this->ran_out_of_room = false; + this->errors = HB_SERIALIZE_ERROR_NONE; this->head = this->start; this->tail = this->end; this->debug_depth = 0; fini (); this->packed.push (nullptr); + this->packed_map.init (); } - bool check_success (bool success) - { return this->successful && (success || (err_other_error (), false)); } + bool check_success (bool success, + hb_serialize_error_t err_type = HB_SERIALIZE_ERROR_OTHER) + { + return successful () + && (success || err (err_type)); + } template <typename T1, typename T2> - bool check_equal (T1 &&v1, T2 &&v2) - { return check_success ((long long) v1 == (long long) v2); } + bool check_equal (T1 &&v1, T2 &&v2, hb_serialize_error_t err_type) + { + if ((long long) v1 != (long long) v2) + { + return err (err_type); + } + return true; + } template <typename T1, typename T2> - bool check_assign (T1 &v1, T2 &&v2) - { return check_equal (v1 = v2, v2); } + bool check_assign (T1 &v1, T2 &&v2, hb_serialize_error_t err_type) + { return check_equal (v1 = v2, v2, err_type); } template <typename T> bool propagate_error (T &&obj) { return check_success (!hb_deref (obj).in_error ()); } @@ -167,12 +203,18 @@ struct hb_serialize_context_t "end [%p..%p] serialized %u bytes; %s", this->start, this->end, (unsigned) (this->head - this->start), - this->successful ? "successful" : "UNSUCCESSFUL"); + successful () ? "successful" : "UNSUCCESSFUL"); propagate_error (packed, packed_map); if (unlikely (!current)) return; - if (unlikely (in_error())) return; + if (unlikely (in_error())) + { + // Offset overflows that occur before link resolution cannot be handled + // by repacking, so set a more general error. + if (offset_overflow ()) err (HB_SERIALIZE_ERROR_OTHER); + return; + } assert (!current->next); @@ -351,7 +393,7 @@ struct hb_serialize_context_t for (const object_t::link_t &link : parent->links) { const object_t* child = packed[link.objidx]; - if (unlikely (!child)) { err_other_error(); return; } + if (unlikely (!child)) { err (HB_SERIALIZE_ERROR_OTHER); return; } unsigned offset = 0; switch ((whence_t) link.whence) { case Head: offset = child->head - parent->head; break; @@ -398,19 +440,19 @@ struct hb_serialize_context_t Type *start_embed (const Type &obj) const { return start_embed (hb_addressof (obj)); } - /* Following two functions exist to allow setting breakpoint on. */ - void err_ran_out_of_room () { this->ran_out_of_room = true; } - void err_other_error () { this->successful = false; } + bool err (hb_serialize_error_t err_type) + { + return !bool ((errors = (errors | err_type))); + } template <typename Type> Type *allocate_size (unsigned int size) { - if (unlikely (!this->successful)) return nullptr; + if (unlikely (in_error ())) return nullptr; if (this->tail - this->head < ptrdiff_t (size)) { - err_ran_out_of_room (); - this->successful = false; + err (HB_SERIALIZE_ERROR_OUT_OF_ROOM); return nullptr; } memset (this->head, 0, size); @@ -497,7 +539,7 @@ struct hb_serialize_context_t /* Output routines. */ hb_bytes_t copy_bytes () const { - assert (this->successful); + assert (successful ()); /* Copy both items from head side and tail side... */ unsigned int len = (this->head - this->start) + (this->end - this->tail); @@ -520,20 +562,22 @@ struct hb_serialize_context_t (char *) b.arrayZ, free); } + const hb_vector_t<object_t *>& object_graph() const + { return packed; } + private: template <typename T> void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset) { auto &off = * ((BEInt<T> *) (parent->head + link.position)); assert (0 == off); - check_assign (off, offset); + check_assign (off, offset, HB_SERIALIZE_ERROR_OFFSET_OVERFLOW); } public: /* TODO Make private. */ char *start, *head, *tail, *end; unsigned int debug_depth; - bool successful; - bool ran_out_of_room; + hb_serialize_error_t errors; private: @@ -550,5 +594,4 @@ struct hb_serialize_context_t hb_hashmap_t<const object_t *, objidx_t, nullptr, 0> packed_map; }; - #endif /* HB_SERIALIZE_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh index b97526f7750..1ef1ba5fb28 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh @@ -87,6 +87,8 @@ struct hb_set_digest_lowest_bits_t } } template <typename T> + void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); } + template <typename T> bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) { for (unsigned int i = 0; i < count; i++) @@ -96,6 +98,8 @@ struct hb_set_digest_lowest_bits_t } return true; } + template <typename T> + bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } bool may_have (hb_codepoint_t g) const { return !!(mask & mask_for (g)); } @@ -135,12 +139,16 @@ struct hb_set_digest_combiner_t tail.add_array (array, count, stride); } template <typename T> + void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); } + template <typename T> bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) { head.add_sorted_array (array, count, stride); tail.add_sorted_array (array, count, stride); return true; } + template <typename T> + bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } bool may_have (hb_codepoint_t g) const { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh index ae8b5eb10f6..9404ba2615b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh @@ -337,6 +337,8 @@ struct hb_set_t while (count && (g = *array, start <= g && g < end)); } } + template <typename T> + void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); } /* Might return false if array looks unsorted. * Used for faster rejection of corrupt data. */ @@ -368,6 +370,8 @@ struct hb_set_t } return true; } + template <typename T> + bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } void del (hb_codepoint_t g) { @@ -828,7 +832,7 @@ struct hb_set_t hb_codepoint_t get_max () const { unsigned int count = pages.length; - for (int i = count - 1; i >= 0; i++) + for (int i = count - 1; i >= 0; i--) if (!page_at (i).is_empty ()) return page_map[(unsigned) i].major * page_t::PAGE_BITS + page_at (i).get_max (); return INVALID; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc index f5b7fa50a04..ec4b2414709 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc @@ -43,6 +43,7 @@ uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof /*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {}; DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF}; +DEFINE_NULL_NAMESPACE_BYTES (OT, VarIdx) = {0xFF,0xFF,0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00}; DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00}; DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc index fe9be3ce020..1f64bc99a0c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc @@ -56,9 +56,6 @@ hb_subset_input_create_or_fail () hb_tag_t default_drop_tables[] = { // Layout disabled by default - HB_TAG ('G', 'S', 'U', 'B'), - HB_TAG ('G', 'P', 'O', 'S'), - HB_TAG ('G', 'D', 'E', 'F'), HB_TAG ('m', 'o', 'r', 'x'), HB_TAG ('m', 'o', 'r', 't'), HB_TAG ('k', 'e', 'r', 'x'), 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 d055783a4d2..dfb0d42f38d 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 @@ -39,6 +39,7 @@ #include "hb-ot-stat-table.hh" +typedef hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> script_langsys_map; #ifndef HB_NO_SUBSET_CFF static inline void _add_cff_seac_components (const OT::cff1::accelerator_t &cff, @@ -70,7 +71,8 @@ static inline void _gsub_closure_glyphs_lookups_features (hb_face_t *face, hb_set_t *gids_to_retain, hb_map_t *gsub_lookups, - hb_map_t *gsub_features) + hb_map_t *gsub_features, + script_langsys_map *gsub_langsys) { hb_set_t lookup_indices; hb_ot_layout_collect_lookups (face, @@ -96,7 +98,13 @@ _gsub_closure_glyphs_lookups_features (hb_face_t *face, nullptr, nullptr, &feature_indices); + gsub->prune_features (gsub_lookups, &feature_indices); + hb_map_t duplicate_feature_map; + gsub->find_duplicate_features (gsub_lookups, &feature_indices, &duplicate_feature_map); + + feature_indices.clear (); + gsub->prune_langsys (&duplicate_feature_map, gsub_langsys, &feature_indices); _remap_indexes (&feature_indices, gsub_features); gsub.destroy (); @@ -106,7 +114,8 @@ static inline void _gpos_closure_lookups_features (hb_face_t *face, const hb_set_t *gids_to_retain, hb_map_t *gpos_lookups, - hb_map_t *gpos_features) + hb_map_t *gpos_features, + script_langsys_map *gpos_langsys) { hb_set_t lookup_indices; hb_ot_layout_collect_lookups (face, @@ -129,8 +138,15 @@ _gpos_closure_lookups_features (hb_face_t *face, nullptr, nullptr, &feature_indices); + gpos->prune_features (gpos_lookups, &feature_indices); + hb_map_t duplicate_feature_map; + gpos->find_duplicate_features (gpos_lookups, &feature_indices, &duplicate_feature_map); + + feature_indices.clear (); + gpos->prune_langsys (&duplicate_feature_map, gpos_langsys, &feature_indices); _remap_indexes (&feature_indices, gpos_features); + gpos.destroy (); } #endif @@ -231,10 +247,10 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, #ifndef HB_NO_SUBSET_LAYOUT if (close_over_gsub) // closure all glyphs/lookups/features needed for GSUB substitutions. - _gsub_closure_glyphs_lookups_features (plan->source, plan->_glyphset_gsub, plan->gsub_lookups, plan->gsub_features); + _gsub_closure_glyphs_lookups_features (plan->source, plan->_glyphset_gsub, plan->gsub_lookups, plan->gsub_features, plan->gsub_langsys); if (close_over_gpos) - _gpos_closure_lookups_features (plan->source, plan->_glyphset_gsub, plan->gpos_lookups, plan->gpos_features); + _gpos_closure_lookups_features (plan->source, plan->_glyphset_gsub, plan->gpos_lookups, plan->gpos_features, plan->gpos_langsys); #endif _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ()); @@ -356,11 +372,21 @@ hb_subset_plan_create (hb_face_t *face, plan->reverse_glyph_map = hb_map_create (); plan->gsub_lookups = hb_map_create (); plan->gpos_lookups = hb_map_create (); + + if (plan->check_success (plan->gsub_langsys = hb_object_create<script_langsys_map> ())) + plan->gsub_langsys->init_shallow (); + if (plan->check_success (plan->gpos_langsys = hb_object_create<script_langsys_map> ())) + plan->gpos_langsys->init_shallow (); + plan->gsub_features = hb_map_create (); plan->gpos_features = hb_map_create (); plan->layout_variation_indices = hb_set_create (); plan->layout_variation_idx_map = hb_map_create (); + if (plan->in_error ()) { + return plan; + } + _populate_gids_to_retain (plan, input->unicodes, input->glyphs, @@ -407,6 +433,25 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan) hb_set_destroy (plan->layout_variation_indices); hb_map_destroy (plan->layout_variation_idx_map); + if (plan->gsub_langsys) + { + for (auto _ : plan->gsub_langsys->iter ()) + hb_set_destroy (_.second); + + hb_object_destroy (plan->gsub_langsys); + plan->gsub_langsys->fini_shallow (); + free (plan->gsub_langsys); + } + + if (plan->gpos_langsys) + { + for (auto _ : plan->gpos_langsys->iter ()) + hb_set_destroy (_.second); + + hb_object_destroy (plan->gpos_langsys); + plan->gpos_langsys->fini_shallow (); + free (plan->gpos_langsys); + } free (plan); } 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 cc9cb7a1a2e..1c070f91388 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 @@ -79,7 +79,11 @@ struct hb_subset_plan_t hb_map_t *gsub_lookups; hb_map_t *gpos_lookups; - //active features we'd like to retain + //active langsys we'd like to retain + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *gsub_langsys; + hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *gpos_langsys; + + //active features after removing redundant langsys and prune_features hb_map_t *gsub_features; hb_map_t *gpos_features; 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 8b77ecd45aa..d443d248be5 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc @@ -50,6 +50,7 @@ #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-var-gvar-table.hh" #include "hb-ot-var-hvar-table.hh" +#include "hb-repacker.hh" static unsigned @@ -64,69 +65,132 @@ _plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len) return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs)); } +/* + * Repack the serialization buffer if any offset overflows exist. + */ +static hb_blob_t* +_repack (hb_tag_t tag, const hb_serialize_context_t& c) +{ + if (tag != HB_OT_TAG_GPOS + && tag != HB_OT_TAG_GSUB) + { + // Check for overflow in a non-handled table. + return c.successful () ? c.copy_blob () : nullptr; + } + + 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 (), &repacked); + + if (unlikely (repacked.in_error ())) + // TODO(garretrieger): refactor so we can share the resize/retry logic with the subset + // portion. + return nullptr; + + return repacked.copy_blob (); +} + +template<typename TableType> +static +bool +_try_subset (const TableType *table, + hb_vector_t<char>* buf, + unsigned buf_size, + hb_subset_context_t* c /* OUT */) +{ + c->serializer->start_serialize<TableType> (); + + bool needed = table->subset (c); + if (!c->serializer->ran_out_of_room ()) + { + c->serializer->end_serialize (); + return needed; + } + + buf_size += (buf_size >> 1) + 32; + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", + HB_UNTAG (c->table_tag), buf_size); + + if (unlikely (!buf->alloc (buf_size))) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", + HB_UNTAG (c->table_tag), buf_size); + return needed; + } + + c->serializer->reset (buf->arrayZ, buf_size); + return _try_subset (table, buf, buf_size, c); +} + template<typename TableType> static bool _subset (hb_subset_plan_t *plan) { - bool result = false; hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source); const TableType *table = source_blob->as<TableType> (); hb_tag_t tag = TableType::tableTag; - if (source_blob->data) + if (!source_blob->data) + { + DEBUG_MSG (SUBSET, nullptr, + "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag)); + hb_blob_destroy (source_blob); + return false; + } + + hb_vector_t<char> buf; + /* TODO Not all tables are glyph-related. 'name' table size for example should not be + * affected by number of glyphs. Accommodate that. */ + unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length); + DEBUG_MSG (SUBSET, nullptr, + "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size); + if (unlikely (!buf.alloc (buf_size))) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size); + hb_blob_destroy (source_blob); + return false; + } + + bool needed = false; + hb_serialize_context_t serializer (buf.arrayZ, buf_size); { - hb_vector_t<char> buf; - /* TODO Not all tables are glyph-related. 'name' table size for example should not be - * affected by number of glyphs. Accommodate that. */ - unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length); - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size); - if (unlikely (!buf.alloc (buf_size))) - { - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size); - hb_blob_destroy (source_blob); - return false; - } - retry: - hb_serialize_context_t serializer ((void *) buf, buf_size); - serializer.start_serialize<TableType> (); hb_subset_context_t c (source_blob, plan, &serializer, tag); - bool needed = table->subset (&c); - if (serializer.ran_out_of_room) - { - buf_size += (buf_size >> 1) + 32; - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size); - if (unlikely (!buf.alloc (buf_size))) - { - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size); - hb_blob_destroy (source_blob); - return false; - } - goto retry; - } - serializer.end_serialize (); + needed = _try_subset (table, &buf, buf_size, &c); + } + hb_blob_destroy (source_blob); - result = !serializer.in_error (); + if (serializer.in_error () && !serializer.only_offset_overflow ()) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset FAILED!", HB_UNTAG (tag)); + return false; + } - if (result) - { - if (needed) - { - hb_blob_t *dest_blob = serializer.copy_blob (); - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length); - result = c.plan->add_table (tag, dest_blob); - hb_blob_destroy (dest_blob); - } - else - { - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag)); - } - } + if (!needed) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag)); + return true; } - else - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag)); - hb_blob_destroy (source_blob); - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!"); + bool result = false; + hb_blob_t *dest_blob = _repack (tag, serializer); + if (dest_blob) + { + DEBUG_MSG (SUBSET, nullptr, + "OT::%c%c%c%c final subset table size: %u bytes.", + HB_UNTAG (tag), dest_blob->length); + result = plan->add_table (tag, dest_blob); + hb_blob_destroy (dest_blob); + } + + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", + HB_UNTAG (tag), result ? "success" : "FAILED!"); return result; } @@ -241,8 +305,10 @@ hb_subset (hb_face_t *source, hb_subset_input_t *input) if (unlikely (!input || !source)) return hb_face_get_empty (); hb_subset_plan_t *plan = hb_subset_plan_create (source, input); - if (unlikely (plan->in_error ())) + if (unlikely (plan->in_error ())) { + hb_subset_plan_destroy (plan); return hb_face_get_empty (); + } hb_set_t tags_set; bool success = true; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh index 34d66d7aa3c..5c0cb859def 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh @@ -289,8 +289,8 @@ DECLARE_NULL_INSTANCE (hb_unicode_funcs_t); #define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */ #define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */ #define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */ -#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */ -#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */ +#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats & qamats qatan */ +#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam & holam haser for vav*/ #define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */ #define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */ #define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh index 13517a9c29e..17f7d486fa9 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh @@ -177,6 +177,11 @@ struct hb_vector_t Type *push (T&& v) { Type *p = push (); + if (p == &Crap (Type)) + // If push failed to allocate then don't copy v, since this may cause + // the created copy to leak memory since we won't have stored a + // reference to it. + return p; *p = hb_forward<T> (v); return p; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh index 18516581c7c..4d90e4d576d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh @@ -117,6 +117,9 @@ #pragma GCC diagnostic ignored "-Wshadow" // TODO fix #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" // TODO fix #pragma GCC diagnostic ignored "-Wunused-parameter" // TODO fix +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-result" // TODO fix +#endif #endif /* Ignored intentionally. */ @@ -335,7 +338,6 @@ extern "C" void hb_free_impl(void *ptr); #else # define HB_NODISCARD #endif -#define hb_success_t HB_NODISCARD bool /* https://github.com/harfbuzz/harfbuzz/issues/1852 */ #if defined(__clang__) && !(defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build b/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build index ec3b7c718c3..dddafe9c21c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build @@ -477,6 +477,8 @@ if get_option('tests').enabled() compiled_tests = { 'test-algs': ['test-algs.cc', 'hb-static.cc'], 'test-array': ['test-array.cc'], + 'test-repacker': ['test-repacker.cc', 'hb-static.cc'], + 'test-priority-queue': ['test-priority-queue.cc', 'hb-static.cc'], 'test-iter': ['test-iter.cc', 'hb-static.cc'], 'test-meta': ['test-meta.cc', 'hb-static.cc'], 'test-number': ['test-number.cc', 'hb-number.cc'], diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc new file mode 100644 index 00000000000..fab63acb63b --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc @@ -0,0 +1,89 @@ +/* + * Copyright © 2020 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include "hb.hh" +#include "hb-priority-queue.hh" + +static void +test_insert () +{ + hb_priority_queue_t queue; + assert (queue.is_empty ()); + + queue.insert (10, 0); + assert (!queue.is_empty ()); + assert (queue.minimum () == hb_pair (10, 0)); + + queue.insert (20, 1); + assert (queue.minimum () == hb_pair (10, 0)); + + queue.insert (5, 2); + assert (queue.minimum () == hb_pair (5, 2)); + + queue.insert (15, 3); + assert (queue.minimum () == hb_pair (5, 2)); + + queue.insert (1, 4); + assert (queue.minimum () == hb_pair (1, 4)); +} + +static void +test_extract () +{ + hb_priority_queue_t queue; + queue.insert (0, 0); + queue.insert (60, 6); + queue.insert (30, 3); + queue.insert (40 ,4); + queue.insert (20, 2); + queue.insert (50, 5); + queue.insert (70, 7); + queue.insert (10, 1); + + for (int i = 0; i < 8; i++) + { + assert (!queue.is_empty ()); + assert (queue.minimum () == hb_pair (i * 10, i)); + assert (queue.pop_minimum () == hb_pair (i * 10, i)); + } + + assert (queue.is_empty ()); +} + +static void +test_extract_empty () +{ + hb_priority_queue_t queue; + assert (queue.pop_minimum () == hb_pair (0, 0)); +} + +int +main (int argc, char **argv) +{ + test_insert (); + test_extract (); + test_extract_empty (); +} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc new file mode 100644 index 00000000000..a8cc6395f9e --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc @@ -0,0 +1,485 @@ +/* + * Copyright © 2020 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include <string> + +#include "hb-repacker.hh" +#include "hb-open-type.hh" + +static void start_object(const char* tag, + unsigned len, + hb_serialize_context_t* c) +{ + c->push (); + char* obj = c->allocate_size<char> (len); + strncpy (obj, tag, len); +} + + +static unsigned add_object(const char* tag, + unsigned len, + hb_serialize_context_t* c) +{ + start_object (tag, len, c); + return c->pop_pack (false); +} + + +static void add_offset (unsigned id, + hb_serialize_context_t* c) +{ + OT::Offset16* offset = c->start_embed<OT::Offset16> (); + c->extend_min (offset); + c->add_link (*offset, id); +} + +static void +populate_serializer_simple (hb_serialize_context_t* c) +{ + c->start_serialize<char> (); + + unsigned obj_1 = add_object ("ghi", 3, c); + unsigned obj_2 = add_object ("def", 3, c); + + start_object ("abc", 3, c); + add_offset (obj_2, c); + add_offset (obj_1, c); + c->pop_pack (); + + c->end_serialize(); +} + +static void +populate_serializer_with_overflow (hb_serialize_context_t* c) +{ + std::string large_string(50000, 'a'); + c->start_serialize<char> (); + + unsigned obj_1 = add_object (large_string.c_str(), 10000, c); + unsigned obj_2 = add_object (large_string.c_str(), 20000, c); + unsigned obj_3 = add_object (large_string.c_str(), 50000, c); + + start_object ("abc", 3, c); + add_offset (obj_3, c); + add_offset (obj_2, c); + add_offset (obj_1, c); + c->pop_pack (); + + c->end_serialize(); +} + +static void +populate_serializer_with_dedup_overflow (hb_serialize_context_t* c) +{ + std::string large_string(70000, 'a'); + c->start_serialize<char> (); + + unsigned obj_1 = add_object ("def", 3, c); + + start_object (large_string.c_str(), 60000, c); + add_offset (obj_1, c); + unsigned obj_2 = c->pop_pack (false); + + start_object (large_string.c_str(), 10000, c); + add_offset (obj_2, c); + add_offset (obj_1, c); + c->pop_pack (false); + + c->end_serialize(); +} + +static void +populate_serializer_complex_1 (hb_serialize_context_t* c) +{ + c->start_serialize<char> (); + + unsigned obj_4 = add_object ("jkl", 3, c); + unsigned obj_3 = add_object ("ghi", 3, c); + + start_object ("def", 3, c); + add_offset (obj_3, c); + unsigned obj_2 = c->pop_pack (false); + + start_object ("abc", 3, c); + add_offset (obj_2, c); + add_offset (obj_4, c); + c->pop_pack (); + + c->end_serialize(); +} + +static void +populate_serializer_complex_2 (hb_serialize_context_t* c) +{ + c->start_serialize<char> (); + + unsigned obj_5 = add_object ("mn", 2, c); + + unsigned obj_4 = add_object ("jkl", 3, c); + + start_object ("ghi", 3, c); + add_offset (obj_4, c); + unsigned obj_3 = c->pop_pack (false); + + start_object ("def", 3, c); + add_offset (obj_3, c); + unsigned obj_2 = c->pop_pack (false); + + start_object ("abc", 3, c); + add_offset (obj_2, c); + add_offset (obj_4, c); + add_offset (obj_5, c); + c->pop_pack (); + + c->end_serialize(); +} + +static void +populate_serializer_complex_3 (hb_serialize_context_t* c) +{ + c->start_serialize<char> (); + + unsigned obj_6 = add_object ("opqrst", 6, c); + + unsigned obj_5 = add_object ("mn", 2, c); + + start_object ("jkl", 3, c); + add_offset (obj_6, c); + unsigned obj_4 = c->pop_pack (false); + + start_object ("ghi", 3, c); + add_offset (obj_4, c); + unsigned obj_3 = c->pop_pack (false); + + start_object ("def", 3, c); + add_offset (obj_3, c); + unsigned obj_2 = c->pop_pack (false); + + start_object ("abc", 3, c); + add_offset (obj_2, c); + add_offset (obj_4, c); + add_offset (obj_5, c); + c->pop_pack (); + + c->end_serialize(); +} + +static void test_sort_kahn_1 () +{ + size_t buffer_size = 100; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + populate_serializer_complex_1 (&c); + + graph_t graph (c.object_graph ()); + 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(strncmp (graph.object (2).head, "def", 3) == 0); + assert(graph.object (2).links.length == 1); + assert(graph.object (2).links[0].objidx == 0); + + assert(strncmp (graph.object (1).head, "jkl", 3) == 0); + assert(graph.object (1).links.length == 0); + + assert(strncmp (graph.object (0).head, "ghi", 3) == 0); + assert(graph.object (0).links.length == 0); + + free (buffer); +} + +static void test_sort_kahn_2 () +{ + size_t buffer_size = 100; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + populate_serializer_complex_2 (&c); + + graph_t graph (c.object_graph ()); + graph.sort_kahn (); + + + 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(strncmp (graph.object (3).head, "def", 3) == 0); + assert(graph.object (3).links.length == 1); + assert(graph.object (3).links[0].objidx == 1); + + assert(strncmp (graph.object (2).head, "mn", 2) == 0); + assert(graph.object (2).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(strncmp (graph.object (0).head, "jkl", 3) == 0); + assert(graph.object (0).links.length == 0); + + free (buffer); +} + +static void test_sort_shortest () +{ + size_t buffer_size = 100; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + populate_serializer_complex_2 (&c); + + graph_t graph (c.object_graph ()); + 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(strncmp (graph.object (3).head, "mn", 2) == 0); + assert(graph.object (3).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(strncmp (graph.object (1).head, "ghi", 3) == 0); + assert(graph.object (1).links.length == 1); + assert(graph.object (1).links[0].objidx == 0); + + assert(strncmp (graph.object (0).head, "jkl", 3) == 0); + assert(graph.object (0).links.length == 0); + + free (buffer); +} + +static void test_duplicate_leaf () +{ + size_t buffer_size = 100; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + populate_serializer_complex_2 (&c); + + graph_t graph (c.object_graph ()); + 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(strncmp (graph.object (4).head, "jkl", 3) == 0); + assert(graph.object (4).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(strncmp (graph.object (2).head, "ghi", 3) == 0); + assert(graph.object (2).links.length == 1); + assert(graph.object (2).links[0].objidx == 1); + + assert(strncmp (graph.object (1).head, "jkl", 3) == 0); + assert(graph.object (1).links.length == 0); + + assert(strncmp (graph.object (0).head, "mn", 2) == 0); + assert(graph.object (0).links.length == 0); + + free (buffer); +} + +static void test_duplicate_interior () +{ + size_t buffer_size = 100; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + populate_serializer_complex_3 (&c); + + graph_t graph (c.object_graph ()); + 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(strncmp (graph.object (5).head, "jkl", 3) == 0); + assert(graph.object (5).links.length == 1); + assert(graph.object (5).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(strncmp (graph.object (3).head, "ghi", 3) == 0); + assert(graph.object (3).links.length == 1); + assert(graph.object (3).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(strncmp (graph.object (1).head, "mn", 2) == 0); + assert(graph.object (1).links.length == 0); + + assert(strncmp (graph.object (0).head, "opqrst", 6) == 0); + assert(graph.object (0).links.length == 0); + + free (buffer); +} + +static void +test_serialize () +{ + size_t buffer_size = 100; + void* buffer_1 = malloc (buffer_size); + hb_serialize_context_t c1 (buffer_1, buffer_size); + 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 (); + + assert (actual == expected); + + actual.free (); + expected.free (); + free (buffer_1); + free (buffer_2); +} + +static void test_will_overflow_1 () +{ + size_t buffer_size = 100; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + populate_serializer_complex_2 (&c); + graph_t graph (c.object_graph ()); + + assert (!graph.will_overflow (nullptr)); + + free (buffer); +} + +static void test_will_overflow_2 () +{ + size_t buffer_size = 160000; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + populate_serializer_with_overflow (&c); + graph_t graph (c.object_graph ()); + + assert (graph.will_overflow (nullptr)); + + free (buffer); +} + +static void test_will_overflow_3 () +{ + size_t buffer_size = 160000; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + populate_serializer_with_dedup_overflow (&c); + graph_t graph (c.object_graph ()); + + assert (graph.will_overflow (nullptr)); + + free (buffer); +} + +static void test_resolve_overflows_via_sort () +{ + size_t buffer_size = 160000; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + 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 (), &out); + assert (!out.offset_overflow ()); + hb_bytes_t result = out.copy_bytes (); + assert (result.length == (80000 + 3 + 3 * 2)); + + result.free (); + free (buffer); + free (out_buffer); +} + +static void test_resolve_overflows_via_duplication () +{ + size_t buffer_size = 160000; + void* buffer = malloc (buffer_size); + hb_serialize_context_t c (buffer, buffer_size); + 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 (), &out); + assert (!out.offset_overflow ()); + hb_bytes_t result = out.copy_bytes (); + assert (result.length == (10000 + 2 * 2 + 60000 + 2 + 3 * 2)); + + result.free (); + free (buffer); + free (out_buffer); +} + +// TODO(garretrieger): update will_overflow tests to check the overflows array. +// TODO(garretrieger): add a test(s) using a real font. +// TODO(garretrieger): add tests for priority raising. + +int +main (int argc, char **argv) +{ + test_serialize (); + test_sort_kahn_1 (); + test_sort_kahn_2 (); + test_sort_shortest (); + test_will_overflow_1 (); + test_will_overflow_2 (); + test_will_overflow_3 (); + test_resolve_overflows_via_sort (); + test_resolve_overflows_via_duplication (); + test_duplicate_leaf (); + test_duplicate_interior (); +} diff --git a/Build/source/libs/harfbuzz/version.ac b/Build/source/libs/harfbuzz/version.ac index 6738dd09b39..5db9084725d 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], [2.8.0]) +m4_define([harfbuzz_version], [2.8.1]) |