diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2019-10-28 23:44:53 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2019-10-28 23:44:53 +0000 |
commit | 65b88a70ed4a3b2ee8da094d317b3d8119aec1d7 (patch) | |
tree | 9b8c76c1afc603f7bcb0377efabd7b06cdd43e5d /Build | |
parent | 1631aaed733bf2365f99084b46113a982d918ebc (diff) |
harfbuzz-2.6.3
git-svn-id: svn://tug.org/texlive/trunk@52560 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build')
69 files changed, 3581 insertions, 859 deletions
diff --git a/Build/source/libs/README b/Build/source/libs/README index 3fbd6a47e65..bacd56a4cad 100644 --- a/Build/source/libs/README +++ b/Build/source/libs/README @@ -25,7 +25,7 @@ graphite2 1.3.13 - checked 21dec18 http://sourceforge.net/projects/silgraphite/files/graphite2/ (requires C++11) -harfbuzz 2.6.2 - checked 01oct19 +harfbuzz 2.6.3 - checked 29oct19 http://www.freedesktop.org/software/harfbuzz/release/ icu 63.1 - checked 8jan19 diff --git a/Build/source/libs/harfbuzz/ChangeLog b/Build/source/libs/harfbuzz/ChangeLog index 737ad49db32..494524dcf9b 100644 --- a/Build/source/libs/harfbuzz/ChangeLog +++ b/Build/source/libs/harfbuzz/ChangeLog @@ -1,3 +1,8 @@ +2019-10-29 Akira Kakuto <kakuto@w32tex.org> + + Import harfbuzz-2.6.3. + * Makefile.am, version.ac: Adjusted. + 2019-10-01 Akira Kakuto <kakuto@w32tex.org> Import harfbuzz-2.6.2. diff --git a/Build/source/libs/harfbuzz/Makefile.am b/Build/source/libs/harfbuzz/Makefile.am index 071afb227eb..a8b9c05817f 100644 --- a/Build/source/libs/harfbuzz/Makefile.am +++ b/Build/source/libs/harfbuzz/Makefile.am @@ -129,7 +129,6 @@ libharfbuzz_a_SOURCES = \ @HARFBUZZ_TREE@/src/hb-unicode-emoji-table.hh \ @HARFBUZZ_TREE@/src/hb-vector.hh \ @HARFBUZZ_TREE@/src/hb-utf.hh \ - @HARFBUZZ_TREE@/src/hb-warning.cc \ @HARFBUZZ_TREE@/src/hb-buffer-deserialize-json.hh \ @HARFBUZZ_TREE@/src/hb-buffer-deserialize-text.hh \ @HARFBUZZ_TREE@/src/hb-fallback-shape.cc \ @@ -208,6 +207,7 @@ libharfbuzz_a_SOURCES += \ @HARFBUZZ_TREE@/src/hb-ot-var.cc \ @HARFBUZZ_TREE@/src/hb-ot-var-avar-table.hh \ @HARFBUZZ_TREE@/src/hb-ot-var-fvar-table.hh \ + @HARFBUZZ_TREE@/src/hb-ot-var-gvar-table.hh \ @HARFBUZZ_TREE@/src/hb-ot-var-hvar-table.hh \ @HARFBUZZ_TREE@/src/hb-ot-var-mvar-table.hh \ @HARFBUZZ_TREE@/src/hb-ot-vorg-table.hh \ diff --git a/Build/source/libs/harfbuzz/Makefile.in b/Build/source/libs/harfbuzz/Makefile.in index 861fbbae639..64a55fa8d60 100644 --- a/Build/source/libs/harfbuzz/Makefile.in +++ b/Build/source/libs/harfbuzz/Makefile.in @@ -142,7 +142,6 @@ am_libharfbuzz_a_OBJECTS = @HARFBUZZ_TREE@/src/hb-blob.$(OBJEXT) \ @HARFBUZZ_TREE@/src/hb-subset-cff2.$(OBJEXT) \ @HARFBUZZ_TREE@/src/hb-ucd.$(OBJEXT) \ @HARFBUZZ_TREE@/src/hb-unicode.$(OBJEXT) \ - @HARFBUZZ_TREE@/src/hb-warning.$(OBJEXT) \ @HARFBUZZ_TREE@/src/hb-fallback-shape.$(OBJEXT) \ @HARFBUZZ_TREE@/src/hb-aat-layout.$(OBJEXT) \ @HARFBUZZ_TREE@/src/hb-aat-map.$(OBJEXT) \ @@ -243,8 +242,7 @@ am__depfiles_remade = ./$(DEPDIR)/hbtest-dummy.Po \ @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff1.Po \ @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff2.Po \ @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-ucd.Po \ - @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po \ - @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-warning.Po + @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -798,7 +796,6 @@ libharfbuzz_a_SOURCES = @HARFBUZZ_TREE@/src/hb-algs.hh \ @HARFBUZZ_TREE@/src/hb-unicode.cc \ @HARFBUZZ_TREE@/src/hb-unicode-emoji-table.hh \ @HARFBUZZ_TREE@/src/hb-vector.hh @HARFBUZZ_TREE@/src/hb-utf.hh \ - @HARFBUZZ_TREE@/src/hb-warning.cc \ @HARFBUZZ_TREE@/src/hb-buffer-deserialize-json.hh \ @HARFBUZZ_TREE@/src/hb-buffer-deserialize-text.hh \ @HARFBUZZ_TREE@/src/hb-fallback-shape.cc \ @@ -874,6 +871,7 @@ libharfbuzz_a_SOURCES = @HARFBUZZ_TREE@/src/hb-algs.hh \ @HARFBUZZ_TREE@/src/hb-ot-var.cc \ @HARFBUZZ_TREE@/src/hb-ot-var-avar-table.hh \ @HARFBUZZ_TREE@/src/hb-ot-var-fvar-table.hh \ + @HARFBUZZ_TREE@/src/hb-ot-var-gvar-table.hh \ @HARFBUZZ_TREE@/src/hb-ot-var-hvar-table.hh \ @HARFBUZZ_TREE@/src/hb-ot-var-mvar-table.hh \ @HARFBUZZ_TREE@/src/hb-ot-vorg-table.hh \ @@ -1036,9 +1034,6 @@ clean-noinstLIBRARIES: @HARFBUZZ_TREE@/src/hb-unicode.$(OBJEXT): \ @HARFBUZZ_TREE@/src/$(am__dirstamp) \ @HARFBUZZ_TREE@/src/$(DEPDIR)/$(am__dirstamp) -@HARFBUZZ_TREE@/src/hb-warning.$(OBJEXT): \ - @HARFBUZZ_TREE@/src/$(am__dirstamp) \ - @HARFBUZZ_TREE@/src/$(DEPDIR)/$(am__dirstamp) @HARFBUZZ_TREE@/src/hb-fallback-shape.$(OBJEXT): \ @HARFBUZZ_TREE@/src/$(am__dirstamp) \ @HARFBUZZ_TREE@/src/$(DEPDIR)/$(am__dirstamp) @@ -1189,7 +1184,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-ucd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@@HARFBUZZ_TREE@/src/$(DEPDIR)/hb-warning.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -1833,7 +1827,6 @@ distclean: distclean-recursive -rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff2.Po -rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-ucd.Po -rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po - -rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-warning.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags @@ -1933,7 +1926,6 @@ maintainer-clean: maintainer-clean-recursive -rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-subset-cff2.Po -rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-ucd.Po -rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-unicode.Po - -rm -f @HARFBUZZ_TREE@/src/$(DEPDIR)/hb-warning.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/Build/source/libs/harfbuzz/TLpatches/ChangeLog b/Build/source/libs/harfbuzz/TLpatches/ChangeLog index 29bc18d0ddd..d94995c93b2 100644 --- a/Build/source/libs/harfbuzz/TLpatches/ChangeLog +++ b/Build/source/libs/harfbuzz/TLpatches/ChangeLog @@ -1,3 +1,8 @@ +2019-10-29 Akira Kakuto <kakuto@w32tex.org> + + Imported harfbuzz-2.6.3 source tree from: + http://www.freedesktop.org/software/harfbuzz/release/ + 2019-10-01 Akira Kakuto <kakuto@w32tex.org> Imported harfbuzz-2.6.2 source tree from: diff --git a/Build/source/libs/harfbuzz/TLpatches/TL-Changes b/Build/source/libs/harfbuzz/TLpatches/TL-Changes index 0151695d887..fff802a49a0 100644 --- a/Build/source/libs/harfbuzz/TLpatches/TL-Changes +++ b/Build/source/libs/harfbuzz/TLpatches/TL-Changes @@ -1,4 +1,4 @@ -Changes applied to the harfbuzz-2.6.2/ tree as obtained from: +Changes applied to the harfbuzz-2.6.3/ tree as obtained from: http://www.freedesktop.org/software/harfbuzz/release/ Removed: diff --git a/Build/source/libs/harfbuzz/configure b/Build/source/libs/harfbuzz/configure index ebf0c8f118c..3b0e698ad41 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.6.2. +# Generated by GNU Autoconf 2.69 for harfbuzz (TeX Live) 2.6.3. # # 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.6.2' -PACKAGE_STRING='harfbuzz (TeX Live) 2.6.2' +PACKAGE_VERSION='2.6.3' +PACKAGE_STRING='harfbuzz (TeX Live) 2.6.3' 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.6.2 to adapt to many kinds of systems. +\`configure' configures harfbuzz (TeX Live) 2.6.3 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.6.2:";; + short | recursive ) echo "Configuration of harfbuzz (TeX Live) 2.6.3:";; 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.6.2 +harfbuzz (TeX Live) configure 2.6.3 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.6.2, which was +It was created by harfbuzz (TeX Live) $as_me 2.6.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4047,7 +4047,7 @@ fi # Define the identity of the package. PACKAGE='harfbuzz--tex-live-' - VERSION='2.6.2' + VERSION='2.6.3' # Some tools Automake needs. @@ -4241,8 +4241,8 @@ WARNING_CFLAGS=$kpse_cv_warning_cflags HB_VERSION_MAJOR=2 HB_VERSION_MINOR=6 -HB_VERSION_MICRO=2 -HB_VERSION=2.6.2 +HB_VERSION_MICRO=3 +HB_VERSION=2.6.3 ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -7919,7 +7919,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.6.2, which was +This file was extended by harfbuzz (TeX Live) $as_me 2.6.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7985,7 +7985,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.6.2 +harfbuzz (TeX Live) config.status 2.6.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog index 5432e12cb63..84dc3cceefc 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog +++ b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog @@ -1,3 +1,831 @@ +commit ce11df1b5b8e49712bef249de19bc4768f3a691c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Oct 28 14:45:31 2019 -0700 + + 2.6.3 + + NEWS | 8 ++++++++ + configure.ac | 2 +- + src/hb-font.cc | 2 +- + src/hb-version.h | 4 ++-- + 4 files changed, 12 insertions(+), 4 deletions(-) + +commit 5a59de2b983ed7a1c639ea3e4d23c341134cd6d5 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Oct 28 14:02:47 2019 -0700 + + Actually add +hb_font_get_nominal_glyphs() + + New API: + +hb_font_get_nominal_glyphs() + + src/hb-font.cc | 23 +++++++++++++++++++++++ + src/hb-font.h | 8 ++++++++ + 2 files changed, 31 insertions(+) + +commit 03028a5fe512978a8f8e2396001cf8e425b44f72 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Oct 28 13:46:56 2019 -0700 + + Revert "Don't include codepoint 0 in the results of collect_unicodes." + + This reverts commit 14ad96ffbf77c33d8d33d2686d17c2375381989e. + + This was wrong. My bad! + + https://github.com/harfbuzz/harfbuzz/issues/2031 + + src/hb-ot-cmap-table.hh | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +commit 2714dc31b8d0ffe3c043935dd7619be0dd7b7635 +Merge: aca63902 14ad96ff +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Oct 28 13:01:34 2019 -0700 + + Merge pull request #2032 from googlefonts/collect_unicodes + + Don't include codepoint 0 in the results of collect_unicodes. + +commit 14ad96ffbf77c33d8d33d2686d17c2375381989e +Author: Garret Rieger <grieger@google.com> +Date: Mon Oct 28 12:56:04 2019 -0700 + + Don't include codepoint 0 in the results of collect_unicodes. + It is always assumed to be the notdef glyph. + + src/hb-ot-cmap-table.hh | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +commit aca63902814748b36bf6939421cfa95eed3a1ca7 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 22 00:06:46 2019 +0330 + + [gpos] Don't move pointer when match_glyph_data is not set + + src/hb-ot-layout-gsubgpos.hh | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +commit defe9b6da018bc85750c999454c51fde0cadb9b2 +Author: Qunxin Liu <qxliu@google.com> +Date: Fri Oct 25 10:07:26 2019 -0700 + + crash fix : Heap-buffer-overflow READ 2 + https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18513 + + src/hb-ot-layout-gpos-table.hh | 12 ++++++------ + ...z-testcase-minimized-hb-subset-fuzzer-5677906231033856 | Bin 0 -> 938 bytes + 2 files changed, 6 insertions(+), 6 deletions(-) + +commit b2fcca6e14afc8085cc1c2491b2d7c780dad1450 +Author: Qunxin Liu <qxliu@google.com> +Date: Thu Oct 24 15:15:26 2019 -0700 + + fuzzer crash fix + https://oss-fuzz.com/testcase-detail/5643107869917184 + + src/hb-ot-layout-gsubgpos.hh | 11 +++++++---- + ...-testcase-minimized-hb-subset-fuzzer-5643107869917184 | Bin 0 -> 3232 bytes + 2 files changed, 7 insertions(+), 4 deletions(-) + +commit 9815ca0338b47c6ea4e82f2fbd39d70e3456aca1 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Thu Oct 24 21:05:38 2019 +0330 + + [ci] Use custom subset fuzzer timeout for failing sanitizer bots + + .circleci/config.yml | 8 ++++---- + test/fuzzing/run-shape-fuzzer-tests.py | 3 ++- + test/fuzzing/run-subset-fuzzer-tests.py | 3 ++- + 3 files changed, 8 insertions(+), 6 deletions(-) + +commit b03b62cb304279195569180061cde745e0c9880a +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Wed Oct 23 12:18:21 2019 +0330 + + [ci] Add HB_NO_MT on non HB_TINY no-build-system builds + + .circleci/config.yml | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +commit 5e489670e15329f5eced16e5a76145c6149a265f +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Tue Oct 22 15:03:47 2019 -0700 + + Remove hb-warning.cc + + Fixes https://github.com/harfbuzz/harfbuzz/issues/2005 + + src/Makefile.sources | 1 - + src/harfbuzz.cc | 1 - + src/hb-atomic.hh | 16 +++++----------- + src/hb-mutex.hh | 25 ++++++------------------- + src/hb-warning.cc | 37 ------------------------------------- + 5 files changed, 11 insertions(+), 69 deletions(-) + +commit 05bcdb39d8648c49f7984c404aee096f2ad1d655 +Author: Garret Rieger <grieger@google.com> +Date: Mon Oct 21 16:10:06 2019 -0700 + + Add a specialization of array_t:hash for hb_bytes_t and hb_ubytes_t. + + src/hb-array.hh | 34 ++++++++++++++++++++++++---------- + src/hb-ot-layout-gsubgpos.hh | 2 -- + 2 files changed, 24 insertions(+), 12 deletions(-) + +commit 95ab110cd9a6083a854e538211618b2733aba643 +Author: Garret Rieger <grieger@google.com> +Date: Mon Oct 21 13:15:46 2019 -0700 + + Optimize intersects_array to fix fuzzer timeout. + + src/hb-ot-layout-gsubgpos.hh | 10 +++++----- + ...estcase-minimized-hb-subset-fuzzer-5763024094232576 | Bin 0 -> 125681 bytes + 2 files changed, 5 insertions(+), 5 deletions(-) + +commit be5cdcdfa21a2d956fc8c445452a78e77ede95fb +Author: Garret Rieger <grieger@google.com> +Date: Tue Oct 22 11:55:04 2019 -0700 + + Store the hash value of a key in item_t in hb_map to reduce the number of hash computations. + + src/hb-map.hh | 70 ++++++++++++++++++++++++++++++++++------------------------- + 1 file changed, 40 insertions(+), 30 deletions(-) + +commit b33a0d628e5e76992fdd02fd4178906137e6153c +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Oct 21 13:24:52 2019 -0700 + + fuzzer crash fix: Null-dereference WRITE + https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18363 + + src/hb-ot-layout-common.hh | 4 +++- + ...z-testcase-minimized-hb-subset-fuzzer-5659903036751872 | Bin 0 -> 781 bytes + 2 files changed, 3 insertions(+), 1 deletion(-) + +commit cf414e361a99decd9c1710f1012236bffd067878 +Author: Garret Rieger <grieger@google.com> +Date: Fri Sep 27 09:55:17 2019 -0700 + + Added profiling instructions to TESTING.md + + TESTING.md | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +commit 1f0a9d9be979de01527c05f4dbe6fbc62799597c +Author: Qunxin Liu <qxliu@google.com> +Date: Tue Sep 17 11:10:08 2019 -0700 + + [subset] GPOS Lookup Type 2: PairPos + + src/hb-ot-layout-gpos-table.hh | 131 ++++++++++++++++++++- + test/subset/data/Makefile.am | 1 + + test/subset/data/Makefile.sources | 1 + + ...s2_1_font7.keep-layout-retain-gids.21,23,25.otf | Bin 0 -> 1764 bytes + ...gpos2_1_font7.keep-layout-retain-gids.21,23.otf | Bin 0 -> 1632 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3688 bytes + .../gpos2_1_font7.keep-layout.21,23,25.otf | Bin 0 -> 1428 bytes + .../gpos2_1_font7.keep-layout.21,23.otf | Bin 0 -> 1308 bytes + ...s2_1_font7.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3688 bytes + ...s2_2_font5.keep-layout-retain-gids.21,23,25.otf | Bin 0 -> 1776 bytes + ...gpos2_2_font5.keep-layout-retain-gids.21,23.otf | Bin 0 -> 1644 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3684 bytes + .../gpos2_2_font5.keep-layout.21,23,25.otf | Bin 0 -> 1440 bytes + .../gpos2_2_font5.keep-layout.21,23.otf | Bin 0 -> 1320 bytes + ...s2_2_font5.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3684 bytes + test/subset/data/fonts/gpos2_1_font7.otf | Bin 0 -> 4584 bytes + test/subset/data/fonts/gpos2_2_font5.otf | Bin 0 -> 4580 bytes + test/subset/data/tests/layout.gpos2.tests | 12 ++ + 18 files changed, 139 insertions(+), 6 deletions(-) + +commit e766783152b91fb20baf0c657586628fd7959b1b +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Mon Oct 21 22:17:06 2019 +0330 + + [fuzz] Add https://crbug.com/oss-fuzz/17898 testcase + + ...sterfuzz-testcase-hb-subset-fuzzer-5717414645334016 | Bin 0 -> 310324 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +commit b66094ada0ae7e69d5d08ee8423554629eabccaf +Author: Qunxin Liu <qxliu@google.com> +Date: Mon Sep 30 16:19:18 2019 -0700 + + [subset] GSUB Lookup Type 6: ChainContextSubst + + src/hb-ot-layout-common.hh | 260 ++++++++++++++------- + src/hb-ot-layout-gsubgpos.hh | 218 ++++++++++++++++- + test/subset/data/Makefile.am | 1 + + test/subset/data/Makefile.sources | 1 + + ...ules_f1.keep-layout-retain-gids.30,31,32,33.otf | Bin 0 -> 2380 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3748 bytes + ...ultiple_subrules_f1.keep-layout.30,31,32,33.otf | Bin 0 -> 1916 bytes + ...ubrules_f1.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3748 bytes + ...ules_f1.keep-layout-retain-gids.30,31,32,33.otf | Bin 0 -> 2408 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3780 bytes + ...ultiple_subrules_f1.keep-layout.30,31,32,33.otf | Bin 0 -> 1944 bytes + ...ubrules_f1.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3780 bytes + ...mple_f2.keep-layout-retain-gids.30,31,32,33.otf | Bin 0 -> 2368 bytes + ...eep-layout-retain-gids.retain-all-codepoint.otf | Bin 0 -> 3716 bytes + ...chaining3_simple_f2.keep-layout.30,31,32,33.otf | Bin 0 -> 1904 bytes + ..._simple_f2.keep-layout.retain-all-codepoint.otf | Bin 0 -> 3716 bytes + .../fonts/gsub_chaining1_multiple_subrules_f1.otf | Bin 0 -> 4700 bytes + .../fonts/gsub_chaining2_multiple_subrules_f1.otf | Bin 0 -> 4780 bytes + .../subset/data/fonts/gsub_chaining3_simple_f2.otf | Bin 0 -> 4668 bytes + test/subset/data/tests/layout.gsub6.tests | 12 + + 20 files changed, 405 insertions(+), 87 deletions(-) + +commit eff91bbb4b1e6f4cc8401b1915d5ddad64e053bb +Author: Garret Rieger <grieger@google.com> +Date: Wed Oct 16 16:58:57 2019 -0700 + + Add missing pop() for the failure case of script subsetting. + + src/hb-ot-layout-common.hh | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +commit eab191fd9c851cb7881163ddd5e11a2ebc58cef4 +Author: Garret Rieger <grieger@google.com> +Date: Wed Oct 2 14:28:53 2019 -0700 + + Rewrite hash and == function for hb_array_t as a plain loop. + + Profling showed that the current implementation were accounting for nearly all processing time in some cases. These implementations look to be about 10x faster. + + src/hb-array.hh | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +commit 831daf4c76aed87d229b1edfb59a0a37caa8e581 +Author: Garret Rieger <grieger@google.com> +Date: Tue Oct 1 17:46:27 2019 -0700 + + Enforce HB_MAX_LANGSYS limit during layout subsetting. + + src/hb-ot-layout-common.hh | 68 +++++++++++++-------- + ...ase-minimized-hb-subset-fuzzer-5721073428987904 | Bin 0 -> 349561 bytes + 2 files changed, 41 insertions(+), 27 deletions(-) + +commit 9871461bce9a1557807f69615300e5df4f6ae322 +Author: Garret Rieger <grieger@google.com> +Date: Tue Oct 1 16:29:24 2019 -0700 + + Enforce HB_MAX_SCRIPTS during subsetting of the script table. + + src/hb-ot-layout-common.hh | 46 +++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 41 insertions(+), 5 deletions(-) + +commit 029775bcbd0a25ee1cdb6c0653a2ce189774490a +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Wed Oct 9 11:00:09 2019 +0700 + + [buffer] Minor; improve HB_NO_BUFFER_MESSAGE + + src/hb-buffer.cc | 2 ++ + src/hb-buffer.hh | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +commit 9a68e6b901967da14a5da5acb535c944794627b8 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Wed Oct 16 13:28:15 2019 +0330 + + [doc] minor + + Addresses https://github.com/harfbuzz/harfbuzz/pull/2013/files#r335196908 + + src/hb-common.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit b0b8551afc2ff86d027fdb380210601cb465af41 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sat Oct 12 21:12:19 2019 +0330 + + [glyf] Use range_checker_t in composite_iter_t + + src/hb-ot-glyf-table.hh | 12 +++++++----- + src/hb-ot-var-gvar-table.hh | 19 +++++++++---------- + 2 files changed, 16 insertions(+), 15 deletions(-) + +commit 06e35ce052388e7ce079c0250db62428ae0c5bc8 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sat Oct 12 15:16:31 2019 +0330 + + [glyf] minor + + src/hb-ot-glyf-table.hh | 128 +++++++++++++++++++++++++----------------------- + 1 file changed, 67 insertions(+), 61 deletions(-) + +commit d13bb4bd94a6ba8cdd4a03d40d8089a8f8b3a7ec +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sat Oct 12 12:13:57 2019 +0330 + + [glyf] other cleanups + + src/hb-ot-glyf-table.hh | 338 +++++++++++++++++++++++------------------------- + 1 file changed, 160 insertions(+), 178 deletions(-) + +commit e7aa8c5d22b034f3d7bcf187a63cdec27732fa8a +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sat Oct 12 11:25:32 2019 +0330 + + [glyf] Introduce glyf::Glyph, a hb_bytes_t/GlyphHeader pair + + src/hb-ot-glyf-table.hh | 177 +++++++++++++++++++++++++----------------------- + 1 file changed, 91 insertions(+), 86 deletions(-) + +commit 546ffc9faf869b4971765e9a4fd232cfe0eecaea +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sat Oct 12 09:51:57 2019 +0330 + + [glyf] minor + + src/hb-ot-glyf-table.hh | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +commit 4299ea266e03b64db4e8a132983fed9fd0a967ee +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sat Oct 12 09:51:27 2019 +0330 + + [glyf] Move get_contour_points to GlyphHeader + + src/hb-ot-glyf-table.hh | 260 ++++++++++++++++++++++++++---------------------- + 1 file changed, 141 insertions(+), 119 deletions(-) + +commit b918cd8c76a6333e43b9be23178afc9e74e17024 +Author: Ben Wagner <bungeman@chromium.org> +Date: Thu Oct 10 15:30:48 2019 -0400 + + Document hb_feature_t. + + This documents hb_feature_t. This is motivated mostly by the ambiguity + of the units for 'start' and 'end' (clusters) and whether they are + inclusive or exclusive. This also documents that for lookup type 3 the + value is the one based index into the alternates and that in a list of + features later feature values override previous feature values with the + same tag. + + src/hb-common.h | 15 +++++++++++++++ + src/hb-shape.cc | 4 +++- + 2 files changed, 18 insertions(+), 1 deletion(-) + +commit e637a4b3de2fb8bdbc1b82e822f4a6cc579e794b +Merge: 670fec23 e4464f44 +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Fri Oct 11 10:28:58 2019 +0700 + + Merge pull request #2012 from harfbuzz/lepcha-oo + + Reorder U+1C29 LEPCHA VOWEL SIGN OO + +commit 670fec231d31bf7417de590efd3485f337a7330f +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Thu Oct 10 09:21:08 2019 +0330 + + Minor, add a zero length tolerant memset, hb_memset + + src/hb-algs.hh | 10 +++++++++- + src/hb-buffer.cc | 3 +-- + 2 files changed, 10 insertions(+), 3 deletions(-) + +commit e4464f4484009b4efe7144570384d836cb6bbac8 +Author: David Corbett <corbett.dav@husky.neu.edu> +Date: Wed Oct 9 20:55:52 2019 -0400 + + Reorder U+1C29 LEPCHA VOWEL SIGN OO + + src/gen-use-table.py | 3 +++ + src/hb-ot-shape-complex-use-table.cc | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +commit e17e7443007fc0debc4a26e5cf37d5d76c747fbf +Author: Garret Rieger <grieger@google.com> +Date: Wed Oct 9 11:45:42 2019 -0700 + + Convert existing uses of serialize_append in gsub subsetting to use subset_offset_array. + + src/hb-ot-layout-gsub-table.hh | 44 +++--------------------------------------- + 1 file changed, 3 insertions(+), 41 deletions(-) + +commit 36f18cecbbaf8635a2179a827242ca99d5283666 +Author: Garret Rieger <grieger@google.com> +Date: Mon Oct 7 14:02:31 2019 -0700 + + Add subset_offset_array helper function which simplifies subsetting offset arrays during stream operations. + + src/hb-ot-layout-common.hh | 54 ++++++++++++++++++++++++++++++++++++++++++ + src/hb-ot-layout-gsub-table.hh | 15 +----------- + 2 files changed, 55 insertions(+), 14 deletions(-) + +commit dc45f225212da7b8eca0ddcb3c9cd66e65983605 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 23:27:37 2019 +0330 + + [ot-metrics] Don't use mixed scaled and not scaled for generating extents + + src/hb-ot-cff1-table.cc | 4 ++-- + src/hb-ot-cff2-table.cc | 4 ++-- + src/hb-ot-color-sbix-table.hh | 7 +++++++ + src/hb-ot-glyf-table.hh | 6 +++--- + test/api/test-ot-extents-cff.c | 6 +++--- + 5 files changed, 17 insertions(+), 10 deletions(-) + +commit b068e25f8f89d9b07963dddd5d5e14f61539556f +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 16:29:15 2019 +0330 + + [glyf] Address Behdad's reviews + + Addresses https://github.com/harfbuzz/harfbuzz/pull/1999#issuecomment-539298559 + * Don't check against Null pool + * Remove cryptic _tt suffix + + src/hb-ot-font.cc | 4 ++-- + src/hb-ot-hmtx-table.hh | 16 ++++++++-------- + 2 files changed, 10 insertions(+), 10 deletions(-) + +commit 6961766db2c53ea813079c61e4d996234ae8be4f +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 16:26:48 2019 +0330 + + [glyf] fix scaling direction + + src/hb-ot-glyf-table.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 0527fda4c75e4354198df79275526d4726a3aacc +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 16:19:39 2019 +0330 + + minor + + src/hb-subset-cff-common.cc | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit b2628f1a3e3a6875dcdf7cb89f5b10a4ae76e6f9 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 15:09:09 2019 +0330 + + [glyf] Move glyph bytes drop hints logic to GlyphHeader + + src/hb-ot-glyf-table.hh | 92 ++++++++++++++++++++----------------------------- + 1 file changed, 37 insertions(+), 55 deletions(-) + +commit 1fb9c3b6463fdee9eb4dac697beab4d3d7a5fdcf +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 13:50:16 2019 +0330 + + [glyf] Implement depth limit for add_gid_and_children + + src/hb-ot-glyf-table.hh | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +commit be0eddd41896824cb093024c2b4929b612ee1fae +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 13:46:55 2019 +0330 + + [glyf] Move add_gid_and_children to glyf table + + src/hb-ot-glyf-table.hh | 14 ++++++++++++++ + src/hb-subset-plan.cc | 19 +------------------ + 2 files changed, 15 insertions(+), 18 deletions(-) + +commit c7621cf21115aa563ee4fb9d2fcb601984848494 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 13:24:26 2019 +0330 + + Minor, replace hb_set_add with private API + + src/hb-ot-map.cc | 2 +- + src/hb-subset-cff-common.hh | 2 +- + src/hb-subset-cff1.cc | 2 +- + src/hb-subset-cff2.cc | 2 +- + src/hb-subset-plan.cc | 10 +++++----- + 5 files changed, 9 insertions(+), 9 deletions(-) + +commit ad86806dcb702b25fac6a3364cf0f85e1b8f4b2a +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 12:14:14 2019 +0330 + + [glyf] Move subset related methods inside GlyphHeader + + src/hb-ot-glyf-table.hh | 428 ++++++++++++++++++++++++------------------------ + src/hb-subset-plan.cc | 4 +- + 2 files changed, 214 insertions(+), 218 deletions(-) + +commit 7839e23558344f206175b5a798149e0f04f38266 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Mon Oct 7 11:14:26 2019 +0330 + + [glyf] minor + + src/hb-ot-glyf-table.hh | 38 +++++++++++++++----------------------- + 1 file changed, 15 insertions(+), 23 deletions(-) + +commit cbefbb2439c1a2f4c20877e611f8986b3933234e +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Mon Oct 7 10:15:18 2019 +0330 + + [glyf] Move padding removal logic to GlyphHeader + + src/hb-ot-glyf-table.hh | 219 +++++++++++++++++++++++------------------------- + 1 file changed, 105 insertions(+), 114 deletions(-) + +commit 1ab8f9aa7a182fa078f6c6a5a78ef95686b1ac54 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Mon Oct 7 08:24:12 2019 +0330 + + [glyf] minor + + src/hb-ot-glyf-table.hh | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +commit 13fb5612ad545b419ca217f031864dde1b71c43f +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sun Oct 6 23:24:06 2019 +0330 + + [glyf] Aggregate get_offsets uses + + src/hb-ot-glyf-table.hh | 29 +++++++---------------------- + 1 file changed, 7 insertions(+), 22 deletions(-) + +commit 5179b96958f2db71c315c1d8c224bab87e2f4ae8 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 8 11:09:12 2019 +0330 + + [cff] minor on number_t + + src/hb-cff-interp-common.hh | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +commit d73cdcf3612ae6114a0f828e0f667d447ed1a964 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sun Oct 6 18:09:14 2019 +0330 + + [ot-font] Apply font scaling before turning to int + + src/hb-ot-cff1-table.cc | 12 ++++----- + src/hb-ot-cff1-table.hh | 2 +- + src/hb-ot-cff2-table.cc | 8 +++--- + src/hb-ot-color-cbdt-table.hh | 14 +++++----- + src/hb-ot-color-sbix-table.hh | 8 +++--- + src/hb-ot-font.cc | 12 +++------ + src/hb-ot-glyf-table.hh | 58 ++++++++++++++++++++---------------------- + src/hb-ot-hmtx-table.hh | 2 +- + src/hb-ot-var-hvar-table.hh | 5 ++-- + test/api/test-ot-extents-cff.c | 20 +++++++-------- + 10 files changed, 66 insertions(+), 75 deletions(-) + +commit f2339964b713815c8e0e33699bf34ee24db12215 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sun Oct 6 16:41:52 2019 +0330 + + [glyf] minor, remove GlyphHeader::simple_* helpers + + src/hb-ot-glyf-table.hh | 16 +++------------- + 1 file changed, 3 insertions(+), 13 deletions(-) + +commit 2d7ca6a76a754a42ec09a66319ac3e4ab5efc618 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sun Oct 6 16:31:29 2019 +0330 + + [glyf] Move get_instruction_length inside GlyphHeader struct + + src/hb-ot-glyf-table.hh | 153 ++++++++++++++++++++++++++---------------------- + 1 file changed, 84 insertions(+), 69 deletions(-) + +commit 50aef4d7f80b6c8a19481ad3d0fa89c7c7f222c2 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sun Oct 6 14:00:07 2019 +0330 + + [glyf] cleanup + + src/hb-ot-glyf-table.hh | 128 +++++++++++++++++++++--------------------------- + 1 file changed, 55 insertions(+), 73 deletions(-) + +commit ee3f4630d70099c42fd9c84796b29a236f6135b6 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sun Oct 6 13:56:35 2019 +0330 + + [glyf] Remove get_composite_iter and refactor bytes_for_glyph for shape uses + + src/hb-ot-glyf-table.hh | 42 ++++++++++++++++-------------------------- + src/hb-subset-plan.cc | 2 +- + 2 files changed, 17 insertions(+), 27 deletions(-) + +commit 8378ab96e28fa34f154583850ff1c2c672a4310d +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sun Oct 6 13:49:45 2019 +0330 + + [glyf] Rewrite composite iterator to new iterators convention + + src/hb-ot-glyf-table.hh | 201 ++++++++++++++++++++---------------------------- + src/hb-subset-plan.cc | 10 +-- + 2 files changed, 85 insertions(+), 126 deletions(-) + +commit b7684fa9f42dffa6bd81acfade163123b30800b8 +Merge: 79ec65ae 21c80d95 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sun Oct 6 09:00:48 2019 +0330 + + Merge pull request #1999 from ebraminio/glyf-var + + Implement gvar table and variable glyf + +commit 21c80d955f69c1242c77e0ec7ccd852360dd54dd +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sat Oct 5 23:58:52 2019 +0330 + + [gvar] minor + + src/hb-ot-var-gvar-table.hh | 43 +++++++++++++++++++++---------------------- + 1 file changed, 21 insertions(+), 22 deletions(-) + +commit 5752863640cf4292dec313edebb57aecd47496f3 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Sat Oct 5 23:51:50 2019 +0330 + + [glyf][gvar] Make HB_NO_VAR buildable + + src/hb-ot-font.cc | 2 ++ + src/hb-ot-glyf-table.hh | 6 ++++++ + src/hb-ot-hmtx-table.hh | 8 ++++++++ + 3 files changed, 16 insertions(+) + +commit 8e33510343d151afe49730f3a0b263a2853822b8 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Fri Oct 4 01:11:03 2019 +0330 + + [gvar] minor + + src/hb-ot-var-gvar-table.hh | 132 ++++++++++++++++++++++---------------------- + 1 file changed, 66 insertions(+), 66 deletions(-) + +commit b3afa8164460d63031a80d399200bcaa769c0fa1 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Fri Oct 4 00:32:04 2019 +0330 + + [glyf] Use common convention of other tables access, format + + src/hb-ot-face-table-list.hh | 1 + + src/hb-ot-glyf-table.hh | 65 +++++++++++++++++++------------------------- + 2 files changed, 29 insertions(+), 37 deletions(-) + +commit 88bd342c0ff686daad88bb6b4f2968bbd8b01a24 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Thu Oct 3 22:45:37 2019 +0330 + + [glyf] minor + + src/hb-ot-glyf-table.hh | 247 +++++++++++++++++++++++--------------------- + src/hb-ot-var-gvar-table.hh | 54 +++++----- + 2 files changed, 155 insertions(+), 146 deletions(-) + +commit ee7610181cee5bbc0b5dc291228fbe032097bde4 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Thu Oct 3 15:59:45 2019 +0330 + + [hmtx] Use more conventional internal API style + + src/Makefile.sources | 1 - + src/harfbuzz.cc | 1 - + src/hb-ot-font.cc | 12 ++++++++++++ + src/hb-ot-hmtx-table.cc | 42 ------------------------------------------ + src/hb-ot-hmtx-table.hh | 18 ++++++++++-------- + 5 files changed, 22 insertions(+), 52 deletions(-) + +commit c9577a630fd5bd08482ee7b94bc03c91fcf366c7 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Thu Oct 3 15:48:35 2019 +0330 + + [hmtx] Use more optimal way to access glyf table + + src/hb-ot-hmtx-table.cc | 20 ++++---------------- + src/hb-ot-hmtx-table.hh | 4 ++-- + 2 files changed, 6 insertions(+), 18 deletions(-) + +commit b9ff43c162e8f61cff8e48d3dcbf7c1fe263d625 +Author: Michiharu Ariza <ariza@typekit.com> +Date: Tue Oct 1 16:13:40 2019 +0330 + + Implement gvar table and variable glyf + + Split from Ariza's "[subset] TrueType/CFF2 variable font" work on #1594 + + src/Makefile.sources | 2 + + src/harfbuzz.cc | 1 + + src/hb-ot-font.cc | 4 +- + src/hb-ot-glyf-table.hh | 618 ++++++++++++++--- + src/hb-ot-hmtx-table.cc | 54 ++ + src/hb-ot-hmtx-table.hh | 33 +- + src/hb-ot-var-gvar-table.hh | 734 +++++++++++++++++++++ + test/api/Makefile.am | 1 + + .../SourceSansVariable-Roman-nohvar-41,C1.ttf | Bin 0 -> 4696 bytes + test/api/fonts/SourceSansVariable-Roman.anchor.ttf | Bin 0 -> 4708 bytes + .../api/fonts/SourceSansVariable-Roman.modcomp.ttf | Bin 0 -> 3252 bytes + .../fonts/SourceSerifVariable-Roman-VVAR.abc.ttf | Bin 0 -> 5632 bytes + test/api/test-ot-metrics-tt-var.c | 250 +++++++ + 13 files changed, 1588 insertions(+), 109 deletions(-) + +commit 79ec65ae10f959aeddaa1e39eba5226c604a8c87 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Thu Oct 3 14:27:51 2019 +0330 + + [ot-font] Use var vmtx side bearing in calculating v-origin + + src/hb-ot-font.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 3fd555be543a3e9bf9fee509327dbbc9a7b51cdb +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Thu Oct 3 13:02:41 2019 +0330 + + [hmtx] Prepare to fix and minor fixes + + src/hb-ot-hmtx-table.hh | 41 ++++++++++++++++------------------------- + src/hb-ot-var-hvar-table.hh | 9 +++++---- + 2 files changed, 21 insertions(+), 29 deletions(-) + +commit 6d09b5a8a0f6ed7a2a92d91ac3d027bd54c452be +Author: Michiharu Ariza <ariza@typekit.com> +Date: Thu Oct 3 12:01:39 2019 +0330 + + Implement hmtx/vmtx metrics read from hvar/vvar + + src/hb-ot-hmtx-table.hh | 46 ++++++++++++++++++++++++++++++++++++++++----- + src/hb-ot-var-hvar-table.hh | 19 +++++++++++++------ + 2 files changed, 54 insertions(+), 11 deletions(-) + +commit cfafee52e4ff0441a33530847533f1b1f6019006 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Wed Oct 2 09:22:46 2019 +0330 + + Add Repology badges by @luzpaz + + fixes #2002 + to track downstream packaging of harfbuzz + + README.md | 9 +++++++++ + 1 file changed, 9 insertions(+) + +commit 2d7221a0e3552b1d902629d4ab6c0ce22db983a6 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 1 15:05:02 2019 +0330 + + [cff] minor + + src/hb-ot-cff-common.hh | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +commit 0558413f27e9a18188c0e3d55f5ee57ea42b1548 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 1 13:49:55 2019 +0330 + + Minor, tweak spaces + + src/hb-aat-layout-kerx-table.hh | 4 ++-- + src/hb-array.hh | 4 ++-- + src/hb-buffer.hh | 3 +-- + src/hb-font.h | 4 ++-- + src/hb-font.hh | 8 ++++---- + src/hb-open-file.hh | 2 +- + src/hb-open-type.hh | 10 +++++----- + src/hb-ot-cff-common.hh | 4 ++-- + src/hb-ot-cff1-table.cc | 11 +++++------ + src/hb-ot-cff1-table.hh | 24 ++++++++++++------------ + src/hb-ot-cff2-table.cc | 4 ++-- + src/hb-ot-cmap-table.hh | 6 ++---- + src/hb-ot-color-cbdt-table.hh | 2 +- + src/hb-ot-color-cpal-table.hh | 2 +- + src/hb-ot-kern-table.hh | 12 ++++++------ + src/hb-ot-layout-common.hh | 2 +- + src/hb-ot-layout-gpos-table.hh | 14 +++++++------- + src/hb-ot-os2-table.hh | 4 ++-- + src/hb-ot-shape-complex-myanmar.cc | 4 ++-- + src/hb-subset-cff-common.hh | 2 +- + src/hb-unicode.cc | 8 ++++---- + src/hb-unicode.h | 20 ++++++++++---------- + src/hb-vector.hh | 4 ++-- + src/main.cc | 37 +++++++++++++++++++++++-------------- + src/test-iter.cc | 2 +- + 25 files changed, 101 insertions(+), 96 deletions(-) + +commit 51b720f686adf45bc1b6db3aa76b7d2e62ad1304 +Author: Ebrahim Byagowi <ebrahim@gnu.org> +Date: Tue Oct 1 12:06:22 2019 +0330 + + Fix -Wsizeof-array-div clang warning + + src/hb-ot-shape-complex-arabic-fallback.hh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit faace9437ea09d89ef5f5f9c9fc3ce0dbc672142 +Merge: e48ef080 f0dd724c +Author: Behdad Esfahbod <behdad@behdad.org> +Date: Mon Sep 30 13:34:05 2019 -0700 + + Merge pull request #1807 from harfbuzz/subset-varstore + + VariationStore serializer + commit e48ef0804ad7e4abd35ff3646fa6ed10ad32f1ef Author: Behdad Esfahbod <behdad@behdad.org> Date: Mon Sep 30 12:39:06 2019 -0700 @@ -2250,6 +3078,13 @@ Date: Sat Jul 27 14:56:18 2019 +0430 src/hb-aat-layout-lcar-table.hh | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) +commit f0dd724c1e091f42f289efbebd2c50e830e59c6e +Merge: 68ac767e 4e1da6bb +Author: blueshade7 <ariza@typekit.com> +Date: Mon Jul 29 14:21:05 2019 -0700 + + Merge branch 'master' into subset-varstore + commit 4e1da6bb612b0c6386ab143dbb4ca19ff25bc2ba Author: Ebrahim Byagowi <ebrahim@gnu.org> Date: Mon Jul 29 22:03:56 2019 +0430 @@ -3050,6 +3885,16 @@ Date: Wed Jun 26 13:23:24 2019 -0700 util/options.cc | 44 ++++++++++++--------- 14 files changed, 48 insertions(+), 24 deletions(-) +commit 68ac767e430c4dfe4c556b2c4f962cc3dfc5d3e4 +Author: blueshade7 <ariza@typekit.com> +Date: Fri Jul 12 23:02:29 2019 -0700 + + added skip(), get_next_value() to inc_bimap to subset VarStore with retain-gids + + src/hb-bimap.hh | 25 ++++++++++++++++++++++++- + src/hb-ot-layout-common.hh | 14 +++++++------- + 2 files changed, 31 insertions(+), 8 deletions(-) + commit 4730b350b7ee90338caf3e962343af42412ce3df Author: Behdad Esfahbod <behdad@behdad.org> Date: Fri Jul 12 15:38:35 2019 -0700 @@ -3455,6 +4300,15 @@ Date: Tue Jul 2 14:18:38 2019 -0700 src/gen-ucd-table.py | 8 +++++--- 2 files changed, 20 insertions(+), 11 deletions(-) +commit 634390ecaf600176245e3354edd8dfdcb7f64cc5 +Author: blueshade7 <ariza@typekit.com> +Date: Mon Jul 1 18:52:57 2019 -0700 + + added VariationStore serializer to be used by HVAR/VVAR subsetters + + src/hb-ot-layout-common.hh | 165 ++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 163 insertions(+), 2 deletions(-) + commit 040b261deeed8924edcb087e27a61392d1f85023 Author: Michiharu Ariza <ariza@typekit.com> Date: Sun Jun 30 16:13:07 2019 -0700 diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS index 30fa8c3976c..6cae06dcdcd 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS +++ b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS @@ -1,3 +1,11 @@ +Overview of changes leading to 2.6.3 +Monday, October 28, 2019 +==================================== +- Misc small fixes, mostly to build-related issues. +- New API: ++hb_font_get_nominal_glyphs() + + Overview of changes leading to 2.6.2 Monday, September 30, 2019 ==================================== diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/README b/Build/source/libs/harfbuzz/harfbuzz-src/README index c3cc0c26e94..e0ef93576be 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/README +++ b/Build/source/libs/harfbuzz/harfbuzz-src/README @@ -6,6 +6,7 @@ [![Codacy Code Health](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz) [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/master/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz) [![Coverals Code Coverage](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz) +[![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions) [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/) This is HarfBuzz, a text shaping library. @@ -23,3 +24,11 @@ For custom configurations, see [CONFIG.md](CONFIG.md). For test execution, see [TESTING.md](TESTING.md). Documentation: https://harfbuzz.github.io + + +<details> + <summary>Packaging status of HarfBuzz</summary + +[![Packaging status](https://repology.org/badge/vertical-allrepos/harfbuzz.svg?header=harfbuzz)](https://repology.org/project/harfbuzz/versions) + +</details> diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/README.md b/Build/source/libs/harfbuzz/harfbuzz-src/README.md index c3cc0c26e94..e0ef93576be 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/README.md +++ b/Build/source/libs/harfbuzz/harfbuzz-src/README.md @@ -6,6 +6,7 @@ [![Codacy Code Health](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz) [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/master/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz) [![Coverals Code Coverage](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz) +[![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions) [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/) This is HarfBuzz, a text shaping library. @@ -23,3 +24,11 @@ For custom configurations, see [CONFIG.md](CONFIG.md). For test execution, see [TESTING.md](TESTING.md). Documentation: https://harfbuzz.github.io + + +<details> + <summary>Packaging status of HarfBuzz</summary + +[![Packaging status](https://repology.org/badge/vertical-allrepos/harfbuzz.svg?header=harfbuzz)](https://repology.org/project/harfbuzz/versions) + +</details> diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/TESTING.md b/Build/source/libs/harfbuzz/harfbuzz-src/TESTING.md index 4efc64ca5a9..94be3a0a7f7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/TESTING.md +++ b/Build/source/libs/harfbuzz/harfbuzz-src/TESTING.md @@ -73,3 +73,14 @@ sudo python infra/helper.py build_image harfbuzz sudo python infra/helper.py build_fuzzers --sanitizer address harfbuzz sudo python infra/helper.py run_fuzzer harfbuzz hb-subset-fuzzer ``` + +## Profiling + +``` +make clean +./configure CXXFLAGS="-fno-omit-frame-pointer -g" +make +perf record -o <perf output file> -g <command to run> +perf report -i<perf output file> +``` + diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac b/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac index c88cffea63c..38d9e07404f 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.6.2], + [2.6.3], [https://github.com/harfbuzz/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources index eff0ad347df..cbbad90d22f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources @@ -136,6 +136,7 @@ HB_BASE_sources = \ hb-ot-tag.cc \ hb-ot-var-avar-table.hh \ hb-ot-var-fvar-table.hh \ + hb-ot-var-gvar-table.hh \ hb-ot-var-hvar-table.hh \ hb-ot-var-mvar-table.hh \ hb-ot-var.cc \ @@ -162,7 +163,6 @@ HB_BASE_sources = \ hb-unicode.hh \ hb-utf.hh \ hb-vector.hh \ - hb-warning.cc \ hb.hh \ $(NULL) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py index a8a03a77b84..4523fb8ed76 100755 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py @@ -383,6 +383,9 @@ def map_to_use(data): # TODO: In USE's override list but not in Unicode 12.0 if U == 0x103C: UIPC = Left + # TODO: https://github.com/harfbuzz/harfbuzz/pull/2012 + if U == 0x1C29: UIPC = Left + # TODO: These are not in USE's override list that we have, nor are they in Unicode 12.0 if 0xA926 <= U <= 0xA92A: UIPC = Top # TODO: https://github.com/harfbuzz/harfbuzz/pull/1037 diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc index fe1c3602321..251a0654dc4 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc @@ -44,7 +44,6 @@ #include "hb-static.cc" #include "hb-ucd.cc" #include "hb-unicode.cc" -#include "hb-warning.cc" #include "hb-glib.cc" #include "hb-ft.cc" #include "hb-graphite2.cc" 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 8026b4ef1a2..be1b339aa3c 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 @@ -733,8 +733,8 @@ struct KerxSubTableHeader { typedef ExtendedTypes Types; - unsigned int tuple_count () const { return tupleCount; } - bool is_horizontal () const { return !(coverage & Vertical); } + unsigned tuple_count () const { return tupleCount; } + bool is_horizontal () const { return !(coverage & Vertical); } enum Coverage { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh index c57481bfef0..042e1c20d58 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh @@ -588,10 +588,18 @@ hb_memcmp (const void *a, const void *b, unsigned int len) /* It's illegal to pass NULL to memcmp(), even if len is zero. * So, wrap it. * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */ - if (!len) return 0; + if (unlikely (!len)) return 0; return memcmp (a, b, len); } +static inline void * +hb_memset (void *s, int c, unsigned int n) +{ + /* It's illegal to pass NULL to memset(), even if n is zero. */ + if (unlikely (!n)) return 0; + return memset (s, c, n); +} + static inline bool hb_unsigned_mul_overflows (unsigned int count, unsigned int size) { 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 6efaf5fa558..09d10b47c39 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh @@ -99,7 +99,14 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> template <typename T> operator T * () const { return arrayZ; } HB_INTERNAL bool operator == (const hb_array_t &o) const; - HB_INTERNAL uint32_t hash () const; + + uint32_t hash () const { + uint32_t current = 0; + for (unsigned int i = 0; i < this->length; i++) { + current = current * 31 + hb_hash (this->arrayZ[i]); + } + return current; + } /* * Compare, Sort, and Search. @@ -281,8 +288,8 @@ struct hb_sorted_array_t : } template <typename T> bool bfind (const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, - unsigned int to_store = (unsigned int) -1) const + hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const { int min = 0, max = (int) this->length - 1; const Type *array = this->arrayZ; @@ -332,27 +339,35 @@ hb_sorted_array (T (&array_)[length_]) template <typename T> bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const { - return length == o.length && - + hb_zip (*this, o) - | hb_map ([] (hb_pair_t<T&, T&> &&_) { return _.first == _.second; }) - | hb_all - ; + if (o.length != this->length) return false; + for (unsigned int i = 0; i < this->length; i++) { + if (this->arrayZ[i] != o.arrayZ[i]) return false; + } + return true; } -template <typename T> -uint32_t hb_array_t<T>::hash () const -{ - return - + hb_iter (*this) - | hb_map (hb_hash) - | hb_reduce ([] (uint32_t a, uint32_t b) { return a * 31 + b; }, 0) - ; + +/* TODO Specialize opeator== for hb_bytes_t and hb_ubytes_t. */ + +template <> +inline uint32_t hb_array_t<const char>::hash () const { + uint32_t current = 0; + for (unsigned int i = 0; i < this->length; i++) + current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u); + return current; +} + +template <> +inline uint32_t hb_array_t<const unsigned char>::hash () const { + uint32_t current = 0; + for (unsigned int i = 0; i < this->length; i++) + current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u); + return current; } + typedef hb_array_t<const char> hb_bytes_t; typedef hb_array_t<const unsigned char> hb_ubytes_t; -/* TODO Specialize opeator==/hash() for hb_bytes_t and hb_ubytes_t. */ -//template <> -//uint32_t hb_array_t<const char>::hash () const { return 0; } + #endif /* HB_ARRAY_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh index 09d88937c23..b3fb296b4e1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh @@ -212,25 +212,19 @@ static inline bool _hb_compare_and_swaplp (long *P, long O, long N) static_assert ((sizeof (long) == sizeof (void *)), ""); -#elif !defined(HB_NO_MT) +#elif defined(HB_NO_MT) -#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ +#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) #define _hb_memory_barrier() do {} while (0) -#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) - #define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) -#else /* HB_NO_MT */ - -#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) - -#define _hb_memory_barrier() do {} while (0) - -#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) +#else +#error "Could not find any system to define atomic_int macros." +#error "Check hb-atomic.hh for possible resolutions." #endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh index a773951abdf..cae0a4dea44 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh @@ -94,6 +94,14 @@ struct hb_bimap_t /* Inremental bimap: only lhs is given, rhs is incrementally assigned */ struct hb_inc_bimap_t : hb_bimap_t { + hb_inc_bimap_t () { init (); } + + void init () + { + hb_bimap_t::init (); + next_value = 0; + } + /* Add a mapping from lhs to rhs with a unique value if lhs is unknown. * Return the rhs value as the result. */ @@ -102,12 +110,24 @@ struct hb_inc_bimap_t : hb_bimap_t hb_codepoint_t rhs = forw_map[lhs]; if (rhs == HB_MAP_VALUE_INVALID) { - rhs = get_population (); + rhs = next_value++; set (lhs, rhs); } return rhs; } + hb_codepoint_t skip () + { return next_value++; } + + hb_codepoint_t get_next_value () const + { return next_value; } + + void add_set (const hb_set_t *set) + { + hb_codepoint_t i = HB_SET_VALUE_INVALID; + while (hb_set_next (set, &i)) add (i); + } + /* Create an identity map. */ bool identity (unsigned int size) { @@ -138,6 +158,9 @@ struct hb_inc_bimap_t : hb_bimap_t for (hb_codepoint_t rhs = 0; rhs < count; rhs++) set (work[rhs], rhs); } + + protected: + unsigned int next_value; }; #endif /* HB_BIMAP_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc index bb7f3c7c1d9..6131c861773 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc @@ -324,8 +324,7 @@ hb_buffer_t::clear_positions () out_len = 0; out_info = info; - if (likely (len)) - memset (pos, 0, sizeof (pos[0]) * len); + hb_memset (pos, 0, sizeof (pos[0]) * len); } void @@ -777,8 +776,10 @@ hb_buffer_destroy (hb_buffer_t *buffer) free (buffer->info); free (buffer->pos); +#ifndef HB_NO_BUFFER_MESSAGE if (buffer->message_destroy) buffer->message_destroy (buffer->message_data); +#endif free (buffer); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh index de0655de3e4..b5596d94577 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh @@ -126,9 +126,9 @@ struct hb_buffer_t /* Debugging API */ #ifndef HB_NO_BUFFER_MESSAGE hb_buffer_message_func_t message_func; -#endif void *message_data; hb_destroy_func_t message_destroy; +#endif /* Internal debugging. */ /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ @@ -408,8 +408,7 @@ struct hb_buffer_t } } - void unsafe_to_break_all () - { unsafe_to_break_impl (0, len); } + void unsafe_to_break_all () { unsafe_to_break_impl (0, len); } void safe_to_break_all () { for (unsigned int i = 0; i < len; i++) 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 fdc5c683ab4..780f61892d7 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 @@ -220,18 +220,15 @@ struct number_t void init () { set_real (0.0); } void fini () {} - void set_int (int v) { value = (double) v; } - int to_int () const { return (int) value; } + void set_int (int v) { value = v; } + int to_int () const { return value; } void set_fixed (int32_t v) { value = v / 65536.0; } - int32_t to_fixed () const { return (int32_t) (value * 65536.0); } + int32_t to_fixed () const { return value * 65536.0; } void set_real (double v) { value = v; } double to_real () const { return value; } - int ceil () const { return (int) ::ceil (value); } - int floor () const { return (int) ::floor (value); } - bool in_int_range () const { return ((double) (int16_t) to_int () == value); } @@ -248,7 +245,7 @@ struct number_t } protected: - double value; + double value; }; /* byte string */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h index 9f1764bdc83..037e50880e5 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h @@ -425,6 +425,21 @@ typedef void (*hb_destroy_func_t) (void *user_data); */ #define HB_FEATURE_GLOBAL_END ((unsigned int) -1) +/** + * hb_feature_t: + * @tag: a feature tag + * @value: 0 disables the feature, non-zero (usually 1) enables the feature. + * For features implemented as lookup type 3 (like 'salt') the @value is a one + * based index into the alternates. + * @start: the cluster to start applying this feature setting (inclusive). + * @end: the cluster to end applying this feature setting (exclusive). + * + * The #hb_feature_t is the structure that holds information about requested + * feature application. The feature will be applied with the given value to all + * glyphs which are in clusters between @start (inclusive) and @end (exclusive). + * Setting start to @HB_FEATURE_GLOBAL_START and end to @HB_FEATURE_GLOBAL_END + * specifies that the feature always applies to the entire buffer. + */ typedef struct hb_feature_t { hb_tag_t tag; uint32_t value; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc index ee35966c1cc..e89ad697efd 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc @@ -792,6 +792,29 @@ hb_font_get_nominal_glyph (hb_font_t *font, } /** + * hb_font_get_nominal_glyphs: + * @font: a font. + * + * + * + * Return value: + * + * Since: 2.6.3 + **/ +unsigned int +hb_font_get_nominal_glyphs (hb_font_t *font, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride) +{ + return font->get_nominal_glyphs (count, + first_unicode, unicode_stride, + first_glyph, glyph_stride); +} + +/** * hb_font_get_variation_glyph: * @font: a font. * @unicode: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h index 9b6518791e1..01ff201aeec 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h @@ -459,6 +459,14 @@ hb_font_get_variation_glyph (hb_font_t *font, hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph); +HB_EXTERN unsigned int +hb_font_get_nominal_glyphs (hb_font_t *font, + unsigned int count, + const hb_codepoint_t *first_unicode, + unsigned int unicode_stride, + hb_codepoint_t *first_glyph, + unsigned int glyph_stride); + HB_EXTERN hb_position_t hb_font_get_glyph_h_advance (hb_font_t *font, hb_codepoint_t glyph); @@ -649,8 +657,8 @@ hb_font_set_funcs (hb_font_t *font, /* Be *very* careful with this function! */ HB_EXTERN void hb_font_set_funcs_data (hb_font_t *font, - void *font_data, - hb_destroy_func_t destroy); + void *font_data, + hb_destroy_func_t destroy); HB_EXTERN void diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh index 4adf6ae99a9..b1e8e6440cc 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh @@ -216,7 +216,7 @@ struct hb_font_t } hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, - hb_codepoint_t *glyph) + hb_codepoint_t *glyph) { *glyph = 0; return klass->get.f.nominal_glyph (this, user_data, @@ -286,7 +286,7 @@ struct hb_font_t } hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, - hb_position_t *x, hb_position_t *y) + hb_position_t *x, hb_position_t *y) { *x = *y = 0; return klass->get.f.glyph_h_origin (this, user_data, @@ -328,7 +328,7 @@ struct hb_font_t } hb_bool_t get_glyph_extents (hb_codepoint_t glyph, - hb_glyph_extents_t *extents) + hb_glyph_extents_t *extents) { memset (extents, 0, sizeof (*extents)); return klass->get.f.glyph_extents (this, user_data, @@ -499,7 +499,7 @@ struct hb_font_t } void subtract_glyph_h_origin (hb_codepoint_t glyph, - hb_position_t *x, hb_position_t *y) + hb_position_t *x, hb_position_t *y) { hb_position_t origin_x, origin_y; 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 26e4930a5f7..8c8db4d520b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh @@ -46,16 +46,13 @@ struct hb_hashmap_t static_assert (hb_is_integral (K) || hb_is_pointer (K), ""); static_assert (hb_is_integral (V) || hb_is_pointer (V), ""); - /* TODO If key type is a pointer, keep hash in item_t and use to: - * 1. avoid rehashing when resizing table, and - * 2. compare hash before comparing keys, for speed. - */ struct item_t { K key; V value; + uint32_t hash; - void clear () { key = kINVALID; value = vINVALID; } + void clear () { key = kINVALID; value = vINVALID; hash = 0; } bool operator == (K o) { return hb_deref (key) == hb_deref (o); } bool operator == (const item_t &o) { return *this == o.key; } @@ -137,7 +134,9 @@ struct hb_hashmap_t if (old_items) for (unsigned int i = 0; i < old_size; i++) if (old_items[i].is_real ()) - set (old_items[i].key, old_items[i].value); + set_with_hash (old_items[i].key, + old_items[i].hash, + old_items[i].value); free (old_items); @@ -146,29 +145,9 @@ struct hb_hashmap_t void set (K key, V value) { - if (unlikely (!successful)) return; - if (unlikely (key == kINVALID)) return; - if ((occupancy + occupancy / 2) >= mask && !resize ()) return; - unsigned int i = bucket_for (key); - - if (value == vINVALID && items[i].key != key) - return; /* Trying to delete non-existent key. */ - - if (!items[i].is_unused ()) - { - occupancy--; - if (items[i].is_tombstone ()) - population--; - } - - items[i].key = key; - items[i].value = value; - - occupancy++; - if (!items[i].is_tombstone ()) - population++; - + set_with_hash (key, hb_hash (key), value); } + V get (K key) const { if (unlikely (!items)) return vINVALID; @@ -237,14 +216,45 @@ struct hb_hashmap_t protected: + void 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; + unsigned int i = bucket_for_hash (key, hash); + + if (value == vINVALID && items[i].key != key) + return; /* Trying to delete non-existent key. */ + + if (!items[i].is_unused ()) + { + occupancy--; + if (items[i].is_tombstone ()) + population--; + } + + items[i].key = key; + items[i].value = value; + items[i].hash = hash; + + occupancy++; + if (!items[i].is_tombstone ()) + population++; + } + unsigned int bucket_for (K key) const { - unsigned int i = hb_hash (key) % prime; + return bucket_for_hash (key, hb_hash (key)); + } + + unsigned int bucket_for_hash (K key, uint32_t hash) const + { + unsigned int i = hash % prime; unsigned int step = 0; unsigned int tombstone = (unsigned) -1; while (!items[i].is_unused ()) { - if (items[i] == key) + if (items[i].hash == hash && items[i] == key) return i; if (tombstone == (unsigned) -1 && items[i].is_tombstone ()) tombstone = i; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-mutex.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-mutex.hh index e1362673180..e7f8b1c434b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-mutex.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-mutex.hh @@ -92,25 +92,7 @@ typedef volatile int hb_mutex_impl_t; #define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END -#elif !defined(HB_NO_MT) - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD) -# include <sched.h> -# define HB_SCHED_YIELD() sched_yield () -#else -# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END -#endif - -#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */ -typedef volatile int hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT 0 -#define hb_mutex_impl_init(M) *(M) = 0 -#define hb_mutex_impl_lock(M) HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END -#define hb_mutex_impl_unlock(M) (*(M))-- -#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END - - -#else /* HB_NO_MT */ +#elif defined(HB_NO_MT) typedef int hb_mutex_impl_t; #define HB_MUTEX_IMPL_INIT 0 @@ -120,6 +102,11 @@ typedef int hb_mutex_impl_t; #define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END +#else + +#error "Could not find any system to define mutex macros." +#error "Check hb-mutex.hh for possible resolutions." + #endif 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 b05393647ea..cb1fdf1c998 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 @@ -287,7 +287,7 @@ struct ResourceRecord { return CastR<OpenTypeFontFace> ((data_base+offset).arrayZ); } bool sanitize (hb_sanitize_context_t *c, - const void *data_base) const + const void *data_base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && 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 fce55910326..af242ece12e 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 @@ -264,8 +264,8 @@ struct _hb_has_null template <typename Type> struct _hb_has_null<Type, true> { - static const Type *get_null () { return &Null(Type); } - static Type *get_crap () { return &Crap(Type); } + static const Type *get_null () { return &Null (Type); } + static Type *get_crap () { return &Crap (Type); } }; template <typename Type, typename OffsetType=HBUINT16, bool has_null=true> @@ -423,7 +423,7 @@ struct UnsizedArrayOf { return hb_array (arrayZ, len); } hb_array_t<const Type> as_array (unsigned int len) const { return hb_array (arrayZ, len); } - operator hb_array_t<Type> () { return as_array (); } + operator hb_array_t< Type> () { return as_array (); } operator hb_array_t<const Type> () const { return as_array (); } template <typename T> @@ -902,8 +902,8 @@ struct SortedArrayOf : ArrayOf<Type, LenType> { return *as_array ().bsearch (x, ¬_found); } template <typename T> bool bfind (const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, - unsigned int to_store = (unsigned int) -1) const + hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const { return as_array ().bfind (x, i, not_found, to_store); } }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh index f4c4fe85778..6735c74be49 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh @@ -564,13 +564,13 @@ struct FDSelect3_4 if (glyph < ranges[i].first) break; - return (hb_codepoint_t)ranges[i - 1].fd; + return (hb_codepoint_t) ranges[i - 1].fd; } - GID_TYPE &nRanges () { return ranges.len; } - GID_TYPE nRanges () const { return ranges.len; } - GID_TYPE &sentinel () { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); } - const GID_TYPE &sentinel () const { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); } + GID_TYPE &nRanges () { return ranges.len; } + GID_TYPE nRanges () const { return ranges.len; } + GID_TYPE &sentinel () { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); } + const GID_TYPE &sentinel () const { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); } ArrayOf<FDSelect3_4_Range<GID_TYPE, FD_TYPE>, GID_TYPE> ranges; /* GID_TYPE sentinel */ @@ -608,8 +608,8 @@ struct FDSelect hb_codepoint_t get_fd (hb_codepoint_t glyph) const { - if (this == &Null (FDSelect)) - return 0; + if (this == &Null (FDSelect)) return 0; + switch (format) { case 0: return u.format0.get_fd (glyph); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc index 3e4fc204f34..d1e46256265 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc @@ -203,8 +203,7 @@ struct bounds_t } } - bool empty () const - { return (min.x >= max.x) || (min.y >= max.y); } + bool empty () const { return (min.x >= max.x) || (min.y >= max.y); } point_t min; point_t max; @@ -219,12 +218,12 @@ struct cff1_extents_param_t bounds.init (); } - void start_path () { path_open = true; } - void end_path () { path_open = false; } + void start_path () { path_open = true; } + void end_path () { path_open = false; } bool is_path_open () const { return path_open; } - bool path_open; - bounds_t bounds; + bool path_open; + bounds_t bounds; const OT::cff1::accelerator_t *cff; }; @@ -307,14 +306,14 @@ bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, boun return true; } -bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const +bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const { #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ return true; #endif - bounds_t bounds; + bounds_t bounds; if (!_get_bounds (this, glyph, bounds)) return false; @@ -326,8 +325,8 @@ bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extent } else { - extents->x_bearing = (int32_t)bounds.min.x.floor (); - extents->width = (int32_t)bounds.max.x.ceil () - extents->x_bearing; + extents->x_bearing = font->em_scalef_x (bounds.min.x.to_real ()); + extents->width = font->em_scalef_x (bounds.max.x.to_real () - bounds.min.x.to_real ()); } if (bounds.min.y >= bounds.max.y) { @@ -336,8 +335,8 @@ bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extent } else { - extents->y_bearing = (int32_t)bounds.max.y.ceil (); - extents->height = (int32_t)bounds.min.y.floor () - extents->y_bearing; + extents->y_bearing = font->em_scalef_y (bounds.max.y.to_real ()); + extents->height = font->em_scalef_x (bounds.min.y.to_real () - bounds.max.y.to_real ()); } return true; 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 882250f269d..ad206511c1e 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 @@ -1155,7 +1155,7 @@ struct cff1 } bool is_valid () const { return blob != nullptr; } - bool is_CID () const { return topDict.is_CID (); } + bool is_CID () const { return topDict.is_CID (); } bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; } @@ -1196,7 +1196,7 @@ struct cff1 struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> { - HB_INTERNAL bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; + HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; }; @@ -1225,25 +1225,25 @@ struct cff1 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } - hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const + hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const { if (encoding != &Null(Encoding)) return encoding->get_code (glyph); else { - hb_codepoint_t sid = glyph_to_sid (glyph); + hb_codepoint_t sid = glyph_to_sid (glyph); if (sid == 0) return 0; - hb_codepoint_t code = 0; + hb_codepoint_t code = 0; switch (topDict.EncodingOffset) { - case StandardEncoding: - code = lookup_standard_encoding_for_code (sid); - break; - case ExpertEncoding: - code = lookup_expert_encoding_for_code (sid); - break; - default: - break; + case StandardEncoding: + code = lookup_standard_encoding_for_code (sid); + break; + case ExpertEncoding: + code = lookup_expert_encoding_for_code (sid); + break; + default: + break; } return code; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc index 0251efac8b5..a2242b76fb9 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc @@ -44,8 +44,8 @@ struct cff2_extents_param_t max_y.set_int (INT_MIN); } - void start_path () { path_open = true; } - void end_path () { path_open = false; } + void start_path () { path_open = true; } + void end_path () { path_open = false; } bool is_path_open () const { return path_open; } void update_bounds (const point_t &pt) @@ -125,8 +125,8 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, } else { - extents->x_bearing = (int32_t)param.min_x.floor (); - extents->width = (int32_t)param.max_x.ceil () - extents->x_bearing; + extents->x_bearing = font->em_scalef_x (param.min_x.to_real ()); + extents->width = font->em_scalef_x (param.max_x.to_real () - param.min_x.to_real ()); } if (param.min_y >= param.max_y) { @@ -135,8 +135,8 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, } else { - extents->y_bearing = (int32_t)param.max_y.ceil (); - extents->height = (int32_t)param.min_y.floor () - extents->y_bearing; + extents->y_bearing = font->em_scalef_y (param.max_y.to_real ()); + extents->height = font->em_scalef_y (param.min_y.to_real () - param.max_y.to_real ()); } return true; 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 eb6f2406bd3..e6646152978 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 @@ -736,9 +736,7 @@ struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32> struct UVSMapping { int cmp (const hb_codepoint_t &codepoint) const - { - return unicodeValue.cmp (codepoint); - } + { return unicodeValue.cmp (codepoint); } bool sanitize (hb_sanitize_context_t *c) const { @@ -1170,7 +1168,7 @@ struct cmap return true; return false; - }) + }) ; 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 2a873594a94..3498d3b360d 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 @@ -51,12 +51,12 @@ struct SmallGlyphMetrics return_trace (c->check_struct (this)); } - void get_extents (hb_glyph_extents_t *extents) const + void get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const { - extents->x_bearing = bearingX; - extents->y_bearing = bearingY; - extents->width = width; - extents->height = - (hb_position_t) height; + extents->x_bearing = font->em_scale_x (bearingX); + extents->y_bearing = font->em_scale_y (bearingY); + extents->width = font->em_scale_x (width); + extents->height = font->em_scale_y (-height); } HBUINT8 height; @@ -424,7 +424,7 @@ struct CBDT return false; const GlyphBitmapDataFormat17& glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset); - glyphFormat17.glyphMetrics.get_extents (extents); + glyphFormat17.glyphMetrics.get_extents (font, extents); break; } case 18: { @@ -432,7 +432,7 @@ struct CBDT return false; const GlyphBitmapDataFormat18& glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset); - glyphFormat18.glyphMetrics.get_extents (extents); + glyphFormat18.glyphMetrics.get_extents (font, extents); break; } default: @@ -453,7 +453,7 @@ struct CBDT } hb_blob_t* reference_png (hb_font_t *font, - hb_codepoint_t glyph) const + hb_codepoint_t glyph) const { const void *base; const BitmapSizeTable &strike = this->cblc->choose_strike (font); 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 76df889517b..1b3c7fc0b88 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 @@ -115,7 +115,7 @@ struct CPAL { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); } unsigned int get_palette_count () const { return numPalettes; } - unsigned int get_color_count () const { return numColors; } + unsigned int get_color_count () const { return numColors; } hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const { return v1 ().get_palette_flags (this, palette_index, numPalettes); } 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 6089027f873..35d3fd51056 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 @@ -243,10 +243,17 @@ struct sbix if (strike_ppem) { float scale = font->face->get_upem () / (float) strike_ppem; - extents->x_bearing = roundf (extents->x_bearing * scale); - extents->y_bearing = roundf (extents->y_bearing * scale); - extents->width = roundf (extents->width * scale); - extents->height = roundf (extents->height * scale); + extents->x_bearing = font->em_scalef_x (extents->x_bearing * scale); + extents->y_bearing = font->em_scalef_y (extents->y_bearing * scale); + extents->width = font->em_scalef_x (extents->width * scale); + extents->height = font->em_scalef_y (extents->height * scale); + } + else + { + extents->x_bearing = font->em_scale_x (extents->x_bearing); + extents->y_bearing = font->em_scale_y (extents->y_bearing); + extents->width = font->em_scale_x (extents->width); + extents->height = font->em_scale_y (extents->height); } hb_blob_destroy (blob); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh index 30bab5cb54d..6fa9baf1356 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face-table-list.hh @@ -84,6 +84,7 @@ HB_OT_TABLE (OT, VORG) #ifndef HB_NO_VAR HB_OT_TABLE (OT, fvar) HB_OT_TABLE (OT, avar) +HB_OT_ACCELERATOR (OT, gvar) HB_OT_TABLE (OT, MVAR) #endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc index e6288b44545..96f94e4a9ec 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc @@ -160,11 +160,11 @@ hb_ot_get_glyph_v_origin (hb_font_t *font, #endif hb_glyph_extents_t extents = {0}; - if (ot_face->glyf->get_extents (glyph, &extents)) + if (ot_face->glyf->get_extents (font, glyph, &extents)) { const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; - hb_position_t tsb = vmtx.get_side_bearing (glyph); - *y = font->em_scale_y (extents.y_bearing + tsb); + hb_position_t tsb = vmtx.get_side_bearing (font, glyph); + *y = extents.y_bearing + font->em_scale_y (tsb); return true; } @@ -188,9 +188,9 @@ hb_ot_get_glyph_extents (hb_font_t *font, #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR) if (!ret) ret = ot_face->sbix->get_extents (font, glyph, extents); #endif - if (!ret) ret = ot_face->glyf->get_extents (glyph, extents); + if (!ret) ret = ot_face->glyf->get_extents (font, glyph, extents); #ifndef HB_NO_OT_FONT_CFF - if (!ret) ret = ot_face->cff1->get_extents (glyph, extents); + if (!ret) ret = ot_face->cff1->get_extents (font, glyph, extents); if (!ret) ret = ot_face->cff2->get_extents (font, glyph, extents); #endif #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR) @@ -198,10 +198,6 @@ hb_ot_get_glyph_extents (hb_font_t *font, #endif // TODO Hook up side-bearings variations. - extents->x_bearing = font->em_scale_x (extents->x_bearing); - extents->y_bearing = font->em_scale_y (extents->y_bearing); - extents->width = font->em_scale_x (extents->width); - extents->height = font->em_scale_y (extents->height); return ret; } @@ -315,5 +311,19 @@ hb_ot_font_set_funcs (hb_font_t *font) nullptr); } +#ifndef HB_NO_VAR +int +_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical) +{ + return font->face->table.glyf->get_side_bearing_var (font, glyph, is_vertical); +} + +unsigned +_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical) +{ + return font->face->table.glyf->get_advance_var (font, glyph, is_vertical); +} +#endif + #endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh index 9a791bbf031..f5a64b050e8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh @@ -1,5 +1,6 @@ /* * Copyright © 2015 Google, Inc. + * Copyright © 2019 Adobe Inc. * Copyright © 2019 Ebrahim Byagowi * * This is part of HarfBuzz, a text shaping library. @@ -23,6 +24,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * Google Author(s): Behdad Esfahbod, Garret Rieger, Roderick Sheeter + * Adobe Author(s): Michiharu Ariza */ #ifndef HB_OT_GLYF_TABLE_HH @@ -30,6 +32,10 @@ #include "hb-open-type.hh" #include "hb-ot-head-table.hh" +#include "hb-ot-hmtx-table.hh" +#include "hb-ot-var-gvar-table.hh" + +#include <float.h> namespace OT { @@ -57,7 +63,7 @@ struct loca UnsizedArrayOf<HBUINT8> dataZ; /* Location data. */ public: - DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always + DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always * check the size externally, allow Null() object of it by * defining it _MIN instead. */ }; @@ -77,8 +83,7 @@ struct glyf bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const { TRACE_SANITIZE (this); - /* We don't check for anything specific here. The users of the - * struct do all the hard work... */ + /* Runtime checks as eager sanitizing each glyph is costy */ return_trace (true); } @@ -111,7 +116,7 @@ struct glyf free); bool result = plan->add_table (HB_OT_TAG_loca, loca_blob) - && _add_head_and_set_loca_version(plan, use_short_loca); + && _add_head_and_set_loca_version (plan, use_short_loca); hb_blob_destroy (loca_blob); return result; @@ -136,7 +141,7 @@ struct glyf ; } - // requires source of SubsetGlyph complains the identifier isn't declared + /* requires source of SubsetGlyph complains the identifier isn't declared */ template <typename Iterator> bool serialize (hb_serialize_context_t *c, Iterator it, @@ -147,6 +152,9 @@ struct glyf return_trace (true); } + /* Byte region(s) per glyph to output + unpadded, hints removed if so requested + If we fail to process a glyph we produce an empty (0-length) glyph */ bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -154,9 +162,6 @@ struct glyf glyf *glyf_prime = c->serializer->start_embed <glyf> (); if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false); - // Byte region(s) per glyph to output - // unpadded, hints removed if so requested - // If we fail to process a glyph we produce an empty (0-length) glyph hb_vector_t<SubsetGlyph> glyphs; _populate_subset_glyphs (c->plan, &glyphs); @@ -174,8 +179,8 @@ struct glyf template <typename SubsetGlyph> void - _populate_subset_glyphs (const hb_subset_plan_t * plan, - hb_vector_t<SubsetGlyph> * glyphs /* OUT */) const + _populate_subset_glyphs (const hb_subset_plan_t *plan, + hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const { OT::glyf::accelerator_t glyf; glyf.init (plan->source); @@ -186,14 +191,13 @@ struct glyf SubsetGlyph subset_glyph = {0}; subset_glyph.new_gid = new_gid; - // should never fail: all old gids should be mapped + /* should never fail: all old gids should be mapped */ if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) return subset_glyph; - subset_glyph.source_glyph = glyf.bytes_for_glyph ((const char *) this, - subset_glyph.old_gid); - if (plan->drop_hints) subset_glyph.drop_hints (glyf); - else subset_glyph.dest_start = subset_glyph.source_glyph; + subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true); + if (plan->drop_hints) subset_glyph.drop_hints_bytes (); + else subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes (); return subset_glyph; }) @@ -203,58 +207,6 @@ struct glyf glyf.fini (); } - static void - _fix_component_gids (const hb_subset_plan_t *plan, - hb_bytes_t glyph) - { - OT::glyf::CompositeGlyphHeader::Iterator iterator; - if (OT::glyf::CompositeGlyphHeader::get_iterator (&glyph, - glyph.length, - &iterator)) - { - do - { - hb_codepoint_t new_gid; - if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex, - &new_gid)) - continue; - ((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex = new_gid; - } while (iterator.move_to_next ()); - } - } - - static void - _zero_instruction_length (hb_bytes_t glyph) - { - const GlyphHeader &glyph_header = *glyph.as<GlyphHeader> (); - if (!glyph_header.is_simple_glyph ()) return; // only for simple glyphs - - unsigned int instruction_len_offset = glyph_header.simple_instruction_len_offset (); - const HBUINT16 &instruction_len = StructAtOffset<HBUINT16> (&glyph, - instruction_len_offset); - (HBUINT16 &) instruction_len = 0; - } - - static bool _remove_composite_instruction_flag (hb_bytes_t glyph) - { - const GlyphHeader &glyph_header = *glyph.as<GlyphHeader> (); - if (!glyph_header.is_composite_glyph ()) return true; // only for composites - - /* remove WE_HAVE_INSTRUCTIONS from flags in dest */ - OT::glyf::CompositeGlyphHeader::Iterator composite_it; - if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (&glyph, glyph.length, - &composite_it))) - return false; - const OT::glyf::CompositeGlyphHeader *composite_header; - do - { - composite_header = composite_it.current; - OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&composite_header->flags); - *flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS; - } while (composite_it.move_to_next ()); - return true; - } - static bool _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca) { @@ -273,41 +225,7 @@ struct glyf return success; } - struct GlyphHeader - { - unsigned int simple_instruction_len_offset () const - { return static_size + 2 * numberOfContours; } - - unsigned int simple_length (unsigned int instruction_len) const - { return simple_instruction_len_offset () + 2 + instruction_len; } - - bool is_composite_glyph () const { return numberOfContours < 0; } - bool is_simple_glyph () const { return numberOfContours > 0; } - - void get_extents (hb_glyph_extents_t *extents) const - { - extents->x_bearing = hb_min (xMin, xMax); - extents->y_bearing = hb_max (yMin, yMax); - extents->width = hb_max (xMin, xMax) - extents->x_bearing; - extents->height = hb_min (yMin, yMax) - extents->y_bearing; - } - - bool has_data () const { return numberOfContours; } - - protected: - HBINT16 numberOfContours;/* If the number of contours is - * greater than or equal to zero, - * this is a simple glyph; if negative, - * this is a composite glyph. */ - FWORD xMin; /* Minimum x for coordinate data. */ - FWORD yMin; /* Minimum y for coordinate data. */ - FWORD xMax; /* Maximum x for coordinate data. */ - FWORD yMax; /* Maximum y for coordinate data. */ - public: - DEFINE_SIZE_STATIC (10); - }; - - struct CompositeGlyphHeader + struct CompositeGlyphChain { enum composite_glyph_flag_t { @@ -325,180 +243,248 @@ struct glyf UNSCALED_COMPONENT_OFFSET = 0x1000 }; - HBUINT16 flags; - HBGlyphID glyphIndex; - unsigned int get_size () const { unsigned int size = min_size; - // arg1 and 2 are int16 + /* arg1 and 2 are int16 */ if (flags & ARG_1_AND_2_ARE_WORDS) size += 4; - // arg1 and 2 are int8 + /* arg1 and 2 are int8 */ else size += 2; - // One x 16 bit (scale) + /* One x 16 bit (scale) */ if (flags & WE_HAVE_A_SCALE) size += 2; - // Two x 16 bit (xscale, yscale) + /* Two x 16 bit (xscale, yscale) */ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4; - // Four x 16 bit (xscale, scale01, scale10, yscale) + /* Four x 16 bit (xscale, scale01, scale10, yscale) */ else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8; return size; } - // TODO rewrite using new iterator framework if possible - struct Iterator + bool is_use_my_metrics () const { return flags & USE_MY_METRICS; } + bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); } + void get_anchor_points (unsigned int &point1, unsigned int &point2) const { - const char *glyph_start; - const char *glyph_end; - const CompositeGlyphHeader *current; + const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex); + if (flags & ARG_1_AND_2_ARE_WORDS) + { + point1 = ((const HBUINT16 *) p)[0]; + point2 = ((const HBUINT16 *) p)[1]; + } + else + { + point1 = p[0]; + point2 = p[1]; + } + } - bool move_to_next () + void transform_points (contour_point_vector_t &points) const + { + float matrix[4]; + contour_point_t trans; + if (get_transformation (matrix, trans)) { - if (current->flags & CompositeGlyphHeader::MORE_COMPONENTS) + if (scaled_offsets ()) { - const CompositeGlyphHeader *possible = - &StructAfter<CompositeGlyphHeader, CompositeGlyphHeader> (*current); - if (!in_range (possible)) - return false; - current = possible; - return true; + points.translate (trans); + points.transform (matrix); + } + else + { + points.transform (matrix); + points.translate (trans); } - return false; } + } - bool in_range (const CompositeGlyphHeader *composite) const - { - return (const char *) composite >= glyph_start - && ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end - && ((const char *) composite + composite->get_size ()) <= glyph_end; - } - }; + protected: + bool scaled_offsets () const + { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; } - static bool get_iterator (const char * glyph_data, - unsigned int length, - CompositeGlyphHeader::Iterator *iterator /* OUT */) + bool get_transformation (float (&matrix)[4], contour_point_t &trans) const { - const GlyphHeader &glyph_header = *hb_bytes_t (glyph_data, length).as<GlyphHeader> (); - if (!glyph_header.has_data ()) return false; /* Empty glyph; zero extents. */ + matrix[0] = matrix[3] = 1.f; + matrix[1] = matrix[2] = 0.f; - if (glyph_header.is_composite_glyph ()) + int tx, ty; + const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex); + if (flags & ARG_1_AND_2_ARE_WORDS) { - const CompositeGlyphHeader *possible = - &StructAfter<CompositeGlyphHeader, GlyphHeader> (glyph_header); - - iterator->glyph_start = glyph_data; - iterator->glyph_end = (const char *) glyph_data + length; - if (!iterator->in_range (possible)) - return false; - iterator->current = possible; - return true; + tx = *(const HBINT16 *) p; + p += HBINT16::static_size; + ty = *(const HBINT16 *) p; + p += HBINT16::static_size; + } + else + { + tx = *p++; + ty = *p++; } + if (is_anchored ()) tx = ty = 0; - return false; + trans.init ((float) tx, (float) ty); + + { + const F2DOT14 *points = (const F2DOT14 *) p; + if (flags & WE_HAVE_A_SCALE) + { + matrix[0] = matrix[3] = points[0].to_float (); + return true; + } + else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) + { + matrix[0] = points[0].to_float (); + matrix[3] = points[1].to_float (); + return true; + } + else if (flags & WE_HAVE_A_TWO_BY_TWO) + { + matrix[0] = points[0].to_float (); + matrix[1] = points[1].to_float (); + matrix[2] = points[2].to_float (); + matrix[3] = points[3].to_float (); + return true; + } + } + return tx || ty; } + public: + HBUINT16 flags; + HBGlyphID glyphIndex; + public: DEFINE_SIZE_MIN (4); }; - struct accelerator_t + struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphChain &> { - void init (hb_face_t *face) + typedef const CompositeGlyphChain *__item_t__; + composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) : + glyph (glyph_), current (current_), checker (range_checker_t (glyph.arrayZ, glyph.length)) + { if (!in_range (current)) current = nullptr; } + composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), checker (range_checker_t (nullptr, 0)) {} + + const CompositeGlyphChain &__item__ () const { return *current; } + bool __more__ () const { return current; } + void __next__ () { - memset (this, 0, sizeof (accelerator_t)); - - const OT::head &head = *face->table.head; - if (head.indexToLocFormat > 1 || head.glyphDataFormat != 0) - /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ - return; - short_offset = 0 == head.indexToLocFormat; - - loca_table = hb_sanitize_context_t ().reference_table<loca> (face); - glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face); + if (!(current->flags & CompositeGlyphChain::MORE_COMPONENTS)) { current = nullptr; return; } - num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1; + const CompositeGlyphChain *possible = &StructAfter<CompositeGlyphChain, + CompositeGlyphChain> (*current); + if (!in_range (possible)) { current = nullptr; return; } + current = possible; } + bool operator != (const composite_iter_t& o) const + { return glyph != o.glyph || current != o.current; } - void fini () + bool in_range (const CompositeGlyphChain *composite) const { - loca_table.destroy (); - glyf_table.destroy (); + return checker.in_range (composite, CompositeGlyphChain::min_size) + && checker.in_range (composite, composite->get_size ()); } - /* - * Returns true if the referenced glyph is a valid glyph and a composite glyph. - * If true is returned a pointer to the composite glyph will be written into - * composite. - */ - bool get_composite (hb_codepoint_t glyph, - CompositeGlyphHeader::Iterator *composite /* OUT */) const + private: + hb_bytes_t glyph; + __item_t__ current; + range_checker_t checker; + }; + + struct Glyph + { + private: + struct GlyphHeader { - if (unlikely (!num_glyphs)) - return false; + bool has_data () const { return numberOfContours; } - unsigned int start_offset, end_offset; - if (!get_offsets (glyph, &start_offset, &end_offset)) - return false; /* glyph not found */ + bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const + { + /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */ + /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */ + extents->x_bearing = font->em_scale_x (font->face->table.hmtx->get_side_bearing (gid)); + extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax)); + extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax)); + extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax)); - return CompositeGlyphHeader::get_iterator ((const char *) this->glyf_table + start_offset, - end_offset - start_offset, - composite); - } + return true; + } - enum simple_glyph_flag_t - { - FLAG_ON_CURVE = 0x01, - FLAG_X_SHORT = 0x02, - FLAG_Y_SHORT = 0x04, - FLAG_REPEAT = 0x08, - FLAG_X_SAME = 0x10, - FLAG_Y_SAME = 0x20, - FLAG_RESERVED1 = 0x40, - FLAG_RESERVED2 = 0x80 + HBINT16 numberOfContours; + /* If the number of contours is + * greater than or equal to zero, + * this is a simple glyph; if negative, + * this is a composite glyph. */ + FWORD xMin; /* Minimum x for coordinate data. */ + FWORD yMin; /* Minimum y for coordinate data. */ + FWORD xMax; /* Maximum x for coordinate data. */ + FWORD yMax; /* Maximum y for coordinate data. */ + public: + DEFINE_SIZE_STATIC (10); }; - /* based on FontTools _g_l_y_f.py::trim */ - bool remove_padding (unsigned int start_offset, - unsigned int *end_offset) const + struct SimpleGlyph { - const char *glyph = ((const char *) glyf_table) + start_offset; - unsigned int glyph_length = *end_offset - start_offset; - const GlyphHeader &glyph_header = *hb_bytes_t (glyph, glyph_length).as<GlyphHeader> (); - if (!glyph_header.has_data ()) return true; + const GlyphHeader &header; + hb_bytes_t bytes; + SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) : + header (header_), bytes (bytes_) {} - const char *glyph_end = glyph + glyph_length; - if (glyph_header.is_composite_glyph ()) - /* Trimming for composites not implemented. - * If removing hints it falls out of that. */ - return true; - else + unsigned int instruction_len_offset () const + { return GlyphHeader::static_size + 2 * header.numberOfContours; } + + unsigned int length (unsigned int instruction_len) const + { return instruction_len_offset () + 2 + instruction_len; } + + unsigned int instructions_length () const + { + unsigned int instruction_length_offset = instruction_len_offset (); + if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0; + + const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset); + /* Out of bounds of the current glyph */ + if (unlikely (length (instructionLength) > bytes.length)) return 0; + return instructionLength; + } + + enum simple_glyph_flag_t { + FLAG_ON_CURVE = 0x01, + FLAG_X_SHORT = 0x02, + FLAG_Y_SHORT = 0x04, + FLAG_REPEAT = 0x08, + FLAG_X_SAME = 0x10, + FLAG_Y_SAME = 0x20, + FLAG_RESERVED1 = 0x40, + FLAG_RESERVED2 = 0x80 + }; + + const Glyph trim_padding () const + { + /* based on FontTools _g_l_y_f.py::trim */ + const char *glyph = bytes.arrayZ; + const char *glyph_end = glyph + bytes.length; /* simple glyph w/contours, possibly trimmable */ - glyph += glyph_header.simple_instruction_len_offset (); + glyph += instruction_len_offset (); - if (unlikely (glyph + 2 >= glyph_end)) return false; - uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16> (glyph - 2, 0) + 1; - uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16> (glyph, 0); + if (unlikely (glyph + 2 >= glyph_end)) return Glyph (); + unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1; + unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0); - glyph += 2 + nInstructions; - if (unlikely (glyph + 2 >= glyph_end)) return false; + glyph += 2 + num_instructions; + if (unlikely (glyph + 2 >= glyph_end)) return Glyph (); - unsigned int coordBytes = 0; - unsigned int coordsWithFlags = 0; + unsigned int coord_bytes = 0; + unsigned int coords_with_flags = 0; while (glyph < glyph_end) { - uint8_t flag = (uint8_t) *glyph; + uint8_t flag = *glyph; glyph++; unsigned int repeat = 1; if (flag & FLAG_REPEAT) { - if (glyph >= glyph_end) - { - DEBUG_MSG (SUBSET, nullptr, "Bad flag"); - return false; - } - repeat = ((uint8_t) *glyph) + 1; + if (unlikely (glyph >= glyph_end)) return Glyph (); + repeat = *glyph + 1; glyph++; } @@ -510,141 +496,553 @@ struct glyf if (flag & FLAG_Y_SHORT) yBytes = 1; else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2; - coordBytes += (xBytes + yBytes) * repeat; - coordsWithFlags += repeat; - if (coordsWithFlags >= nCoordinates) - break; + coord_bytes += (xBytes + yBytes) * repeat; + coords_with_flags += repeat; + if (coords_with_flags >= num_coordinates) break; } - if (coordsWithFlags != nCoordinates) + if (unlikely (coords_with_flags != num_coordinates)) return Glyph (); + return Glyph (bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph))); + } + + /* zero instruction length */ + void drop_hints () + { + GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header); + (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0; + } + + void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const + { + unsigned int instructions_len = instructions_length (); + unsigned int glyph_length = length (instructions_len); + dest_start = bytes.sub_array (0, glyph_length - instructions_len); + dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length); + } + + struct x_setter_t + { + void set (contour_point_t &point, float v) const { point.x = v; } + bool is_short (uint8_t flag) const { return flag & FLAG_X_SHORT; } + bool is_same (uint8_t flag) const { return flag & FLAG_X_SAME; } + }; + + struct y_setter_t + { + void set (contour_point_t &point, float v) const { point.y = v; } + bool is_short (uint8_t flag) const { return flag & FLAG_Y_SHORT; } + bool is_same (uint8_t flag) const { return flag & FLAG_Y_SAME; } + }; + + template <typename T> + static bool read_points (const HBUINT8 *&p /* IN/OUT */, + contour_point_vector_t &points_ /* IN/OUT */, + const range_checker_t &checker) + { + T coord_setter; + float v = 0; + for (unsigned int i = 0; i < points_.length - PHANTOM_COUNT; i++) { - DEBUG_MSG (SUBSET, nullptr, "Expect %d coords to have flags, got flags for %d", - nCoordinates, coordsWithFlags); - return false; + uint8_t flag = points_[i].flag; + if (coord_setter.is_short (flag)) + { + if (unlikely (!checker.in_range (p))) return false; + if (coord_setter.is_same (flag)) + v += *p++; + else + v -= *p++; + } + else + { + if (!coord_setter.is_same (flag)) + { + if (unlikely (!checker.in_range ((const HBUINT16 *) p))) return false; + v += *(const HBINT16 *) p; + p += HBINT16::static_size; + } + } + coord_setter.set (points_[i], v); } - glyph += coordBytes; + return true; + } + + bool get_contour_points (contour_point_vector_t &points_ /* OUT */, + hb_vector_t<unsigned int> &end_points_ /* OUT */, + const bool phantom_only=false) const + { + const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header); + range_checker_t checker (bytes.arrayZ, bytes.length); + int num_contours = header.numberOfContours; + if (unlikely (!checker.in_range (&endPtsOfContours[num_contours + 1]))) return false; + unsigned int num_points = endPtsOfContours[num_contours - 1] + 1; + + points_.resize (num_points + PHANTOM_COUNT); + for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); + if (phantom_only) return true; - if (glyph < glyph_end) - *end_offset -= glyph_end - glyph; + /* Read simple glyph points if !phantom_only */ + end_points_.resize (num_contours); + + for (int i = 0; i < num_contours; i++) + end_points_[i] = endPtsOfContours[i]; + + /* Skip instructions */ + const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1], + endPtsOfContours[num_contours]); + + /* Read flags */ + for (unsigned int i = 0; i < num_points; i++) + { + if (unlikely (!checker.in_range (p))) return false; + uint8_t flag = *p++; + points_[i].flag = flag; + if (flag & FLAG_REPEAT) + { + if (unlikely (!checker.in_range (p))) return false; + unsigned int repeat_count = *p++; + while ((repeat_count-- > 0) && (++i < num_points)) + points_[i].flag = flag; + } + } + + /* Read x & y coordinates */ + return (read_points<x_setter_t> (p, points_, checker) && + read_points<y_setter_t> (p, points_, checker)); } - return true; - } + }; - bool get_offsets (hb_codepoint_t glyph, - unsigned int *start_offset /* OUT */, - unsigned int *end_offset /* OUT */) const + struct CompositeGlyph { - if (unlikely (glyph >= num_glyphs)) - return false; + const GlyphHeader &header; + hb_bytes_t bytes; + CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) : + header (header_), bytes (bytes_) {} - if (short_offset) + composite_iter_t get_iterator () const + { return composite_iter_t (bytes, &StructAfter<CompositeGlyphChain, GlyphHeader> (header)); } + + unsigned int instructions_length (hb_bytes_t bytes) const { - const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ; - *start_offset = 2 * offsets[glyph]; - *end_offset = 2 * offsets[glyph + 1]; + unsigned int start = bytes.length; + unsigned int end = bytes.length; + const CompositeGlyphChain *last = nullptr; + for (auto &item : get_iterator ()) + last = &item; + if (unlikely (!last)) return 0; + + if ((uint16_t) last->flags & CompositeGlyphChain::WE_HAVE_INSTRUCTIONS) + start = (char *) last - &bytes + last->get_size (); + if (unlikely (start > end)) return 0; + return end - start; } - else + + /* Trimming for composites not implemented. + * If removing hints it falls out of that. */ + const Glyph trim_padding () const { return Glyph (bytes); } + + /* remove WE_HAVE_INSTRUCTIONS flag from composite glyph */ + void drop_hints () { - const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ; + for (const auto &_ : get_iterator ()) + *const_cast<OT::HBUINT16 *> (&_.flags) = (uint16_t) _.flags & ~OT::glyf::CompositeGlyphChain::WE_HAVE_INSTRUCTIONS; + } + + /* Chop instructions off the end */ + void drop_hints_bytes (hb_bytes_t &dest_start) const + { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); } + + bool get_contour_points (contour_point_vector_t &points_ /* OUT */, + hb_vector_t<unsigned int> &end_points_ /* OUT */, + const bool phantom_only=false) const + { + /* add one pseudo point for each component in composite glyph */ + unsigned int num_points = hb_len (get_iterator ()); + points_.resize (num_points + PHANTOM_COUNT); + for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); + return true; + } + }; + + enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE }; - *start_offset = offsets[glyph]; - *end_offset = offsets[glyph + 1]; + enum phantom_point_index_t + { + PHANTOM_LEFT = 0, + PHANTOM_RIGHT = 1, + PHANTOM_TOP = 2, + PHANTOM_BOTTOM = 3, + PHANTOM_COUNT = 4 + }; + + public: + composite_iter_t get_composite_iterator () const + { + if (type != COMPOSITE) return composite_iter_t (); + return CompositeGlyph (*header, bytes).get_iterator (); + } + + const Glyph trim_padding () const + { + switch (type) { + case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding (); + case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding (); + default: return bytes; } + } - if (*start_offset > *end_offset || *end_offset > glyf_table.get_length ()) - return false; + void drop_hints () + { + switch (type) { + case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return; + case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return; + default: return; + } + } - return true; + void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const + { + switch (type) { + case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return; + case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return; + default: return; + } + } + + /* for a simple glyph, return contour end points, flags, along with coordinate points + * for a composite glyph, return pseudo component points + * in both cases points trailed with four phantom points + */ + bool get_contour_points (contour_point_vector_t &points_ /* OUT */, + hb_vector_t<unsigned int> &end_points_ /* OUT */, + const bool phantom_only=false) const + { + switch (type) { + case COMPOSITE: return CompositeGlyph (*header, bytes).get_contour_points (points_, end_points_, phantom_only); + case SIMPLE: return SimpleGlyph (*header, bytes).get_contour_points (points_, end_points_, phantom_only); + default: + /* empty glyph */ + points_.resize (PHANTOM_COUNT); + for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); + return true; + } } - bool get_instruction_length (hb_bytes_t glyph, - unsigned int * length /* OUT */) const + bool is_simple_glyph () const { return type == SIMPLE; } + bool is_composite_glyph () const { return type == COMPOSITE; } + + bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const { - const GlyphHeader &glyph_header = *glyph.as<GlyphHeader> (); - /* Empty glyph; no instructions. */ - if (!glyph_header.has_data ()) + if (type == EMPTY) return true; /* Empty glyph; zero extents. */ + return header->get_extents (font, gid, extents); + } + + hb_bytes_t get_bytes () const { return bytes; } + const GlyphHeader &get_header () const { return *header; } + + Glyph (hb_bytes_t bytes_ = hb_bytes_t ()) : + bytes (bytes_), header (bytes.as<GlyphHeader> ()) + { + int num_contours = header->numberOfContours; + if (unlikely (num_contours == 0)) type = EMPTY; + else if (num_contours > 0) type = SIMPLE; + else type = COMPOSITE; /* negative numbers */ + } + + protected: + hb_bytes_t bytes; + const GlyphHeader *header; + unsigned type; + }; + + struct accelerator_t + { + void init (hb_face_t *face_) + { + short_offset = false; + num_glyphs = 0; + loca_table = nullptr; + glyf_table = nullptr; + face = face_; + const OT::head &head = *face->table.head; + if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0) + /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ + return; + short_offset = 0 == head.indexToLocFormat; + + loca_table = hb_sanitize_context_t ().reference_table<loca> (face); + glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face); + + num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1; + } + + void fini () + { + loca_table.destroy (); + glyf_table.destroy (); + } + + enum phantom_point_index_t + { + PHANTOM_LEFT = 0, + PHANTOM_RIGHT = 1, + PHANTOM_TOP = 2, + PHANTOM_BOTTOM = 3, + PHANTOM_COUNT = 4 + }; + + protected: + + void init_phantom_points (hb_codepoint_t gid, hb_array_t<contour_point_t> &phantoms /* IN/OUT */) const + { + const Glyph &glyph = glyph_for_gid (gid); + int h_delta = (int) glyph.get_header ().xMin - face->table.hmtx->get_side_bearing (gid); + int v_orig = (int) glyph.get_header ().yMax + face->table.vmtx->get_side_bearing (gid); + unsigned int h_adv = face->table.hmtx->get_advance (gid); + unsigned int v_adv = face->table.vmtx->get_advance (gid); + + phantoms[PHANTOM_LEFT].x = h_delta; + phantoms[PHANTOM_RIGHT].x = h_adv + h_delta; + phantoms[PHANTOM_TOP].y = v_orig; + phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv; + } + + struct contour_bounds_t + { + contour_bounds_t () { min.x = min.y = FLT_MAX; max.x = max.y = -FLT_MAX; } + + void add (const contour_point_t &p) { - *length = 0; - // only 0 byte glyphs are healthy when missing GlyphHeader - return glyph.length == 0; + min.x = hb_min (min.x, p.x); + min.y = hb_min (min.y, p.y); + max.x = hb_max (max.x, p.x); + max.y = hb_max (max.y, p.y); } - if (glyph_header.is_composite_glyph ()) + + bool empty () const { return (min.x >= max.x) || (min.y >= max.y); } + + contour_point_t min; + contour_point_t max; + }; + +#ifndef HB_NO_VAR + /* Note: Recursively calls itself. + * all_points includes phantom points + */ + bool get_points_var (hb_codepoint_t gid, + const int *coords, unsigned int coord_count, + contour_point_vector_t &all_points /* OUT */, + unsigned int depth = 0) const + { + if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return false; + contour_point_vector_t points; + hb_vector_t<unsigned int> end_points; + const Glyph &glyph = glyph_for_gid (gid); + if (unlikely (!glyph.get_contour_points (points, end_points))) return false; + hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT); + init_phantom_points (gid, phantoms); + if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, coords, coord_count, points.as_array (), end_points.as_array ()))) return false; + + unsigned int comp_index = 0; + if (glyph.is_simple_glyph ()) + all_points.extend (points.as_array ()); + else if (glyph.is_composite_glyph ()) { - unsigned int start = glyph.length; - unsigned int end = glyph.length; - unsigned int glyph_offset = &glyph - glyf_table; - CompositeGlyphHeader::Iterator composite_it; - if (unlikely (!CompositeGlyphHeader::get_iterator (&glyph, glyph.length, - &composite_it))) - return false; - const CompositeGlyphHeader *last; - do + for (auto &item : glyph.get_composite_iterator ()) { - last = composite_it.current; - } while (composite_it.move_to_next ()); + contour_point_vector_t comp_points; + if (unlikely (!get_points_var (item.glyphIndex, coords, coord_count, + comp_points, depth)) + || comp_points.length < PHANTOM_COUNT) + return false; - if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS) - start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) - + last->get_size () - glyph_offset; - if (unlikely (start > end)) - { - DEBUG_MSG (SUBSET, nullptr, "Invalid instruction offset, %d is outside " - "%d byte buffer", start, glyph.length); - return false; + /* Copy phantom points from component if USE_MY_METRICS flag set */ + if (item.is_use_my_metrics ()) + for (unsigned int i = 0; i < PHANTOM_COUNT; i++) + phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; + + /* Apply component transformation & translation */ + item.transform_points (comp_points); + + /* Apply translatation from gvar */ + comp_points.translate (points[comp_index]); + + if (item.is_anchored ()) + { + unsigned int p1, p2; + item.get_anchor_points (p1, p2); + if (likely (p1 < all_points.length && p2 < comp_points.length)) + { + contour_point_t delta; + delta.init (all_points[p1].x - comp_points[p2].x, + all_points[p1].y - comp_points[p2].y); + + comp_points.translate (delta); + } + } + + all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT)); + + comp_index++; } - *length = end - start; + + all_points.extend (phantoms); } - else + else return false; + + return true; + } + + bool get_points_bearing_applied (hb_font_t *font, hb_codepoint_t gid, contour_point_vector_t &all_points) const + { + if (unlikely (!get_points_var (gid, font->coords, font->num_coords, all_points) || + all_points.length < PHANTOM_COUNT)) return false; + + /* Undocumented rasterizer behavior: + * Shift points horizontally by the updated left side bearing + */ + contour_point_t delta; + delta.init (-all_points[all_points.length - PHANTOM_COUNT + PHANTOM_LEFT].x, 0.f); + if (delta.x) all_points.translate (delta); + return true; + } + + protected: + + bool get_var_extents_and_phantoms (hb_font_t *font, hb_codepoint_t gid, + hb_glyph_extents_t *extents=nullptr /* OUT */, + contour_point_vector_t *phantoms=nullptr /* OUT */) const + { + contour_point_vector_t all_points; + if (!unlikely (get_points_bearing_applied (font, gid, all_points))) return false; + if (extents) { - unsigned int instruction_len_offset = glyph_header.simple_instruction_len_offset (); - if (unlikely (instruction_len_offset + 2 > glyph.length)) + contour_bounds_t bounds; + for (unsigned int i = 0; i + PHANTOM_COUNT < all_points.length; i++) + bounds.add (all_points[i]); + + if (bounds.min.x > bounds.max.x) { - DEBUG_MSG (SUBSET, nullptr, "Glyph size is too short, missing field " - "instructionLength."); - return false; + extents->width = 0; + extents->x_bearing = 0; } - - const HBUINT16 &instruction_len = StructAtOffset<HBUINT16> (&glyph, - instruction_len_offset); - /* Out of bounds of the current glyph */ - if (unlikely (glyph_header.simple_length (instruction_len) > glyph.length)) + else + { + extents->x_bearing = font->em_scalef_x (bounds.min.x); + extents->width = font->em_scalef_x (bounds.max.x - bounds.min.x); + } + if (bounds.min.y > bounds.max.y) + { + extents->height = 0; + extents->y_bearing = 0; + } + else { - DEBUG_MSG (SUBSET, nullptr, "The instructions array overruns the " - "glyph's boundaries."); - return false; + extents->y_bearing = font->em_scalef_y (bounds.max.y); + extents->height = font->em_scalef_y (bounds.min.y - bounds.max.y); } - *length = (uint16_t) instruction_len; } + if (phantoms) + for (unsigned int i = 0; i < PHANTOM_COUNT; i++) + (*phantoms)[i] = all_points[all_points.length - PHANTOM_COUNT + i]; return true; } - bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const + bool get_var_metrics (hb_font_t *font, hb_codepoint_t gid, + contour_point_vector_t &phantoms) const + { return get_var_extents_and_phantoms (font, gid, nullptr, &phantoms); } + + bool get_extents_var (hb_font_t *font, hb_codepoint_t gid, + hb_glyph_extents_t *extents) const + { return get_var_extents_and_phantoms (font, gid, extents); } +#endif + + public: +#ifndef HB_NO_VAR + unsigned int get_advance_var (hb_font_t *font, hb_codepoint_t gid, + bool is_vertical) const { - unsigned int start_offset, end_offset; - if (!get_offsets (glyph, &start_offset, &end_offset)) - return false; + bool success = false; + contour_point_vector_t phantoms; + phantoms.resize (PHANTOM_COUNT); - hb_bytes_t ((const char *) glyf_table + start_offset, - end_offset - start_offset).as<GlyphHeader> ()->get_extents (extents); - return true; + if (likely (font->num_coords == face->table.gvar->get_axis_count ())) + success = get_var_metrics (font, gid, phantoms); + + if (unlikely (!success)) + return is_vertical ? face->table.vmtx->get_advance (gid) : face->table.hmtx->get_advance (gid); + + if (is_vertical) + return roundf (phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y); + else + return roundf (phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x); } - hb_bytes_t bytes_for_glyph (const char *glyf, hb_codepoint_t gid) + int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const + { + hb_glyph_extents_t extents; + contour_point_vector_t phantoms; + phantoms.resize (PHANTOM_COUNT); + + if (unlikely (!get_var_extents_and_phantoms (font, gid, &extents, &phantoms))) + return is_vertical ? face->table.vmtx->get_side_bearing (gid) : face->table.hmtx->get_side_bearing (gid); + + return is_vertical ? ceil (phantoms[PHANTOM_TOP].y) - extents.y_bearing : floor (phantoms[PHANTOM_LEFT].x); + } +#endif + + bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const + { +#ifndef HB_NO_VAR + unsigned int coord_count; + const int *coords = hb_font_get_var_coords_normalized (font, &coord_count); + if (coords && coord_count > 0 && coord_count == face->table.gvar->get_axis_count ()) + return get_extents_var (font, gid, extents); +#endif + + if (unlikely (gid >= num_glyphs)) return false; + + return glyph_for_gid (gid).get_extents (font, gid, extents); + } + + const Glyph + glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const { unsigned int start_offset, end_offset; - if (unlikely (!(get_offsets (gid, &start_offset, &end_offset) && - remove_padding (start_offset, &end_offset)))) + if (unlikely (gid >= num_glyphs)) return Glyph (); + + if (short_offset) { - DEBUG_MSG (SUBSET, nullptr, "Unable to get offset or remove padding for %d", gid); - return hb_bytes_t (); + const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ; + start_offset = 2 * offsets[gid]; + end_offset = 2 * offsets[gid + 1]; } - hb_bytes_t glyph_bytes = hb_bytes_t (glyf + start_offset, end_offset - start_offset); - if (!glyph_bytes.as<GlyphHeader> ()->has_data ()) + else { - DEBUG_MSG (SUBSET, nullptr, "Empty or invalid glyph size, %d", gid); - return hb_bytes_t (); + const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ; + start_offset = offsets[gid]; + end_offset = offsets[gid + 1]; } - return glyph_bytes; + + if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ())) + return Glyph (); + + Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset, + end_offset - start_offset)); + return needs_padding_removal ? glyph.trim_padding () : glyph; + } + + void + add_gid_and_children (hb_codepoint_t gid, hb_set_t *gids_to_retain, + unsigned int depth = 0) const + { + if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return; + /* Check if is already visited */ + if (gids_to_retain->has (gid)) return; + + gids_to_retain->add (gid); + + for (auto &item : glyph_for_gid (gid).get_composite_iterator ()) + add_gid_and_children (item.glyphIndex, gids_to_retain, depth); } private: @@ -652,13 +1050,14 @@ struct glyf unsigned int num_glyphs; hb_blob_ptr_t<loca> loca_table; hb_blob_ptr_t<glyf> glyf_table; + hb_face_t *face; }; struct SubsetGlyph { hb_codepoint_t new_gid; hb_codepoint_t old_gid; - hb_bytes_t source_glyph; + Glyph source_glyph; hb_bytes_t dest_start; /* region of source_glyph to copy first */ hb_bytes_t dest_end; /* region of source_glyph to copy second */ @@ -670,8 +1069,7 @@ struct glyf hb_bytes_t dest_glyph = dest_start.copy (c); dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length); unsigned int pad_length = padding (); - DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", - dest_glyph.length, dest_glyph.length + pad_length, pad_length); + DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length); HBUINT8 pad; pad = 0; @@ -681,56 +1079,27 @@ struct glyf pad_length--; } - if (dest_glyph.length) + if (!unlikely (dest_glyph.length)) return_trace (true); + + /* update components gids */ + for (auto &_ : Glyph (dest_glyph).get_composite_iterator ()) { - _fix_component_gids (plan, dest_glyph); - if (plan->drop_hints) - { - _zero_instruction_length (dest_glyph); - c->check_success (_remove_composite_instruction_flag (dest_glyph)); - } + hb_codepoint_t new_gid; + if (plan->new_gid_for_old_gid (_.glyphIndex, &new_gid)) + ((OT::glyf::CompositeGlyphChain *) &_)->glyphIndex = new_gid; } + if (plan->drop_hints) Glyph (dest_glyph).drop_hints (); + return_trace (true); } - void drop_hints (const OT::glyf::accelerator_t& glyf) - { - if (source_glyph.length == 0) return; - - unsigned int instruction_len = 0; - if (!glyf.get_instruction_length (source_glyph, &instruction_len)) - { - DEBUG_MSG (SUBSET, nullptr, "Unable to read instruction length for new_gid %d", - new_gid); - return ; - } - - const GlyphHeader& header = *source_glyph.as<GlyphHeader> (); - DEBUG_MSG (SUBSET, nullptr, "new_gid %d drop %d instruction bytes " - "from %d byte source glyph", - new_gid, instruction_len, source_glyph.length); - if (header.is_composite_glyph ()) - { - /* just chop instructions off the end for composite glyphs */ - dest_start = hb_bytes_t (&source_glyph, source_glyph.length - instruction_len); - } - else - { - unsigned int glyph_length = header.simple_length (instruction_len); - dest_start = hb_bytes_t (&source_glyph, glyph_length - instruction_len); - dest_end = hb_bytes_t (&source_glyph + glyph_length, - source_glyph.length - glyph_length); - DEBUG_MSG (SUBSET, nullptr, "source_len %d start len %d glyph_len %d " - "instruction_len %d end len %d", - source_glyph.length, dest_start.length, glyph_length, - instruction_len, dest_end.length); - } - } + void drop_hints_bytes () + { source_glyph.drop_hints_bytes (dest_start, dest_end); } - unsigned int length () const { return dest_start.length + dest_end.length; } + unsigned int length () const { return dest_start.length + dest_end.length; } /* pad to 2 to ensure 2-byte loca will be ok */ - unsigned int padding () const { return length () % 2; } + unsigned int padding () const { return length () % 2; } unsigned int padded_size () const { return length () + padding (); } }; 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 6b2cc866265..e20b3726226 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 @@ -42,6 +42,13 @@ #define HB_OT_TAG_vmtx HB_TAG('v','m','t','x') +HB_INTERNAL int +_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical); + +HB_INTERNAL unsigned +_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical); + + namespace OT { @@ -53,6 +60,7 @@ struct LongMetric DEFINE_SIZE_STATIC (4); }; + template <typename T, typename H> struct hmtxvmtx { @@ -128,13 +136,12 @@ struct hmtxvmtx auto it = + hb_range (c->plan->num_output_glyphs ()) | hb_map ([c, &_mtx] (unsigned _) - { - hb_codepoint_t old_gid; - if (c->plan->old_gid_for_new_gid (_, &old_gid)) - return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid)); - else - return hb_pair (0u, 0u); - }) + { + hb_codepoint_t old_gid; + if (!c->plan->old_gid_for_new_gid (_, &old_gid)) + return hb_pair (0u, 0); + return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid)); + }) ; table_prime->serialize (c->serializer, it, num_advances); @@ -146,9 +153,7 @@ struct hmtxvmtx // Amend header num hmetrics if (unlikely (!subset_update_header (c->plan, num_advances))) - { return_trace (false); - } return_trace (true); } @@ -190,8 +195,7 @@ struct hmtxvmtx var_table.destroy (); } - /* TODO Add variations version. */ - unsigned int get_side_bearing (hb_codepoint_t glyph) const + int get_side_bearing (hb_codepoint_t glyph) const { if (glyph < num_advances) return table->longMetricZ[glyph].sb; @@ -203,6 +207,23 @@ struct hmtxvmtx return bearings[glyph - num_advances]; } + int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const + { + int side_bearing = get_side_bearing (glyph); + +#ifndef HB_NO_VAR + if (unlikely (glyph >= num_metrics) || !font->num_coords) + return side_bearing; + + if (var_table.get_length ()) + return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?! + + return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); +#else + return side_bearing; +#endif + } + unsigned int get_advance (hb_codepoint_t glyph) const { if (unlikely (glyph >= num_metrics)) @@ -223,11 +244,18 @@ struct hmtxvmtx hb_font_t *font) const { unsigned int advance = get_advance (glyph); - if (likely (glyph < num_metrics)) - { - advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?! - } + +#ifndef HB_NO_VAR + if (unlikely (glyph >= num_metrics) || !font->num_coords) + return advance; + + if (var_table.get_length ()) + return advance + roundf (var_table->get_advance_var (font, glyph)); // TODO Optimize?! + + return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); +#else return advance; +#endif } unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh index 7dfb207b2dc..36e5a358e6a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh @@ -167,8 +167,8 @@ struct KernOTSubTableHeader static constexpr bool apple = false; typedef AAT::ObsoleteTypes Types; - unsigned int tuple_count () const { return 0; } - bool is_horizontal () const { return (coverage & Horizontal); } + unsigned tuple_count () const { return 0; } + bool is_horizontal () const { return (coverage & Horizontal); } enum Coverage { @@ -222,8 +222,8 @@ struct KernAATSubTableHeader static constexpr bool apple = true; typedef AAT::ObsoleteTypes Types; - unsigned int tuple_count () const { return 0; } - bool is_horizontal () const { return !(coverage & Vertical); } + unsigned tuple_count () const { return 0; } + bool is_horizontal () const { return !(coverage & Vertical); } enum Coverage { @@ -275,8 +275,8 @@ struct kern { static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; - bool has_data () const { return u.version32; } - unsigned int get_type () const { return u.major; } + bool has_data () const { return u.version32; } + unsigned get_type () const { return u.major; } bool has_state_machine () const { 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 73c28caabd5..fa08140f565 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 @@ -33,6 +33,7 @@ #include "hb-ot-layout.hh" #include "hb-open-type.hh" #include "hb-set.hh" +#include "hb-bimap.hh" #ifndef HB_MAX_NESTING_LEVEL @@ -66,6 +67,76 @@ namespace OT { #define NOT_COVERED ((unsigned int) -1) +template<typename Iterator> +static inline void Coverage_serialize (hb_serialize_context_t *c, + Iterator it); + +template<typename Iterator> +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, + hb_sorted_vector_t<unsigned> klasses, + hb_map_t *klass_map /*INOUT*/); + + +template<typename OutputArray> +struct subset_offset_array_t +{ + subset_offset_array_t + (hb_subset_context_t *subset_context, + OutputArray& out, + const void *src_base, + const void *dest_base) + : _subset_context(subset_context), _out (out), _src_base (src_base), _dest_base (dest_base) {} + + template <typename T> + bool + operator () + (T&& offset) + { + auto *o = _out.serialize_append (_subset_context->serializer); + if (unlikely (!o)) return false; + auto snap = _subset_context->serializer->snapshot (); + bool ret = o->serialize_subset (_subset_context, offset, _src_base, _dest_base); + if (!ret) + { + _out.pop (); + _subset_context->serializer->revert (snap); + } + return ret; + } + + private: + hb_subset_context_t *_subset_context; + OutputArray &_out; + const void *_src_base; + const void *_dest_base; +}; + +/* + * Helper to subset an array of offsets. Subsets the thing pointed to by each offset + * and discards the offset in the array if the subset operation results in an empty + * thing. + */ +struct +{ + template<typename OutputArray> + subset_offset_array_t<OutputArray> + operator () + (hb_subset_context_t *subset_context, + OutputArray& out, + const void *src_base, + const void *dest_base) const + { + return subset_offset_array_t<OutputArray> (subset_context, out, src_base, dest_base); + } +} +HB_FUNCOBJ (subset_offset_array); + /* * * OpenType Layout Common Table Formats @@ -82,6 +153,26 @@ struct Record_sanitize_closure_t { const void *list_base; }; +struct RecordList_subset_context_t { + + RecordList_subset_context_t() : script_count (0), langsys_count (0) + {} + + bool visitScript () + { + return script_count++ < HB_MAX_SCRIPTS; + } + + bool visitLangSys () + { + return langsys_count++ < HB_MAX_LANGSYS; + } + + private: + unsigned int script_count; + unsigned int langsys_count; +}; + template <typename Type> struct Record { @@ -138,11 +229,26 @@ struct RecordListOf : RecordArrayOf<Type> bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - auto *out = c->serializer->embed (*this); - if (unlikely (!out)) return_trace (false); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + RecordList_subset_context_t record_list_context; + unsigned int count = this->len; for (unsigned int i = 0; i < count; i++) - out->get_offset (i).serialize_subset (c, this->get_offset (i), this, out); + { + auto *record = out->serialize_append (c->serializer); + if (unlikely (!record)) return false; + auto snap = c->serializer->snapshot (); + if (record->offset.serialize_subset (c, this->get_offset (i), this, out, &record_list_context)) + { + record->tag = this->get_tag(i); + continue; + } + out->pop (); + c->serializer->revert (snap); + } + return_trace (true); } @@ -207,7 +313,6 @@ struct Script; struct LangSys; struct Feature; - struct LangSys { unsigned int get_feature_count () const @@ -274,15 +379,33 @@ struct Script bool has_default_lang_sys () const { return defaultLangSys != 0; } const LangSys& get_default_lang_sys () const { return this+defaultLangSys; } - bool subset (hb_subset_context_t *c) const + bool subset (hb_subset_context_t *c, RecordList_subset_context_t *record_list_context) const { TRACE_SUBSET (this); - auto *out = c->serializer->embed (*this); - if (unlikely (!out)) return_trace (false); + if (!record_list_context->visitScript ()) return_trace (false); + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->defaultLangSys.serialize_copy (c->serializer, defaultLangSys, this, out); - unsigned int count = langSys.len; - for (unsigned int i = 0; i < count; i++) - out->langSys.arrayZ[i].offset.serialize_copy (c->serializer, langSys[i].offset, this, out); + + for (const auto &src: langSys) + { + if (!record_list_context->visitLangSys ()) { + continue; + } + + auto snap = c->serializer->snapshot (); + auto *lang_sys = c->serializer->embed (src); + + if (likely(lang_sys) + && lang_sys->offset.serialize_copy (c->serializer, src.offset, this, out)) + { + out->langSys.len++; + continue; + } + c->serializer->revert (snap); + } return_trace (true); } @@ -559,7 +682,7 @@ struct Feature const FeatureParams &get_feature_params () const { return this+featureParams; } - bool subset (hb_subset_context_t *c) const + bool subset (hb_subset_context_t *c, RecordList_subset_context_t *r) const { TRACE_SUBSET (this); auto *out = c->serializer->embed (*this); @@ -1072,6 +1195,23 @@ struct Coverage } } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto it = + + iter () + | hb_filter (glyphset) + | hb_map_retains_sorting (glyph_map) + ; + + bool ret = bool (it); + Coverage_serialize (c->serializer, it); + return_trace (ret); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1190,15 +1330,51 @@ struct Coverage DEFINE_SIZE_UNION (2, format); }; +template<typename Iterator> +static inline void +Coverage_serialize (hb_serialize_context_t *c, + Iterator it) +{ 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, + hb_sorted_vector_t<unsigned> klasses, + hb_map_t *klass_map /*INOUT*/) +{ + bool has_no_match = glyphset.get_population () > gid_klass_map.get_population (); + + hb_map_t m; + if (!klass_map) klass_map = &m; + + if (has_no_match) klass_map->set (0, 0); + unsigned idx = klass_map->has (0) ? 1 : 0; + for (const unsigned k: klasses.iter ()) + { + if (klass_map->has (k)) continue; + klass_map->set (k, idx); + idx++; + } + + auto it = + + glyphs.iter () + | hb_map_retains_sorting ([&] (const HBGlyphID& gid) -> hb_pair_t<hb_codepoint_t, HBUINT16> + { + HBUINT16 new_klass; + new_klass = klass_map->get (gid_klass_map[gid]); + return hb_pair ((hb_codepoint_t)gid, new_klass); + }) + ; + + c->propagate_error (glyphs, klasses); + ClassDef_serialize (c, it); +} /* * Class Definition Table */ -static inline void ClassDef_serialize (hb_serialize_context_t *c, - hb_array_t<const HBGlyphID> glyphs, - hb_array_t<const HBUINT16> klasses); - struct ClassDefFormat1 { friend struct ClassDef; @@ -1209,53 +1385,53 @@ struct ClassDefFormat1 return classValue[(unsigned int) (glyph_id - startGlyph)]; } + template<typename Iterator, + hb_requires (hb_is_iterator (Iterator))> bool serialize (hb_serialize_context_t *c, - hb_array_t<const HBGlyphID> glyphs, - hb_array_t<const HBUINT16> klasses) + Iterator it) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!glyphs)) + if (unlikely (!it)) { startGlyph = 0; classValue.len = 0; return_trace (true); } - hb_codepoint_t glyph_min = +glyphs | hb_reduce (hb_min, 0xFFFFu); - hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u); - - startGlyph = glyph_min; - c->check_assign (classValue.len, glyph_max - glyph_min + 1); - if (unlikely (!c->extend (classValue))) return_trace (false); - - for (unsigned int i = 0; i < glyphs.length; i++) - classValue[glyphs[i] - glyph_min] = klasses[i]; - + startGlyph = (*it).first; + classValue.serialize (c, + it + | hb_map (hb_second)); return_trace (true); } - bool subset (hb_subset_context_t *c) const + bool subset (hb_subset_context_t *c, + hb_map_t *klass_map = nullptr /*OUT*/) const { TRACE_SUBSET (this); const hb_set_t &glyphset = *c->plan->glyphset (); const hb_map_t &glyph_map = *c->plan->glyph_map; + hb_sorted_vector_t<HBGlyphID> glyphs; - hb_vector_t<HBUINT16> klasses; + hb_sorted_vector_t<unsigned> orig_klasses; + hb_map_t gid_org_klass_map; hb_codepoint_t start = startGlyph; hb_codepoint_t end = start + classValue.len; - for (hb_codepoint_t g = start; g < end; g++) + for (const hb_codepoint_t gid : + hb_range (start, end) + | hb_filter (glyphset)) { - if (!glyphset.has (g)) continue; - unsigned int value = classValue[g - start]; - if (!value) continue; - glyphs.push(glyph_map[g]); - klasses.push(value); + unsigned klass = classValue[gid - start]; + if (!klass) continue; + + glyphs.push (glyph_map[gid]); + gid_org_klass_map.set (glyph_map[gid], klass); + orig_klasses.push (klass); } - c->serializer->propagate_error (glyphs, klasses); - ClassDef_serialize (c->serializer, glyphs, klasses); + + ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map, + glyphs, orig_klasses, klass_map); return_trace ((bool) glyphs); } @@ -1345,70 +1521,89 @@ struct ClassDefFormat2 return rangeRecord.bsearch (glyph_id).value; } + template<typename Iterator, + hb_requires (hb_is_iterator (Iterator))> bool serialize (hb_serialize_context_t *c, - hb_array_t<const HBGlyphID> glyphs, - hb_array_t<const HBUINT16> klasses) + Iterator it) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!glyphs)) + if (unlikely (!it)) { rangeRecord.len = 0; return_trace (true); } - unsigned int count = glyphs.len (); - unsigned int num_ranges = 1; - for (unsigned int i = 1; i < count; i++) - if (glyphs[i - 1] + 1 != glyphs[i] || - klasses[i - 1] != klasses[i]) - num_ranges++; - rangeRecord.len = num_ranges; - if (unlikely (!c->extend (rangeRecord))) return_trace (false); + unsigned num_ranges = 1; + hb_codepoint_t prev_gid = (*it).first; + unsigned prev_klass = (*it).second; - unsigned int range = 0; - rangeRecord[range].start = glyphs[0]; - rangeRecord[range].value = klasses[0]; - for (unsigned int i = 1; i < count; i++) + RangeRecord range_rec; + range_rec.start = prev_gid; + range_rec.end = prev_gid; + range_rec.value = prev_klass; + + RangeRecord *record = c->copy (range_rec); + if (unlikely (!record)) return_trace (false); + + for (const auto gid_klass_pair : + (++it)) { - if (glyphs[i - 1] + 1 != glyphs[i] || - klasses[i - 1] != klasses[i]) + hb_codepoint_t cur_gid = gid_klass_pair.first; + unsigned cur_klass = gid_klass_pair.second; + + if (cur_gid != prev_gid + 1 || + cur_klass != prev_klass) { - rangeRecord[range].end = glyphs[i - 1]; - range++; - rangeRecord[range].start = glyphs[i]; - rangeRecord[range].value = klasses[i]; + if (unlikely (!record)) break; + record->end = prev_gid; + num_ranges++; + + range_rec.start = cur_gid; + range_rec.end = cur_gid; + range_rec.value = cur_klass; + + record = c->copy (range_rec); } + + prev_klass = cur_klass; + prev_gid = cur_gid; } - rangeRecord[range].end = glyphs[count - 1]; + + if (likely (record)) record->end = prev_gid; + rangeRecord.len = num_ranges; return_trace (true); } - bool subset (hb_subset_context_t *c) const + bool subset (hb_subset_context_t *c, + hb_map_t *klass_map = nullptr /*OUT*/) const { TRACE_SUBSET (this); const hb_set_t &glyphset = *c->plan->glyphset (); const hb_map_t &glyph_map = *c->plan->glyph_map; - hb_vector_t<HBGlyphID> glyphs; - hb_vector_t<HBUINT16> klasses; - unsigned int count = rangeRecord.len; - for (unsigned int i = 0; i < count; i++) + hb_sorted_vector_t<HBGlyphID> glyphs; + hb_sorted_vector_t<unsigned> orig_klasses; + hb_map_t gid_org_klass_map; + + unsigned count = rangeRecord.len; + for (unsigned i = 0; i < count; i++) { - unsigned int value = rangeRecord[i].value; - if (!value) continue; + unsigned klass = rangeRecord[i].value; + if (!klass) continue; hb_codepoint_t start = rangeRecord[i].start; hb_codepoint_t end = rangeRecord[i].end + 1; for (hb_codepoint_t g = start; g < end; g++) { if (!glyphset.has (g)) continue; glyphs.push (glyph_map[g]); - klasses.push (value); + gid_org_klass_map.set (glyph_map[g], klass); + orig_klasses.push (klass); } } - c->serializer->propagate_error (glyphs, klasses); - ClassDef_serialize (c->serializer, glyphs, klasses); + + ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map, + glyphs, orig_klasses, klass_map); return_trace ((bool) glyphs); } @@ -1505,25 +1700,36 @@ struct ClassDef } } - bool serialize (hb_serialize_context_t *c, - hb_array_t<const HBGlyphID> glyphs, - hb_array_t<const HBUINT16> klasses) + template<typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + bool serialize (hb_serialize_context_t *c, Iterator it) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - unsigned int format = 2; - if (likely (glyphs)) + unsigned format = 2; + if (likely (it)) { - hb_codepoint_t glyph_min = +glyphs | hb_reduce (hb_min, 0xFFFFu); - hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u); + hb_codepoint_t glyph_min = (*it).first; + hb_codepoint_t glyph_max = + it + | hb_map (hb_first) + | hb_reduce (hb_max, 0u); - unsigned int count = glyphs.len (); - unsigned int num_ranges = 1; - for (unsigned int i = 1; i < count; i++) - if (glyphs[i - 1] + 1 != glyphs[i] || - klasses[i - 1] != klasses[i]) - num_ranges++; + unsigned num_ranges = 1; + hb_codepoint_t prev_gid = glyph_min; + unsigned prev_klass = (*it).second; + + for (const auto gid_klass_pair : it) + { + hb_codepoint_t cur_gid = gid_klass_pair.first; + unsigned cur_klass = gid_klass_pair.second; + if (cur_gid != prev_gid + 1 || + cur_klass != prev_klass) + num_ranges++; + + prev_gid = cur_gid; + prev_klass = cur_klass; + } if (1 + (glyph_max - glyph_min + 1) < num_ranges * 3) format = 1; @@ -1532,18 +1738,19 @@ struct ClassDef switch (u.format) { - case 1: return_trace (u.format1.serialize (c, glyphs, klasses)); - case 2: return_trace (u.format2.serialize (c, glyphs, klasses)); + case 1: return_trace (u.format1.serialize (c, it)); + case 2: return_trace (u.format2.serialize (c, it)); default:return_trace (false); } } - bool subset (hb_subset_context_t *c) const + bool subset (hb_subset_context_t *c, + hb_map_t *klass_map = nullptr /*OUT*/) const { TRACE_SUBSET (this); switch (u.format) { - case 1: return_trace (u.format1.subset (c)); - case 2: return_trace (u.format2.subset (c)); + case 1: return_trace (u.format1.subset (c, klass_map)); + case 2: return_trace (u.format2.subset (c, klass_map)); default:return_trace (false); } } @@ -1610,10 +1817,10 @@ struct ClassDef DEFINE_SIZE_UNION (2, format); }; +template<typename Iterator> static inline void ClassDef_serialize (hb_serialize_context_t *c, - hb_array_t<const HBGlyphID> glyphs, - hb_array_t<const HBUINT16> klasses) -{ c->start_embed<ClassDef> ()->serialize (c, glyphs, klasses); } + Iterator it) +{ c->start_embed<ClassDef> ()->serialize (c, it); } /* @@ -1691,6 +1898,21 @@ struct VarRegionList axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount)); } + bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_bimap_t ®ion_map) + { + TRACE_SERIALIZE (this); + VarRegionList *out = c->allocate_min<VarRegionList> (); + if (unlikely (!out)) return_trace (false); + axisCount = src->axisCount; + regionCount = region_map.get_population (); + if (unlikely (!c->allocate_size<VarRegionList> (get_size () - min_size))) return_trace (false); + for (unsigned int r = 0; r < regionCount; r++) + memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * region_map.backward (r)], VarRegionAxis::static_size * axisCount); + + return_trace (true); + } + + unsigned int get_size () const { return min_size + VarRegionAxis::static_size * axisCount * regionCount; } unsigned int get_region_count () const { return regionCount; } protected: @@ -1723,7 +1945,7 @@ struct VarData unsigned int count = regionIndices.len; unsigned int scount = shortCount; - const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices); + const HBUINT8 *bytes = get_delta_bytes (); const HBUINT8 *row = bytes + inner * (scount + count); float delta = 0.; @@ -1763,11 +1985,117 @@ struct VarData return_trace (c->check_struct (this) && regionIndices.sanitize (c) && shortCount <= regionIndices.len && - c->check_range (&StructAfter<HBUINT8> (regionIndices), + c->check_range (get_delta_bytes (), itemCount, get_row_size ())); } + bool serialize (hb_serialize_context_t *c, + const VarData *src, + const hb_inc_bimap_t &inner_map, + const hb_bimap_t ®ion_map) + { + TRACE_SERIALIZE (this); + if (unlikely (!c->extend_min (*this))) return_trace (false); + itemCount = inner_map.get_next_value (); + + /* Optimize short count */ + unsigned short ri_count = src->regionIndices.len; + enum delta_size_t { kZero=0, kByte, kShort }; + hb_vector_t<delta_size_t> delta_sz; + hb_vector_t<unsigned int> ri_map; /* maps old index to new index */ + delta_sz.resize (ri_count); + ri_map.resize (ri_count); + unsigned int new_short_count = 0; + unsigned int r; + for (r = 0; r < ri_count; r++) + { + delta_sz[r] = kZero; + for (unsigned int i = 0; i < inner_map.get_next_value (); i++) + { + unsigned int old = inner_map.backward (i); + int16_t delta = src->get_item_delta (old, r); + if (delta < -128 || 127 < delta) + { + delta_sz[r] = kShort; + new_short_count++; + break; + } + else if (delta != 0) + delta_sz[r] = kByte; + } + } + unsigned int short_index = 0; + unsigned int byte_index = new_short_count; + unsigned int new_ri_count = 0; + for (r = 0; r < ri_count; r++) + if (delta_sz[r]) + { + ri_map[r] = (delta_sz[r] == kShort)? short_index++ : byte_index++; + new_ri_count++; + } + + shortCount = new_short_count; + regionIndices.len = new_ri_count; + + unsigned int size = regionIndices.get_size () - HBUINT16::static_size/*regionIndices.len*/ + (get_row_size () * itemCount); + if (unlikely (!c->allocate_size<HBUINT8> (size))) + return_trace (false); + + for (r = 0; r < ri_count; r++) + if (delta_sz[r]) regionIndices[ri_map[r]] = region_map[src->regionIndices[r]]; + + for (unsigned int i = 0; i < itemCount; i++) + { + unsigned int old = inner_map.backward (i); + for (unsigned int r = 0; r < ri_count; r++) + if (delta_sz[r]) set_item_delta (i, ri_map[r], src->get_item_delta (old, r)); + } + + return_trace (true); + } + + void collect_region_refs (hb_inc_bimap_t ®ion_map, const hb_inc_bimap_t &inner_map) const + { + for (unsigned int r = 0; r < regionIndices.len; r++) + { + unsigned int region = regionIndices[r]; + if (region_map.has (region)) continue; + for (unsigned int i = 0; i < inner_map.get_next_value (); i++) + if (get_item_delta (inner_map.backward (i), r) != 0) + { + region_map.add (region); + break; + } + } + } + + protected: + const HBUINT8 *get_delta_bytes () const + { return &StructAfter<HBUINT8> (regionIndices); } + + HBUINT8 *get_delta_bytes () + { return &StructAfter<HBUINT8> (regionIndices); } + + int16_t get_item_delta (unsigned int item, unsigned int region) const + { + if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0; + const HBINT8 *p = (const HBINT8 *)get_delta_bytes () + item * get_row_size (); + if (region < shortCount) + return ((const HBINT16 *)p)[region]; + else + return (p + HBINT16::static_size * shortCount)[region - shortCount]; + } + + void set_item_delta (unsigned int item, unsigned int region, int16_t delta) + { + HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size (); + if (region < shortCount) + ((HBINT16 *)p)[region] = delta; + else + (p + HBINT16::static_size * shortCount)[region - shortCount] = delta; + } + protected: HBUINT16 itemCount; HBUINT16 shortCount; @@ -1815,6 +2143,43 @@ struct VariationStore dataSets.sanitize (c, this)); } + bool serialize (hb_serialize_context_t *c, + const VariationStore *src, + const hb_array_t <hb_inc_bimap_t> &inner_maps) + { + TRACE_SERIALIZE (this); + unsigned int set_count = 0; + for (unsigned int i = 0; i < inner_maps.length; i++) + if (inner_maps[i].get_population () > 0) set_count++; + + unsigned int size = min_size + HBUINT32::static_size * set_count; + if (unlikely (!c->allocate_size<HBUINT32> (size))) return_trace (false); + format = 1; + + hb_inc_bimap_t region_map; + for (unsigned int i = 0; i < inner_maps.length; i++) + (src+src->dataSets[i]).collect_region_refs (region_map, inner_maps[i]); + region_map.sort (); + + if (unlikely (!regions.serialize (c, this) + .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 () + */ + dataSets.len = set_count; + unsigned int set_index = 0; + for (unsigned int i = 0; i < inner_maps.length; i++) + { + if (inner_maps[i].get_population () == 0) continue; + if (unlikely (!dataSets[set_index++].serialize (c, this) + .serialize (c, &(src+src->dataSets[i]), inner_maps[i], region_map))) + return_trace (false); + } + + return_trace (true); + } + unsigned int get_region_index_count (unsigned int ivs) const { return (this+dataSets[ivs]).get_region_index_count (); } @@ -1833,6 +2198,8 @@ struct VariationStore &scalars[0], num_scalars); } + unsigned int get_sub_table_count () const { return dataSets.len; } + protected: HBUINT16 format; LOffsetTo<VarRegionList> regions; 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 73107f490b5..024312d610c 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 @@ -101,10 +101,10 @@ struct ValueFormat : HBUINT16 unsigned int get_len () const { return hb_popcount ((unsigned int) *this); } unsigned int get_size () const { return get_len () * Value::static_size; } - bool apply_value (hb_ot_apply_context_t *c, - const void *base, - const Value *values, - hb_glyph_position_t &glyph_pos) const + bool apply_value (hb_ot_apply_context_t *c, + const void *base, + const Value *values, + hb_glyph_position_t &glyph_pos) const { bool ret = false; unsigned int format = *this; @@ -257,7 +257,7 @@ struct AnchorFormat1 TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } - + AnchorFormat1* copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); @@ -558,7 +558,7 @@ struct SinglePosFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_set_t &glyphset = *c->plan->glyphset (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto it = @@ -647,7 +647,7 @@ struct SinglePosFormat2 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_set_t &glyphset = *c->plan->glyphset (); const hb_map_t &glyph_map = *c->plan->glyph_map; unsigned sub_length = valueFormat.get_len (); @@ -761,6 +761,18 @@ struct PairValueRecord { friend struct PairSet; + bool serialize (hb_serialize_context_t *c, + unsigned length, + const hb_map_t &glyph_map) const + { + TRACE_SERIALIZE (this); + auto *out = c->start_embed (*this); + if (unlikely (!c->extend_min (out))) return_trace (false); + + out->secondGlyph = glyph_map[secondGlyph]; + return_trace (c->copy (values, length)); + } + protected: HBGlyphID secondGlyph; /* GlyphID of second glyph in the * pair--first glyph is listed in the @@ -846,6 +858,37 @@ struct PairSet return_trace (false); } + bool subset (hb_subset_context_t *c, + const ValueFormat valueFormats[2]) const + { + TRACE_SUBSET (this); + auto snap = c->serializer->snapshot (); + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->len = 0; + + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + unsigned len1 = valueFormats[0].get_len (); + unsigned len2 = valueFormats[1].get_len (); + unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); + + const PairValueRecord *record = &firstPairValueRecord; + unsigned count = len, num = 0; + for (unsigned i = 0; i < count; i++) + { + if (!glyphset.has (record->secondGlyph)) continue; + if (record->serialize (c->serializer, len1 + len2, glyph_map)) num++; + record = &StructAtOffset<const PairValueRecord> (record, record_size); + } + + out->len = num; + if (!num) c->serializer->revert (snap); + return_trace (num); + } + struct sanitize_closure_t { const void *base; @@ -919,8 +962,43 @@ struct PairPosFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - // TODO(subset) - return_trace (false); + + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->format = format; + out->valueFormat[0] = valueFormat[0]; + out->valueFormat[1] = valueFormat[1]; + + 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>& _) + { + 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, out, valueFormat); + if (!ret) + { + out->pairSet.pop (); + c->serializer->revert (snap); + } + return ret; + }, + hb_second) + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + + out->coverage.serialize (c->serializer, out) + .serialize (c->serializer, new_coverage.iter ()); + + return_trace (bool (new_coverage)); } bool sanitize (hb_sanitize_context_t *c) const @@ -1011,8 +1089,49 @@ struct PairPosFormat2 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - // TODO(subset) - return_trace (false); + 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, out, &klass1_map); + out->class1Count = klass1_map.get_population (); + + hb_map_t klass2_map; + out->classDef2.serialize_subset (c, classDef2, this, out, &klass2_map); + out->class2Count = klass2_map.get_population (); + + unsigned record_len = valueFormat1.get_len () + 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) * record_len; + for (unsigned i = 0; i < record_len; i++) + c->serializer->copy (values[idx+i]); + }) + ; + }) + ; + + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto it = + + hb_iter (this+coverage) + | hb_filter (glyphset) + | hb_map_retains_sorting (glyph_map) + ; + + out->coverage.serialize (c->serializer, out).serialize (c->serializer, it); + return_trace (out->class1Count && out->class2Count && bool (it)); } bool sanitize (hb_sanitize_context_t *c) const @@ -1242,7 +1361,7 @@ struct CursivePosFormat1 hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, Iterator it, - const void *src_base) + const void *src_base) { if (unlikely (!c->extend_min ((*this)))) return; this->format = 1; @@ -1273,7 +1392,7 @@ struct CursivePosFormat1 + hb_zip (this+coverage, entryExitRecord) | hb_filter (glyphset, hb_first) | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&> - { return hb_pair (glyph_map[p.first], p.second);}) + { return hb_pair (glyph_map[p.first], p.second);}) ; bool ret = bool (it); 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 a2722ade93d..fc21cb056e8 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 @@ -452,20 +452,7 @@ struct MultipleSubstFormat1 hb_sorted_vector_t<hb_codepoint_t> new_coverage; + hb_zip (this+coverage, sequence) | hb_filter (glyphset, hb_first) - | hb_filter ([this, c, out] (const OffsetTo<Sequence>& _) - { - auto *o = out->sequence.serialize_append (c->serializer); - if (unlikely (!o)) return false; - auto snap = c->serializer->snapshot (); - bool ret = o->serialize_subset (c, _, this, out); - if (!ret) - { - out->sequence.pop (); - c->serializer->revert (snap); - } - return ret; - }, - hb_second) + | hb_filter (subset_offset_array (c, out->sequence, this, out), hb_second) | hb_map (hb_first) | hb_map (glyph_map) | hb_sink (new_coverage) @@ -675,20 +662,7 @@ struct AlternateSubstFormat1 hb_sorted_vector_t<hb_codepoint_t> new_coverage; + hb_zip (this+coverage, alternateSet) | hb_filter (glyphset, hb_first) - | hb_filter ([this, c, out] (const OffsetTo<AlternateSet>& _) - { - auto *o = out->alternateSet.serialize_append (c->serializer); - if (unlikely (!o)) return false; - auto snap = c->serializer->snapshot (); - bool ret = o->serialize_subset (c, _, this, out); - if (!ret) - { - out->alternateSet.pop (); - c->serializer->revert (snap); - } - return ret; - }, - hb_second) + | hb_filter (subset_offset_array (c, out->alternateSet, this, out), hb_second) | hb_map (hb_first) | hb_map (glyph_map) | hb_sink (new_coverage) @@ -948,19 +922,7 @@ struct LigatureSet if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + hb_iter (ligature) - | hb_filter ([this, c, out] (const OffsetTo<Ligature>& _) - { - auto *o = out->ligature.serialize_append (c->serializer); - if (unlikely (!o)) return false; - auto snap = c->serializer->snapshot (); - bool ret = o->serialize_subset (c, _, this, out); - if (!ret) - { - out->ligature.pop (); - c->serializer->revert (snap); - } - return ret; - }) + | hb_filter (subset_offset_array (c, out->ligature, this, out)) | hb_drain ; return_trace (bool (out->ligature)); @@ -1074,20 +1036,7 @@ struct LigatureSubstFormat1 hb_sorted_vector_t<hb_codepoint_t> new_coverage; + hb_zip (this+coverage, ligatureSet) | hb_filter (glyphset, hb_first) - | hb_filter ([this, c, out] (const OffsetTo<LigatureSet>& _) - { - auto *o = out->ligatureSet.serialize_append (c->serializer); - if (unlikely (!o)) return false; - auto snap = c->serializer->snapshot (); - bool ret = o->serialize_subset (c, _, this, out); - if (!ret) - { - out->ligatureSet.pop (); - c->serializer->revert (snap); - } - return ret; - }, - hb_second) + | hb_filter (subset_offset_array (c, out->ligatureSet, this, out), hb_second) | hb_map (hb_first) | hb_map (glyph_map) | hb_sink (new_coverage) 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 c6e6ac9cb40..579d17871b8 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 @@ -387,7 +387,7 @@ struct hb_ot_apply_context_t : skip == matcher_t::SKIP_NO)) { num_items--; - match_glyph_data++; + if (match_glyph_data) match_glyph_data++; return true; } @@ -414,7 +414,7 @@ struct hb_ot_apply_context_t : skip == matcher_t::SKIP_NO)) { num_items--; - match_glyph_data++; + if (match_glyph_data) match_glyph_data++; return true; } @@ -712,11 +712,9 @@ static inline bool intersects_array (const hb_set_t *glyphs, intersects_func_t intersects_func, const void *intersects_data) { - return - + hb_iter (values, count) - | hb_map ([&] (const HBUINT16 &_) { return intersects_func (glyphs, _, intersects_data); }) - | hb_any - ; + for (const HBUINT16 &_ : + hb_iter (values, count)) + if (intersects_func (glyphs, _, intersects_data)) return true; + return false; } @@ -2002,6 +2000,83 @@ struct ChainRule lookup.arrayZ, lookup_context)); } + template<typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + void serialize_array (hb_serialize_context_t *c, + HBUINT16 len, + Iterator it) const + { + c->copy (len); + for (const auto g : it) + { + HBUINT16 gid; + gid = g; + c->copy (gid); + } + } + + ChainRule* copy (hb_serialize_context_t *c, + const hb_map_t *backtrack_map, + const hb_map_t *input_map = nullptr, + const hb_map_t *lookahead_map = nullptr) const + { + TRACE_SERIALIZE (this); + auto *out = c->start_embed (this); + if (unlikely (!out)) return_trace (nullptr); + + const hb_map_t *mapping = backtrack_map; + serialize_array (c, backtrack.len, + backtrack.iter () + | hb_map (mapping)); + + const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); + if (input_map) mapping = input_map; + serialize_array (c, input.lenP1, + input.iter () + | hb_map (mapping)); + + const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); + if (lookahead_map) mapping = lookahead_map; + serialize_array (c, lookahead.len, + lookahead.iter () + | hb_map (mapping)); + + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + c->copy (lookup); + + return_trace (out); + } + + bool subset (hb_subset_context_t *c, + const hb_map_t *backtrack_map = nullptr, + const hb_map_t *input_map = nullptr, + const hb_map_t *lookahead_map = nullptr) const + { + TRACE_SUBSET (this); + + const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); + const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); + + if (!backtrack_map) + { + const hb_set_t &glyphset = *c->plan->glyphset (); + if (!hb_all (backtrack, glyphset) || + !hb_all (input, glyphset) || + !hb_all (lookahead, glyphset)) + return_trace (false); + + copy (c->serializer, c->plan->glyph_map); + } + else + { + if (!hb_all (backtrack, backtrack_map) || + !hb_all (input, input_map) || + !hb_all (lookahead, lookahead_map)) + return_trace (false); + + copy (c->serializer, backtrack_map, input_map, lookahead_map); + } + + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -2083,6 +2158,40 @@ struct ChainRuleSet ; } + bool subset (hb_subset_context_t *c, + const hb_map_t *backtrack_klass_map = nullptr, + const hb_map_t *input_klass_map = nullptr, + const hb_map_t *lookahead_klass_map = nullptr) const + { + TRACE_SUBSET (this); + + auto snap = c->serializer->snapshot (); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + for (const OffsetTo<ChainRule>& _ : rule) + { + if (!_) continue; + auto *o = out->rule.serialize_append (c->serializer); + if (unlikely (!o)) continue; + + auto o_snap = c->serializer->snapshot (); + if (!o->serialize_subset (c, _, this, out, + backtrack_klass_map, + input_klass_map, + lookahead_klass_map)) + { + out->rule.pop (); + c->serializer->revert (o_snap); + } + } + + bool ret = bool (out->rule); + if (!ret) c->serializer->revert (snap); + + return_trace (ret); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -2175,8 +2284,25 @@ struct ChainContextFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - // TODO(subset) - return_trace (false); + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->format = format; + + hb_sorted_vector_t<hb_codepoint_t> new_coverage; + + hb_zip (this+coverage, ruleSet) + | hb_filter (glyphset, hb_first) + | hb_filter (subset_offset_array (c, out->ruleSet, this, out), hb_second) + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + + out->coverage.serialize (c->serializer, out) + .serialize (c->serializer, new_coverage.iter ()); + return_trace (bool (new_coverage)); } bool sanitize (hb_sanitize_context_t *c) const @@ -2314,8 +2440,54 @@ struct ChainContextFormat2 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - // TODO(subset) - return_trace (false); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->format = format; + out->coverage.serialize_subset (c, coverage, this, out); + + hb_map_t backtrack_klass_map; + out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, out, &backtrack_klass_map); + + // subset inputClassDef based on glyphs survived in Coverage subsetting + hb_map_t input_klass_map; + out->inputClassDef.serialize_subset (c, inputClassDef, this, out, &input_klass_map); + + hb_map_t lookahead_klass_map; + out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, out, &lookahead_klass_map); + + hb_vector_t<unsigned> rulesets; + bool ret = true; + for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet) + | hb_filter (input_klass_map, hb_first) + | hb_map (hb_second)) + { + auto *o = out->ruleSet.serialize_append (c->serializer); + if (unlikely (!o)) + { + ret = false; + break; + } + if (!o->serialize_subset (c, _, this, out, + &backtrack_klass_map, + &input_klass_map, + &lookahead_klass_map)) + { + rulesets.push (0); + } + else rulesets.push (1); + } + + if (!ret) return_trace (ret); + + //prune empty trailing ruleSets + unsigned count = rulesets.length; + while (count > 0 && rulesets[count-1] == 0) + { + out->ruleSet.pop (); + count--; + } + + return_trace (bool (out->ruleSet)); } bool sanitize (hb_sanitize_context_t *c) const @@ -2457,11 +2629,46 @@ struct ChainContextFormat3 lookup.len, lookup.arrayZ, lookup_context)); } + template<typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + bool serialize_coverage_offsets (hb_subset_context_t *c, + Iterator it, + const void* src_base, + const void* dst_base) const + { + TRACE_SERIALIZE (this); + auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> (); + + if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) return_trace (false); + + + it + | hb_apply (subset_offset_array (c, *out, src_base, dst_base)) + ; + + return_trace (out->len); + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - // TODO(subset) - return_trace (false); + + auto *out = c->serializer->start_embed (this); + if (unlikely (!out)) return_trace (false); + if (unlikely (!c->serializer->embed (this->format))) return_trace (false); + + if (!serialize_coverage_offsets (c, backtrack.iter (), this, out)) + return_trace (false); + + const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + if (!serialize_coverage_offsets (c, input.iter (), this, out)) + return_trace (false); + + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); + if (!serialize_coverage_offsets (c, lookahead.iter (), this, out)) + return_trace (false); + + const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); + return_trace (c->serializer->copy (lookup)); } bool sanitize (hb_sanitize_context_t *c) const diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc index d40c67af9c0..e4bb4b63661 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc @@ -38,7 +38,7 @@ void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const { for (unsigned int i = 0; i < lookups[table_index].length; i++) - hb_set_add (lookups_out, lookups[table_index][i].index); + lookups_out->add (lookups[table_index][i].index); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh index 037fcae1e68..f6b150323b6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh @@ -134,8 +134,8 @@ struct OS2 OBLIQUE = 1u<<9 }; - bool is_italic () const { return fsSelection & ITALIC; } - bool is_oblique () const { return fsSelection & OBLIQUE; } + bool is_italic () const { return fsSelection & ITALIC; } + bool is_oblique () const { return fsSelection & OBLIQUE; } bool use_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; } enum width_class_t { 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 bb0141d1093..2a7a8ebbc02 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 @@ -230,8 +230,8 @@ arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUS return false; const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest); - static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup) - <= ARABIC_FALLBACK_MAX_LOOKUPS, ""); + static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) == + ARABIC_FALLBACK_MAX_LOOKUPS * sizeof (ManifestLookup), ""); /* TODO sanitize the table? */ unsigned j = 0; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc index dad1dba4adf..fc3490d7168 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc @@ -116,8 +116,8 @@ enum myanmar_syllable_type_t { static void setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_buffer_t *buffer, - hb_font_t *font HB_UNUSED) + hb_buffer_t *buffer, + hb_font_t *font HB_UNUSED) { HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_category); HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_position); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.cc index 4c5d687c7b4..e3889b3e607 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.cc @@ -347,7 +347,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPst, VPst, VPst, VBlw, FAbv, FAbv, FAbv, + /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv, /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, O, O, O, O, O, O, O, O, /* 1C40 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, B, B, 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 new file mode 100644 index 00000000000..666b3089521 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh @@ -0,0 +1,734 @@ +/* + * Copyright © 2019 Adobe Inc. + * Copyright © 2019 Ebrahim Byagowi + * + * 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. + * + * Adobe Author(s): Michiharu Ariza + */ + +#ifndef HB_OT_VAR_GVAR_TABLE_HH +#define HB_OT_VAR_GVAR_TABLE_HH + +#include "hb-open-type.hh" +#include "hb-ot-glyf-table.hh" +#include "hb-ot-var-fvar-table.hh" + +/* + * gvar -- Glyph Variation Table + * https://docs.microsoft.com/en-us/typography/opentype/spec/gvar + */ +#define HB_OT_TAG_gvar HB_TAG('g','v','a','r') + +namespace OT { + +struct contour_point_t +{ + void init (float x_=0.f, float y_=0.f) { flag = 0; x = x_; y = y_; } + + void translate (const contour_point_t &p) { x += p.x; y += p.y; } + + uint8_t flag; + float x, y; +}; + +struct contour_point_vector_t : hb_vector_t<contour_point_t> +{ + void extend (const hb_array_t<contour_point_t> &a) + { + unsigned int old_len = length; + resize (old_len + a.length); + for (unsigned int i = 0; i < a.length; i++) + (*this)[old_len + i] = a[i]; + } + + void transform (const float (&matrix)[4]) + { + for (unsigned int i = 0; i < length; i++) + { + contour_point_t &p = (*this)[i]; + float x_ = p.x * matrix[0] + p.y * matrix[2]; + p.y = p.x * matrix[1] + p.y * matrix[3]; + p.x = x_; + } + } + + void translate (const contour_point_t& delta) + { + for (unsigned int i = 0; i < length; i++) + (*this)[i].translate (delta); + } +}; + +struct range_checker_t +{ + range_checker_t (const void *data_, unsigned int length_) + : data ((const char *) data_), length (length_) {} + + template <typename T> + bool in_range (const T *p, unsigned int size = T::static_size) const + { + return ((const char *) p) >= data + && ((const char *) p + size) <= data + length; + } + + protected: + const char *data; + const unsigned int length; +}; + +struct Tuple : UnsizedArrayOf<F2DOT14> {}; + +struct TuppleIndex : HBUINT16 +{ + enum Flags { + EmbeddedPeakTuple = 0x8000u, + IntermediateRegion = 0x4000u, + PrivatePointNumbers = 0x2000u, + TupleIndexMask = 0x0FFFu + }; + + DEFINE_SIZE_STATIC (2); +}; + +struct TupleVarHeader +{ + unsigned int get_size (unsigned int axis_count) const + { + return min_size + + (has_peak () ? get_peak_tuple ().get_size (axis_count) : 0) + + (has_intermediate () ? (get_start_tuple (axis_count).get_size (axis_count) + + get_end_tuple (axis_count).get_size (axis_count)) : 0); + } + + const TupleVarHeader &get_next (unsigned int axis_count) const + { return StructAtOffset<TupleVarHeader> (this, get_size (axis_count)); } + + float calculate_scalar (const int *coords, unsigned int coord_count, + const hb_array_t<const F2DOT14> shared_tuples) const + { + const F2DOT14 *peak_tuple; + + if (has_peak ()) + peak_tuple = &(get_peak_tuple ()[0]); + else + { + unsigned int index = get_index (); + if (unlikely (index * coord_count >= shared_tuples.length)) + return 0.f; + peak_tuple = &shared_tuples[coord_count * index]; + } + + const F2DOT14 *start_tuple = nullptr; + const F2DOT14 *end_tuple = nullptr; + if (has_intermediate ()) + { + start_tuple = get_start_tuple (coord_count); + end_tuple = get_end_tuple (coord_count); + } + + float scalar = 1.f; + for (unsigned int i = 0; i < coord_count; i++) + { + int v = coords[i]; + int peak = peak_tuple[i]; + if (!peak || v == peak) continue; + + if (has_intermediate ()) + { + int start = start_tuple[i]; + int end = end_tuple[i]; + if (unlikely (start > peak || peak > end || + (start < 0 && end > 0 && peak))) continue; + if (v < start || v > end) return 0.f; + if (v < peak) + { if (peak != start) scalar *= (float) (v - start) / (peak - start); } + else + { if (peak != end) scalar *= (float) (end - v) / (end - peak); } + } + else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.f; + else + scalar *= (float) v / peak; + } + return scalar; + } + + unsigned int get_data_size () const { return varDataSize; } + + bool has_peak () const { return (tupleIndex & TuppleIndex::EmbeddedPeakTuple); } + bool has_intermediate () const { return (tupleIndex & TuppleIndex::IntermediateRegion); } + bool has_private_points () const { return (tupleIndex & TuppleIndex::PrivatePointNumbers); } + unsigned int get_index () const { return (tupleIndex & TuppleIndex::TupleIndexMask); } + + protected: + const Tuple &get_peak_tuple () const + { return StructAfter<Tuple> (tupleIndex); } + const Tuple &get_start_tuple (unsigned int axis_count) const + { return *(const Tuple *) &get_peak_tuple ()[has_peak () ? axis_count : 0]; } + const Tuple &get_end_tuple (unsigned int axis_count) const + { return *(const Tuple *) &get_peak_tuple ()[has_peak () ? (axis_count * 2) : axis_count]; } + + HBUINT16 varDataSize; + TuppleIndex tupleIndex; + /* UnsizedArrayOf<F2DOT14> peakTuple - optional */ + /* UnsizedArrayOf<F2DOT14> intermediateStartTuple - optional */ + /* UnsizedArrayOf<F2DOT14> intermediateEndTuple - optional */ + + public: + DEFINE_SIZE_MIN (4); +}; + +struct TupleVarCount : HBUINT16 +{ + bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); } + unsigned int get_count () const { return (*this) & CountMask; } + + protected: + enum Flags + { + SharedPointNumbers = 0x8000u, + CountMask = 0x0FFFu + }; + + public: + DEFINE_SIZE_STATIC (2); +}; + +struct GlyphVarData +{ + const TupleVarHeader &get_tuple_var_header (void) const + { return StructAfter<TupleVarHeader> (data); } + + struct tuple_iterator_t + { + void init (const GlyphVarData *var_data_, unsigned int length_, unsigned int axis_count_) + { + var_data = var_data_; + length = length_; + index = 0; + axis_count = axis_count_; + current_tuple = &var_data->get_tuple_var_header (); + data_offset = 0; + } + + bool get_shared_indices (hb_vector_t<unsigned int> &shared_indices /* OUT */) + { + if (var_data->has_shared_point_numbers ()) + { + range_checker_t checker (var_data, length); + const HBUINT8 *base = &(var_data+var_data->data); + const HBUINT8 *p = base; + if (!unpack_points (p, shared_indices, checker)) return false; + data_offset = p - base; + } + return true; + } + + bool is_valid () const + { + return (index < var_data->tupleVarCount.get_count ()) && + in_range (current_tuple) && + current_tuple->get_size (axis_count); + } + + bool move_to_next () + { + data_offset += current_tuple->get_data_size (); + current_tuple = ¤t_tuple->get_next (axis_count); + index++; + return is_valid (); + } + + bool in_range (const void *p, unsigned int l) const + { return (const char*) p >= (const char*) var_data && (const char*) p+l <= (const char*) var_data + length; } + + template <typename T> bool in_range (const T *p) const { return in_range (p, sizeof (*p)); } + + const HBUINT8 *get_serialized_data () const + { return &(var_data+var_data->data) + data_offset; } + + private: + const GlyphVarData *var_data; + unsigned int length; + unsigned int index; + unsigned int axis_count; + unsigned int data_offset; + + public: + const TupleVarHeader *current_tuple; + }; + + static bool get_tuple_iterator (const GlyphVarData *var_data, + unsigned int length, + unsigned int axis_count, + hb_vector_t<unsigned int> &shared_indices /* OUT */, + tuple_iterator_t *iterator /* OUT */) + { + iterator->init (var_data, length, axis_count); + if (!iterator->get_shared_indices (shared_indices)) + return false; + return iterator->is_valid (); + } + + bool has_shared_point_numbers () const { return tupleVarCount.has_shared_point_numbers (); } + + static bool unpack_points (const HBUINT8 *&p /* IN/OUT */, + hb_vector_t<unsigned int> &points /* OUT */, + const range_checker_t &check) + { + enum packed_point_flag_t + { + POINTS_ARE_WORDS = 0x80, + POINT_RUN_COUNT_MASK = 0x7F + }; + + if (unlikely (!check.in_range (p))) return false; + + uint16_t count = *p++; + if (count & POINTS_ARE_WORDS) + { + if (unlikely (!check.in_range (p))) return false; + count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++; + } + points.resize (count); + + unsigned int n = 0; + uint16_t i = 0; + while (i < count) + { + if (unlikely (!check.in_range (p))) return false; + uint16_t j; + uint8_t control = *p++; + uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1; + if (control & POINTS_ARE_WORDS) + { + for (j = 0; j < run_count && i < count; j++, i++) + { + if (unlikely (!check.in_range ((const HBUINT16 *) p))) + return false; + n += *(const HBUINT16 *)p; + points[i] = n; + p += HBUINT16::static_size; + } + } + else + { + for (j = 0; j < run_count && i < count; j++, i++) + { + if (unlikely (!check.in_range (p))) return false; + n += *p++; + points[i] = n; + } + } + if (j < run_count) return false; + } + return true; + } + + static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */, + hb_vector_t<int> &deltas /* IN/OUT */, + const range_checker_t &check) + { + enum packed_delta_flag_t + { + DELTAS_ARE_ZERO = 0x80, + DELTAS_ARE_WORDS = 0x40, + DELTA_RUN_COUNT_MASK = 0x3F + }; + + unsigned int i = 0; + unsigned int count = deltas.length; + while (i < count) + { + if (unlikely (!check.in_range (p))) return false; + uint8_t control = *p++; + unsigned int run_count = (control & DELTA_RUN_COUNT_MASK) + 1; + unsigned int j; + if (control & DELTAS_ARE_ZERO) + for (j = 0; j < run_count && i < count; j++, i++) + deltas[i] = 0; + else if (control & DELTAS_ARE_WORDS) + for (j = 0; j < run_count && i < count; j++, i++) + { + if (unlikely (!check.in_range ((const HBUINT16 *) p))) + return false; + deltas[i] = *(const HBINT16 *) p; + p += HBUINT16::static_size; + } + else + for (j = 0; j < run_count && i < count; j++, i++) + { + if (unlikely (!check.in_range (p))) + return false; + deltas[i] = *(const HBINT8 *) p++; + } + if (j < run_count) + return false; + } + return true; + } + + protected: + TupleVarCount tupleVarCount; + OffsetTo<HBUINT8> data; + /* TupleVarHeader tupleVarHeaders[] */ + public: + DEFINE_SIZE_MIN (4); +}; + +struct gvar +{ + static constexpr hb_tag_t tableTag = HB_OT_TAG_gvar; + + bool sanitize_shallow (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && (version.major == 1) && + (glyphCount == c->get_num_glyphs ()) && + c->check_array (&(this+sharedTuples), axisCount * sharedTupleCount) && + (is_long_offset () ? + c->check_array (get_long_offset_array (), glyphCount+1) : + c->check_array (get_short_offset_array (), glyphCount+1)) && + c->check_array (((const HBUINT8*)&(this+dataZ)) + get_offset (0), + get_offset (glyphCount) - get_offset (0))); + } + + /* GlyphVarData not sanitized here; must be checked while accessing each glyph varation data */ + bool sanitize (hb_sanitize_context_t *c) const + { return sanitize_shallow (c); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + + gvar *out = c->serializer->allocate_min<gvar> (); + if (unlikely (!out)) return_trace (false); + + out->version.major = 1; + out->version.minor = 0; + out->axisCount = axisCount; + out->sharedTupleCount = sharedTupleCount; + + unsigned int num_glyphs = c->plan->num_output_glyphs (); + out->glyphCount = num_glyphs; + + unsigned int subset_data_size = 0; + for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) + { + hb_codepoint_t old_gid; + if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue; + subset_data_size += get_glyph_var_data_length (old_gid); + } + + bool long_offset = subset_data_size & ~0xFFFFu; + out->flags = long_offset ? 1 : 0; + + HBUINT8 *subset_offsets = c->serializer->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1)); + if (!subset_offsets) return_trace (false); + + /* shared tuples */ + if (!sharedTupleCount || !sharedTuples) + out->sharedTuples = 0; + else + { + unsigned int shared_tuple_size = F2DOT14::static_size * axisCount * sharedTupleCount; + F2DOT14 *tuples = c->serializer->allocate_size<F2DOT14> (shared_tuple_size); + if (!tuples) return_trace (false); + out->sharedTuples = (char *) tuples - (char *) out; + memcpy (tuples, &(this+sharedTuples), shared_tuple_size); + } + + char *subset_data = c->serializer->allocate_size<char> (subset_data_size); + if (!subset_data) return_trace (false); + out->dataZ = subset_data - (char *)out; + + unsigned int glyph_offset = 0; + for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) + { + hb_codepoint_t old_gid; + unsigned int length = c->plan->old_gid_for_new_gid (gid, &old_gid) ? get_glyph_var_data_length (old_gid) : 0; + + if (long_offset) + ((HBUINT32 *) subset_offsets)[gid] = glyph_offset; + else + ((HBUINT16 *) subset_offsets)[gid] = glyph_offset / 2; + + if (length > 0) memcpy (subset_data, get_glyph_var_data (old_gid), length); + subset_data += length; + glyph_offset += length; + } + if (long_offset) + ((HBUINT32 *) subset_offsets)[num_glyphs] = glyph_offset; + else + ((HBUINT16 *) subset_offsets)[num_glyphs] = glyph_offset / 2; + + return_trace (true); + } + + protected: + const GlyphVarData *get_glyph_var_data (hb_codepoint_t glyph) const + { + unsigned int start_offset = get_offset (glyph); + unsigned int end_offset = get_offset (glyph+1); + + if ((start_offset == end_offset) || + unlikely ((start_offset > get_offset (glyphCount)) || + (start_offset + GlyphVarData::min_size > end_offset))) + return &Null (GlyphVarData); + return &(((unsigned char *) this + start_offset) + dataZ); + } + + bool is_long_offset () const { return (flags & 1) != 0; } + + unsigned int get_offset (unsigned int i) const + { + if (is_long_offset ()) + return get_long_offset_array ()[i]; + else + return get_short_offset_array ()[i] * 2; + } + + unsigned int get_glyph_var_data_length (unsigned int glyph) const + { + unsigned int end_offset = get_offset (glyph + 1); + unsigned int start_offset = get_offset (glyph); + if (unlikely (start_offset > end_offset || end_offset > get_offset (glyphCount))) + return 0; + return end_offset - start_offset; + } + + const HBUINT32 * get_long_offset_array () const { return (const HBUINT32 *) &offsetZ; } + const HBUINT16 *get_short_offset_array () const { return (const HBUINT16 *) &offsetZ; } + + public: + struct accelerator_t + { + void init (hb_face_t *face) + { + gvar_table = hb_sanitize_context_t ().reference_table<gvar> (face); + hb_blob_ptr_t<fvar> fvar_table = hb_sanitize_context_t ().reference_table<fvar> (face); + unsigned int axis_count = fvar_table->get_axis_count (); + fvar_table.destroy (); + + if (unlikely ((gvar_table->glyphCount != face->get_num_glyphs ()) || + (gvar_table->axisCount != axis_count))) + fini (); + + unsigned int num_shared_coord = gvar_table->sharedTupleCount * gvar_table->axisCount; + shared_tuples.resize (num_shared_coord); + for (unsigned int i = 0; i < num_shared_coord; i++) + shared_tuples[i] = (&(gvar_table + gvar_table->sharedTuples))[i]; + } + + void fini () + { + gvar_table.destroy (); + shared_tuples.fini (); + } + + private: + struct x_getter { static float get (const contour_point_t &p) { return p.x; } }; + struct y_getter { static float get (const contour_point_t &p) { return p.y; } }; + + template <typename T> + static float infer_delta (const hb_array_t<contour_point_t> points, + const hb_array_t<contour_point_t> deltas, + unsigned int target, unsigned int prev, unsigned int next) + { + float target_val = T::get (points[target]); + float prev_val = T::get (points[prev]); + float next_val = T::get (points[next]); + float prev_delta = T::get (deltas[prev]); + float next_delta = T::get (deltas[next]); + + if (prev_val == next_val) + return (prev_delta == next_delta) ? prev_delta : 0.f; + else if (target_val <= hb_min (prev_val, next_val)) + return (prev_val < next_val) ? prev_delta : next_delta; + else if (target_val >= hb_max (prev_val, next_val)) + return (prev_val > next_val) ? prev_delta : next_delta; + + /* linear interpolation */ + float r = (target_val - prev_val) / (next_val - prev_val); + return (1.f - r) * prev_delta + r * next_delta; + } + + static unsigned int next_index (unsigned int i, unsigned int start, unsigned int end) + { return (i >= end) ? start : (i + 1); } + + public: + bool apply_deltas_to_points (hb_codepoint_t glyph, + const int *coords, unsigned int coord_count, + const hb_array_t<contour_point_t> points, + const hb_array_t<unsigned int> end_points) const + { + if (unlikely (coord_count != gvar_table->axisCount)) return false; + + const GlyphVarData *var_data = gvar_table->get_glyph_var_data (glyph); + if (var_data == &Null (GlyphVarData)) return true; + hb_vector_t<unsigned int> shared_indices; + GlyphVarData::tuple_iterator_t iterator; + if (!GlyphVarData::get_tuple_iterator (var_data, + gvar_table->get_glyph_var_data_length (glyph), + gvar_table->axisCount, + shared_indices, + &iterator)) + return false; + + /* Save original points for inferred delta calculation */ + contour_point_vector_t orig_points; + orig_points.resize (points.length); + for (unsigned int i = 0; i < orig_points.length; i++) + orig_points[i] = points[i]; + + contour_point_vector_t deltas; /* flag is used to indicate referenced point */ + deltas.resize (points.length); + + do + { + float scalar = iterator.current_tuple->calculate_scalar (coords, coord_count, shared_tuples.as_array ()); + if (scalar == 0.f) continue; + const HBUINT8 *p = iterator.get_serialized_data (); + unsigned int length = iterator.current_tuple->get_data_size (); + if (unlikely (!iterator.in_range (p, length))) + return false; + + range_checker_t checker (p, length); + hb_vector_t<unsigned int> private_indices; + if (iterator.current_tuple->has_private_points () && + !GlyphVarData::unpack_points (p, private_indices, checker)) + return false; + const hb_array_t<unsigned int> &indices = private_indices.length ? private_indices : shared_indices; + + bool apply_to_all = (indices.length == 0); + unsigned int num_deltas = apply_to_all ? points.length : indices.length; + hb_vector_t<int> x_deltas; + x_deltas.resize (num_deltas); + if (!GlyphVarData::unpack_deltas (p, x_deltas, checker)) + return false; + hb_vector_t<int> y_deltas; + y_deltas.resize (num_deltas); + if (!GlyphVarData::unpack_deltas (p, y_deltas, checker)) + return false; + + for (unsigned int i = 0; i < deltas.length; i++) + deltas[i].init (); + for (unsigned int i = 0; i < num_deltas; i++) + { + unsigned int pt_index = apply_to_all ? i : indices[i]; + deltas[pt_index].flag = 1; /* this point is referenced, i.e., explicit deltas specified */ + deltas[pt_index].x += x_deltas[i] * scalar; + deltas[pt_index].y += y_deltas[i] * scalar; + } + + /* infer deltas for unreferenced points */ + unsigned int start_point = 0; + for (unsigned int c = 0; c < end_points.length; c++) + { + unsigned int end_point = end_points[c]; + unsigned int i, j; + + /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */ + unsigned int unref_count = 0; + for (i = start_point; i <= end_point; i++) + if (!deltas[i].flag) unref_count++; + if (unref_count == 0 || unref_count > end_point - start_point) + goto no_more_gaps; + + j = start_point; + for (;;) + { + /* Locate the next gap of unreferenced points between two referenced points prev and next. + * Note that a gap may wrap around at left (start_point) and/or at right (end_point). + */ + unsigned int prev, next; + for (;;) + { + i = j; + j = next_index (i, start_point, end_point); + if (deltas[i].flag && !deltas[j].flag) break; + } + prev = j = i; + for (;;) + { + i = j; + j = next_index (i, start_point, end_point); + if (!deltas[i].flag && deltas[j].flag) break; + } + next = j; + /* Infer deltas for all unref points in the gap between prev and next */ + i = prev; + for (;;) + { + i = next_index (i, start_point, end_point); + if (i == next) break; + deltas[i].x = infer_delta<x_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next); + deltas[i].y = infer_delta<y_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next); + if (--unref_count == 0) goto no_more_gaps; + } + } +no_more_gaps: + start_point = end_point + 1; + } + + /* apply specified / inferred deltas to points */ + for (unsigned int i = 0; i < points.length; i++) + { + points[i].x += (float) roundf (deltas[i].x); + points[i].y += (float) roundf (deltas[i].y); + } + } while (iterator.move_to_next ()); + + return true; + } + + unsigned int get_axis_count () const { return gvar_table->axisCount; } + + protected: + const GlyphVarData *get_glyph_var_data (hb_codepoint_t glyph) const + { return gvar_table->get_glyph_var_data (glyph); } + + private: + hb_blob_ptr_t<gvar> gvar_table; + hb_vector_t<F2DOT14> shared_tuples; + }; + + protected: + FixedVersion<>version; /* Version of gvar table. Set to 0x00010000u. */ + HBUINT16 axisCount; + HBUINT16 sharedTupleCount; + LOffsetTo<F2DOT14> + sharedTuples; /* LOffsetTo<UnsizedArrayOf<Tupple>> */ + HBUINT16 glyphCount; + HBUINT16 flags; + LOffsetTo<GlyphVarData> + dataZ; /* Array of GlyphVarData */ + UnsizedArrayOf<HBUINT8> + offsetZ; /* Array of 16-bit or 32-bit (glyphCount+1) offsets */ + public: + DEFINE_SIZE_MIN (20); +}; + +struct gvar_accelerator_t : gvar::accelerator_t {}; + +} /* namespace OT */ + +#endif /* HB_OT_VAR_GVAR_TABLE_HH */ 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 a8d9fe3c875..223430fb829 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 @@ -114,14 +114,21 @@ struct HVARVVAR rsbMap.sanitize (c, this)); } - float get_advance_var (hb_codepoint_t glyph, - const int *coords, unsigned int coord_count) const + float get_advance_var (hb_font_t *font, hb_codepoint_t glyph) const { unsigned int varidx = (this+advMap).map (glyph); + return (this+varStore).get_delta (varidx, font->coords, font->num_coords); + } + + float get_side_bearing_var (hb_codepoint_t glyph, + const int *coords, unsigned int coord_count) const + { + if (!has_side_bearing_deltas ()) return 0.f; + unsigned int varidx = (this+lsbMap).map (glyph); return (this+varStore).get_delta (varidx, coords, coord_count); } - bool has_sidebearing_deltas () const { return lsbMap && rsbMap; } + bool has_side_bearing_deltas () const { return lsbMap && rsbMap; } protected: FixedVersion<>version; /* Version of the metrics variation table diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc index deff77bedcd..cf4e1525a25 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc @@ -154,7 +154,9 @@ hb_shape_full (hb_font_t *font, * * Shapes @buffer using @font turning its Unicode characters content to * positioned glyphs. If @features is not %NULL, it will be used to control the - * features applied during shaping. + * features applied during shaping. If two @features have the same tag but + * overlapping ranges the value of the feature with the higher index takes + * precedence. * * Since: 0.9.2 **/ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc index b71ac57cc08..c9a880ad500 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc @@ -68,8 +68,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, { /* use hb_set to determine the subset of font dicts */ hb_set_t *set = hb_set_create (); - if (set == &Null (hb_set_t)) - return false; + if (unlikely (set == &Null (hb_set_t))) return false; hb_codepoint_t prev_fd = CFF_UNDEF_CODE; for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh index 6c36e458f53..3c66119603f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh @@ -548,7 +548,7 @@ struct subr_remap_t : hb_inc_bimap_t /* create a remapping of subroutine numbers from old to new. * no optimization based on usage counts. fonttools doesn't appear doing that either. */ - + hb_codepoint_t old_num = HB_SET_VALUE_INVALID; while (hb_set_next (closure, &old_num)) add (old_num); @@ -916,7 +916,7 @@ struct subr_subsetter_t hb_set_t *closure, const subr_subset_param_t ¶m) { - hb_set_add (closure, subr_num); + closure->add (subr_num); collect_subr_refs_in_str (subrs[subr_num], param); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc index 21bd97fbb80..e9e075749e7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc @@ -389,7 +389,7 @@ struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t<cff1_cs_opset_subr_subset_t byte_str_ref_t str_ref = env.str_ref; env.call_subr (subrs, type); param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num); - hb_set_add (closure, env.context.subr_num); + closure->add (env.context.subr_num); param.set_current_str (env, true); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc index 9bdd0ee7d6e..7edc3f51535 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc @@ -219,7 +219,7 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t byte_str_ref_t str_ref = env.str_ref; env.call_subr (subrs, type); param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num); - hb_set_add (closure, env.context.subr_num); + closure->add (env.context.subr_num); param.set_current_str (env, true); } 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 65591136834..e537772c093 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 @@ -34,38 +34,17 @@ #include "hb-ot-var-fvar-table.hh" #include "hb-ot-stat-table.hh" -static inline void -_add_gid_and_children (const OT::glyf::accelerator_t &glyf, - hb_codepoint_t gid, - hb_set_t *gids_to_retain) -{ - if (gids_to_retain->has (gid)) - // Already visited this gid, ignore. - return; - - hb_set_add (gids_to_retain, gid); - - OT::glyf::CompositeGlyphHeader::Iterator composite; - if (glyf.get_composite (gid, &composite)) - { - do - { - _add_gid_and_children (glyf, (hb_codepoint_t) composite.current->glyphIndex, gids_to_retain); - } while (composite.move_to_next()); - } -} - #ifndef HB_NO_SUBSET_CFF static inline void _add_cff_seac_components (const OT::cff1::accelerator_t &cff, - hb_codepoint_t gid, - hb_set_t *gids_to_retain) + hb_codepoint_t gid, + hb_set_t *gids_to_retain) { hb_codepoint_t base_gid, accent_gid; if (cff.get_seac_components (gid, &base_gid, &accent_gid)) { - hb_set_add (gids_to_retain, base_gid); - hb_set_add (gids_to_retain, accent_gid); + gids_to_retain->add (base_gid); + gids_to_retain->add (accent_gid); } } #endif @@ -151,7 +130,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, hb_codepoint_t gid = HB_SET_VALUE_INVALID; while (plan->_glyphset_gsub->next (&gid)) { - _add_gid_and_children (glyf, gid, plan->_glyphset); + glyf.add_gid_and_children (gid, plan->_glyphset); #ifndef HB_NO_SUBSET_CFF if (cff.is_valid ()) _add_cff_seac_components (cff, gid, plan->_glyphset); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc index 9a8184063df..08a4054cd0c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc @@ -270,9 +270,9 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs) **/ hb_bool_t hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, - hb_user_data_key_t *key, - void * data, - hb_destroy_func_t destroy, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, hb_bool_t replace) { return hb_object_set_user_data (ufuncs, key, data, destroy, replace); @@ -291,7 +291,7 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, **/ void * hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, - hb_user_data_key_t *key) + hb_user_data_key_t *key) { return hb_object_get_user_data (ufuncs, key); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.h index df0b91f0190..61b1b0ba1f7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.h @@ -200,15 +200,15 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs); HB_EXTERN hb_bool_t hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, - hb_user_data_key_t *key, - void * data, - hb_destroy_func_t destroy, + hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy, hb_bool_t replace); HB_EXTERN void * hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, - hb_user_data_key_t *key); + hb_user_data_key_t *key); HB_EXTERN void @@ -260,7 +260,7 @@ typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs, * @user_data: * @destroy: * - * + * * * Since: 0.9.2 **/ @@ -276,7 +276,7 @@ hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs, * @user_data: * @destroy: * - * + * * * Since: 0.9.2 **/ @@ -292,7 +292,7 @@ hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs, * @user_data: * @destroy: * - * + * * * Since: 0.9.2 **/ @@ -308,7 +308,7 @@ hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs, * @user_data: * @destroy: * - * + * * * Since: 0.9.2 **/ @@ -324,7 +324,7 @@ hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs, * @user_data: * @destroy: * - * + * * * Since: 0.9.2 **/ @@ -340,7 +340,7 @@ hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs, * @user_data: * @destroy: * - * + * * * Since: 0.9.2 **/ 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 288a5416dec..7b150fba054 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh @@ -302,8 +302,8 @@ struct hb_sorted_vector_t : hb_vector_t<Type> { return as_array ().bsearch (x, not_found); } template <typename T> bool bfind (const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, - unsigned int to_store = (unsigned int) -1) const + hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const { return as_array ().bfind (x, i, not_found, to_store); } }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-warning.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-warning.cc deleted file mode 100644 index 60c7445b789..00000000000 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-warning.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © 2012 Google, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Google Author(s): Behdad Esfahbod - */ - -#include "hb.hh" - -#ifdef HB_ATOMIC_INT_NIL -#error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe" -#error "Check hb-atomic.hh for possible resolutions." -#endif - -#ifdef HB_MUTEX_IMPL_NIL -#error "Could not find any system to define mutex macros, library WILL NOT be thread-safe" -#error "Check hb-mutex.hh for possible resolutions." -#endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc index 0aa4a5b204b..983cb557db7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc @@ -45,7 +45,8 @@ using namespace OT; int main (int argc, char **argv) { - if (argc != 2) { + if (argc != 2) + { fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]); exit (1); } @@ -65,7 +66,8 @@ main (int argc, char **argv) const OpenTypeFontFile& ot = *sanitized; - switch (ot.get_tag ()) { + switch (ot.get_tag ()) + { case OpenTypeFontFile::TrueTypeTag: printf ("OpenType font with TrueType outlines\n"); break; @@ -91,20 +93,23 @@ main (int argc, char **argv) int num_fonts = ot.get_face_count (); printf ("%d font(s) found in file\n", num_fonts); - for (int n_font = 0; n_font < num_fonts; n_font++) { + for (int n_font = 0; n_font < num_fonts; n_font++) + { const OpenTypeFontFace &font = ot.get_face (n_font); printf ("Font %d of %d:\n", n_font, num_fonts); int num_tables = font.get_table_count (); printf (" %d table(s) found in font\n", num_tables); - for (int n_table = 0; n_table < num_tables; n_table++) { + for (int n_table = 0; n_table < num_tables; n_table++) + { const OpenTypeTable &table = font.get_table (n_table); printf (" Table %2d of %2d: %.4s (0x%08x+0x%08x)\n", n_table, num_tables, (const char *) table.tag, (unsigned int) table.offset, (unsigned int) table.length); - switch (table.tag) { + switch (table.tag) + { case HB_OT_TAG_GSUB: case HB_OT_TAG_GPOS: @@ -114,10 +119,11 @@ main (int argc, char **argv) int num_scripts = g.get_script_count (); printf (" %d script(s) found in table\n", num_scripts); - for (int n_script = 0; n_script < num_scripts; n_script++) { + for (int n_script = 0; n_script < num_scripts; n_script++) + { const Script &script = g.get_script (n_script); printf (" Script %2d of %2d: %.4s\n", n_script, num_scripts, - (const char *)g.get_script_tag(n_script)); + (const char *)g.get_script_tag(n_script)); if (!script.has_default_lang_sys()) printf (" No default language system\n"); @@ -140,34 +146,37 @@ main (int argc, char **argv) int num_features = langsys.get_feature_count (); printf (" %d feature(s) found in language system\n", num_features); - for (int n_feature = 0; n_feature < num_features; n_feature++) { + for (int n_feature = 0; n_feature < num_features; n_feature++) + { printf (" Feature index %2d of %2d: %d\n", n_feature, num_features, - langsys.get_feature_index (n_feature)); + langsys.get_feature_index (n_feature)); } } } int num_features = g.get_feature_count (); printf (" %d feature(s) found in table\n", num_features); - for (int n_feature = 0; n_feature < num_features; n_feature++) { + for (int n_feature = 0; n_feature < num_features; n_feature++) + { const Feature &feature = g.get_feature (n_feature); int num_lookups = feature.get_lookup_count (); printf (" Feature %2d of %2d: %c%c%c%c\n", n_feature, num_features, - HB_UNTAG(g.get_feature_tag(n_feature))); + HB_UNTAG(g.get_feature_tag(n_feature))); printf (" %d lookup(s) found in feature\n", num_lookups); for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) { printf (" Lookup index %2d of %2d: %d\n", n_lookup, num_lookups, - feature.get_lookup_index (n_lookup)); + feature.get_lookup_index (n_lookup)); } } int num_lookups = g.get_lookup_count (); printf (" %d lookup(s) found in table\n", num_lookups); - for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) { + for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) + { const Lookup &lookup = g.get_lookup (n_lookup); printf (" Lookup %2d of %2d: type %d, props 0x%04X\n", n_lookup, num_lookups, - lookup.get_type(), lookup.get_props()); + lookup.get_type(), lookup.get_props()); } } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc index b5a4c8695aa..9c83171889f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc @@ -234,7 +234,7 @@ main (int argc, char **argv) { hb_set_t *set = hb_set_create (); for (unsigned int i = 0; i < temp1; ++i) - hb_set_add (set, i); + hb_set_add (set, i); temp1++; return set; }) diff --git a/Build/source/libs/harfbuzz/version.ac b/Build/source/libs/harfbuzz/version.ac index d261233f584..65a8e5045c5 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.6.2]) +m4_define([harfbuzz_version], [2.6.3]) |