summaryrefslogtreecommitdiff
path: root/Build/source/libs/harfbuzz/harfbuzz-src/src
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2020-05-18 10:44:36 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2020-05-18 10:44:36 +0000
commitf71aeb3fe9f385a634c46188515206f91c087b82 (patch)
treec629a78664446246792fc22a7cf8f36b9e4ffcee /Build/source/libs/harfbuzz/harfbuzz-src/src
parent57f9b626bae9d06ab9a7818a4bf6de15213980bb (diff)
harfbuzz 2.6.6
git-svn-id: svn://tug.org/texlive/trunk@55197 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src')
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am76
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources4
-rwxr-xr-xBuild/source/libs/harfbuzz/harfbuzz-src/src/check-libstdc++.sh3
-rwxr-xr-xBuild/source/libs/harfbuzz/harfbuzz-src/src/check-static-inits.sh13
-rwxr-xr-xBuild/source/libs/harfbuzz/harfbuzz-src/src/check-symbols.sh11
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/fix_get_types.py15
-rwxr-xr-xBuild/source/libs/harfbuzz/harfbuzz-src/src/gen-arabic-table.py12
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py33
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/gen-emoji-table.py8
-rwxr-xr-xBuild/source/libs/harfbuzz/harfbuzz-src/src/gen-indic-table.py11
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/gen-os2-unicode-ranges.py11
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py41
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/gen-ucd-table.py9
-rwxr-xr-xBuild/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py19
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py46
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc1
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-fdsc-table.hh8
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh10
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh44
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh50
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh8
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc8
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh10
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc33
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.hh13
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh96
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh61
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.cc76
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc51
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh35
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh47
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh15
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh7
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc57
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh1
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc69
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.h32
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh3
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.cc261
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.h98
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh139
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc144
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h13
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh3
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc202
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc44
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.cc.tmpl2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.h.tmpl2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc13
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.h2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject.h2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc18
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.h10
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-icu.cc36
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh3
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh22
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh11
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh12
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.hh43
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.rl21
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number.cc95
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh57
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh293
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-std-str.hh425
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc224
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh420
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc69
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh90
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh394
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh636
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh142
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh127
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc25
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh676
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh21
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-head-table.hh12
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hhea-table.hh61
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh52
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-kern-table.hh37
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh828
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh130
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh535
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh122
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh454
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc127
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h24
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh8
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh131
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-maxp-table.hh7
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh7
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language-static.hh15
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh87
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-table.hh21
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-unicode-ranges.hh24
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh15
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc10
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc20
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic-machine.rl2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc12
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar-machine.rl2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.cc27
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex.hh5
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc135
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh7
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh14
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh9
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh34
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh363
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-hvar-table.hh329
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh9
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh21
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh135
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.cc62
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh146
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc36
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-string-array.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.cc8
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh147
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc617
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh3
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc380
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh3
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc25
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc99
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh12
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc263
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h9
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh5
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ucd.cc18
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode-emoji-table.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc24
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb.h1
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh13
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc408
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build669
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-array.cc76
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-meta.cc5
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-number.cc29
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-color.cc348
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-glyphname.cc91
172 files changed, 9134 insertions, 4166 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am
index a76d9685839..d2e1ccdf8c8 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am
@@ -13,6 +13,8 @@ TESTS =
check_PROGRAMS =
EXTRA_DIST += harfbuzz.cc
+EXTRA_DIST += meson.build
+EXTRA_DIST += fix_get_types.py
# Convenience targets:
lib: $(BUILT_SOURCES) libharfbuzz.la
@@ -50,12 +52,7 @@ endif
if HAVE_FREETYPE
HBCFLAGS += $(FREETYPE_CFLAGS)
HBLIBS += $(FREETYPE_LIBS)
-# XXX
-# The following creates a recursive dependency on FreeType if FreeType is
-# built with HarfBuzz support enabled. Newer pkg-config handles that just
-# fine but pkg-config 0.26 as shipped in Ubuntu 14.04 crashes. Remove
-# in a year or two, or otherwise work around it...
-#HBDEPS += $(FREETYPE_DEPS)
+HBDEPS += $(FREETYPE_DEPS)
HBSOURCES += $(HB_FT_sources)
HBHEADERS += $(HB_FT_headers)
endif
@@ -153,6 +150,7 @@ cmake_DATA = harfbuzz-config.cmake
EXTRA_DIST += hb-version.h.in harfbuzz.pc.in harfbuzz-config.cmake.in
lib_LTLIBRARIES += libharfbuzz-subset.la
+libharfbuzz_subset_la_LINK = $(chosen_linker) $(libharfbuzz_subset_la_LDFLAGS)
libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources)
libharfbuzz_subset_la_CPPFLAGS = $(HBCFLAGS) $(CODE_COVERAGE_CFLAGS)
libharfbuzz_subset_la_LDFLAGS = $(base_link_flags) $(export_symbols_subset) $(CODE_COVERAGE_LDFLAGS)
@@ -290,7 +288,7 @@ ucd-table: gen-ucd-table.py ucd.nounihan.grouped.zip hb-common.h
use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \
|| ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false)
-vowel-constraints: gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt
+vowel-constraints: gen-vowel-constraints.py ms-use/IndicShapingInvalidCluster.txt Scripts.txt
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \
|| ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false)
@@ -334,6 +332,7 @@ noinst_PROGRAMS = \
test-buffer-serialize \
test-ot-meta \
test-ot-name \
+ test-ot-glyphname \
test-gpos-size-params \
test-gsub-would-substitute \
$(NULL)
@@ -359,6 +358,10 @@ test_ot_name_SOURCES = test-ot-name.cc
test_ot_name_CPPFLAGS = $(HBCFLAGS)
test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)
+test_ot_glyphname_SOURCES = test-ot-glyphname.cc
+test_ot_glyphname_CPPFLAGS = $(HBCFLAGS)
+test_ot_glyphname_LDADD = libharfbuzz.la $(HBLIBS)
+
test_gpos_size_params_SOURCES = test-gpos-size-params.cc
test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)
@@ -367,31 +370,6 @@ test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
-if HAVE_FREETYPE
-if HAVE_CAIRO_FT
-noinst_PROGRAMS += test-ot-color
-test_ot_color_SOURCES = test-ot-color.cc
-test_ot_color_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS)
-test_ot_color_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS)
-endif # HAVE_CAIRO_FT
-endif # HAVE_FREETYPE
-
-dist_check_SCRIPTS = \
- check-c-linkage-decls.sh \
- check-externs.sh \
- check-header-guards.sh \
- check-includes.sh \
- check-static-inits.sh \
- check-symbols.sh \
- $(NULL)
-TESTS += $(dist_check_SCRIPTS)
-
-if !WITH_LIBSTDCXX
-dist_check_SCRIPTS += \
- check-libstdc++.sh \
- $(NULL)
-endif
-
check_PROGRAMS += \
dump-indic-data \
dump-khmer-data \
@@ -411,7 +389,7 @@ dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
dump_use_data_CPPFLAGS = $(HBCFLAGS)
dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
-COMPILED_TESTS = test-algs test-iter test-meta test-number test-ot-tag test-unicode-ranges test-bimap
+COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-unicode-ranges test-bimap
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
check_PROGRAMS += $(COMPILED_TESTS)
@@ -421,6 +399,10 @@ test_algs_SOURCES = test-algs.cc hb-static.cc
test_algs_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_algs_LDADD = $(COMPILED_TESTS_LDADD)
+test_array_SOURCES = test-array.cc
+test_array_CPPFLAGS = $(HBCFLAGS)
+test_array_LDADD = libharfbuzz.la $(HBLIBS)
+
test_iter_SOURCES = test-iter.cc hb-static.cc
test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_iter_LDADD = $(COMPILED_TESTS_LDADD)
@@ -445,8 +427,25 @@ test_bimap_SOURCES = test-bimap.cc hb-static.cc
test_bimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_bimap_LDADD = $(COMPILED_TESTS_LDADD)
+dist_check_SCRIPTS = \
+ check-c-linkage-decls.sh \
+ check-externs.sh \
+ check-header-guards.sh \
+ check-includes.sh \
+ check-static-inits.sh \
+ check-symbols.sh \
+ $(NULL)
+TESTS += $(dist_check_SCRIPTS)
+
+if !WITH_LIBSTDCXX
+dist_check_SCRIPTS += \
+ check-libstdc++.sh \
+ $(NULL)
+endif
+
TESTS_ENVIRONMENT = \
srcdir="$(srcdir)" \
+ builddir="$(builddir)" \
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
HBSOURCES="$(HBSOURCES)" \
HBHEADERS="$(HBHEADERS)" \
@@ -456,7 +455,16 @@ if HAVE_INTROSPECTION
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS = HarfBuzz-0.0.gir # What does the 0 mean anyway?!
-INTROSPECTION_SCANNER_ARGS = -I$(srcdir) -n hb --identifier-prefix=hb_ --warn-all
+INTROSPECTION_SCANNER_ARGS = \
+ -I$(srcdir) \
+ --warn-all --verbose \
+ --namespace=HarfBuzz \
+ --nsversion=0.0 \
+ --symbol-prefix=hb \
+ --symbol-prefix=hb_gobject \
+ --identifier-prefix=hb_ \
+ --pkg-export=harfbuzz-gobject \
+ --c-include=hb-gobject.h
INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
INTROSPECTION_SCANNER_ENV = CC="$(CC)"
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
index cbbad90d22f..81b5cde7a49 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources
@@ -35,6 +35,8 @@ HB_BASE_sources = \
hb-config.hh \
hb-debug.hh \
hb-dispatch.hh \
+ hb-draw.cc \
+ hb-draw.hh \
hb-face.cc \
hb-face.hh \
hb-fallback-shape.cc \
@@ -57,6 +59,7 @@ HB_BASE_sources = \
hb-ot-cff-common.hh \
hb-ot-cff1-table.cc \
hb-ot-cff1-table.hh \
+ hb-ot-cff1-std-str.hh \
hb-ot-cff2-table.cc \
hb-ot-cff2-table.hh \
hb-ot-cmap-table.hh \
@@ -192,6 +195,7 @@ HB_BASE_headers = \
hb-buffer.h \
hb-common.h \
hb-deprecated.h \
+ hb-draw.h \
hb-face.h \
hb-font.h \
hb-map.h \
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/check-libstdc++.sh b/Build/source/libs/harfbuzz/harfbuzz-src/src/check-libstdc++.sh
index ce0bdab755f..a7b4c495ffb 100755
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/check-libstdc++.sh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/check-libstdc++.sh
@@ -22,8 +22,7 @@ fi
tested=false
# harfbuzz-icu links to libstdc++ because icu does.
-# harfbuzz-subset uses libstdc++.
-for soname in harfbuzz harfbuzz-gobject; do
+for soname in harfbuzz harfbuzz-subset harfbuzz-gobject; do
for suffix in so dylib; do
so=$libs/lib$soname.$suffix
if ! test -f "$so"; then continue; fi
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/check-static-inits.sh b/Build/source/libs/harfbuzz/harfbuzz-src/src/check-static-inits.sh
index def25c70143..cdfdee8fc40 100755
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/check-static-inits.sh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/check-static-inits.sh
@@ -4,7 +4,7 @@ LC_ALL=C
export LC_ALL
test -z "$srcdir" && srcdir=.
-test -z "$libs" && libs=.libs
+test -z "$builddir" && builddir=.
stat=0
if which objdump 2>/dev/null >/dev/null; then
@@ -14,18 +14,21 @@ else
exit 77
fi
-OBJS=$libs/*.o
+OBJS=$(find $builddir/ -name '*.o')
if test "x`echo $OBJS`" = "x$OBJS" 2>/dev/null >/dev/null; then
echo "check-static-inits.sh: object files not found; skipping test"
exit 77
fi
+tested=false
+
echo "Checking that no object file has static initializers"
for obj in $OBJS; do
if objdump -t "$obj" | grep '[.][cd]tors' | grep -v '\<00*\>'; then
echo "Ouch, $obj has static initializers/finalizers"
stat=1
fi
+ tested=true
done
echo "Checking that no object file has lazy static C++ constructors/destructors or other such stuff"
@@ -35,6 +38,12 @@ for obj in $OBJS; do
echo "Ouch, $obj has lazy static C++ constructors/destructors or other such stuff"
stat=1
fi
+ tested=true
done
+if ! $tested; then
+ echo "check-static-inits.sh: no objects found; skipping test"
+ exit 77
+fi
+
exit $stat
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/check-symbols.sh b/Build/source/libs/harfbuzz/harfbuzz-src/src/check-symbols.sh
index f181b631212..a6ca1c2d6c1 100755
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/check-symbols.sh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/check-symbols.sh
@@ -4,10 +4,11 @@ LC_ALL=C
export LC_ALL
test -z "$srcdir" && srcdir=.
+test -z "$builddir" && builddir=.
test -z "$libs" && libs=.libs
stat=0
-IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_.*\|llvm_.*'
+IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_.*\|llvm_.*\|flush_fn_list\|writeout_fn_list'
if which nm 2>/dev/null >/dev/null; then
:
@@ -26,7 +27,7 @@ for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
symprefix=
if test $suffix = dylib; then symprefix=_; fi
- EXPORTED_SYMBOLS=`nm "$so" | grep ' [BCDGINRST] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`
+ EXPORTED_SYMBOLS=`nm "$so" | grep ' [BCDGIRST] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`
prefix=$symprefix`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
@@ -36,7 +37,7 @@ for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
stat=1
fi
- def=$soname.def
+ def=$builddir/$soname.def
if ! test -f "$def"; then
echo "'$def' not found; skipping"
else
@@ -47,9 +48,9 @@ for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
# cheat: copy the last line from the def file!
tail -n1 "$def"
} | c++filt | diff "$def" - >&2 || stat=1
- fi
- tested=true
+ tested=true
+ fi
done
done
if ! $tested; then
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/fix_get_types.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/fix_get_types.py
new file mode 100644
index 00000000000..f5df60522a9
--- /dev/null
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/fix_get_types.py
@@ -0,0 +1,15 @@
+import re
+import argparse
+
+if __name__=='__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('input')
+ parser.add_argument('output')
+ args = parser.parse_args()
+
+ with open(args.input, 'r') as inp:
+ with open(args.output, 'w') as out:
+ for l in inp.readlines():
+ l = re.sub('_t_get_type', '_get_type', l)
+ l = re.sub('_T \(', ' (', l)
+ out.write(l)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-arabic-table.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-arabic-table.py
index ccecb406a0b..5e4206ba695 100755
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-arabic-table.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-arabic-table.py
@@ -1,11 +1,15 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
import io, os.path, sys
if len (sys.argv) != 4:
- print ("usage: ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt", file=sys.stderr)
+ print ("""usage: ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
+
+Input files, as of Unicode 12:
+* https://unicode.org/Public/UCD/latest/ucd/ArabicShaping.txt
+* https://unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
+* https://unicode.org/Public/UCD/latest/ucd/Blocks.txt
+""", file=sys.stderr)
sys.exit (1)
files = [io.open (x, encoding='utf-8') for x in sys.argv[1:]]
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py
index 9111c698c36..37f54bc2281 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
import io, os, re, sys
@@ -15,10 +13,35 @@ for h in header_paths:
if h.endswith (".h"):
with io.open (h, encoding='utf-8') as f: headers_content.append (f.read ())
-symbols = "\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M)))
+symbols = sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M))
+if '--experimental-api' not in sys.argv:
+ # Move these to harfbuzz-sections.txt when got stable
+ experimental_symbols = \
+"""hb_font_draw_glyph
+hb_draw_funcs_t
+hb_draw_close_path_func_t
+hb_draw_cubic_to_func_t
+hb_draw_line_to_func_t
+hb_draw_move_to_func_t
+hb_draw_quadratic_to_func_t
+hb_draw_funcs_create
+hb_draw_funcs_destroy
+hb_draw_funcs_is_immutable
+hb_draw_funcs_make_immutable
+hb_draw_funcs_reference
+hb_draw_funcs_set_close_path_func
+hb_draw_funcs_set_cubic_to_func
+hb_draw_funcs_set_line_to_func
+hb_draw_funcs_set_move_to_func
+hb_draw_funcs_set_quadratic_to_func
+hb_font_get_var_coords_design
+hb_ot_layout_closure_lookups
+hb_ot_layout_closure_features""".splitlines ()
+ symbols = [x for x in symbols if x not in experimental_symbols]
+symbols = "\n".join (symbols)
result = symbols if os.environ.get('PLAIN_LIST', '') else """EXPORTS
%s
-LIBRARY lib%s-0.dll""" % (symbols, output_file.replace ('.def', ''))
+LIBRARY lib%s-0.dll""" % (symbols, output_file.replace ('src/', '').replace ('.def', ''))
with open (output_file, "w") as f: f.write (result)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-emoji-table.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-emoji-table.py
index 49770d4fd8b..c02febca1ad 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-emoji-table.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-emoji-table.py
@@ -1,13 +1,15 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
-from __future__ import print_function, division, absolute_import
import sys
import os.path
from collections import OrderedDict
import packTab
if len (sys.argv) != 2:
- print("usage: ./gen-emoji-table.py emoji-data.txt", file=sys.stderr)
+ print("""usage: ./gen-emoji-table.py emoji-data.txt
+
+Input file, as of Unicode 12:
+* https://www.unicode.org/Public/emoji/12.0/emoji-data.txt""", file=sys.stderr)
sys.exit (1)
f = open(sys.argv[1])
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-indic-table.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-indic-table.py
index 912b1d7ea2c..e9d152acd27 100755
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-indic-table.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-indic-table.py
@@ -1,11 +1,14 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
import io, sys
if len (sys.argv) != 4:
- print ("usage: ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt", file=sys.stderr)
+ print ("""usage: ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
+
+Input files, as of Unicode 12:
+* https://unicode.org/Public/UCD/latest/ucd/IndicSyllabicCategory.txt
+* https://unicode.org/Public/UCD/latest/ucd/IndicPositionalCategory.txt
+* https://unicode.org/Public/UCD/latest/ucd/Blocks.txt""", file=sys.stderr)
sys.exit (1)
ALLOWED_SINGLES = [0x00A0, 0x25CC]
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-os2-unicode-ranges.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-os2-unicode-ranges.py
index 515f4ca1492..4d433c50b38 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-os2-unicode-ranges.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-os2-unicode-ranges.py
@@ -1,22 +1,13 @@
-#!/usr/bin/python
-
-# -*- coding: utf-8 -*-
+#!/usr/bin/env python3
# Generates the code for a sorted unicode range array as used in hb-ot-os2-unicode-ranges.hh
# Input is a tab seperated list of unicode ranges from the otspec
# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur).
-from __future__ import print_function, division, absolute_import
-
import io
import re
import sys
-try:
- reload(sys)
- sys.setdefaultencoding('utf-8')
-except NameError:
- pass # Python 3
print ("""static OS2Range _hb_os2_unicode_ranges[] =
{""")
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py
index 49f5b30bbe5..958a6e7c097 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
"""Generator of the mapping from OpenType tags to BCP 47 tags and vice
versa.
@@ -18,18 +18,11 @@ first BCP 47 tag happens to be the chosen disambiguated tag. In that
case, the fallback behavior will choose the right tag anyway.
"""
-from __future__ import absolute_import, division, print_function, unicode_literals
-
import collections
-try:
- from HTMLParser import HTMLParser
- def write (s):
- print (s.encode ('utf-8'), end='')
-except ImportError:
- from html.parser import HTMLParser
- def write (s):
- sys.stdout.flush ()
- sys.stdout.buffer.write (s.encode ('utf-8'))
+from html.parser import HTMLParser
+def write (s):
+ sys.stdout.flush ()
+ sys.stdout.buffer.write (s.encode ('utf-8'))
import io
import itertools
import re
@@ -37,16 +30,16 @@ import sys
import unicodedata
if len (sys.argv) != 3:
- print ('usage: ./gen-tag-table.py languagetags language-subtag-registry', file=sys.stderr)
+ print ('''usage: ./gen-tag-table.py languagetags language-subtag-registry
+
+Input files, as of Unicode 12:
+* https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
+* https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry''', file=sys.stderr)
sys.exit (1)
-try:
- from html import unescape
- def html_unescape (parser, entity):
- return unescape (entity)
-except ImportError:
- def html_unescape (parser, entity):
- return parser.unescape (entity)
+from html import unescape
+def html_unescape (parser, entity):
+ return unescape (entity)
def expect (condition, message=None):
if not condition:
@@ -54,7 +47,7 @@ def expect (condition, message=None):
raise AssertionError
raise AssertionError (message)
-# from http://www-01.sil.org/iso639-3/iso-639-3.tab
+# from https://www-01.sil.org/iso639-3/iso-639-3.tab
ISO_639_3_TO_1 = {
'aar': 'aa',
'abk': 'ab',
@@ -754,7 +747,7 @@ ot.add_language ('und-Syre', 'SYRE')
ot.add_language ('und-Syrj', 'SYRJ')
ot.add_language ('und-Syrn', 'SYRN')
-bcp_47.names['xst'] = u"Silt'e"
+bcp_47.names['xst'] = "Silt'e"
bcp_47.scopes['xst'] = ' (retired code)'
bcp_47.macrolanguages['xst'] = {'stv', 'wle'}
@@ -861,7 +854,7 @@ def hb_tag (tag):
Returns:
A snippet of C++ representing ``tag``.
"""
- return u"HB_TAG('%s','%s','%s','%s')" % tuple (('%-4s' % tag)[:4])
+ return "HB_TAG('%s','%s','%s','%s')" % tuple (('%-4s' % tag)[:4])
def get_variant_set (name):
"""Return a set of variant language names from a name.
@@ -873,7 +866,7 @@ def get_variant_set (name):
Returns:
A set of normalized language names.
"""
- return set (unicodedata.normalize ('NFD', n.replace ('\u2019', u"'"))
+ return set (unicodedata.normalize ('NFD', n.replace ('\u2019', "'"))
.encode ('ASCII', 'ignore')
.strip ()
for n in re.split ('[\n(),]', name) if n)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-ucd-table.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-ucd-table.py
index 552c3c675c1..21788365524 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-ucd-table.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-ucd-table.py
@@ -1,13 +1,14 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division, absolute_import
+#!/usr/bin/env python3
import io, os.path, sys, re
import logging
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
if len (sys.argv) not in (2, 3):
- print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml [/path/to/hb-common.h]", file=sys.stderr)
+ print("""usage: ./gen-ucd-table ucd.nounihan.grouped.xml [/path/to/hb-common.h]
+
+Input file, as of Unicode 12:
+* https://unicode.org/Public/UCD/latest/ucdxml/ucd.nounihan.grouped.zip""", file=sys.stderr)
sys.exit(1)
# https://github.com/harfbuzz/packtab
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 4523fb8ed76..0cbb52906c6 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
@@ -1,13 +1,17 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# flake8: noqa
-from __future__ import print_function, division, absolute_import
-
import io
import sys
if len (sys.argv) != 5:
- print ("usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt", file=sys.stderr)
+ print ("""usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
+
+Input file, as of Unicode 12:
+* https://unicode.org/Public/UCD/latest/ucd/IndicSyllabicCategory.txt
+* https://unicode.org/Public/UCD/latest/ucd/IndicPositionalCategory.txt
+* https://unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
+* https://unicode.org/Public/UCD/latest/ucd/Blocks.txt""", file=sys.stderr)
sys.exit (1)
BLACKLISTED_BLOCKS = ["Thai", "Lao"]
@@ -147,18 +151,13 @@ property_names = [
'Overstruck',
]
-try:
- basestring
-except NameError:
- basestring = str
-
class PropertyValue(object):
def __init__(self, name_):
self.name = name_
def __str__(self):
return self.name
def __eq__(self, other):
- return self.name == (other if isinstance(other, basestring) else other.name)
+ return self.name == (other if isinstance(other, str) else other.name)
def __ne__(self, other):
return not (self == other)
def __hash__(self):
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py
index 8ca90c819cb..0a0337f27e5 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
"""Generator of the function to prohibit certain vowel sequences.
@@ -6,26 +6,23 @@ It creates ``_hb_preprocess_text_vowel_constraints``, which inserts dotted
circles into sequences prohibited by the USE script development spec.
This function should be used as the ``preprocess_text`` of an
``hb_ot_complex_shaper_t``.
-"""
-from __future__ import absolute_import, division, print_function, unicode_literals
+"""
import collections
-try:
- from HTMLParser import HTMLParser
- def write (s):
- print (s.encode ('utf-8'), end='')
-except ImportError:
- from html.parser import HTMLParser
- def write (s):
- sys.stdout.flush ()
- sys.stdout.buffer.write (s.encode ('utf-8'))
+from html.parser import HTMLParser
+def write (s):
+ sys.stdout.flush ()
+ sys.stdout.buffer.write (s.encode ('utf-8'))
import itertools
import io
import sys
if len (sys.argv) != 3:
- print ('usage: ./gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt', file=sys.stderr)
+ print ("""usage: ./gen-vowel-constraints.py ms-use/IndicShapingInvalidCluster.txt Scripts.txt
+
+Input file, as of Unicode 12:
+* https://unicode.org/Public/UCD/latest/ucd/Scripts.txt""", file=sys.stderr)
sys.exit (1)
with io.open (sys.argv[2], encoding='utf-8') as f:
@@ -84,7 +81,8 @@ class ConstraintSet (object):
else:
self._c[first] = ConstraintSet (rest)
- def _indent (self, depth):
+ @staticmethod
+ def _indent (depth):
return (' ' * depth).replace (' ', '\t')
def __str__ (self, index=0, depth=4):
@@ -92,17 +90,20 @@ class ConstraintSet (object):
indent = self._indent (depth)
if isinstance (self._c, list):
if len (self._c) == 0:
+ assert index == 2, 'Cannot use `matched` for this constraint; the general case has not been implemented'
s.append ('{}matched = true;\n'.format (indent))
elif len (self._c) == 1:
+ assert index == 1, 'Cannot use `matched` for this constraint; the general case has not been implemented'
s.append ('{}matched = 0x{:04X}u == buffer->cur ({}).codepoint;\n'.format (indent, next (iter (self._c)), index or ''))
else:
- s.append ('{}if (0x{:04X}u == buffer->cur ({}).codepoint &&\n'.format (indent, self._c[0], index))
- s.append ('{}buffer->idx + {} < count &&\n'.format (self._indent (depth + 2), len (self._c)))
+ s.append ('{}if (0x{:04X}u == buffer->cur ({}).codepoint &&\n'.format (indent, self._c[0], index or ''))
+ if index:
+ s.append ('{}buffer->idx + {} < count &&\n'.format (self._indent (depth + 2), index + 1))
for i, cp in enumerate (self._c[1:], start=1):
s.append ('{}0x{:04X}u == buffer->cur ({}).codepoint{}\n'.format (
self._indent (depth + 2), cp, index + i, ')' if i == len (self._c) - 1 else ' &&'))
s.append ('{}{{\n'.format (indent))
- for i in range (len (self._c)):
+ for i in range (index + 1):
s.append ('{}buffer->next_glyph ();\n'.format (self._indent (depth + 1)))
s.append ('{}_output_dotted_circle (buffer);\n'.format (self._indent (depth + 1)))
s.append ('{}}}\n'.format (indent))
@@ -128,7 +129,12 @@ class ConstraintSet (object):
constraints = {}
with io.open (sys.argv[1], encoding='utf-8') as f:
- constraints_header = [f.readline ().strip () for i in range (2)]
+ constraints_header = []
+ while True:
+ line = f.readline ().strip ()
+ if line == '#':
+ break
+ constraints_header.append(line)
for line in f:
j = line.find ('#')
if j >= 0:
@@ -147,7 +153,7 @@ print ('/* == Start of generated functions == */')
print ('/*')
print (' * The following functions are generated by running:')
print (' *')
-print (' * %s use Scripts.txt' % sys.argv[0])
+print (' * %s ms-use/IndicShapingInvalidCluster.txt Scripts.txt' % sys.argv[0])
print (' *')
print (' * on files with these headers:')
print (' *')
@@ -185,7 +191,7 @@ print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB
print ('\t\t\t\t hb_buffer_t *buffer,')
print ('\t\t\t\t hb_font_t *font HB_UNUSED)')
print ('{')
-print ('#if defined(HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS)')
+print ('#ifdef HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS')
print (' return;')
print ('#endif')
print (' if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)')
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc
index 251a0654dc4..6a07a9e0db2 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/harfbuzz.cc
@@ -4,6 +4,7 @@
#include "hb-buffer-serialize.cc"
#include "hb-buffer.cc"
#include "hb-common.cc"
+#include "hb-draw.cc"
#include "hb-face.cc"
#include "hb-fallback-shape.cc"
#include "hb-font.cc"
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-fdsc-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-fdsc-table.hh
index 604d5bcf054..4bc97b742bb 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-fdsc-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-fdsc-table.hh
@@ -65,7 +65,7 @@ struct FontDescriptor
protected:
Tag tag; /* The 4-byte table tag name. */
union {
- HBFixed value; /* The value for the descriptor tag. */
+ HBFixed value; /* The value for the descriptor tag. */
HBUINT32 nalfType; /* If the tag is `nalf`, see non_alphabetic_value_t */
} u;
public:
@@ -80,10 +80,10 @@ struct fdsc
Weight = HB_TAG ('w','g','h','t'),
/* Percent weight relative to regular weight.
* (defaul value: 1.0) */
- Width = HB_TAG ('w','d','t','h'),
+ Width = HB_TAG ('w','d','t','h'),
/* Percent width relative to regular width.
* (default value: 1.0) */
- Slant = HB_TAG ('s','l','n','t'),
+ Slant = HB_TAG ('s','l','n','t'),
/* Angle of slant in degrees, where positive
* is clockwise from straight up.
* (default value: 0.0) */
@@ -108,7 +108,7 @@ struct fdsc
}
protected:
- HBFixed version; /* Version number of the font descriptors
+ HBFixed version; /* Version number of the font descriptors
* table (0x00010000 for the current version). */
LArrayOf<FontDescriptor>
descriptors; /* List of tagged-coordinate pairs style descriptors
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh
index ef988841a94..f2785a6f588 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-ankr-table.hh
@@ -66,7 +66,7 @@ struct ankr
{
const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
if (!offset)
- return Null(Anchor);
+ return Null (Anchor);
const GlyphAnchors &anchors = &(this+anchorData) + *offset;
return anchors[i];
}
@@ -81,7 +81,7 @@ struct ankr
}
protected:
- HBUINT16 version; /* Version number (set to zero) */
+ HBUINT16 version; /* Version number (set to zero) */
HBUINT16 flags; /* Flags (currently unused; set to zero) */
LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors>>>
lookupTable; /* Offset to the table's lookup table */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh
index 473f2cdcd27..f186917fc62 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh
@@ -303,7 +303,7 @@ struct LookupFormat10
const typename T::type get_value_or_null (hb_codepoint_t glyph_id) const
{
if (!(firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount))
- return Null(T);
+ return Null (T);
const HBUINT8 *p = &valueArrayZ[(glyph_id - firstGlyph) * valueSize];
@@ -358,7 +358,7 @@ struct Lookup
case 10: return u.format10.get_value_or_null (glyph_id);
default:
const T *v = get_value (glyph_id, num_glyphs);
- return v ? *v : Null(T);
+ return v ? *v : Null (T);
}
}
@@ -825,7 +825,7 @@ struct hb_aat_apply_context_t :
HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
hb_font_t *font_,
hb_buffer_t *buffer_,
- hb_blob_t *blob = const_cast<hb_blob_t *> (&Null(hb_blob_t)));
+ hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
HB_INTERNAL ~hb_aat_apply_context_t ();
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh
index 788d4084a1f..359e859cfc6 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-feat-table.hh
@@ -129,6 +129,11 @@ struct FeatureName
hb_ot_name_id_t get_feature_name_id () const { return nameIndex; }
+ bool is_exclusive () const { return featureFlags & Exclusive; }
+
+ /* A FeatureName with no settings is meaningless */
+ bool has_data () const { return nSettings; }
+
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -139,7 +144,7 @@ struct FeatureName
protected:
HBUINT16 feature; /* Feature type. */
HBUINT16 nSettings; /* The number of records in the setting name array. */
- LOffsetTo<UnsizedArrayOf<SettingName>, false>
+ LNNOffsetTo<UnsizedArrayOf<SettingName>>
settingTableZ; /* Offset in bytes from the beginning of this table to
* this feature's setting name array. The actual type of
* record this offset refers to will depend on the
@@ -172,6 +177,9 @@ struct feat
return featureNameCount;
}
+ bool exposes_feature (hb_aat_layout_feature_type_t feature_type) const
+ { return get_feature (feature_type).has_data (); }
+
const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
{ return namesZ.bsearch (featureNameCount, feature_type); }
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh
index e1787d10c67..49506e9f5ab 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-just-table.hh
@@ -51,10 +51,10 @@ struct ActionSubrecordHeader
return_trace (likely (c->check_struct (this)));
}
- HBUINT16 actionClass; /* The JustClass value associated with this
+ HBUINT16 actionClass; /* The JustClass value associated with this
* ActionSubrecord. */
- HBUINT16 actionType; /* The type of postcompensation action. */
- HBUINT16 actionLength; /* Length of this ActionSubrecord record, which
+ HBUINT16 actionType; /* The type of postcompensation action. */
+ HBUINT16 actionLength; /* Length of this ActionSubrecord record, which
* must be a multiple of 4. */
public:
DEFINE_SIZE_STATIC (6);
@@ -70,11 +70,11 @@ struct DecompositionAction
ActionSubrecordHeader
header;
- HBFixed lowerLimit; /* If the distance factor is less than this value,
+ HBFixed lowerLimit; /* If the distance factor is less than this value,
* then the ligature is decomposed. */
- HBFixed upperLimit; /* If the distance factor is greater than this value,
+ HBFixed upperLimit; /* If the distance factor is greater than this value,
* then the ligature is decomposed. */
- HBUINT16 order; /* Numerical order in which this ligature will
+ HBUINT16 order; /* Numerical order in which this ligature will
* be decomposed; you may want infrequent ligatures
* to decompose before more frequent ones. The ligatures
* on the line of text will decompose in increasing
@@ -118,14 +118,14 @@ struct ConditionalAddGlyphAction
protected:
ActionSubrecordHeader
header;
- HBFixed substThreshold; /* Distance growth factor (in ems) at which
+ HBFixed substThreshold; /* Distance growth factor (in ems) at which
* this glyph is replaced and the growth factor
* recalculated. */
- HBGlyphID addGlyph; /* Glyph to be added as kashida. If this value is
+ HBGlyphID addGlyph; /* Glyph to be added as kashida. If this value is
* 0xFFFF, no extra glyph will be added. Note that
* generally when a glyph is added, justification
* will need to be redone. */
- HBGlyphID substGlyph; /* Glyph to be substituted for this glyph if the
+ HBGlyphID substGlyph; /* Glyph to be substituted for this glyph if the
* growth factor equals or exceeds the value of
* substThreshold. */
public:
@@ -143,16 +143,16 @@ struct DuctileGlyphAction
protected:
ActionSubrecordHeader
header;
- HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
+ HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
* This would normally be 0x64756374 ('duct'),
* but you may use any axis the font contains. */
- HBFixed minimumLimit; /* The lowest value for the ductility axis tha
+ HBFixed minimumLimit; /* The lowest value for the ductility axis tha
* still yields an acceptable appearance. Normally
* this will be 1.0. */
- HBFixed noStretchValue; /* This is the default value that corresponds to
+ HBFixed noStretchValue; /* This is the default value that corresponds to
* no change in appearance. Normally, this will
* be 1.0. */
- HBFixed maximumLimit; /* The highest value for the ductility axis that
+ HBFixed maximumLimit; /* The highest value for the ductility axis that
* still yields an acceptable appearance. */
public:
DEFINE_SIZE_STATIC (22);
@@ -169,8 +169,8 @@ struct RepeatedAddGlyphAction
protected:
ActionSubrecordHeader
header;
- HBUINT16 flags; /* Currently unused; set to 0. */
- HBGlyphID glyph; /* Glyph that should be added if the distance factor
+ HBUINT16 flags; /* Currently unused; set to 0. */
+ HBGlyphID glyph; /* Glyph that should be added if the distance factor
* is growing. */
public:
DEFINE_SIZE_STATIC (10);
@@ -271,14 +271,14 @@ struct JustWidthDeltaEntry
};
protected:
- HBFixed beforeGrowLimit;/* The ratio by which the advance width of the
+ HBFixed beforeGrowLimit;/* The ratio by which the advance width of the
* glyph is permitted to grow on the left or top side. */
- HBFixed beforeShrinkLimit;
+ HBFixed beforeShrinkLimit;
/* The ratio by which the advance width of the
* glyph is permitted to shrink on the left or top side. */
- HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph
+ HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph
* is permitted to shrink on the left or top side. */
- HBFixed afterShrinkLimit;
+ HBFixed afterShrinkLimit;
/* The ratio by which the advance width of the glyph
* is at most permitted to shrink on the right or
* bottom side. */
@@ -361,7 +361,7 @@ struct JustificationHeader
OffsetTo<JustificationCategory>
justClassTable; /* Offset to the justification category state table. */
OffsetTo<WidthDeltaCluster>
- wdcTable; /* Offset from start of justification table to start
+ wdcTable; /* Offset from start of justification table to start
* of the subtable containing the width delta factors
* for the glyphs in your font.
*
@@ -372,7 +372,7 @@ struct JustificationHeader
*
* The postcompensation subtable, if present in the font. */
Lookup<OffsetTo<WidthDeltaCluster>>
- lookupTable; /* Lookup table associating glyphs with width delta
+ lookupTable; /* Lookup table associating glyphs with width delta
* clusters. See the description of Width Delta Clusters
* table for details on how to interpret the lookup values. */
@@ -397,7 +397,7 @@ struct just
protected:
FixedVersion<>version; /* Version of the justification table
* (0x00010000u for version 1.0). */
- HBUINT16 format; /* Format of the justification table (set to 0). */
+ HBUINT16 format; /* Format of the justification table (set to 0). */
OffsetTo<JustificationHeader>
horizData; /* Byte offset from the start of the justification table
* to the header for tables that contain justification
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 be1b339aa3c..6ad32b30002 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
@@ -281,35 +281,28 @@ struct KerxSubTableFormat1
hb_glyph_position_t &o = buffer->pos[idx];
- /* Testing shows that CoreText only applies kern (cross-stream or not)
- * if none has been applied by previous subtables. That is, it does
- * NOT seem to accumulate as otherwise implied by specs. */
-
- /* The following flag is undocumented in the spec, but described
- * in the 'kern' table example. */
- if (v == -0x8000)
- {
- o.attach_type() = ATTACH_TYPE_NONE;
- o.attach_chain() = 0;
- o.x_offset = o.y_offset = 0;
- }
- else if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+ if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
{
if (crossStream)
{
- if (buffer->pos[idx].attach_type() && !buffer->pos[idx].y_offset)
+ /* The following flag is undocumented in the spec, but described
+ * in the 'kern' table example. */
+ if (v == -0x8000)
{
- o.y_offset = c->font->em_scale_y (v);
+ o.attach_type() = ATTACH_TYPE_NONE;
+ o.attach_chain() = 0;
+ o.y_offset = 0;
+ }
+ else if (o.attach_type())
+ {
+ o.y_offset += c->font->em_scale_y (v);
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
}
}
else if (buffer->info[idx].mask & kern_mask)
{
- if (!buffer->pos[idx].x_offset)
- {
- buffer->pos[idx].x_advance += c->font->em_scale_x (v);
- buffer->pos[idx].x_offset += c->font->em_scale_x (v);
- }
+ o.x_advance += c->font->em_scale_x (v);
+ o.x_offset += c->font->em_scale_x (v);
}
}
else
@@ -317,19 +310,22 @@ struct KerxSubTableFormat1
if (crossStream)
{
/* CoreText doesn't do crossStream kerning in vertical. We do. */
- if (buffer->pos[idx].attach_type() && !buffer->pos[idx].x_offset)
+ if (v == -0x8000)
+ {
+ o.attach_type() = ATTACH_TYPE_NONE;
+ o.attach_chain() = 0;
+ o.x_offset = 0;
+ }
+ else if (o.attach_type())
{
- o.x_offset = c->font->em_scale_x (v);
+ o.x_offset += c->font->em_scale_x (v);
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
}
}
else if (buffer->info[idx].mask & kern_mask)
{
- if (!buffer->pos[idx].y_offset)
- {
- buffer->pos[idx].y_advance += c->font->em_scale_y (v);
- buffer->pos[idx].y_offset += c->font->em_scale_y (v);
- }
+ o.y_advance += c->font->em_scale_y (v);
+ o.y_offset += c->font->em_scale_y (v);
}
}
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh
index d8df579f507..9d04c7102ef 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh
@@ -948,8 +948,10 @@ struct Chain
hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType;
hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting;
retry:
- const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type);
- if (info && info->setting == setting)
+ // Check whether this type/setting pair was requested in the map, and if so, apply its flags.
+ // (The search here only looks at the type and setting fields of feature_info_t.)
+ hb_aat_map_builder_t::feature_info_t info = { type, setting, false, 0 };
+ if (map->features.bsearch (info))
{
flags &= feature.disableFlags;
flags |= feature.enableFlags;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh
index 4e0234074fe..8c04a6482ff 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-opbd-table.hh
@@ -160,8 +160,8 @@ struct opbd
* Format 0 indicates distance and Format 1 indicates
* control point. */
union {
- opbdFormat0 format0;
- opbdFormat1 format1;
+ opbdFormat0 format0;
+ opbdFormat1 format1;
} u;
public:
DEFINE_SIZE_MIN (8);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh
index 99dddd88268..baa1c72020f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh
@@ -62,7 +62,7 @@ struct TrackTableEntry
}
protected:
- HBFixed track; /* Track value for this record. */
+ HBFixed track; /* Track value for this record. */
NameID trackNameID; /* The 'name' table index for this track.
* (a short word or phrase like "loose"
* or "very tight") */
@@ -141,7 +141,7 @@ struct TrackData
protected:
HBUINT16 nTracks; /* Number of separate tracks included in this table. */
HBUINT16 nSizes; /* Number of point sizes included in this table. */
- LOffsetTo<UnsizedArrayOf<HBFixed>, false>
+ LNNOffsetTo<UnsizedArrayOf<HBFixed>>
sizeTable; /* Offset from start of the tracking table to
* Array[nSizes] of size values.. */
UnsizedArrayOf<TrackTableEntry>
@@ -210,8 +210,8 @@ struct trak
protected:
FixedVersion<>version; /* Version of the tracking table
- * (0x00010000u for version 1.0). */
- HBUINT16 format; /* Format of the tracking table (set to 0). */
+ * (0x00010000u for version 1.0). */
+ HBUINT16 format; /* Format of the tracking table (set to 0). */
OffsetTo<TrackData>
horizData; /* Offset from start of tracking table to TrackData
* for horizontal text (or 0 if none). */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc
index 4e506de16e8..49c908fd16f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc
@@ -55,7 +55,7 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p
face (font->face),
buffer (buffer_),
sanitizer (),
- ankr_table (&Null(AAT::ankr)),
+ ankr_table (&Null (AAT::ankr)),
lookup_index (0),
debug_depth (0)
{
@@ -172,11 +172,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
const hb_aat_feature_mapping_t *
hb_aat_layout_find_feature_mapping (hb_tag_t tag)
{
- return (const hb_aat_feature_mapping_t *) hb_bsearch (&tag,
- feature_mappings,
- ARRAY_LENGTH (feature_mappings),
- sizeof (feature_mappings[0]),
- hb_aat_feature_mapping_t::cmp);
+ return hb_sorted_array (feature_mappings).bsearch (tag);
}
#endif
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh
index 8310bfcc2d2..5e4e3bda154 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh
@@ -39,14 +39,8 @@ struct hb_aat_feature_mapping_t
hb_aat_layout_feature_selector_t selectorToEnable;
hb_aat_layout_feature_selector_t selectorToDisable;
- HB_INTERNAL static int cmp (const void *key_, const void *entry_)
- {
- hb_tag_t key = * (unsigned int *) key_;
- const hb_aat_feature_mapping_t * entry = (const hb_aat_feature_mapping_t *) entry_;
- return key < entry->otFeatureTag ? -1 :
- key > entry->otFeatureTag ? 1 :
- 0;
- }
+ int cmp (hb_tag_t key) const
+ { return key < otFeatureTag ? -1 : key > otFeatureTag ? 1 : 0; }
};
HB_INTERNAL const hb_aat_feature_mapping_t *
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc
index bc879359aae..2c38c350296 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc
@@ -33,25 +33,48 @@
#include "hb-aat-map.hh"
#include "hb-aat-layout.hh"
+#include "hb-aat-layout-feat-table.hh"
-void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
- unsigned int value)
+void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned value)
{
+ if (!face->table.feat->has_data ()) return;
+
if (tag == HB_TAG ('a','a','l','t'))
{
+ if (!face->table.feat->exposes_feature (HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES))
+ return;
feature_info_t *info = features.push();
info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
info->setting = (hb_aat_layout_feature_selector_t) value;
+ info->seq = features.length;
+ info->is_exclusive = true;
return;
}
const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
if (!mapping) return;
+ const AAT::FeatureName* feature = &face->table.feat->get_feature (mapping->aatFeatureType);
+ if (!feature->has_data ())
+ {
+ /* Special case: Chain::compile_flags will fall back to the deprecated version of
+ * small-caps if necessary, so we need to check for that possibility.
+ * https://github.com/harfbuzz/harfbuzz/issues/2307 */
+ if (mapping->aatFeatureType == HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE &&
+ mapping->selectorToEnable == HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS)
+ {
+ feature = &face->table.feat->get_feature (HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE);
+ if (!feature->has_data ()) return;
+ }
+ else return;
+ }
+
feature_info_t *info = features.push();
info->type = mapping->aatFeatureType;
info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
+ info->seq = features.length;
+ info->is_exclusive = feature->is_exclusive ();
}
void
@@ -63,7 +86,11 @@ hb_aat_map_builder_t::compile (hb_aat_map_t &m)
features.qsort ();
unsigned int j = 0;
for (unsigned int i = 1; i < features.length; i++)
- if (features[i].type != features[j].type)
+ if (features[i].type != features[j].type ||
+ /* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
+ * respectively, so we mask out the low-order bit when checking for "duplicates"
+ * (selectors referring to the same feature setting) here. */
+ (!features[i].is_exclusive && ((features[i].setting & ~1) != (features[j].setting & ~1))))
features[++j] = features[i];
features.shrink (j + 1);
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.hh
index 984a59cca5b..5a0fa705445 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.hh
@@ -64,19 +64,24 @@ struct hb_aat_map_builder_t
{
hb_aat_layout_feature_type_t type;
hb_aat_layout_feature_selector_t setting;
+ bool is_exclusive;
unsigned seq; /* For stable sorting only. */
HB_INTERNAL static int cmp (const void *pa, const void *pb)
{
const feature_info_t *a = (const feature_info_t *) pa;
const feature_info_t *b = (const feature_info_t *) pb;
- return (a->type != b->type) ? (a->type < b->type ? -1 : 1) :
- (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
+ if (a->type != b->type) return (a->type < b->type ? -1 : 1);
+ if (!a->is_exclusive &&
+ (a->setting & ~1) != (b->setting & ~1)) return (a->setting < b->setting ? -1 : 1);
+ return (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
}
- int cmp (hb_aat_layout_feature_type_t ty) const
+ /* compares type & setting only, not is_exclusive flag or seq number */
+ int cmp (const feature_info_t& f) const
{
- return (type != ty) ? (type < ty ? -1 : 1) : 0;
+ return (f.type != type) ? (f.type < type ? -1 : 1) :
+ (f.setting != setting) ? (f.setting < setting ? -1 : 1) : 0;
}
};
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 042e1c20d58..5d2a48c4694 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
@@ -360,6 +360,13 @@ struct
(hb_forward<T> (a) >= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
}
HB_FUNCOBJ (hb_max);
+struct
+{
+ template <typename T, typename T2, typename T3> constexpr auto
+ operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN
+ (hb_min (hb_max (hb_forward<T> (x), hb_forward<T2> (min)), hb_forward<T3> (max)))
+}
+HB_FUNCOBJ (hb_clamp);
/*
@@ -486,7 +493,7 @@ template <typename T>
static inline HB_CONST_FUNC unsigned int
hb_ctz (T v)
{
- if (unlikely (!v)) return 0;
+ if (unlikely (!v)) return 8 * sizeof (T);
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
if (sizeof (T) <= sizeof (unsigned int))
@@ -600,12 +607,6 @@ hb_memset (void *s, int c, unsigned int n)
return memset (s, c, n);
}
-static inline bool
-hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
-{
- return (size > 0) && (count >= ((unsigned int) -1) / size);
-}
-
static inline unsigned int
hb_ceil_to_4 (unsigned int v)
{
@@ -634,29 +635,90 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
/*
+ * Overflow checking.
+ */
+
+/* Consider __builtin_mul_overflow use here also */
+static inline bool
+hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
+{
+ return (size > 0) && (count >= ((unsigned int) -1) / size);
+}
+
+
+/*
* Sort and search.
*/
-template <typename ...Ts>
-static inline void *
-hb_bsearch (const void *key, const void *base,
- size_t nmemb, size_t size,
- int (*compar)(const void *_key, const void *_item, Ts... _ds),
- Ts... ds)
+
+template <typename K, typename V, typename ...Ts>
+static int
+_hb_cmp_method (const void *pkey, const void *pval, Ts... ds)
+{
+ const K& key = * (const K*) pkey;
+ const V& val = * (const V*) pval;
+
+ return val.cmp (key, ds...);
+}
+
+template <typename V, typename K, typename ...Ts>
+static inline bool
+hb_bsearch_impl (unsigned *pos, /* Out */
+ const K& key,
+ V* base, size_t nmemb, size_t stride,
+ int (*compar)(const void *_key, const void *_item, Ts... _ds),
+ Ts... ds)
{
+ /* This is our *only* bsearch implementation. */
+
int min = 0, max = (int) nmemb - 1;
while (min <= max)
{
int mid = ((unsigned int) min + (unsigned int) max) / 2;
- const void *p = (const void *) (((const char *) base) + (mid * size));
- int c = compar (key, p, ds...);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ V* p = (V*) (((const char *) base) + (mid * stride));
+#pragma GCC diagnostic pop
+ int c = compar ((const void *) hb_addressof (key), (const void *) p, ds...);
if (c < 0)
max = mid - 1;
else if (c > 0)
min = mid + 1;
else
- return (void *) p;
+ {
+ *pos = mid;
+ return true;
+ }
}
- return nullptr;
+ *pos = min;
+ return false;
+}
+
+template <typename V, typename K>
+static inline V*
+hb_bsearch (const K& key, V* base,
+ size_t nmemb, size_t stride = sizeof (V),
+ int (*compar)(const void *_key, const void *_item) = _hb_cmp_method<K, V>)
+{
+ unsigned pos;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar) ?
+ (V*) (((const char *) base) + (pos * stride)) : nullptr;
+#pragma GCC diagnostic pop
+}
+template <typename V, typename K, typename ...Ts>
+static inline V*
+hb_bsearch (const K& key, V* base,
+ size_t nmemb, size_t stride,
+ int (*compar)(const void *_key, const void *_item, Ts... _ds),
+ Ts... ds)
+{
+ unsigned pos;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar, ds...) ?
+ (V*) (((const char *) base) + (pos * stride)) : nullptr;
+#pragma GCC diagnostic pop
}
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 d9adf2c728e..172d9c13cc9 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
@@ -171,6 +171,24 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
unsigned int get_size () const { return length * this->get_item_size (); }
+ /*
+ * Reverse the order of items in this array in the range [start, end).
+ */
+ void reverse (unsigned start = 0, unsigned end = -1)
+ {
+ start = hb_min (start, length);
+ end = hb_min (end, length);
+
+ if (end < start + 2)
+ return;
+
+ for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--) {
+ Type temp = arrayZ[rhs];
+ arrayZ[rhs] = arrayZ[lhs];
+ arrayZ[lhs] = temp;
+ }
+ }
+
hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
{
if (!start_offset && !seg_count)
@@ -199,10 +217,11 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
template <typename T,
unsigned P = sizeof (Type),
hb_enable_if (P == 1)>
- bool in_range (const T *p, unsigned int size = T::static_size) const
+ bool check_range (const T *p, unsigned int size = T::static_size) const
{
- return ((const char *) p) >= arrayZ
- && ((const char *) p + size) <= arrayZ + length;
+ return arrayZ <= ((const char *) p)
+ && ((const char *) p) <= arrayZ + length
+ && (unsigned int) (arrayZ + length - (const char *) p) >= size;
}
/* Only call if you allocated the underlying array using malloc() or similar. */
@@ -300,23 +319,15 @@ struct hb_sorted_array_t :
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;
- while (min <= max)
+ unsigned pos;
+
+ if (bsearch_impl (x, &pos))
{
- int mid = ((unsigned int) min + (unsigned int) max) / 2;
- int c = array[mid].cmp (x);
- if (c < 0)
- max = mid - 1;
- else if (c > 0)
- min = mid + 1;
- else
- {
- if (i)
- *i = mid;
- return true;
- }
+ if (i)
+ *i = pos;
+ return true;
}
+
if (i)
{
switch (not_found)
@@ -329,14 +340,22 @@ struct hb_sorted_array_t :
break;
case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
- if (max < 0 || (max < (int) this->length && array[max].cmp (x) > 0))
- max++;
- *i = max;
+ *i = pos;
break;
}
}
return false;
}
+ template <typename T>
+ bool bsearch_impl (const T &x, unsigned *pos) const
+ {
+ return hb_bsearch_impl (pos,
+ x,
+ this->arrayZ,
+ this->length,
+ sizeof (Type),
+ _hb_cmp_method<T, Type>);
+ }
};
template <typename T> inline hb_sorted_array_t<T>
hb_sorted_array (T *array, unsigned int length)
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 cae0a4dea44..e9f3a6a52df 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh
@@ -151,9 +151,9 @@ struct hb_inc_bimap_t : hb_bimap_t
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
work[rhs] = back_map[rhs];
-
+
work.qsort (cmp_id);
-
+
clear ();
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
set (work[rhs], rhs);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.cc
index 2e72683c8b9..3ca31c5fe65 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.cc
@@ -25,18 +25,6 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-
-/* https://github.com/harfbuzz/harfbuzz/issues/1308
- * http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
- * https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html
- */
-#if !defined(_POSIX_C_SOURCE) && !defined(_MSC_VER) && !defined(__NetBSD__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-macros"
-#define _POSIX_C_SOURCE 200809L
-#pragma GCC diagnostic pop
-#endif
-
#include "hb.hh"
#include "hb-blob.hh"
@@ -201,7 +189,7 @@ hb_blob_copy_writable_or_fail (hb_blob_t *blob)
hb_blob_t *
hb_blob_get_empty ()
{
- return const_cast<hb_blob_t *> (&Null(hb_blob_t));
+ return const_cast<hb_blob_t *> (&Null (hb_blob_t));
}
/**
@@ -488,6 +476,9 @@ hb_blob_t::try_make_writable ()
#ifndef HB_NO_OPEN
#ifdef HAVE_MMAP
+# if !defined(HB_NO_RESOURCE_FORK) && defined(__APPLE__)
+# include <sys/paths.h>
+# endif
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
@@ -532,6 +523,39 @@ _hb_mapped_file_destroy (void *file_)
}
#endif
+#ifdef _PATH_RSRCFORKSPEC
+static int
+_open_resource_fork (const char *file_name, hb_mapped_file_t *file)
+{
+ size_t name_len = strlen (file_name);
+ size_t len = name_len + sizeof (_PATH_RSRCFORKSPEC);
+
+ char *rsrc_name = (char *) malloc (len);
+ if (unlikely (!rsrc_name)) return -1;
+
+ strncpy (rsrc_name, file_name, name_len);
+ strncpy (rsrc_name + name_len, _PATH_RSRCFORKSPEC,
+ sizeof (_PATH_RSRCFORKSPEC) - 1);
+
+ int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0);
+ free (rsrc_name);
+
+ if (fd != -1)
+ {
+ struct stat st;
+ if (fstat (fd, &st) != -1)
+ file->length = (unsigned long) st.st_size;
+ else
+ {
+ close (fd);
+ fd = -1;
+ }
+ }
+
+ return fd;
+}
+#endif
+
/**
* hb_blob_create_from_file:
* @file_name: font filename.
@@ -556,6 +580,19 @@ hb_blob_create_from_file (const char *file_name)
if (unlikely (fstat (fd, &st) == -1)) goto fail;
file->length = (unsigned long) st.st_size;
+
+#ifdef _PATH_RSRCFORKSPEC
+ if (unlikely (file->length == 0))
+ {
+ int rfd = _open_resource_fork (file_name, file);
+ if (rfd != -1)
+ {
+ close (fd);
+ fd = rfd;
+ }
+ }
+#endif
+
file->contents = (char *) mmap (nullptr, file->length, PROT_READ,
MAP_PRIVATE | MAP_NORESERVE, fd, 0);
@@ -579,7 +616,7 @@ fail_without_close:
HANDLE fd;
unsigned int size = strlen (file_name) + 1;
wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size);
- if (unlikely (wchar_file_name == nullptr)) goto fail_without_close;
+ if (unlikely (!wchar_file_name)) goto fail_without_close;
mbstowcs (wchar_file_name, file_name, size);
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
{
@@ -613,14 +650,14 @@ fail_without_close:
file->length = (unsigned long) GetFileSize (fd, nullptr);
file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr);
#endif
- if (unlikely (file->mapping == nullptr)) goto fail;
+ if (unlikely (!file->mapping)) goto fail;
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0);
#else
file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0);
#endif
- if (unlikely (file->contents == nullptr)) goto fail;
+ if (unlikely (!file->contents)) goto fail;
CloseHandle (fd);
return hb_blob_create (file->contents, file->length,
@@ -638,10 +675,10 @@ fail_without_close:
It's used as a fallback for systems without mmap or to read from pipes */
unsigned long len = 0, allocated = BUFSIZ * 16;
char *data = (char *) malloc (allocated);
- if (unlikely (data == nullptr)) return hb_blob_get_empty ();
+ if (unlikely (!data)) return hb_blob_get_empty ();
FILE *fp = fopen (file_name, "rb");
- if (unlikely (fp == nullptr)) goto fread_fail_without_close;
+ if (unlikely (!fp)) goto fread_fail_without_close;
while (!feof (fp))
{
@@ -652,7 +689,7 @@ fail_without_close:
can cover files like that but lets limit our fallback reader */
if (unlikely (allocated > (2 << 28))) goto fread_fail;
char *new_data = (char *) realloc (data, allocated);
- if (unlikely (new_data == nullptr)) goto fread_fail;
+ if (unlikely (!new_data)) goto fread_fail;
data = new_data;
}
@@ -666,6 +703,7 @@ fail_without_close:
len += addition;
}
+ fclose (fp);
return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data,
(hb_destroy_func_t) free);
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 6131c861773..d443edf2584 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc
@@ -438,13 +438,6 @@ hb_buffer_t::set_masks (hb_mask_t value,
if (!mask)
return;
- if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
- unsigned int count = len;
- for (unsigned int i = 0; i < count; i++)
- info[i].mask = (info[i].mask & not_mask) | value;
- return;
- }
-
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
@@ -455,27 +448,13 @@ void
hb_buffer_t::reverse_range (unsigned int start,
unsigned int end)
{
- unsigned int i, j;
-
if (end - start < 2)
return;
- for (i = start, j = end - 1; i < j; i++, j--) {
- hb_glyph_info_t t;
-
- t = info[i];
- info[i] = info[j];
- info[j] = t;
- }
+ hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end);
if (have_positions) {
- for (i = start, j = end - 1; i < j; i++, j--) {
- hb_glyph_position_t t;
-
- t = pos[i];
- pos[i] = pos[j];
- pos[j] = t;
- }
+ hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end);
}
}
@@ -612,7 +591,7 @@ done:
void
hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
{
- unsigned int cluster = (unsigned int) -1;
+ unsigned int cluster = UINT_MAX;
cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster);
_unsafe_to_break_set_mask (info, start, end, cluster);
}
@@ -628,7 +607,7 @@ hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int en
assert (start <= out_len);
assert (idx <= end);
- unsigned int cluster = (unsigned int) -1;
+ unsigned int cluster = UINT_MAX;
cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster);
cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster);
_unsafe_to_break_set_mask (out_info, start, out_len, cluster);
@@ -736,7 +715,7 @@ hb_buffer_create ()
hb_buffer_t *
hb_buffer_get_empty ()
{
- return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
+ return const_cast<hb_buffer_t *> (&Null (hb_buffer_t));
}
/**
@@ -958,7 +937,7 @@ hb_buffer_get_direction (hb_buffer_t *buffer)
*
* You can pass one of the predefined #hb_script_t values, or use
* hb_script_from_string() or hb_script_from_iso15924_tag() to get the
- * corresponding script from an ISO 15924 script tag.
+ * corresponding script from an ISO 15924 script tag.
*
* Since: 0.9.2
**/
@@ -1001,7 +980,7 @@ hb_buffer_get_script (hb_buffer_t *buffer)
* are orthogonal to the scripts, and though they are related, they are
* different concepts and should not be confused with each other.
*
- * Use hb_language_from_string() to convert from BCP 47 language tags to
+ * Use hb_language_from_string() to convert from BCP 47 language tags to
* #hb_language_t.
*
* Since: 0.9.2
@@ -1738,7 +1717,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
* @buffer: an #hb_buffer_t.
* @source: source #hb_buffer_t.
* @start: start index into source buffer to copy. Use 0 to copy from start of buffer.
- * @end: end index into source buffer to copy. Use (unsigned int) -1 to copy to end of buffer.
+ * @end: end index into source buffer to copy. Use @HB_FEATURE_GLOBAL_END to copy to end of buffer.
*
* Append (part of) contents of another buffer to this buffer.
*
@@ -1860,18 +1839,8 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
- unsigned int count = buffer->len;
- if (unlikely (!count)) return;
- hb_glyph_info_t *info = buffer->info;
-
- unsigned int start = 0;
- unsigned int end;
- for (end = start + 1; end < count; end++)
- if (info[start].cluster != info[end].cluster) {
- normalize_glyphs_cluster (buffer, start, end, backward);
- start = end;
- }
- normalize_glyphs_cluster (buffer, start, end, backward);
+ foreach_cluster (buffer, start, end)
+ normalize_glyphs_cluster (buffer, start, end, backward);
}
void
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h
index d5cb7468618..2f581f3c735 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h
@@ -365,7 +365,7 @@ hb_buffer_clear_contents (hb_buffer_t *buffer);
HB_EXTERN hb_bool_t
hb_buffer_pre_allocate (hb_buffer_t *buffer,
- unsigned int size);
+ unsigned int size);
HB_EXTERN hb_bool_t
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 b5596d94577..dce89fabeb8 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh
@@ -228,10 +228,10 @@ struct hb_buffer_t
/* Makes a copy of the glyph at idx to output and replace glyph_index */
hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index)
{
- if (unlikely (!make_room_for (0, 1))) return Crap(hb_glyph_info_t);
+ if (unlikely (!make_room_for (0, 1))) return Crap (hb_glyph_info_t);
if (unlikely (idx == len && !out_len))
- return Crap(hb_glyph_info_t);
+ return Crap (hb_glyph_info_t);
out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1];
out_info[out_len].codepoint = glyph_index;
@@ -386,7 +386,7 @@ struct hb_buffer_t
inf.cluster = cluster;
}
- int
+ unsigned int
_unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
unsigned int start, unsigned int end,
unsigned int cluster) const
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 780f61892d7..91a9b7d0d16 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
@@ -252,30 +252,27 @@ struct number_t
struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
{
// encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
- template <typename INTTYPE, int minVal, int maxVal>
- static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, int value)
+ template <typename T, typename V>
+ static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value)
{
TRACE_SERIALIZE (this);
- if (unlikely ((value < minVal || value > maxVal)))
- return_trace (false);
-
HBUINT8 *p = c->allocate_size<HBUINT8> (1);
- if (unlikely (p == nullptr)) return_trace (false);
+ if (unlikely (!p)) return_trace (false);
*p = intOp;
- INTTYPE *ip = c->allocate_size<INTTYPE> (INTTYPE::static_size);
- if (unlikely (ip == nullptr)) return_trace (false);
- *ip = (unsigned int) value;
-
- return_trace (true);
+ T *ip = c->allocate_size<T> (T::static_size);
+ if (unlikely (!ip)) return_trace (false);
+ return_trace (c->check_assign (*ip, value));
}
- static bool serialize_int4 (hb_serialize_context_t *c, int value)
- { return serialize_int<HBUINT32, 0, 0x7FFFFFFF> (c, OpCode_longintdict, value); }
+ template <typename V>
+ static bool serialize_int4 (hb_serialize_context_t *c, V value)
+ { return serialize_int<HBINT32> (c, OpCode_longintdict, value); }
- static bool serialize_int2 (hb_serialize_context_t *c, int value)
- { return serialize_int<HBUINT16, 0, 0x7FFF> (c, OpCode_shortint, value); }
+ template <typename V>
+ static bool serialize_int2 (hb_serialize_context_t *c, V value)
+ { return serialize_int<HBINT16> (c, OpCode_shortint, value); }
/* Defining null_size allows a Null object may be created. Should be safe because:
* A descendent struct Dict uses a Null pointer to indicate a missing table,
@@ -408,7 +405,7 @@ struct cff_stack_t
else
{
set_error ();
- return Crap(ELEM);
+ return Crap (ELEM);
}
}
@@ -419,7 +416,7 @@ struct cff_stack_t
else
{
set_error ();
- return Crap(ELEM);
+ return Crap (ELEM);
}
}
void pop (unsigned int n)
@@ -435,7 +432,7 @@ struct cff_stack_t
if (unlikely (count < 0))
{
set_error ();
- return Null(ELEM);
+ return Null (ELEM);
}
return elements[count - 1];
}
@@ -542,7 +539,7 @@ struct op_serializer_t
TRACE_SERIALIZE (this);
HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
- if (unlikely (d == nullptr)) return_trace (false);
+ if (unlikely (!d)) return_trace (false);
memcpy (d, &opstr.str[0], opstr.str.length);
return_trace (true);
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh
index d9ad4d0d69f..52d778ffe29 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh
@@ -76,13 +76,13 @@ struct biased_subrs_t
void fini () {}
- unsigned int get_count () const { return (subrs == nullptr) ? 0 : subrs->count; }
+ unsigned int get_count () const { return subrs ? subrs->count : 0; }
unsigned int get_bias () const { return bias; }
byte_str_t operator [] (unsigned int index) const
{
- if (unlikely ((subrs == nullptr) || index >= subrs->count))
- return Null(byte_str_t);
+ if (unlikely (!subrs || index >= subrs->count))
+ return Null (byte_str_t);
else
return (*subrs)[index];
}
@@ -551,8 +551,13 @@ struct path_procs_t
static void rcurveline (ENV &env, PARAM& param)
{
+ unsigned int arg_count = env.argStack.get_count ();
+ if (unlikely (arg_count < 8))
+ return;
+
unsigned int i = 0;
- for (; i + 6 <= env.argStack.get_count (); i += 6)
+ unsigned int curve_limit = arg_count - 2;
+ for (; i + 6 <= curve_limit; i += 6)
{
point_t pt1 = env.get_pt ();
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
@@ -562,34 +567,34 @@ struct path_procs_t
pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
PATH::curve (env, param, pt1, pt2, pt3);
}
- for (; i + 2 <= env.argStack.get_count (); i += 2)
- {
- point_t pt1 = env.get_pt ();
- pt1.move (env.eval_arg (i), env.eval_arg (i+1));
- PATH::line (env, param, pt1);
- }
+
+ point_t pt1 = env.get_pt ();
+ pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+ PATH::line (env, param, pt1);
}
static void rlinecurve (ENV &env, PARAM& param)
{
+ unsigned int arg_count = env.argStack.get_count ();
+ if (unlikely (arg_count < 8))
+ return;
+
unsigned int i = 0;
- unsigned int line_limit = (env.argStack.get_count () % 6);
+ unsigned int line_limit = arg_count - 6;
for (; i + 2 <= line_limit; i += 2)
{
point_t pt1 = env.get_pt ();
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
PATH::line (env, param, pt1);
}
- for (; i + 6 <= env.argStack.get_count (); i += 6)
- {
- point_t pt1 = env.get_pt ();
- pt1.move (env.eval_arg (i), env.eval_arg (i+1));
- point_t pt2 = pt1;
- pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
- point_t pt3 = pt2;
- pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
- PATH::curve (env, param, pt1, pt2, pt3);
- }
+
+ point_t pt1 = env.get_pt ();
+ pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+ point_t pt2 = pt1;
+ pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+ point_t pt3 = pt2;
+ pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+ PATH::curve (env, param, pt1, pt2, pt3);
}
static void vvcurveto (ENV &env, PARAM& param)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh
index 1f03d82399b..a520ca3bce5 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh
@@ -27,8 +27,6 @@
#define HB_CFF_INTERP_DICT_COMMON_HH
#include "hb-cff-interp-common.hh"
-#include <math.h>
-#include <float.h>
namespace CFF {
@@ -58,19 +56,6 @@ struct top_dict_values_t : dict_values_t<OPSTR>
}
void fini () { dict_values_t<OPSTR>::fini (); }
- unsigned int calculate_serialized_op_size (const OPSTR& opstr) const
- {
- switch (opstr.op)
- {
- case OpCode_CharStrings:
- case OpCode_FDArray:
- return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
-
- default:
- return opstr.str.length;
- }
- }
-
unsigned int charStringsOffset;
unsigned int FDArrayOffset;
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
index a72100e1aba..8d9bb2689bb 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
@@ -80,7 +80,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
{
template <typename ACC>
void init (const byte_str_t &str, ACC &acc, unsigned int fd,
- const int *coords_=nullptr, unsigned int num_coords_=0)
+ const int *coords_=nullptr, unsigned int num_coords_=0)
{
SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
@@ -90,7 +90,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
seen_blend = false;
seen_vsindex_ = false;
scalars.init ();
- do_blend = (coords != nullptr) && num_coords && (varStore != &Null(CFF2VariationStore));
+ do_blend = num_coords && coords && varStore->size;
set_ivs (acc.privateDicts[fd].ivs);
}
@@ -134,8 +134,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
if (do_blend)
{
scalars.resize (region_count);
- varStore->varStore.get_scalars (get_ivs (),
- (int *)coords, num_coords,
+ varStore->varStore.get_scalars (get_ivs (), coords, num_coords,
&scalars[0], region_count);
}
seen_blend = true;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc
index 0ae0c05f488..5b60ff4b215 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc
@@ -69,7 +69,6 @@ _hb_options_init ()
if (0 == strncmp (c, name, p - c) && strlen (name) == static_cast<size_t>(p - c)) do { u.opts.symbol = true; } while (0)
OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
- OPTION ("aat", aat);
#undef OPTION
@@ -333,14 +332,14 @@ retry:
/**
* hb_language_from_string:
* @str: (array length=len) (element-type uint8_t): a string representing
- * a BCP 47 language tag
+ * a BCP 47 language tag
* @len: length of the @str, or -1 if it is %NULL-terminated.
*
- * Converts @str representing a BCP 47 language tag to the corresponding
+ * Converts @str representing a BCP 47 language tag to the corresponding
* #hb_language_t.
*
* Return value: (transfer none):
- * The #hb_language_t corresponding to the BCP 47 language tag.
+ * The #hb_language_t corresponding to the BCP 47 language tag.
*
* Since: 0.9.2
**/
@@ -422,12 +421,12 @@ hb_language_get_default ()
/**
* hb_script_from_iso15924_tag:
- * @tag: an #hb_tag_t representing an ISO 15924 tag.
+ * @tag: an #hb_tag_t representing an ISO 15924 tag.
*
- * Converts an ISO 15924 script tag to a corresponding #hb_script_t.
+ * Converts an ISO 15924 script tag to a corresponding #hb_script_t.
*
* Return value:
- * An #hb_script_t corresponding to the ISO 15924 tag.
+ * An #hb_script_t corresponding to the ISO 15924 tag.
*
* Since: 0.9.2
**/
@@ -468,15 +467,15 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
/**
* hb_script_from_string:
* @str: (array length=len) (element-type uint8_t): a string representing an
- * ISO 15924 tag.
+ * ISO 15924 tag.
* @len: length of the @str, or -1 if it is %NULL-terminated.
*
- * Converts a string @str representing an ISO 15924 script tag to a
+ * Converts a string @str representing an ISO 15924 script tag to a
* corresponding #hb_script_t. Shorthand for hb_tag_from_string() then
* hb_script_from_iso15924_tag().
*
* Return value:
- * An #hb_script_t corresponding to the ISO 15924 tag.
+ * An #hb_script_t corresponding to the ISO 15924 tag.
*
* Since: 0.9.2
**/
@@ -493,7 +492,7 @@ hb_script_from_string (const char *str, int len)
* See hb_script_from_iso15924_tag().
*
* Return value:
- * An #hb_tag_t representing an ISO 15924 script tag.
+ * An #hb_tag_t representing an ISO 15924 script tag.
*
* Since: 0.9.2
**/
@@ -590,38 +589,6 @@ hb_script_get_horizontal_direction (hb_script_t script)
}
-/* hb_user_data_array_t */
-
-bool
-hb_user_data_array_t::set (hb_user_data_key_t *key,
- void * data,
- hb_destroy_func_t destroy,
- hb_bool_t replace)
-{
- if (!key)
- return false;
-
- if (replace) {
- if (!data && !destroy) {
- items.remove (key, lock);
- return true;
- }
- }
- hb_user_data_item_t item = {key, data, destroy};
- bool ret = !!items.replace_or_insert (item, lock, (bool) replace);
-
- return ret;
-}
-
-void *
-hb_user_data_array_t::get (hb_user_data_key_t *key)
-{
- hb_user_data_item_t item = {nullptr, nullptr, nullptr};
-
- return items.find (key, &item, lock) ? item.data : nullptr;
-}
-
-
/* hb_version */
@@ -960,14 +927,14 @@ hb_feature_to_string (hb_feature_t *feature,
len += 4;
while (len && s[len - 1] == ' ')
len--;
- if (feature->start != 0 || feature->end != (unsigned int) -1)
+ if (feature->start != HB_FEATURE_GLOBAL_START || feature->end != HB_FEATURE_GLOBAL_END)
{
s[len++] = '[';
if (feature->start)
len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
if (feature->end != feature->start + 1) {
s[len++] = ':';
- if (feature->end != (unsigned int) -1)
+ if (feature->end != HB_FEATURE_GLOBAL_END)
len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
}
s[len++] = ']';
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
index 14c5395952b..07659fad153 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-config.hh
@@ -58,6 +58,7 @@
#define HB_NO_BITMAP
#define HB_NO_CFF
#define HB_NO_COLOR
+#define HB_NO_DRAW
#define HB_NO_ERRNO
#define HB_NO_FACE_COLLECT_UNICODES
#define HB_NO_GETENV
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc
index 8885cfe7304..76e00fd5ce3 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc
@@ -278,13 +278,32 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
CFRelease ((CGFontRef) data);
}
+/**
+ * hb_coretext_face_create:
+ * @cg_font: The CGFontRef to work upon
+ *
+ * Creates an #hb_face_t face object from the specified
+ * CGFontRef.
+ *
+ * Return value: the new #hb_face_t face object
+ *
+ * Since: 0.9.10
+ */
hb_face_t *
hb_coretext_face_create (CGFontRef cg_font)
{
return hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
}
-/*
+/**
+ * hb_coretext_face_get_cg_font:
+ * @face: The #hb_face_t to work upon
+ *
+ * Fetches the CGFontRef associated with an #hb_face_t
+ * face object
+ *
+ * Return value: the CGFontRef found
+ *
* Since: 0.9.10
*/
CGFontRef
@@ -351,10 +370,17 @@ retry:
return font->data.coretext;
}
-
-/*
+/**
+ * hb_coretext_font_create:
+ * @ct_font: The CTFontRef to work upon
+ *
+ * Creates an #hb_font_t font object from the specified
+ * CTFontRef.
+ *
+ * Return value: the new #hb_font_t font object
+ *
* Since: 1.7.2
- */
+ **/
hb_font_t *
hb_coretext_font_create (CTFontRef ct_font)
{
@@ -375,6 +401,17 @@ hb_coretext_font_create (CTFontRef ct_font)
return font;
}
+/**
+ * hb_coretext_face_get_ct_font:
+ * @font: #hb_font_t to work upon
+ *
+ * Fetches the CTFontRef associated with the specified
+ * #hb_font_t font object.
+ *
+ * Return value: the CTFontRef found
+ *
+ * Since: 0.9.10
+ */
CTFontRef
hb_coretext_font_get_ct_font (hb_font_t *font)
{
@@ -475,13 +512,19 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
hb_vector_t<feature_event_t> feature_events;
for (unsigned int i = 0; i < num_features; i++)
{
+ active_feature_t feature;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1010
const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag);
if (!mapping)
continue;
- active_feature_t feature;
feature.rec.feature = mapping->aatFeatureType;
feature.rec.setting = features[i].value ? mapping->selectorToEnable : mapping->selectorToDisable;
+#else
+ feature.rec.feature = features[i].tag;
+ feature.rec.setting = features[i].value;
+#endif
feature.order = i;
feature_event_t *event;
@@ -530,6 +573,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
/* active_features.qsort (); */
for (unsigned int j = 0; j < active_features.length; j++)
{
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1010
CFStringRef keys[] = {
kCTFontFeatureTypeIdentifierKey,
kCTFontFeatureSelectorIdentifierKey
@@ -538,6 +582,17 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature),
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting)
};
+#else
+ char tag[5] = {HB_UNTAG (active_features[j].rec.feature)};
+ CFTypeRef keys[] = {
+ kCTFontOpenTypeFeatureTag,
+ kCTFontOpenTypeFeatureValue
+ };
+ CFTypeRef values[] = {
+ CFStringCreateWithCString (kCFAllocatorDefault, tag, kCFStringEncodingASCII),
+ CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting)
+ };
+#endif
static_assert ((ARRAY_LENGTH_CONST (keys) == ARRAY_LENGTH_CONST (values)), "");
CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault,
(const void **) keys,
@@ -605,7 +660,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
scratch_size -= _consumed; \
} while (0)
- ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, /*nothing*/);
+ ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, ((void)nullptr) /*nothing*/);
unsigned int chars_len = 0;
for (unsigned int i = 0; i < buffer->len; i++) {
hb_codepoint_t c = buffer->info[i].codepoint;
@@ -619,7 +674,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
}
}
- ALLOCATE_ARRAY (unsigned int, log_clusters, chars_len, /*nothing*/);
+ ALLOCATE_ARRAY (unsigned int, log_clusters, chars_len, ((void)nullptr) /*nothing*/);
chars_len = 0;
for (unsigned int i = 0; i < buffer->len; i++)
{
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.h
index 4b0a6f01b6f..e53dbaf2c7f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.h
@@ -40,8 +40,40 @@
HB_BEGIN_DECLS
+/**
+ * HB_CORETEXT_TAG_MORT:
+ *
+ * The #hb_tag_t tag for the `mort` (glyph metamorphosis) table,
+ * which holds AAT features.
+ *
+ * For more information, see
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html
+ *
+ **/
#define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t')
+
+/**
+ * HB_CORETEXT_TAG_MORX:
+ *
+ * The #hb_tag_t tag for the `morx` (extended glyph metamorphosis)
+ * table, which holds AAT features.
+ *
+ * For more information, see
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html
+ *
+ **/
#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
+
+/**
+ * HB_CORETEXT_TAG_KERX:
+ *
+ * The #hb_tag_t tag for the `kerx` (extended kerning) table, which
+ * holds AAT kerning information.
+ *
+ * For more information, see
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kerx.html
+ *
+ **/
#define HB_CORETEXT_TAG_KERX HB_TAG('k','e','r','x')
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
index a7e52c8cbe2..5c13e5d1aab 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh
@@ -46,7 +46,6 @@ struct hb_options_t
bool unused : 1; /* In-case sign bit is here. */
bool initialized : 1;
bool uniscribe_bug_compatible : 1;
- bool aat : 1;
};
union hb_options_union_t {
@@ -230,7 +229,7 @@ _hb_debug_msg<0> (const char *what HB_UNUSED,
...) {}
#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
-#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, false, 0, 0, __VA_ARGS__)
+#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, false, 0, 0, __VA_ARGS__)
#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
index efb2029ec0c..f2fce073e05 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-directwrite.cc
@@ -635,7 +635,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
const wchar_t localeName[20] = {0};
- if (buffer->props.language != nullptr)
+ if (buffer->props.language)
mbstowcs ((wchar_t*) localeName,
hb_language_to_string (buffer->props.language), 20);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.cc
new file mode 100644
index 00000000000..1a5f9c8c6bd
--- /dev/null
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.cc
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2019-2020 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.
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_DRAW
+#ifdef HB_EXPERIMENTAL_API
+
+#include "hb-draw.hh"
+#include "hb-ot.h"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
+
+/**
+ * hb_draw_funcs_set_move_to_func:
+ * @funcs: draw functions object
+ * @move_to: move-to callback
+ *
+ * Sets move-to callback to the draw functions object.
+ *
+ * Since: EXPERIMENTAL
+ **/
+void
+hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
+ hb_draw_move_to_func_t move_to)
+{
+ if (unlikely (hb_object_is_immutable (funcs))) return;
+ funcs->move_to = move_to;
+}
+
+/**
+ * hb_draw_funcs_set_line_to_func:
+ * @funcs: draw functions object
+ * @line_to: line-to callback
+ *
+ * Sets line-to callback to the draw functions object.
+ *
+ * Since: EXPERIMENTAL
+ **/
+void
+hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
+ hb_draw_line_to_func_t line_to)
+{
+ if (unlikely (hb_object_is_immutable (funcs))) return;
+ funcs->line_to = line_to;
+}
+
+/**
+ * hb_draw_funcs_set_quadratic_to_func:
+ * @funcs: draw functions object
+ * @move_to: quadratic-to callback
+ *
+ * Sets quadratic-to callback to the draw functions object.
+ *
+ * Since: EXPERIMENTAL
+ **/
+void
+hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
+ hb_draw_quadratic_to_func_t quadratic_to)
+{
+ if (unlikely (hb_object_is_immutable (funcs))) return;
+ funcs->quadratic_to = quadratic_to;
+ funcs->is_quadratic_to_set = true;
+}
+
+/**
+ * hb_draw_funcs_set_cubic_to_func:
+ * @funcs: draw functions
+ * @cubic_to: cubic-to callback
+ *
+ * Sets cubic-to callback to the draw functions object.
+ *
+ * Since: EXPERIMENTAL
+ **/
+void
+hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
+ hb_draw_cubic_to_func_t cubic_to)
+{
+ if (unlikely (hb_object_is_immutable (funcs))) return;
+ funcs->cubic_to = cubic_to;
+}
+
+/**
+ * hb_draw_funcs_set_close_path_func:
+ * @funcs: draw functions object
+ * @close_path: close-path callback
+ *
+ * Sets close-path callback to the draw functions object.
+ *
+ * Since: EXPERIMENTAL
+ **/
+void
+hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
+ hb_draw_close_path_func_t close_path)
+{
+ if (unlikely (hb_object_is_immutable (funcs))) return;
+ funcs->close_path = close_path;
+}
+
+static void
+_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
+
+static void
+_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
+
+static void
+_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
+ hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
+ hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
+ hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+_close_path_nil (void *user_data HB_UNUSED) {}
+
+/**
+ * hb_draw_funcs_create:
+ *
+ * Creates a new draw callbacks object.
+ *
+ * Since: EXPERIMENTAL
+ **/
+hb_draw_funcs_t *
+hb_draw_funcs_create ()
+{
+ hb_draw_funcs_t *funcs;
+ if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ())))
+ return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
+
+ funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil;
+ funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil;
+ funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil;
+ funcs->is_quadratic_to_set = false;
+ funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil;
+ funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil;
+ return funcs;
+}
+
+/**
+ * hb_draw_funcs_reference:
+ * @funcs: draw functions
+ *
+ * Add to callbacks object refcount.
+ *
+ * Returns: The same object.
+ * Since: EXPERIMENTAL
+ **/
+hb_draw_funcs_t *
+hb_draw_funcs_reference (hb_draw_funcs_t *funcs)
+{
+ return hb_object_reference (funcs);
+}
+
+/**
+ * hb_draw_funcs_destroy:
+ * @funcs: draw functions
+ *
+ * Decreases refcount of callbacks object and deletes the object if it reaches
+ * to zero.
+ *
+ * Since: EXPERIMENTAL
+ **/
+void
+hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
+{
+ if (!hb_object_destroy (funcs)) return;
+
+ free (funcs);
+}
+
+/**
+ * hb_draw_funcs_make_immutable:
+ * @funcs: draw functions
+ *
+ * Makes funcs object immutable.
+ *
+ * Since: EXPERIMENTAL
+ **/
+void
+hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs)
+{
+ if (hb_object_is_immutable (funcs))
+ return;
+
+ hb_object_make_immutable (funcs);
+}
+
+/**
+ * hb_draw_funcs_is_immutable:
+ * @funcs: draw functions
+ *
+ * Checks whether funcs is immutable.
+ *
+ * Returns: If is immutable.
+ * Since: EXPERIMENTAL
+ **/
+hb_bool_t
+hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs)
+{
+ return hb_object_is_immutable (funcs);
+}
+
+/**
+ * hb_font_draw_glyph:
+ * @font: a font object
+ * @glyph: a glyph id
+ * @funcs: draw callbacks object
+ * @user_data: parameter you like be passed to the callbacks when are called
+ *
+ * Draw a glyph.
+ *
+ * Returns: Whether the font had the glyph and the operation completed successfully.
+ * Since: EXPERIMENTAL
+ **/
+hb_bool_t
+hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
+ const hb_draw_funcs_t *funcs,
+ void *user_data)
+{
+ if (unlikely (funcs == &Null (hb_draw_funcs_t) ||
+ glyph >= font->face->get_num_glyphs ()))
+ return false;
+
+ draw_helper_t draw_helper (funcs, user_data);
+ if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true;
+#ifndef HB_NO_CFF
+ if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true;
+ if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true;
+#endif
+
+ return false;
+}
+
+#endif
+#endif
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.h
new file mode 100644
index 00000000000..98eccf4c0c0
--- /dev/null
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2019-2020 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.
+ */
+
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
+#ifndef HB_DRAW_H
+#define HB_DRAW_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+#ifdef HB_EXPERIMENTAL_API
+typedef void (*hb_draw_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
+typedef void (*hb_draw_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
+typedef void (*hb_draw_quadratic_to_func_t) (hb_position_t control_x, hb_position_t control_y,
+ hb_position_t to_x, hb_position_t to_y,
+ void *user_data);
+typedef void (*hb_draw_cubic_to_func_t) (hb_position_t control1_x, hb_position_t control1_y,
+ hb_position_t control2_x, hb_position_t control2_y,
+ hb_position_t to_x, hb_position_t to_y,
+ void *user_data);
+typedef void (*hb_draw_close_path_func_t) (void *user_data);
+
+/**
+ * hb_draw_funcs_t:
+ *
+ * Glyph draw callbacks.
+ *
+ * _move_to, _line_to and _cubic_to calls are nessecary to be defined but we
+ * translate _quadratic_to calls to _cubic_to if the callback isn't defined.
+ *
+ * Since: EXPERIMENTAL
+ **/
+typedef struct hb_draw_funcs_t hb_draw_funcs_t;
+
+HB_EXTERN void
+hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
+ hb_draw_move_to_func_t move_to);
+
+HB_EXTERN void
+hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
+ hb_draw_line_to_func_t line_to);
+
+HB_EXTERN void
+hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
+ hb_draw_quadratic_to_func_t quadratic_to);
+
+HB_EXTERN void
+hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
+ hb_draw_cubic_to_func_t cubic_to);
+
+HB_EXTERN void
+hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
+ hb_draw_close_path_func_t close_path);
+
+HB_EXTERN hb_draw_funcs_t *
+hb_draw_funcs_create (void);
+
+HB_EXTERN hb_draw_funcs_t *
+hb_draw_funcs_reference (hb_draw_funcs_t *funcs);
+
+HB_EXTERN void
+hb_draw_funcs_destroy (hb_draw_funcs_t *funcs);
+
+HB_EXTERN void
+hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs);
+
+HB_EXTERN hb_bool_t
+hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs);
+#endif
+
+HB_END_DECLS
+
+#endif /* HB_DRAW_H */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh
new file mode 100644
index 00000000000..2aa0a5b4db4
--- /dev/null
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-draw.hh
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2020 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.
+ */
+
+#ifndef HB_DRAW_HH
+#define HB_DRAW_HH
+
+#include "hb.hh"
+
+#ifdef HB_EXPERIMENTAL_API
+struct hb_draw_funcs_t
+{
+ hb_object_header_t header;
+
+ hb_draw_move_to_func_t move_to;
+ hb_draw_line_to_func_t line_to;
+ hb_draw_quadratic_to_func_t quadratic_to;
+ bool is_quadratic_to_set;
+ hb_draw_cubic_to_func_t cubic_to;
+ hb_draw_close_path_func_t close_path;
+};
+
+struct draw_helper_t
+{
+ draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_)
+ {
+ funcs = funcs_;
+ user_data = user_data_;
+ path_open = false;
+ path_start_x = current_x = path_start_y = current_y = 0;
+ }
+ ~draw_helper_t () { end_path (); }
+
+ void move_to (hb_position_t x, hb_position_t y)
+ {
+ if (path_open) end_path ();
+ current_x = path_start_x = x;
+ current_y = path_start_y = y;
+ }
+
+ void line_to (hb_position_t x, hb_position_t y)
+ {
+ if (equal_to_current (x, y)) return;
+ if (!path_open) start_path ();
+ funcs->line_to (x, y, user_data);
+ current_x = x;
+ current_y = y;
+ }
+
+ void
+ quadratic_to (hb_position_t control_x, hb_position_t control_y,
+ hb_position_t to_x, hb_position_t to_y)
+ {
+ if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y))
+ return;
+ if (!path_open) start_path ();
+ if (funcs->is_quadratic_to_set)
+ funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data);
+ else
+ funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f),
+ roundf ((current_y + 2.f * control_y) / 3.f),
+ roundf ((to_x + 2.f * control_x) / 3.f),
+ roundf ((to_y + 2.f * control_y) / 3.f),
+ to_x, to_y, user_data);
+ current_x = to_x;
+ current_y = to_y;
+ }
+
+ void
+ cubic_to (hb_position_t control1_x, hb_position_t control1_y,
+ hb_position_t control2_x, hb_position_t control2_y,
+ hb_position_t to_x, hb_position_t to_y)
+ {
+ if (equal_to_current (control1_x, control1_y) &&
+ equal_to_current (control2_x, control2_y) &&
+ equal_to_current (to_x, to_y))
+ return;
+ if (!path_open) start_path ();
+ funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data);
+ current_x = to_x;
+ current_y = to_y;
+ }
+
+ void end_path ()
+ {
+ if (path_open)
+ {
+ if ((path_start_x != current_x) || (path_start_y != current_y))
+ funcs->line_to (path_start_x, path_start_y, user_data);
+ funcs->close_path (user_data);
+ }
+ path_open = false;
+ path_start_x = current_x = path_start_y = current_y = 0;
+ }
+
+ protected:
+ bool equal_to_current (hb_position_t x, hb_position_t y)
+ { return current_x == x && current_y == y; }
+
+ void start_path ()
+ {
+ if (path_open) end_path ();
+ path_open = true;
+ funcs->move_to (path_start_x, path_start_y, user_data);
+ }
+
+ hb_position_t path_start_x;
+ hb_position_t path_start_y;
+
+ hb_position_t current_x;
+ hb_position_t current_y;
+
+ bool path_open;
+ const hb_draw_funcs_t *funcs;
+ void *user_data;
+};
+#endif
+
+#endif /* HB_DRAW_HH */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
index 0c9949fff19..e4d8a3f36ad 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc
@@ -226,7 +226,7 @@ hb_face_create (hb_blob_t *blob,
hb_face_t *
hb_face_get_empty ()
{
- return const_cast<hb_face_t *> (&Null(hb_face_t));
+ return const_cast<hb_face_t *> (&Null (hb_face_t));
}
@@ -546,7 +546,7 @@ void
hb_face_collect_unicodes (hb_face_t *face,
hb_set_t *out)
{
- face->table.cmap->collect_unicodes (out);
+ face->table.cmap->collect_unicodes (out, face->get_num_glyphs ());
}
/**
* hb_face_collect_variation_selectors:
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh
index 68834baeb83..f1b472ccf39 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh
@@ -94,7 +94,7 @@ struct hb_face_t
unsigned int get_num_glyphs () const
{
unsigned int ret = num_glyphs.get_relaxed ();
- if (unlikely (ret == (unsigned int) -1))
+ if (unlikely (ret == UINT_MAX))
return load_num_glyphs ();
return ret;
}
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 e89ad697efd..27959487dc9 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
@@ -33,6 +33,9 @@
#include "hb-ot.h"
+#include "hb-ot-var-avar-table.hh"
+#include "hb-ot-var-fvar-table.hh"
+
/**
* SECTION:hb-font
@@ -674,7 +677,8 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
void *user_data, \
hb_destroy_func_t destroy) \
{ \
- if (hb_object_is_immutable (ffuncs)) { \
+ if (hb_object_is_immutable (ffuncs)) \
+ { \
if (destroy) \
destroy (user_data); \
return; \
@@ -1332,6 +1336,7 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
0, /* num_coords */
nullptr, /* coords */
+ nullptr, /* design_coords */
const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t),
@@ -1383,6 +1388,20 @@ hb_font_create (hb_face_t *face)
return font;
}
+static void
+_hb_font_adopt_var_coords (hb_font_t *font,
+ int *coords, /* 2.14 normalized */
+ float *design_coords,
+ unsigned int coords_length)
+{
+ free (font->coords);
+ free (font->design_coords);
+
+ font->coords = coords;
+ font->design_coords = design_coords;
+ font->num_coords = coords_length;
+}
+
/**
* hb_font_create_sub_font:
* @parent: parent font.
@@ -1413,15 +1432,22 @@ hb_font_create_sub_font (hb_font_t *parent)
font->y_ppem = parent->y_ppem;
font->ptem = parent->ptem;
- font->num_coords = parent->num_coords;
- if (font->num_coords)
+ unsigned int num_coords = parent->num_coords;
+ if (num_coords)
{
- unsigned int size = parent->num_coords * sizeof (parent->coords[0]);
- font->coords = (int *) malloc (size);
- if (unlikely (!font->coords))
- font->num_coords = 0;
+ int *coords = (int *) calloc (num_coords, sizeof (parent->coords[0]));
+ float *design_coords = (float *) calloc (num_coords, sizeof (parent->design_coords[0]));
+ if (likely (coords && design_coords))
+ {
+ memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
+ memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0]));
+ _hb_font_adopt_var_coords (font, coords, design_coords, num_coords);
+ }
else
- memcpy (font->coords, parent->coords, size);
+ {
+ free (coords);
+ free (design_coords);
+ }
}
return font;
@@ -1439,7 +1465,7 @@ hb_font_create_sub_font (hb_font_t *parent)
hb_font_t *
hb_font_get_empty ()
{
- return const_cast<hb_font_t *> (&Null(hb_font_t));
+ return const_cast<hb_font_t *> (&Null (hb_font_t));
}
/**
@@ -1481,6 +1507,7 @@ hb_font_destroy (hb_font_t *font)
hb_font_funcs_destroy (font->klass);
free (font->coords);
+ free (font->design_coords);
free (font);
}
@@ -1842,17 +1869,6 @@ hb_font_get_ptem (hb_font_t *font)
* Variations
*/
-static void
-_hb_font_adopt_var_coords_normalized (hb_font_t *font,
- int *coords, /* 2.14 normalized */
- unsigned int coords_length)
-{
- free (font->coords);
-
- font->coords = coords;
- font->num_coords = coords_length;
-}
-
/**
* hb_font_set_variations:
*
@@ -1875,13 +1891,30 @@ hb_font_set_variations (hb_font_t *font,
unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
- if (unlikely (coords_length && !normalized))
+ float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
+
+ if (unlikely (coords_length && !(normalized && design_coords)))
+ {
+ free (normalized);
+ free (design_coords);
return;
+ }
- hb_ot_var_normalize_variations (font->face,
- variations, variations_length,
- normalized, coords_length);
- _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
+ const OT::fvar &fvar = *font->face->table.fvar;
+ for (unsigned int i = 0; i < variations_length; i++)
+ {
+ hb_ot_var_axis_info_t info;
+ if (hb_ot_var_find_axis_info (font->face, variations[i].tag, &info) &&
+ info.axis_index < coords_length)
+ {
+ float v = variations[i].value;
+ design_coords[info.axis_index] = v;
+ normalized[info.axis_index] = fvar.normalize_axis_value (info.axis_index, v);
+ }
+ }
+ font->face->table.avar->map_coords (normalized, coords_length);
+
+ _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
}
/**
@@ -1898,11 +1931,20 @@ hb_font_set_var_coords_design (hb_font_t *font,
return;
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
- if (unlikely (coords_length && !normalized))
+ float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
+
+ if (unlikely (coords_length && !(normalized && design_coords)))
+ {
+ free (normalized);
+ free (design_coords);
return;
+ }
+
+ if (coords_length)
+ memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0]));
hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
- _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
+ _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
}
/**
@@ -1946,13 +1988,30 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
return;
int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
- if (unlikely (coords_length && !copy))
+ int *unmapped = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
+ float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (design_coords[0])) : nullptr;
+
+ if (unlikely (coords_length && !(copy && unmapped && design_coords)))
+ {
+ free (copy);
+ free (unmapped);
+ free (design_coords);
return;
+ }
if (coords_length)
+ {
memcpy (copy, coords, coords_length * sizeof (coords[0]));
+ memcpy (unmapped, coords, coords_length * sizeof (coords[0]));
+ }
+
+ /* Best effort design coords simulation */
+ font->face->table.avar->unmap_coords (unmapped, coords_length);
+ for (unsigned int i = 0; i < coords_length; ++i)
+ design_coords[i] = font->face->table.fvar->unnormalize_axis_value (i, unmapped[i]);
+ free (unmapped);
- _hb_font_adopt_var_coords_normalized (font, copy, coords_length);
+ _hb_font_adopt_var_coords (font, copy, design_coords, coords_length);
}
/**
@@ -1972,6 +2031,26 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
return font->coords;
}
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_font_get_var_coords_design:
+ *
+ * Return value is valid as long as variation coordinates of the font
+ * are not modified.
+ *
+ * Since: EXPERIMENTAL
+ */
+const float *
+hb_font_get_var_coords_design (hb_font_t *font,
+ unsigned int *length)
+{
+ if (length)
+ *length = font->num_coords;
+
+ return font->design_coords;
+}
+#endif
#endif
#ifndef HB_DISABLE_DEPRECATED
@@ -2076,6 +2155,13 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_func_t func,
void *user_data, hb_destroy_func_t destroy)
{
+ if (hb_object_is_immutable (ffuncs))
+ {
+ if (destroy)
+ destroy (user_data);
+ return;
+ }
+
hb_font_get_glyph_trampoline_t *trampoline;
trampoline = trampoline_create (func, user_data, destroy);
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 01ff201aeec..e1a5719f1dd 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.h
@@ -33,6 +33,7 @@
#include "hb-common.h"
#include "hb-face.h"
+#include "hb-draw.h"
HB_BEGIN_DECLS
@@ -704,6 +705,12 @@ hb_font_set_var_coords_design (hb_font_t *font,
const float *coords,
unsigned int coords_length);
+#ifdef HB_EXPERIMENTAL_API
+HB_EXTERN const float *
+hb_font_get_var_coords_design (hb_font_t *font,
+ unsigned int *length);
+#endif
+
HB_EXTERN void
hb_font_set_var_coords_normalized (hb_font_t *font,
const int *coords, /* 2.14 normalized */
@@ -717,6 +724,12 @@ HB_EXTERN void
hb_font_set_var_named_instance (hb_font_t *font,
unsigned instance_index);
+#ifdef HB_EXPERIMENTAL_API
+HB_EXTERN hb_bool_t
+hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
+ const hb_draw_funcs_t *funcs, void *user_data);
+#endif
+
HB_END_DECLS
#endif /* HB_FONT_H */
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 b1e8e6440cc..12982fc6b49 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh
@@ -120,6 +120,7 @@ struct hb_font_t
/* Font variation coordinates. */
unsigned int num_coords;
int *coords;
+ float *design_coords;
hb_font_funcs_t *klass;
void *user_data;
@@ -286,7 +287,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,
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
index e526bf40d56..b18b990b975 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
@@ -48,8 +48,13 @@
* @short_description: FreeType integration
* @include: hb-ft.h
*
- * Functions for using HarfBuzz with the FreeType library to provide face and
+ * Functions for using HarfBuzz with the FreeType library.
+ *
+ * HarfBuzz supports using FreeType to provide face and
* font data.
+ *
+ * <note>Note that FreeType is not thread-safe, therefore these
+ * functions are not thread-safe either.</note>
**/
@@ -127,10 +132,13 @@ _hb_ft_font_destroy (void *data)
/**
* hb_ft_font_set_load_flags:
- * @font:
- * @load_flags:
+ * @font: #hb_font_t to work upon
+ * @load_flags: The FreeType load flags to set
*
+ * Sets the FT_Load_Glyph load flags for the specified #hb_font_t.
*
+ * For more information, see
+ * https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
*
* Since: 1.0.5
**/
@@ -140,7 +148,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
if (hb_object_is_immutable (font))
return;
- if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+ if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
return;
hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
@@ -150,17 +158,21 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
/**
* hb_ft_font_get_load_flags:
- * @font:
+ * @font: #hb_font_t to work upon
*
+ * Fetches the FT_Load_Glyph load flags of the specified #hb_font_t.
*
+ * For more information, see
+ * https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
+ *
+ * Return value: FT_Load_Glyph flags found
*
- * Return value:
* Since: 1.0.5
**/
int
hb_ft_font_get_load_flags (hb_font_t *font)
{
- if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+ if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
return 0;
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
@@ -168,10 +180,21 @@ hb_ft_font_get_load_flags (hb_font_t *font)
return ft_font->load_flags;
}
+/**
+ * hb_ft_get_face:
+ * @font: #hb_font_t to work upon
+ *
+ * Fetches the FT_Face associated with the specified #hb_font_t
+ * font object.
+ *
+ * Return value: the FT_Face found
+ *
+ * Since: 0.9.2
+ **/
FT_Face
hb_ft_font_get_face (hb_font_t *font)
{
- if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+ if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
return nullptr;
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
@@ -179,6 +202,47 @@ hb_ft_font_get_face (hb_font_t *font)
return ft_font->ft_face;
}
+/**
+ * hb_ft_font_lock_face:
+ * @font:
+ *
+ *
+ *
+ * Return value:
+ * Since: 2.6.5
+ **/
+FT_Face
+hb_ft_font_lock_face (hb_font_t *font)
+{
+ if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
+ return nullptr;
+
+ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
+
+ ft_font->lock.lock ();
+
+ return ft_font->ft_face;
+}
+
+/**
+ * hb_ft_font_unlock_face:
+ * @font:
+ *
+ *
+ *
+ * Return value:
+ * Since: 2.6.5
+ **/
+void
+hb_ft_font_unlock_face (hb_font_t *font)
+{
+ if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
+ return;
+
+ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
+
+ ft_font->lock.unlock ();
+}
static hb_bool_t
@@ -595,12 +659,22 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data
/**
* hb_ft_face_create:
- * @ft_face: (destroy destroy) (scope notified):
- * @destroy:
+ * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
+ * @destroy: A callback to call when the face object is not needed anymore
+ *
+ * Creates an #hb_face_t face object from the specified FT_Face.
+ *
+ * This variant of the function does not provide any life-cycle management.
*
+ * Most client programs should use hb_ft_face_create_referenced()
+ * (or, perhaps, hb_ft_face_create_cached()) instead.
*
+ * If you know you have valid reasons not to use hb_ft_face_create_referenced(),
+ * then it is the client program's responsibility to destroy @ft_face
+ * after the #hb_face_t face object has been destroyed.
+ *
+ * Return value: (transfer full): the new #hb_face_t face object
*
- * Return value: (transfer full):
* Since: 0.9.2
**/
hb_face_t *
@@ -630,11 +704,20 @@ hb_ft_face_create (FT_Face ft_face,
/**
* hb_ft_face_create_referenced:
- * @ft_face:
+ * @ft_face: FT_Face to work upon
+ *
+ * Creates an #hb_face_t face object from the specified FT_Face.
+ *
+ * This is the preferred variant of the hb_ft_face_create*
+ * function family, because it calls FT_Reference_Face() on @ft_face,
+ * ensuring that @ft_face remains alive as long as the resulting
+ * #hb_face_t face object remains alive. Also calls FT_Done_Face()
+ * when the #hb_face_t face object is destroyed.
*
+ * Use this version unless you know you have good reasons not to.
*
+ * Return value: (transfer full): the new #hb_face_t face object
*
- * Return value: (transfer full):
* Since: 0.9.38
**/
hb_face_t *
@@ -652,11 +735,21 @@ hb_ft_face_finalize (FT_Face ft_face)
/**
* hb_ft_face_create_cached:
- * @ft_face:
+ * @ft_face: FT_Face to work upon
+ *
+ * Creates an #hb_face_t face object from the specified FT_Face.
+ *
+ * This variant of the function caches the newly created #hb_face_t
+ * face object, using the @generic pointer of @ft_face. Subsequent function
+ * calls that are passed the same @ft_face parameter will have the same
+ * #hb_face_t returned to them, and that #hb_face_t will be correctly
+ * reference counted.
*
+ * However, client programs are still responsible for destroying
+ * @ft_face after the last #hb_face_t face object has been destroyed.
*
+ * Return value: (transfer full): the new #hb_face_t face object
*
- * Return value: (transfer full):
* Since: 0.9.2
**/
hb_face_t *
@@ -674,15 +767,34 @@ hb_ft_face_create_cached (FT_Face ft_face)
return hb_face_reference ((hb_face_t *) ft_face->generic.data);
}
-
/**
* hb_ft_font_create:
- * @ft_face: (destroy destroy) (scope notified):
- * @destroy:
+ * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
+ * @destroy: (optional): A callback to call when the font object is not needed anymore
+ *
+ * Creates an #hb_font_t font object from the specified FT_Face.
+ *
+ * <note>Note: You must set the face size on @ft_face before calling
+ * hb_ft_font_create() on it. Otherwise, HarfBuzz will not pick up
+ * the face size.</note>
+ *
+ * This variant of the function does not provide any life-cycle management.
*
+ * Most client programs should use hb_ft_font_create_referenced()
+ * instead.
*
+ * If you know you have valid reasons not to use hb_ft_font_create_referenced(),
+ * then it is the client program's responsibility to destroy @ft_face
+ * after the #hb_font_t font object has been destroyed.
+ *
+ * HarfBuzz will use the @destroy callback on the #hb_font_t font object
+ * if it is supplied when you use this function. However, even if @destroy
+ * is provided, it is the client program's responsibility to destroy @ft_face,
+ * and it is the client program's responsibility to ensure that @ft_face is
+ * destroyed only after the #hb_font_t font object has been destroyed.
+ *
+ * Return value: (transfer full): the new #hb_font_t font object
*
- * Return value: (transfer full):
* Since: 0.9.2
**/
hb_font_t *
@@ -700,6 +812,16 @@ hb_ft_font_create (FT_Face ft_face,
return font;
}
+/**
+ * hb_ft_font_has_changed:
+ * @font: #hb_font_t to work upon
+ *
+ * Refreshes the state of @font when the underlying FT_Face has changed.
+ * This function should be called after changing the size or
+ * variation-axis settings on the FT_Face.
+ *
+ * Since: 1.0.5
+ **/
void
hb_ft_font_changed (hb_font_t *font)
{
@@ -718,7 +840,7 @@ hb_ft_font_changed (hb_font_t *font)
ft_face->size->metrics.y_ppem);
#endif
-#ifdef HAVE_FT_GET_VAR_BLEND_COORDINATES
+#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
FT_MM_Var *mm_var = nullptr;
if (!FT_Get_MM_Var (ft_face, &mm_var))
{
@@ -755,11 +877,23 @@ hb_ft_font_changed (hb_font_t *font)
/**
* hb_ft_font_create_referenced:
- * @ft_face:
+ * @ft_face: FT_Face to work upon
+ *
+ * Creates an #hb_font_t font object from the specified FT_Face.
+ *
+ * <note>Note: You must set the face size on @ft_face before calling
+ * hb_ft_font_create_references() on it. Otherwise, HarfBuzz will not pick up
+ * the face size.</note>
*
+ * This is the preferred variant of the hb_ft_font_create*
+ * function family, because it calls FT_Reference_Face() on @ft_face,
+ * ensuring that @ft_face remains alive as long as the resulting
+ * #hb_font_t font object remains alive.
*
+ * Use this version unless you know you have good reasons not to.
+ *
+ * Return value: (transfer full): the new #hb_font_t font object
*
- * Return value: (transfer full):
* Since: 0.9.38
**/
hb_font_t *
@@ -818,6 +952,28 @@ _release_blob (FT_Face ft_face)
hb_blob_destroy ((hb_blob_t *) ft_face->generic.data);
}
+/**
+ * hb_ft_font_set_funcs:
+ * @font: #hb_font_t to work upon
+ *
+ * Configures the font-functions structure of the specified
+ * #hb_font_t font object to use FreeType font functions.
+ *
+ * In particular, you can use this function to configure an
+ * existing #hb_face_t face object for use with FreeType font
+ * functions even if that #hb_face_t face object was initially
+ * created with hb_face_create(), and therefore was not
+ * initially configured to use FreeType font functions.
+ *
+ * An #hb_face_t face object created with hb_ft_face_create()
+ * is preconfigured for FreeType font functions and does not
+ * require this function to be used.
+ *
+ * <note>Note: Internally, this function creates an FT_Face.
+* </note>
+ *
+ * Since: 1.0.5
+ **/
void
hb_ft_font_set_funcs (hb_font_t *font)
{
@@ -857,7 +1013,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
FT_Set_Transform (ft_face, &matrix, nullptr);
}
-#ifdef HAVE_FT_SET_VAR_BLEND_COORDINATES
+#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
unsigned int num_coords;
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
if (num_coords)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h
index 94013eeb915..bf07115ab92 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.h
@@ -110,6 +110,12 @@ hb_ft_font_create_referenced (FT_Face ft_face);
HB_EXTERN FT_Face
hb_ft_font_get_face (hb_font_t *font);
+HB_EXTERN FT_Face
+hb_ft_font_lock_face (hb_font_t *font);
+
+HB_EXTERN void
+hb_ft_font_unlock_face (hb_font_t *font);
+
HB_EXTERN void
hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc
index db02b6760e3..058f65ae69c 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc
@@ -41,7 +41,11 @@
* @short_description: GLib integration
* @include: hb-glib.h
*
- * Functions for using HarfBuzz with the GLib library to provide Unicode data.
+ * Functions for using HarfBuzz with the GLib library.
+ *
+ * HarfBuzz supports using GLib to provide Unicode data, by attaching
+ * GLib functions to the virtual methods in a #hb_unicode_funcs_t function
+ * structure.
**/
@@ -169,6 +173,17 @@ glib_script_to_script[] =
};
#endif
+/**
+ * hb_glib_script_to_script:
+ * @script: The GUnicodeScript identifier to query
+ *
+ * Fetches the #hb_script_t script that corresponds to the
+ * specified GUnicodeScript identifier.
+ *
+ * Return value: the #hb_script_t script found
+ *
+ * Since: 0.9.38
+ **/
hb_script_t
hb_glib_script_to_script (GUnicodeScript script)
{
@@ -185,6 +200,17 @@ hb_glib_script_to_script (GUnicodeScript script)
#endif
}
+/**
+ * hb_glib_script_from_script:
+ * @script: The #hb_script_t to query
+ *
+ * Fetches the GUnicodeScript identifier that corresponds to the
+ * specified #hb_script_t script.
+ *
+ * Return value: the GUnicodeScript identifier found
+ *
+ * Since: 0.9.38
+ **/
GUnicodeScript
hb_glib_script_from_script (hb_script_t script)
{
@@ -373,6 +399,16 @@ void free_static_glib_funcs ()
}
#endif
+/**
+ * hb_glib_get_unicode_funcs:
+ *
+ * Fetches a Unicode-functions structure that is populated
+ * with the appropriate GLib function for each method.
+ *
+ * Return value: (transfer none): a pointer to the #hb_unicode_funcs_t Unicode-functions structure
+ *
+ * Since: 0.9.38
+ **/
hb_unicode_funcs_t *
hb_glib_get_unicode_funcs ()
{
@@ -391,6 +427,12 @@ _hb_g_bytes_unref (void *data)
/**
* hb_glib_blob_create:
+ * @gbytes: the GBytes structure to work upon
+ *
+ * Creates an #hb_blob_t blob from the specified
+ * GBytes data structure.
+ *
+ * Return value: (transfer full): the new #hb_blob_t blob object
*
* Since: 0.9.38
**/
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.cc.tmpl b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.cc.tmpl
index 17f1adeb1dc..2ffd1c9d7bb 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.cc.tmpl
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.cc.tmpl
@@ -1,6 +1,6 @@
/*** BEGIN file-header ***/
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright (C) 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.h.tmpl b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.h.tmpl
index 7ef9dfc0295..f8bd29e5401 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.h.tmpl
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-enums.h.tmpl
@@ -1,6 +1,6 @@
/*** BEGIN file-header ***/
/*
- * Copyright © 2013 Google, Inc.
+ * Copyright (C) 2013 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc
index 7f4922ef192..7c46e264007 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc
@@ -32,11 +32,20 @@
/**
* SECTION:hb-gobject
* @title: hb-gobject
- * @short_description: GObject integration
+ * @short_description: GObject integration support
* @include: hb-gobject.h
*
- * Functions for using HarfBuzz with the GObject library to provide
+ * Support for using HarfBuzz with the GObject library to provide
* type data.
+ *
+ * The types and functions listed here are solely a linkage between
+ * HarfBuzz's public data types and the GTypes used by the GObject framework.
+ * HarfBuzz uses GObject introspection to generate its Python bindings
+ * (and potentially other language bindings); client programs should never need
+ * to access the GObject-integration mechanics.
+ *
+ * For client programs using the GNOME and GTK software stack, please see the
+ * GLib and FreeType integration pages.
**/
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.h
index 800beede0f1..6fad8d70194 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright (C) 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject.h
index ea1bd25df82..8891aa0ee79 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright (C) 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
index f0f2f8c7361..d8a72dc2f18 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc
@@ -45,7 +45,11 @@
* @short_description: Graphite2 integration
* @include: hb-graphite2.h
*
- * Functions for using HarfBuzz with the Graphite2 fonts.
+ * Functions for using HarfBuzz with fonts that include Graphite features.
+ *
+ * For Graphite features to work, you must be sure that HarfBuzz was compiled
+ * with the `graphite2` shaping engine enabled. Currently, the default is to
+ * not enable `graphite2` shaping.
**/
@@ -152,7 +156,15 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
free (data);
}
-/*
+/**
+ * hb_graphite2_face_get_gr_face:
+ * @face: @hb_face_t to query
+ *
+ * Fetches the Graphite2 gr_face corresponding to the specified
+ * #hb_face_t face object.
+ *
+ * Return value: the gr_face found
+ *
* Since: 0.9.10
*/
gr_face *
@@ -376,7 +388,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
buffer->len = glyph_count;
/* Positioning. */
- unsigned int currclus = (unsigned int) -1;
+ unsigned int currclus = UINT_MAX;
const hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, nullptr);
if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.h
index 1720191b42f..f299da9f71c 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.h
@@ -32,7 +32,15 @@
HB_BEGIN_DECLS
-
+/**
+ * HB_GRAPHITE2_TAG_SILF:
+ *
+ * The #hb_tag_t tag for the `Silf` table, which holds Graphite
+ * features.
+ *
+ * For more information, see http://graphite.sil.org/
+ *
+ **/
#define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f')
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-icu.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-icu.cc
index 985ff02dcdf..c1dcc24c26e 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-icu.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-icu.cc
@@ -54,7 +54,21 @@
* @short_description: ICU integration
* @include: hb-icu.h
*
- * Functions for using HarfBuzz with the ICU library to provide Unicode data.
+ * Functions for using HarfBuzz with the International Components for Unicode
+ * (ICU) library. HarfBuzz supports using ICU to provide Unicode data, by attaching
+ * ICU functions to the virtual methods in a #hb_unicode_funcs_t function
+ * structure.
+ **/
+
+/**
+ * hb_icu_script_to_script:
+ * @script: The UScriptCode identifier to query
+ *
+ * Fetches the #hb_script_t script that corresponds to the
+ * specified UScriptCode identifier.
+ *
+ * Return value: the #hb_script_t script found
+ *
**/
hb_script_t
@@ -66,6 +80,16 @@ hb_icu_script_to_script (UScriptCode script)
return hb_script_from_string (uscript_getShortName (script), -1);
}
+/**
+ * hb_icu_script_from_script:
+ * @script: The #hb_script_t script to query
+ *
+ * Fetches the UScriptCode identifier that corresponds to the
+ * specified #hb_script_t script.
+ *
+ * Return value: the UScriptCode identifier found
+ *
+ **/
UScriptCode
hb_icu_script_from_script (hb_script_t script)
{
@@ -350,6 +374,16 @@ void free_static_icu_funcs ()
}
#endif
+/**
+ * hb_icu_get_unicode_funcs:
+ *
+ * Fetches a Unicode-functions structure that is populated
+ * with the appropriate ICU function for each method.
+ *
+ * Return value: (transfer none): a pointer to the #hb_unicode_funcs_t Unicode-functions structure
+ *
+ * Since: 0.9.38
+ **/
hb_unicode_funcs_t *
hb_icu_get_unicode_funcs ()
{
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh
index 99d533c045c..3f952fe7fce 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-kern.hh
@@ -52,8 +52,7 @@ struct hb_kern_machine_t
OT::hb_ot_apply_context_t c (1, font, buffer);
c.set_lookup_mask (kern_mask);
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
- OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
- skippy_iter.init (&c);
+ auto &skippy_iter = c.iter_input;
bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
unsigned int count = buffer->len;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh
index 15535d75bd4..54bc60d4c8b 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh
@@ -41,22 +41,6 @@
* Casts
*/
-/* Cast to struct T, reference to reference */
-template<typename Type, typename TObject>
-static inline const Type& CastR(const TObject &X)
-{ return reinterpret_cast<const Type&> (X); }
-template<typename Type, typename TObject>
-static inline Type& CastR(TObject &X)
-{ return reinterpret_cast<Type&> (X); }
-
-/* Cast to struct T, pointer to pointer */
-template<typename Type, typename TObject>
-static inline const Type* CastP(const TObject *X)
-{ return reinterpret_cast<const Type*> (X); }
-template<typename Type, typename TObject>
-static inline Type* CastP(TObject *X)
-{ return reinterpret_cast<Type*> (X); }
-
/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
* location pointed to by P plus Ofs bytes. */
template<typename Type>
@@ -70,7 +54,7 @@ static inline const Type& StructAtOffsetUnaligned(const void *P, unsigned int of
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
- return * reinterpret_cast<Type*> ((char *) P + offset);
+ return * reinterpret_cast<const Type*> ((const char *) P + offset);
#pragma GCC diagnostic pop
}
template<typename Type>
@@ -135,7 +119,7 @@ static inline Type& StructAfter(TObject &X)
#define DEFINE_SIZE_ARRAY(size, array) \
DEFINE_COMPILES_ASSERTION ((void) (array)[0].static_size) \
- DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + HB_VAR_ARRAY * sizeof ((array)[0])) \
+ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + (HB_VAR_ARRAY+0) * sizeof ((array)[0])) \
static constexpr unsigned null_size = (size); \
static constexpr unsigned min_size = (size)
@@ -250,7 +234,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
static Returned* convert (Stored *p) { return p; }
/* By default null/init/fini the object. */
- static const Stored* get_null () { return &Null(Stored); }
+ static const Stored* get_null () { return &Null (Stored); }
static Stored *create (Data *data)
{
Stored *p = (Stored *) calloc (1, sizeof (Stored));
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc
index a2c770c586d..191be143727 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc
@@ -69,7 +69,7 @@ hb_map_create ()
hb_map_t *
hb_map_get_empty ()
{
- return const_cast<hb_map_t *> (&Null(hb_map_t));
+ return const_cast<hb_map_t *> (&Null (hb_map_t));
}
/**
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
index 8c8db4d520b..b7bf7fe59d1 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
@@ -135,8 +135,8 @@ struct hb_hashmap_t
for (unsigned int i = 0; i < old_size; i++)
if (old_items[i].is_real ())
set_with_hash (old_items[i].key,
- old_items[i].hash,
- old_items[i].value);
+ old_items[i].hash,
+ old_items[i].value);
free (old_items);
@@ -211,7 +211,7 @@ struct hb_hashmap_t
)
/* Sink interface. */
- hb_hashmap_t<K, V, kINVALID, vINVALID>& operator << (const hb_pair_t<K, V>& v)
+ hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
{ set (v.first, v.second); return *this; }
protected:
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
index 2dfaeb7b464..c08b191f1fd 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
@@ -396,5 +396,16 @@ using hb_is_trivial= hb_bool_constant<
>;
#define hb_is_trivial(T) hb_is_trivial<T>::value
+/* hb_unwrap_type (T)
+ * If T has no T::type, returns T. Otherwise calls itself on T::type recursively.
+ */
+
+template <typename T, typename>
+struct _hb_unwrap_type : hb_type_identity_t<T> {};
+template <typename T>
+struct _hb_unwrap_type<T, hb_void_t<typename T::type>> : _hb_unwrap_type<typename T::type, void> {};
+template <typename T>
+using hb_unwrap_type = _hb_unwrap_type<T, void>;
+#define hb_unwrap_type(T) typename hb_unwrap_type<T>::type
#endif /* HB_META_HH */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh
index d4578205e33..9853939b077 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh
@@ -104,7 +104,7 @@ struct NullHelper
} \
}; \
namespace Namespace { \
- static_assert (true, "Just so we take semicolon after.")
+ static_assert (true, "") /* Require semicolon after. */
#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
@@ -117,7 +117,7 @@ struct NullHelper
return _hb_Null_##Type; \
} \
}; \
- static_assert (true, "Just so we take semicolon after.")
+ static_assert (true, "") /* Require semicolon after. */
#define DEFINE_NULL_INSTANCE(Type) \
const Type _hb_Null_##Type
@@ -135,7 +135,7 @@ template <typename Type>
static inline Type& Crap () {
static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
- memcpy (obj, &Null(Type), sizeof (*obj));
+ memcpy (obj, &Null (Type), sizeof (*obj));
return *obj;
}
template <typename QType>
@@ -148,11 +148,11 @@ struct CrapHelper
template <typename Type>
struct CrapOrNullHelper {
- static Type & get () { return Crap(Type); }
+ static Type & get () { return Crap (Type); }
};
template <typename Type>
struct CrapOrNullHelper<const Type> {
- static const Type & get () { return Null(Type); }
+ static const Type & get () { return Null (Type); }
};
#define CrapOrNull(Type) CrapOrNullHelper<Type>::get ()
@@ -174,7 +174,7 @@ struct hb_nonnull_ptr_t
/* Only auto-cast to const types. */
template <typename C> operator const C * () const { return get (); }
operator const char * () const { return (const char *) get (); }
- T * get () const { return v ? v : const_cast<T *> (&Null(T)); }
+ T * get () const { return v ? v : const_cast<T *> (&Null (T)); }
T * get_raw () const { return v; }
T *v;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.hh
index c78c85097e1..1a9dbba6dd3 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.hh
@@ -30,10 +30,8 @@
#include "hb.hh"
-#include <float.h>
-
-#line 37 "hb-number-parser.hh"
+#line 35 "hb-number-parser.hh"
static const unsigned char _double_parser_trans_keys[] = {
0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u,
46u, 101u, 0
@@ -93,12 +91,12 @@ static const int double_parser_error = 0;
static const int double_parser_en_main = 1;
-#line 70 "hb-number-parser.rl"
+#line 68 "hb-number-parser.rl"
/* Works only for n < 512 */
static inline double
-_pow10 (unsigned int exponent)
+_pow10 (unsigned exponent)
{
static const double _powers_of_10[] =
{
@@ -112,38 +110,37 @@ _pow10 (unsigned int exponent)
100.,
10.
};
- unsigned int mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
+ unsigned mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
double result = 1;
for (const double *power = _powers_of_10; mask; ++power, mask >>= 1)
if (exponent & mask) result *= *power;
return result;
}
+/* a variant of strtod that also gets end of buffer in its second argument */
static inline double
-strtod_rl (const char *buf, char **end_ptr)
+strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
{
- const char *p, *pe;
double value = 0;
double frac = 0;
double frac_count = 0;
- unsigned int exp = 0;
+ unsigned exp = 0;
bool neg = false, exp_neg = false, exp_overflow = false;
- const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
- const unsigned int MAX_EXP = 0x7FFu; /* 1^11-1 */
- p = buf;
- pe = p + strlen (p);
+ const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 2^52-1 */
+ const unsigned MAX_EXP = 0x7FFu; /* 2^11-1 */
+ const char *pe = *end_ptr;
while (p < pe && ISSPACE (*p))
p++;
int cs;
-#line 142 "hb-number-parser.hh"
+#line 139 "hb-number-parser.hh"
{
cs = double_parser_start;
}
-#line 147 "hb-number-parser.hh"
+#line 144 "hb-number-parser.hh"
{
int _slen;
int _trans;
@@ -169,21 +166,21 @@ _resume:
switch ( _double_parser_trans_actions[_trans] ) {
case 1:
-#line 39 "hb-number-parser.rl"
+#line 37 "hb-number-parser.rl"
{ neg = true; }
break;
case 4:
-#line 40 "hb-number-parser.rl"
+#line 38 "hb-number-parser.rl"
{ exp_neg = true; }
break;
case 2:
-#line 42 "hb-number-parser.rl"
+#line 40 "hb-number-parser.rl"
{
value = value * 10. + ((*p) - '0');
}
break;
case 3:
-#line 45 "hb-number-parser.rl"
+#line 43 "hb-number-parser.rl"
{
if (likely (frac <= MAX_FRACT / 10))
{
@@ -193,7 +190,7 @@ _resume:
}
break;
case 5:
-#line 52 "hb-number-parser.rl"
+#line 50 "hb-number-parser.rl"
{
if (likely (exp * 10 + ((*p) - '0') <= MAX_EXP))
exp = exp * 10 + ((*p) - '0');
@@ -201,7 +198,7 @@ _resume:
exp_overflow = true;
}
break;
-#line 205 "hb-number-parser.hh"
+#line 202 "hb-number-parser.hh"
}
_again:
@@ -213,10 +210,10 @@ _again:
_out: {}
}
-#line 116 "hb-number-parser.rl"
+#line 113 "hb-number-parser.rl"
- *end_ptr = (char *) p;
+ *end_ptr = p;
if (frac_count) value += frac / _pow10 (frac_count);
if (neg) value *= -1.;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.rl b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.rl
index 8445fa22a13..c6c4a3bab88 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.rl
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number-parser.rl
@@ -28,8 +28,6 @@
#include "hb.hh"
-#include <float.h>
-
%%{
machine double_parser;
@@ -71,7 +69,7 @@ main := (
/* Works only for n < 512 */
static inline double
-_pow10 (unsigned int exponent)
+_pow10 (unsigned exponent)
{
static const double _powers_of_10[] =
{
@@ -85,27 +83,26 @@ _pow10 (unsigned int exponent)
100.,
10.
};
- unsigned int mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
+ unsigned mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
double result = 1;
for (const double *power = _powers_of_10; mask; ++power, mask >>= 1)
if (exponent & mask) result *= *power;
return result;
}
+/* a variant of strtod that also gets end of buffer in its second argument */
static inline double
-strtod_rl (const char *buf, char **end_ptr)
+strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
{
- const char *p, *pe;
double value = 0;
double frac = 0;
double frac_count = 0;
- unsigned int exp = 0;
+ unsigned exp = 0;
bool neg = false, exp_neg = false, exp_overflow = false;
- const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
- const unsigned int MAX_EXP = 0x7FFu; /* 1^11-1 */
- p = buf;
- pe = p + strlen (p);
+ const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 2^52-1 */
+ const unsigned MAX_EXP = 0x7FFu; /* 2^11-1 */
+ const char *pe = *end_ptr;
while (p < pe && ISSPACE (*p))
p++;
@@ -115,7 +112,7 @@ strtod_rl (const char *buf, char **end_ptr)
write exec;
}%%
- *end_ptr = (char *) p;
+ *end_ptr = p;
if (frac_count) value += frac / _pow10 (frac_count);
if (neg) value *= -1.;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number.cc
index 4f84d4ad5cd..6e4f3f7ebd0 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-number.cc
@@ -25,21 +25,16 @@
#include "hb.hh"
#include "hb-machinery.hh"
+#include "hb-number.hh"
#include "hb-number-parser.hh"
-#include <locale.h>
-#ifdef HAVE_XLOCALE_H
-#include <xlocale.h>
-#endif
-
template<typename T, typename Func>
static bool
_parse_number (const char **pp, const char *end, T *pv,
bool whole_buffer, Func f)
{
char buf[32];
- unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1,
- (unsigned int) (end - *pp));
+ unsigned len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned) (end - *pp));
strncpy (buf, *pp, len);
buf[len] = '\0';
@@ -50,7 +45,8 @@ _parse_number (const char **pp, const char *end, T *pv,
*pv = f (p, &pend);
if (unlikely (errno || p == pend ||
/* Check if consumed whole buffer if is requested */
- (whole_buffer && pend - p != end - *pp))) return false;
+ (whole_buffer && pend - p != end - *pp)))
+ return false;
*pp += pend - p;
return true;
@@ -65,83 +61,20 @@ hb_parse_int (const char **pp, const char *end, int *pv, bool whole_buffer)
}
bool
-hb_parse_uint (const char **pp, const char *end, unsigned int *pv,
+hb_parse_uint (const char **pp, const char *end, unsigned *pv,
bool whole_buffer, int base)
{
- return _parse_number<unsigned int> (pp, end, pv, whole_buffer,
- [base] (const char *p, char **end)
- { return strtoul (p, end, base); });
-}
-
-
-#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L)
-#define USE_XLOCALE 1
-#define HB_LOCALE_T locale_t
-#define HB_CREATE_LOCALE(locName) newlocale (LC_ALL_MASK, locName, nullptr)
-#define HB_FREE_LOCALE(loc) freelocale (loc)
-#elif defined(_MSC_VER)
-#define USE_XLOCALE 1
-#define HB_LOCALE_T _locale_t
-#define HB_CREATE_LOCALE(locName) _create_locale (LC_ALL, locName)
-#define HB_FREE_LOCALE(loc) _free_locale (loc)
-#define strtod_l(a, b, c) _strtod_l ((a), (b), (c))
-#endif
-
-#ifdef USE_XLOCALE
-
-#if HB_USE_ATEXIT
-static void free_static_C_locale ();
-#endif
-
-static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<HB_LOCALE_T>,
- hb_C_locale_lazy_loader_t>
-{
- static HB_LOCALE_T create ()
- {
- HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
-
-#if HB_USE_ATEXIT
- atexit (free_static_C_locale);
-#endif
-
- return C_locale;
- }
- static void destroy (HB_LOCALE_T p)
- {
- HB_FREE_LOCALE (p);
- }
- static HB_LOCALE_T get_null ()
- {
- return nullptr;
- }
-} static_C_locale;
-
-#if HB_USE_ATEXIT
-static
-void free_static_C_locale ()
-{
- static_C_locale.free_instance ();
-}
-#endif
-
-static HB_LOCALE_T
-get_C_locale ()
-{
- return static_C_locale.get_unconst ();
+ return _parse_number<unsigned> (pp, end, pv, whole_buffer,
+ [base] (const char *p, char **end)
+ { return strtoul (p, end, base); });
}
-#endif /* USE_XLOCALE */
bool
-hb_parse_double (const char **pp, const char *end, double *pv,
- bool whole_buffer)
+hb_parse_double (const char **pp, const char *end, double *pv, bool whole_buffer)
{
- return _parse_number<double> (pp, end, pv, whole_buffer,
- [] (const char *p, char **end)
- {
-#ifdef USE_XLOCALE
- return strtod_l (p, end, get_C_locale ());
-#else
- return strtod_rl (p, end);
-#endif
- });
+ const char *pend = end;
+ *pv = strtod_rl (*pp, &pend);
+ if (unlikely (*pp == pend)) return false;
+ *pp = pend;
+ return !whole_buffer || end == pend;
}
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 cb1fdf1c998..2f01ce91e98 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
@@ -249,7 +249,7 @@ struct TTCHeader
switch (u.header.version.major) {
case 2: /* version 2 is compatible with version 1 */
case 1: return u.version1.get_face (i);
- default:return Null(OpenTypeFontFace);
+ default:return Null (OpenTypeFontFace);
}
}
@@ -284,7 +284,7 @@ struct TTCHeader
struct ResourceRecord
{
const OpenTypeFontFace & get_face (const void *data_base) const
- { return CastR<OpenTypeFontFace> ((data_base+offset).arrayZ); }
+ { return * reinterpret_cast<const OpenTypeFontFace *> ((data_base+offset).arrayZ); }
bool sanitize (hb_sanitize_context_t *c,
const void *data_base) const
@@ -478,7 +478,7 @@ struct OpenTypeFontFile
case TrueTypeTag: return u.fontFace;
case TTCTag: return u.ttcHeader.get_face (i);
case DFontTag: return u.rfHeader.get_face (i, base_offset);
- default: return Null(OpenTypeFontFace);
+ default: return Null (OpenTypeFontFace);
}
}
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 af242ece12e..fee71df8465 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
@@ -73,6 +73,13 @@ struct IntType
HB_INTERNAL static int cmp (const IntType *a, const IntType *b)
{ return b->cmp (*a); }
+ HB_INTERNAL static int cmp (const void *a, const void *b)
+ {
+ IntType *pa = (IntType *) a;
+ IntType *pb = (IntType *) b;
+
+ return pb->cmp (*pa);
+ }
template <typename Type2>
int cmp (Type2 a) const
{
@@ -306,11 +313,8 @@ struct OffsetTo : Offset<OffsetType, has_null>
}
template <typename ...Ts>
- bool serialize_subset (hb_subset_context_t *c,
- const OffsetTo& src,
- const void *src_base,
- const void *dst_base,
- Ts&&... ds)
+ bool serialize_subset (hb_subset_context_t *c, const OffsetTo& src,
+ const void *src_base, Ts&&... ds)
{
*this = 0;
if (src.is_null ())
@@ -323,7 +327,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
bool ret = c->dispatch (src_base+src, hb_forward<Ts> (ds)...);
if (ret || !has_null)
- s->add_link (*this, s->pop_pack (), dst_base);
+ s->add_link (*this, s->pop_pack ());
else
s->pop_discard ();
@@ -331,11 +335,13 @@ struct OffsetTo : Offset<OffsetType, has_null>
}
/* TODO: Somehow merge this with previous function into a serialize_dispatch(). */
+ /* Workaround clang bug: https://bugs.llvm.org/show_bug.cgi?id=23029
+ * Can't compile: whence = hb_serialize_context_t::Head followed by Ts&&...
+ */
template <typename ...Ts>
- bool serialize_copy (hb_serialize_context_t *c,
- const OffsetTo& src,
- const void *src_base,
- const void *dst_base,
+ bool serialize_copy (hb_serialize_context_t *c, const OffsetTo& src,
+ const void *src_base, unsigned dst_bias,
+ hb_serialize_context_t::whence_t whence,
Ts&&... ds)
{
*this = 0;
@@ -346,11 +352,15 @@ struct OffsetTo : Offset<OffsetType, has_null>
bool ret = c->copy (src_base+src, hb_forward<Ts> (ds)...);
- c->add_link (*this, c->pop_pack (), dst_base);
+ c->add_link (*this, c->pop_pack (), whence, dst_bias);
return ret;
}
+ bool serialize_copy (hb_serialize_context_t *c, const OffsetTo& src,
+ const void *src_base, unsigned dst_bias = 0)
+ { return serialize_copy (c, src, src_base, dst_bias, hb_serialize_context_t::Head); }
+
bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -594,7 +604,7 @@ struct ArrayOf
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
{ return as_array ().sub_array (start_offset, count); }
- bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+ hb_success_t serialize (hb_serialize_context_t *c, unsigned items_len)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
@@ -604,7 +614,7 @@ struct ArrayOf
}
template <typename Iterator,
hb_requires (hb_is_source_of (Iterator, Type))>
- bool serialize (hb_serialize_context_t *c, Iterator items)
+ hb_success_t serialize (hb_serialize_context_t *c, Iterator items)
{
TRACE_SERIALIZE (this);
unsigned count = items.len ();
@@ -1026,18 +1036,15 @@ struct VarSizedBinSearchArrayOf
template <typename T>
const Type *bsearch (const T &key) const
{
- unsigned int size = header.unitSize;
- int min = 0, max = (int) get_length () - 1;
- while (min <= max)
- {
- int mid = ((unsigned int) min + (unsigned int) max) / 2;
- const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
- int c = p->cmp (key);
- if (c < 0) max = mid - 1;
- else if (c > 0) min = mid + 1;
- else return p;
- }
- return nullptr;
+ unsigned pos;
+ return hb_bsearch_impl (&pos,
+ key,
+ (const void *) bytesZ,
+ get_length (),
+ header.unitSize,
+ _hb_cmp_method<T, Type>)
+ ? (const Type *) (((const char *) &bytesZ) + (pos * header.unitSize))
+ : nullptr;
}
private:
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 6735c74be49..e5286cd792d 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
@@ -38,6 +38,9 @@ using namespace OT;
#define CFF_UNDEF_CODE 0xFFFFFFFF
+using objidx_t = hb_serialize_context_t::objidx_t;
+using whence_t = hb_serialize_context_t::whence_t;
+
/* utility macro */
template<typename Type>
static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset)
@@ -89,11 +92,14 @@ struct CFFIndex
unsigned int offset_array_size () const
{ return calculate_offset_array_size (offSize, count); }
- static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count,
- unsigned int dataSize)
+ CFFIndex *copy (hb_serialize_context_t *c) const
{
- if (count == 0) return COUNT::static_size;
- return min_size + calculate_offset_array_size (offSize_, count) + dataSize;
+ TRACE_SERIALIZE (this);
+ unsigned int size = get_size ();
+ CFFIndex *out = c->allocate_size<CFFIndex> (size);
+ if (likely (out))
+ memcpy (out, this, size);
+ return_trace (out);
}
bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
@@ -101,7 +107,7 @@ struct CFFIndex
TRACE_SERIALIZE (this);
unsigned int size = src.get_size ();
CFFIndex *dest = c->allocate_size<CFFIndex> (size);
- if (unlikely (dest == nullptr)) return_trace (false);
+ if (unlikely (!dest)) return_trace (false);
memcpy (dest, &src, size);
return_trace (true);
}
@@ -114,7 +120,7 @@ struct CFFIndex
if (byteArray.length == 0)
{
COUNT *dest = c->allocate_min<COUNT> ();
- if (unlikely (dest == nullptr)) return_trace (false);
+ if (unlikely (!dest)) return_trace (false);
*dest = 0;
}
else
@@ -139,10 +145,9 @@ struct CFFIndex
/* serialize data */
for (unsigned int i = 0; i < byteArray.length; i++)
{
- const byte_str_t &bs = byteArray[i];
- unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
- if (unlikely (dest == nullptr))
- return_trace (false);
+ const byte_str_t &bs = byteArray[i];
+ unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
+ if (unlikely (!dest)) return_trace (false);
memcpy (dest, &bs[0], bs.length);
}
}
@@ -163,6 +168,71 @@ struct CFFIndex
return result;
}
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator it)
+ {
+ TRACE_SERIALIZE (this);
+ if (it.len () == 0)
+ {
+ COUNT *dest = c->allocate_min<COUNT> ();
+ if (unlikely (!dest)) return_trace (false);
+ *dest = 0;
+ }
+ else
+ {
+ serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; }));
+ for (const byte_str_t &_ : +it)
+ _.copy (c);
+ }
+ return_trace (true);
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ const byte_str_array_t &byteArray)
+ { return serialize (c, + hb_iter (byteArray)); }
+
+ bool serialize (hb_serialize_context_t *c,
+ const str_buff_vec_t &buffArray)
+ {
+ auto it =
+ + hb_iter (buffArray)
+ | hb_map ([] (const str_buff_t &_) { return byte_str_t (_.arrayZ, _.length); })
+ ;
+ return serialize (c, it);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool serialize_header (hb_serialize_context_t *c,
+ Iterator it)
+ {
+ TRACE_SERIALIZE (this);
+
+ unsigned total = + it | hb_reduce (hb_add, 0);
+ unsigned off_size = calcOffSize (total);
+
+ /* serialize CFFIndex header */
+ if (unlikely (!c->extend_min (*this))) return_trace (false);
+ this->count = it.len ();
+ this->offSize = off_size;
+ if (unlikely (!c->allocate_size<HBUINT8> (off_size * (it.len () + 1))))
+ return_trace (false);
+
+ /* serialize indices */
+ unsigned int offset = 1;
+ unsigned int i = 0;
+ for (unsigned _ : +it)
+ {
+ CFFIndex<COUNT>::set_offset_at (i++, offset);
+ offset += _;
+ }
+ CFFIndex<COUNT>::set_offset_at (i, offset);
+
+ return_trace (true);
+ }
+
void set_offset_at (unsigned int index, unsigned int offset)
{
HBUINT8 *p = offsets + offSize * index + offSize;
@@ -189,7 +259,7 @@ struct CFFIndex
unsigned int length_at (unsigned int index) const
{
if (unlikely ((offset_at (index + 1) < offset_at (index)) ||
- (offset_at (index + 1) > offset_at (count))))
+ (offset_at (index + 1) > offset_at (count))))
return 0;
return offset_at (index + 1) - offset_at (index);
}
@@ -237,7 +307,8 @@ struct CFFIndex
public:
COUNT count; /* Number of object data. Note there are (count+1) offsets */
HBUINT8 offSize; /* The byte size of each offset in the offsets array. */
- HBUINT8 offsets[HB_VAR_ARRAY]; /* The array of (count + 1) offsets into objects array (1-base). */
+ HBUINT8 offsets[HB_VAR_ARRAY];
+ /* The array of (count + 1) offsets into objects array (1-base). */
/* HBUINT8 data[HB_VAR_ARRAY]; Object data */
public:
DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
@@ -250,7 +321,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
{
if (likely (index < CFFIndex<COUNT>::count))
return byte_str_t (CFFIndex<COUNT>::data_base () + CFFIndex<COUNT>::offset_at (index) - 1, CFFIndex<COUNT>::length_at (index));
- return Null(byte_str_t);
+ return Null (byte_str_t);
}
template <typename DATA, typename PARAM1, typename PARAM2>
@@ -284,85 +355,41 @@ struct CFFIndexOf : CFFIndex<COUNT>
for (unsigned int i = 0; i < dataArrayLen; i++)
{
TYPE *dest = c->start_embed<TYPE> ();
- if (unlikely (dest == nullptr ||
- !dest->serialize (c, dataArray[i], param1, param2)))
+ if (unlikely (!dest || !dest->serialize (c, dataArray[i], param1, param2)))
return_trace (false);
}
return_trace (true);
}
-
- /* in parallel to above */
- template <typename DATA, typename PARAM>
- static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
- const DATA *dataArray,
- unsigned int dataArrayLen,
- hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
- const PARAM &param)
- {
- /* determine offset size */
- unsigned int totalDataSize = 0;
- for (unsigned int i = 0; i < dataArrayLen; i++)
- {
- unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
- dataSizeArray[i] = dataSize;
- totalDataSize += dataSize;
- }
- offSize_ = calcOffSize (totalDataSize);
-
- return CFFIndex<COUNT>::calculate_serialized_size (offSize_, dataArrayLen, totalDataSize);
- }
};
/* Top Dict, Font Dict, Private Dict */
struct Dict : UnsizedByteStr
{
- template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
+ template <typename DICTVAL, typename OP_SERIALIZER, typename ...Ts>
bool serialize (hb_serialize_context_t *c,
const DICTVAL &dictval,
OP_SERIALIZER& opszr,
- PARAM& param)
+ Ts&&... ds)
{
TRACE_SERIALIZE (this);
for (unsigned int i = 0; i < dictval.get_count (); i++)
- if (unlikely (!opszr.serialize (c, dictval[i], param)))
+ if (unlikely (!opszr.serialize (c, dictval[i], hb_forward<Ts> (ds)...)))
return_trace (false);
return_trace (true);
}
- /* in parallel to above */
- template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
- static unsigned int calculate_serialized_size (const DICTVAL &dictval,
- OP_SERIALIZER& opszr,
- PARAM& param)
- {
- unsigned int size = 0;
- for (unsigned int i = 0; i < dictval.get_count (); i++)
- size += opszr.calculate_serialized_size (dictval[i], param);
- return size;
- }
-
- template <typename DICTVAL, typename OP_SERIALIZER>
- static unsigned int calculate_serialized_size (const DICTVAL &dictval,
- OP_SERIALIZER& opszr)
- {
- unsigned int size = 0;
- for (unsigned int i = 0; i < dictval.get_count (); i++)
- size += opszr.calculate_serialized_size (dictval[i]);
- return size;
- }
-
- template <typename INTTYPE, int minVal, int maxVal>
- static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, int value, op_code_t intOp)
+ template <typename T, typename V>
+ static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, V value, op_code_t intOp)
{
// XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
- if (/*unlikely*/ (!serialize_int<INTTYPE, minVal, maxVal> (c, intOp, value)))
+ if (/*unlikely*/ (!serialize_int<T, V> (c, intOp, value)))
return false;
TRACE_SERIALIZE (this);
/* serialize the opcode */
HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
- if (unlikely (p == nullptr)) return_trace (false);
+ if (unlikely (!p)) return_trace (false);
if (Is_OpCode_ESC (op))
{
*p = OpCode_escape;
@@ -373,17 +400,28 @@ struct Dict : UnsizedByteStr
return_trace (true);
}
- static bool serialize_uint4_op (hb_serialize_context_t *c, op_code_t op, int value)
- { return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
+ template <typename V>
+ static bool serialize_int4_op (hb_serialize_context_t *c, op_code_t op, V value)
+ { return serialize_int_op<HBINT32> (c, op, value, OpCode_longintdict); }
+
+ template <typename V>
+ static bool serialize_int2_op (hb_serialize_context_t *c, op_code_t op, V value)
+ { return serialize_int_op<HBINT16> (c, op, value, OpCode_shortint); }
- static bool serialize_uint2_op (hb_serialize_context_t *c, op_code_t op, int value)
- { return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
+ template <typename T, int int_op>
+ static bool serialize_link_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence)
+ {
+ T &ofs = *(T *) (c->head + OpCode_Size (int_op));
+ if (unlikely (!serialize_int_op<T> (c, op, 0, int_op))) return false;
+ c->add_link (ofs, link, whence);
+ return true;
+ }
- static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value)
- { return serialize_uint4_op (c, op, value); }
+ static bool serialize_link4_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head)
+ { return serialize_link_op<HBINT32, OpCode_longintdict> (c, op, link, whence); }
- static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value)
- { return serialize_uint2_op (c, op, value); }
+ static bool serialize_link2_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head)
+ { return serialize_link_op<HBINT16, OpCode_shortint> (c, op, link, whence); }
};
struct TopDict : Dict {};
@@ -392,105 +430,39 @@ struct PrivateDict : Dict {};
struct table_info_t
{
- void init () { offSize = offset = size = 0; }
+ void init () { offset = size = 0; link = 0; }
unsigned int offset;
unsigned int size;
- unsigned int offSize;
+ objidx_t link;
};
template <typename COUNT>
struct FDArray : CFFIndexOf<COUNT, FontDict>
{
- /* used by CFF1 */
- template <typename DICTVAL, typename OP_SERIALIZER>
+ template <typename DICTVAL, typename INFO, typename Iterator, typename OP_SERIALIZER>
bool serialize (hb_serialize_context_t *c,
- unsigned int offSize_,
- const hb_vector_t<DICTVAL> &fontDicts,
+ Iterator it,
OP_SERIALIZER& opszr)
{
TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (*this))) return_trace (false);
- this->count = fontDicts.length;
- this->offSize = offSize_;
- if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
- return_trace (false);
- /* serialize font dict offsets */
- unsigned int offset = 1;
- unsigned int fid = 0;
- for (; fid < fontDicts.length; fid++)
- {
- CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
- offset += FontDict::calculate_serialized_size (fontDicts[fid], opszr);
- }
- CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
-
- /* serialize font dicts */
- for (unsigned int i = 0; i < fontDicts.length; i++)
+ /* serialize INDEX data */
+ hb_vector_t<unsigned> sizes;
+ c->push ();
+ + it
+ | hb_map ([&] (const hb_pair_t<const DICTVAL&, const INFO&> &_)
{
FontDict *dict = c->start_embed<FontDict> ();
- if (unlikely (!dict->serialize (c, fontDicts[i], opszr, fontDicts[i])))
- return_trace (false);
- }
- return_trace (true);
- }
-
- /* used by CFF2 */
- template <typename DICTVAL, typename OP_SERIALIZER>
- bool serialize (hb_serialize_context_t *c,
- unsigned int offSize_,
- const hb_vector_t<DICTVAL> &fontDicts,
- unsigned int fdCount,
- const hb_inc_bimap_t &fdmap,
- OP_SERIALIZER& opszr,
- const hb_vector_t<table_info_t> &privateInfos)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (*this))) return_trace (false);
- this->count = fdCount;
- this->offSize = offSize_;
- if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
- return_trace (false);
-
- /* serialize font dict offsets */
- unsigned int offset = 1;
- unsigned int fid = 0;
- for (unsigned i = 0; i < fontDicts.length; i++)
- if (fdmap.has (i))
- {
- if (unlikely (fid >= fdCount)) return_trace (false);
- CFFIndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
- offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
- }
- CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
-
- /* serialize font dicts */
- for (unsigned int i = 0; i < fontDicts.length; i++)
- if (fdmap.has (i))
- {
- FontDict *dict = c->start_embed<FontDict> ();
- if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]])))
- return_trace (false);
- }
- return_trace (true);
- }
-
- /* in parallel to above */
- template <typename OP_SERIALIZER, typename DICTVAL>
- static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
- const hb_vector_t<DICTVAL> &fontDicts,
- unsigned int fdCount,
- const hb_inc_bimap_t &fdmap,
- OP_SERIALIZER& opszr)
- {
- unsigned int dictsSize = 0;
- for (unsigned int i = 0; i < fontDicts.len; i++)
- if (fdmap.has (i))
- dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr);
-
- offSize_ = calcOffSize (dictsSize);
- return CFFIndex<COUNT>::calculate_serialized_size (offSize_, fdCount, dictsSize);
+ dict->serialize (c, _.first, opszr, _.second);
+ return c->head - (const char*)dict;
+ })
+ | hb_sink (sizes)
+ ;
+ c->pop_pack (false);
+
+ /* serialize INDEX header */
+ return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes)));
}
};
@@ -544,7 +516,7 @@ struct FDSelect3_4
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) ||
- (nRanges () == 0) || ranges[0].first != 0))
+ (nRanges () == 0) || ranges[0].first != 0))
return_trace (false);
for (unsigned int i = 1; i < nRanges (); i++)
@@ -588,14 +560,11 @@ struct FDSelect
TRACE_SERIALIZE (this);
unsigned int size = src.get_size (num_glyphs);
FDSelect *dest = c->allocate_size<FDSelect> (size);
- if (unlikely (dest == nullptr)) return_trace (false);
+ if (unlikely (!dest)) return_trace (false);
memcpy (dest, &src, size);
return_trace (true);
}
- unsigned int calculate_serialized_size (unsigned int num_glyphs) const
- { return get_size (num_glyphs); }
-
unsigned int get_size (unsigned int num_glyphs) const
{
switch (format)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-std-str.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-std-str.hh
new file mode 100644
index 00000000000..65d56ae18b5
--- /dev/null
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-std-str.hh
@@ -0,0 +1,425 @@
+/*
+ * Copyright © 2019 Adobe, 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_OT_CFF1_STD_STR_HH
+#if 0 /* Make checks happy. */
+#define HB_OT_CFF1_STD_STR_HH
+#include "hb.hh"
+#endif
+
+_S(".notdef")
+_S("space")
+_S("exclam")
+_S("quotedbl")
+_S("numbersign")
+_S("dollar")
+_S("percent")
+_S("ampersand")
+_S("quoteright")
+_S("parenleft")
+_S("parenright")
+_S("asterisk")
+_S("plus")
+_S("comma")
+_S("hyphen")
+_S("period")
+_S("slash")
+_S("zero")
+_S("one")
+_S("two")
+_S("three")
+_S("four")
+_S("five")
+_S("six")
+_S("seven")
+_S("eight")
+_S("nine")
+_S("colon")
+_S("semicolon")
+_S("less")
+_S("equal")
+_S("greater")
+_S("question")
+_S("at")
+_S("A")
+_S("B")
+_S("C")
+_S("D")
+_S("E")
+_S("F")
+_S("G")
+_S("H")
+_S("I")
+_S("J")
+_S("K")
+_S("L")
+_S("M")
+_S("N")
+_S("O")
+_S("P")
+_S("Q")
+_S("R")
+_S("S")
+_S("T")
+_S("U")
+_S("V")
+_S("W")
+_S("X")
+_S("Y")
+_S("Z")
+_S("bracketleft")
+_S("backslash")
+_S("bracketright")
+_S("asciicircum")
+_S("underscore")
+_S("quoteleft")
+_S("a")
+_S("b")
+_S("c")
+_S("d")
+_S("e")
+_S("f")
+_S("g")
+_S("h")
+_S("i")
+_S("j")
+_S("k")
+_S("l")
+_S("m")
+_S("n")
+_S("o")
+_S("p")
+_S("q")
+_S("r")
+_S("s")
+_S("t")
+_S("u")
+_S("v")
+_S("w")
+_S("x")
+_S("y")
+_S("z")
+_S("braceleft")
+_S("bar")
+_S("braceright")
+_S("asciitilde")
+_S("exclamdown")
+_S("cent")
+_S("sterling")
+_S("fraction")
+_S("yen")
+_S("florin")
+_S("section")
+_S("currency")
+_S("quotesingle")
+_S("quotedblleft")
+_S("guillemotleft")
+_S("guilsinglleft")
+_S("guilsinglright")
+_S("fi")
+_S("fl")
+_S("endash")
+_S("dagger")
+_S("daggerdbl")
+_S("periodcentered")
+_S("paragraph")
+_S("bullet")
+_S("quotesinglbase")
+_S("quotedblbase")
+_S("quotedblright")
+_S("guillemotright")
+_S("ellipsis")
+_S("perthousand")
+_S("questiondown")
+_S("grave")
+_S("acute")
+_S("circumflex")
+_S("tilde")
+_S("macron")
+_S("breve")
+_S("dotaccent")
+_S("dieresis")
+_S("ring")
+_S("cedilla")
+_S("hungarumlaut")
+_S("ogonek")
+_S("caron")
+_S("emdash")
+_S("AE")
+_S("ordfeminine")
+_S("Lslash")
+_S("Oslash")
+_S("OE")
+_S("ordmasculine")
+_S("ae")
+_S("dotlessi")
+_S("lslash")
+_S("oslash")
+_S("oe")
+_S("germandbls")
+_S("onesuperior")
+_S("logicalnot")
+_S("mu")
+_S("trademark")
+_S("Eth")
+_S("onehalf")
+_S("plusminus")
+_S("Thorn")
+_S("onequarter")
+_S("divide")
+_S("brokenbar")
+_S("degree")
+_S("thorn")
+_S("threequarters")
+_S("twosuperior")
+_S("registered")
+_S("minus")
+_S("eth")
+_S("multiply")
+_S("threesuperior")
+_S("copyright")
+_S("Aacute")
+_S("Acircumflex")
+_S("Adieresis")
+_S("Agrave")
+_S("Aring")
+_S("Atilde")
+_S("Ccedilla")
+_S("Eacute")
+_S("Ecircumflex")
+_S("Edieresis")
+_S("Egrave")
+_S("Iacute")
+_S("Icircumflex")
+_S("Idieresis")
+_S("Igrave")
+_S("Ntilde")
+_S("Oacute")
+_S("Ocircumflex")
+_S("Odieresis")
+_S("Ograve")
+_S("Otilde")
+_S("Scaron")
+_S("Uacute")
+_S("Ucircumflex")
+_S("Udieresis")
+_S("Ugrave")
+_S("Yacute")
+_S("Ydieresis")
+_S("Zcaron")
+_S("aacute")
+_S("acircumflex")
+_S("adieresis")
+_S("agrave")
+_S("aring")
+_S("atilde")
+_S("ccedilla")
+_S("eacute")
+_S("ecircumflex")
+_S("edieresis")
+_S("egrave")
+_S("iacute")
+_S("icircumflex")
+_S("idieresis")
+_S("igrave")
+_S("ntilde")
+_S("oacute")
+_S("ocircumflex")
+_S("odieresis")
+_S("ograve")
+_S("otilde")
+_S("scaron")
+_S("uacute")
+_S("ucircumflex")
+_S("udieresis")
+_S("ugrave")
+_S("yacute")
+_S("ydieresis")
+_S("zcaron")
+_S("exclamsmall")
+_S("Hungarumlautsmall")
+_S("dollaroldstyle")
+_S("dollarsuperior")
+_S("ampersandsmall")
+_S("Acutesmall")
+_S("parenleftsuperior")
+_S("parenrightsuperior")
+_S("twodotenleader")
+_S("onedotenleader")
+_S("zerooldstyle")
+_S("oneoldstyle")
+_S("twooldstyle")
+_S("threeoldstyle")
+_S("fouroldstyle")
+_S("fiveoldstyle")
+_S("sixoldstyle")
+_S("sevenoldstyle")
+_S("eightoldstyle")
+_S("nineoldstyle")
+_S("commasuperior")
+_S("threequartersemdash")
+_S("periodsuperior")
+_S("questionsmall")
+_S("asuperior")
+_S("bsuperior")
+_S("centsuperior")
+_S("dsuperior")
+_S("esuperior")
+_S("isuperior")
+_S("lsuperior")
+_S("msuperior")
+_S("nsuperior")
+_S("osuperior")
+_S("rsuperior")
+_S("ssuperior")
+_S("tsuperior")
+_S("ff")
+_S("ffi")
+_S("ffl")
+_S("parenleftinferior")
+_S("parenrightinferior")
+_S("Circumflexsmall")
+_S("hyphensuperior")
+_S("Gravesmall")
+_S("Asmall")
+_S("Bsmall")
+_S("Csmall")
+_S("Dsmall")
+_S("Esmall")
+_S("Fsmall")
+_S("Gsmall")
+_S("Hsmall")
+_S("Ismall")
+_S("Jsmall")
+_S("Ksmall")
+_S("Lsmall")
+_S("Msmall")
+_S("Nsmall")
+_S("Osmall")
+_S("Psmall")
+_S("Qsmall")
+_S("Rsmall")
+_S("Ssmall")
+_S("Tsmall")
+_S("Usmall")
+_S("Vsmall")
+_S("Wsmall")
+_S("Xsmall")
+_S("Ysmall")
+_S("Zsmall")
+_S("colonmonetary")
+_S("onefitted")
+_S("rupiah")
+_S("Tildesmall")
+_S("exclamdownsmall")
+_S("centoldstyle")
+_S("Lslashsmall")
+_S("Scaronsmall")
+_S("Zcaronsmall")
+_S("Dieresissmall")
+_S("Brevesmall")
+_S("Caronsmall")
+_S("Dotaccentsmall")
+_S("Macronsmall")
+_S("figuredash")
+_S("hypheninferior")
+_S("Ogoneksmall")
+_S("Ringsmall")
+_S("Cedillasmall")
+_S("questiondownsmall")
+_S("oneeighth")
+_S("threeeighths")
+_S("fiveeighths")
+_S("seveneighths")
+_S("onethird")
+_S("twothirds")
+_S("zerosuperior")
+_S("foursuperior")
+_S("fivesuperior")
+_S("sixsuperior")
+_S("sevensuperior")
+_S("eightsuperior")
+_S("ninesuperior")
+_S("zeroinferior")
+_S("oneinferior")
+_S("twoinferior")
+_S("threeinferior")
+_S("fourinferior")
+_S("fiveinferior")
+_S("sixinferior")
+_S("seveninferior")
+_S("eightinferior")
+_S("nineinferior")
+_S("centinferior")
+_S("dollarinferior")
+_S("periodinferior")
+_S("commainferior")
+_S("Agravesmall")
+_S("Aacutesmall")
+_S("Acircumflexsmall")
+_S("Atildesmall")
+_S("Adieresissmall")
+_S("Aringsmall")
+_S("AEsmall")
+_S("Ccedillasmall")
+_S("Egravesmall")
+_S("Eacutesmall")
+_S("Ecircumflexsmall")
+_S("Edieresissmall")
+_S("Igravesmall")
+_S("Iacutesmall")
+_S("Icircumflexsmall")
+_S("Idieresissmall")
+_S("Ethsmall")
+_S("Ntildesmall")
+_S("Ogravesmall")
+_S("Oacutesmall")
+_S("Ocircumflexsmall")
+_S("Otildesmall")
+_S("Odieresissmall")
+_S("OEsmall")
+_S("Oslashsmall")
+_S("Ugravesmall")
+_S("Uacutesmall")
+_S("Ucircumflexsmall")
+_S("Udieresissmall")
+_S("Yacutesmall")
+_S("Thornsmall")
+_S("Ydieresissmall")
+_S("001.000")
+_S("001.001")
+_S("001.002")
+_S("001.003")
+_S("Black")
+_S("Bold")
+_S("Book")
+_S("Light")
+_S("Medium")
+_S("Regular")
+_S("Roman")
+_S("Semibold")
+
+#endif /* HB_OT_CFF1_STD_STR_HH */
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 55abd11d610..66b9c8c907a 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
@@ -28,11 +28,25 @@
#ifndef HB_NO_CFF
+#include "hb-draw.hh"
+#include "hb-algs.hh"
#include "hb-ot-cff1-table.hh"
#include "hb-cff1-interp-cs.hh"
using namespace CFF;
+struct sid_to_gid_t
+{
+ uint16_t sid;
+ uint8_t gid;
+
+ int cmp (uint16_t a) const
+ {
+ if (a == sid) return 0;
+ return (a < sid) ? -1 : 1;
+ }
+};
+
/* SID to code */
static const uint8_t standard_encoding_to_code [] =
{
@@ -104,6 +118,80 @@ static const uint16_t expert_subset_charset_to_sid [] =
340, 341, 342, 343, 344, 345, 346
};
+/* SID to glyph ID */
+static const sid_to_gid_t expert_charset_sid_to_gid [] =
+{
+ { 1, 1 }, { 13, 12 }, { 14, 13 }, { 15, 14 },
+ { 27, 26 }, { 28, 27 }, { 99, 15 }, { 109, 46 },
+ { 110, 47 }, { 150, 111 }, { 155, 101 }, { 158, 100 },
+ { 163, 102 }, { 164, 112 }, { 169, 113 }, { 229, 2 },
+ { 230, 3 }, { 231, 4 }, { 232, 5 }, { 233, 6 },
+ { 234, 7 }, { 235, 8 }, { 236, 9 }, { 237, 10 },
+ { 238, 11 }, { 239, 16 }, { 240, 17 }, { 241, 18 },
+ { 242, 19 }, { 243, 20 }, { 244, 21 }, { 245, 22 },
+ { 246, 23 }, { 247, 24 }, { 248, 25 }, { 249, 28 },
+ { 250, 29 }, { 251, 30 }, { 252, 31 }, { 253, 32 },
+ { 254, 33 }, { 255, 34 }, { 256, 35 }, { 257, 36 },
+ { 258, 37 }, { 259, 38 }, { 260, 39 }, { 261, 40 },
+ { 262, 41 }, { 263, 42 }, { 264, 43 }, { 265, 44 },
+ { 266, 45 }, { 267, 48 }, { 268, 49 }, { 269, 50 },
+ { 270, 51 }, { 271, 52 }, { 272, 53 }, { 273, 54 },
+ { 274, 55 }, { 275, 56 }, { 276, 57 }, { 277, 58 },
+ { 278, 59 }, { 279, 60 }, { 280, 61 }, { 281, 62 },
+ { 282, 63 }, { 283, 64 }, { 284, 65 }, { 285, 66 },
+ { 286, 67 }, { 287, 68 }, { 288, 69 }, { 289, 70 },
+ { 290, 71 }, { 291, 72 }, { 292, 73 }, { 293, 74 },
+ { 294, 75 }, { 295, 76 }, { 296, 77 }, { 297, 78 },
+ { 298, 79 }, { 299, 80 }, { 300, 81 }, { 301, 82 },
+ { 302, 83 }, { 303, 84 }, { 304, 85 }, { 305, 86 },
+ { 306, 87 }, { 307, 88 }, { 308, 89 }, { 309, 90 },
+ { 310, 91 }, { 311, 92 }, { 312, 93 }, { 313, 94 },
+ { 314, 95 }, { 315, 96 }, { 316, 97 }, { 317, 98 },
+ { 318, 99 }, { 319, 103 }, { 320, 104 }, { 321, 105 },
+ { 322, 106 }, { 323, 107 }, { 324, 108 }, { 325, 109 },
+ { 326, 110 }, { 327, 114 }, { 328, 115 }, { 329, 116 },
+ { 330, 117 }, { 331, 118 }, { 332, 119 }, { 333, 120 },
+ { 334, 121 }, { 335, 122 }, { 336, 123 }, { 337, 124 },
+ { 338, 125 }, { 339, 126 }, { 340, 127 }, { 341, 128 },
+ { 342, 129 }, { 343, 130 }, { 344, 131 }, { 345, 132 },
+ { 346, 133 }, { 347, 134 }, { 348, 135 }, { 349, 136 },
+ { 350, 137 }, { 351, 138 }, { 352, 139 }, { 353, 140 },
+ { 354, 141 }, { 355, 142 }, { 356, 143 }, { 357, 144 },
+ { 358, 145 }, { 359, 146 }, { 360, 147 }, { 361, 148 },
+ { 362, 149 }, { 363, 150 }, { 364, 151 }, { 365, 152 },
+ { 366, 153 }, { 367, 154 }, { 368, 155 }, { 369, 156 },
+ { 370, 157 }, { 371, 158 }, { 372, 159 }, { 373, 160 },
+ { 374, 161 }, { 375, 162 }, { 376, 163 }, { 377, 164 },
+ { 378, 165 }
+};
+
+/* SID to glyph ID */
+static const sid_to_gid_t expert_subset_charset_sid_to_gid [] =
+{
+ { 1, 1 }, { 13, 8 }, { 14, 9 }, { 15, 10 },
+ { 27, 22 }, { 28, 23 }, { 99, 11 }, { 109, 41 },
+ { 110, 42 }, { 150, 64 }, { 155, 55 }, { 158, 54 },
+ { 163, 56 }, { 164, 65 }, { 169, 66 }, { 231, 2 },
+ { 232, 3 }, { 235, 4 }, { 236, 5 }, { 237, 6 },
+ { 238, 7 }, { 239, 12 }, { 240, 13 }, { 241, 14 },
+ { 242, 15 }, { 243, 16 }, { 244, 17 }, { 245, 18 },
+ { 246, 19 }, { 247, 20 }, { 248, 21 }, { 249, 24 },
+ { 250, 25 }, { 251, 26 }, { 253, 27 }, { 254, 28 },
+ { 255, 29 }, { 256, 30 }, { 257, 31 }, { 258, 32 },
+ { 259, 33 }, { 260, 34 }, { 261, 35 }, { 262, 36 },
+ { 263, 37 }, { 264, 38 }, { 265, 39 }, { 266, 40 },
+ { 267, 43 }, { 268, 44 }, { 269, 45 }, { 270, 46 },
+ { 272, 47 }, { 300, 48 }, { 301, 49 }, { 302, 50 },
+ { 305, 51 }, { 314, 52 }, { 315, 53 }, { 320, 57 },
+ { 321, 58 }, { 322, 59 }, { 323, 60 }, { 324, 61 },
+ { 325, 62 }, { 326, 63 }, { 327, 67 }, { 328, 68 },
+ { 329, 69 }, { 330, 70 }, { 331, 71 }, { 332, 72 },
+ { 333, 73 }, { 334, 74 }, { 335, 75 }, { 336, 76 },
+ { 337, 77 }, { 338, 78 }, { 339, 79 }, { 340, 80 },
+ { 341, 81 }, { 342, 82 }, { 343, 83 }, { 344, 84 },
+ { 345, 85 }, { 346, 86 }
+};
+
/* code to SID */
static const uint8_t standard_encoding_to_sid [] =
{
@@ -157,6 +245,18 @@ hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t gl
return 0;
}
+hb_codepoint_t OT::cff1::lookup_expert_charset_for_glyph (hb_codepoint_t sid)
+{
+ const auto *pair = hb_sorted_array (expert_charset_sid_to_gid).bsearch (sid);
+ return pair ? pair->gid : 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid)
+{
+ const auto *pair = hb_sorted_array (expert_subset_charset_sid_to_gid).bsearch (sid);
+ return pair ? pair->gid : 0;
+}
+
hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
{
if (code < ARRAY_LENGTH (standard_encoding_to_sid))
@@ -342,6 +442,130 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
return true;
}
+#ifdef HB_EXPERIMENTAL_API
+struct cff1_path_param_t
+{
+ cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
+ draw_helper_t &draw_helper_, point_t *delta_)
+ {
+ draw_helper = &draw_helper_;
+ cff = cff_;
+ font = font_;
+ delta = delta_;
+ }
+
+ void move_to (const point_t &p)
+ {
+ point_t point = p;
+ if (delta) point.move (*delta);
+ draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
+ }
+
+ void line_to (const point_t &p)
+ {
+ point_t point = p;
+ if (delta) point.move (*delta);
+ draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
+ }
+
+ void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
+ {
+ point_t point1 = p1, point2 = p2, point3 = p3;
+ if (delta)
+ {
+ point1.move (*delta);
+ point2.move (*delta);
+ point3.move (*delta);
+ }
+ draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()),
+ font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()),
+ font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ()));
+ }
+
+ void end_path () { draw_helper->end_path (); }
+
+ hb_font_t *font;
+ draw_helper_t *draw_helper;
+ point_t *delta;
+
+ const OT::cff1::accelerator_t *cff;
+};
+
+struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_interp_env_t, cff1_path_param_t>
+{
+ static void moveto (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt)
+ {
+ param.move_to (pt);
+ env.moveto (pt);
+ }
+
+ static void line (cff1_cs_interp_env_t &env, cff1_path_param_t &param, const point_t &pt1)
+ {
+ param.line_to (pt1);
+ env.moveto (pt1);
+ }
+
+ static void curve (cff1_cs_interp_env_t &env, cff1_path_param_t &param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+ {
+ param.cubic_to (pt1, pt2, pt3);
+ env.moveto (pt3);
+ }
+};
+
+static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
+ draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr);
+
+struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
+{
+ static void process_seac (cff1_cs_interp_env_t &env, cff1_path_param_t& param)
+ {
+ /* End previous path */
+ param.end_path ();
+
+ unsigned int n = env.argStack.get_count ();
+ point_t delta;
+ delta.x = env.argStack[n-4];
+ delta.y = env.argStack[n-3];
+ hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
+ hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
+
+ if (unlikely (!(!env.in_seac && base && accent
+ && _get_path (param.cff, param.font, base, *param.draw_helper, true)
+ && _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta))))
+ env.set_error ();
+ }
+};
+
+bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
+ draw_helper_t &draw_helper, bool in_seac, point_t *delta)
+{
+ if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
+
+ unsigned int fd = cff->fdSelect->get_fd (glyph);
+ cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp;
+ const byte_str_t str = (*cff->charStrings)[glyph];
+ interp.env.init (str, *cff, fd);
+ interp.env.set_in_seac (in_seac);
+ cff1_path_param_t param (cff, font, draw_helper, delta);
+ if (unlikely (!interp.interpret (param))) return false;
+
+ /* Let's end the path specially since it is called inside seac also */
+ param.end_path ();
+
+ return true;
+}
+
+bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
+{
+#ifdef HB_NO_OT_FONT_CFF
+ /* XXX Remove check when this code moves to .hh file. */
+ return true;
+#endif
+
+ return _get_path (this, font, glyph, draw_helper);
+}
+#endif
+
struct get_seac_param_t
{
void init (const OT::cff1::accelerator_t *_cff)
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 ad206511c1e..e1296c391ad 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
@@ -27,15 +27,21 @@
#ifndef HB_OT_CFF1_TABLE_HH
#define HB_OT_CFF1_TABLE_HH
-#include "hb-ot-head-table.hh"
#include "hb-ot-cff-common.hh"
#include "hb-subset-cff1.hh"
+#include "hb-draw.hh"
+
+#define HB_STRING_ARRAY_NAME cff1_std_strings
+#define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh"
+#include "hb-string-array.hh"
+#undef HB_STRING_ARRAY_LIST
+#undef HB_STRING_ARRAY_NAME
namespace CFF {
/*
* CFF -- Compact Font Format (CFF)
- * http://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
+ * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
*/
#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
@@ -49,7 +55,6 @@ template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
typedef CFFIndex<HBUINT16> CFF1Index;
typedef CFF1Index CFF1CharStrings;
-typedef FDArray<HBUINT16> CFF1FDArray;
typedef Subrs<HBUINT16> CFF1Subrs;
struct CFF1FDSelect : FDSelect {};
@@ -169,7 +174,7 @@ struct Encoding
TRACE_SERIALIZE (this);
unsigned int size = src.get_size ();
Encoding *dest = c->allocate_size<Encoding> (size);
- if (unlikely (dest == nullptr)) return_trace (false);
+ if (unlikely (!dest)) return_trace (false);
memcpy (dest, &src, size);
return_trace (true);
}
@@ -183,13 +188,13 @@ struct Encoding
{
TRACE_SERIALIZE (this);
Encoding *dest = c->extend_min (*this);
- if (unlikely (dest == nullptr)) return_trace (false);
+ if (unlikely (!dest)) return_trace (false);
dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
switch (format) {
case 0:
{
Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
- if (unlikely (fmt0 == nullptr)) return_trace (false);
+ if (unlikely (!fmt0)) return_trace (false);
fmt0->nCodes () = enc_count;
unsigned int glyph = 0;
for (unsigned int i = 0; i < code_ranges.length; i++)
@@ -206,7 +211,7 @@ struct Encoding
case 1:
{
Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
- if (unlikely (fmt1 == nullptr)) return_trace (false);
+ if (unlikely (!fmt1)) return_trace (false);
fmt1->nRanges () = code_ranges.length;
for (unsigned int i = 0; i < code_ranges.length; i++)
{
@@ -223,7 +228,7 @@ struct Encoding
if (supp_codes.length)
{
CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
- if (unlikely (suppData == nullptr)) return_trace (false);
+ if (unlikely (!suppData)) return_trace (false);
suppData->nSups () = supp_codes.length;
for (unsigned int i = 0; i < supp_codes.length; i++)
{
@@ -235,23 +240,6 @@ struct Encoding
return_trace (true);
}
- /* parallel to above: calculate the size of a subset Encoding */
- static unsigned int calculate_serialized_size (uint8_t format,
- unsigned int enc_count,
- unsigned int supp_count)
- {
- unsigned int size = min_size;
- switch (format)
- {
- case 0: size += Encoding0::min_size + HBUINT8::static_size * enc_count; break;
- case 1: size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; break;
- default:return 0;
- }
- if (supp_count > 0)
- size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
- return size;
- }
-
unsigned int get_size () const
{
unsigned int size = min_size;
@@ -414,7 +402,7 @@ struct Charset1_2 {
for (unsigned int i = 0;; i++)
{
if (glyph >= num_glyphs)
- return 0;
+ return 0;
if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
return glyph + (sid - ranges[i].first);
glyph += (ranges[i].nLeft + 1);
@@ -457,7 +445,7 @@ struct Charset
TRACE_SERIALIZE (this);
unsigned int size = src.get_size (num_glyphs);
Charset *dest = c->allocate_size<Charset> (size);
- if (unlikely (dest == nullptr)) return_trace (false);
+ if (unlikely (!dest)) return_trace (false);
memcpy (dest, &src, size);
return_trace (true);
}
@@ -470,14 +458,14 @@ struct Charset
{
TRACE_SERIALIZE (this);
Charset *dest = c->extend_min (*this);
- if (unlikely (dest == nullptr)) return_trace (false);
+ if (unlikely (!dest)) return_trace (false);
dest->format = format;
switch (format)
{
case 0:
{
Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
- if (unlikely (fmt0 == nullptr)) return_trace (false);
+ if (unlikely (!fmt0)) return_trace (false);
unsigned int glyph = 0;
for (unsigned int i = 0; i < sid_ranges.length; i++)
{
@@ -491,10 +479,10 @@ struct Charset
case 1:
{
Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
- if (unlikely (fmt1 == nullptr)) return_trace (false);
+ if (unlikely (!fmt1)) return_trace (false);
for (unsigned int i = 0; i < sid_ranges.length; i++)
{
- if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
+ if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
return_trace (false);
fmt1->ranges[i].first = sid_ranges[i].code;
fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
@@ -505,10 +493,10 @@ struct Charset
case 2:
{
Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
- if (unlikely (fmt2 == nullptr)) return_trace (false);
+ if (unlikely (!fmt2)) return_trace (false);
for (unsigned int i = 0; i < sid_ranges.length; i++)
{
- if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
+ if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
return_trace (false);
fmt2->ranges[i].first = sid_ranges[i].code;
fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
@@ -520,19 +508,6 @@ struct Charset
return_trace (true);
}
- /* parallel to above: calculate the size of a subset Charset */
- static unsigned int calculate_serialized_size (uint8_t format,
- unsigned int count)
- {
- switch (format)
- {
- case 0: return min_size + Charset0::min_size + HBUINT16::static_size * (count - 1);
- case 1: return min_size + Charset1::min_size + Charset1_Range::static_size * count;
- case 2: return min_size + Charset2::min_size + Charset2_Range::static_size * count;
- default:return 0;
- }
- }
-
unsigned int get_size (unsigned int num_glyphs) const
{
switch (format)
@@ -544,8 +519,9 @@ struct Charset
}
}
- hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
{
+ if (unlikely (glyph >= num_glyphs)) return 0;
switch (format)
{
case 0: return u.format0.get_sid (glyph);
@@ -594,7 +570,7 @@ struct Charset
struct CFF1StringIndex : CFF1Index
{
bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
- unsigned int offSize_, const hb_inc_bimap_t &sidmap)
+ const hb_inc_bimap_t &sidmap)
{
TRACE_SERIALIZE (this);
if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
@@ -612,30 +588,14 @@ struct CFF1StringIndex : CFF1Index
for (unsigned int i = 0; i < strings.count; i++)
{
hb_codepoint_t j = sidmap[i];
- if (j != CFF_UNDEF_CODE)
+ if (j != HB_MAP_VALUE_INVALID)
bytesArray[j] = strings[i];
}
- bool result = CFF1Index::serialize (c, offSize_, bytesArray);
+ bool result = CFF1Index::serialize (c, bytesArray);
bytesArray.fini ();
return_trace (result);
}
-
- /* in parallel to above */
- unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_inc_bimap_t &sidmap) const
- {
- offSize_ = 0;
- if ((count == 0) || (sidmap.get_population () == 0))
- return count.static_size;
-
- unsigned int dataSize = 0;
- for (unsigned int i = 0; i < count; i++)
- if (sidmap[i] != CFF_UNDEF_CODE)
- dataSize += length_at (i);
-
- offSize_ = calcOffSize(dataSize);
- return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_population (), dataSize);
- }
};
struct cff1_top_dict_interp_env_t : num_interp_env_t
@@ -738,7 +698,7 @@ struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
unsigned int EncodingOffset;
unsigned int CharsetOffset;
unsigned int FDSelectOffset;
- table_info_t privateDictInfo;
+ table_info_t privateDictInfo;
};
struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
@@ -880,21 +840,10 @@ struct cff1_private_dict_values_base_t : dict_values_t<VAL>
{
dict_values_t<VAL>::init ();
subrsOffset = 0;
- localSubrs = &Null(CFF1Subrs);
+ localSubrs = &Null (CFF1Subrs);
}
void fini () { dict_values_t<VAL>::fini (); }
- unsigned int calculate_serialized_size () const
- {
- unsigned int size = 0;
- for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
- if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
- size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
- else
- size += dict_values_t<VAL>::get_value (i).str.length;
- return size;
- }
-
unsigned int subrsOffset;
const CFF1Subrs *localSubrs;
};
@@ -997,6 +946,37 @@ typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1
typedef CFF1Index CFF1NameIndex;
typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
+struct cff1_font_dict_values_mod_t
+{
+ cff1_font_dict_values_mod_t() { init (); }
+
+ void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
+
+ void init (const cff1_font_dict_values_t *base_,
+ unsigned int fontName_)
+ {
+ base = base_;
+ fontName = fontName_;
+ privateDictInfo.init ();
+ }
+
+ unsigned get_count () const { return base->get_count (); }
+
+ const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
+
+ const cff1_font_dict_values_t *base;
+ table_info_t privateDictInfo;
+ unsigned int fontName;
+};
+
+struct CFF1FDArray : FDArray<HBUINT16>
+{
+ /* FDArray::serialize() requires this partial specialization to compile */
+ template <typename ITER, typename OP_SERIALIZER>
+ bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
+ { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
+};
+
} /* namespace CFF */
namespace OT {
@@ -1031,7 +1011,7 @@ struct cff1
const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
- if (cff == &Null(OT::cff1))
+ if (cff == &Null (OT::cff1))
{ fini (); return; }
nameIndex = &cff->nameIndex (cff);
@@ -1052,7 +1032,7 @@ struct cff1
}
if (is_predef_charset ())
- charset = &Null(Charset);
+ charset = &Null (Charset);
else
{
charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
@@ -1064,16 +1044,30 @@ struct cff1
{
fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
- if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
- (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
+ if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
+ (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
{ fini (); return; }
fdCount = fdArray->count;
}
else
{
- fdArray = &Null(CFF1FDArray);
- fdSelect = &Null(CFF1FDSelect);
+ fdArray = &Null (CFF1FDArray);
+ fdSelect = &Null (CFF1FDSelect);
+ }
+
+ encoding = &Null (Encoding);
+ if (is_CID ())
+ {
+ if (unlikely (charset == &Null (Charset))) { fini (); return; }
+ }
+ else
+ {
+ if (!is_predef_encoding ())
+ {
+ encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
+ if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
+ }
}
stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
@@ -1086,7 +1080,7 @@ struct cff1
charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
- if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
+ if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
{ fini (); return; }
num_glyphs = charStrings->count;
@@ -1104,14 +1098,14 @@ struct cff1
{
byte_str_t fontDictStr = (*fdArray)[i];
if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
- cff1_font_dict_values_t *font;
+ cff1_font_dict_values_t *font;
cff1_font_dict_interpreter_t font_interp;
font_interp.env.init (fontDictStr);
font = fontDicts.push ();
- if (unlikely (font == &Crap(cff1_font_dict_values_t))) { fini (); return; }
+ if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; }
font->init ();
if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
- PRIVDICTVAL *priv = &privateDicts[i];
+ PRIVDICTVAL *priv = &privateDicts[i];
const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
@@ -1120,15 +1114,15 @@ struct cff1
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
- if (priv->localSubrs != &Null(CFF1Subrs) &&
+ if (priv->localSubrs != &Null (CFF1Subrs) &&
unlikely (!priv->localSubrs->sanitize (&sc)))
{ fini (); return; }
}
}
else /* non-CID */
{
- cff1_top_dict_values_t *font = &topDict;
- PRIVDICTVAL *priv = &privateDicts[0];
+ cff1_top_dict_values_t *font = &topDict;
+ PRIVDICTVAL *priv = &privateDicts[0];
const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
@@ -1138,7 +1132,7 @@ struct cff1
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
- if (priv->localSubrs != &Null(CFF1Subrs) &&
+ if (priv->localSubrs != &Null (CFF1Subrs) &&
unlikely (!priv->localSubrs->sanitize (&sc)))
{ fini (); return; }
}
@@ -1154,7 +1148,7 @@ struct cff1
blob = nullptr;
}
- bool is_valid () const { return blob != nullptr; }
+ bool is_valid () const { return blob; }
bool is_CID () const { return topDict.is_CID (); }
bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
@@ -1165,69 +1159,18 @@ struct cff1
if (unlikely (sid == CFF_UNDEF_SID))
return 0;
- if (charset != &Null(Charset))
+ if (charset != &Null (Charset))
return charset->get_glyph (sid, num_glyphs);
else if ((topDict.CharsetOffset == ISOAdobeCharset)
&& (code <= 228 /*zcaron*/)) return sid;
return 0;
}
- protected:
- hb_blob_t *blob;
- hb_sanitize_context_t sc;
-
- public:
- const Charset *charset;
- const CFF1NameIndex *nameIndex;
- const CFF1TopDictIndex *topDictIndex;
- const CFF1StringIndex *stringIndex;
- const CFF1Subrs *globalSubrs;
- const CFF1CharStrings *charStrings;
- const CFF1FDArray *fdArray;
- const CFF1FDSelect *fdSelect;
- unsigned int fdCount;
-
- cff1_top_dict_values_t topDict;
- hb_vector_t<cff1_font_dict_values_t> fontDicts;
- hb_vector_t<PRIVDICTVAL> privateDicts;
-
- unsigned int num_glyphs;
- };
-
- struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
- {
- 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;
- };
-
- struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t>
- {
- void init (hb_face_t *face)
- {
- SUPER::init (face);
- if (blob == nullptr) return;
-
- const OT::cff1 *cff = this->blob->as<OT::cff1> ();
- encoding = &Null(Encoding);
- if (is_CID ())
- {
- if (unlikely (charset == &Null(Charset))) { fini (); return; }
- }
- else
- {
- if (!is_predef_encoding ())
- {
- encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
- if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
- }
- }
- }
-
bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
{
- if (encoding != &Null(Encoding))
+ if (encoding != &Null (Encoding))
return encoding->get_code (glyph);
else
{
@@ -1251,20 +1194,20 @@ struct cff1
hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
{
- if (charset != &Null(Charset))
- return charset->get_sid (glyph);
+ if (charset != &Null (Charset))
+ return charset->get_sid (glyph, num_glyphs);
else
{
hb_codepoint_t sid = 0;
switch (topDict.CharsetOffset)
{
- case ISOAdobeCharset:
+ case ISOAdobeCharset:
if (glyph <= 228 /*zcaron*/) sid = glyph;
break;
- case ExpertCharset:
+ case ExpertCharset:
sid = lookup_expert_charset_for_sid (glyph);
break;
- case ExpertSubsetCharset:
+ case ExpertSubsetCharset:
sid = lookup_expert_subset_charset_for_sid (glyph);
break;
default:
@@ -1274,35 +1217,174 @@ struct cff1
}
}
- const Encoding *encoding;
+ hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
+ {
+ if (charset != &Null (Charset))
+ return charset->get_glyph (sid, num_glyphs);
+ else
+ {
+ hb_codepoint_t glyph = 0;
+ switch (topDict.CharsetOffset)
+ {
+ case ISOAdobeCharset:
+ if (sid <= 228 /*zcaron*/) glyph = sid;
+ break;
+ case ExpertCharset:
+ glyph = lookup_expert_charset_for_glyph (sid);
+ break;
+ case ExpertSubsetCharset:
+ glyph = lookup_expert_subset_charset_for_glyph (sid);
+ break;
+ default:
+ break;
+ }
+ return glyph;
+ }
+ }
- private:
- typedef accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> SUPER;
+ protected:
+ hb_blob_t *blob;
+ hb_sanitize_context_t sc;
+
+ public:
+ const Encoding *encoding;
+ const Charset *charset;
+ const CFF1NameIndex *nameIndex;
+ const CFF1TopDictIndex *topDictIndex;
+ const CFF1StringIndex *stringIndex;
+ const CFF1Subrs *globalSubrs;
+ const CFF1CharStrings *charStrings;
+ const CFF1FDArray *fdArray;
+ const CFF1FDSelect *fdSelect;
+ unsigned int fdCount;
+
+ cff1_top_dict_values_t topDict;
+ hb_vector_t<cff1_font_dict_values_t>
+ fontDicts;
+ hb_vector_t<PRIVDICTVAL> privateDicts;
+
+ unsigned int num_glyphs;
};
- bool subset (hb_subset_plan_t *plan) const
+ struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
{
- hb_blob_t *cff_prime = nullptr;
-
- bool success = true;
- if (hb_subset_cff1 (plan, &cff_prime)) {
- success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime);
- hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
- success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
- hb_blob_destroy (head_blob);
- } else {
- success = false;
+ void init (hb_face_t *face)
+ {
+ SUPER::init (face);
+
+ if (!is_valid ()) return;
+ if (is_CID ()) return;
+
+ /* fill glyph_names */
+ for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
+ {
+ hb_codepoint_t sid = glyph_to_sid (gid);
+ gname_t gname;
+ gname.sid = sid;
+ if (sid < cff1_std_strings_length)
+ gname.name = cff1_std_strings (sid);
+ else
+ {
+ byte_str_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
+ gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length);
+ }
+ if (unlikely (!gname.name.arrayZ)) { fini (); return; }
+ glyph_names.push (gname);
+ }
+ glyph_names.qsort ();
}
- hb_blob_destroy (cff_prime);
- return success;
- }
+ void fini ()
+ {
+ glyph_names.fini ();
+
+ SUPER::fini ();
+ }
+
+ bool get_glyph_name (hb_codepoint_t glyph,
+ char *buf, unsigned int buf_len) const
+ {
+ if (!buf) return true;
+ if (unlikely (!is_valid ())) return false;
+ if (is_CID()) return false;
+ hb_codepoint_t sid = glyph_to_sid (glyph);
+ const char *str;
+ size_t str_len;
+ if (sid < cff1_std_strings_length)
+ {
+ hb_bytes_t byte_str = cff1_std_strings (sid);
+ str = byte_str.arrayZ;
+ str_len = byte_str.length;
+ }
+ else
+ {
+ byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
+ str = (const char *)ubyte_str.arrayZ;
+ str_len = ubyte_str.length;
+ }
+ if (!str_len) return false;
+ unsigned int len = hb_min (buf_len - 1, str_len);
+ strncpy (buf, (const char*)str, len);
+ buf[len] = '\0';
+ return true;
+ }
+
+ bool get_glyph_from_name (const char *name, int len,
+ hb_codepoint_t *glyph) const
+ {
+ if (len < 0) len = strlen (name);
+ if (unlikely (!len)) return false;
+
+ gname_t key = { hb_bytes_t (name, len), 0 };
+ const gname_t *gname = glyph_names.bsearch (key);
+ if (!gname) return false;
+ hb_codepoint_t gid = sid_to_glyph (gname->sid);
+ if (!gid && gname->sid) return false;
+ *glyph = gid;
+ return true;
+ }
+
+ 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;
+#ifdef HB_EXPERIMENTAL_API
+ HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
+#endif
+
+ private:
+ struct gname_t
+ {
+ hb_bytes_t name;
+ uint16_t sid;
+
+ static int cmp (const void *a_, const void *b_)
+ {
+ const gname_t *a = (const gname_t *)a_;
+ const gname_t *b = (const gname_t *)b_;
+ int minlen = hb_min (a->name.length, b->name.length);
+ int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
+ if (ret) return ret;
+ return a->name.length - b->name.length;
+ }
+
+ int cmp (const gname_t &a) const { return cmp (&a, this); }
+ };
+
+ hb_sorted_vector_t<gname_t> glyph_names;
+
+ typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
+ };
+
+ struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {};
+
+ bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); }
protected:
HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
+ HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
+ HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
public:
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 a2242b76fb9..ac0feeee21b 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
@@ -30,6 +30,7 @@
#include "hb-ot-cff2-table.hh"
#include "hb-cff2-interp-cs.hh"
+#include "hb-draw.hh"
using namespace CFF;
@@ -142,5 +143,73 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
return true;
}
+#ifdef HB_EXPERIMENTAL_API
+struct cff2_path_param_t
+{
+ cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_)
+ {
+ draw_helper = &draw_helper_;
+ font = font_;
+ }
+
+ void move_to (const point_t &p)
+ { draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
+
+ void line_to (const point_t &p)
+ { draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
+
+ void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
+ {
+ draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()),
+ font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()),
+ font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ()));
+ }
+
+ protected:
+ draw_helper_t *draw_helper;
+ hb_font_t *font;
+};
+
+struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t, cff2_path_param_t>
+{
+ static void moveto (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt)
+ {
+ param.move_to (pt);
+ env.moveto (pt);
+ }
+
+ static void line (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1)
+ {
+ param.line_to (pt1);
+ env.moveto (pt1);
+ }
+
+ static void curve (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+ {
+ param.cubic_to (pt1, pt2, pt3);
+ env.moveto (pt3);
+ }
+};
+
+struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
+
+bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
+{
+#ifdef HB_NO_OT_FONT_CFF
+ /* XXX Remove check when this code moves to .hh file. */
+ return true;
+#endif
+
+ if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
+
+ unsigned int fd = fdSelect->get_fd (glyph);
+ cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
+ const byte_str_t str = (*charStrings)[glyph];
+ interp.env.init (str, *this, fd, font->coords, font->num_coords);
+ cff2_path_param_t param (font, draw_helper);
+ if (unlikely (!interp.interpret (param))) return false;
+ return true;
+}
+#endif
#endif
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
index 8646cde58d6..075a0d4ef72 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
@@ -27,9 +27,9 @@
#ifndef HB_OT_CFF2_TABLE_HH
#define HB_OT_CFF2_TABLE_HH
-#include "hb-ot-head-table.hh"
#include "hb-ot-cff-common.hh"
#include "hb-subset-cff2.hh"
+#include "hb-draw.hh"
namespace CFF {
@@ -43,7 +43,6 @@ typedef CFFIndex<HBUINT32> CFF2Index;
template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {};
typedef CFF2Index CFF2CharStrings;
-typedef FDArray<HBUINT32> CFF2FDArray;
typedef Subrs<HBUINT32> CFF2Subrs;
typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
@@ -56,14 +55,11 @@ struct CFF2FDSelect
TRACE_SERIALIZE (this);
unsigned int size = src.get_size (num_glyphs);
CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
- if (unlikely (dest == nullptr)) return_trace (false);
+ if (unlikely (!dest)) return_trace (false);
memcpy (dest, &src, size);
return_trace (true);
}
- unsigned int calculate_serialized_size (unsigned int num_glyphs) const
- { return get_size (num_glyphs); }
-
unsigned int get_size (unsigned int num_glyphs) const
{
switch (format)
@@ -127,7 +123,7 @@ struct CFF2VariationStore
TRACE_SERIALIZE (this);
unsigned int size_ = varStore->get_size ();
CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
- if (unlikely (dest == nullptr)) return_trace (false);
+ if (unlikely (!dest)) return_trace (false);
memcpy (dest, varStore, size_);
return_trace (true);
}
@@ -150,26 +146,6 @@ struct cff2_top_dict_values_t : top_dict_values_t<>
}
void fini () { top_dict_values_t<>::fini (); }
- unsigned int calculate_serialized_size () const
- {
- unsigned int size = 0;
- for (unsigned int i = 0; i < get_count (); i++)
- {
- op_code_t op = get_value (i).op;
- switch (op)
- {
- case OpCode_vstore:
- case OpCode_FDSelect:
- size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
- break;
- default:
- size += top_dict_values_t<>::calculate_serialized_op_size (get_value (i));
- break;
- }
- }
- return size;
- }
-
unsigned int vstoreOffset;
unsigned int FDSelectOffset;
};
@@ -256,22 +232,11 @@ struct cff2_private_dict_values_base_t : dict_values_t<VAL>
{
dict_values_t<VAL>::init ();
subrsOffset = 0;
- localSubrs = &Null(CFF2Subrs);
+ localSubrs = &Null (CFF2Subrs);
ivs = 0;
}
void fini () { dict_values_t<VAL>::fini (); }
- unsigned int calculate_serialized_size () const
- {
- unsigned int size = 0;
- for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
- if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
- size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
- else
- size += dict_values_t<VAL>::get_value (i).str.length;
- return size;
- }
-
unsigned int subrsOffset;
const CFF2Subrs *localSubrs;
unsigned int ivs;
@@ -404,6 +369,14 @@ struct cff2_private_dict_opset_subset_t : dict_opset_t
typedef dict_interpreter_t<cff2_top_dict_opset_t, cff2_top_dict_values_t> cff2_top_dict_interpreter_t;
typedef dict_interpreter_t<cff2_font_dict_opset_t, cff2_font_dict_values_t> cff2_font_dict_interpreter_t;
+struct CFF2FDArray : FDArray<HBUINT32>
+{
+ /* FDArray::serialize does not compile without this partial specialization */
+ template <typename ITER, typename OP_SERIALIZER>
+ bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
+ { return FDArray<HBUINT32>::serialize<cff2_font_dict_values_t, table_info_t> (c, it, opszr); }
+};
+
} /* namespace CFF */
namespace OT {
@@ -438,7 +411,7 @@ struct cff2
const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
- if (cff2 == &Null(OT::cff2))
+ if (cff2 == &Null (OT::cff2))
{ fini (); return; }
{ /* parse top dict */
@@ -456,11 +429,11 @@ struct cff2
fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset);
fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset);
- if (((varStore != &Null(CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
- (charStrings == &Null(CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
- (globalSubrs == &Null(CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
- (fdArray == &Null(CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
- (((fdSelect != &Null(CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
+ if (((varStore != &Null (CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
+ (charStrings == &Null (CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
+ (globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
+ (fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
+ (((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
{ fini (); return; }
num_glyphs = charStrings->count;
@@ -479,7 +452,7 @@ struct cff2
cff2_font_dict_interpreter_t font_interp;
font_interp.env.init (fontDictStr);
font = fontDicts.push ();
- if (unlikely (font == &Crap(cff2_font_dict_values_t))) { fini (); return; }
+ if (unlikely (font == &Crap (cff2_font_dict_values_t))) { fini (); return; }
font->init ();
if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
@@ -491,7 +464,7 @@ struct cff2
if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; }
privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset);
- if (privateDicts[i].localSubrs != &Null(CFF2Subrs) &&
+ if (privateDicts[i].localSubrs != &Null (CFF2Subrs) &&
unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
{ fini (); return; }
}
@@ -507,7 +480,7 @@ struct cff2
blob = nullptr;
}
- bool is_valid () const { return blob != nullptr; }
+ bool is_valid () const { return blob; }
protected:
hb_blob_t *blob;
@@ -533,27 +506,14 @@ struct cff2
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
+#ifdef HB_EXPERIMENTAL_API
+ HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
+#endif
};
typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
- bool subset (hb_subset_plan_t *plan) const
- {
- hb_blob_t *cff2_prime = nullptr;
-
- bool success = true;
- if (hb_subset_cff2 (plan, &cff2_prime)) {
- success = success && plan->add_table (HB_OT_TAG_cff2, cff2_prime);
- hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
- success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
- hb_blob_destroy (head_blob);
- } else {
- success = false;
- }
- hb_blob_destroy (cff2_prime);
-
- return success;
- }
+ bool subset (hb_subset_context_t *c) const { return hb_subset_cff2 (c); }
public:
FixedVersion<HBUINT8> version; /* Version of CFF2 table. set to 0x0200u */
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 9ebd8e417f9..861a5eaedbb 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
@@ -83,18 +83,16 @@ struct CmapSubtableFormat4
HBUINT16 *endCode = c->start_embed<HBUINT16> ();
hb_codepoint_t prev_endcp = 0xFFFF;
- + it
- | hb_apply ([&] (const hb_item_type<Iterator> _)
- {
- if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
- {
- HBUINT16 end_code;
- end_code = prev_endcp;
- c->copy<HBUINT16> (end_code);
- }
- prev_endcp = _.first;
- })
- ;
+ for (const hb_item_type<Iterator> _ : +it)
+ {
+ if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
+ {
+ HBUINT16 end_code;
+ end_code = prev_endcp;
+ c->copy<HBUINT16> (end_code);
+ }
+ prev_endcp = _.first;
+ }
{
// last endCode
@@ -121,19 +119,17 @@ struct CmapSubtableFormat4
HBUINT16 *startCode = c->start_embed<HBUINT16> ();
hb_codepoint_t prev_cp = 0xFFFF;
- + it
- | hb_apply ([&] (const hb_item_type<Iterator> _)
- {
- if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
- {
- HBUINT16 start_code;
- start_code = _.first;
- c->copy<HBUINT16> (start_code);
- }
-
- prev_cp = _.first;
- })
- ;
+ for (const hb_item_type<Iterator> _ : +it)
+ {
+ if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
+ {
+ HBUINT16 start_code;
+ start_code = _.first;
+ c->copy<HBUINT16> (start_code);
+ }
+
+ prev_cp = _.first;
+ }
// There must be a final entry with end_code == 0xFFFF.
if (it.len () == 0 || prev_cp != 0xFFFF)
@@ -162,30 +158,28 @@ struct CmapSubtableFormat4
if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size)
return nullptr;
- + it
- | hb_apply ([&] (const hb_item_type<Iterator> _)
- {
- if (_.first == startCode[i])
- {
- use_delta = true;
- start_gid = _.second;
- }
- else if (_.second != last_gid + 1) use_delta = false;
-
- if (_.first == endCode[i])
- {
- HBINT16 delta;
- if (use_delta) delta = (int)start_gid - (int)startCode[i];
- else delta = 0;
- c->copy<HBINT16> (delta);
-
- i++;
- }
-
- last_gid = _.second;
- last_cp = _.first;
- })
- ;
+ for (const hb_item_type<Iterator> _ : +it)
+ {
+ if (_.first == startCode[i])
+ {
+ use_delta = true;
+ start_gid = _.second;
+ }
+ else if (_.second != last_gid + 1) use_delta = false;
+
+ if (_.first == endCode[i])
+ {
+ HBINT16 delta;
+ if (use_delta) delta = (int)start_gid - (int)startCode[i];
+ else delta = 0;
+ c->copy<HBINT16> (delta);
+
+ i++;
+ }
+
+ last_gid = _.second;
+ last_cp = _.first;
+ }
if (it.len () == 0 || last_cp != 0xFFFF)
{
@@ -238,12 +232,21 @@ struct CmapSubtableFormat4
void serialize (hb_serialize_context_t *c,
Iterator it)
{
+ auto format4_iter =
+ + it
+ | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
+ { return _.first <= 0xFFFF; })
+ ;
+
+ //comment off temporarily while we're working on supporting --gids option
+ //if (format4_iter.len () == 0) return;
+
unsigned table_initpos = c->length ();
if (unlikely (!c->extend_min (*this))) return;
this->format = 4;
//serialize endCode[]
- HBUINT16 *endCode = serialize_endcode_array (c, it);
+ HBUINT16 *endCode = serialize_endcode_array (c, format4_iter);
if (unlikely (!endCode)) return;
unsigned segcount = (c->length () - min_size) / HBUINT16::static_size;
@@ -252,14 +255,14 @@ struct CmapSubtableFormat4
if (unlikely (!c->allocate_size<HBUINT16> (HBUINT16::static_size))) return; // 2 bytes of padding.
// serialize startCode[]
- HBUINT16 *startCode = serialize_startcode_array (c, it);
+ HBUINT16 *startCode = serialize_startcode_array (c, format4_iter);
if (unlikely (!startCode)) return;
//serialize idDelta[]
- HBINT16 *idDelta = serialize_idDelta_array (c, it, endCode, startCode, segcount);
+ HBINT16 *idDelta = serialize_idDelta_array (c, format4_iter, endCode, startCode, segcount);
if (unlikely (!idDelta)) return;
- HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, it, endCode, startCode, idDelta, segcount);
+ HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
if (unlikely (!c->check_success (idRangeOffset))) return;
if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return;
@@ -291,27 +294,28 @@ struct CmapSubtableFormat4
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
- /* Custom two-array bsearch. */
- int min = 0, max = (int) this->segCount - 1;
- const HBUINT16 *startCount = this->startCount;
- const HBUINT16 *endCount = this->endCount;
- unsigned int i;
- while (min <= max)
+ struct CustomRange
{
- int mid = ((unsigned int) min + (unsigned int) max) / 2;
- if (codepoint < startCount[mid])
- max = mid - 1;
- else if (codepoint > endCount[mid])
- min = mid + 1;
- else
+ int cmp (hb_codepoint_t k,
+ unsigned distance) const
{
- i = mid;
- goto found;
+ if (k > last) return +1;
+ if (k < (&last)[distance]) return -1;
+ return 0;
}
- }
- return false;
+ HBUINT16 last;
+ };
+
+ const HBUINT16 *found =hb_bsearch (codepoint,
+ this->endCount,
+ this->segCount,
+ 2,
+ _hb_cmp_method<hb_codepoint_t, CustomRange, unsigned>,
+ this->segCount + 1);
+ if (!found)
+ return false;
+ unsigned int i = found - endCount;
- found:
hb_codepoint_t gid;
unsigned int rangeOffset = this->idRangeOffset[i];
if (rangeOffset == 0)
@@ -333,8 +337,10 @@ struct CmapSubtableFormat4
*glyph = gid;
return true;
}
+
HB_INTERNAL static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
{ return ((const accelerator_t *) obj)->get_glyph (codepoint, glyph); }
+
void collect_unicodes (hb_set_t *out) const
{
unsigned int count = this->segCount;
@@ -528,20 +534,26 @@ struct CmapSubtableLongSegmented
return true;
}
- void collect_unicodes (hb_set_t *out) const
+ void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
{
for (unsigned int i = 0; i < this->groups.len; i++)
{
hb_codepoint_t start = this->groups[i].startCharCode;
hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
(hb_codepoint_t) HB_UNICODE_MAX);
- for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
+ hb_codepoint_t gid = this->groups[i].glyphID;
+ if (!gid)
{
- hb_codepoint_t gid = T::group_get_glyph (this->groups[i], codepoint);
- if (unlikely (!gid))
- continue;
- out->add (codepoint);
+ /* Intention is: if (hb_is_same (T, CmapSubtableFormat13)) continue; */
+ if (! T::group_get_glyph (this->groups[i], end)) continue;
+ start++;
+ gid++;
}
+ if (unlikely ((unsigned int) gid >= num_glyphs)) continue;
+ if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
+ end = start + (hb_codepoint_t) num_glyphs - gid;
+
+ out->add_range (start, end);
}
}
@@ -582,33 +594,29 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
hb_codepoint_t glyphID = 0;
- + it
- | hb_apply ([&] (const hb_item_type<Iterator> _)
- {
- if (startCharCode == 0xFFFF)
- {
- startCharCode = _.first;
- endCharCode = _.first;
- glyphID = _.second;
- }
- else if (!_is_gid_consecutive (endCharCode, startCharCode, glyphID, _.first, _.second))
- {
- CmapSubtableLongGroup grouprecord;
- grouprecord.startCharCode = startCharCode;
- grouprecord.endCharCode = endCharCode;
- grouprecord.glyphID = glyphID;
- c->copy<CmapSubtableLongGroup> (grouprecord);
-
- startCharCode = _.first;
- endCharCode = _.first;
- glyphID = _.second;
- }
- else
- {
- endCharCode = _.first;
- }
- })
- ;
+ for (const hb_item_type<Iterator> _ : +it)
+ {
+ if (startCharCode == 0xFFFF)
+ {
+ startCharCode = _.first;
+ endCharCode = _.first;
+ glyphID = _.second;
+ }
+ else if (!_is_gid_consecutive (endCharCode, startCharCode, glyphID, _.first, _.second))
+ {
+ CmapSubtableLongGroup grouprecord;
+ grouprecord.startCharCode = startCharCode;
+ grouprecord.endCharCode = endCharCode;
+ grouprecord.glyphID = glyphID;
+ c->copy<CmapSubtableLongGroup> (grouprecord);
+
+ startCharCode = _.first;
+ endCharCode = _.first;
+ glyphID = _.second;
+ }
+ else
+ endCharCode = _.first;
+ }
CmapSubtableLongGroup record;
record.startCharCode = startCharCode;
@@ -772,7 +780,7 @@ struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32>
{
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
- out->add (arrayZ[i].glyphID);
+ out->add (arrayZ[i].unicodeValue);
}
void closure_glyphs (const hb_set_t *unicodes,
@@ -839,6 +847,20 @@ struct VariationSelectorRecord
return GLYPH_VARIANT_NOT_FOUND;
}
+ VariationSelectorRecord(const VariationSelectorRecord& other)
+ {
+ *this = other;
+ }
+
+ void operator= (const VariationSelectorRecord& other)
+ {
+ varSelector = other.varSelector;
+ HBUINT32 offset = other.defaultUVS;
+ defaultUVS = offset;
+ offset = other.nonDefaultUVS;
+ nonDefaultUVS = offset;
+ }
+
void collect_unicodes (hb_set_t *out, const void *base) const
{
(base+defaultUVS).collect_unicodes (out);
@@ -856,50 +878,43 @@ struct VariationSelectorRecord
nonDefaultUVS.sanitize (c, base));
}
- VariationSelectorRecord* copy (hb_serialize_context_t *c,
- const hb_set_t *unicodes,
- const hb_set_t *glyphs,
- const hb_map_t *glyph_map,
- const void *src_base,
- const void *dst_base) const
+ hb_pair_t<unsigned, unsigned>
+ copy (hb_serialize_context_t *c,
+ const hb_set_t *unicodes,
+ const hb_set_t *glyphs,
+ const hb_map_t *glyph_map,
+ const void *base) const
{
auto snap = c->snapshot ();
auto *out = c->embed<VariationSelectorRecord> (*this);
- if (unlikely (!out)) return nullptr;
+ if (unlikely (!out)) return hb_pair (0, 0);
out->defaultUVS = 0;
out->nonDefaultUVS = 0;
- bool drop = true;
-
- if (defaultUVS != 0)
+ unsigned non_default_uvs_objidx = 0;
+ if (nonDefaultUVS != 0)
{
c->push ();
- if (c->copy (src_base+defaultUVS, unicodes))
- {
- c->add_link (out->defaultUVS, c->pop_pack (), dst_base);
- drop = false;
- }
+ if (c->copy (base+nonDefaultUVS, unicodes, glyphs, glyph_map))
+ non_default_uvs_objidx = c->pop_pack ();
else c->pop_discard ();
}
- if (nonDefaultUVS != 0)
+ unsigned default_uvs_objidx = 0;
+ if (defaultUVS != 0)
{
c->push ();
- if (c->copy (src_base+nonDefaultUVS, unicodes, glyphs, glyph_map))
- {
- c->add_link (out->nonDefaultUVS, c->pop_pack (), dst_base);
- drop = false;
- }
+ if (c->copy (base+defaultUVS, unicodes))
+ default_uvs_objidx = c->pop_pack ();
else c->pop_discard ();
}
- if (drop)
- {
+
+ if (!default_uvs_objidx && !non_default_uvs_objidx)
c->revert (snap);
- return nullptr;
- }
- else return out;
+
+ return hb_pair (default_uvs_objidx, non_default_uvs_objidx);
}
HBUINT24 varSelector; /* Variation selector. */
@@ -932,7 +947,7 @@ struct CmapSubtableFormat14
const hb_set_t *unicodes,
const hb_set_t *glyphs,
const hb_map_t *glyph_map,
- const void *src_base)
+ const void *base)
{
auto snap = c->snapshot ();
unsigned table_initpos = c->length ();
@@ -941,17 +956,67 @@ struct CmapSubtableFormat14
if (unlikely (!c->extend_min (*this))) return;
this->format = 14;
- const CmapSubtableFormat14 *src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (src_base);
- for (const VariationSelectorRecord& _ : src_tbl->record)
- c->copy (_, unicodes, glyphs, glyph_map, src_base, this);
+ auto src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (base);
+
+ /*
+ * Some versions of OTS require that offsets are in order. Due to the use
+ * of push()/pop_pack() serializing the variation records in order results
+ * in the offsets being in reverse order (first record has the largest
+ * offset). While this is perfectly valid, it will cause some versions of
+ * OTS to consider this table bad.
+ *
+ * So to prevent this issue we serialize the variation records in reverse
+ * order, so that the offsets are ordered from small to large. Since
+ * variation records are supposed to be in increasing order of varSelector
+ * we then have to reverse the order of the written variation selector
+ * records after everything is finalized.
+ */
+ hb_vector_t<hb_pair_t<unsigned, unsigned>> obj_indices;
+ for (int i = src_tbl->record.len - 1; i >= 0; i--)
+ {
+ hb_pair_t<unsigned, unsigned> result = src_tbl->record[i].copy (c, unicodes, glyphs, glyph_map, base);
+ if (result.first || result.second)
+ obj_indices.push (result);
+ }
if (c->length () - table_initpos == CmapSubtableFormat14::min_size)
+ {
c->revert (snap);
- else
+ return;
+ }
+
+ int tail_len = init_tail - c->tail;
+ c->check_assign (this->length, c->length () - table_initpos + tail_len);
+ c->check_assign (this->record.len,
+ (c->length () - table_initpos - CmapSubtableFormat14::min_size) /
+ VariationSelectorRecord::static_size);
+
+ /* Correct the incorrect write order by reversing the order of the variation
+ records array. */
+ _reverse_variation_records ();
+
+ /* Now that records are in the right order, we can set up the offsets. */
+ _add_links_to_variation_records (c, obj_indices);
+ }
+
+ void _reverse_variation_records ()
+ {
+ record.as_array ().reverse ();
+ }
+
+ void _add_links_to_variation_records (hb_serialize_context_t *c,
+ const hb_vector_t<hb_pair_t<unsigned, unsigned>>& obj_indices)
+ {
+ for (unsigned i = 0; i < obj_indices.length; i++)
{
- int tail_len = init_tail - c->tail;
- c->check_assign (this->length, c->length () - table_initpos + tail_len);
- c->check_assign (this->record.len, (c->length () - table_initpos - CmapSubtableFormat14::min_size) / VariationSelectorRecord::static_size);
+ /*
+ * Since the record array has been reversed (see comments in copy())
+ * but obj_indices has not been, the indices at obj_indices[i]
+ * are for the variation record at record[j].
+ */
+ int j = obj_indices.length - 1 - i;
+ c->add_link (record[j].defaultUVS, obj_indices[i].first);
+ c->add_link (record[j].nonDefaultUVS, obj_indices[i].second);
}
}
@@ -966,6 +1031,12 @@ struct CmapSubtableFormat14
;
}
+ void collect_unicodes (hb_set_t *out) const
+ {
+ for (const VariationSelectorRecord& _ : record)
+ _.collect_unicodes (out, this);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -1001,15 +1072,15 @@ struct CmapSubtable
default: return false;
}
}
- void collect_unicodes (hb_set_t *out) const
+ void collect_unicodes (hb_set_t *out, unsigned int num_glyphs = UINT_MAX) const
{
switch (u.format) {
case 0: u.format0 .collect_unicodes (out); return;
case 4: u.format4 .collect_unicodes (out); return;
case 6: u.format6 .collect_unicodes (out); return;
case 10: u.format10.collect_unicodes (out); return;
- case 12: u.format12.collect_unicodes (out); return;
- case 13: u.format13.collect_unicodes (out); return;
+ case 12: u.format12.collect_unicodes (out, num_glyphs); return;
+ case 13: u.format13.collect_unicodes (out, num_glyphs); return;
case 14:
default: return;
}
@@ -1021,12 +1092,12 @@ struct CmapSubtable
Iterator it,
unsigned format,
const hb_subset_plan_t *plan,
- const void *src_base)
+ const void *base)
{
switch (format) {
- case 4: u.format4.serialize (c, it); return;
- case 12: u.format12.serialize (c, it); return;
- case 14: u.format14.serialize (c, plan->unicodes, plan->_glyphset, plan->glyph_map, src_base); return;
+ case 4: return u.format4.serialize (c, it);
+ case 12: return u.format12.serialize (c, it);
+ case 14: return u.format14.serialize (c, plan->unicodes, plan->_glyphset, plan->glyph_map, base);
default: return;
}
}
@@ -1087,8 +1158,7 @@ struct EncodingRecord
EncodingRecord* copy (hb_serialize_context_t *c,
Iterator it,
unsigned format,
- const void *src_base,
- const void *dst_base,
+ const void *base,
const hb_subset_plan_t *plan,
/* INOUT */ unsigned *objidx) const
{
@@ -1102,7 +1172,7 @@ struct EncodingRecord
{
CmapSubtable *cmapsubtable = c->push<CmapSubtable> ();
unsigned origin_length = c->length ();
- cmapsubtable->serialize (c, it, format, plan, &(src_base+subtable));
+ cmapsubtable->serialize (c, it, format, plan, &(base+subtable));
if (c->length () - origin_length > 0) *objidx = c->pop_pack ();
else c->pop_discard ();
}
@@ -1113,7 +1183,7 @@ struct EncodingRecord
return_trace (nullptr);
}
- c->add_link (out->subtable, *objidx, dst_base);
+ c->add_link (out->subtable, *objidx);
return_trace (out);
}
@@ -1134,7 +1204,7 @@ struct cmap
void serialize (hb_serialize_context_t *c,
Iterator it,
EncodingRecIter encodingrec_iter,
- const void *src_base,
+ const void *base,
const hb_subset_plan_t *plan)
{
if (unlikely (!c->extend_min ((*this)))) return;
@@ -1144,11 +1214,14 @@ struct cmap
for (const EncodingRecord& _ : encodingrec_iter)
{
- unsigned format = (src_base+_.subtable).u.format;
+ hb_set_t unicodes_set;
+ (base+_.subtable).collect_unicodes (&unicodes_set);
- if (format == 4) c->copy (_, it, 4u, src_base, this, plan, &format4objidx);
- else if (format == 12) c->copy (_, it, 12u, src_base, this, plan, &format12objidx);
- else if (format == 14) c->copy (_, it, 14u, src_base, this, plan, &format14objidx);
+ unsigned format = (base+_.subtable).u.format;
+
+ if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
+ else if (format == 12) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
+ else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
}
c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size);
@@ -1187,7 +1260,6 @@ struct cmap
})
;
-
if (unlikely (!encodingrec_iter.len ())) return_trace (false);
const EncodingRecord *unicode_bmp= nullptr, *unicode_ucs4 = nullptr, *ms_bmp = nullptr, *ms_ucs4 = nullptr;
@@ -1205,7 +1277,7 @@ struct cmap
else if (_.platformID == 3 && _.encodingID == 10) ms_ucs4 = table;
}
- if (unlikely (!unicode_bmp && !ms_bmp)) return_trace (false);
+ if (unlikely (!has_format12 && !unicode_bmp && !ms_bmp)) return_trace (false);
if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
auto it =
@@ -1339,8 +1411,8 @@ struct cmap
return get_nominal_glyph (unicode, glyph);
}
- void collect_unicodes (hb_set_t *out) const
- { subtable->collect_unicodes (out); }
+ void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
+ { subtable->collect_unicodes (out, num_glyphs); }
void collect_variation_selectors (hb_set_t *out) const
{ subtable_uvs->collect_variation_selectors (out); }
void collect_variation_unicodes (hb_codepoint_t variation_selector,
@@ -1413,7 +1485,7 @@ struct cmap
}
const EncodingRecord *find_encodingrec (unsigned int platform_id,
- unsigned int encoding_id) const
+ unsigned int encoding_id) const
{
EncodingRecord key;
key.platformID = platform_id;
@@ -1445,9 +1517,9 @@ struct cmap
}
protected:
- HBUINT16 version; /* Table version number (0). */
+ HBUINT16 version; /* Table version number (0). */
SortedArrayOf<EncodingRecord>
- encodingRecord; /* Encoding tables. */
+ encodingRecord; /* Encoding tables. */
public:
DEFINE_SIZE_ARRAY (4, encodingRecord);
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh
index 3498d3b360d..2500fbe3f22 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
@@ -21,7 +21,7 @@
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
- * Google Author(s): Seigo Nonaka
+ * Google Author(s): Seigo Nonaka, Calder Kitagawa
*/
#ifndef HB_OT_COLOR_CBDT_TABLE_HH
@@ -43,6 +43,35 @@
namespace OT {
+struct cblc_bitmap_size_subset_context_t
+{
+ const char *cbdt;
+ unsigned int cbdt_length;
+ hb_vector_t<char> *cbdt_prime;
+ unsigned int size; /* INOUT
+ * Input: old size of IndexSubtable
+ * Output: new size of IndexSubtable
+ */
+ unsigned int num_tables; /* INOUT
+ * Input: old number of subtables.
+ * Output: new number of subtables.
+ */
+ hb_codepoint_t start_glyph; /* OUT */
+ hb_codepoint_t end_glyph; /* OUT */
+};
+
+static inline bool
+_copy_data_to_cbdt (hb_vector_t<char> *cbdt_prime,
+ const void *data,
+ unsigned length)
+{
+ unsigned int new_len = cbdt_prime->length + length;
+ if (unlikely (!cbdt_prime->alloc (new_len))) return false;
+ memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length);
+ cbdt_prime->length = new_len;
+ return true;
+}
+
struct SmallGlyphMetrics
{
bool sanitize (hb_sanitize_context_t *c) const
@@ -56,7 +85,7 @@ struct SmallGlyphMetrics
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);
+ extents->height = font->em_scale_y (-static_cast<int>(height));
}
HBUINT8 height;
@@ -65,7 +94,7 @@ struct SmallGlyphMetrics
HBINT8 bearingY;
HBUINT8 advance;
public:
- DEFINE_SIZE_STATIC(5);
+ DEFINE_SIZE_STATIC (5);
};
struct BigGlyphMetrics : SmallGlyphMetrics
@@ -74,7 +103,7 @@ struct BigGlyphMetrics : SmallGlyphMetrics
HBINT8 vertBearingY;
HBUINT8 vertAdvance;
public:
- DEFINE_SIZE_STATIC(8);
+ DEFINE_SIZE_STATIC (8);
};
struct SBitLineMetrics
@@ -98,7 +127,7 @@ struct SBitLineMetrics
HBINT8 padding1;
HBINT8 padding2;
public:
- DEFINE_SIZE_STATIC(12);
+ DEFINE_SIZE_STATIC (12);
};
@@ -118,7 +147,7 @@ struct IndexSubtableHeader
HBUINT16 imageFormat;
HBUINT32 imageDataOffset;
public:
- DEFINE_SIZE_STATIC(8);
+ DEFINE_SIZE_STATIC (8);
};
template <typename OffsetType>
@@ -143,11 +172,23 @@ struct IndexSubtableFormat1Or3
return true;
}
+ bool add_offset (hb_serialize_context_t *c,
+ unsigned int offset,
+ unsigned int *size /* OUT (accumulated) */)
+ {
+ TRACE_SERIALIZE (this);
+ Offset<OffsetType> embedded_offset;
+ embedded_offset = offset;
+ *size += sizeof (OffsetType);
+ auto *o = c->embed (embedded_offset);
+ return_trace ((bool) o);
+ }
+
IndexSubtableHeader header;
UnsizedArrayOf<Offset<OffsetType>>
- offsetArrayZ;
+ offsetArrayZ;
public:
- DEFINE_SIZE_ARRAY(8, offsetArrayZ);
+ DEFINE_SIZE_ARRAY (8, offsetArrayZ);
};
struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<HBUINT32> {};
@@ -159,35 +200,153 @@ struct IndexSubtable
{
TRACE_SANITIZE (this);
if (!u.header.sanitize (c)) return_trace (false);
- switch (u.header.indexFormat) {
+ switch (u.header.indexFormat)
+ {
case 1: return_trace (u.format1.sanitize (c, glyph_count));
case 3: return_trace (u.format3.sanitize (c, glyph_count));
default:return_trace (true);
}
}
+ bool
+ finish_subtable (hb_serialize_context_t *c,
+ unsigned int cbdt_prime_len,
+ unsigned int num_glyphs,
+ unsigned int *size /* OUT (accumulated) */)
+ {
+ TRACE_SERIALIZE (this);
+
+ unsigned int local_offset = cbdt_prime_len - u.header.imageDataOffset;
+ switch (u.header.indexFormat)
+ {
+ case 1: return_trace (u.format1.add_offset (c, local_offset, size));
+ case 3: {
+ if (!u.format3.add_offset (c, local_offset, size))
+ return_trace (false);
+ if (!(num_glyphs & 0x01)) // Pad to 32-bit alignment if needed.
+ return_trace (u.format3.add_offset (c, 0, size));
+ return_trace (true);
+ }
+ // TODO: implement 2, 4, 5.
+ case 2: case 4: // No-op.
+ case 5: // Pad to 32-bit aligned.
+ default: return_trace (false);
+ }
+ }
+
+ bool
+ fill_missing_glyphs (hb_serialize_context_t *c,
+ unsigned int cbdt_prime_len,
+ unsigned int num_missing,
+ unsigned int *size /* OUT (accumulated) */,
+ unsigned int *num_glyphs /* OUT (accumulated) */)
+ {
+ TRACE_SERIALIZE (this);
+
+ unsigned int local_offset = cbdt_prime_len - u.header.imageDataOffset;
+ switch (u.header.indexFormat)
+ {
+ case 1: {
+ for (unsigned int i = 0; i < num_missing; i++)
+ {
+ if (unlikely (!u.format1.add_offset (c, local_offset, size)))
+ return_trace (false);
+ *num_glyphs += 1;
+ }
+ return_trace (true);
+ }
+ case 3: {
+ for (unsigned int i = 0; i < num_missing; i++)
+ {
+ if (unlikely (!u.format3.add_offset (c, local_offset, size)))
+ return_trace (false);
+ *num_glyphs += 1;
+ }
+ return_trace (true);
+ }
+ // TODO: implement 2, 4, 5.
+ case 2: // Add empty space in cbdt_prime?.
+ case 4: case 5: // No-op as sparse is supported.
+ default: return_trace (false);
+ }
+ }
+
+ bool
+ copy_glyph_at_idx (hb_serialize_context_t *c, unsigned int idx,
+ const char *cbdt, unsigned int cbdt_length,
+ hb_vector_t<char> *cbdt_prime /* INOUT */,
+ IndexSubtable *subtable_prime /* INOUT */,
+ unsigned int *size /* OUT (accumulated) */) const
+ {
+ TRACE_SERIALIZE (this);
+
+ unsigned int offset, length, format;
+ if (unlikely (!get_image_data (idx, &offset, &length, &format))) return_trace (false);
+ if (unlikely (offset > cbdt_length || cbdt_length - offset < length)) return_trace (false);
+
+ auto *header_prime = subtable_prime->get_header ();
+ unsigned int new_local_offset = cbdt_prime->length - (unsigned int) header_prime->imageDataOffset;
+ if (unlikely (!_copy_data_to_cbdt (cbdt_prime, cbdt + offset, length))) return_trace (false);
+
+ return_trace (subtable_prime->add_offset (c, new_local_offset, size));
+ }
+
+ bool
+ add_offset (hb_serialize_context_t *c, unsigned int local_offset,
+ unsigned int *size /* OUT (accumulated) */)
+ {
+ TRACE_SERIALIZE (this);
+ switch (u.header.indexFormat)
+ {
+ case 1: return_trace (u.format1.add_offset (c, local_offset, size));
+ case 3: return_trace (u.format3.add_offset (c, local_offset, size));
+ // TODO: Implement tables 2, 4, 5
+ case 2: // Should be a no-op.
+ case 4: case 5: // Handle sparse cases.
+ default: return_trace (false);
+ }
+ }
+
bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const
{
- switch (u.header.indexFormat) {
+ switch (u.header.indexFormat)
+ {
case 2: case 5: /* TODO */
case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */
default:return (false);
}
}
- bool get_image_data (unsigned int idx,
- unsigned int *offset,
- unsigned int *length,
- unsigned int *format) const
+ bool
+ get_image_data (unsigned int idx, unsigned int *offset,
+ unsigned int *length, unsigned int *format) const
{
*format = u.header.imageFormat;
- switch (u.header.indexFormat) {
+ switch (u.header.indexFormat)
+ {
case 1: return u.format1.get_image_data (idx, offset, length);
case 3: return u.format3.get_image_data (idx, offset, length);
default: return false;
}
}
+ const IndexSubtableHeader* get_header () const { return &u.header; }
+
+ void populate_header (unsigned index_format,
+ unsigned image_format,
+ unsigned int image_data_offset,
+ unsigned int *size)
+ {
+ u.header.indexFormat = index_format;
+ u.header.imageFormat = image_format;
+ u.header.imageDataOffset = image_data_offset;
+ switch (u.header.indexFormat)
+ {
+ case 1: *size += IndexSubtableFormat1::min_size; break;
+ case 3: *size += IndexSubtableFormat3::min_size; break;
+ }
+ }
+
protected:
union {
IndexSubtableHeader header;
@@ -209,12 +368,133 @@ struct IndexSubtableRecord
offsetToSubtable.sanitize (c, base, lastGlyphIndex - firstGlyphIndex + 1));
}
- bool get_extents (hb_glyph_extents_t *extents,
- const void *base) const
+ const IndexSubtable* get_subtable (const void *base) const
+ {
+ return &(base+offsetToSubtable);
+ }
+
+ bool add_new_subtable (hb_subset_context_t* c,
+ cblc_bitmap_size_subset_context_t *bitmap_size_context,
+ IndexSubtableRecord *record,
+ const hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> *lookup, /* IN */
+ const void *base,
+ unsigned int *start /* INOUT */) const
+ {
+ TRACE_SERIALIZE (this);
+
+ auto *subtable = c->serializer->start_embed<IndexSubtable> ();
+ if (unlikely (!subtable)) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (subtable))) return_trace (false);
+
+ auto *old_subtable = get_subtable (base);
+ auto *old_header = old_subtable->get_header ();
+
+ subtable->populate_header (old_header->indexFormat,
+ old_header->imageFormat,
+ bitmap_size_context->cbdt_prime->length,
+ &bitmap_size_context->size);
+
+ unsigned int num_glyphs = 0;
+ bool early_exit = false;
+ for (unsigned int i = *start; i < lookup->length; i++)
+ {
+ hb_codepoint_t new_gid = (*lookup)[i].first;
+ const IndexSubtableRecord *next_record = (*lookup)[i].second;
+ const IndexSubtable *next_subtable = next_record->get_subtable (base);
+ auto *next_header = next_subtable->get_header ();
+ if (next_header != old_header)
+ {
+ *start = i;
+ early_exit = true;
+ break;
+ }
+ unsigned int num_missing = record->add_glyph_for_subset (new_gid);
+ if (unlikely (!subtable->fill_missing_glyphs (c->serializer,
+ bitmap_size_context->cbdt_prime->length,
+ num_missing,
+ &bitmap_size_context->size,
+ &num_glyphs)))
+ return_trace (false);
+
+ hb_codepoint_t old_gid = 0;
+ c->plan->old_gid_for_new_gid (new_gid, &old_gid);
+ if (old_gid < next_record->firstGlyphIndex)
+ return_trace (false);
+
+ unsigned int old_idx = (unsigned int) old_gid - next_record->firstGlyphIndex;
+ if (unlikely (!next_subtable->copy_glyph_at_idx (c->serializer,
+ old_idx,
+ bitmap_size_context->cbdt,
+ bitmap_size_context->cbdt_length,
+ bitmap_size_context->cbdt_prime,
+ subtable,
+ &bitmap_size_context->size)))
+ return_trace (false);
+ num_glyphs += 1;
+ }
+ if (!early_exit)
+ *start = lookup->length;
+ if (unlikely (!subtable->finish_subtable (c->serializer,
+ bitmap_size_context->cbdt_prime->length,
+ num_glyphs,
+ &bitmap_size_context->size)))
+ return_trace (false);
+ return_trace (true);
+ }
+
+ bool add_new_record (hb_subset_context_t *c,
+ cblc_bitmap_size_subset_context_t *bitmap_size_context,
+ const hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> *lookup, /* IN */
+ const void *base,
+ unsigned int *start, /* INOUT */
+ hb_vector_t<IndexSubtableRecord>* records /* INOUT */) const
{
- return (base+offsetToSubtable).get_extents (extents);
+ TRACE_SERIALIZE (this);
+ auto snap = c->serializer->snapshot ();
+ unsigned int old_size = bitmap_size_context->size;
+ unsigned int old_cbdt_prime_length = bitmap_size_context->cbdt_prime->length;
+
+ // Set to invalid state to indicate filling glyphs is not yet started.
+ records->resize (records->length + 1);
+ (*records)[records->length - 1].firstGlyphIndex = 1;
+ (*records)[records->length - 1].lastGlyphIndex = 0;
+ bitmap_size_context->size += IndexSubtableRecord::min_size;
+
+ c->serializer->push ();
+
+ if (unlikely (!add_new_subtable (c, bitmap_size_context, &((*records)[records->length - 1]), lookup, base, start)))
+ {
+ c->serializer->pop_discard ();
+ c->serializer->revert (snap);
+ bitmap_size_context->cbdt_prime->shrink (old_cbdt_prime_length);
+ bitmap_size_context->size = old_size;
+ records->resize (records->length - 1);
+ return_trace (false);
+ }
+
+ bitmap_size_context->num_tables += 1;
+ return_trace (true);
}
+ unsigned int add_glyph_for_subset (hb_codepoint_t gid)
+ {
+ if (firstGlyphIndex > lastGlyphIndex)
+ {
+ firstGlyphIndex = gid;
+ lastGlyphIndex = gid;
+ return 0;
+ }
+ // TODO maybe assert? this shouldn't occur.
+ if (lastGlyphIndex > gid)
+ return 0;
+ unsigned int num_missing = (unsigned int) (gid - lastGlyphIndex - 1);
+ lastGlyphIndex = gid;
+ return num_missing;
+ }
+
+ bool get_extents (hb_glyph_extents_t *extents, const void *base) const
+ { return (base+offsetToSubtable).get_extents (extents); }
+
bool get_image_data (unsigned int gid,
const void *base,
unsigned int *offset,
@@ -230,7 +510,7 @@ struct IndexSubtableRecord
HBGlyphID lastGlyphIndex;
LOffsetTo<IndexSubtable> offsetToSubtable;
public:
- DEFINE_SIZE_STATIC(8);
+ DEFINE_SIZE_STATIC (8);
};
struct IndexSubtableArray
@@ -243,6 +523,77 @@ struct IndexSubtableArray
return_trace (indexSubtablesZ.sanitize (c, count, this));
}
+ void
+ build_lookup (hb_subset_context_t *c, cblc_bitmap_size_subset_context_t *bitmap_size_context,
+ hb_vector_t<hb_pair_t<hb_codepoint_t,
+ const IndexSubtableRecord*>> *lookup /* OUT */) const
+ {
+ bool start_glyph_is_set = false;
+ for (hb_codepoint_t new_gid = 0; new_gid < c->plan->num_output_glyphs (); new_gid++)
+ {
+ hb_codepoint_t old_gid;
+ if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) continue;
+
+ const IndexSubtableRecord* record = find_table (old_gid, bitmap_size_context->num_tables);
+ if (unlikely (!record)) continue;
+
+ // Don't add gaps to the lookup. The best way to determine if a glyph is a
+ // gap is that it has no image data.
+ unsigned int offset, length, format;
+ if (unlikely (!record->get_image_data (old_gid, this, &offset, &length, &format))) continue;
+
+ lookup->push (hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*> (new_gid, record));
+
+ if (!start_glyph_is_set)
+ {
+ bitmap_size_context->start_glyph = new_gid;
+ start_glyph_is_set = true;
+ }
+
+ bitmap_size_context->end_glyph = new_gid;
+ }
+ }
+
+ bool
+ subset (hb_subset_context_t *c,
+ cblc_bitmap_size_subset_context_t *bitmap_size_context) const
+ {
+ TRACE_SUBSET (this);
+
+ auto *dst = c->serializer->start_embed<IndexSubtableArray> ();
+ if (unlikely (!dst)) return_trace (false);
+
+ hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> lookup;
+ build_lookup (c, bitmap_size_context, &lookup);
+
+ bitmap_size_context->size = 0;
+ bitmap_size_context->num_tables = 0;
+ hb_vector_t<IndexSubtableRecord> records;
+ for (unsigned int start = 0; start < lookup.length;)
+ {
+ if (unlikely (!lookup[start].second->add_new_record (c, bitmap_size_context, &lookup, this, &start, &records)))
+ {
+ // Discard any leftover pushes to the serializer from successful records.
+ for (unsigned int i = 0; i < records.length; i++)
+ c->serializer->pop_discard ();
+ return_trace (false);
+ }
+ }
+
+ /* Workaround to ensure offset ordering is from least to greatest when
+ * resolving links. */
+ hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
+ for (unsigned int i = 0; i < records.length; i++)
+ objidxs.push (c->serializer->pop_pack ());
+ for (unsigned int i = 0; i < records.length; i++)
+ {
+ IndexSubtableRecord* record = c->serializer->embed (records[i]);
+ if (unlikely (!record)) return_trace (false);
+ c->serializer->add_link (record->offsetToSubtable, objidxs[records.length - 1 - i]);
+ }
+ return_trace (true);
+ }
+
public:
const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
{
@@ -274,14 +625,48 @@ struct BitmapSizeTable
vertical.sanitize (c));
}
- const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
- const void *base,
- const void **out_base) const
+ const IndexSubtableRecord *
+ find_table (hb_codepoint_t glyph, const void *base, const void **out_base) const
{
*out_base = &(base+indexSubtableArrayOffset);
return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
}
+ bool
+ subset (hb_subset_context_t *c, const void *base,
+ const char *cbdt, unsigned int cbdt_length,
+ hb_vector_t<char> *cbdt_prime /* INOUT */) const
+ {
+ TRACE_SUBSET (this);
+ auto *out_table = c->serializer->embed (this);
+ if (unlikely (!out_table)) return_trace (false);
+
+ cblc_bitmap_size_subset_context_t bitmap_size_context;
+ bitmap_size_context.cbdt = cbdt;
+ bitmap_size_context.cbdt_length = cbdt_length;
+ bitmap_size_context.cbdt_prime = cbdt_prime;
+ bitmap_size_context.size = indexTablesSize;
+ bitmap_size_context.num_tables = numberOfIndexSubtables;
+ bitmap_size_context.start_glyph = 1;
+ bitmap_size_context.end_glyph = 0;
+
+ if (!out_table->indexSubtableArrayOffset.serialize_subset (c,
+ indexSubtableArrayOffset,
+ base,
+ &bitmap_size_context))
+ return_trace (false);
+ if (!bitmap_size_context.size ||
+ !bitmap_size_context.num_tables ||
+ bitmap_size_context.start_glyph > bitmap_size_context.end_glyph)
+ return_trace (false);
+
+ out_table->indexTablesSize = bitmap_size_context.size;
+ out_table->numberOfIndexSubtables = bitmap_size_context.num_tables;
+ out_table->startGlyphIndex = bitmap_size_context.start_glyph;
+ out_table->endGlyphIndex = bitmap_size_context.end_glyph;
+ return_trace (true);
+ }
+
protected:
LNNOffsetTo<IndexSubtableArray>
indexSubtableArrayOffset;
@@ -297,7 +682,7 @@ struct BitmapSizeTable
HBUINT8 bitDepth;
HBINT8 flags;
public:
- DEFINE_SIZE_STATIC(48);
+ DEFINE_SIZE_STATIC (48);
};
@@ -310,7 +695,7 @@ struct GlyphBitmapDataFormat17
SmallGlyphMetrics glyphMetrics;
LArrayOf<HBUINT8> data;
public:
- DEFINE_SIZE_ARRAY(9, data);
+ DEFINE_SIZE_ARRAY (9, data);
};
struct GlyphBitmapDataFormat18
@@ -318,14 +703,14 @@ struct GlyphBitmapDataFormat18
BigGlyphMetrics glyphMetrics;
LArrayOf<HBUINT8> data;
public:
- DEFINE_SIZE_ARRAY(12, data);
+ DEFINE_SIZE_ARRAY (12, data);
};
struct GlyphBitmapDataFormat19
{
LArrayOf<HBUINT8> data;
public:
- DEFINE_SIZE_ARRAY(4, data);
+ DEFINE_SIZE_ARRAY (4, data);
};
struct CBLC
@@ -342,12 +727,50 @@ struct CBLC
sizeTables.sanitize (c, this));
}
+ static bool
+ sink_cbdt (hb_subset_context_t *c, hb_vector_t<char>* cbdt_prime)
+ {
+ hb_blob_t *cbdt_prime_blob = hb_blob_create (cbdt_prime->arrayZ,
+ cbdt_prime->length,
+ HB_MEMORY_MODE_WRITABLE,
+ cbdt_prime->arrayZ,
+ free);
+ cbdt_prime->init (); // Leak arrayZ to the blob.
+ bool ret = c->plan->add_table (HB_OT_TAG_CBDT, cbdt_prime_blob);
+ hb_blob_destroy (cbdt_prime_blob);
+ return ret;
+ }
+
+ bool
+ subset_size_table (hb_subset_context_t *c, const BitmapSizeTable& table,
+ const char *cbdt /* IN */, unsigned int cbdt_length,
+ CBLC *cblc_prime /* INOUT */, hb_vector_t<char> *cbdt_prime /* INOUT */) const
+ {
+ TRACE_SUBSET (this);
+ cblc_prime->sizeTables.len++;
+
+ auto snap = c->serializer->snapshot ();
+ auto cbdt_prime_len = cbdt_prime->length;
+
+ if (!table.subset (c, this, cbdt, cbdt_length, cbdt_prime))
+ {
+ cblc_prime->sizeTables.len--;
+ c->serializer->revert (snap);
+ cbdt_prime->shrink (cbdt_prime_len);
+ return_trace (false);
+ }
+ return_trace (true);
+ }
+
+ // Implemented in cc file as it depends on definition of CBDT.
+ HB_INTERNAL bool subset (hb_subset_context_t *c) const;
+
protected:
const BitmapSizeTable &choose_strike (hb_font_t *font) const
{
unsigned count = sizeTables.len;
if (unlikely (!count))
- return Null(BitmapSizeTable);
+ return Null (BitmapSizeTable);
unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
if (!requested_ppem)
@@ -373,7 +796,7 @@ struct CBLC
FixedVersion<> version;
LArrayOf<BitmapSizeTable> sizeTables;
public:
- DEFINE_SIZE_ARRAY(8, sizeTables);
+ DEFINE_SIZE_ARRAY (8, sizeTables);
};
struct CBDT
@@ -384,8 +807,8 @@ struct CBDT
{
void init (hb_face_t *face)
{
- cblc = hb_sanitize_context_t().reference_table<CBLC> (face);
- cbdt = hb_sanitize_context_t().reference_table<CBDT> (face);
+ cblc = hb_sanitize_context_t ().reference_table<CBLC> (face);
+ cbdt = hb_sanitize_context_t ().reference_table<CBDT> (face);
upem = hb_face_get_upem (face);
}
@@ -396,8 +819,8 @@ struct CBDT
this->cbdt.destroy ();
}
- bool get_extents (hb_font_t *font, hb_codepoint_t glyph,
- hb_glyph_extents_t *extents) const
+ bool
+ get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
{
const void *base;
const BitmapSizeTable &strike = this->cblc->choose_strike (font);
@@ -412,33 +835,27 @@ struct CBDT
if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
return false;
+ unsigned int cbdt_len = cbdt.get_length ();
+ if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+ return false;
+
+ switch (image_format)
{
- unsigned int cbdt_len = cbdt.get_length ();
- if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+ case 17: {
+ if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
return false;
-
- switch (image_format)
- {
- case 17: {
- if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
- return false;
- const GlyphBitmapDataFormat17& glyphFormat17 =
- StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
- glyphFormat17.glyphMetrics.get_extents (font, extents);
- break;
- }
- case 18: {
- if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
- return false;
- const GlyphBitmapDataFormat18& glyphFormat18 =
- StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
- glyphFormat18.glyphMetrics.get_extents (font, extents);
- break;
- }
- default:
- // TODO: Support other image formats.
- return false;
- }
+ auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
+ glyphFormat17.glyphMetrics.get_extents (font, extents);
+ break;
+ }
+ case 18: {
+ if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
+ return false;
+ auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
+ glyphFormat18.glyphMetrics.get_extents (font, extents);
+ break;
+ }
+ default: return false; /* TODO: Support other image formats. */
}
/* Convert to font units. */
@@ -452,8 +869,8 @@ struct CBDT
return true;
}
- hb_blob_t* reference_png (hb_font_t *font,
- hb_codepoint_t glyph) const
+ hb_blob_t*
+ reference_png (hb_font_t *font, hb_codepoint_t glyph) const
{
const void *base;
const BitmapSizeTable &strike = this->cblc->choose_strike (font);
@@ -465,44 +882,41 @@ struct CBDT
if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
return hb_blob_get_empty ();
+ unsigned int cbdt_len = cbdt.get_length ();
+ if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+ return hb_blob_get_empty ();
+
+ switch (image_format)
+ {
+ case 17:
{
- unsigned int cbdt_len = cbdt.get_length ();
- if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+ if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
return hb_blob_get_empty ();
-
- switch (image_format)
- {
- case 17: {
- if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
- return hb_blob_get_empty ();
- const GlyphBitmapDataFormat17& glyphFormat17 =
- StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
- return hb_blob_create_sub_blob (cbdt.get_blob (),
- image_offset + GlyphBitmapDataFormat17::min_size,
- glyphFormat17.data.len);
- }
- case 18: {
- if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
- return hb_blob_get_empty ();
- const GlyphBitmapDataFormat18& glyphFormat18 =
- StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
- return hb_blob_create_sub_blob (cbdt.get_blob (),
- image_offset + GlyphBitmapDataFormat18::min_size,
- glyphFormat18.data.len);
- }
- case 19: {
- if (unlikely (image_length < GlyphBitmapDataFormat19::min_size))
- return hb_blob_get_empty ();
- const GlyphBitmapDataFormat19& glyphFormat19 =
- StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
- return hb_blob_create_sub_blob (cbdt.get_blob (),
- image_offset + GlyphBitmapDataFormat19::min_size,
- glyphFormat19.data.len);
- }
- }
+ auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
+ return hb_blob_create_sub_blob (cbdt.get_blob (),
+ image_offset + GlyphBitmapDataFormat17::min_size,
+ glyphFormat17.data.len);
+ }
+ case 18:
+ {
+ if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
+ return hb_blob_get_empty ();
+ auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
+ return hb_blob_create_sub_blob (cbdt.get_blob (),
+ image_offset + GlyphBitmapDataFormat18::min_size,
+ glyphFormat18.data.len);
+ }
+ case 19:
+ {
+ if (unlikely (image_length < GlyphBitmapDataFormat19::min_size))
+ return hb_blob_get_empty ();
+ auto &glyphFormat19 = StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
+ return hb_blob_create_sub_blob (cbdt.get_blob (),
+ image_offset + GlyphBitmapDataFormat19::min_size,
+ glyphFormat19.data.len);
+ }
+ default: return hb_blob_get_empty (); /* TODO: Support other image formats. */
}
-
- return hb_blob_get_empty ();
}
bool has_data () const { return cbdt.get_length (); }
@@ -525,9 +939,41 @@ struct CBDT
FixedVersion<> version;
UnsizedArrayOf<HBUINT8> dataZ;
public:
- DEFINE_SIZE_ARRAY(4, dataZ);
+ DEFINE_SIZE_ARRAY (4, dataZ);
};
+inline bool
+CBLC::subset (hb_subset_context_t *c) const
+{
+ TRACE_SUBSET (this);
+
+ auto *cblc_prime = c->serializer->start_embed<CBLC> ();
+
+ // Use a vector as a secondary buffer as the tables need to be built in parallel.
+ hb_vector_t<char> cbdt_prime;
+
+ if (unlikely (!cblc_prime)) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (cblc_prime))) return_trace (false);
+ cblc_prime->version = version;
+
+ hb_blob_t* cbdt_blob = hb_sanitize_context_t ().reference_table<CBDT> (c->plan->source);
+ unsigned int cbdt_length;
+ CBDT* cbdt = (CBDT *) hb_blob_get_data (cbdt_blob, &cbdt_length);
+ if (unlikely (cbdt_length < CBDT::min_size))
+ {
+ hb_blob_destroy (cbdt_blob);
+ return_trace (false);
+ }
+ _copy_data_to_cbdt (&cbdt_prime, cbdt, CBDT::min_size);
+
+ for (const BitmapSizeTable& table : + sizeTables.iter ())
+ subset_size_table (c, table, (const char *) cbdt, cbdt_length, cblc_prime, &cbdt_prime);
+
+ hb_blob_destroy (cbdt_blob);
+
+ return_trace (CBLC::sink_cbdt (c, &cbdt_prime));
+}
+
struct CBDT_accelerator_t : CBDT::accelerator_t {};
} /* namespace OT */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh
index e2ed7c65490..82eab963371 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh
@@ -1,5 +1,6 @@
/*
* Copyright © 2018 Ebrahim Byagowi
+ * Copyright © 2020 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -20,6 +21,8 @@
* 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): Calder Kitagawa
*/
#ifndef HB_OT_COLOR_COLR_TABLE_HH
@@ -47,7 +50,7 @@ struct LayerRecord
return_trace (c->check_struct (this));
}
- protected:
+ public:
HBGlyphID glyphId; /* Glyph ID of layer glyph */
Index colorIdx; /* Index value to use with a
* selected color palette.
@@ -112,6 +115,38 @@ struct COLR
return glyph_layers.length;
}
+ struct accelerator_t
+ {
+ accelerator_t () {}
+ ~accelerator_t () { fini (); }
+
+ void init (hb_face_t *face)
+ { colr = hb_sanitize_context_t ().reference_table<COLR> (face); }
+
+ void fini () { this->colr.destroy (); }
+
+ bool is_valid () { return colr.get_blob ()->length; }
+
+ void closure_glyphs (hb_codepoint_t glyph,
+ hb_set_t *related_ids /* OUT */) const
+ { colr->closure_glyphs (glyph, related_ids); }
+
+ private:
+ hb_blob_ptr_t<COLR> colr;
+ };
+
+ void closure_glyphs (hb_codepoint_t glyph,
+ hb_set_t *related_ids /* OUT */) const
+ {
+ const BaseGlyphRecord *record = get_base_glyph_record (glyph);
+ if (!record) return;
+
+ auto glyph_layers = (this+layersZ).as_array (numLayers).sub_array (record->firstLayerIdx,
+ record->numLayers);
+ if (!glyph_layers.length) return;
+ related_ids->add_array (&glyph_layers[0].glyphId, glyph_layers.length, LayerRecord::min_size);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -120,6 +155,111 @@ struct COLR
(this+layersZ).sanitize (c, numLayers)));
}
+ template<typename BaseIterator, typename LayerIterator,
+ hb_requires (hb_is_iterator (BaseIterator)),
+ hb_requires (hb_is_iterator (LayerIterator))>
+ bool serialize (hb_serialize_context_t *c,
+ unsigned version,
+ BaseIterator base_it,
+ LayerIterator layer_it)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (base_it.len () != layer_it.len ()))
+ return_trace (false);
+
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ this->version = version;
+ numLayers = 0;
+ numBaseGlyphs = base_it.len ();
+ baseGlyphsZ = COLR::min_size;
+ layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size;
+
+ for (const hb_item_type<BaseIterator>& _ : + base_it.iter ())
+ {
+ auto* record = c->embed (_);
+ if (unlikely (!record)) return_trace (false);
+ record->firstLayerIdx = numLayers;
+ numLayers += record->numLayers;
+ }
+
+ for (const hb_item_type<LayerIterator>& _ : + layer_it.iter ())
+ _.as_array ().copy (c);
+
+ return_trace (true);
+ }
+
+ const BaseGlyphRecord* get_base_glyph_record (hb_codepoint_t gid) const
+ {
+ if ((unsigned int) gid == 0) // Ignore notdef.
+ return nullptr;
+ const BaseGlyphRecord* record = &(this+baseGlyphsZ).bsearch (numBaseGlyphs, (unsigned int) gid);
+ if ((record && (hb_codepoint_t) record->glyphId != gid))
+ record = nullptr;
+ return record;
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
+
+ auto base_it =
+ + hb_range (c->plan->num_output_glyphs ())
+ | hb_map_retains_sorting ([&](hb_codepoint_t new_gid)
+ {
+ hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
+
+ const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid);
+ if (unlikely (!old_record))
+ return hb_pair_t<bool, BaseGlyphRecord> (false, Null (BaseGlyphRecord));
+
+ BaseGlyphRecord new_record;
+ new_record.glyphId = new_gid;
+ new_record.numLayers = old_record->numLayers;
+ return hb_pair_t<bool, BaseGlyphRecord> (true, new_record);
+ })
+ | hb_filter (hb_first)
+ | hb_map_retains_sorting (hb_second)
+ ;
+
+ auto layer_it =
+ + hb_range (c->plan->num_output_glyphs ())
+ | hb_map (reverse_glyph_map)
+ | hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
+ {
+ const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid);
+ hb_vector_t<LayerRecord> out_layers;
+
+ if (unlikely (!old_record ||
+ old_record->firstLayerIdx >= numLayers ||
+ old_record->firstLayerIdx + old_record->numLayers > numLayers))
+ return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
+
+ auto layers = (this+layersZ).as_array (numLayers).sub_array (old_record->firstLayerIdx,
+ old_record->numLayers);
+ out_layers.resize (layers.length);
+ for (unsigned int i = 0; i < layers.length; i++) {
+ out_layers[i] = layers[i];
+ hb_codepoint_t new_gid = 0;
+ if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid)))
+ return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
+ out_layers[i].glyphId = new_gid;
+ }
+
+ return hb_pair_t<bool, hb_vector_t<LayerRecord>> (true, out_layers);
+ })
+ | hb_filter (hb_first)
+ | hb_map_retains_sorting (hb_second)
+ ;
+
+ if (unlikely (!base_it || !layer_it || base_it.len () != layer_it.len ()))
+ return_trace (false);
+
+ COLR *colr_prime = c->serializer->start_embed<COLR> ();
+ return_trace (colr_prime->serialize (c->serializer, version, base_it, layer_it));
+ }
+
protected:
HBUINT16 version; /* Table version number (starts at 0). */
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */
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 1b3c7fc0b88..ce9f76e45e9 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
@@ -155,7 +155,7 @@ struct CPAL
private:
const CPALV1Tail& v1 () const
{
- if (version == 0) return Null(CPALV1Tail);
+ if (version == 0) return Null (CPALV1Tail);
return StructAfter<CPALV1Tail> (*this);
}
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 35d3fd51056..09da11597da 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
@@ -1,5 +1,6 @@
/*
* Copyright © 2018 Ebrahim Byagowi
+ * Copyright © 2020 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -20,12 +21,15 @@
* 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): Calder Kitagawa
*/
#ifndef HB_OT_COLOR_SBIX_TABLE_HH
#define HB_OT_COLOR_SBIX_TABLE_HH
#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
/*
* sbix -- Standard Bitmap Graphics
@@ -40,6 +44,20 @@ namespace OT {
struct SBIXGlyph
{
+ SBIXGlyph* copy (hb_serialize_context_t *c, unsigned int data_length) const
+ {
+ TRACE_SERIALIZE (this);
+ SBIXGlyph* new_glyph = c->start_embed<SBIXGlyph> ();
+ if (unlikely (!new_glyph)) return_trace (nullptr);
+ if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr);
+
+ new_glyph->xOffset = xOffset;
+ new_glyph->yOffset = yOffset;
+ new_glyph->graphicType = graphicType;
+ data.copy (c, data_length);
+ return_trace (new_glyph);
+ }
+
HBINT16 xOffset; /* The horizontal (x-axis) offset from the left
* edge of the graphic to the glyph’s origin.
* That is, the x-coordinate of the point on the
@@ -62,6 +80,9 @@ struct SBIXGlyph
struct SBIXStrike
{
+ static unsigned int get_size (unsigned num_glyphs)
+ { return min_size + num_glyphs * HBUINT32::static_size; }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -116,6 +137,49 @@ struct SBIXStrike
return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
}
+ bool subset (hb_subset_context_t *c, unsigned int available_len) const
+ {
+ TRACE_SUBSET (this);
+ unsigned int num_output_glyphs = c->plan->num_output_glyphs ();
+
+ auto* out = c->serializer->start_embed<SBIXStrike> ();
+ if (unlikely (!out)) return_trace (false);
+ auto snap = c->serializer->snapshot ();
+ if (unlikely (!c->serializer->extend (*out, num_output_glyphs + 1))) return_trace (false);
+ out->ppem = ppem;
+ out->resolution = resolution;
+ HBUINT32 head;
+ head = get_size (num_output_glyphs + 1);
+
+ bool has_glyphs = false;
+ for (unsigned new_gid = 0; new_gid < num_output_glyphs; new_gid++)
+ {
+ hb_codepoint_t old_gid;
+ if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid) ||
+ unlikely (imageOffsetsZ[old_gid].is_null () ||
+ imageOffsetsZ[old_gid + 1].is_null () ||
+ imageOffsetsZ[old_gid + 1] <= imageOffsetsZ[old_gid] ||
+ imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid] <= SBIXGlyph::min_size) ||
+ (unsigned int) imageOffsetsZ[old_gid + 1] > available_len)
+ {
+ out->imageOffsetsZ[new_gid] = head;
+ continue;
+ }
+ has_glyphs = true;
+ unsigned int delta = imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid];
+ unsigned int glyph_data_length = delta - SBIXGlyph::min_size;
+ if (!(this+imageOffsetsZ[old_gid]).copy (c->serializer, glyph_data_length))
+ return_trace (false);
+ out->imageOffsetsZ[new_gid] = head;
+ head += delta;
+ }
+ if (has_glyphs)
+ out->imageOffsetsZ[num_output_glyphs] = head;
+ else
+ c->serializer->revert (snap);
+ return_trace (has_glyphs);
+ }
+
public:
HBUINT16 ppem; /* The PPEM size for which this strike was designed. */
HBUINT16 resolution; /* The device pixel density (in PPI) for which this
@@ -140,7 +204,7 @@ struct sbix
{
void init (hb_face_t *face)
{
- table = hb_sanitize_context_t().reference_table<sbix> (face);
+ table = hb_sanitize_context_t ().reference_table<sbix> (face);
num_glyphs = face->get_num_glyphs ();
}
void fini () { table.destroy (); }
@@ -173,7 +237,7 @@ struct sbix
{
unsigned count = table->strikes.len;
if (unlikely (!count))
- return Null(SBIXStrike);
+ return Null (SBIXStrike);
unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
if (!requested_ppem)
@@ -237,7 +301,7 @@ struct sbix
extents->x_bearing = x_offset;
extents->y_bearing = png.IHDR.height + y_offset;
extents->width = png.IHDR.width;
- extents->height = -png.IHDR.height;
+ extents->height = -1 * png.IHDR.height;
/* Convert to font units. */
if (strike_ppem)
@@ -275,6 +339,63 @@ struct sbix
strikes.sanitize (c, this)));
}
+ bool
+ add_strike (hb_subset_context_t *c, unsigned i) const
+ {
+ if (strikes[i].is_null () || c->source_blob->length < (unsigned) strikes[i])
+ return false;
+
+ return (this+strikes[i]).subset (c, c->source_blob->length - (unsigned) strikes[i]);
+ }
+
+ bool serialize_strike_offsets (hb_subset_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+
+ auto *out = c->serializer->start_embed<LOffsetLArrayOf<SBIXStrike>> ();
+ if (unlikely (!out)) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ hb_vector_t<LOffsetTo<SBIXStrike>*> new_strikes;
+ hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
+ for (int i = strikes.len - 1; i >= 0; --i)
+ {
+ auto* o = out->serialize_append (c->serializer);
+ if (unlikely (!o)) return_trace (false);
+ *o = 0;
+ auto snap = c->serializer->snapshot ();
+ c->serializer->push ();
+ bool ret = add_strike (c, i);
+ if (!ret)
+ {
+ c->serializer->pop_discard ();
+ out->pop ();
+ c->serializer->revert (snap);
+ }
+ else
+ {
+ objidxs.push (c->serializer->pop_pack ());
+ new_strikes.push (o);
+ }
+ }
+ for (unsigned int i = 0; i < new_strikes.length; ++i)
+ c->serializer->add_link (*new_strikes[i], objidxs[new_strikes.length - 1 - i]);
+
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t* c) const
+ {
+ TRACE_SUBSET (this);
+
+ sbix *sbix_prime = c->serializer->start_embed<sbix> ();
+ if (unlikely (!sbix_prime)) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->version))) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->flags))) return_trace (false);
+
+ return_trace (serialize_strike_offsets (c));
+ }
+
protected:
HBUINT16 version; /* Table version number — set to 1 */
HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines.
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh
index 926d61e0faf..1cc40ae53fa 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh
@@ -80,7 +80,7 @@ struct SVG
struct accelerator_t
{
void init (hb_face_t *face)
- { table = hb_sanitize_context_t().reference_table<SVG> (face); }
+ { table = hb_sanitize_context_t ().reference_table<SVG> (face); }
void fini () { table.destroy (); }
hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
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 96f94e4a9ec..a1dc88603a2 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
@@ -183,22 +183,21 @@ hb_ot_get_glyph_extents (hb_font_t *font,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
- bool ret = false;
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
- if (!ret) ret = ot_face->sbix->get_extents (font, glyph, extents);
+ if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
#endif
- if (!ret) ret = ot_face->glyf->get_extents (font, glyph, extents);
+ if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
#ifndef HB_NO_OT_FONT_CFF
- if (!ret) ret = ot_face->cff1->get_extents (font, glyph, extents);
- if (!ret) ret = ot_face->cff2->get_extents (font, glyph, extents);
+ if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
+ if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
#endif
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
- if (!ret) ret = ot_face->CBDT->get_extents (font, glyph, extents);
+ if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
#endif
// TODO Hook up side-bearings variations.
- return ret;
+ return false;
}
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
@@ -210,7 +209,11 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
- return ot_face->post->get_glyph_name (glyph, name, size);
+ if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
+#ifndef HB_NO_OT_FONT_CFF
+ if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
+#endif
+ return false;
}
static hb_bool_t
hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
@@ -220,7 +223,11 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
- return ot_face->post->get_glyph_from_name (name, len, glyph);
+ if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
+#ifndef HB_NO_OT_FONT_CFF
+ if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
+#endif
+ return false;
}
#endif
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh
index 94fff58a158..4f291924afd 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-gasp-table.hh
@@ -48,8 +48,8 @@ struct GaspRange
}
public:
- HBUINT16 rangeMaxPPEM; /* Upper limit of range, in PPEM */
- HBUINT16 rangeGaspBehavior;
+ HBUINT16 rangeMaxPPEM; /* Upper limit of range, in PPEM */
+ HBUINT16 rangeGaspBehavior;
/* Flags describing desired rasterizer behavior. */
public:
DEFINE_SIZE_STATIC (4);
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 571e50ea0c7..ce7ffa9d1f8 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
@@ -34,8 +34,7 @@
#include "hb-ot-head-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-var-gvar-table.hh"
-
-#include <float.h>
+#include "hb-draw.hh"
namespace OT {
@@ -148,7 +147,19 @@ struct glyf
const hb_subset_plan_t *plan)
{
TRACE_SERIALIZE (this);
+ unsigned init_len = c->length ();
for (const auto &_ : it) _.serialize (c, plan);
+
+ /* As a special case when all glyph in the font are empty, add a zero byte
+ * to the table, so that OTS doesn’t reject it, and to make the table work
+ * on Windows as well.
+ * See https://github.com/khaledhosny/ots/issues/52 */
+ if (init_len == c->length ())
+ {
+ HBUINT8 empty_byte;
+ empty_byte = 0;
+ c->copy (empty_byte);
+ }
return_trace (true);
}
@@ -229,18 +240,18 @@ struct glyf
{
enum composite_glyph_flag_t
{
- ARG_1_AND_2_ARE_WORDS = 0x0001,
- ARGS_ARE_XY_VALUES = 0x0002,
- ROUND_XY_TO_GRID = 0x0004,
- WE_HAVE_A_SCALE = 0x0008,
- MORE_COMPONENTS = 0x0020,
- WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
- WE_HAVE_A_TWO_BY_TWO = 0x0080,
- WE_HAVE_INSTRUCTIONS = 0x0100,
- USE_MY_METRICS = 0x0200,
- OVERLAP_COMPOUND = 0x0400,
- SCALED_COMPONENT_OFFSET = 0x0800,
- UNSCALED_COMPONENT_OFFSET = 0x1000
+ ARG_1_AND_2_ARE_WORDS = 0x0001,
+ ARGS_ARE_XY_VALUES = 0x0002,
+ ROUND_XY_TO_GRID = 0x0004,
+ WE_HAVE_A_SCALE = 0x0008,
+ MORE_COMPONENTS = 0x0020,
+ WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
+ WE_HAVE_A_TWO_BY_TWO = 0x0080,
+ WE_HAVE_INSTRUCTIONS = 0x0100,
+ USE_MY_METRICS = 0x0200,
+ OVERLAP_COMPOUND = 0x0400,
+ SCALED_COMPONENT_OFFSET = 0x0800,
+ UNSCALED_COMPONENT_OFFSET = 0x1000
};
unsigned int get_size () const
@@ -361,7 +372,7 @@ struct glyf
typedef const CompositeGlyphChain *__item_t__;
composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
glyph (glyph_), current (current_)
- { if (!in_range (current)) current = nullptr; }
+ { if (!check_range (current)) current = nullptr; }
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr) {}
const CompositeGlyphChain &__item__ () const { return *current; }
@@ -372,16 +383,16 @@ struct glyf
const CompositeGlyphChain *possible = &StructAfter<CompositeGlyphChain,
CompositeGlyphChain> (*current);
- if (!in_range (possible)) { current = nullptr; return; }
+ if (!check_range (possible)) { current = nullptr; return; }
current = possible;
}
bool operator != (const composite_iter_t& o) const
{ return glyph != o.glyph || current != o.current; }
- bool in_range (const CompositeGlyphChain *composite) const
+ bool check_range (const CompositeGlyphChain *composite) const
{
- return glyph.in_range (composite, CompositeGlyphChain::min_size)
- && glyph.in_range (composite, composite->get_size ());
+ return glyph.check_range (composite, CompositeGlyphChain::min_size)
+ && glyph.check_range (composite, composite->get_size ());
}
private:
@@ -389,8 +400,29 @@ struct glyf
__item_t__ current;
};
+ enum phantom_point_index_t
+ {
+ PHANTOM_LEFT = 0,
+ PHANTOM_RIGHT = 1,
+ PHANTOM_TOP = 2,
+ PHANTOM_BOTTOM = 3,
+ PHANTOM_COUNT = 4
+ };
+
struct Glyph
{
+ 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
+ };
+
private:
struct GlyphHeader
{
@@ -445,18 +477,6 @@ struct glyf
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 */
@@ -470,7 +490,6 @@ struct glyf
unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
glyph += 2 + num_instructions;
- if (unlikely (glyph + 2 >= glyph_end)) return Glyph ();
unsigned int coord_bytes = 0;
unsigned int coords_with_flags = 0;
@@ -519,70 +538,53 @@ struct glyf
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 hb_bytes_t &bytes)
+ const hb_bytes_t &bytes,
+ void (* setter) (contour_point_t &_, float v),
+ const simple_glyph_flag_t short_flag,
+ const simple_glyph_flag_t same_flag)
{
- T coord_setter;
float v = 0;
- for (unsigned int i = 0; i < points_.length - PHANTOM_COUNT; i++)
+ for (unsigned i = 0; i < points_.length; i++)
{
uint8_t flag = points_[i].flag;
- if (coord_setter.is_short (flag))
+ if (flag & short_flag)
{
- if (unlikely (!bytes.in_range (p))) return false;
- if (coord_setter.is_same (flag))
+ if (unlikely (!bytes.check_range (p))) return false;
+ if (flag & same_flag)
v += *p++;
else
v -= *p++;
}
else
{
- if (!coord_setter.is_same (flag))
+ if (!(flag & same_flag))
{
- if (unlikely (!bytes.in_range ((const HBUINT16 *) p))) return false;
+ if (unlikely (!bytes.check_range ((const HBUINT16 *) p))) return false;
v += *(const HBINT16 *) p;
p += HBINT16::static_size;
}
}
- coord_setter.set (points_[i], v);
+ setter (points_[i], v);
}
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
+ bool phantom_only = false) const
{
const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
int num_contours = header.numberOfContours;
- if (unlikely (!bytes.in_range (&endPtsOfContours[num_contours + 1]))) return false;
+ if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
- points_.resize (num_points + PHANTOM_COUNT);
+ points_.resize (num_points);
for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
if (phantom_only) return true;
- /* 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];
+ points_[endPtsOfContours[i]].is_end_point = true;
/* Skip instructions */
const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
@@ -591,12 +593,12 @@ struct glyf
/* Read flags */
for (unsigned int i = 0; i < num_points; i++)
{
- if (unlikely (!bytes.in_range (p))) return false;
+ if (unlikely (!bytes.check_range (p))) return false;
uint8_t flag = *p++;
points_[i].flag = flag;
if (flag & FLAG_REPEAT)
{
- if (unlikely (!bytes.in_range (p))) return false;
+ if (unlikely (!bytes.check_range (p))) return false;
unsigned int repeat_count = *p++;
while ((repeat_count-- > 0) && (++i < num_points))
points_[i].flag = flag;
@@ -604,8 +606,10 @@ struct glyf
}
/* Read x & y coordinates */
- return (read_points<x_setter_t> (p, points_, bytes) &&
- read_points<y_setter_t> (p, points_, bytes));
+ return (read_points (p, points_, bytes,
+ [] (contour_point_t &p, float v) { p.x = v; }, FLAG_X_SHORT, FLAG_X_SAME) &&
+ read_points (p, points_, bytes,
+ [] (contour_point_t &p, float v) { p.y = v; }, FLAG_Y_SHORT, FLAG_Y_SAME));
}
};
@@ -648,30 +652,10 @@ struct glyf
/* 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 };
- 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
{
@@ -706,39 +690,130 @@ struct glyf
}
}
- /* 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
+ /* Note: Recursively calls itself.
+ * all_points includes 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
+ template<typename T>
+ bool get_points (T glyph_for_gid, hb_font_t *font,
+ contour_point_vector_t &all_points /* OUT */,
+ bool phantom_only = false,
+ unsigned int depth = 0) const
{
+ if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
+ contour_point_vector_t points;
+
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;
+ case COMPOSITE:
+ {
+ /* pseudo component points for each component in composite glyph */
+ unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ());
+ if (unlikely (!points.resize (num_points))) return false;
+ for (unsigned i = 0; i < points.length; i++)
+ points[i].init ();
+ break;
+ }
+ case SIMPLE:
+ if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
+ return false;
+ break;
+ default: return false; /* empty glyph */
}
- }
- bool is_simple_glyph () const { return type == SIMPLE; }
- bool is_composite_glyph () const { return type == COMPOSITE; }
+ hb_face_t *face = font->face;
- bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+ /* Init phantom points */
+ if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
+ hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
+ {
+ for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
+ int h_delta = (int) header->xMin - face->table.hmtx->get_side_bearing (gid);
+ int v_orig = (int) header->yMax + face->table.vmtx->get_side_bearing (gid);
+ unsigned h_adv = face->table.hmtx->get_advance (gid);
+ unsigned 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;
+ }
+
+#ifndef HB_NO_VAR
+ if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, font, points.as_array ())))
+ return false;
+#endif
+
+ switch (type) {
+ case SIMPLE:
+ all_points.extend (points.as_array ());
+ break;
+ case COMPOSITE:
+ {
+ unsigned int comp_index = 0;
+ for (auto &item : get_composite_iterator ())
+ {
+ contour_point_vector_t comp_points;
+ if (unlikely (!glyph_for_gid (item.glyphIndex).get_points (glyph_for_gid, font, comp_points, phantom_only, depth + 1))
+ || comp_points.length < PHANTOM_COUNT)
+ 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 translation 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++;
+ }
+
+ all_points.extend (phantoms);
+ } break;
+ default: return false;
+ }
+
+ if (depth == 0) /* Apply at top level */
+ {
+ /* Undocumented rasterizer behavior:
+ * Shift points horizontally by the updated left side bearing
+ */
+ contour_point_t delta;
+ delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
+ if (delta.x) all_points.translate (delta);
+ }
+
+ return true;
+ }
+
+ bool get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const
{
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; }
+ hb_bytes_t get_bytes () const { return bytes; }
- Glyph (hb_bytes_t bytes_ = hb_bytes_t ()) :
- bytes (bytes_), header (bytes.as<GlyphHeader> ())
+ Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
+ hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_),
+ header (bytes.as<GlyphHeader> ())
{
int num_contours = header->numberOfContours;
if (unlikely (num_contours == 0)) type = EMPTY;
@@ -748,6 +823,7 @@ struct glyf
protected:
hb_bytes_t bytes;
+ hb_codepoint_t gid;
const GlyphHeader *header;
unsigned type;
};
@@ -771,6 +847,7 @@ struct glyf
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
+ num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
}
void fini ()
@@ -779,223 +856,137 @@ struct glyf
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
+ template<typename T>
+ bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) 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;
- }
+ /* Making this alloc free is not that easy
+ https://github.com/harfbuzz/harfbuzz/issues/2095
+ mostly because of gvar handling in VF fonts,
+ perhaps a separate path for non-VF fonts can be considered */
+ contour_point_vector_t all_points;
- struct contour_bounds_t
- {
- contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
+ bool phantom_only = !consumer.is_consuming_contour_points ();
+ if (unlikely (!glyph_for_gid (gid).get_points ([this] (hb_codepoint_t gid) -> const Glyph { return this->glyph_for_gid (gid); },
+ font, all_points, phantom_only)))
+ return false;
- void add (const contour_point_t &p)
+ if (consumer.is_consuming_contour_points ())
{
- 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);
+ for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
+ consumer.consume_point (all_points[point_index]);
+ consumer.points_end ();
}
- bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
-
- void get_extents (hb_font_t *font, hb_glyph_extents_t *extents)
- {
- if (unlikely (empty ()))
- {
- extents->width = 0;
- extents->x_bearing = 0;
- extents->height = 0;
- extents->y_bearing = 0;
- return;
- }
- extents->x_bearing = font->em_scalef_x (min_x);
- extents->width = font->em_scalef_x (max_x - min_x);
- extents->y_bearing = font->em_scalef_y (max_y);
- extents->height = font->em_scalef_y (min_y - max_y);
- }
+ /* Where to write phantoms, nullptr if not requested */
+ contour_point_t *phantoms = consumer.get_phantoms_sink ();
+ if (phantoms)
+ for (unsigned i = 0; i < PHANTOM_COUNT; ++i)
+ phantoms[i] = all_points[all_points.length - PHANTOM_COUNT + i];
- protected:
- float min_x, min_y, max_x, max_y;
- };
+ return true;
+ }
+ public:
#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
+ struct points_aggregator_t
{
- 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;
+ hb_font_t *font;
+ hb_glyph_extents_t *extents;
+ contour_point_t *phantoms;
- unsigned int comp_index = 0;
- if (glyph.is_simple_glyph ())
- all_points.extend (points.as_array ());
- else if (glyph.is_composite_glyph ())
+ struct contour_bounds_t
{
- for (auto &item : glyph.get_composite_iterator ())
- {
- 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;
-
- /* 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];
+ contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
- /* Apply component transformation & translation */
- item.transform_points (comp_points);
+ void add (const contour_point_t &p)
+ {
+ 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);
+ }
- /* Apply translatation from gvar */
- comp_points.translate (points[comp_index]);
+ bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
- if (item.is_anchored ())
+ void get_extents (hb_font_t *font, hb_glyph_extents_t *extents)
+ {
+ if (unlikely (empty ()))
{
- 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);
- }
+ extents->width = 0;
+ extents->x_bearing = 0;
+ extents->height = 0;
+ extents->y_bearing = 0;
+ return;
}
-
- all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
-
- comp_index++;
+ extents->x_bearing = font->em_scalef_x (min_x);
+ extents->width = font->em_scalef_x (max_x - min_x);
+ extents->y_bearing = font->em_scalef_y (max_y);
+ extents->height = font->em_scalef_y (min_y - max_y);
}
- all_points.extend (phantoms);
- }
- else return false;
+ protected:
+ float min_x, min_y, max_x, max_y;
+ } bounds;
- 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)
+ points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_)
{
- contour_bounds_t bounds;
- for (unsigned int i = 0; i + PHANTOM_COUNT < all_points.length; i++)
- bounds.add (all_points[i]);
- bounds.get_extents (font, extents);
+ font = font_;
+ extents = extents_;
+ phantoms = phantoms_;
+ if (extents) bounds = contour_bounds_t ();
}
- 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_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); }
+ void consume_point (const contour_point_t &point) { bounds.add (point); }
+ void points_end () { bounds.get_extents (font, extents); }
- 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
+ bool is_consuming_contour_points () { return extents; }
+ contour_point_t *get_phantoms_sink () { return phantoms; }
+ };
- public:
-#ifndef HB_NO_VAR
- unsigned int get_advance_var (hb_font_t *font, hb_codepoint_t gid,
- bool is_vertical) const
+ unsigned int
+ get_advance_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
{
bool success = false;
- contour_point_vector_t phantoms;
- phantoms.resize (PHANTOM_COUNT);
+ contour_point_t phantoms[PHANTOM_COUNT];
if (likely (font->num_coords == face->table.gvar->get_axis_count ()))
- success = get_var_metrics (font, gid, phantoms);
+ success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
if (unlikely (!success))
- return is_vertical ? face->table.vmtx->get_advance (gid) : face->table.hmtx->get_advance (gid);
+ 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);
+ return is_vertical
+ ? roundf (phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y)
+ : roundf (phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x);
}
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);
+ contour_point_t phantoms[PHANTOM_COUNT];
+ if (unlikely (!get_points (font, gid, points_aggregator_t (font, &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);
+ return is_vertical
+ ? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
+ : floorf (phantoms[PHANTOM_LEFT].x);
}
#endif
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
{
+ if (unlikely (gid >= num_glyphs)) return false;
#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);
+ if (font->num_coords && font->num_coords == face->table.gvar->get_axis_count ())
+ return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
#endif
-
- if (unlikely (gid >= num_glyphs)) return false;
-
- return glyph_for_gid (gid).get_extents (font, gid, extents);
+ return glyph_for_gid (gid).get_extents (font, extents);
}
const Glyph
@@ -1021,7 +1012,7 @@ struct glyf
return Glyph ();
Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
- end_offset - start_offset));
+ end_offset - start_offset), gid);
return needs_padding_removal ? glyph.trim_padding () : glyph;
}
@@ -1036,9 +1027,130 @@ struct glyf
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);
+ add_gid_and_children (item.glyphIndex, gids_to_retain, depth);
}
+#ifdef HB_EXPERIMENTAL_API
+ struct path_builder_t
+ {
+ hb_font_t *font;
+ draw_helper_t *draw_helper;
+
+ struct optional_point_t
+ {
+ optional_point_t () { has_data = false; }
+ optional_point_t (float x_, float y_) { x = x_; y = y_; has_data = true; }
+
+ bool has_data;
+ float x;
+ float y;
+
+ optional_point_t lerp (optional_point_t p, float t)
+ { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
+ } first_oncurve, first_offcurve, last_offcurve;
+
+ path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_)
+ {
+ font = font_;
+ draw_helper = &draw_helper_;
+ first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
+ }
+
+ /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
+ See also:
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
+ * https://stackoverflow.com/a/20772557 */
+ void consume_point (const contour_point_t &point)
+ {
+ /* Skip empty contours */
+ if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data))
+ return;
+
+ bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
+ optional_point_t p (point.x, point.y);
+ if (!first_oncurve.has_data)
+ {
+ if (is_on_curve)
+ {
+ first_oncurve = p;
+ draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
+ }
+ else
+ {
+ if (first_offcurve.has_data)
+ {
+ optional_point_t mid = first_offcurve.lerp (p, .5f);
+ first_oncurve = mid;
+ last_offcurve = p;
+ draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
+ }
+ else
+ first_offcurve = p;
+ }
+ }
+ else
+ {
+ if (last_offcurve.has_data)
+ {
+ if (is_on_curve)
+ {
+ draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
+ font->em_scalef_x (p.x), font->em_scalef_y (p.y));
+ last_offcurve = optional_point_t ();
+ }
+ else
+ {
+ optional_point_t mid = last_offcurve.lerp (p, .5f);
+ draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
+ font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
+ last_offcurve = p;
+ }
+ }
+ else
+ {
+ if (is_on_curve)
+ draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
+ else
+ last_offcurve = p;
+ }
+ }
+
+ if (point.is_end_point)
+ {
+ if (first_offcurve.has_data && last_offcurve.has_data)
+ {
+ optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
+ draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
+ font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
+ last_offcurve = optional_point_t ();
+ /* now check the rest */
+ }
+
+ if (first_offcurve.has_data && first_oncurve.has_data)
+ draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y),
+ font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
+ else if (last_offcurve.has_data && first_oncurve.has_data)
+ draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
+ font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
+ else if (first_oncurve.has_data)
+ draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
+
+ /* Getting ready for the next contour */
+ first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
+ draw_helper->end_path ();
+ }
+ }
+ void points_end () {}
+
+ bool is_consuming_contour_points () { return true; }
+ contour_point_t *get_phantoms_sink () { return nullptr; }
+ };
+
+ bool
+ get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const
+ { return get_points (font, gid, path_builder_t (font, draw_helper)); }
+#endif
+
private:
bool short_offset;
unsigned int num_glyphs;
@@ -1073,7 +1185,7 @@ struct glyf
pad_length--;
}
- if (!unlikely (dest_glyph.length)) return_trace (true);
+ if (unlikely (!dest_glyph.length)) return_trace (true);
/* update components gids */
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh
index 96c1d1f634f..c9c391bad5f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hdmx-table.hh
@@ -107,11 +107,8 @@ struct hdmx
this->numRecords = it.len ();
this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0);
- + it
- | hb_apply ([c] (const hb_item_type<Iterator>& _) {
- c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
- })
- ;
+ for (const hb_item_type<Iterator>& _ : +it)
+ c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
return_trace (c->successful);
}
@@ -134,10 +131,10 @@ struct hdmx
auto row =
+ hb_range (c->plan->num_output_glyphs ())
| hb_map (c->plan->reverse_glyph_map)
- | hb_map ([=] (hb_codepoint_t _)
+ | hb_map ([this, c, device_record] (hb_codepoint_t _)
{
if (c->plan->is_empty_glyph (_))
- return Null(HBUINT8);
+ return Null (HBUINT8);
return device_record->widthsZ.as_array (get_num_glyphs ()) [_];
})
;
@@ -164,10 +161,12 @@ struct hdmx
}
protected:
- HBUINT16 version; /* Table version number (0) */
- HBUINT16 numRecords; /* Number of device records. */
- HBUINT32 sizeDeviceRecord; /* Size of a device record, 32-bit aligned. */
- DeviceRecord firstDeviceRecord; /* Array of device records. */
+ HBUINT16 version; /* Table version number (0) */
+ HBUINT16 numRecords; /* Number of device records. */
+ HBUINT32 sizeDeviceRecord;
+ /* Size of a device record, 32-bit aligned. */
+ DeviceRecord firstDeviceRecord;
+ /* Array of device records. */
public:
DEFINE_SIZE_MIN (8);
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-head-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-head-table.hh
index 3c0bb3d6ddd..5613a96dbfd 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-head-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-head-table.hh
@@ -54,6 +54,18 @@ struct head
return 16 <= upem && upem <= 16384 ? upem : 1000;
}
+ bool serialize (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace ((bool) c->embed (this));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ return_trace (serialize (c->serializer));
+ }
+
enum mac_style_flag_t {
BOLD = 1u<<0,
ITALIC = 1u<<1,
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hhea-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hhea-table.hh
index 778b6c51323..d9c9bd35377 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hhea-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hhea-table.hh
@@ -54,35 +54,38 @@ struct _hea
}
public:
- FixedVersion<>version; /* 0x00010000u for version 1.0. */
- FWORD ascender; /* Typographic ascent. */
- FWORD descender; /* Typographic descent. */
- FWORD lineGap; /* Typographic line gap. */
- UFWORD advanceMax; /* Maximum advance width/height value in
- * metrics table. */
- FWORD minLeadingBearing; /* Minimum left/top sidebearing value in
- * metrics table. */
- FWORD minTrailingBearing; /* Minimum right/bottom sidebearing value;
- * calculated as Min(aw - lsb -
- * (xMax - xMin)) for horizontal. */
- FWORD maxExtent; /* horizontal: Max(lsb + (xMax - xMin)),
- * vertical: minLeadingBearing+(yMax-yMin). */
- HBINT16 caretSlopeRise; /* Used to calculate the slope of the
- * cursor (rise/run); 1 for vertical caret,
- * 0 for horizontal.*/
- HBINT16 caretSlopeRun; /* 0 for vertical caret, 1 for horizontal. */
- HBINT16 caretOffset; /* The amount by which a slanted
- * highlight on a glyph needs
- * to be shifted to produce the
- * best appearance. Set to 0 for
- * non-slanted fonts. */
- HBINT16 reserved1; /* Set to 0. */
- HBINT16 reserved2; /* Set to 0. */
- HBINT16 reserved3; /* Set to 0. */
- HBINT16 reserved4; /* Set to 0. */
- HBINT16 metricDataFormat; /* 0 for current format. */
- HBUINT16 numberOfLongMetrics; /* Number of LongMetric entries in metric
- * table. */
+ FixedVersion<>version; /* 0x00010000u for version 1.0. */
+ FWORD ascender; /* Typographic ascent. */
+ FWORD descender; /* Typographic descent. */
+ FWORD lineGap; /* Typographic line gap. */
+ UFWORD advanceMax; /* Maximum advance width/height value in
+ * metrics table. */
+ FWORD minLeadingBearing;
+ /* Minimum left/top sidebearing value in
+ * metrics table. */
+ FWORD minTrailingBearing;
+ /* Minimum right/bottom sidebearing value;
+ * calculated as Min(aw - lsb -
+ * (xMax - xMin)) for horizontal. */
+ FWORD maxExtent; /* horizontal: Max(lsb + (xMax - xMin)),
+ * vertical: minLeadingBearing+(yMax-yMin). */
+ HBINT16 caretSlopeRise; /* Used to calculate the slope of the
+ * cursor (rise/run); 1 for vertical caret,
+ * 0 for horizontal.*/
+ HBINT16 caretSlopeRun; /* 0 for vertical caret, 1 for horizontal. */
+ HBINT16 caretOffset; /* The amount by which a slanted
+ * highlight on a glyph needs
+ * to be shifted to produce the
+ * best appearance. Set to 0 for
+ * non-slanted fonts. */
+ HBINT16 reserved1; /* Set to 0. */
+ HBINT16 reserved2; /* Set to 0. */
+ HBINT16 reserved3; /* Set to 0. */
+ HBINT16 reserved4; /* Set to 0. */
+ HBINT16 metricDataFormat;/* 0 for current format. */
+ HBUINT16 numberOfLongMetrics;
+ /* Number of LongMetric entries in metric
+ * table. */
public:
DEFINE_SIZE_STATIC (36);
};
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 e20b3726226..413774284f1 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
@@ -169,7 +169,7 @@ struct hmtxvmtx
num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics;
- table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
+ table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
/* Cap num_metrics() and num_advances() based on table length. */
unsigned int len = table.get_length ();
@@ -186,7 +186,7 @@ struct hmtxvmtx
table = hb_blob_get_empty ();
}
- var_table = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag);
+ var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
}
void fini ()
@@ -216,7 +216,7 @@ struct hmtxvmtx
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 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
@@ -250,7 +250,7 @@ struct hmtxvmtx
return advance;
if (var_table.get_length ())
- return advance + roundf (var_table->get_advance_var (font, glyph)); // TODO Optimize?!
+ return advance + roundf (var_table->get_advance_var (glyph, font)); // TODO Optimize?!
return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
#else
@@ -295,27 +295,29 @@ struct hmtxvmtx
};
protected:
- UnsizedArrayOf<LongMetric>longMetricZ;/* Paired advance width and leading
- * bearing values for each glyph. The
- * value numOfHMetrics comes from
- * the 'hhea' table. If the font is
- * monospaced, only one entry need
- * be in the array, but that entry is
- * required. The last entry applies to
- * all subsequent glyphs. */
-/*UnsizedArrayOf<FWORD> leadingBearingX;*//* Here the advance is assumed
- * to be the same as the advance
- * for the last entry above. The
- * number of entries in this array is
- * derived from numGlyphs (from 'maxp'
- * table) minus numberOfLongMetrics.
- * This generally is used with a run
- * of monospaced glyphs (e.g., Kanji
- * fonts or Courier fonts). Only one
- * run is allowed and it must be at
- * the end. This allows a monospaced
- * font to vary the side bearing
- * values for each glyph. */
+ UnsizedArrayOf<LongMetric>
+ longMetricZ; /* Paired advance width and leading
+ * bearing values for each glyph. The
+ * value numOfHMetrics comes from
+ * the 'hhea' table. If the font is
+ * monospaced, only one entry need
+ * be in the array, but that entry is
+ * required. The last entry applies to
+ * all subsequent glyphs. */
+/*UnsizedArrayOf<FWORD> leadingBearingX;*/
+ /* Here the advance is assumed
+ * to be the same as the advance
+ * for the last entry above. The
+ * number of entries in this array is
+ * derived from numGlyphs (from 'maxp'
+ * table) minus numberOfLongMetrics.
+ * This generally is used with a run
+ * of monospaced glyphs (e.g., Kanji
+ * fonts or Courier fonts). Only one
+ * run is allowed and it must be at
+ * the end. This allows a monospaced
+ * font to vary the side bearing
+ * values for each glyph. */
public:
DEFINE_SIZE_ARRAY (0, longMetricZ);
};
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 36e5a358e6a..3563cab8bd8 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
@@ -86,21 +86,26 @@ struct KernSubTableFormat3
}
protected:
- KernSubTableHeader header;
- HBUINT16 glyphCount; /* The number of glyphs in this font. */
- HBUINT8 kernValueCount; /* The number of kerning values. */
- HBUINT8 leftClassCount; /* The number of left-hand classes. */
- HBUINT8 rightClassCount;/* The number of right-hand classes. */
- HBUINT8 flags; /* Set to zero (reserved for future use). */
- UnsizedArrayOf<FWORD> kernValueZ; /* The kerning values.
- * Length kernValueCount. */
+ KernSubTableHeader
+ header;
+ HBUINT16 glyphCount; /* The number of glyphs in this font. */
+ HBUINT8 kernValueCount; /* The number of kerning values. */
+ HBUINT8 leftClassCount; /* The number of left-hand classes. */
+ HBUINT8 rightClassCount;/* The number of right-hand classes. */
+ HBUINT8 flags; /* Set to zero (reserved for future use). */
+ UnsizedArrayOf<FWORD>
+ kernValueZ; /* The kerning values.
+ * Length kernValueCount. */
#if 0
- UnsizedArrayOf<HBUINT8>leftClass; /* The left-hand classes.
- * Length glyphCount. */
- UnsizedArrayOf<HBUINT8>rightClass; /* The right-hand classes.
- * Length glyphCount. */
- UnsizedArrayOf<HBUINT8>kernIndex; /* The indices into the kernValue array.
- * Length leftClassCount * rightClassCount */
+ UnsizedArrayOf<HBUINT8>
+ leftClass; /* The left-hand classes.
+ * Length glyphCount. */
+ UnsizedArrayOf<HBUINT8>
+ rightClass; /* The right-hand classes.
+ * Length glyphCount. */
+ UnsizedArrayOf<HBUINT8>kernIndex;
+ /* The indices into the kernValue array.
+ * Length leftClassCount * rightClassCount */
#endif
public:
DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
@@ -246,8 +251,8 @@ struct KernAATSubTableHeader
HBUINT8 coverage; /* Coverage bits. */
HBUINT8 format; /* Subtable format. */
HBUINT16 tupleIndex; /* The tuple index (used for variations fonts).
- * This value specifies which tuple this subtable covers.
- * Note: We don't implement. */
+ * This value specifies which tuple this subtable covers.
+ * Note: We don't implement. */
public:
DEFINE_SIZE_STATIC (8);
};
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 fa08140f565..68ad17a2314 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
@@ -60,6 +60,18 @@
#define HB_MAX_LANGSYS 2000
#endif
+#ifndef HB_MAX_FEATURES
+#define HB_MAX_FEATURES 750
+#endif
+
+#ifndef HB_MAX_FEATURE_INDICES
+#define HB_MAX_FEATURE_INDICES 1500
+#endif
+
+#ifndef HB_MAX_LOOKUP_INDICES
+#define HB_MAX_LOOKUP_INDICES 20000
+#endif
+
namespace OT {
@@ -73,48 +85,130 @@ static inline void Coverage_serialize (hb_serialize_context_t *c,
template<typename Iterator>
static inline void ClassDef_serialize (hb_serialize_context_t *c,
- Iterator it);
+ 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*/);
+ const hb_set_t &glyphset,
+ const hb_map_t &gid_klass_map,
+ hb_sorted_vector_t<HBGlyphID> &glyphs,
+ const hb_set_t &klasses,
+ hb_map_t *klass_map /*INOUT*/);
+
+struct hb_subset_layout_context_t :
+ hb_dispatch_context_t<hb_subset_layout_context_t, hb_empty_t, HB_DEBUG_SUBSET>
+{
+ const char *get_name () { return "SUBSET_LAYOUT"; }
+ static return_t default_return_value () { return hb_empty_t (); }
+
+ bool visitScript ()
+ {
+ return script_count++ < HB_MAX_SCRIPTS;
+ }
+
+ bool visitLangSys ()
+ {
+ return langsys_count++ < HB_MAX_LANGSYS;
+ }
+ bool visitFeatureIndex (int count)
+ {
+ feature_index_count += count;
+ return feature_index_count < HB_MAX_FEATURE_INDICES;
+ }
+
+ bool visitLookupIndex()
+ {
+ lookup_index_count++;
+ return lookup_index_count < HB_MAX_LOOKUP_INDICES;
+ }
+
+ hb_subset_context_t *subset_context;
+ const hb_tag_t table_tag;
+ const hb_map_t *lookup_index_map;
+ const hb_map_t *feature_index_map;
+ unsigned debug_depth;
+
+ hb_subset_layout_context_t (hb_subset_context_t *c_,
+ hb_tag_t tag_,
+ hb_map_t *lookup_map_,
+ hb_map_t *feature_map_) :
+ subset_context (c_),
+ table_tag (tag_),
+ lookup_index_map (lookup_map_),
+ feature_index_map (feature_map_),
+ debug_depth (0),
+ script_count (0),
+ langsys_count (0),
+ feature_index_count (0),
+ lookup_index_count (0)
+ {}
+
+ private:
+ unsigned script_count;
+ unsigned langsys_count;
+ unsigned feature_index_count;
+ unsigned lookup_index_count;
+};
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) {}
+ subset_offset_array_t (hb_subset_context_t *subset_context_,
+ OutputArray& out_,
+ const void *base_) : subset_context (subset_context_),
+ out (out_), base (base_) {}
template <typename T>
- bool
- operator ()
- (T&& offset)
+ bool operator () (T&& offset)
{
- auto *o = _out.serialize_append (_subset_context->serializer);
+ 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);
+ auto snap = subset_context->serializer->snapshot ();
+ bool ret = o->serialize_subset (subset_context, offset, base);
if (!ret)
{
- _out.pop ();
- _subset_context->serializer->revert (snap);
+ 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;
+ hb_subset_context_t *subset_context;
+ OutputArray &out;
+ const void *base;
+};
+
+
+template<typename OutputArray, typename Arg>
+struct subset_offset_array_arg_t
+{
+ subset_offset_array_arg_t (hb_subset_context_t *subset_context_,
+ OutputArray& out_,
+ const void *base_,
+ Arg &&arg_) : subset_context (subset_context_), out (out_),
+ base (base_), arg (arg_) {}
+
+ 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, base, arg);
+ if (!ret)
+ {
+ out.pop ();
+ subset_context->serializer->revert (snap);
+ }
+ return ret;
+ }
+
+ private:
+ hb_subset_context_t *subset_context;
+ OutputArray &out;
+ const void *base;
+ Arg &&arg;
};
/*
@@ -126,16 +220,55 @@ 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
+ operator () (hb_subset_context_t *subset_context, OutputArray& out,
+ const void *base) const
+ { return subset_offset_array_t<OutputArray> (subset_context, out, base); }
+
+ /* Variant with one extra argument passed to serialize_subset */
+ template<typename OutputArray, typename Arg>
+ subset_offset_array_arg_t<OutputArray, Arg>
+ operator () (hb_subset_context_t *subset_context, OutputArray& out,
+ const void *base, Arg &&arg) const
+ { return subset_offset_array_arg_t<OutputArray, Arg> (subset_context, out, base, arg); }
+}
+HB_FUNCOBJ (subset_offset_array);
+
+template<typename OutputArray>
+struct subset_record_array_t
+{
+ subset_record_array_t (hb_subset_layout_context_t *c_, OutputArray* out_,
+ const void *base_) : subset_layout_context (c_),
+ out (out_), base (base_) {}
+
+ template <typename T>
+ void
+ operator () (T&& record)
{
- return subset_offset_array_t<OutputArray> (subset_context, out, src_base, dest_base);
+ auto snap = subset_layout_context->subset_context->serializer->snapshot ();
+ bool ret = record.subset (subset_layout_context, base);
+ if (!ret) subset_layout_context->subset_context->serializer->revert (snap);
+ else out->len++;
}
+
+ private:
+ hb_subset_layout_context_t *subset_layout_context;
+ OutputArray *out;
+ const void *base;
+};
+
+/*
+ * Helper to subset a RecordList/record array. Subsets each Record in the array and
+ * discards the record if the subset operation returns false.
+ */
+struct
+{
+ template<typename OutputArray>
+ subset_record_array_t<OutputArray>
+ operator () (hb_subset_layout_context_t *c, OutputArray* out,
+ const void *base) const
+ { return subset_record_array_t<OutputArray> (c, out, base); }
}
-HB_FUNCOBJ (subset_offset_array);
+HB_FUNCOBJ (subset_record_array);
/*
*
@@ -153,31 +286,20 @@ 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
{
int cmp (hb_tag_t a) const { return tag.cmp (a); }
+ bool subset (hb_subset_layout_context_t *c, const void *base) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->subset_context->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+ bool ret = out->offset.serialize_subset (c->subset_context, offset, base, c, &tag);
+ return_trace (ret);
+ }
+
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -226,29 +348,16 @@ struct RecordListOf : RecordArrayOf<Type>
const Type& operator [] (unsigned int i) const
{ return this+this->get_offset (i); }
- bool subset (hb_subset_context_t *c) const
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
if (unlikely (!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++)
- {
- 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);
- }
-
+ + this->iter ()
+ | hb_apply (subset_record_array (l, out, this))
+ ;
return_trace (true);
}
@@ -259,11 +368,31 @@ struct RecordListOf : RecordArrayOf<Type>
}
};
+struct Feature;
+
+struct RecordListOfFeature : RecordListOf<Feature>
+{
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ unsigned count = this->len;
+ + hb_zip (*this, hb_range (count))
+ | hb_filter (l->feature_index_map, hb_second)
+ | hb_map (hb_first)
+ | hb_apply (subset_record_array (l, out, this))
+ ;
+ return_trace (true);
+ }
+};
struct RangeRecord
{
int cmp (hb_codepoint_t g) const
- { return g < start ? -1 : g <= end ? 0 : +1; }
+ { return g < first ? -1 : g <= last ? 0 : +1; }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -272,14 +401,14 @@ struct RangeRecord
}
bool intersects (const hb_set_t *glyphs) const
- { return glyphs->intersects (start, end); }
+ { return glyphs->intersects (first, last); }
template <typename set_t>
- bool add_coverage (set_t *glyphs) const
- { return glyphs->add_range (start, end); }
+ bool collect_coverage (set_t *glyphs) const
+ { return glyphs->add_range (first, last); }
- HBGlyphID start; /* First GlyphID in the range */
- HBGlyphID end; /* Last GlyphID in the range */
+ HBGlyphID first; /* First GlyphID in the range */
+ HBGlyphID last; /* Last GlyphID in the range */
HBUINT16 value; /* Value */
public:
DEFINE_SIZE_STATIC (6);
@@ -289,6 +418,29 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
struct IndexArray : ArrayOf<Index>
{
+ bool intersects (const hb_map_t *indexes) const
+ { return hb_any (*this, indexes); }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ hb_subset_layout_context_t *l,
+ Iterator it)
+ {
+ if (!it) return;
+ if (unlikely (!c->extend_min ((*this)))) return;
+
+ for (const auto _ : it)
+ {
+ if (!l->visitLookupIndex()) break;
+
+ Index i;
+ i = _;
+ c->copy (i);
+ this->len++;
+ }
+ }
+
unsigned int get_indexes (unsigned int start_offset,
unsigned int *_count /* IN/OUT */,
unsigned int *_indexes /* OUT */) const
@@ -309,10 +461,6 @@ struct IndexArray : ArrayOf<Index>
};
-struct Script;
-struct LangSys;
-struct Feature;
-
struct LangSys
{
unsigned int get_feature_count () const
@@ -340,6 +488,42 @@ struct LangSys
return_trace (c->embed (*this));
}
+ bool operator == (const LangSys& o) const
+ {
+ if (featureIndex.len != o.featureIndex.len ||
+ reqFeatureIndex != o.reqFeatureIndex)
+ return false;
+
+ for (const auto _ : + hb_zip (featureIndex, o.featureIndex))
+ if (_.first != _.second) return false;
+
+ return true;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l,
+ const Tag *tag = nullptr) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex) ? l->feature_index_map->get (reqFeatureIndex) : 0xFFFFu;
+
+ if (!l->visitFeatureIndex (featureIndex.len))
+ return_trace (false);
+
+ auto it =
+ + hb_iter (featureIndex)
+ | hb_filter (l->feature_index_map)
+ | hb_map (l->feature_index_map)
+ ;
+
+ bool ret = bool (it);
+ out->featureIndex.serialize (c->serializer, l, it);
+ return_trace (ret);
+ }
+
bool sanitize (hb_sanitize_context_t *c,
const Record_sanitize_closure_t * = nullptr) const
{
@@ -379,34 +563,46 @@ 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, RecordList_subset_context_t *record_list_context) const
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l,
+ const Tag *tag) const
{
TRACE_SUBSET (this);
- if (!record_list_context->visitScript ()) return_trace (false);
+ if (!l->visitScript ()) return_trace (false);
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
- out->defaultLangSys.serialize_copy (c->serializer, defaultLangSys, this, out);
-
- for (const auto &src: langSys)
+ bool defaultLang = false;
+ if (has_default_lang_sys ())
{
- if (!record_list_context->visitLangSys ()) {
- continue;
+ c->serializer->push ();
+ const LangSys& ls = this+defaultLangSys;
+ bool ret = ls.subset (c, l);
+ if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
+ {
+ c->serializer->pop_discard ();
+ out->defaultLangSys = 0;
}
-
- 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))
+ else
{
- out->langSys.len++;
- continue;
+ c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
+ defaultLang = true;
}
- c->serializer->revert (snap);
}
- return_trace (true);
+
+ + langSys.iter ()
+ | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
+ | hb_filter ([&] (const Record<LangSys>& record)
+ {
+ const LangSys& d = this+defaultLangSys;
+ const LangSys& l = this+record.offset;
+ return !(l == d);
+ })
+ | hb_apply (subset_record_array (l, &(out->langSys), this))
+ ;
+
+ return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
}
bool sanitize (hb_sanitize_context_t *c,
@@ -682,13 +878,27 @@ struct Feature
const FeatureParams &get_feature_params () const
{ return this+featureParams; }
- bool subset (hb_subset_context_t *c, RecordList_subset_context_t *r) const
+ bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
+ { return lookupIndex.intersects (lookup_indexes); }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l,
+ const Tag *tag = nullptr) 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 (!out || !c->serializer->extend_min (out))) return_trace (false);
+
out->featureParams = 0; /* TODO(subset) FeatureParams. */
- return_trace (true);
+
+ auto it =
+ + hb_iter (lookupIndex)
+ | hb_filter (l->lookup_index_map)
+ | hb_map (l->lookup_index_map)
+ ;
+
+ out->lookupIndex.serialize (c->serializer, l, it);
+ return_trace (bool (it) || (tag && *tag == HB_TAG ('p', 'r', 'e', 'f')));
}
bool sanitize (hb_sanitize_context_t *c,
@@ -775,10 +985,10 @@ struct Lookup
template <typename TSubTable>
const OffsetArrayOf<TSubTable>& get_subtables () const
- { return CastR<OffsetArrayOf<TSubTable>> (subTable); }
+ { return reinterpret_cast<const OffsetArrayOf<TSubTable> &> (subTable); }
template <typename TSubTable>
OffsetArrayOf<TSubTable>& get_subtables ()
- { return CastR<OffsetArrayOf<TSubTable>> (subTable); }
+ { return reinterpret_cast<OffsetArrayOf<TSubTable> &> (subTable); }
template <typename TSubTable>
const TSubTable& get_subtable (unsigned int i) const
@@ -848,17 +1058,17 @@ struct Lookup
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 (!out || !c->serializer->extend_min (out))) return_trace (false);
+ out->lookupType = lookupType;
+ out->lookupFlag = lookupFlag;
- /* Subset the actual subtables. */
- /* TODO Drop empty ones, either by calling intersects() beforehand,
- * or just dropping null offsets after. */
- const OffsetArrayOf<TSubTable>& subtables = get_subtables<TSubTable> ();
- OffsetArrayOf<TSubTable>& out_subtables = out->get_subtables<TSubTable> ();
- unsigned int count = subTable.len;
- for (unsigned int i = 0; i < count; i++)
- out_subtables[i].serialize_subset (c, subtables[i], this, out, get_type ());
+ const hb_set_t *glyphset = c->plan->glyphset ();
+ unsigned int lookup_type = get_type ();
+ + hb_iter (get_subtables <TSubTable> ())
+ | hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
+ | hb_apply (subset_offset_array (c, out->get_subtables<TSubTable> (), this, lookup_type))
+ ;
return_trace (true);
}
@@ -868,6 +1078,10 @@ struct Lookup
{
TRACE_SANITIZE (this);
if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
+
+ unsigned subtables = get_subtable_count ();
+ if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
+
if (lookupFlag & LookupFlag::UseMarkFilteringSet)
{
const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
@@ -890,8 +1104,7 @@ struct Lookup
* https://bugs.chromium.org/p/chromium/issues/detail?id=960331
*/
unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
- unsigned int count = get_subtable_count ();
- for (unsigned int i = 1; i < count; i++)
+ for (unsigned int i = 1; i < subtables; i++)
if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
return_trace (false);
}
@@ -912,6 +1125,32 @@ struct Lookup
typedef OffsetListOf<Lookup> LookupList;
+template <typename TLookup>
+struct LookupOffsetList : OffsetListOf<TLookup>
+{
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ unsigned count = this->len;
+ + hb_zip (*this, hb_range (count))
+ | hb_filter (l->lookup_index_map, hb_second)
+ | hb_map (hb_first)
+ | hb_apply (subset_offset_array (c, *out, this))
+ ;
+ return_trace (true);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (OffsetListOf<TLookup>::sanitize (c, this));
+ }
+};
+
/*
* Coverage Table
@@ -956,7 +1195,7 @@ struct CoverageFormat1
{ return glyphs->has (glyphArray[index]); }
template <typename set_t>
- bool add_coverage (set_t *glyphs) const
+ bool collect_coverage (set_t *glyphs) const
{ return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len); }
public:
@@ -993,8 +1232,8 @@ struct CoverageFormat2
unsigned int get_coverage (hb_codepoint_t glyph_id) const
{
const RangeRecord &range = rangeRecord.bsearch (glyph_id);
- return likely (range.start <= range.end) ?
- (unsigned int) range.value + (glyph_id - range.start) :
+ return likely (range.first <= range.last) ?
+ (unsigned int) range.value + (glyph_id - range.first) :
NOT_COVERED;
}
@@ -1032,10 +1271,10 @@ struct CoverageFormat2
if (last + 1 != g)
{
range++;
- rangeRecord[range].start = g;
+ rangeRecord[range].first = g;
rangeRecord[range].value = count;
}
- rangeRecord[range].end = g;
+ rangeRecord[range].last = g;
last = g;
count++;
}
@@ -1065,7 +1304,7 @@ struct CoverageFormat2
for (i = 0; i < count; i++) {
const RangeRecord &range = rangeRecord[i];
if (range.value <= index &&
- index < (unsigned int) range.value + (range.end - range.start) &&
+ index < (unsigned int) range.value + (range.last - range.first) &&
range.intersects (glyphs))
return true;
else if (index < range.value)
@@ -1075,11 +1314,11 @@ struct CoverageFormat2
}
template <typename set_t>
- bool add_coverage (set_t *glyphs) const
+ bool collect_coverage (set_t *glyphs) const
{
unsigned int count = rangeRecord.len;
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+ if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
return false;
return true;
}
@@ -1093,8 +1332,8 @@ struct CoverageFormat2
c = &c_;
coverage = 0;
i = 0;
- j = c->rangeRecord.len ? c->rangeRecord[0].start : 0;
- if (unlikely (c->rangeRecord[0].start > c->rangeRecord[0].end))
+ j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
+ if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
{
/* Broken table. Skip. */
i = c->rangeRecord.len;
@@ -1104,13 +1343,13 @@ struct CoverageFormat2
bool more () const { return i < c->rangeRecord.len; }
void next ()
{
- if (j >= c->rangeRecord[i].end)
+ if (j >= c->rangeRecord[i].last)
{
i++;
if (more ())
{
unsigned int old = coverage;
- j = c->rangeRecord[i].start;
+ j = c->rangeRecord[i].first;
coverage = c->rangeRecord[i].value;
if (unlikely (coverage != old + 1))
{
@@ -1246,12 +1485,12 @@ struct Coverage
/* Might return false if array looks unsorted.
* Used for faster rejection of corrupt data. */
template <typename set_t>
- bool add_coverage (set_t *glyphs) const
+ bool collect_coverage (set_t *glyphs) const
{
switch (u.format)
{
- case 1: return u.format1.add_coverage (glyphs);
- case 2: return u.format2.add_coverage (glyphs);
+ case 1: return u.format1.collect_coverage (glyphs);
+ case 2: return u.format2.collect_coverage (glyphs);
default:return false;
}
}
@@ -1259,7 +1498,7 @@ struct Coverage
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
{
static constexpr bool is_sorted_iterator = true;
- iter_t (const Coverage &c_ = Null(Coverage))
+ iter_t (const Coverage &c_ = Null (Coverage))
{
memset (this, 0, sizeof (*this));
format = c_.u.format;
@@ -1333,22 +1572,28 @@ struct Coverage
template<typename Iterator>
static inline void
Coverage_serialize (hb_serialize_context_t *c,
- Iterator it)
+ 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*/)
+ const hb_set_t &glyphset,
+ const hb_map_t &gid_klass_map,
+ hb_sorted_vector_t<HBGlyphID> &glyphs,
+ const hb_set_t &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 (!klass_map)
+ {
+ ClassDef_serialize (c, hb_zip (glyphs.iter (), + glyphs.iter ()
+ | hb_map (gid_klass_map)));
+ return;
+ }
+
+ /* any glyph not assigned a class value falls into Class zero (0),
+ * if any glyph assigned to class 0, remapping must start with 0->0*/
+ if (glyphset.get_population () > gid_klass_map.get_population ())
+ klass_map->set (0, 0);
- if (has_no_match) klass_map->set (0, 0);
unsigned idx = klass_map->has (0) ? 1 : 0;
for (const unsigned k: klasses.iter ())
{
@@ -1356,17 +1601,16 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
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);
- })
+ | hb_map_retains_sorting ([&] (const HBGlyphID& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
+ {
+ unsigned 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);
}
@@ -1388,7 +1632,7 @@ struct ClassDefFormat1
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool serialize (hb_serialize_context_t *c,
- Iterator it)
+ Iterator it)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
@@ -1400,21 +1644,31 @@ struct ClassDefFormat1
return_trace (true);
}
- startGlyph = (*it).first;
- classValue.serialize (c, + it
- | hb_map (hb_second));
+ hb_codepoint_t glyph_min = (*it).first;
+ hb_codepoint_t glyph_max = + it
+ | hb_map (hb_first)
+ | hb_reduce (hb_max, 0u);
+ unsigned glyph_count = glyph_max - glyph_min + 1;
+
+ startGlyph = glyph_min;
+ if (unlikely (!classValue.serialize (c, glyph_count))) return_trace (false);
+ for (const hb_pair_t<hb_codepoint_t, unsigned>& gid_klass_pair : + it)
+ {
+ unsigned idx = gid_klass_pair.first - glyph_min;
+ classValue[idx] = gid_klass_pair.second;
+ }
return_trace (true);
}
bool subset (hb_subset_context_t *c,
- hb_map_t *klass_map = nullptr /*OUT*/) const
+ hb_map_t *klass_map = nullptr /*OUT*/) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
const hb_map_t &glyph_map = *c->plan->glyph_map;
-
+
hb_sorted_vector_t<HBGlyphID> glyphs;
- hb_sorted_vector_t<unsigned> orig_klasses;
+ hb_set_t orig_klasses;
hb_map_t gid_org_klass_map;
hb_codepoint_t start = startGlyph;
@@ -1427,11 +1681,11 @@ struct ClassDefFormat1
glyphs.push (glyph_map[gid]);
gid_org_klass_map.set (glyph_map[gid], klass);
- orig_klasses.push (klass);
+ orig_klasses.add (klass);
}
ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map,
- glyphs, orig_klasses, klass_map);
+ glyphs, orig_klasses, klass_map);
return_trace ((bool) glyphs);
}
@@ -1442,7 +1696,7 @@ struct ClassDefFormat1
}
template <typename set_t>
- bool add_coverage (set_t *glyphs) const
+ bool collect_coverage (set_t *glyphs) const
{
unsigned int start = 0;
unsigned int count = classValue.len;
@@ -1465,7 +1719,7 @@ struct ClassDefFormat1
}
template <typename set_t>
- bool add_class (set_t *glyphs, unsigned int klass) const
+ bool collect_class (set_t *glyphs, unsigned int klass) const
{
unsigned int count = classValue.len;
for (unsigned int i = 0; i < count; i++)
@@ -1524,7 +1778,7 @@ struct ClassDefFormat2
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool serialize (hb_serialize_context_t *c,
- Iterator it)
+ Iterator it)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
@@ -1540,8 +1794,8 @@ struct ClassDefFormat2
unsigned prev_klass = (*it).second;
RangeRecord range_rec;
- range_rec.start = prev_gid;
- range_rec.end = prev_gid;
+ range_rec.first = prev_gid;
+ range_rec.last = prev_gid;
range_rec.value = prev_klass;
RangeRecord *record = c->copy (range_rec);
@@ -1553,37 +1807,37 @@ struct ClassDefFormat2
unsigned cur_klass = gid_klass_pair.second;
if (cur_gid != prev_gid + 1 ||
- cur_klass != prev_klass)
+ cur_klass != prev_klass)
{
- if (unlikely (!record)) break;
- record->end = prev_gid;
- num_ranges++;
+ if (unlikely (!record)) break;
+ record->last = prev_gid;
+ num_ranges++;
- range_rec.start = cur_gid;
- range_rec.end = cur_gid;
- range_rec.value = cur_klass;
+ range_rec.first = cur_gid;
+ range_rec.last = cur_gid;
+ range_rec.value = cur_klass;
- record = c->copy (range_rec);
+ record = c->copy (range_rec);
}
prev_klass = cur_klass;
prev_gid = cur_gid;
}
- if (likely (record)) record->end = prev_gid;
+ if (likely (record)) record->last = prev_gid;
rangeRecord.len = num_ranges;
return_trace (true);
}
bool subset (hb_subset_context_t *c,
- hb_map_t *klass_map = nullptr /*OUT*/) const
+ hb_map_t *klass_map = nullptr /*OUT*/) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
const hb_map_t &glyph_map = *c->plan->glyph_map;
hb_sorted_vector_t<HBGlyphID> glyphs;
- hb_sorted_vector_t<unsigned> orig_klasses;
+ hb_set_t orig_klasses;
hb_map_t gid_org_klass_map;
unsigned count = rangeRecord.len;
@@ -1591,19 +1845,19 @@ struct ClassDefFormat2
{
unsigned klass = rangeRecord[i].value;
if (!klass) continue;
- hb_codepoint_t start = rangeRecord[i].start;
- hb_codepoint_t end = rangeRecord[i].end + 1;
+ hb_codepoint_t start = rangeRecord[i].first;
+ hb_codepoint_t end = rangeRecord[i].last + 1;
for (hb_codepoint_t g = start; g < end; g++)
{
if (!glyphset.has (g)) continue;
glyphs.push (glyph_map[g]);
- gid_org_klass_map.set (glyph_map[g], klass);
- orig_klasses.push (klass);
+ gid_org_klass_map.set (glyph_map[g], klass);
+ orig_klasses.add (klass);
}
}
ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map,
- glyphs, orig_klasses, klass_map);
+ glyphs, orig_klasses, klass_map);
return_trace ((bool) glyphs);
}
@@ -1614,24 +1868,24 @@ struct ClassDefFormat2
}
template <typename set_t>
- bool add_coverage (set_t *glyphs) const
+ bool collect_coverage (set_t *glyphs) const
{
unsigned int count = rangeRecord.len;
for (unsigned int i = 0; i < count; i++)
if (rangeRecord[i].value)
- if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+ if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
return false;
return true;
}
template <typename set_t>
- bool add_class (set_t *glyphs, unsigned int klass) const
+ bool collect_class (set_t *glyphs, unsigned int klass) const
{
unsigned int count = rangeRecord.len;
for (unsigned int i = 0; i < count; i++)
{
if (rangeRecord[i].value == klass)
- if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+ if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
return false;
}
return true;
@@ -1657,9 +1911,9 @@ struct ClassDefFormat2
{
if (!hb_set_next (glyphs, &g))
break;
- if (g < rangeRecord[i].start)
+ if (g < rangeRecord[i].first)
return true;
- g = rangeRecord[i].end;
+ g = rangeRecord[i].last;
}
if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
return true;
@@ -1713,7 +1967,7 @@ struct ClassDef
hb_codepoint_t glyph_min = (*it).first;
hb_codepoint_t glyph_max = + it
| hb_map (hb_first)
- | hb_reduce (hb_max, 0u);
+ | hb_reduce (hb_max, 0u);
unsigned num_ranges = 1;
hb_codepoint_t prev_gid = glyph_min;
@@ -1721,17 +1975,18 @@ struct ClassDef
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;
+ hb_codepoint_t cur_gid = gid_klass_pair.first;
+ unsigned cur_klass = gid_klass_pair.second;
+ if (cur_gid == glyph_min || !cur_klass) continue;
+ 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)
+ if (1 + (glyph_max - glyph_min + 1) <= num_ranges * 3)
format = 1;
}
u.format = format;
@@ -1745,7 +2000,7 @@ struct ClassDef
}
bool subset (hb_subset_context_t *c,
- hb_map_t *klass_map = nullptr /*OUT*/) const
+ hb_map_t *klass_map = nullptr /*OUT*/) const
{
TRACE_SUBSET (this);
switch (u.format) {
@@ -1769,11 +2024,11 @@ struct ClassDef
/* Might return false if array looks unsorted.
* Used for faster rejection of corrupt data. */
template <typename set_t>
- bool add_coverage (set_t *glyphs) const
+ bool collect_coverage (set_t *glyphs) const
{
switch (u.format) {
- case 1: return u.format1.add_coverage (glyphs);
- case 2: return u.format2.add_coverage (glyphs);
+ case 1: return u.format1.collect_coverage (glyphs);
+ case 2: return u.format2.collect_coverage (glyphs);
default:return false;
}
}
@@ -1781,11 +2036,11 @@ struct ClassDef
/* Might return false if array looks unsorted.
* Used for faster rejection of corrupt data. */
template <typename set_t>
- bool add_class (set_t *glyphs, unsigned int klass) const
+ bool collect_class (set_t *glyphs, unsigned int klass) const
{
switch (u.format) {
- case 1: return u.format1.add_class (glyphs, klass);
- case 2: return u.format2.add_class (glyphs, klass);
+ case 1: return u.format1.collect_class (glyphs, klass);
+ case 2: return u.format2.collect_class (glyphs, klass);
default:return false;
}
}
@@ -1819,7 +2074,7 @@ struct ClassDef
template<typename Iterator>
static inline void ClassDef_serialize (hb_serialize_context_t *c,
- Iterator it)
+ Iterator it)
{ c->start_embed<ClassDef> ()->serialize (c, it); }
@@ -1906,8 +2161,13 @@ struct VarRegionList
axisCount = src->axisCount;
regionCount = region_map.get_population ();
if (unlikely (!c->allocate_size<VarRegionList> (get_size () - min_size))) return_trace (false);
+ unsigned int region_count = src->get_region_count ();
for (unsigned int r = 0; r < regionCount; r++)
- memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * region_map.backward (r)], VarRegionAxis::static_size * axisCount);
+ {
+ unsigned int backward = region_map.backward (r);
+ if (backward >= region_count) return_trace (false);
+ memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
+ }
return_trace (true);
}
@@ -1967,7 +2227,7 @@ struct VarData
return delta;
}
- void get_scalars (int *coords, unsigned int coord_count,
+ void get_scalars (const int *coords, unsigned int coord_count,
const VarRegionList &regions,
float *scalars /*OUT */,
unsigned int num_scalars) const
@@ -2031,8 +2291,8 @@ struct VarData
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++;
+ ri_map[r] = (delta_sz[r] == kShort)? short_index++ : byte_index++;
+ new_ri_count++;
}
shortCount = new_short_count;
@@ -2145,7 +2405,7 @@ struct VariationStore
bool serialize (hb_serialize_context_t *c,
const VariationStore *src,
- const hb_array_t <hb_inc_bimap_t> &inner_maps)
+ const hb_array_t <hb_inc_bimap_t> &inner_maps)
{
TRACE_SERIALIZE (this);
unsigned int set_count = 0;
@@ -2184,7 +2444,7 @@ struct VariationStore
{ return (this+dataSets[ivs]).get_region_index_count (); }
void get_scalars (unsigned int ivs,
- int *coords, unsigned int coord_count,
+ const int *coords, unsigned int coord_count,
float *scalars /*OUT*/,
unsigned int num_scalars) const
{
@@ -2216,6 +2476,14 @@ struct ConditionFormat1
{
friend struct Condition;
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+ return_trace (true);
+ }
+
private:
bool evaluate (const int *coords, unsigned int coord_len) const
{
@@ -2248,6 +2516,17 @@ struct Condition
}
}
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -2278,6 +2557,18 @@ struct ConditionSet
return true;
}
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ + conditions.iter ()
+ | hb_apply (subset_offset_array (c, out->conditions, this))
+ ;
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -2294,6 +2585,30 @@ struct FeatureTableSubstitutionRecord
{
friend struct FeatureTableSubstitution;
+ void collect_lookups (const void *base, hb_set_t *lookup_indexes /* OUT */) const
+ {
+ return (base+feature).add_lookup_indexes_to (lookup_indexes);
+ }
+
+ void closure_features (const void *base,
+ const hb_map_t *lookup_indexes,
+ hb_set_t *feature_indexes /* OUT */) const
+ {
+ if ((base+feature).intersects_lookup_indexes (lookup_indexes))
+ feature_indexes->add (featureIndex);
+ }
+
+ bool subset (hb_subset_layout_context_t *c, const void *base) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->subset_context->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ out->featureIndex = c->feature_index_map->get (featureIndex);
+ bool ret = out->feature.serialize_subset (c->subset_context, feature, base, c);
+ return_trace (ret);
+ }
+
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -2321,6 +2636,39 @@ struct FeatureTableSubstitution
return nullptr;
}
+ void collect_lookups (const hb_set_t *feature_indexes,
+ hb_set_t *lookup_indexes /* OUT */) const
+ {
+ + hb_iter (substitutions)
+ | hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
+ | hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
+ { r.collect_lookups (this, lookup_indexes); })
+ ;
+ }
+
+ void closure_features (const hb_map_t *lookup_indexes,
+ hb_set_t *feature_indexes /* OUT */) const
+ {
+ for (const FeatureTableSubstitutionRecord& record : substitutions)
+ record.closure_features (this, lookup_indexes, feature_indexes);
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ out->version.major = version.major;
+ out->version.minor = version.minor;
+
+ + substitutions.iter ()
+ | hb_apply (subset_record_array (l, &(out->substitutions), this))
+ ;
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -2341,6 +2689,32 @@ struct FeatureVariationRecord
{
friend struct FeatureVariations;
+ void collect_lookups (const void *base,
+ const hb_set_t *feature_indexes,
+ hb_set_t *lookup_indexes /* OUT */) const
+ {
+ return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
+ }
+
+ void closure_features (const void *base,
+ const hb_map_t *lookup_indexes,
+ hb_set_t *feature_indexes /* OUT */) const
+ {
+ (base+substitutions).closure_features (lookup_indexes, feature_indexes);
+ }
+
+ bool subset (hb_subset_layout_context_t *c, const void *base) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->subset_context->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ out->conditions.serialize_subset (c->subset_context, conditions, base);
+ out->substitutions.serialize_subset (c->subset_context, substitutions, base, c);
+
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -2391,6 +2765,36 @@ struct FeatureVariations
return_trace (c->embed (*this));
}
+ void collect_lookups (const hb_set_t *feature_indexes,
+ hb_set_t *lookup_indexes /* OUT */) const
+ {
+ for (const FeatureVariationRecord& r : varRecords)
+ r.collect_lookups (this, feature_indexes, lookup_indexes);
+ }
+
+ void closure_features (const hb_map_t *lookup_indexes,
+ hb_set_t *feature_indexes /* OUT */) const
+ {
+ for (const FeatureVariationRecord& record : varRecords)
+ record.closure_features (this, lookup_indexes, feature_indexes);
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ out->version.major = version.major;
+ out->version.minor = version.minor;
+
+ + varRecords.iter ()
+ | hb_apply (subset_record_array (l, &(out->varRecords), this))
+ ;
+ return_trace (bool (out->varRecords));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh
index dc751d88ea9..7873f94faaa 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gdef-table.hh
@@ -96,6 +96,13 @@ struct AttachList
struct CaretValueFormat1
{
friend struct CaretValue;
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+ return_trace (true);
+ }
private:
hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
@@ -119,6 +126,13 @@ struct CaretValueFormat1
struct CaretValueFormat2
{
friend struct CaretValue;
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+ return_trace (true);
+ }
private:
hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
@@ -153,6 +167,15 @@ struct CaretValueFormat3
font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
}
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -185,6 +208,19 @@ struct CaretValue
}
}
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
+ case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -229,6 +265,19 @@ struct LigGlyph
return carets.len;
}
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ + hb_iter (carets)
+ | hb_apply (subset_offset_array (c, out->carets, this))
+ ;
+
+ return_trace (bool (out->carets));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -265,6 +314,28 @@ struct LigCaretList
return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
}
+ 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 *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, ligGlyph)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (subset_offset_array (c, out->ligGlyph, this), 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
{
TRACE_SANITIZE (this);
@@ -288,6 +359,34 @@ struct MarkGlyphSetsFormat1
bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
{ return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ bool ret = true;
+ for (const LOffsetTo<Coverage>& offset : coverage.iter ())
+ {
+ auto *o = out->coverage.serialize_append (c->serializer);
+ if (unlikely (!o))
+ {
+ ret = false;
+ break;
+ }
+
+ //not using o->serialize_subset (c, offset, this, out) here because
+ //OTS doesn't allow null offset.
+ //See issue: https://github.com/khaledhosny/ots/issues/172
+ c->serializer->push ();
+ c->dispatch (this+offset);
+ c->serializer->add_link (*o, c->serializer->pop_pack ());
+ }
+
+ return_trace (ret && out->coverage.len);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -313,6 +412,15 @@ struct MarkGlyphSets
}
}
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ switch (u.format) {
+ case 1: return_trace (u.format1.subset (c));
+ default:return_trace (false);
+ }
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -356,7 +464,7 @@ struct GDEF
unsigned int get_glyph_class (hb_codepoint_t glyph) const
{ return (this+glyphClassDef).get_class (glyph); }
void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
- { (this+glyphClassDef).add_class (glyphs, klass); }
+ { (this+glyphClassDef).collect_class (glyphs, klass); }
bool has_mark_attachment_types () const { return markAttachClassDef != 0; }
unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
@@ -386,7 +494,7 @@ struct GDEF
bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; }
const VariationStore &get_var_store () const
- { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
+ { return version.to_int () >= 0x00010003u ? this+varStore : Null (VariationStore); }
/* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
* glyph class and other bits, and high 8-bit the mark attachment type (if any).
@@ -416,7 +524,7 @@ struct GDEF
{
void init (hb_face_t *face)
{
- this->table = hb_sanitize_context_t().reference_table<GDEF> (face);
+ this->table = hb_sanitize_context_t ().reference_table<GDEF> (face);
if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
{
hb_blob_destroy (this->table.get_blob ());
@@ -442,16 +550,20 @@ struct GDEF
auto *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
- out->glyphClassDef.serialize_subset (c, glyphClassDef, this, out);
- out->attachList = 0;//TODO(subset) serialize_subset (c, attachList, this, out);
- out->ligCaretList = 0;//TODO(subset) serialize_subset (c, ligCaretList, this, out);
- out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, out);
+ out->glyphClassDef.serialize_subset (c, glyphClassDef, this);
+ out->attachList = 0;//TODO(subset) serialize_subset (c, attachList, this);
+ out->ligCaretList.serialize_subset (c, ligCaretList, this);
+ out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this);
if (version.to_int () >= 0x00010002u)
- out->markGlyphSetsDef = 0;// TODO(subset) serialize_subset (c, markGlyphSetsDef, this, out);
+ {
+ if (!out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this) &&
+ version.to_int () == 0x00010002u)
+ out->version.minor = 0;
+ }
if (version.to_int () >= 0x00010003u)
- out->varStore = 0;// TODO(subset) serialize_subset (c, varStore, this, out);
+ out->varStore = 0;// TODO(subset) serialize_subset (c, varStore, this);
return_trace (true);
}
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 024312d610c..d55d6ece8e5 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
@@ -34,6 +34,11 @@
namespace OT {
+struct MarkArray;
+static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
+ const MarkArray &mark_array,
+ const hb_set_t &glyphset,
+ hb_map_t* klass_mapping /* INOUT */);
/* buffer **position** var allocations */
#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
@@ -155,6 +160,22 @@ struct ValueFormat : HBUINT16
return ret;
}
+ void serialize_copy (hb_serialize_context_t *c, const void *base, const Value *values) const
+ {
+ unsigned int format = *this;
+ if (!format) return;
+
+ if (format & xPlacement) c->copy (*values++);
+ if (format & yPlacement) c->copy (*values++);
+ if (format & xAdvance) c->copy (*values++);
+ if (format & yAdvance) c->copy (*values++);
+
+ if (format & xPlaDevice) copy_device (c, base, values++);
+ if (format & yPlaDevice) copy_device (c, base, values++);
+ if (format & xAdvDevice) copy_device (c, base, values++);
+ if (format & yAdvDevice) copy_device (c, base, values++);
+ }
+
private:
bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
{
@@ -173,18 +194,41 @@ struct ValueFormat : HBUINT16
return true;
}
- HB_INTERNAL static OffsetTo<Device>& get_device (Value* value)
- { return *CastP<OffsetTo<Device>> (value); }
- HB_INTERNAL static const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
+ bool copy_device (hb_serialize_context_t *c, const void *base, const Value *src_value) const
+ {
+ Value *dst_value = c->copy (*src_value);
+
+ if (!dst_value) return false;
+ if (*dst_value == 0) return true;
+
+ *dst_value = 0;
+ c->push ();
+ if ((base + get_device (src_value)).copy (c))
+ {
+ c->add_link (*dst_value, c->pop_pack ());
+ return true;
+ }
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
+ }
+
+ static inline OffsetTo<Device>& get_device (Value* value)
+ {
+ return *static_cast<OffsetTo<Device> *> (value);
+ }
+ static inline const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
{
if (worked) *worked |= bool (*value);
- return *CastP<OffsetTo<Device>> (value);
+ return *static_cast<const OffsetTo<Device> *> (value);
}
- HB_INTERNAL static const HBINT16& get_short (const Value* value, bool *worked=nullptr)
+ static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
{
if (worked) *worked |= bool (*value);
- return *CastP<HBINT16> (value);
+ return *reinterpret_cast<const HBINT16 *> (value);
}
public:
@@ -237,9 +281,10 @@ struct ValueFormat : HBUINT16
};
template<typename Iterator>
-static inline void SinglePos_serialize (hb_serialize_context_t *c,
- Iterator it,
- ValueFormat valFormat);
+static void SinglePos_serialize (hb_serialize_context_t *c,
+ const void *src,
+ Iterator it,
+ ValueFormat valFormat);
struct AnchorFormat1
@@ -344,8 +389,8 @@ struct AnchorFormat3
auto *out = c->embed<AnchorFormat3> (this);
if (unlikely (!out)) return_trace (nullptr);
- out->xDeviceTable.serialize_copy (c, xDeviceTable, this, out);
- out->yDeviceTable.serialize_copy (c, yDeviceTable, this, out);
+ out->xDeviceTable.serialize_copy (c, xDeviceTable, this);
+ out->yDeviceTable.serialize_copy (c, yDeviceTable, this);
return_trace (out);
}
@@ -420,11 +465,33 @@ struct AnchorMatrix
unsigned int cols, bool *found) const
{
*found = false;
- if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
+ if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
*found = !matrixZ[row * cols + col].is_null ();
return this+matrixZ[row * cols + col];
}
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool serialize (hb_serialize_context_t *c,
+ unsigned num_rows,
+ AnchorMatrix const *offset_matrix,
+ Iterator index_iter)
+ {
+ TRACE_SERIALIZE (this);
+ if (!index_iter.len ()) return_trace (false);
+ if (unlikely (!c->extend_min ((*this)))) return_trace (false);
+
+ this->rows = num_rows;
+ for (const unsigned i : index_iter)
+ {
+ auto *offset = c->embed (offset_matrix->matrixZ[i]);
+ if (!offset) return_trace (false);
+ offset->serialize_copy (c, offset_matrix->matrixZ[i], offset_matrix, c->to_bias (this));
+ }
+
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
{
TRACE_SANITIZE (this);
@@ -438,7 +505,6 @@ struct AnchorMatrix
}
HBUINT16 rows; /* Number of rows */
- protected:
UnsizedArrayOf<OffsetTo<Anchor>>
matrixZ; /* Matrix of offsets to Anchor tables--
* from beginning of AnchorMatrix table */
@@ -451,12 +517,25 @@ struct MarkRecord
{
friend struct MarkArray;
+ unsigned get_class () const { return (unsigned) klass; }
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
}
+ MarkRecord *copy (hb_serialize_context_t *c, const void *base,
+ unsigned dst_bias, const hb_map_t *klass_mapping) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->klass = klass_mapping->get (klass);
+ out->markAnchor.serialize_copy (c, markAnchor, base, dst_bias);
+ return_trace (out);
+ }
+
protected:
HBUINT16 klass; /* Class defined for this mark */
OffsetTo<Anchor>
@@ -502,6 +581,20 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
return_trace (true);
}
+ template<typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, MarkRecord))>
+ bool serialize (hb_serialize_context_t *c,
+ const hb_map_t *klass_mapping,
+ const void *base,
+ Iterator it)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (*this))) return_trace (false);
+ if (unlikely (!c->check_assign (len, it.len ()))) return_trace (false);
+ c->copy_all (it, base, c->to_bias (this), klass_mapping);
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -517,8 +610,10 @@ struct SinglePosFormat1
bool intersects (const hb_set_t *glyphs) const
{ return (this+coverage).intersects (glyphs); }
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
const Coverage &get_coverage () const { return this+coverage; }
@@ -538,14 +633,19 @@ struct SinglePosFormat1
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
+ const void *src,
Iterator it,
ValueFormat valFormat)
{
- if (unlikely (!c->extend_min (*this))) return;
+ auto out = c->extend_min (*this);
+ if (unlikely (!out)) return;
if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
- for (const auto &_ : hb_second (*it))
- c->copy (_);
+ + it
+ | hb_map (hb_second)
+ | hb_apply ([&] (hb_array_t<const Value> _)
+ { valFormat.serialize_copy (c, src, &_); })
+ ;
auto glyphs =
+ it
@@ -569,7 +669,7 @@ struct SinglePosFormat1
;
bool ret = bool (it);
- SinglePos_serialize (c->serializer, it, valueFormat);
+ SinglePos_serialize (c->serializer, this, it, valueFormat);
return_trace (ret);
}
@@ -600,8 +700,10 @@ struct SinglePosFormat2
bool intersects (const hb_set_t *glyphs) const
{ return (this+coverage).intersects (glyphs); }
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
const Coverage &get_coverage () const { return this+coverage; }
@@ -625,16 +727,20 @@ struct SinglePosFormat2
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
+ const void *src,
Iterator it,
ValueFormat valFormat)
{
- if (unlikely (!c->extend_min (*this))) return;
+ auto out = c->extend_min (*this);
+ if (unlikely (!out)) return;
if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
if (unlikely (!c->check_assign (valueCount, it.len ()))) return;
- for (const auto iter : it)
- for (const auto &_ : iter.second)
- c->copy (_);
+ + it
+ | hb_map (hb_second)
+ | hb_apply ([&] (hb_array_t<const Value> _)
+ { valFormat.serialize_copy (c, src, &_); })
+ ;
auto glyphs =
+ it
@@ -665,7 +771,7 @@ struct SinglePosFormat2
;
bool ret = bool (it);
- SinglePos_serialize (c->serializer, it, valueFormat);
+ SinglePos_serialize (c->serializer, this, it, valueFormat);
return_trace (ret);
}
@@ -711,6 +817,7 @@ struct SinglePos
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
+ const void *src,
Iterator glyph_val_iter_pairs,
ValueFormat valFormat)
{
@@ -721,9 +828,9 @@ struct SinglePos
u.format = format;
switch (u.format) {
- case 1: u.format1.serialize (c, glyph_val_iter_pairs, valFormat);
+ case 1: u.format1.serialize (c, src, glyph_val_iter_pairs, valFormat);
return;
- case 2: u.format2.serialize (c, glyph_val_iter_pairs, valFormat);
+ case 2: u.format2.serialize (c, src, glyph_val_iter_pairs, valFormat);
return;
default:return;
}
@@ -750,27 +857,42 @@ struct SinglePos
};
template<typename Iterator>
-static inline void
+static void
SinglePos_serialize (hb_serialize_context_t *c,
+ const void *src,
Iterator it,
ValueFormat valFormat)
-{ c->start_embed<SinglePos> ()->serialize (c, it, valFormat); }
+{ c->start_embed<SinglePos> ()->serialize (c, src, it, valFormat); }
struct PairValueRecord
{
friend struct PairSet;
+ int cmp (hb_codepoint_t k) const
+ { return secondGlyph.cmp (k); }
+
+ struct serialize_closure_t
+ {
+ const void *base;
+ const ValueFormat *valueFormats;
+ unsigned len1; /* valueFormats[0].get_len() */
+ const hb_map_t *glyph_map;
+ };
+
bool serialize (hb_serialize_context_t *c,
- unsigned length,
- const hb_map_t &glyph_map) const
+ serialize_closure_t *closure) 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));
+
+ out->secondGlyph = (*closure->glyph_map)[secondGlyph];
+
+ closure->valueFormats[0].serialize_copy (c, closure->base, &values[0]);
+ closure->valueFormats[1].serialize_copy (c, closure->base, &values[closure->len1]);
+
+ return_trace (true);
}
protected:
@@ -817,8 +939,8 @@ struct PairSet
}
bool apply (hb_ot_apply_context_t *c,
- const ValueFormat *valueFormats,
- unsigned int pos) const
+ const ValueFormat *valueFormats,
+ unsigned int pos) const
{
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
@@ -826,40 +948,26 @@ struct PairSet
unsigned int len2 = valueFormats[1].get_len ();
unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
- unsigned int count = len;
-
- /* Hand-coded bsearch. */
- if (unlikely (!count))
- return_trace (false);
- hb_codepoint_t x = buffer->info[pos].codepoint;
- int min = 0, max = (int) count - 1;
- while (min <= max)
+ const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
+ &firstPairValueRecord,
+ len,
+ record_size);
+ if (record)
{
- int mid = ((unsigned int) min + (unsigned int) max) / 2;
- const PairValueRecord *record = &StructAtOffset<PairValueRecord> (&firstPairValueRecord, record_size * mid);
- hb_codepoint_t mid_x = record->secondGlyph;
- if (x < mid_x)
- max = mid - 1;
- else if (x > mid_x)
- min = mid + 1;
- else
- {
- /* Note the intentional use of "|" instead of short-circuit "||". */
- if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
- valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
- buffer->unsafe_to_break (buffer->idx, pos + 1);
- if (len2)
- pos++;
- buffer->idx = pos;
- return_trace (true);
- }
+ /* Note the intentional use of "|" instead of short-circuit "||". */
+ if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
+ valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
+ buffer->unsafe_to_break (buffer->idx, pos + 1);
+ if (len2)
+ pos++;
+ buffer->idx = pos;
+ return_trace (true);
}
-
return_trace (false);
}
bool subset (hb_subset_context_t *c,
- const ValueFormat valueFormats[2]) const
+ const ValueFormat valueFormats[2]) const
{
TRACE_SUBSET (this);
auto snap = c->serializer->snapshot ();
@@ -875,12 +983,20 @@ struct PairSet
unsigned len2 = valueFormats[1].get_len ();
unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+ PairValueRecord::serialize_closure_t closure =
+ {
+ this,
+ valueFormats,
+ len1,
+ &glyph_map
+ };
+
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++;
+ if (glyphset.has (record->secondGlyph)
+ && record->serialize (c->serializer, &closure)) num++;
record = &StructAtOffset<const PairValueRecord> (record, record_size);
}
@@ -891,7 +1007,6 @@ struct PairSet
struct sanitize_closure_t
{
- const void *base;
const ValueFormat *valueFormats;
unsigned int len1; /* valueFormats[0].get_len() */
unsigned int stride; /* 1 + len1 + len2 */
@@ -908,8 +1023,8 @@ struct PairSet
unsigned int count = len;
const PairValueRecord *record = &firstPairValueRecord;
- return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
- closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
+ return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
+ closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
}
protected:
@@ -935,9 +1050,11 @@ struct PairPosFormat1
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
unsigned int count = pairSet.len;
for (unsigned int i = 0; i < count; i++)
(this+pairSet[i]).collect_glyphs (c, valueFormat);
@@ -981,7 +1098,7 @@ struct PairPosFormat1
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);
+ bool ret = o->serialize_subset (c, _, this, valueFormat);
if (!ret)
{
out->pairSet.pop ();
@@ -1011,7 +1128,6 @@ struct PairPosFormat1
unsigned int len2 = valueFormat[1].get_len ();
PairSet::sanitize_closure_t closure =
{
- this,
valueFormat,
len1,
1 + len1 + len2
@@ -1046,10 +1162,12 @@ struct PairPosFormat2
(this+classDef2).intersects (glyphs);
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
- if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
}
const Coverage &get_coverage () const { return this+coverage; }
@@ -1096,32 +1214,33 @@ struct PairPosFormat2
out->valueFormat2 = valueFormat2;
hb_map_t klass1_map;
- out->classDef1.serialize_subset (c, classDef1, this, out, &klass1_map);
+ out->classDef1.serialize_subset (c, classDef1, this, &klass1_map);
out->class1Count = klass1_map.get_population ();
hb_map_t klass2_map;
- out->classDef2.serialize_subset (c, classDef2, this, out, &klass2_map);
+ out->classDef2.serialize_subset (c, classDef2, this, &klass2_map);
out->class2Count = klass2_map.get_population ();
- unsigned record_len = valueFormat1.get_len () + valueFormat2.get_len ();
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+ hb_range ((unsigned) class1Count)
| hb_filter (klass1_map)
| hb_apply ([&] (const unsigned class1_idx)
- {
- + hb_range ((unsigned) class2Count)
- | hb_filter (klass2_map)
- | hb_apply ([&] (const unsigned class2_idx)
- {
- unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_len;
- for (unsigned i = 0; i < record_len; i++)
- c->serializer->copy (values[idx+i]);
- })
- ;
- })
+ {
+ + hb_range ((unsigned) class2Count)
+ | hb_filter (klass2_map)
+ | hb_apply ([&] (const unsigned class2_idx)
+ {
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ valueFormat1.serialize_copy (c->serializer, this, &values[idx]);
+ valueFormat2.serialize_copy (c->serializer, this, &values[idx + len1]);
+ })
+ ;
+ })
;
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it =
@@ -1217,16 +1336,14 @@ struct EntryExitRecord
return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
}
- EntryExitRecord* copy (hb_serialize_context_t *c,
- const void *src_base,
- const void *dst_base) const
+ EntryExitRecord* copy (hb_serialize_context_t *c, const void *base) const
{
TRACE_SERIALIZE (this);
auto *out = c->embed (this);
if (unlikely (!out)) return_trace (nullptr);
- out->entryAnchor.serialize_copy (c, entryAnchor, src_base, dst_base);
- out->exitAnchor.serialize_copy (c, exitAnchor, src_base, dst_base);
+ out->entryAnchor.serialize_copy (c, entryAnchor, base);
+ out->exitAnchor.serialize_copy (c, exitAnchor, base);
return_trace (out);
}
@@ -1251,8 +1368,10 @@ struct CursivePosFormat1
bool intersects (const hb_set_t *glyphs) const
{ return (this+coverage).intersects (glyphs); }
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
const Coverage &get_coverage () const { return this+coverage; }
@@ -1359,9 +1478,7 @@ struct CursivePosFormat1
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- Iterator it,
- const void *src_base)
+ void serialize (hb_serialize_context_t *c, Iterator it, const void *base)
{
if (unlikely (!c->extend_min ((*this)))) return;
this->format = 1;
@@ -1369,7 +1486,7 @@ struct CursivePosFormat1
for (const EntryExitRecord& entry_record : + it
| hb_map (hb_second))
- c->copy (entry_record, src_base, this);
+ c->copy (entry_record, base);
auto glyphs =
+ it
@@ -1444,16 +1561,41 @@ typedef AnchorMatrix BaseArray; /* base-major--
* mark-minor--
* ordered by class--zero-based. */
+static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
+ const MarkArray &mark_array,
+ const hb_set_t &glyphset,
+ hb_map_t* klass_mapping /* INOUT */)
+{
+ hb_set_t orig_classes;
+
+ + hb_zip (mark_coverage, mark_array)
+ | hb_filter (glyphset, hb_first)
+ | hb_map (hb_second)
+ | hb_map (&MarkRecord::get_class)
+ | hb_sink (orig_classes)
+ ;
+
+ unsigned idx = 0;
+ for (auto klass : orig_classes.iter ())
+ {
+ if (klass_mapping->has (klass)) continue;
+ klass_mapping->set (klass, idx);
+ idx++;
+ }
+}
+
struct MarkBasePosFormat1
{
bool intersects (const hb_set_t *glyphs) const
{ return (this+markCoverage).intersects (glyphs) &&
(this+baseCoverage).intersects (glyphs); }
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
- if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
}
const Coverage &get_coverage () const { return this+markCoverage; }
@@ -1501,8 +1643,70 @@ struct MarkBasePosFormat1
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_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark_iter =
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + mark_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->markCoverage.serialize (c->serializer, out)
+ .serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ out->markArray.serialize (c->serializer, out)
+ .serialize (c->serializer, &klass_mapping, &(this+markArray), + mark_iter
+ | hb_map (hb_second));
+
+ unsigned basecount = (this+baseArray).rows;
+ auto base_iter =
+ + hb_zip (this+baseCoverage, hb_range (basecount))
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ new_coverage.reset ();
+ + base_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->baseCoverage.serialize (c->serializer, out)
+ .serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ hb_sorted_vector_t<unsigned> base_indexes;
+ for (const unsigned row : + base_iter
+ | hb_map (hb_second))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (base_indexes)
+ ;
+ }
+ out->baseArray.serialize (c->serializer, out)
+ .serialize (c->serializer, base_iter.len (), &(this+baseArray), base_indexes.iter ());
+
+ return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -1571,10 +1775,12 @@ struct MarkLigPosFormat1
{ return (this+markCoverage).intersects (glyphs) &&
(this+ligatureCoverage).intersects (glyphs); }
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
- if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
}
const Coverage &get_coverage () const { return this+markCoverage; }
@@ -1691,10 +1897,12 @@ struct MarkMarkPosFormat1
{ return (this+mark1Coverage).intersects (glyphs) &&
(this+mark2Coverage).intersects (glyphs); }
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return;
- if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
}
const Coverage &get_coverage () const { return this+mark1Coverage; }
@@ -1746,8 +1954,70 @@ struct MarkMarkPosFormat1
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_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark1_iter =
+ + hb_zip (this+mark1Coverage, this+mark1Array)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + mark1_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->mark1Coverage.serialize (c->serializer, out)
+ .serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ out->mark1Array.serialize (c->serializer, out)
+ .serialize (c->serializer, &klass_mapping, &(this+mark1Array), + mark1_iter
+ | hb_map (hb_second));
+//////
+ unsigned mark2count = (this+mark2Array).rows;
+ auto mark2_iter =
+ + hb_zip (this+mark2Coverage, hb_range (mark2count))
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ new_coverage.reset ();
+ + mark2_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->mark2Coverage.serialize (c->serializer, out)
+ .serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ hb_sorted_vector_t<unsigned> mark2_indexes;
+ for (const unsigned row : + mark2_iter
+ | hb_map (hb_second))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (mark2_indexes)
+ ;
+ }
+ out->mark2Array.serialize (c->serializer, out)
+ .serialize (c->serializer, mark2_iter.len (), &(this+mark2Array), mark2_indexes.iter ());
+
+ return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -1853,6 +2123,12 @@ struct PosLookupSubTable
}
}
+ bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c, lookup_type);
+ }
+
protected:
union {
SinglePos single;
@@ -1897,18 +2173,37 @@ struct PosLookup : Lookup
hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
{ return dispatch (c); }
+ hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
+ {
+ if (c->is_lookup_visited (this_index))
+ return hb_closure_lookups_context_t::default_return_value ();
+
+ c->set_lookup_visited (this_index);
+ if (!intersects (c->glyphs))
+ {
+ c->set_lookup_inactive (this_index);
+ return hb_closure_lookups_context_t::default_return_value ();
+ }
+ c->set_recurse_func (dispatch_closure_lookups_recurse_func);
+
+ hb_closure_lookups_context_t::return_t ret = dispatch (c);
+ return ret;
+ }
+
template <typename set_t>
- void add_coverage (set_t *glyphs) const
+ void collect_coverage (set_t *glyphs) const
{
- hb_add_coverage_context_t<set_t> c (glyphs);
+ hb_collect_coverage_context_t<set_t> c (glyphs);
dispatch (&c);
}
- HB_INTERNAL static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
+ static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
template <typename context_t>
static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+ HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index);
+
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{ return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
@@ -1930,14 +2225,17 @@ struct GPOS : GSUBGPOS
static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
const PosLookup& get_lookup (unsigned int i) const
- { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
+ { return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
bool subset (hb_subset_context_t *c) const
- { return GSUBGPOS::subset<PosLookup> (c); }
+ {
+ hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_features);
+ return GSUBGPOS::subset<PosLookup> (&l);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{ return GSUBGPOS::sanitize<PosLookup> (c); }
@@ -2060,12 +2358,19 @@ struct GPOS_accelerator_t : GPOS::accelerator_t {};
#ifndef HB_NO_OT_LAYOUT
template <typename context_t>
-/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
+/*static*/ typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
{
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
return l.dispatch (c);
}
-/*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
+
+/*static*/ inline hb_closure_lookups_context_t::return_t PosLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
+{
+ const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (this_index);
+ return l.closure_lookups (c, this_index);
+}
+
+/*static*/ bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
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 fc21cb056e8..01a5af125e4 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
@@ -37,8 +37,8 @@ namespace OT {
typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
template<typename Iterator>
-static inline void SingleSubst_serialize (hb_serialize_context_t *c,
- Iterator it);
+static void SingleSubst_serialize (hb_serialize_context_t *c,
+ Iterator it);
struct SingleSubstFormat1
@@ -56,9 +56,11 @@ struct SingleSubstFormat1
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
unsigned d = deltaGlyphID;
+ hb_iter (this+coverage)
| hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
@@ -154,9 +156,11 @@ struct SingleSubstFormat2
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ hb_zip (this+coverage, substitute)
| hb_map (hb_second)
| hb_sink (c->output)
@@ -255,9 +259,8 @@ struct SingleSubst
if (glyphs)
{
format = 1;
- auto get_delta = [=] (hb_codepoint_pair_t _) {
- return (unsigned) (_.second - _.first) & 0xFFFF;
- };
+ auto get_delta = [=] (hb_codepoint_pair_t _)
+ { return (unsigned) (_.second - _.first) & 0xFFFF; };
delta = get_delta (*glyphs);
if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
}
@@ -293,7 +296,7 @@ struct SingleSubst
};
template<typename Iterator>
-static inline void
+static void
SingleSubst_serialize (hb_serialize_context_t *c,
Iterator it)
{ c->start_embed<SingleSubst> ()->serialize (c, it); }
@@ -359,9 +362,9 @@ struct Sequence
if (!intersects (&glyphset)) return_trace (false);
auto it =
- + hb_iter (substitute)
- | hb_map (glyph_map)
- ;
+ + hb_iter (substitute)
+ | hb_map (glyph_map)
+ ;
auto *out = c->serializer->start_embed (*this);
return_trace (out->serialize (c->serializer, it));
@@ -395,9 +398,11 @@ struct MultipleSubstFormat1
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ hb_zip (this+coverage, sequence)
| hb_map (hb_second)
| hb_map (hb_add (this))
@@ -452,7 +457,7 @@ struct MultipleSubstFormat1
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ hb_zip (this+coverage, sequence)
| hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->sequence, this, out), hb_second)
+ | hb_filter (subset_offset_array (c, out->sequence, this), hb_second)
| hb_map (hb_first)
| hb_map (glyph_map)
| hb_sink (new_coverage)
@@ -599,15 +604,18 @@ struct AlternateSubstFormat1
void closure (hb_closure_context_t *c) const
{
+ hb_zip (this+coverage, alternateSet)
+ | hb_filter (c->glyphs, hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this))
| hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ hb_zip (this+coverage, alternateSet)
| hb_map (hb_second)
| hb_map (hb_add (this))
@@ -662,7 +670,7 @@ struct AlternateSubstFormat1
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ hb_zip (this+coverage, alternateSet)
| hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->alternateSet, this, out), hb_second)
+ | hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second)
| hb_map (hb_first)
| hb_map (glyph_map)
| hb_sink (new_coverage)
@@ -922,7 +930,7 @@ struct LigatureSet
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ hb_iter (ligature)
- | hb_filter (subset_offset_array (c, out->ligature, this, out))
+ | hb_filter (subset_offset_array (c, out->ligature, this))
| hb_drain
;
return_trace (bool (out->ligature));
@@ -966,9 +974,11 @@ struct LigatureSubstFormat1
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ hb_zip (this+coverage, ligatureSet)
| hb_map (hb_second)
@@ -992,7 +1002,7 @@ struct LigatureSubstFormat1
{
TRACE_APPLY (this);
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
const LigatureSet &lig_set = this+ligatureSet[index];
@@ -1036,7 +1046,7 @@ struct LigatureSubstFormat1
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ hb_zip (this+coverage, ligatureSet)
| hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->ligatureSet, this, out), hb_second)
+ | hb_filter (subset_offset_array (c, out->ligatureSet, this), hb_second)
| hb_map (hb_first)
| hb_map (glyph_map)
| hb_sink (new_coverage)
@@ -1114,7 +1124,6 @@ struct ChainContextSubst : ChainContext {};
struct ExtensionSubst : Extension<ExtensionSubst>
{
typedef struct SubstLookupSubTable SubTable;
-
bool is_reverse () const;
};
@@ -1157,20 +1166,22 @@ struct ReverseChainSingleSubstFormat1
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
unsigned int count;
count = backtrack.len;
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(this+backtrack[i]).add_coverage (c->before))) return;
+ if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
count = lookahead.len;
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(this+lookahead[i]).add_coverage (c->after))) return;
+ if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
count = substitute.len;
@@ -1188,7 +1199,7 @@ struct ReverseChainSingleSubstFormat1
if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
return_trace (false); /* No chaining to this type */
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
@@ -1313,6 +1324,12 @@ struct SubstLookupSubTable
}
}
+ bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c, lookup_type);
+ }
+
protected:
union {
SingleSubst single;
@@ -1336,14 +1353,14 @@ struct SubstLookup : Lookup
const SubTable& get_subtable (unsigned int i) const
{ return Lookup::get_subtable<SubTable> (i); }
- HB_INTERNAL static bool lookup_type_is_reverse (unsigned int lookup_type)
+ static inline bool lookup_type_is_reverse (unsigned int lookup_type)
{ return lookup_type == SubTable::ReverseChainSingle; }
bool is_reverse () const
{
unsigned int type = get_type ();
if (unlikely (type == SubTable::Extension))
- return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
+ return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse ();
return lookup_type_is_reverse (type);
}
@@ -1373,6 +1390,24 @@ struct SubstLookup : Lookup
return ret;
}
+ hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
+ {
+ if (c->is_lookup_visited (this_index))
+ return hb_closure_lookups_context_t::default_return_value ();
+
+ c->set_lookup_visited (this_index);
+ if (!intersects (c->glyphs))
+ {
+ c->set_lookup_inactive (this_index);
+ return hb_closure_lookups_context_t::default_return_value ();
+ }
+
+ c->set_recurse_func (dispatch_closure_lookups_recurse_func);
+
+ hb_closure_lookups_context_t::return_t ret = dispatch (c);
+ return ret;
+ }
+
hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
{
c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
@@ -1380,9 +1415,9 @@ struct SubstLookup : Lookup
}
template <typename set_t>
- void add_coverage (set_t *glyphs) const
+ void collect_coverage (set_t *glyphs) const
{
- hb_add_coverage_context_t<set_t> c (glyphs);
+ hb_collect_coverage_context_t<set_t> c (glyphs);
dispatch (&c);
}
@@ -1394,7 +1429,7 @@ struct SubstLookup : Lookup
return dispatch (c);
}
- HB_INTERNAL static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
+ static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
SubTable& serialize_subtable (hb_serialize_context_t *c,
unsigned int i)
@@ -1461,9 +1496,9 @@ struct SubstLookup : Lookup
}
template <typename context_t>
- HB_INTERNAL static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+ static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
- HB_INTERNAL static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
+ static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
{
if (!c->should_visit_lookup (lookup_index))
return hb_empty_t ();
@@ -1478,6 +1513,8 @@ struct SubstLookup : Lookup
return ret;
}
+ HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
+
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{ return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
@@ -1499,10 +1536,13 @@ struct GSUB : GSUBGPOS
static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
const SubstLookup& get_lookup (unsigned int i) const
- { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
+ { return static_cast<const SubstLookup &> (GSUBGPOS::get_lookup (i)); }
bool subset (hb_subset_context_t *c) const
- { return GSUBGPOS::subset<SubstLookup> (c); }
+ {
+ hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_features);
+ return GSUBGPOS::subset<SubstLookup> (&l);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{ return GSUBGPOS::sanitize<SubstLookup> (c); }
@@ -1522,18 +1562,22 @@ struct GSUB_accelerator_t : GSUB::accelerator_t {};
#ifndef HB_NO_OT_LAYOUT
/*static*/ inline bool ExtensionSubst::is_reverse () const
{
- unsigned int type = get_type ();
- if (unlikely (type == SubTable::Extension))
- return CastR<ExtensionSubst> (get_subtable<SubTable>()).is_reverse ();
- return SubstLookup::lookup_type_is_reverse (type);
+ return SubstLookup::lookup_type_is_reverse (get_type ());
}
template <typename context_t>
-/*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
+/*static*/ typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
{
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
return l.dispatch (c);
}
-/*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
+
+/*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
+{
+ const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index);
+ return l.closure_lookups (c, this_index);
+}
+
+/*static*/ bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
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 579d17871b8..c5c63edc544 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
@@ -76,10 +76,17 @@ struct hb_closure_context_t :
nesting_level_left++;
}
+ bool lookup_limit_exceeded ()
+ { return lookup_count > HB_MAX_LOOKUP_INDICES; }
+
bool should_visit_lookup (unsigned int lookup_index)
{
+ if (lookup_count++ > HB_MAX_LOOKUP_INDICES)
+ return false;
+
if (is_lookup_done (lookup_index))
return false;
+
done_lookups->set (lookup_index, glyphs->get_population ());
return true;
}
@@ -106,7 +113,9 @@ struct hb_closure_context_t :
recurse_func (nullptr),
nesting_level_left (nesting_level_left_),
debug_depth (0),
- done_lookups (done_lookups_) {}
+ done_lookups (done_lookups_),
+ lookup_count (0)
+ {}
~hb_closure_context_t () { flush (); }
@@ -114,14 +123,83 @@ struct hb_closure_context_t :
void flush ()
{
+ hb_set_del_range (output, face->get_num_glyphs (), hb_set_get_max (output)); /* Remove invalid glyphs. */
hb_set_union (glyphs, output);
hb_set_clear (output);
}
private:
hb_map_t *done_lookups;
+ unsigned int lookup_count;
};
+struct hb_closure_lookups_context_t :
+ hb_dispatch_context_t<hb_closure_lookups_context_t, hb_empty_t, 0>
+{
+ const char *get_name () { return "CLOSURE_LOOKUPS"; }
+ typedef return_t (*recurse_func_t) (hb_closure_lookups_context_t *c, unsigned lookup_index);
+ template <typename T>
+ return_t dispatch (const T &obj) { obj.closure_lookups (this); return hb_empty_t (); }
+ static return_t default_return_value () { return hb_empty_t (); }
+ void recurse (unsigned lookup_index)
+ {
+ if (unlikely (nesting_level_left == 0 || !recurse_func))
+ return;
+
+ /* Return if new lookup was recursed to before. */
+ if (is_lookup_visited (lookup_index))
+ return;
+
+ set_lookup_visited (lookup_index);
+ nesting_level_left--;
+ recurse_func (this, lookup_index);
+ nesting_level_left++;
+ }
+
+ void set_lookup_visited (unsigned lookup_index)
+ { visited_lookups->add (lookup_index); }
+
+ void set_lookup_inactive (unsigned lookup_index)
+ { inactive_lookups->add (lookup_index); }
+
+ bool lookup_limit_exceeded ()
+ { return lookup_count > HB_MAX_LOOKUP_INDICES; }
+
+ bool is_lookup_visited (unsigned lookup_index)
+ {
+ if (lookup_count++ > HB_MAX_LOOKUP_INDICES)
+ return true;
+
+ return visited_lookups->has (lookup_index);
+ }
+
+ hb_face_t *face;
+ const hb_set_t *glyphs;
+ recurse_func_t recurse_func;
+ unsigned int nesting_level_left;
+ unsigned int debug_depth;
+
+ hb_closure_lookups_context_t (hb_face_t *face_,
+ const hb_set_t *glyphs_,
+ hb_set_t *visited_lookups_,
+ hb_set_t *inactive_lookups_,
+ unsigned nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
+ face (face_),
+ glyphs (glyphs_),
+ recurse_func (nullptr),
+ nesting_level_left (nesting_level_left_),
+ debug_depth (0),
+ visited_lookups (visited_lookups_),
+ inactive_lookups (inactive_lookups_),
+ lookup_count (0) {}
+
+ void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+
+ private:
+ hb_set_t *visited_lookups;
+ hb_set_t *inactive_lookups;
+ unsigned int lookup_count;
+};
struct hb_would_apply_context_t :
hb_dispatch_context_t<hb_would_apply_context_t, bool, 0>
@@ -229,23 +307,23 @@ struct hb_collect_glyphs_context_t :
template <typename set_t>
-struct hb_add_coverage_context_t :
- hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
+struct hb_collect_coverage_context_t :
+ hb_dispatch_context_t<hb_collect_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
{
const char *get_name () { return "GET_COVERAGE"; }
typedef const Coverage &return_t;
template <typename T>
return_t dispatch (const T &obj) { return obj.get_coverage (); }
- static return_t default_return_value () { return Null(Coverage); }
+ static return_t default_return_value () { return Null (Coverage); }
bool stop_sublookup_iteration (return_t r) const
{
- r.add_coverage (set);
+ r.collect_coverage (set);
return false;
}
- hb_add_coverage_context_t (set_t *set_) :
- set (set_),
- debug_depth (0) {}
+ hb_collect_coverage_context_t (set_t *set_) :
+ set (set_),
+ debug_depth (0) {}
set_t *set;
unsigned int debug_depth;
@@ -355,7 +433,7 @@ struct hb_ot_apply_context_t :
}
void reset (unsigned int start_index_,
- unsigned int num_items_)
+ unsigned int num_items_)
{
idx = start_index_;
num_items = num_items_;
@@ -363,7 +441,11 @@ struct hb_ot_apply_context_t :
matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
}
- void reject () { num_items++; match_glyph_data--; }
+ void reject ()
+ {
+ num_items++;
+ if (match_glyph_data) match_glyph_data--;
+ }
matcher_t::may_skip_t
may_skip (const hb_glyph_info_t &info) const
@@ -487,7 +569,7 @@ struct hb_ot_apply_context_t :
#ifndef HB_NO_OT_LAYOUT
*face->table.GDEF->table
#else
- Null(GDEF)
+ Null (GDEF)
#endif
),
var_store (gdef.get_var_store ()),
@@ -563,53 +645,56 @@ struct hb_ot_apply_context_t :
return true;
}
- void _set_glyph_props (hb_codepoint_t glyph_index,
- unsigned int class_guess = 0,
- bool ligature = false,
- bool component = false) const
+ void _set_glyph_class (hb_codepoint_t glyph_index,
+ unsigned int class_guess = 0,
+ bool ligature = false,
+ bool component = false) const
{
- unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
- HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
- add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
+ unsigned int props = _hb_glyph_info_get_glyph_props (&buffer->cur());
+
+ props |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
if (ligature)
{
- add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
+ props |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
/* In the only place that the MULTIPLIED bit is used, Uniscribe
* seems to only care about the "last" transformation between
* Ligature and Multiple substitutions. Ie. if you ligate, expand,
* and ligate again, it forgives the multiplication and acts as
* if only ligation happened. As such, clear MULTIPLIED bit.
*/
- add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+ props &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
}
if (component)
- add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+ props |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+
if (likely (has_glyph_classes))
- _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
+ props = (props & ~HB_OT_LAYOUT_GLYPH_PROPS_CLASS_MASK) | gdef.get_glyph_props (glyph_index);
else if (class_guess)
- _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
+ props = (props & ~HB_OT_LAYOUT_GLYPH_PROPS_CLASS_MASK) | class_guess;
+
+ _hb_glyph_info_set_glyph_props (&buffer->cur(), props);
}
void replace_glyph (hb_codepoint_t glyph_index) const
{
- _set_glyph_props (glyph_index);
+ _set_glyph_class (glyph_index);
buffer->replace_glyph (glyph_index);
}
void replace_glyph_inplace (hb_codepoint_t glyph_index) const
{
- _set_glyph_props (glyph_index);
+ _set_glyph_class (glyph_index);
buffer->cur().codepoint = glyph_index;
}
void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
- unsigned int class_guess) const
+ unsigned int class_guess) const
{
- _set_glyph_props (glyph_index, class_guess, true);
+ _set_glyph_class (glyph_index, class_guess, true);
buffer->replace_glyph (glyph_index);
}
void output_glyph_for_component (hb_codepoint_t glyph_index,
- unsigned int class_guess) const
+ unsigned int class_guess) const
{
- _set_glyph_props (glyph_index, class_guess, false, true);
+ _set_glyph_class (glyph_index, class_guess, false, true);
buffer->output_glyph (glyph_index);
}
};
@@ -619,7 +704,7 @@ struct hb_get_subtables_context_t :
hb_dispatch_context_t<hb_get_subtables_context_t, hb_empty_t, HB_DEBUG_APPLY>
{
template <typename Type>
- HB_INTERNAL static bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
+ static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
{
const Type *typed_obj = (const Type *) obj;
return typed_obj->apply (c);
@@ -635,7 +720,7 @@ struct hb_get_subtables_context_t :
obj = &obj_;
apply_func = apply_func_;
digest.init ();
- obj_.get_coverage ().add_coverage (&digest);
+ obj_.get_coverage ().collect_coverage (&digest);
}
bool apply (OT::hb_ot_apply_context_t *c) const
@@ -725,12 +810,12 @@ static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const
static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
- class_def.add_class (glyphs, value);
+ class_def.collect_class (glyphs, value);
}
static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
{
const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
- (data+coverage).add_coverage (glyphs);
+ (data+coverage).collect_coverage (glyphs);
}
static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
hb_set_t *glyphs,
@@ -991,18 +1076,19 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
buffer->idx++;
}
- if (!is_mark_ligature && last_lig_id) {
+ if (!is_mark_ligature && last_lig_id)
+ {
/* Re-adjust components for any marks following. */
- for (unsigned int i = buffer->idx; i < buffer->len; i++) {
- if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
- unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
- if (!this_comp)
- break;
- unsigned int new_lig_comp = components_so_far - last_num_components +
- hb_min (this_comp, last_num_components);
- _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
- } else
- break;
+ for (unsigned i = buffer->idx; i < buffer->len; ++i)
+ {
+ if (last_lig_id != _hb_glyph_info_get_lig_id (&buffer->info[i])) break;
+
+ unsigned this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
+ if (!this_comp) break;
+
+ unsigned new_lig_comp = components_so_far - last_num_components +
+ hb_min (this_comp, last_num_components);
+ _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
}
}
return_trace (true);
@@ -1057,6 +1143,17 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
struct LookupRecord
{
+ LookupRecord* copy (hb_serialize_context_t *c,
+ const hb_map_t *lookup_map)
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->embed (*this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->lookupListIndex = hb_map_get (lookup_map, lookupListIndex);
+ return_trace (out);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -1303,6 +1400,8 @@ struct Rule
void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
{
+ if (unlikely (c->lookup_limit_exceeded ())) return;
+
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
(inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
context_closure_lookup (c,
@@ -1311,6 +1410,15 @@ struct Rule
lookup_context);
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ if (unlikely (c->lookup_limit_exceeded ())) return;
+
+ const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ recurse_lookups (c, lookupCount, lookupRecord.arrayZ);
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c,
ContextCollectGlyphsLookupContext &lookup_context) const
{
@@ -1359,7 +1467,7 @@ struct Rule
* glyph */
HBUINT16 lookupCount; /* Number of LookupRecords */
UnsizedArrayOf<HBUINT16>
- inputZ; /* Array of match inputs--start with
+ inputZ; /* Array of match inputs--start with
* second glyph */
/*UnsizedArrayOf<LookupRecord>
lookupRecordX;*/ /* Array of LookupRecords--in
@@ -1384,6 +1492,8 @@ struct RuleSet
void closure (hb_closure_context_t *c,
ContextClosureLookupContext &lookup_context) const
{
+ if (unlikely (c->lookup_limit_exceeded ())) return;
+
return
+ hb_iter (rule)
| hb_map (hb_add (this))
@@ -1391,6 +1501,17 @@ struct RuleSet
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ if (unlikely (c->lookup_limit_exceeded ())) return;
+
+ return
+ + hb_iter (rule)
+ | hb_map (hb_add (this))
+ | hb_apply ([&] (const Rule &_) { _.closure_lookups (c); })
+ ;
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c,
ContextCollectGlyphsLookupContext &lookup_context) const
{
@@ -1474,9 +1595,17 @@ struct ContextFormat1
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ + hb_iter (ruleSet)
+ | hb_map (hb_add (this))
+ | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); })
+ ;
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- (this+coverage).add_coverage (c->input);
+ (this+coverage).collect_coverage (c->input);
struct ContextCollectGlyphsLookupContext lookup_context = {
{collect_glyph},
@@ -1588,9 +1717,17 @@ struct ContextFormat2
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ + hb_iter (ruleSet)
+ | hb_map (hb_add (this))
+ | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); })
+ ;
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- (this+coverage).add_coverage (c->input);
+ (this+coverage).collect_coverage (c->input);
const ClassDef &class_def = this+classDef;
struct ContextCollectGlyphsLookupContext lookup_context = {
@@ -1695,9 +1832,15 @@ struct ContextFormat3
lookup_context);
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+ recurse_lookups (c, lookupCount, lookupRecord);
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- (this+coverageZ[0]).add_coverage (c->input);
+ (this+coverageZ[0]).collect_coverage (c->input);
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
struct ContextCollectGlyphsLookupContext lookup_context = {
@@ -1949,6 +2092,8 @@ struct ChainRule
void closure (hb_closure_context_t *c,
ChainContextClosureLookupContext &lookup_context) const
{
+ if (unlikely (c->lookup_limit_exceeded ())) return;
+
const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
@@ -1960,6 +2105,16 @@ struct ChainRule
lookup_context);
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ if (unlikely (c->lookup_limit_exceeded ())) return;
+
+ const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+ const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+ recurse_lookups (c, lookup.len, lookup.arrayZ);
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c,
ChainContextCollectGlyphsLookupContext &lookup_context) const
{
@@ -2003,8 +2158,8 @@ struct ChainRule
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void serialize_array (hb_serialize_context_t *c,
- HBUINT16 len,
- Iterator it) const
+ HBUINT16 len,
+ Iterator it) const
{
c->copy (len);
for (const auto g : it)
@@ -2045,9 +2200,9 @@ struct ChainRule
}
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
+ 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);
@@ -2058,18 +2213,18 @@ struct ChainRule
{
const hb_set_t &glyphset = *c->plan->glyphset ();
if (!hb_all (backtrack, glyphset) ||
- !hb_all (input, glyphset) ||
- !hb_all (lookahead, glyphset))
- return_trace (false);
+ !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);
+ !hb_all (input, input_map) ||
+ !hb_all (lookahead, lookahead_map))
+ return_trace (false);
copy (c->serializer, backtrack_map, input_map, lookahead_map);
}
@@ -2120,6 +2275,8 @@ struct ChainRuleSet
}
void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
{
+ if (unlikely (c->lookup_limit_exceeded ())) return;
+
return
+ hb_iter (rule)
| hb_map (hb_add (this))
@@ -2127,6 +2284,17 @@ struct ChainRuleSet
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ if (unlikely (c->lookup_limit_exceeded ())) return;
+
+ return
+ + hb_iter (rule)
+ | hb_map (hb_add (this))
+ | hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c); })
+ ;
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
{
return
@@ -2159,9 +2327,9 @@ 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
+ 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);
@@ -2176,13 +2344,13 @@ struct ChainRuleSet
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))
+ if (!o->serialize_subset (c, _, this,
+ backtrack_klass_map,
+ input_klass_map,
+ lookahead_klass_map))
{
- out->rule.pop ();
- c->serializer->revert (o_snap);
+ out->rule.pop ();
+ c->serializer->revert (o_snap);
}
}
@@ -2240,9 +2408,17 @@ struct ChainContextFormat1
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ + hb_iter (ruleSet)
+ | hb_map (hb_add (this))
+ | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); })
+ ;
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- (this+coverage).add_coverage (c->input);
+ (this+coverage).collect_coverage (c->input);
struct ChainContextCollectGlyphsLookupContext lookup_context = {
{collect_glyph},
@@ -2294,7 +2470,7 @@ struct ChainContextFormat1
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_filter (subset_offset_array (c, out->ruleSet, this), hb_second)
| hb_map (hb_first)
| hb_map (glyph_map)
| hb_sink (new_coverage)
@@ -2376,9 +2552,17 @@ struct ChainContextFormat2
;
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ + hb_iter (ruleSet)
+ | hb_map (hb_add (this))
+ | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); })
+ ;
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- (this+coverage).add_coverage (c->input);
+ (this+coverage).collect_coverage (c->input);
const ClassDef &backtrack_class_def = this+backtrackClassDef;
const ClassDef &input_class_def = this+inputClassDef;
@@ -2443,17 +2627,17 @@ struct ChainContextFormat2
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);
+ out->coverage.serialize_subset (c, coverage, this);
hb_map_t backtrack_klass_map;
- out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, out, &backtrack_klass_map);
+ out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, &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);
+ out->inputClassDef.serialize_subset (c, inputClassDef, this, &input_klass_map);
hb_map_t lookahead_klass_map;
- out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, out, &lookahead_klass_map);
+ out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, &lookahead_klass_map);
hb_vector_t<unsigned> rulesets;
bool ret = true;
@@ -2464,15 +2648,15 @@ struct ChainContextFormat2
auto *o = out->ruleSet.serialize_append (c->serializer);
if (unlikely (!o))
{
- ret = false;
- break;
+ ret = false;
+ break;
}
- if (!o->serialize_subset (c, _, this, out,
- &backtrack_klass_map,
- &input_klass_map,
- &lookahead_klass_map))
+ if (!o->serialize_subset (c, _, this,
+ &backtrack_klass_map,
+ &input_klass_map,
+ &lookahead_klass_map))
{
- rulesets.push (0);
+ rulesets.push (0);
}
else rulesets.push (1);
}
@@ -2566,11 +2750,19 @@ struct ChainContextFormat3
lookup_context);
}
+ void closure_lookups (hb_closure_lookups_context_t *c) const
+ {
+ const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+ const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
+ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+ recurse_lookups (c, lookup.len, lookup.arrayZ);
+ }
+
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
- (this+input[0]).add_coverage (c->input);
+ (this+input[0]).collect_coverage (c->input);
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
@@ -2631,10 +2823,7 @@ struct ChainContextFormat3
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
+ bool serialize_coverage_offsets (hb_subset_context_t *c, Iterator it, const void* base) const
{
TRACE_SERIALIZE (this);
auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> ();
@@ -2642,7 +2831,7 @@ struct ChainContextFormat3
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))
+ | hb_apply (subset_offset_array (c, *out, base))
;
return_trace (out->len);
@@ -2656,15 +2845,15 @@ struct ChainContextFormat3
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))
+ if (!serialize_coverage_offsets (c, backtrack.iter (), this))
return_trace (false);
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
- if (!serialize_coverage_offsets (c, input.iter (), this, out))
+ if (!serialize_coverage_offsets (c, input.iter (), this))
return_trace (false);
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
- if (!serialize_coverage_offsets (c, lookahead.iter (), this, out))
+ if (!serialize_coverage_offsets (c, lookahead.iter (), this))
return_trace (false);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
@@ -2737,7 +2926,7 @@ struct ExtensionFormat1
template <typename X>
const X& get_subtable () const
- { return this + CastR<LOffsetTo<typename T::SubTable>> (extensionOffset); }
+ { return this + reinterpret_cast<const LOffsetTo<typename T::SubTable> &> (extensionOffset); }
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
@@ -2781,7 +2970,7 @@ struct Extension
{
switch (u.format) {
case 1: return u.format1.template get_subtable<typename T::SubTable> ();
- default:return Null(typename T::SubTable);
+ default:return Null (typename T::SubTable);
}
}
@@ -2814,7 +3003,7 @@ struct hb_ot_layout_lookup_accelerator_t
void init (const TLookup &lookup)
{
digest.init ();
- lookup.add_coverage (&digest);
+ lookup.collect_coverage (&digest);
subtables.init ();
OT::hb_get_subtables_context_t c_get_subtables (subtables);
@@ -2875,10 +3064,11 @@ struct GSUBGPOS
bool find_variations_index (const int *coords, unsigned int num_coords,
unsigned int *index) const
{
-#ifdef HB_NOVAR
+#ifdef HB_NO_VAR
+ *index = FeatureVariations::NOT_FOUND_INDEX;
return false;
#endif
- return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
+ return (version.to_int () >= 0x00010001u ? this+featureVars : Null (FeatureVariations))
.find_index (coords, num_coords, index);
}
const Feature& get_feature_variation (unsigned int feature_index,
@@ -2897,32 +3087,70 @@ struct GSUBGPOS
return get_feature (feature_index);
}
+ void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
+ hb_set_t *lookup_indexes /* OUT */) const
+ {
+#ifndef HB_NO_VAR
+ if (version.to_int () >= 0x00010001u)
+ (this+featureVars).collect_lookups (feature_indexes, lookup_indexes);
+#endif
+ }
+
template <typename TLookup>
- bool subset (hb_subset_context_t *c) const
+ bool subset (hb_subset_layout_context_t *c) const
{
TRACE_SUBSET (this);
- auto *out = c->serializer->embed (*this);
+ auto *out = c->subset_context->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
- out->scriptList.serialize_subset (c, scriptList, this, out);
- out->featureList.serialize_subset (c, featureList, this, out);
+ typedef LookupOffsetList<TLookup> TLookupList;
+ reinterpret_cast<OffsetTo<TLookupList> &> (out->lookupList)
+ .serialize_subset (c->subset_context,
+ reinterpret_cast<const OffsetTo<TLookupList> &> (lookupList),
+ this,
+ c);
- typedef OffsetListOf<TLookup> TLookupList;
- /* TODO Use intersects() to count how many subtables survive? */
- CastR<OffsetTo<TLookupList>> (out->lookupList)
- .serialize_subset (c,
- CastR<OffsetTo<TLookupList>> (lookupList),
- this,
- out);
+ reinterpret_cast<OffsetTo<RecordListOfFeature> &> (out->featureList)
+ .serialize_subset (c->subset_context,
+ reinterpret_cast<const OffsetTo<RecordListOfFeature> &> (featureList),
+ this,
+ c);
+
+ out->scriptList.serialize_subset (c->subset_context,
+ scriptList,
+ this,
+ c);
#ifndef HB_NO_VAR
if (version.to_int () >= 0x00010001u)
- out->featureVars.serialize_copy (c->serializer, featureVars, this, out);
+ {
+ bool ret = out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
+ if (!ret)
+ {
+ out->version.major = 1;
+ out->version.minor = 0;
+ }
+ }
#endif
return_trace (true);
}
+ void closure_features (const hb_map_t *lookup_indexes, /* IN */
+ hb_set_t *feature_indexes /* OUT */) const
+ {
+ unsigned int feature_count = hb_min (get_feature_count (), (unsigned) HB_MAX_FEATURES);
+ for (unsigned i = 0; i < feature_count; i++)
+ {
+ if (get_feature (i).intersects_lookup_indexes (lookup_indexes))
+ feature_indexes->add (i);
+ }
+#ifndef HB_NO_VAR
+ if (version.to_int () >= 0x00010001u)
+ (this+featureVars).closure_features (lookup_indexes, feature_indexes);
+#endif
+ }
+
unsigned int get_size () const
{
return min_size +
@@ -2938,7 +3166,7 @@ struct GSUBGPOS
likely (version.major == 1) &&
scriptList.sanitize (c, this) &&
featureList.sanitize (c, this) &&
- CastR<OffsetTo<TLookupList>> (lookupList).sanitize (c, this))))
+ reinterpret_cast<const OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
return_trace (false);
#ifndef HB_NO_VAR
@@ -2954,7 +3182,7 @@ struct GSUBGPOS
{
void init (hb_face_t *face)
{
- this->table = hb_sanitize_context_t().reference_table<T> (face);
+ this->table = hb_sanitize_context_t ().reference_table<T> (face);
if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
{
hb_blob_destroy (this->table.get_blob ());
@@ -2988,11 +3216,11 @@ struct GSUBGPOS
FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
* to 0x00010000u */
OffsetTo<ScriptList>
- scriptList; /* ScriptList table */
+ scriptList; /* ScriptList table */
OffsetTo<FeatureList>
- featureList; /* FeatureList table */
+ featureList; /* FeatureList table */
OffsetTo<LookupList>
- lookupList; /* LookupList table */
+ lookupList; /* LookupList table */
LOffsetTo<FeatureVariations>
featureVars; /* Offset to Feature Variations
table--from beginning of table
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh
index 53eb623cf5c..ffd2bf45745 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-jstf-table.hh
@@ -222,7 +222,7 @@ struct JSTF
FixedVersion<>version; /* Version of the JSTF table--initially set
* to 0x00010000u */
RecordArrayOf<JstfScript>
- scriptList; /* Array of JstfScripts--listed
+ scriptList; /* Array of JstfScripts--listed
* alphabetically by ScriptTag */
public:
DEFINE_SIZE_ARRAY (6, scriptList);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
index fba3ad1916a..5b1d9764edb 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc
@@ -399,27 +399,6 @@ OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
#ifdef HB_NO_OT_LAYOUT_BLACKLIST
return false;
#endif
-
-#ifndef HB_NO_AAT_SHAPE
- /* Mac OS X prefers morx over GSUB. It also ships with various Indic fonts,
- * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
- * GSUB/GPOS tables. Some have GSUB with zero scripts, those are ignored by
- * our morx/GSUB preference code. But if GSUB has non-zero scripts, we tend
- * to prefer it over morx because we want to be consistent with other OpenType
- * shapers.
- *
- * To work around broken Indic Mac system fonts, we ignore GSUB table if
- * OS/2 VendorId is 'MUTF' and font has morx table as well.
- *
- * https://github.com/harfbuzz/harfbuzz/issues/1410
- * https://github.com/harfbuzz/harfbuzz/issues/1348
- * https://github.com/harfbuzz/harfbuzz/issues/1391
- */
- if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') &&
- face->table.morx->has_data ()))
- return true;
-#endif
-
return false;
}
@@ -440,7 +419,7 @@ get_gsubgpos_table (hb_face_t *face,
switch (table_tag) {
case HB_OT_TAG_GSUB: return *face->table.GSUB->table;
case HB_OT_TAG_GPOS: return *face->table.GPOS->table;
- default: return Null(OT::GSUBGPOS);
+ default: return Null (OT::GSUBGPOS);
}
}
@@ -785,7 +764,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
- unsigned int *feature_index)
+ unsigned int *feature_index /* OUT */)
{
return hb_ot_layout_language_get_required_feature (face,
table_tag,
@@ -802,7 +781,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag
- * @feature_index: The index of the requested feature
+ * @feature_index: (out): The index of the requested feature
* @feature_tag: (out): The #hb_tag_t of the requested feature
*
* Fetches the tag of a requested feature index in the given face's GSUB or GPOS table,
@@ -817,8 +796,8 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
- unsigned int *feature_index,
- hb_tag_t *feature_tag)
+ unsigned int *feature_index /* OUT */,
+ hb_tag_t *feature_tag /* OUT */)
{
const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
@@ -1004,7 +983,7 @@ struct hb_collect_features_context_t
hb_set_t *feature_indexes_)
: g (get_gsubgpos_table (face, table_tag)),
feature_indexes (feature_indexes_),
- script_count(0),langsys_count(0) {}
+ script_count (0),langsys_count (0), feature_index_count (0) {}
bool visited (const OT::Script &s)
{
@@ -1033,6 +1012,12 @@ struct hb_collect_features_context_t
return visited (l, visited_langsys);
}
+ bool visited_feature_indices (unsigned count)
+ {
+ feature_index_count += count;
+ return feature_index_count > HB_MAX_FEATURE_INDICES;
+ }
+
private:
template <typename T>
bool visited (const T &p, hb_set_t &visited_set)
@@ -1054,6 +1039,7 @@ struct hb_collect_features_context_t
hb_set_t visited_langsys;
unsigned int script_count;
unsigned int langsys_count;
+ unsigned int feature_index_count;
};
static void
@@ -1066,10 +1052,11 @@ langsys_collect_features (hb_collect_features_context_t *c,
if (!features)
{
/* All features. */
- if (l.has_required_feature ())
+ if (l.has_required_feature () && !c->visited_feature_indices (1))
c->feature_indexes->add (l.get_required_feature_index ());
- l.add_feature_indexes_to (c->feature_indexes);
+ if (!c->visited_feature_indices (l.featureIndex.len))
+ l.add_feature_indexes_to (c->feature_indexes);
}
else
{
@@ -1212,7 +1199,75 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
hb_set_next (&feature_indexes, &feature_index);)
g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
+
+ g.feature_variation_collect_lookups (&feature_indexes, lookup_indexes);
+}
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_ot_layout_closure_lookups:
+ * @face: #hb_face_t to work upon
+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @lookup_indexes: (inout): lookup_indices collected from feature
+ * list
+ *
+ * Returns all inactive lookups reachable from lookup_indices
+ *
+ * Since: EXPERIMENTAL
+ **/
+void
+hb_ot_layout_closure_lookups (hb_face_t *face,
+ hb_tag_t table_tag,
+ const hb_set_t *glyphs,
+ hb_set_t *lookup_indexes /* IN/OUT */)
+{
+ hb_set_t visited_lookups, inactive_lookups;
+ OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
+
+ for (unsigned lookup_index : + hb_iter (lookup_indexes))
+ {
+ switch (table_tag)
+ {
+ case HB_OT_TAG_GSUB:
+ {
+ const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
+ l.closure_lookups (&c, lookup_index);
+ break;
+ }
+ case HB_OT_TAG_GPOS:
+ {
+ const OT::PosLookup& l = face->table.GPOS->table->get_lookup (lookup_index);
+ l.closure_lookups (&c, lookup_index);
+ break;
+ }
+ }
+ }
+
+ hb_set_union (lookup_indexes, &visited_lookups);
+ hb_set_subtract (lookup_indexes, &inactive_lookups);
+}
+
+/**
+ * hb_ot_layout_closure_features:
+ * @face: #hb_face_t to work upon
+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
+ * @lookup_indexes: (in): collected active lookup_indices
+ * @feature_indexes: (out): all active feature indexes collected
+ *
+ * Returns all active feature indexes
+ *
+ * Since: EXPERIMENTAL
+ **/
+void
+hb_ot_layout_closure_features (hb_face_t *face,
+ hb_tag_t table_tag,
+ const hb_map_t *lookup_indexes, /* IN */
+ hb_set_t *feature_indexes /* OUT */)
+{
+ const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+ g.closure_features (lookup_indexes, feature_indexes);
}
+#endif
#ifndef HB_NO_LAYOUT_COLLECT_GLYPHS
@@ -1223,7 +1278,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
* @lookup_index: The index of the feature lookup to query
* @glyphs_before: (out): Array of glyphs preceding the substitution range
* @glyphs_input: (out): Array of input glyphs that would be substituted by the lookup
- * @glyphs_after: (out): Array of glyphs following the substition range
+ * @glyphs_after: (out): Array of glyphs following the substitution range
* @glyphs_output: (out): Array of glyphs that would be the substitued output of the lookup
*
* Fetches a list of all glyphs affected by the specified lookup in the
@@ -1458,8 +1513,8 @@ hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
**/
void
hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
- unsigned int lookup_index,
- hb_set_t *glyphs /* OUT */)
+ unsigned int lookup_index,
+ hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups;
OT::hb_closure_context_t c (face, glyphs, &done_lookups);
@@ -1494,7 +1549,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
do
{
glyphs_length = glyphs->get_population ();
- if (lookups != nullptr)
+ if (lookups)
{
for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);)
gsub.get_lookup (lookup_index).closure (&c, lookup_index);
@@ -1587,8 +1642,8 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
* specifically in their respective size ranges; other ways to differentiate fonts within
* a subfamily are not covered by the `size` feature.
*
- * For more information on this distinction, see the `size` documentation at
- * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-39size39
+ * For more information on this distinction, see the [`size` feature documentation](
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size).
*
* Return value: true if data found, false otherwise
*
@@ -1957,7 +2012,7 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
*
* Fetches a baseline value from the face.
*
- * Return value: if found baseline value in the the font.
+ * Return value: if found baseline value in the font.
*
* Since: 2.6.0
**/
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h
index 7e8a897cff5..0bd66166a35 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h
@@ -161,7 +161,7 @@ HB_EXTERN hb_bool_t
hb_ot_layout_table_find_script (hb_face_t *face,
hb_tag_t table_tag,
hb_tag_t script_tag,
- unsigned int *script_index);
+ unsigned int *script_index /* OUT */);
HB_EXTERN hb_bool_t
hb_ot_layout_table_select_script (hb_face_t *face,
@@ -199,15 +199,15 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
- unsigned int *feature_index);
+ unsigned int *feature_index /* OUT */);
HB_EXTERN hb_bool_t
hb_ot_layout_language_get_required_feature (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
- unsigned int *feature_index,
- hb_tag_t *feature_tag);
+ unsigned int *feature_index /* OUT */,
+ hb_tag_t *feature_tag /* OUT */);
HB_EXTERN unsigned int
hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
@@ -233,7 +233,7 @@ hb_ot_layout_language_find_feature (hb_face_t *face,
unsigned int script_index,
unsigned int language_index,
hb_tag_t feature_tag,
- unsigned int *feature_index);
+ unsigned int *feature_index /* OUT */);
HB_EXTERN unsigned int
hb_ot_layout_feature_get_lookups (hb_face_t *face,
@@ -263,6 +263,20 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
const hb_tag_t *features,
hb_set_t *lookup_indexes /* OUT */);
+#ifdef HB_EXPERIMENTAL_API
+HB_EXTERN void
+hb_ot_layout_closure_lookups (hb_face_t *face,
+ hb_tag_t table_tag,
+ const hb_set_t *glyphs,
+ hb_set_t *lookup_indexes /* IN/OUT */);
+
+HB_EXTERN void
+hb_ot_layout_closure_features (hb_face_t *face,
+ hb_tag_t table_tag,
+ const hb_map_t *lookup_indexes, /* IN */
+ hb_set_t *feature_indexes /* OUT */);
+#endif
+
HB_EXTERN void
hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
hb_tag_t table_tag,
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
index f3bb15581a1..4e052b0c263 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.hh
@@ -80,14 +80,14 @@ enum hb_ot_layout_glyph_props_flags_t
HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE = 0x04u,
HB_OT_LAYOUT_GLYPH_PROPS_MARK = 0x08u,
+ HB_OT_LAYOUT_GLYPH_PROPS_CLASS_MASK = HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH |
+ HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE |
+ HB_OT_LAYOUT_GLYPH_PROPS_MARK,
+
/* The following are used internally; not derived from GDEF. */
HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u,
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x20u,
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED = 0x40u,
-
- HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
- HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
- HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
};
HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh
index 0a4827d745a..b4f2fb904bf 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh
@@ -134,13 +134,13 @@ struct hb_ot_map_t
unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const
{
const feature_map_t *map = features.bsearch (feature_tag);
- return map ? map->stage[table_index] : (unsigned int) -1;
+ return map ? map->stage[table_index] : UINT_MAX;
}
void get_stage_lookups (unsigned int table_index, unsigned int stage,
const struct lookup_map_t **plookups, unsigned int *lookup_count) const
{
- if (unlikely (stage == (unsigned int) -1)) {
+ if (unlikely (stage == UINT_MAX)) {
*plookups = nullptr;
*lookup_count = 0;
return;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh
index 7529e0c0800..0033f4cc6e7 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh
@@ -48,7 +48,7 @@ struct MathValueRecord
}
protected:
- HBINT16 value; /* The X or Y value in design units */
+ HBINT16 value; /* The X or Y value in design units */
OffsetTo<Device> deviceTable; /* Offset to the device table - from the
* beginning of parent table. May be NULL.
* Suggested format for device table is 1. */
@@ -279,14 +279,15 @@ struct MathKern
protected:
HBUINT16 heightCount;
UnsizedArrayOf<MathValueRecord>
- mathValueRecordsZ; /* Array of correction heights at
- * which the kern value changes.
- * Sorted by the height value in
- * design units (heightCount entries),
- * Followed by:
- * Array of kern values corresponding
- * to heights. (heightCount+1 entries).
- */
+ mathValueRecordsZ;
+ /* Array of correction heights at
+ * which the kern value changes.
+ * Sorted by the height value in
+ * design units (heightCount entries),
+ * Followed by:
+ * Array of kern values corresponding
+ * to heights. (heightCount+1 entries).
+ */
public:
DEFINE_SIZE_ARRAY (2, mathValueRecordsZ);
@@ -345,15 +346,18 @@ struct MathKernInfo
}
protected:
- OffsetTo<Coverage> mathKernCoverage; /* Offset to Coverage table -
- * from the beginning of the
- * MathKernInfo table. */
- ArrayOf<MathKernInfoRecord> mathKernInfoRecords; /* Array of
- * MathKernInfoRecords,
- * per-glyph information for
- * mathematical positioning
- * of subscripts and
- * superscripts. */
+ OffsetTo<Coverage>
+ mathKernCoverage;
+ /* Offset to Coverage table -
+ * from the beginning of the
+ * MathKernInfo table. */
+ ArrayOf<MathKernInfoRecord>
+ mathKernInfoRecords;
+ /* Array of MathKernInfoRecords,
+ * per-glyph information for
+ * mathematical positioning
+ * of subscripts and
+ * superscripts. */
public:
DEFINE_SIZE_ARRAY (4, mathKernInfoRecords);
@@ -471,19 +475,21 @@ struct MathGlyphPartRecord
}
protected:
- HBGlyphID glyph; /* Glyph ID for the part. */
- HBUINT16 startConnectorLength; /* Advance width/ height of the straight bar
- * connector material, in design units, is at
- * the beginning of the glyph, in the
- * direction of the extension. */
- HBUINT16 endConnectorLength; /* Advance width/ height of the straight bar
- * connector material, in design units, is at
- * the end of the glyph, in the direction of
- * the extension. */
- HBUINT16 fullAdvance; /* Full advance width/height for this part,
- * in the direction of the extension.
- * In design units. */
- PartFlags partFlags; /* Part qualifiers. */
+ HBGlyphID glyph; /* Glyph ID for the part. */
+ HBUINT16 startConnectorLength;
+ /* Advance width/ height of the straight bar
+ * connector material, in design units, is at
+ * the beginning of the glyph, in the
+ * direction of the extension. */
+ HBUINT16 endConnectorLength;
+ /* Advance width/ height of the straight bar
+ * connector material, in design units, is at
+ * the end of the glyph, in the direction of
+ * the extension. */
+ HBUINT16 fullAdvance; /* Full advance width/height for this part,
+ * in the direction of the extension.
+ * In design units. */
+ PartFlags partFlags; /* Part qualifiers. */
public:
DEFINE_SIZE_STATIC (10);
@@ -522,12 +528,15 @@ struct MathGlyphAssembly
}
protected:
- MathValueRecord italicsCorrection; /* Italics correction of this
- * MathGlyphAssembly. Should not
- * depend on the assembly size. */
- ArrayOf<MathGlyphPartRecord> partRecords; /* Array of part records, from
- * left to right and bottom to
- * top. */
+ MathValueRecord
+ italicsCorrection;
+ /* Italics correction of this
+ * MathGlyphAssembly. Should not
+ * depend on the assembly size. */
+ ArrayOf<MathGlyphPartRecord>
+ partRecords; /* Array of part records, from
+ * left to right and bottom to
+ * top. */
public:
DEFINE_SIZE_ARRAY (6, partRecords);
@@ -645,27 +654,30 @@ struct MathVariants
}
protected:
- HBUINT16 minConnectorOverlap; /* Minimum overlap of connecting
- * glyphs during glyph construction,
- * in design units. */
- OffsetTo<Coverage> vertGlyphCoverage; /* Offset to Coverage table -
- * from the beginning of MathVariants
- * table. */
- OffsetTo<Coverage> horizGlyphCoverage; /* Offset to Coverage table -
- * from the beginning of MathVariants
- * table. */
- HBUINT16 vertGlyphCount; /* Number of glyphs for which
- * information is provided for
- * vertically growing variants. */
- HBUINT16 horizGlyphCount; /* Number of glyphs for which
- * information is provided for
- * horizontally growing variants. */
+ HBUINT16 minConnectorOverlap;
+ /* Minimum overlap of connecting
+ * glyphs during glyph construction,
+ * in design units. */
+ OffsetTo<Coverage> vertGlyphCoverage;
+ /* Offset to Coverage table -
+ * from the beginning of MathVariants
+ * table. */
+ OffsetTo<Coverage> horizGlyphCoverage;
+ /* Offset to Coverage table -
+ * from the beginning of MathVariants
+ * table. */
+ HBUINT16 vertGlyphCount; /* Number of glyphs for which
+ * information is provided for
+ * vertically growing variants. */
+ HBUINT16 horizGlyphCount;/* Number of glyphs for which
+ * information is provided for
+ * horizontally growing variants. */
/* Array of offsets to MathGlyphConstruction tables - from the beginning of
the MathVariants table, for shapes growing in vertical/horizontal
direction. */
UnsizedArrayOf<OffsetTo<MathGlyphConstruction>>
- glyphConstruction;
+ glyphConstruction;
public:
DEFINE_SIZE_ARRAY (10, glyphConstruction);
@@ -702,11 +714,14 @@ struct MATH
const MathVariants &get_variants () const { return this+mathVariants; }
protected:
- FixedVersion<>version; /* Version of the MATH table
- * initially set to 0x00010000u */
- OffsetTo<MathConstants> mathConstants;/* MathConstants table */
- OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
- OffsetTo<MathVariants> mathVariants; /* MathVariants table */
+ FixedVersion<>version; /* Version of the MATH table
+ * initially set to 0x00010000u */
+ OffsetTo<MathConstants>
+ mathConstants; /* MathConstants table */
+ OffsetTo<MathGlyphInfo>
+ mathGlyphInfo; /* MathGlyphInfo table */
+ OffsetTo<MathVariants>
+ mathVariants; /* MathVariants table */
public:
DEFINE_SIZE_STATIC (10);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-maxp-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-maxp-table.hh
index 1c25eda16b5..929956d12bf 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-maxp-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-maxp-table.hh
@@ -126,9 +126,10 @@ struct maxp
}
protected:
- FixedVersion<>version; /* Version of the maxp table (0.5 or 1.0),
- * 0x00005000u or 0x00010000u. */
- HBUINT16 numGlyphs; /* The number of glyphs in the font. */
+ FixedVersion<>version;/* Version of the maxp table (0.5 or 1.0),
+ * 0x00005000u or 0x00010000u. */
+ HBUINT16 numGlyphs;
+ /* The number of glyphs in the font. */
/*maxpV1Tail v1Tail[HB_VAR_ARRAY]; */
public:
DEFINE_SIZE_STATIC (6);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh
index 43a02d6cec3..1225e26ce1e 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-meta-table.hh
@@ -56,7 +56,7 @@ struct DataMap
protected:
Tag tag; /* A tag indicating the type of metadata. */
- LOffsetTo<UnsizedArrayOf<HBUINT8>>
+ LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
dataZ; /* Offset in bytes from the beginning of the
* metadata table to the data for this tag. */
HBUINT32 dataLength; /* Length of the data. The data is not required to
@@ -108,12 +108,13 @@ struct meta
protected:
HBUINT32 version; /* Version number of the metadata table — set to 1. */
HBUINT32 flags; /* Flags — currently unused; set to 0. */
- HBUINT32 dataOffset; /* Per Apple specification:
+ HBUINT32 dataOffset;
+ /* Per Apple specification:
* Offset from the beginning of the table to the data.
* Per OT specification:
* Reserved. Not used; should be set to 0. */
LArrayOf<DataMap>
- dataMaps; /* Array of data map records. */
+ dataMaps;/* Array of data map records. */
public:
DEFINE_SIZE_ARRAY (16, dataMaps);
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language-static.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language-static.hh
index 580e7637b90..c496dc2981a 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language-static.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language-static.hh
@@ -37,12 +37,8 @@
struct hb_ot_language_map_t
{
- static int cmp (const void *key, const void *item)
- {
- unsigned int a = * (unsigned int *) key;
- unsigned int b = ((const hb_ot_language_map_t *) item)->code;
- return a < b ? -1 : a > b ? +1 : 0;
- }
+ int cmp (unsigned int key) const
+ { return key < code ? -1 : key > code ? +1 : 0; }
uint16_t code;
char lang[6];
@@ -433,12 +429,7 @@ _hb_ot_name_language_for (unsigned int code,
#ifdef HB_NO_OT_NAME_LANGUAGE
return HB_LANGUAGE_INVALID;
#endif
- const hb_ot_language_map_t *entry = (const hb_ot_language_map_t *)
- hb_bsearch (&code,
- array,
- len,
- sizeof (array[0]),
- hb_ot_language_map_t::cmp);
+ auto *entry = hb_bsearch (code, array, len);
if (entry)
return hb_language_from_string (entry->lang, -1);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh
index 84be04c8bfd..b46976d46b3 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh
@@ -97,17 +97,47 @@ struct NameRecord
return UNSUPPORTED;
}
- NameRecord* copy (hb_serialize_context_t *c,
- const void *src_base,
- const void *dst_base) const
+ NameRecord* copy (hb_serialize_context_t *c, const void *base) const
{
TRACE_SERIALIZE (this);
auto *out = c->embed (this);
if (unlikely (!out)) return_trace (nullptr);
- out->offset.serialize_copy (c, offset, src_base, dst_base, length);
+ out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length);
return_trace (out);
}
+ bool isUnicode () const
+ {
+ unsigned int p = platformID;
+ unsigned int e = encodingID;
+
+ return (p == 0 ||
+ (p == 3 && (e == 0 || e == 1 || e == 10)));
+ }
+
+ static int cmp (const void *pa, const void *pb)
+ {
+ const NameRecord *a = (const NameRecord *)pa;
+ const NameRecord *b = (const NameRecord *)pb;
+
+ if (a->platformID != b->platformID)
+ return a->platformID - b->platformID;
+
+ if (a->encodingID != b->encodingID)
+ return a->encodingID - b->encodingID;
+
+ if (a->languageID != b->languageID)
+ return a->languageID - b->languageID;
+
+ if (a->nameID != b->nameID)
+ return a->nameID - b->nameID;
+
+ if (a->length != b->length)
+ return a->length - b->length;
+
+ return 0;
+ }
+
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -134,7 +164,7 @@ _hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
/* Compare by name_id, then language. */
if (a->name_id != b->name_id)
- return a->name_id < b->name_id ? -1 : +1;
+ return a->name_id - b->name_id;
if (a->language == b->language) return 0;
if (!a->language) return -1;
@@ -156,10 +186,10 @@ _hb_ot_name_entry_cmp (const void *pa, const void *pb)
const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
if (a->entry_score != b->entry_score)
- return a->entry_score < b->entry_score ? -1 : +1;
+ return a->entry_score - b->entry_score;
if (a->entry_index != b->entry_index)
- return a->entry_index < b->entry_index ? -1 : +1;
+ return a->entry_index - b->entry_index;
return 0;
}
@@ -184,18 +214,23 @@ struct name
this->format = 0;
this->count = it.len ();
- auto snap = c->snapshot ();
- this->nameRecordZ.serialize (c, this->count);
- if (unlikely (!c->check_assign (this->stringOffset, c->length ()))) return_trace (false);
- c->revert (snap);
+ NameRecord *name_records = (NameRecord *) calloc (it.len (), NameRecord::static_size);
+ hb_array_t<NameRecord> records (name_records, it.len ());
+
+ for (const NameRecord& record : it)
+ {
+ memcpy (name_records, &record, NameRecord::static_size);
+ name_records++;
+ }
- const void *dst_string_pool = &(this + this->stringOffset);
+ records.qsort ();
- for (const auto &_ : it) c->copy (_, src_string_pool, dst_string_pool);
+ c->copy_all (records, src_string_pool);
+ free (records.arrayZ);
if (unlikely (c->ran_out_of_room)) return_trace (false);
- assert (this->stringOffset == c->length ());
+ this->stringOffset = c->length ();
return_trace (true);
}
@@ -210,6 +245,8 @@ struct name
auto it =
+ nameRecordZ.as_array (count)
| hb_filter (c->plan->name_ids, &NameRecord::nameID)
+ | hb_filter (c->plan->name_languages, &NameRecord::languageID)
+ | hb_filter ([&] (const NameRecord& namerecord) { return c->plan->name_legacy || namerecord.isUnicode (); })
;
name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset));
@@ -237,7 +274,7 @@ struct name
{
void init (hb_face_t *face)
{
- this->table = hb_sanitize_context_t().reference_table<name> (face);
+ this->table = hb_sanitize_context_t ().reference_table<name> (face);
assert (this->table.get_length () >= this->table->stringOffset);
this->pool = (const char *) (const void *) (this->table+this->table->stringOffset);
this->pool_len = this->table.get_length () - this->table->stringOffset;
@@ -281,16 +318,14 @@ struct name
this->table.destroy ();
}
- int get_index (hb_ot_name_id_t name_id,
- hb_language_t language,
- unsigned int *width=nullptr) const
+ int get_index (hb_ot_name_id_t name_id,
+ hb_language_t language,
+ unsigned int *width=nullptr) const
{
const hb_ot_name_entry_t key = {name_id, {0}, language};
- const hb_ot_name_entry_t *entry = (const hb_ot_name_entry_t *)
- hb_bsearch (&key,
- (const hb_ot_name_entry_t *) this->names,
+ const hb_ot_name_entry_t *entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
this->names.length,
- sizeof (key),
+ sizeof (hb_ot_name_entry_t),
_hb_ot_name_entry_cmp_key);
if (!entry)
return -1;
@@ -318,12 +353,12 @@ struct name
};
/* We only implement format 0 for now. */
- HBUINT16 format; /* Format selector (=0/1). */
- HBUINT16 count; /* Number of name records. */
+ HBUINT16 format; /* Format selector (=0/1). */
+ HBUINT16 count; /* Number of name records. */
NNOffsetTo<UnsizedArrayOf<HBUINT8>>
- stringOffset; /* Offset to start of string storage (from start of table). */
+ stringOffset; /* Offset to start of string storage (from start of table). */
UnsizedArrayOf<NameRecord>
- nameRecordZ; /* The name records where count is the number of records. */
+ nameRecordZ; /* The name records where count is the number of records. */
public:
DEFINE_SIZE_ARRAY (6, nameRecordZ);
};
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 f6b150323b6..bcbc3315926 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
@@ -216,19 +216,20 @@ struct OS2
uint16_t *min_cp, /* OUT */
uint16_t *max_cp /* OUT */)
{
- *min_cp = codepoints->get_min ();
- *max_cp = codepoints->get_max ();
+ *min_cp = hb_min (0xFFFFu, codepoints->get_min ());
+ *max_cp = hb_min (0xFFFFu, codepoints->get_max ());
}
/* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 */
- enum font_page_t {
- HEBREW_FONT_PAGE = 0xB100, // Hebrew Windows 3.1 font page
- SIMP_ARABIC_FONT_PAGE = 0xB200, // Simplified Arabic Windows 3.1 font page
- TRAD_ARABIC_FONT_PAGE = 0xB300, // Traditional Arabic Windows 3.1 font page
- OEM_ARABIC_FONT_PAGE = 0xB400, // OEM Arabic Windows 3.1 font page
- SIMP_FARSI_FONT_PAGE = 0xBA00, // Simplified Farsi Windows 3.1 font page
- TRAD_FARSI_FONT_PAGE = 0xBB00, // Traditional Farsi Windows 3.1 font page
- THAI_FONT_PAGE = 0xDE00 // Thai Windows 3.1 font page
+ enum font_page_t
+ {
+ FONT_PAGE_HEBREW = 0xB100, /* Hebrew Windows 3.1 font page */
+ FONT_PAGE_SIMP_ARABIC = 0xB200, /* Simplified Arabic Windows 3.1 font page */
+ FONT_PAGE_TRAD_ARABIC = 0xB300, /* Traditional Arabic Windows 3.1 font page */
+ FONT_PAGE_OEM_ARABIC = 0xB400, /* OEM Arabic Windows 3.1 font page */
+ FONT_PAGE_SIMP_FARSI = 0xBA00, /* Simplified Farsi Windows 3.1 font page */
+ FONT_PAGE_TRAD_FARSI = 0xBB00, /* Traditional Farsi Windows 3.1 font page */
+ FONT_PAGE_THAI = 0xDE00 /* Thai Windows 3.1 font page */
};
font_page_t get_font_page () const
{ return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-unicode-ranges.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-unicode-ranges.hh
index b0ccd00d7b6..9613d2d186d 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-unicode-ranges.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-unicode-ranges.hh
@@ -33,19 +33,8 @@ namespace OT {
struct OS2Range
{
- static int
- cmp (const void *_key, const void *_item)
- {
- hb_codepoint_t cp = *((hb_codepoint_t *) _key);
- const OS2Range *range = (OS2Range *) _item;
-
- if (cp < range->start)
- return -1;
- else if (cp <= range->end)
- return 0;
- else
- return +1;
- }
+ int cmp (hb_codepoint_t key) const
+ { return (key < start) ? -1 : key <= end ? 0 : +1; }
hb_codepoint_t start;
hb_codepoint_t end;
@@ -233,13 +222,8 @@ static const OS2Range _hb_os2_unicode_ranges[] =
static unsigned int
_hb_ot_os2_get_unicode_range_bit (hb_codepoint_t cp)
{
- OS2Range *range = (OS2Range*) hb_bsearch (&cp, _hb_os2_unicode_ranges,
- ARRAY_LENGTH (_hb_os2_unicode_ranges),
- sizeof (OS2Range),
- OS2Range::cmp);
- if (range != nullptr)
- return range->bit;
- return -1;
+ auto *range = hb_sorted_array (_hb_os2_unicode_ranges).bsearch (cp);
+ return range ? range->bit : -1;
}
} /* namespace OT */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh
index 38302f5518e..8586331cd45 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-post-table.hh
@@ -35,8 +35,6 @@
#undef HB_STRING_ARRAY_LIST
#undef HB_STRING_ARRAY_NAME
-#define NUM_FORMAT1_NAMES 258
-
/*
* post -- PostScript
* https://docs.microsoft.com/en-us/typography/opentype/spec/post
@@ -167,8 +165,7 @@ struct post
}
hb_bytes_t st (name, len);
- const uint16_t *gid = (const uint16_t *) hb_bsearch (hb_addressof (st), gids, count,
- sizeof (gids[0]), cmp_key, (void *) this);
+ auto* gid = hb_bsearch (st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
if (gid)
{
*glyph = *gid;
@@ -185,7 +182,7 @@ struct post
unsigned int get_glyph_count () const
{
if (version == 0x00010000)
- return NUM_FORMAT1_NAMES;
+ return format1_names_length;
if (version == 0x00020000)
return glyphNameIndex->len;
@@ -213,7 +210,7 @@ struct post
{
if (version == 0x00010000)
{
- if (glyph >= NUM_FORMAT1_NAMES)
+ if (glyph >= format1_names_length)
return hb_bytes_t ();
return format1_names (glyph);
@@ -223,9 +220,9 @@ struct post
return hb_bytes_t ();
unsigned int index = glyphNameIndex->arrayZ[glyph];
- if (index < NUM_FORMAT1_NAMES)
+ if (index < format1_names_length)
return format1_names (index);
- index -= NUM_FORMAT1_NAMES;
+ index -= format1_names_length;
if (index >= index_to_offset.length)
return hb_bytes_t ();
@@ -262,7 +259,7 @@ struct post
* 0x00020000 for version 2.0
* 0x00025000 for version 2.5 (deprecated)
* 0x00030000 for version 3.0 */
- HBFixed italicAngle; /* Italic angle in counter-clockwise degrees
+ HBFixed italicAngle; /* Italic angle in counter-clockwise degrees
* from the vertical. Zero for upright text,
* negative for text that leans to the right
* (forward). */
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 2a7a8ebbc02..262ab8a1fab 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
@@ -292,7 +292,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
{
arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
if (unlikely (!fallback_plan))
- return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
+ return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
fallback_plan->num_lookups = 0;
fallback_plan->free_lookups = false;
@@ -309,7 +309,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
assert (fallback_plan->num_lookups == 0);
free (fallback_plan);
- return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
+ return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
}
static void
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc
index f92e6378a1f..0c1863bc51b 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc
@@ -271,7 +271,7 @@ data_create_arabic (const hb_ot_shape_plan_t *plan)
arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
arabic_plan->do_fallback = arabic_plan->do_fallback &&
(FEATURE_IS_SYRIAC (arabic_features[i]) ||
- plan->map.needs_fallback (arabic_features[i]));
+ plan->map.needs_fallback (arabic_features[i]));
}
return arabic_plan;
@@ -292,7 +292,7 @@ arabic_joining (hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
- unsigned int prev = (unsigned int) -1, state = 0;
+ unsigned int prev = UINT_MAX, state = 0;
/* Check pre-context */
for (unsigned int i = 0; i < buffer->context_len[0]; i++)
@@ -318,7 +318,7 @@ arabic_joining (hb_buffer_t *buffer)
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
- if (entry->prev_action != NONE && prev != (unsigned int) -1)
+ if (entry->prev_action != NONE && prev != UINT_MAX)
{
info[prev].arabic_shaping_action() = entry->prev_action;
buffer->unsafe_to_break (prev, i + 1);
@@ -338,7 +338,7 @@ arabic_joining (hb_buffer_t *buffer)
continue;
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
- if (entry->prev_action != NONE && prev != (unsigned int) -1)
+ if (entry->prev_action != NONE && prev != UINT_MAX)
info[prev].arabic_shaping_action() = entry->prev_action;
break;
}
@@ -604,7 +604,7 @@ postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
}
-/* http://www.unicode.org/reports/tr53/ */
+/* https://www.unicode.org/reports/tr53/ */
static hb_codepoint_t
modifier_combining_marks[] =
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc
index a921f16fada..a755aea098b 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-default.cc
@@ -49,5 +49,25 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
true, /* fallback_position */
};
+/* Same as default but no mark advance zeroing / fallback positioning.
+ * Dumbest shaper ever, basically. */
+const hb_ot_complex_shaper_t _hb_ot_complex_shaper_dumber =
+{
+ nullptr, /* collect_features */
+ nullptr, /* override_features */
+ nullptr, /* data_create */
+ nullptr, /* data_destroy */
+ nullptr, /* preprocess_text */
+ nullptr, /* postprocess_glyphs */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
+ nullptr, /* decompose */
+ nullptr, /* compose */
+ nullptr, /* setup_masks */
+ HB_TAG_NONE, /* gpos_tag */
+ nullptr, /* reorder_marks */
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+ false, /* fallback_position */
+};
+
#endif
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic-machine.rl b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic-machine.rl
index 5f819bd2964..1613548a5da 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic-machine.rl
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic-machine.rl
@@ -76,7 +76,7 @@ complex_syllable_tail = (halant_group.cn)* medial_group halant_or_matra_group sy
consonant_syllable = (Repha|CS)? cn complex_syllable_tail;
vowel_syllable = reph? V.n? (ZWJ | complex_syllable_tail);
standalone_cluster = ((Repha|CS)? PLACEHOLDER | reph? DOTTEDCIRCLE).n? complex_syllable_tail;
-symbol_cluster = symbol syllable_tail;
+symbol_cluster = symbol syllable_tail;
broken_cluster = reph? n? complex_syllable_tail;
other = any;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc
index 26dc60ddc98..3dab3aa11c9 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc
@@ -248,6 +248,7 @@ struct indic_shape_plan_t
hb_indic_would_substitute_feature_t pref;
hb_indic_would_substitute_feature_t blwf;
hb_indic_would_substitute_feature_t pstf;
+ hb_indic_would_substitute_feature_t vatu;
hb_mask_t mask_array[INDIC_NUM_FEATURES];
};
@@ -286,6 +287,7 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context);
indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context);
indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f'), zero_context);
+ indic_plan->vatu.init (&plan->map, HB_TAG('v','a','t','u'), zero_context);
for (unsigned int i = 0; i < ARRAY_LENGTH (indic_plan->mask_array); i++)
indic_plan->mask_array[i] = (indic_features[i].flags & F_GLOBAL) ?
@@ -315,10 +317,16 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan,
* base at 0. The font however, only has lookups matching
* 930,94D in 'blwf', not the expected 94D,930 (with new-spec
* table). As such, we simply match both sequences. Seems
- * to work. */
+ * to work.
+ *
+ * Vatu is done as well, for:
+ * https://github.com/harfbuzz/harfbuzz/issues/1587
+ */
hb_codepoint_t glyphs[3] = {virama, consonant, virama};
if (indic_plan->blwf.would_substitute (glyphs , 2, face) ||
- indic_plan->blwf.would_substitute (glyphs+1, 2, face))
+ indic_plan->blwf.would_substitute (glyphs+1, 2, face) ||
+ indic_plan->vatu.would_substitute (glyphs , 2, face) ||
+ indic_plan->vatu.would_substitute (glyphs+1, 2, face))
return POS_BELOW_C;
if (indic_plan->pstf.would_substitute (glyphs , 2, face) ||
indic_plan->pstf.would_substitute (glyphs+1, 2, face))
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar-machine.rl b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar-machine.rl
index 67133cd7346..098a63e53ac 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar-machine.rl
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar-machine.rl
@@ -78,7 +78,7 @@ complex_syllable_tail = As* medial_group main_vowel_group post_vowel_group* pwo_
syllable_tail = (H (c|IV).VS?)* (H | complex_syllable_tail);
consonant_syllable = (k|CS)? (c|IV|D|GB).VS? syllable_tail;
-punctuation_cluster = P V;
+punctuation_cluster = P V;
broken_cluster = k? VS? syllable_tail;
other = any;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.cc
index 2f8041323ab..fc09eccda33 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.cc
@@ -2,15 +2,16 @@
/*
* The following functions are generated by running:
*
- * ./gen-vowel-constraints.py use Scripts.txt
+ * ./gen-vowel-constraints.py ms-use/IndicShapingInvalidCluster.txt Scripts.txt
*
* on files with these headers:
*
- * # Copied from https://docs.microsoft.com/en-us/typography/script-development/use
- * # On October 23, 2018; with documentd dated 02/07/2018.
+ * # IndicShapingInvalidCluster.txt
+ * # Date: 2015-03-12, 21:17:00 GMT [AG]
+ * # Date: 2019-11-08, 23:22:00 GMT [AG]
*
- * # Scripts-12.0.0.txt
- * # Date: 2019-01-28, 22:16:47 GMT
+ * # Scripts-12.1.0.txt
+ * # Date: 2019-04-01, 09:10:42 GMT
*/
#include "hb.hh"
@@ -211,6 +212,22 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
processed = true;
break;
+ case HB_SCRIPT_TAMIL:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ if (0x0B85u == buffer->cur ().codepoint &&
+ 0x0BC2u == buffer->cur (1).codepoint)
+ {
+ buffer->next_glyph ();
+ _output_dotted_circle (buffer);
+ }
+ buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ processed = true;
+ break;
+
case HB_SCRIPT_TELUGU:
for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
{
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex.hh
index 2691622135a..a9f5834425a 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex.hh
@@ -50,8 +50,9 @@ enum hb_ot_shape_zero_width_marks_type_t {
/* Master OT shaper list */
#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
- HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
+ HB_COMPLEX_SHAPER_IMPLEMENT (default) \
+ HB_COMPLEX_SHAPER_IMPLEMENT (dumber) \
HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
@@ -60,7 +61,7 @@ enum hb_ot_shape_zero_width_marks_type_t {
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_zawgyi) \
HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
HB_COMPLEX_SHAPER_IMPLEMENT (use) \
- /* ^--- Add new shapers here */
+ /* ^--- Add new shapers here; keep sorted. */
struct hb_ot_complex_shaper_t
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc
index 024bcfe04fd..42bf524d164 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc
@@ -422,12 +422,12 @@ position_cluster (const hb_ot_shape_plan_t *plan,
/* Find the base glyph */
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = start; i < end; i++)
- if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
+ if (!_hb_glyph_info_is_unicode_mark (&info[i]))
{
/* Find mark glyphs */
unsigned int j;
for (j = i + 1; j < end; j++)
- if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
+ if (!_hb_glyph_info_is_unicode_mark (&info[j]))
break;
position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing);
@@ -452,7 +452,7 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 1; i < count; i++)
- if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
+ if (likely (!_hb_glyph_info_is_unicode_mark (&info[i]))) {
position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing);
start = i;
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc
index 553d5325749..50b5829c4aa 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc
@@ -334,7 +334,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
{
unsigned int end;
for (end = buffer->idx + 1; end < count; end++)
- if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
+ if (unlikely (_hb_glyph_info_is_unicode_mark (&buffer->info[end])))
break;
if (end < count)
@@ -360,7 +360,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
/* Find all the marks now. */
for (end = buffer->idx + 1; end < count; end++)
- if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))
+ if (!_hb_glyph_info_is_unicode_mark(&buffer->info[end]))
break;
/* idx to end is one non-simple cluster. */
@@ -435,7 +435,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
* This is both an optimization to avoid trying to compose every two neighboring
* glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul
* fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
- HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
+ _hb_glyph_info_is_unicode_mark(&buffer->cur()))
{
if (/* If there's anything between the starter and this char, they should have CCC
* smaller than this character's. */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
index 5d9a70cda2e..00ecdfab373 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc
@@ -48,6 +48,16 @@
#include "hb-aat-layout.hh"
+#ifndef HB_NO_AAT_SHAPE
+static inline bool
+_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t *props)
+{
+ /* https://github.com/harfbuzz/harfbuzz/issues/2124 */
+ return hb_aat_layout_has_substitution (face) &&
+ (HB_DIRECTION_IS_HORIZONTAL (props->direction) || !hb_ot_layout_has_substitution (face));
+}
+#endif
+
/**
* SECTION:hb-ot-shape
* @title: hb-ot-shape
@@ -63,23 +73,6 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
const hb_feature_t *user_features,
unsigned int num_user_features);
-#ifndef HB_NO_AAT_SHAPE
-static inline bool
-_hb_apply_morx (hb_face_t *face)
-{
- if (hb_options ().aat &&
- hb_aat_layout_has_substitution (face))
- return true;
-
- /* Ignore empty GSUB tables. */
- return (!hb_ot_layout_has_substitution (face) ||
- !hb_ot_layout_table_get_script_tags (face,
- HB_OT_TAG_GSUB,
- 0, nullptr, nullptr)) &&
- hb_aat_layout_has_substitution (face);
-}
-#endif
-
hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face,
const hb_segment_properties_t *props) :
face (face),
@@ -87,7 +80,7 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
map (face, props),
aat_map (face, props)
#ifndef HB_NO_AAT_SHAPE
- , apply_morx (_hb_apply_morx (face))
+ , apply_morx (_hb_apply_morx (face, props))
#endif
{
shaper = hb_ot_shape_complex_categorize (this);
@@ -95,8 +88,9 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
script_fallback_mark_positioning = shaper->fallback_position;
- if (apply_morx)
- shaper = &_hb_ot_complex_shaper_default;
+ /* https://github.com/harfbuzz/harfbuzz/issues/1528 */
+ if (apply_morx && shaper != &_hb_ot_complex_shaper_default)
+ shaper = &_hb_ot_complex_shaper_dumber;
}
void
@@ -119,6 +113,8 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
#endif
plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
+ plan.has_vert = !!plan.map.get_1_mask (HB_TAG ('v','e','r','t'));
+
hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ?
HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
#ifndef HB_NO_OT_KERN
@@ -156,17 +152,13 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
if (0)
;
#ifndef HB_NO_AAT_SHAPE
- else if (hb_options ().aat && hb_aat_layout_has_positioning (face))
+ else if (hb_aat_layout_has_positioning (face))
plan.apply_kerx = true;
#endif
else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face))
plan.apply_gpos = true;
-#ifndef HB_NO_AAT_SHAPE
- else if (hb_aat_layout_has_positioning (face))
- plan.apply_kerx = true;
-#endif
- if (!plan.apply_kerx && !has_gpos_kern)
+ if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos))
{
/* Apparently Apple applies kerx if GPOS kern was not applied. */
#ifndef HB_NO_AAT_SHAPE
@@ -594,24 +586,85 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
* Substitute
*/
-static inline void
-hb_ot_mirror_chars (const hb_ot_shape_context_t *c)
+static hb_codepoint_t
+hb_vert_char_for (hb_codepoint_t u)
{
- if (HB_DIRECTION_IS_FORWARD (c->target_direction))
- return;
+ switch (u >> 8)
+ {
+ case 0x20: switch (u) {
+ case 0x2013u: return 0xfe32u; // EN DASH
+ case 0x2014u: return 0xfe31u; // EM DASH
+ case 0x2025u: return 0xfe30u; // TWO DOT LEADER
+ case 0x2026u: return 0xfe19u; // HORIZONTAL ELLIPSIS
+ } break;
+ case 0x30: switch (u) {
+ case 0x3001u: return 0xfe11u; // IDEOGRAPHIC COMMA
+ case 0x3002u: return 0xfe12u; // IDEOGRAPHIC FULL STOP
+ case 0x3008u: return 0xfe3fu; // LEFT ANGLE BRACKET
+ case 0x3009u: return 0xfe40u; // RIGHT ANGLE BRACKET
+ case 0x300au: return 0xfe3du; // LEFT DOUBLE ANGLE BRACKET
+ case 0x300bu: return 0xfe3eu; // RIGHT DOUBLE ANGLE BRACKET
+ case 0x300cu: return 0xfe41u; // LEFT CORNER BRACKET
+ case 0x300du: return 0xfe42u; // RIGHT CORNER BRACKET
+ case 0x300eu: return 0xfe43u; // LEFT WHITE CORNER BRACKET
+ case 0x300fu: return 0xfe44u; // RIGHT WHITE CORNER BRACKET
+ case 0x3010u: return 0xfe3bu; // LEFT BLACK LENTICULAR BRACKET
+ case 0x3011u: return 0xfe3cu; // RIGHT BLACK LENTICULAR BRACKET
+ case 0x3014u: return 0xfe39u; // LEFT TORTOISE SHELL BRACKET
+ case 0x3015u: return 0xfe3au; // RIGHT TORTOISE SHELL BRACKET
+ case 0x3016u: return 0xfe17u; // LEFT WHITE LENTICULAR BRACKET
+ case 0x3017u: return 0xfe18u; // RIGHT WHITE LENTICULAR BRACKET
+ } break;
+ case 0xfe: switch (u) {
+ case 0xfe4fu: return 0xfe34u; // WAVY LOW LINE
+ } break;
+ case 0xff: switch (u) {
+ case 0xff01u: return 0xfe15u; // FULLWIDTH EXCLAMATION MARK
+ case 0xff08u: return 0xfe35u; // FULLWIDTH LEFT PARENTHESIS
+ case 0xff09u: return 0xfe36u; // FULLWIDTH RIGHT PARENTHESIS
+ case 0xff0cu: return 0xfe10u; // FULLWIDTH COMMA
+ case 0xff1au: return 0xfe13u; // FULLWIDTH COLON
+ case 0xff1bu: return 0xfe14u; // FULLWIDTH SEMICOLON
+ case 0xff1fu: return 0xfe16u; // FULLWIDTH QUESTION MARK
+ case 0xff3bu: return 0xfe47u; // FULLWIDTH LEFT SQUARE BRACKET
+ case 0xff3du: return 0xfe48u; // FULLWIDTH RIGHT SQUARE BRACKET
+ case 0xff3fu: return 0xfe33u; // FULLWIDTH LOW LINE
+ case 0xff5bu: return 0xfe37u; // FULLWIDTH LEFT CURLY BRACKET
+ case 0xff5du: return 0xfe38u; // FULLWIDTH RIGHT CURLY BRACKET
+ } break;
+ }
- hb_buffer_t *buffer = c->buffer;
- hb_unicode_funcs_t *unicode = buffer->unicode;
- hb_mask_t rtlm_mask = c->plan->rtlm_mask;
+ return u;
+}
+static inline void
+hb_ot_rotate_chars (const hb_ot_shape_context_t *c)
+{
+ hb_buffer_t *buffer = c->buffer;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++) {
- hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
- if (likely (codepoint == info[i].codepoint || !c->font->has_glyph (codepoint)))
- info[i].mask |= rtlm_mask;
- else
- info[i].codepoint = codepoint;
+
+ if (HB_DIRECTION_IS_BACKWARD (c->target_direction))
+ {
+ hb_unicode_funcs_t *unicode = buffer->unicode;
+ hb_mask_t rtlm_mask = c->plan->rtlm_mask;
+
+ for (unsigned int i = 0; i < count; i++) {
+ hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
+ if (unlikely (codepoint != info[i].codepoint && c->font->has_glyph (codepoint)))
+ info[i].codepoint = codepoint;
+ else
+ info[i].mask |= rtlm_mask;
+ }
+ }
+
+ if (HB_DIRECTION_IS_VERTICAL (c->target_direction) && !c->plan->has_vert)
+ {
+ for (unsigned int i = 0; i < count; i++) {
+ hb_codepoint_t codepoint = hb_vert_char_for (info[i].codepoint);
+ if (unlikely (codepoint != info[i].codepoint && c->font->has_glyph (codepoint)))
+ info[i].codepoint = codepoint;
+ }
}
}
@@ -693,7 +746,7 @@ hb_ot_shape_setup_masks (const hb_ot_shape_context_t *c)
for (unsigned int i = 0; i < c->num_user_features; i++)
{
const hb_feature_t *feature = &c->user_features[i];
- if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
+ if (!(feature->start == HB_FEATURE_GLOBAL_START && feature->end == HB_FEATURE_GLOBAL_END)) {
unsigned int shift;
hb_mask_t mask = map->get_mask (feature->tag, &shift);
buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
@@ -788,7 +841,7 @@ hb_ot_substitute_default (const hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
- hb_ot_mirror_chars (c);
+ hb_ot_rotate_chars (c);
HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh
index 2cde73d854c..acc98772a95 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh
@@ -37,9 +37,9 @@ struct hb_ot_shape_plan_key_t
{
unsigned int variations_index[2];
- void init (hb_face_t *face,
- const int *coords,
- unsigned int num_coords)
+ void init (hb_face_t *face,
+ const int *coords,
+ unsigned num_coords)
{
for (unsigned int table_index = 0; table_index < 2; table_index++)
hb_ot_layout_table_find_feature_variations (face,
@@ -99,6 +99,7 @@ struct hb_ot_shape_plan_t
#else
static constexpr bool has_frac = false;
#endif
+ bool has_vert : 1;
bool has_gpos_mark : 1;
bool zero_marks : 1;
bool fallback_glyph_classes : 1;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh
index 2cdd3a488b3..88135234db5 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-stat-table.hh
@@ -77,7 +77,7 @@ struct AxisValueFormat1
NameID valueNameID; /* The name ID for entries in the 'name' table
* that provide a display string for this
* attribute value. */
- HBFixed value; /* A numeric value for this attribute value. */
+ HBFixed value; /* A numeric value for this attribute value. */
public:
DEFINE_SIZE_STATIC (12);
};
@@ -102,10 +102,10 @@ struct AxisValueFormat2
NameID valueNameID; /* The name ID for entries in the 'name' table
* that provide a display string for this
* attribute value. */
- HBFixed nominalValue; /* A numeric value for this attribute value. */
- HBFixed rangeMinValue; /* The minimum value for a range associated
+ HBFixed nominalValue; /* A numeric value for this attribute value. */
+ HBFixed rangeMinValue; /* The minimum value for a range associated
* with the specified name ID. */
- HBFixed rangeMaxValue; /* The maximum value for a range associated
+ HBFixed rangeMaxValue; /* The maximum value for a range associated
* with the specified name ID. */
public:
DEFINE_SIZE_STATIC (20);
@@ -131,8 +131,8 @@ struct AxisValueFormat3
NameID valueNameID; /* The name ID for entries in the 'name' table
* that provide a display string for this
* attribute value. */
- HBFixed value; /* A numeric value for this attribute value. */
- HBFixed linkedValue; /* The numeric value for a style-linked mapping
+ HBFixed value; /* A numeric value for this attribute value. */
+ HBFixed linkedValue; /* The numeric value for a style-linked mapping
* from this value. */
public:
DEFINE_SIZE_STATIC (16);
@@ -150,7 +150,7 @@ struct AxisValueRecord
HBUINT16 axisIndex; /* Zero-base index into the axis record array
* identifying the axis to which this value
* applies. Must be less than designAxisCount. */
- HBFixed value; /* A numeric value for this attribute value. */
+ HBFixed value; /* A numeric value for this attribute value. */
public:
DEFINE_SIZE_STATIC (6);
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh
index ef8ba3f5a21..29219adb0a1 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-avar-table.hh
@@ -51,7 +51,7 @@ struct AxisValueMap
public:
F2DOT14 coords[2];
// F2DOT14 fromCoord; /* A normalized coordinate value obtained using
-// * default normalization. */
+// * default normalization. */
// F2DOT14 toCoord; /* The modified, normalized coordinate value. */
public:
@@ -79,7 +79,7 @@ struct SegmentMaps : ArrayOf<AxisValueMap>
return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
unsigned int i;
- unsigned int count = len;
+ unsigned int count = len - 1;
for (i = 1; i < count && value > arrayZ[i].fromCoord; i++)
;
@@ -90,9 +90,8 @@ struct SegmentMaps : ArrayOf<AxisValueMap>
return arrayZ[i-1].toCoord;
int denom = arrayZ[i].fromCoord - arrayZ[i-1].fromCoord;
- return arrayZ[i-1].toCoord +
- ((arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
- (value - arrayZ[i-1].fromCoord) + denom/2) / denom;
+ return roundf (arrayZ[i-1].toCoord + ((float) (arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
+ (value - arrayZ[i-1].fromCoord)) / denom);
#undef toCoord
#undef fromCoord
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh
index 7ce3123819d..af22f706e54 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-fvar-table.hh
@@ -83,9 +83,9 @@ struct AxisRecord
public:
Tag axisTag; /* Tag identifying the design variation for the axis. */
- HBFixed minValue; /* The minimum coordinate value for the axis. */
- HBFixed defaultValue; /* The default coordinate value for the axis. */
- HBFixed maxValue; /* The maximum coordinate value for the axis. */
+ HBFixed minValue; /* The minimum coordinate value for the axis. */
+ HBFixed defaultValue; /* The default coordinate value for the axis. */
+ HBFixed maxValue; /* The maximum coordinate value for the axis. */
HBUINT16 flags; /* Axis flags. */
NameID axisNameID; /* The name ID for entries in the 'name' table that
* provide a display name for this axis. */
@@ -150,17 +150,8 @@ struct fvar
{
if (axes_count)
{
- /* TODO Rewrite as hb_array_t<>::sub-array() */
- unsigned int count = axisCount;
- start_offset = hb_min (start_offset, count);
-
- count -= start_offset;
- axes_array += start_offset;
-
- count = hb_min (count, *axes_count);
- *axes_count = count;
-
- for (unsigned int i = 0; i < count; i++)
+ hb_array_t<const AxisRecord> arr = hb_array (&(this+firstAxis), axisCount).sub_array (start_offset, axes_count);
+ for (unsigned i = 0; i < arr.length; ++i)
get_axis_deprecated (start_offset + i, axes_array + i);
}
return axisCount;
@@ -173,17 +164,8 @@ struct fvar
{
if (axes_count)
{
- /* TODO Rewrite as hb_array_t<>::sub-array() */
- unsigned int count = axisCount;
- start_offset = hb_min (start_offset, count);
-
- count -= start_offset;
- axes_array += start_offset;
-
- count = hb_min (count, *axes_count);
- *axes_count = count;
-
- for (unsigned int i = 0; i < count; i++)
+ hb_array_t<const AxisRecord> arr = hb_array (&(this+firstAxis), axisCount).sub_array (start_offset, axes_count);
+ for (unsigned i = 0; i < arr.length; ++i)
get_axis_info (start_offset + i, axes_array + i);
}
return axisCount;
@@ -229,7 +211,7 @@ struct fvar
hb_ot_var_axis_info_t axis;
get_axis_info (axis_index, &axis);
- v = hb_max (hb_min (v, axis.max_value), axis.min_value); /* Clamp. */
+ v = hb_clamp (v, axis.min_value, axis.max_value);
if (v == axis.default_value)
return 0;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
index a76121d8605..db944f6dc51 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
@@ -29,8 +29,6 @@
#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
@@ -42,12 +40,14 @@ namespace OT {
struct contour_point_t
{
- void init (float x_=0.f, float y_=0.f) { flag = 0; x = x_; y = y_; }
+ void init (float x_ = 0.f, float y_ = 0.f, bool is_end_point_ = false)
+ { flag = 0; x = x_; y = y_; is_end_point = is_end_point_; }
void translate (const contour_point_t &p) { x += p.x; y += p.y; }
uint8_t flag;
float x, y;
+ bool is_end_point;
};
struct contour_point_vector_t : hb_vector_t<contour_point_t>
@@ -78,50 +78,34 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t>
}
};
-struct Tuple : UnsizedArrayOf<F2DOT14> {};
-
-struct TuppleIndex : HBUINT16
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
+struct TupleVariationHeader
{
- enum Flags {
- EmbeddedPeakTuple = 0x8000u,
- IntermediateRegion = 0x4000u,
- PrivatePointNumbers = 0x2000u,
- TupleIndexMask = 0x0FFFu
- };
-
- DEFINE_SIZE_STATIC (2);
-};
+ unsigned get_size (unsigned axis_count) const
+ { return min_size + get_all_tuples (axis_count).get_size (); }
-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);
- }
+ unsigned get_data_size () const { return varDataSize; }
- const TupleVarHeader &get_next (unsigned int axis_count) const
- { return StructAtOffset<TupleVarHeader> (this, get_size (axis_count)); }
+ const TupleVariationHeader &get_next (unsigned axis_count) const
+ { return StructAtOffset<TupleVariationHeader> (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 hb_array_t<const F2DOT14> shared_tuples) const
{
- const F2DOT14 *peak_tuple;
+ hb_array_t<const F2DOT14> peak_tuple;
if (has_peak ())
- peak_tuple = &(get_peak_tuple ()[0]);
+ peak_tuple = get_peak_tuple (coord_count);
else
{
unsigned int index = get_index ();
if (unlikely (index * coord_count >= shared_tuples.length))
return 0.f;
- peak_tuple = &shared_tuples[coord_count * index];
+ peak_tuple = shared_tuples.sub_array (coord_count * index, coord_count);
}
- const F2DOT14 *start_tuple = nullptr;
- const F2DOT14 *end_tuple = nullptr;
+ hb_array_t<const F2DOT14> start_tuple;
+ hb_array_t<const F2DOT14> end_tuple;
if (has_intermediate ())
{
start_tuple = get_start_tuple (coord_count);
@@ -154,58 +138,64 @@ struct TupleVarHeader
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;
+ struct TuppleIndex : HBUINT16
+ {
+ enum Flags {
+ EmbeddedPeakTuple = 0x8000u,
+ IntermediateRegion = 0x4000u,
+ PrivatePointNumbers = 0x2000u,
+ TupleIndexMask = 0x0FFFu
+ };
+
+ DEFINE_SIZE_STATIC (2);
+ };
+
+ hb_array_t<const F2DOT14> get_all_tuples (unsigned axis_count) const
+ { return StructAfter<UnsizedArrayOf<F2DOT14>> (tupleIndex).as_array ((has_peak () + has_intermediate () * 2) * axis_count); }
+ hb_array_t<const F2DOT14> get_peak_tuple (unsigned axis_count) const
+ { return get_all_tuples (axis_count).sub_array (0, axis_count); }
+ hb_array_t<const F2DOT14> get_start_tuple (unsigned axis_count) const
+ { return get_all_tuples (axis_count).sub_array (has_peak () * axis_count, axis_count); }
+ hb_array_t<const F2DOT14> get_end_tuple (unsigned axis_count) const
+ { return get_all_tuples (axis_count).sub_array (has_peak () * axis_count + axis_count, axis_count); }
+
+ HBUINT16 varDataSize; /* The size in bytes of the serialized
+ * data for this tuple variation table. */
+ TuppleIndex tupleIndex; /* A packed field. The high 4 bits are flags (see below).
+ The low 12 bits are an index into a shared tuple
+ records array. */
/* UnsizedArrayOf<F2DOT14> peakTuple - optional */
+ /* Peak tuple record for this tuple variation table — optional,
+ * determined by flags in the tupleIndex value.
+ *
+ * Note that this must always be included in the 'cvar' table. */
/* UnsizedArrayOf<F2DOT14> intermediateStartTuple - optional */
+ /* Intermediate start tuple record for this tuple variation table — optional,
+ determined by flags in the tupleIndex value. */
/* UnsizedArrayOf<F2DOT14> intermediateEndTuple - optional */
-
+ /* Intermediate end tuple record for this tuple variation table — optional,
+ * determined by flags in the tupleIndex value. */
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
+struct GlyphVariationData
{
- const TupleVarHeader &get_tuple_var_header (void) const
- { return StructAfter<TupleVarHeader> (data); }
+ const TupleVariationHeader &get_tuple_var_header (void) const
+ { return StructAfter<TupleVariationHeader> (data); }
struct tuple_iterator_t
{
- void init (const GlyphVarData *var_data_, unsigned int length_, unsigned int axis_count_)
+ void init (hb_bytes_t var_data_bytes_, unsigned int axis_count_)
{
- var_data = var_data_;
- length = length_;
+ var_data_bytes = var_data_bytes_;
+ var_data = var_data_bytes_.as<GlyphVariationData> ();
index = 0;
axis_count = axis_count_;
current_tuple = &var_data->get_tuple_var_header ();
@@ -216,10 +206,9 @@ struct GlyphVarData
{
if (var_data->has_shared_point_numbers ())
{
- hb_bytes_t bytes ((const char *) var_data, length);
const HBUINT8 *base = &(var_data+var_data->data);
const HBUINT8 *p = base;
- if (!unpack_points (p, shared_indices, bytes)) return false;
+ if (!unpack_points (p, shared_indices, var_data_bytes)) return false;
data_offset = p - base;
}
return true;
@@ -228,7 +217,8 @@ struct GlyphVarData
bool is_valid () const
{
return (index < var_data->tupleVarCount.get_count ()) &&
- in_range (current_tuple) &&
+ var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) &&
+ var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (), current_tuple->get_size (axis_count))) &&
current_tuple->get_size (axis_count);
}
@@ -240,32 +230,25 @@ struct GlyphVarData
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;
+ const GlyphVariationData *var_data;
unsigned int index;
unsigned int axis_count;
unsigned int data_offset;
public:
- const TupleVarHeader *current_tuple;
+ hb_bytes_t var_data_bytes;
+ const TupleVariationHeader *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 */)
+ static bool get_tuple_iterator (hb_bytes_t var_data_bytes, unsigned axis_count,
+ hb_vector_t<unsigned int> &shared_indices /* OUT */,
+ tuple_iterator_t *iterator /* OUT */)
{
- iterator->init (var_data, length, axis_count);
+ iterator->init (var_data_bytes, axis_count);
if (!iterator->get_shared_indices (shared_indices))
return false;
return iterator->is_valid ();
@@ -283,12 +266,12 @@ struct GlyphVarData
POINT_RUN_COUNT_MASK = 0x7F
};
- if (unlikely (!bytes.in_range (p))) return false;
+ if (unlikely (!bytes.check_range (p))) return false;
uint16_t count = *p++;
if (count & POINTS_ARE_WORDS)
{
- if (unlikely (!bytes.in_range (p))) return false;
+ if (unlikely (!bytes.check_range (p))) return false;
count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
}
points.resize (count);
@@ -297,7 +280,7 @@ struct GlyphVarData
uint16_t i = 0;
while (i < count)
{
- if (unlikely (!bytes.in_range (p))) return false;
+ if (unlikely (!bytes.check_range (p))) return false;
uint16_t j;
uint8_t control = *p++;
uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1;
@@ -305,7 +288,7 @@ struct GlyphVarData
{
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.in_range ((const HBUINT16 *) p)))
+ if (unlikely (!bytes.check_range ((const HBUINT16 *) p)))
return false;
n += *(const HBUINT16 *)p;
points[i] = n;
@@ -316,7 +299,7 @@ struct GlyphVarData
{
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.in_range (p))) return false;
+ if (unlikely (!bytes.check_range (p))) return false;
n += *p++;
points[i] = n;
}
@@ -341,7 +324,7 @@ struct GlyphVarData
unsigned int count = deltas.length;
while (i < count)
{
- if (unlikely (!bytes.in_range (p))) return false;
+ if (unlikely (!bytes.check_range (p))) return false;
uint8_t control = *p++;
unsigned int run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
unsigned int j;
@@ -351,7 +334,7 @@ struct GlyphVarData
else if (control & DELTAS_ARE_WORDS)
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.in_range ((const HBUINT16 *) p)))
+ if (unlikely (!bytes.check_range ((const HBUINT16 *) p)))
return false;
deltas[i] = *(const HBINT16 *) p;
p += HBUINT16::static_size;
@@ -359,7 +342,7 @@ struct GlyphVarData
else
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.in_range (p)))
+ if (unlikely (!bytes.check_range (p)))
return false;
deltas[i] = *(const HBINT8 *) p++;
}
@@ -369,10 +352,32 @@ struct GlyphVarData
return true;
}
+ bool has_data () const { return tupleVarCount; }
+
protected:
- TupleVarCount tupleVarCount;
- OffsetTo<HBUINT8> data;
- /* TupleVarHeader tupleVarHeaders[] */
+ 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);
+ };
+
+ TupleVarCount tupleVarCount; /* A packed field. The high 4 bits are flags, and the
+ * low 12 bits are the number of tuple variation tables
+ * for this glyph. The number of tuple variation tables
+ * can be any number between 1 and 4095. */
+ OffsetTo<HBUINT8>
+ data; /* Offset from the start of the GlyphVariationData table
+ * to the serialized data. */
+ /* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
public:
DEFINE_SIZE_MIN (4);
};
@@ -386,7 +391,7 @@ struct gvar
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && (version.major == 1) &&
(glyphCount == c->get_num_glyphs ()) &&
- c->check_array (&(this+sharedTuples), axisCount * sharedTupleCount) &&
+ sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
(is_long_offset () ?
c->check_array (get_long_offset_array (), glyphCount+1) :
c->check_array (get_short_offset_array (), glyphCount+1)) &&
@@ -394,7 +399,7 @@ struct gvar
get_offset (glyphCount) - get_offset (0)));
}
- /* GlyphVarData not sanitized here; must be checked while accessing each glyph varation data */
+ /* GlyphVariationData not sanitized here; must be checked while accessing each glyph varation data */
bool sanitize (hb_sanitize_context_t *c) const
{ return sanitize_shallow (c); }
@@ -418,7 +423,7 @@ struct gvar
{
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);
+ subset_data_size += get_glyph_var_data_bytes (c->source_blob, old_gid).length;
}
bool long_offset = subset_data_size & ~0xFFFFu;
@@ -436,27 +441,30 @@ struct gvar
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);
+ 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;
+ 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;
+ hb_bytes_t var_data_bytes = c->plan->old_gid_for_new_gid (gid, &old_gid)
+ ? get_glyph_var_data_bytes (c->source_blob, old_gid)
+ : hb_bytes_t ();
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 (var_data_bytes.length > 0)
+ memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
+ subset_data += var_data_bytes.length;
+ glyph_offset += var_data_bytes.length;
}
if (long_offset)
((HBUINT32 *) subset_offsets)[num_glyphs] = glyph_offset;
@@ -467,16 +475,12 @@ struct gvar
}
protected:
- const GlyphVarData *get_glyph_var_data (hb_codepoint_t glyph) const
+ const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob, 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);
+ unsigned start_offset = get_offset (glyph);
+ unsigned length = get_offset (glyph+1) - start_offset;
+ hb_bytes_t var_data = blob->as_bytes ().sub_array (((unsigned) dataZ) + start_offset, length);
+ return likely (var_data.length >= GlyphVariationData::min_size) ? var_data : hb_bytes_t ();
}
bool is_long_offset () const { return (flags & 1) != 0; }
@@ -489,15 +493,6 @@ struct gvar
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; }
@@ -505,27 +500,8 @@ struct gvar
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 ();
- }
+ { table = hb_sanitize_context_t ().reference_table<gvar> (face); }
+ void fini () { table.destroy (); }
private:
struct x_getter { static float get (const contour_point_t &p) { return p.x; } };
@@ -543,11 +519,11 @@ struct gvar
float next_delta = T::get (deltas[next]);
if (prev_val == next_val)
- return (prev_delta == next_delta) ? prev_delta : 0.f;
+ 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;
+ 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;
+ return (prev_val > next_val) ? prev_delta : next_delta;
/* linear interpolation */
float r = (target_val - prev_val) / (next_val - prev_val);
@@ -558,23 +534,19 @@ struct gvar
{ 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
+ bool apply_deltas_to_points (hb_codepoint_t glyph, hb_font_t *font,
+ const hb_array_t<contour_point_t> points) const
{
- if (unlikely (coord_count != gvar_table->axisCount)) return false;
+ /* num_coords should exactly match gvar's axisCount due to how GlyphVariationData tuples are aligned */
+ if (!font->num_coords || font->num_coords != table->axisCount) return true;
- const GlyphVarData *var_data = gvar_table->get_glyph_var_data (glyph);
- if (var_data == &Null (GlyphVarData)) return true;
+ hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyph);
+ if (!var_data_bytes.as<GlyphVariationData> ()->has_data ()) 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;
+ GlyphVariationData::tuple_iterator_t iterator;
+ if (!GlyphVariationData::get_tuple_iterator (var_data_bytes, table->axisCount,
+ shared_indices, &iterator))
+ return true; /* so isn't applied at all */
/* Save original points for inferred delta calculation */
contour_point_vector_t orig_points;
@@ -585,19 +557,27 @@ struct gvar
contour_point_vector_t deltas; /* flag is used to indicate referenced point */
deltas.resize (points.length);
+ hb_vector_t<unsigned> end_points;
+ for (unsigned i = 0; i < points.length; ++i)
+ if (points[i].is_end_point)
+ end_points.push (i);
+
+ int *coords = font->coords;
+ unsigned num_coords = font->num_coords;
+ hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
do
{
- float scalar = iterator.current_tuple->calculate_scalar (coords, coord_count, shared_tuples.as_array ());
+ float scalar = iterator.current_tuple->calculate_scalar (coords, num_coords, shared_tuples);
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)))
+ if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
return false;
hb_bytes_t bytes ((const char *) p, length);
hb_vector_t<unsigned int> private_indices;
if (iterator.current_tuple->has_private_points () &&
- !GlyphVarData::unpack_points (p, private_indices, bytes))
+ !GlyphVariationData::unpack_points (p, private_indices, bytes))
return false;
const hb_array_t<unsigned int> &indices = private_indices.length ? private_indices : shared_indices;
@@ -605,11 +585,11 @@ struct gvar
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, bytes))
+ if (!GlyphVariationData::unpack_deltas (p, x_deltas, bytes))
return false;
hb_vector_t<int> y_deltas;
y_deltas.resize (num_deltas);
- if (!GlyphVarData::unpack_deltas (p, y_deltas, bytes))
+ if (!GlyphVariationData::unpack_deltas (p, y_deltas, bytes))
return false;
for (unsigned int i = 0; i < deltas.length; i++)
@@ -623,26 +603,26 @@ struct gvar
}
/* infer deltas for unreferenced points */
- unsigned int start_point = 0;
- for (unsigned int c = 0; c < end_points.length; c++)
+ unsigned start_point = 0;
+ for (unsigned c = 0; c < end_points.length; c++)
{
- unsigned int end_point = end_points[c];
- unsigned int i, j;
+ unsigned end_point = end_points[c];
/* 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++)
+ unsigned unref_count = 0;
+ for (unsigned i = start_point; i <= end_point; i++)
if (!deltas[i].flag) unref_count++;
+
+ unsigned j = start_point;
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;
+ unsigned int prev, next, i;
for (;;)
{
i = j;
@@ -683,29 +663,36 @@ no_more_gaps:
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); }
+ unsigned int get_axis_count () const { return table->axisCount; }
private:
- hb_blob_ptr_t<gvar> gvar_table;
- hb_vector_t<F2DOT14> shared_tuples;
+ hb_blob_ptr_t<gvar> table;
};
protected:
- FixedVersion<>version; /* Version of gvar table. Set to 0x00010000u. */
- HBUINT16 axisCount;
+ FixedVersion<>version; /* Version number of the glyph variations table
+ * Set to 0x00010000u. */
+ HBUINT16 axisCount; /* The number of variation axes for this font. This must be
+ * the same number as axisCount in the 'fvar' table. */
HBUINT16 sharedTupleCount;
- LOffsetTo<F2DOT14>
- sharedTuples; /* LOffsetTo<UnsizedArrayOf<Tupple>> */
- HBUINT16 glyphCount;
- HBUINT16 flags;
- LOffsetTo<GlyphVarData>
- dataZ; /* Array of GlyphVarData */
+ /* The number of shared tuple records. Shared tuple records
+ * can be referenced within glyph variation data tables for
+ * multiple glyphs, as opposed to other tuple records stored
+ * directly within a glyph variation data table. */
+ LNNOffsetTo<UnsizedArrayOf<F2DOT14>>
+ sharedTuples; /* Offset from the start of this table to the shared tuple records.
+ * Array of tuple records shared across all glyph variation data tables. */
+ HBUINT16 glyphCount; /* The number of glyphs in this font. This must match the number of
+ * glyphs stored elsewhere in the font. */
+ HBUINT16 flags; /* Bit-field that gives the format of the offset array that follows.
+ * If bit 0 is clear, the offsets are uint16; if bit 0 is set, the
+ * offsets are uint32. */
+ LOffsetTo<GlyphVariationData>
+ dataZ; /* Offset from the start of this table to the array of
+ * GlyphVariationData tables. */
UnsizedArrayOf<HBUINT8>
- offsetZ; /* Array of 16-bit or 32-bit (glyphCount+1) offsets */
+ offsetZ; /* Offsets from the start of the GlyphVariationData array
+ * to each GlyphVariationData table. */
public:
DEFINE_SIZE_MIN (20);
};
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 223430fb829..fdcc88d6748 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
@@ -44,6 +44,38 @@ struct DeltaSetIndexMap
get_width ()));
}
+ template <typename T>
+ bool serialize (hb_serialize_context_t *c, const T &plan)
+ {
+ unsigned int width = plan.get_width ();
+ unsigned int inner_bit_count = plan.get_inner_bit_count ();
+ const hb_array_t<const unsigned int> output_map = plan.get_output_map ();
+
+ TRACE_SERIALIZE (this);
+ if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
+ return_trace (false);
+ if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+ format = ((width-1)<<4)|(inner_bit_count-1);
+ mapCount = output_map.length;
+ HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
+ if (unlikely (!p)) return_trace (false);
+ for (unsigned int i = 0; i < output_map.length; i++)
+ {
+ unsigned int v = output_map[i];
+ unsigned int outer = v >> 16;
+ unsigned int inner = v & 0xFFFF;
+ unsigned int u = (outer << inner_bit_count) | inner;
+ for (unsigned int w = width; w > 0;)
+ {
+ p[--w] = u;
+ u >>= 8;
+ }
+ p += width;
+ }
+ return_trace (true);
+ }
+
unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
{
/* If count is zero, pass value unchanged. This takes
@@ -63,7 +95,7 @@ struct DeltaSetIndexMap
}
{ /* Repack it. */
- unsigned int n = get_inner_bitcount ();
+ unsigned int n = get_inner_bit_count ();
unsigned int outer = u >> n;
unsigned int inner = u & ((1 << n) - 1);
u = (outer<<16) | inner;
@@ -72,22 +104,230 @@ struct DeltaSetIndexMap
return u;
}
- protected:
- unsigned int get_width () const { return ((format >> 4) & 3) + 1; }
-
- unsigned int get_inner_bitcount () const { return (format & 0xF) + 1; }
+ unsigned int get_map_count () const { return mapCount; }
+ unsigned int get_width () const { return ((format >> 4) & 3) + 1; }
+ unsigned int get_inner_bit_count () const { return (format & 0xF) + 1; }
protected:
HBUINT16 format; /* A packed field that describes the compressed
* representation of delta-set indices. */
HBUINT16 mapCount; /* The number of mapping entries. */
UnsizedArrayOf<HBUINT8>
- mapDataZ; /* The delta-set index mapping data. */
+ mapDataZ; /* The delta-set index mapping data. */
public:
DEFINE_SIZE_ARRAY (4, mapDataZ);
};
+struct index_map_subset_plan_t
+{
+ enum index_map_index_t {
+ ADV_INDEX,
+ LSB_INDEX, /* dual as TSB */
+ RSB_INDEX, /* dual as BSB */
+ VORG_INDEX
+ };
+
+ void init (const DeltaSetIndexMap &index_map,
+ hb_inc_bimap_t &outer_map,
+ hb_vector_t<hb_set_t *> &inner_sets,
+ const hb_subset_plan_t *plan)
+ {
+ map_count = 0;
+ outer_bit_count = 0;
+ inner_bit_count = 1;
+ max_inners.init ();
+ output_map.init ();
+
+ if (&index_map == &Null (DeltaSetIndexMap)) return;
+
+ unsigned int last_val = (unsigned int)-1;
+ hb_codepoint_t last_gid = (hb_codepoint_t)-1;
+ hb_codepoint_t gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ());
+
+ outer_bit_count = (index_map.get_width () * 8) - index_map.get_inner_bit_count ();
+ max_inners.resize (inner_sets.length);
+ for (unsigned i = 0; i < inner_sets.length; i++) max_inners[i] = 0;
+
+ /* Search backwards for a map value different from the last map value */
+ for (; gid > 0; gid--)
+ {
+ hb_codepoint_t old_gid;
+ if (!plan->old_gid_for_new_gid (gid - 1, &old_gid))
+ {
+ if (last_gid == (hb_codepoint_t) -1)
+ continue;
+ else
+ break;
+ }
+
+ unsigned int v = index_map.map (old_gid);
+ if (last_gid == (hb_codepoint_t) -1)
+ {
+ last_val = v;
+ last_gid = gid;
+ continue;
+ }
+ if (v != last_val) break;
+
+ last_gid = gid;
+ }
+
+ if (unlikely (last_gid == (hb_codepoint_t)-1)) return;
+ map_count = last_gid;
+ for (gid = 0; gid < map_count; gid++)
+ {
+ hb_codepoint_t old_gid;
+ if (plan->old_gid_for_new_gid (gid, &old_gid))
+ {
+ unsigned int v = index_map.map (old_gid);
+ unsigned int outer = v >> 16;
+ unsigned int inner = v & 0xFFFF;
+ outer_map.add (outer);
+ if (inner > max_inners[outer]) max_inners[outer] = inner;
+ if (outer >= inner_sets.length) return;
+ inner_sets[outer]->add (inner);
+ }
+ }
+ }
+
+ void fini ()
+ {
+ max_inners.fini ();
+ output_map.fini ();
+ }
+
+ void remap (const DeltaSetIndexMap *input_map,
+ const hb_inc_bimap_t &outer_map,
+ const hb_vector_t<hb_inc_bimap_t> &inner_maps,
+ const hb_subset_plan_t *plan)
+ {
+ if (input_map == &Null (DeltaSetIndexMap)) return;
+
+ for (unsigned int i = 0; i < max_inners.length; i++)
+ {
+ if (inner_maps[i].get_population () == 0) continue;
+ unsigned int bit_count = (max_inners[i]==0)? 1: hb_bit_storage (inner_maps[i][max_inners[i]]);
+ if (bit_count > inner_bit_count) inner_bit_count = bit_count;
+ }
+
+ output_map.resize (map_count);
+ for (hb_codepoint_t gid = 0; gid < output_map.length; gid++)
+ {
+ hb_codepoint_t old_gid;
+ if (plan->old_gid_for_new_gid (gid, &old_gid))
+ {
+ unsigned int v = input_map->map (old_gid);
+ unsigned int outer = v >> 16;
+ output_map[gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]);
+ }
+ else
+ output_map[gid] = 0; /* Map unused glyph to outer/inner=0/0 */
+ }
+ }
+
+ unsigned int get_inner_bit_count () const { return inner_bit_count; }
+ unsigned int get_width () const { return ((outer_bit_count + inner_bit_count + 7) / 8); }
+ unsigned int get_map_count () const { return map_count; }
+
+ unsigned int get_size () const
+ { return (map_count? (DeltaSetIndexMap::min_size + get_width () * map_count): 0); }
+
+ bool is_identity () const { return get_output_map ().length == 0; }
+ hb_array_t<const unsigned int> get_output_map () const { return output_map.as_array (); }
+
+ protected:
+ unsigned int map_count;
+ hb_vector_t<unsigned int> max_inners;
+ unsigned int outer_bit_count;
+ unsigned int inner_bit_count;
+ hb_vector_t<unsigned int> output_map;
+};
+
+struct hvarvvar_subset_plan_t
+{
+ hvarvvar_subset_plan_t() : inner_maps (), index_map_plans () {}
+ ~hvarvvar_subset_plan_t() { fini (); }
+
+ void init (const hb_array_t<const DeltaSetIndexMap *> &index_maps,
+ const VariationStore &_var_store,
+ const hb_subset_plan_t *plan)
+ {
+ index_map_plans.resize (index_maps.length);
+
+ var_store = &_var_store;
+ inner_sets.resize (var_store->get_sub_table_count ());
+ for (unsigned int i = 0; i < inner_sets.length; i++)
+ inner_sets[i] = hb_set_create ();
+ adv_set = hb_set_create ();
+
+ inner_maps.resize (var_store->get_sub_table_count ());
+
+ for (unsigned int i = 0; i < inner_maps.length; i++)
+ inner_maps[i].init ();
+
+ if (unlikely (!index_map_plans.length || !inner_sets.length || !inner_maps.length)) return;
+
+ bool retain_adv_map = false;
+ index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan);
+ if (index_maps[0] == &Null (DeltaSetIndexMap))
+ {
+ retain_adv_map = plan->retain_gids;
+ outer_map.add (0);
+ for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
+ {
+ hb_codepoint_t old_gid;
+ if (plan->old_gid_for_new_gid (gid, &old_gid))
+ inner_sets[0]->add (old_gid);
+ }
+ hb_set_union (adv_set, inner_sets[0]);
+ }
+
+ for (unsigned int i = 1; i < index_maps.length; i++)
+ index_map_plans[i].init (*index_maps[i], outer_map, inner_sets, plan);
+
+ outer_map.sort ();
+
+ if (retain_adv_map)
+ {
+ for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
+ if (inner_sets[0]->has (gid))
+ inner_maps[0].add (gid);
+ else
+ inner_maps[0].skip ();
+ }
+ else
+ {
+ inner_maps[0].add_set (adv_set);
+ hb_set_subtract (inner_sets[0], adv_set);
+ inner_maps[0].add_set (inner_sets[0]);
+ }
+
+ for (unsigned int i = 1; i < inner_maps.length; i++)
+ inner_maps[i].add_set (inner_sets[i]);
+
+ for (unsigned int i = 0; i < index_maps.length; i++)
+ index_map_plans[i].remap (index_maps[i], outer_map, inner_maps, plan);
+ }
+
+ void fini ()
+ {
+ for (unsigned int i = 0; i < inner_sets.length; i++)
+ hb_set_destroy (inner_sets[i]);
+ hb_set_destroy (adv_set);
+ inner_maps.fini_deep ();
+ index_map_plans.fini_deep ();
+ }
+
+ hb_inc_bimap_t outer_map;
+ hb_vector_t<hb_inc_bimap_t> inner_maps;
+ hb_vector_t<index_map_subset_plan_t> index_map_plans;
+ const VariationStore *var_store;
+
+ protected:
+ hb_vector_t<hb_set_t *> inner_sets;
+ hb_set_t *adv_set;
+};
/*
* HVAR -- Horizontal Metrics Variations
@@ -114,7 +354,59 @@ struct HVARVVAR
rsbMap.sanitize (c, this));
}
- float get_advance_var (hb_font_t *font, hb_codepoint_t glyph) const
+ void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const
+ {
+ index_maps.push (&(this+advMap));
+ index_maps.push (&(this+lsbMap));
+ index_maps.push (&(this+rsbMap));
+ }
+
+ bool serialize_index_maps (hb_serialize_context_t *c,
+ const hb_array_t<index_map_subset_plan_t> &im_plans)
+ {
+ TRACE_SERIALIZE (this);
+ if (im_plans[index_map_subset_plan_t::ADV_INDEX].is_identity ())
+ advMap = 0;
+ else if (unlikely (!advMap.serialize (c, this).serialize (c, im_plans[index_map_subset_plan_t::ADV_INDEX])))
+ return_trace (false);
+ if (im_plans[index_map_subset_plan_t::LSB_INDEX].is_identity ())
+ lsbMap = 0;
+ else if (unlikely (!lsbMap.serialize (c, this).serialize (c, im_plans[index_map_subset_plan_t::LSB_INDEX])))
+ return_trace (false);
+ if (im_plans[index_map_subset_plan_t::RSB_INDEX].is_identity ())
+ rsbMap = 0;
+ else if (unlikely (!rsbMap.serialize (c, this).serialize (c, im_plans[index_map_subset_plan_t::RSB_INDEX])))
+ return_trace (false);
+
+ return_trace (true);
+ }
+
+ template <typename T>
+ bool _subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ hvarvvar_subset_plan_t hvar_plan;
+ hb_vector_t<const DeltaSetIndexMap *>
+ index_maps;
+
+ ((T*)this)->listup_index_maps (index_maps);
+ hvar_plan.init (index_maps.as_array (), this+varStore, c->plan);
+
+ T *out = c->serializer->allocate_min<T> ();
+ if (unlikely (!out)) return_trace (false);
+
+ out->version.major = 1;
+ out->version.minor = 0;
+
+ if (unlikely (!out->varStore.serialize (c->serializer, out)
+ .serialize (c->serializer, hvar_plan.var_store, hvar_plan.inner_maps.as_array ())))
+ return_trace (false);
+
+ return_trace (out->T::serialize_index_maps (c->serializer,
+ hvar_plan.index_map_plans.as_array ()));
+ }
+
+ float get_advance_var (hb_codepoint_t glyph, hb_font_t *font) const
{
unsigned int varidx = (this+advMap).map (glyph);
return (this+varStore).get_delta (varidx, font->coords, font->num_coords);
@@ -148,6 +440,7 @@ struct HVARVVAR
struct HVAR : HVARVVAR {
static constexpr hb_tag_t tableTag = HB_OT_TAG_HVAR;
+ bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<HVAR> (c); }
};
struct VVAR : HVARVVAR {
static constexpr hb_tag_t tableTag = HB_OT_TAG_VVAR;
@@ -159,6 +452,28 @@ struct VVAR : HVARVVAR {
vorgMap.sanitize (c, this));
}
+ void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const
+ {
+ HVARVVAR::listup_index_maps (index_maps);
+ index_maps.push (&(this+vorgMap));
+ }
+
+ bool serialize_index_maps (hb_serialize_context_t *c,
+ const hb_array_t<index_map_subset_plan_t> &im_plans)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!HVARVVAR::serialize_index_maps (c, im_plans)))
+ return_trace (false);
+ if (!im_plans[index_map_subset_plan_t::VORG_INDEX].get_map_count ())
+ vorgMap = 0;
+ else if (unlikely (!vorgMap.serialize (c, this).serialize (c, im_plans[index_map_subset_plan_t::VORG_INDEX])))
+ return_trace (false);
+
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); }
+
protected:
LOffsetTo<DeltaSetIndexMap>
vorgMap; /* Offset to vertical-origin var-idx mapping. */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh
index 5a9d2afb7c6..1b7fad9cec4 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-mvar-table.hh
@@ -77,7 +77,9 @@ struct MVAR
const int *coords, unsigned int coord_count) const
{
const VariationValueRecord *record;
- record = (VariationValueRecord *) hb_bsearch (&tag, valuesZ.arrayZ,
+ record = (VariationValueRecord *) hb_bsearch (tag,
+ (const VariationValueRecord *)
+ (const HBUINT8 *) valuesZ,
valueRecordCount, valueRecordSize,
tag_compare);
if (!record)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh
index a4d6b0622b3..c6803200f98 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh
@@ -84,7 +84,7 @@ struct VORG
this->defaultVertOriginY = defaultVertOriginY;
this->vertYOrigins.len = it.len ();
- for (const auto _ : it) c->copy (_);
+ c->copy_all (it);
}
bool subset (hb_subset_context_t *c) const
@@ -122,10 +122,11 @@ struct VORG
}
protected:
- FixedVersion<> version; /* Version of VORG table. Set to 0x00010000u. */
- FWORD defaultVertOriginY; /* The default vertical origin. */
+ FixedVersion<>version; /* Version of VORG table. Set to 0x00010000u. */
+ FWORD defaultVertOriginY;
+ /* The default vertical origin. */
SortedArrayOf<VertOriginMetric>
- vertYOrigins; /* The array of vertical origins. */
+ vertYOrigins; /* The array of vertical origins. */
public:
DEFINE_SIZE_ARRAY(8, vertYOrigins);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh
index 83875dbe13d..dcf0faf2a93 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-pool.hh
@@ -41,9 +41,7 @@ struct hb_pool_t
{
next = nullptr;
- + hb_iter (chunks)
- | hb_apply ([] (chunk_t *_) { ::free (_); })
- ;
+ for (chunk_t *_ : chunks) ::free (_);
chunks.fini ();
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh
index 7859c6a2c6b..091b3010f0a 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-sanitize.hh
@@ -113,6 +113,9 @@
#ifndef HB_SANITIZE_MAX_OPS_MAX
#define HB_SANITIZE_MAX_OPS_MAX 0x3FFFFFFF
#endif
+#ifndef HB_SANITIZE_MAX_SUTABLES
+#define HB_SANITIZE_MAX_SUTABLES 0x4000
+#endif
struct hb_sanitize_context_t :
hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
@@ -120,7 +123,7 @@ struct hb_sanitize_context_t :
hb_sanitize_context_t () :
debug_depth (0),
start (nullptr), end (nullptr),
- max_ops (0),
+ max_ops (0), max_subtables (0),
writable (false), edit_count (0),
blob (nullptr),
num_glyphs (65536),
@@ -134,6 +137,12 @@ struct hb_sanitize_context_t :
static return_t no_dispatch_return_value () { return false; }
bool stop_sublookup_iteration (const return_t r) const { return !r; }
+ bool visit_subtables (unsigned count)
+ {
+ max_subtables += count;
+ return max_subtables < HB_SANITIZE_MAX_SUTABLES;
+ }
+
private:
template <typename T, typename ...Ts> auto
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
@@ -189,8 +198,12 @@ struct hb_sanitize_context_t :
void start_processing ()
{
reset_object ();
- this->max_ops = hb_max ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
- (unsigned) HB_SANITIZE_MAX_OPS_MIN);
+ if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR)))
+ this->max_ops = HB_SANITIZE_MAX_OPS_MAX;
+ else
+ this->max_ops = hb_clamp ((unsigned) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+ (unsigned) HB_SANITIZE_MAX_OPS_MIN,
+ (unsigned) HB_SANITIZE_MAX_OPS_MAX);
this->edit_count = 0;
this->debug_depth = 0;
@@ -376,7 +389,7 @@ struct hb_sanitize_context_t :
mutable unsigned int debug_depth;
const char *start, *end;
- mutable int max_ops;
+ mutable int max_ops, max_subtables;
private:
bool writable;
unsigned int edit_count;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
index 4c674b1b1a4..4fb4f4ef40a 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
@@ -45,12 +45,13 @@ struct hb_serialize_context_t
{
typedef unsigned objidx_t;
- struct range_t
- {
- char *head, *tail;
- };
+ enum whence_t {
+ Head, /* Relative to the current object head (default). */
+ Tail, /* Relative to the current object tail after packed. */
+ Absolute /* Absolute: from the start of the serialize buffer. */
+ };
- struct object_t : range_t
+ struct object_t
{
void fini () { links.fini (); }
@@ -70,17 +71,29 @@ struct hb_serialize_context_t
struct link_t
{
bool is_wide: 1;
- unsigned position : 31;
+ bool is_signed: 1;
+ unsigned whence: 2;
+ unsigned position: 28;
unsigned bias;
objidx_t objidx;
};
+ char *head;
+ char *tail;
hb_vector_t<link_t> links;
object_t *next;
};
- range_t snapshot () { range_t s = {head, tail} ; return s; }
+ struct snapshot_t
+ {
+ char *head;
+ char *tail;
+ object_t *current; // Just for sanity check
+ unsigned num_links;
+ };
+ snapshot_t snapshot ()
+ { return snapshot_t { head, tail, current, current->links.length }; }
hb_serialize_context_t (void *start_, unsigned int size) :
start ((char *) start_),
@@ -123,7 +136,7 @@ struct hb_serialize_context_t
template <typename T1, typename T2>
bool check_equal (T1 &&v1, T2 &&v2)
- { return check_success (v1 == v2); }
+ { return check_success ((long long) v1 == (long long) v2); }
template <typename T1, typename T2>
bool check_assign (T1 &v1, T2 &&v2)
@@ -166,7 +179,7 @@ struct hb_serialize_context_t
if (packed.length <= 1)
return;
- pop_pack ();
+ pop_pack (false);
resolve_links ();
}
@@ -191,11 +204,16 @@ struct hb_serialize_context_t
object_t *obj = current;
if (unlikely (!obj)) return;
current = current->next;
- revert (*obj);
+ revert (obj->head, obj->tail);
obj->fini ();
object_pool.free (obj);
}
- objidx_t pop_pack ()
+
+ /* Set share to false when an object is unlikely sharable with others
+ * so not worth an attempt, or a contiguous table is serialized as
+ * multiple consecutive objects in the reverse order so can't be shared.
+ */
+ objidx_t pop_pack (bool share=true)
{
object_t *obj = current;
if (unlikely (!obj)) return 0;
@@ -211,11 +229,15 @@ struct hb_serialize_context_t
return 0;
}
- objidx_t objidx = packed_map.get (obj);
- if (objidx)
+ objidx_t objidx;
+ if (share)
{
- obj->fini ();
- return objidx;
+ objidx = packed_map.get (obj);
+ if (objidx)
+ {
+ obj->fini ();
+ return objidx;
+ }
}
tail -= len;
@@ -231,17 +253,24 @@ struct hb_serialize_context_t
objidx = packed.length - 1;
- packed_map.set (obj, objidx);
+ if (share) packed_map.set (obj, objidx);
return objidx;
}
- void revert (range_t snap)
+ void revert (snapshot_t snap)
+ {
+ assert (snap.current == current);
+ current->links.shrink (snap.num_links);
+ revert (snap.head, snap.tail);
+ }
+ void revert (char *snap_head,
+ char *snap_tail)
{
- assert (snap.head <= head);
- assert (tail <= snap.tail);
- head = snap.head;
- tail = snap.tail;
+ assert (snap_head <= head);
+ assert (tail <= snap_tail);
+ head = snap_head;
+ tail = snap_tail;
discard_stale_objects ();
}
@@ -260,7 +289,9 @@ struct hb_serialize_context_t
}
template <typename T>
- void add_link (T &ofs, objidx_t objidx, const void *base = nullptr)
+ void add_link (T &ofs, objidx_t objidx,
+ whence_t whence = Head,
+ unsigned bias = 0)
{
static_assert (sizeof (T) == 2 || sizeof (T) == 4, "");
@@ -270,18 +301,24 @@ struct hb_serialize_context_t
assert (current);
assert (current->head <= (const char *) &ofs);
- if (!base)
- base = current->head;
- else
- assert (current->head <= (const char *) base);
-
auto& link = *current->links.push ();
+
link.is_wide = sizeof (T) == 4;
+ link.is_signed = hb_is_signed (hb_unwrap_type (T));
+ link.whence = (unsigned) whence;
link.position = (const char *) &ofs - current->head;
- link.bias = (const char *) base - current->head;
+ link.bias = bias;
link.objidx = objidx;
}
+ unsigned to_bias (const void *base) const
+ {
+ if (!base) return 0;
+ assert (current);
+ assert (current->head <= (const char *) base);
+ return (const char *) base - current->head;
+ }
+
void resolve_links ()
{
if (unlikely (in_error ())) return;
@@ -293,20 +330,29 @@ struct hb_serialize_context_t
for (const object_t::link_t &link : parent->links)
{
const object_t* child = packed[link.objidx];
- assert (link.bias <= (size_t) (parent->tail - parent->head));
- unsigned offset = (child->head - parent->head) - link.bias;
+ if (unlikely (!child)) { err_other_error(); return; }
+ unsigned offset = 0;
+ switch ((whence_t) link.whence) {
+ case Head: offset = child->head - parent->head; break;
+ case Tail: offset = child->head - parent->tail; break;
+ case Absolute: offset = (head - start) + (child->head - tail); break;
+ }
- if (link.is_wide)
+ assert (offset >= link.bias);
+ offset -= link.bias;
+ if (link.is_signed)
{
- auto &off = * ((BEInt<uint32_t, 4> *) (parent->head + link.position));
- assert (0 == off);
- check_assign (off, offset);
+ if (link.is_wide)
+ assign_offset<int32_t> (parent, link, offset);
+ else
+ assign_offset<int16_t> (parent, link, offset);
}
else
{
- auto &off = * ((BEInt<uint16_t, 2> *) (parent->head + link.position));
- assert (0 == off);
- check_assign (off, offset);
+ if (link.is_wide)
+ assign_offset<uint32_t> (parent, link, offset);
+ else
+ assign_offset<uint16_t> (parent, link, offset);
}
}
}
@@ -387,6 +433,12 @@ struct hb_serialize_context_t
Type *copy (const Type *src, Ts&&... ds)
{ return copy (*src, hb_forward<Ts> (ds)...); }
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator)),
+ typename ...Ts>
+ void copy_all (Iterator it, Ts&&... ds)
+ { for (decltype (*it) _ : it) copy (_, hb_forward<Ts> (ds)...); }
+
template <typename Type>
hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; }
@@ -441,6 +493,15 @@ struct hb_serialize_context_t
(char *) b.arrayZ, free);
}
+ private:
+ template <typename T>
+ void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset)
+ {
+ auto &off = * ((BEInt<T, sizeof (T)> *) (parent->head + link.position));
+ assert (0 == off);
+ check_assign (off, offset);
+ }
+
public: /* TODO Make private. */
char *start, *head, *tail, *end;
unsigned int debug_depth;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.cc
index 10638a7e6d5..0551ed80f25 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.cc
@@ -69,7 +69,7 @@ hb_set_create ()
hb_set_t *
hb_set_get_empty ()
{
- return const_cast<hb_set_t *> (&Null(hb_set_t));
+ return const_cast<hb_set_t *> (&Null (hb_set_t));
}
/**
@@ -145,9 +145,9 @@ hb_set_get_user_data (hb_set_t *set,
* hb_set_allocation_successful:
* @set: a set.
*
- *
*
- * Return value:
+ *
+ * Return value:
*
* Since: 0.9.2
**/
@@ -161,7 +161,7 @@ hb_set_allocation_successful (const hb_set_t *set)
* hb_set_clear:
* @set: a set.
*
- *
+ *
*
* Since: 0.9.2
**/
@@ -175,9 +175,9 @@ hb_set_clear (hb_set_t *set)
* hb_set_is_empty:
* @set: a set.
*
- *
*
- * Return value:
+ *
+ * Return value:
*
* Since: 0.9.7
**/
@@ -190,11 +190,11 @@ hb_set_is_empty (const hb_set_t *set)
/**
* hb_set_has:
* @set: a set.
- * @codepoint:
+ * @codepoint:
*
- *
*
- * Return value:
+ *
+ * Return value:
*
* Since: 0.9.2
**/
@@ -208,9 +208,9 @@ hb_set_has (const hb_set_t *set,
/**
* hb_set_add:
* @set: a set.
- * @codepoint:
+ * @codepoint:
+ *
*
- *
*
* Since: 0.9.2
**/
@@ -224,10 +224,10 @@ hb_set_add (hb_set_t *set,
/**
* hb_set_add_range:
* @set: a set.
- * @first:
- * @last:
+ * @first:
+ * @last:
+ *
*
- *
*
* Since: 0.9.7
**/
@@ -242,9 +242,9 @@ hb_set_add_range (hb_set_t *set,
/**
* hb_set_del:
* @set: a set.
- * @codepoint:
+ * @codepoint:
+ *
*
- *
*
* Since: 0.9.2
**/
@@ -258,10 +258,10 @@ hb_set_del (hb_set_t *set,
/**
* hb_set_del_range:
* @set: a set.
- * @first:
- * @last:
+ * @first:
+ * @last:
+ *
*
- *
*
* Since: 0.9.7
**/
@@ -278,7 +278,7 @@ hb_set_del_range (hb_set_t *set,
* @set: a set.
* @other: other set.
*
- *
+ *
*
* Return value: %TRUE if the two sets are equal, %FALSE otherwise.
*
@@ -312,9 +312,9 @@ hb_set_is_subset (const hb_set_t *set,
/**
* hb_set_set:
* @set: a set.
- * @other:
+ * @other:
+ *
*
- *
*
* Since: 0.9.2
**/
@@ -328,9 +328,9 @@ hb_set_set (hb_set_t *set,
/**
* hb_set_union:
* @set: a set.
- * @other:
+ * @other:
+ *
*
- *
*
* Since: 0.9.2
**/
@@ -344,9 +344,9 @@ hb_set_union (hb_set_t *set,
/**
* hb_set_intersect:
* @set: a set.
- * @other:
+ * @other:
+ *
*
- *
*
* Since: 0.9.2
**/
@@ -360,9 +360,9 @@ hb_set_intersect (hb_set_t *set,
/**
* hb_set_subtract:
* @set: a set.
- * @other:
+ * @other:
+ *
*
- *
*
* Since: 0.9.2
**/
@@ -376,9 +376,9 @@ hb_set_subtract (hb_set_t *set,
/**
* hb_set_symmetric_difference:
* @set: a set.
- * @other:
+ * @other:
+ *
*
- *
*
* Since: 0.9.2
**/
@@ -394,7 +394,7 @@ hb_set_symmetric_difference (hb_set_t *set,
* hb_set_invert:
* @set: a set.
*
- *
+ *
*
* Since: 0.9.10
*
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
index 36d11c0319f..b6e2086a2e3 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
@@ -89,6 +89,23 @@ struct hb_set_t
}
}
+ void del_range (hb_codepoint_t a, hb_codepoint_t b)
+ {
+ elt_t *la = &elt (a);
+ elt_t *lb = &elt (b);
+ if (la == lb)
+ *la &= ~((mask (b) << 1) - mask(a));
+ else
+ {
+ *la &= mask (a) - 1;
+ la++;
+
+ memset (la, 0, (char *) lb - (char *) la);
+
+ *lb &= ~((mask (b) << 1) - 1);
+ }
+ }
+
bool is_equal (const page_t *other) const
{
return 0 == hb_memcmp (&v, &other->v, sizeof (v));
@@ -135,7 +152,11 @@ struct hb_set_t
unsigned int i = m / ELT_BITS;
unsigned int j = m & ELT_MASK;
- const elt_t vv = v[i] & ((elt_t (1) << (j + 1)) - 1);
+ /* Fancy mask to avoid shifting by elt_t bitsize, which is undefined. */
+ const elt_t mask = j < 8 * sizeof (elt_t) - 1 ?
+ ((elt_t (1) << (j + 1)) - 1) :
+ (elt_t) -1;
+ const elt_t vv = v[i] & mask;
const elt_t *p = &vv;
while (true)
{
@@ -258,7 +279,7 @@ struct hb_set_t
return true;
}
- void dirty () { population = (unsigned int) -1; }
+ void dirty () { population = UINT_MAX; }
void add (hb_codepoint_t g)
{
@@ -362,14 +383,56 @@ struct hb_set_t
dirty ();
page->del (g);
}
+
+ private:
+ void del_pages (int ds, int de)
+ {
+ if (ds <= de)
+ {
+ unsigned int write_index = 0;
+ for (unsigned int i = 0; i < page_map.length; i++)
+ {
+ int m = (int) page_map[i].major;
+ if (m < ds || de < m)
+ page_map[write_index++] = page_map[i];
+ }
+ compact (write_index);
+ resize (write_index);
+ }
+ }
+
+ public:
void del_range (hb_codepoint_t a, hb_codepoint_t b)
{
/* TODO perform op even if !successful. */
- /* TODO Optimize, like add_range(). */
if (unlikely (!successful)) return;
- for (unsigned int i = a; i < b + 1; i++)
- del (i);
+ if (unlikely (a > b || a == INVALID || b == INVALID)) return;
+ dirty ();
+ unsigned int ma = get_major (a);
+ unsigned int mb = get_major (b);
+ /* Delete pages from ds through de if ds <= de. */
+ int ds = (a == major_start (ma))? (int) ma: (int) (ma + 1);
+ int de = (b + 1 == major_start (mb + 1))? (int) mb: ((int) mb - 1);
+ if (ds > de || (int) ma < ds)
+ {
+ page_t *page = page_for (a);
+ if (page)
+ {
+ if (ma == mb)
+ page->del_range (a, b);
+ else
+ page->del_range (a, major_start (ma + 1) - 1);
+ }
+ }
+ if (de < (int) mb && ma != mb)
+ {
+ page_t *page = page_for (b);
+ if (page)
+ page->del_range (major_start (mb), b);
+ }
+ del_pages (ds, de);
}
+
bool get (hb_codepoint_t g) const
{
const page_t *page = page_for (g);
@@ -387,7 +450,10 @@ struct hb_set_t
bool operator () (hb_codepoint_t k) const { return has (k); }
/* Sink interface. */
- hb_set_t& operator << (hb_codepoint_t v) { add (v); return *this; }
+ hb_set_t& operator << (hb_codepoint_t v)
+ { add (v); return *this; }
+ hb_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+ { add_range (range.first, range.second); return *this; }
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
{
@@ -446,6 +512,34 @@ struct hb_set_t
return true;
}
+ void compact (unsigned int length)
+ {
+ hb_vector_t<uint32_t> old_index_to_page_map_index;
+ old_index_to_page_map_index.resize(pages.length);
+ for (uint32_t i = 0; i < old_index_to_page_map_index.length; i++)
+ old_index_to_page_map_index[i] = 0xFFFFFFFF;
+
+ for (uint32_t i = 0; i < length; i++)
+ old_index_to_page_map_index[page_map[i].index] = i;
+
+ compact_pages (old_index_to_page_map_index);
+ }
+
+ void compact_pages (const hb_vector_t<uint32_t>& old_index_to_page_map_index)
+ {
+ unsigned int write_index = 0;
+ for (unsigned int i = 0; i < pages.length; i++)
+ {
+ if (old_index_to_page_map_index[i] == 0xFFFFFFFF) continue;
+
+ if (write_index < i)
+ pages[write_index] = pages[i];
+
+ page_map[old_index_to_page_map_index[i]].index = write_index;
+ write_index++;
+ }
+ }
+
template <typename Op>
void process (const Op& op, const hb_set_t *other)
{
@@ -459,10 +553,22 @@ struct hb_set_t
unsigned int count = 0, newCount = 0;
unsigned int a = 0, b = 0;
+ unsigned int write_index = 0;
for (; a < na && b < nb; )
{
if (page_map[a].major == other->page_map[b].major)
{
+ if (!Op::passthru_left)
+ {
+ // Move page_map entries that we're keeping from the left side set
+ // to the front of the page_map vector. This isn't necessary if
+ // passthru_left is set since no left side pages will be removed
+ // in that case.
+ if (write_index < a)
+ page_map[write_index] = page_map[a];
+ write_index++;
+ }
+
count++;
a++;
b++;
@@ -485,9 +591,16 @@ struct hb_set_t
if (Op::passthru_right)
count += nb - b;
- if (count > pages.length)
- if (!resize (count))
- return;
+ if (!Op::passthru_left)
+ {
+ na = write_index;
+ next_page = write_index;
+ compact (write_index);
+ }
+
+ if (!resize (count))
+ return;
+
newCount = count;
/* Process in-place backward. */
@@ -662,7 +775,7 @@ struct hb_set_t
unsigned int get_population () const
{
- if (population != (unsigned int) -1)
+ if (population != UINT_MAX)
return population;
unsigned int pop = 0;
@@ -698,8 +811,15 @@ struct hb_set_t
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
{
static constexpr bool is_sorted_iterator = true;
- iter_t (const hb_set_t &s_ = Null(hb_set_t)) :
- s (&s_), v (INVALID), l (s->get_population () + 1) { __next__ (); }
+ iter_t (const hb_set_t &s_ = Null (hb_set_t),
+ bool init = true) : s (&s_), v (INVALID), l(0)
+ {
+ if (init)
+ {
+ l = s->get_population () + 1;
+ __next__ ();
+ }
+ }
typedef hb_codepoint_t __item_t__;
hb_codepoint_t __item__ () const { return v; }
@@ -707,7 +827,7 @@ struct hb_set_t
void __next__ () { s->next (&v); if (l) l--; }
void __prev__ () { s->previous (&v); }
unsigned __len__ () const { return l; }
- iter_t end () const { return iter_t (*s); }
+ iter_t end () const { return iter_t (*s, false); }
bool operator != (const iter_t& o) const
{ return s != o.s || v != o.v; }
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
index ffd723d0836..666470b4f16 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
@@ -257,7 +257,7 @@ bail:
hb_shape_plan_t *
hb_shape_plan_get_empty ()
{
- return const_cast<hb_shape_plan_t *> (&Null(hb_shape_plan_t));
+ return const_cast<hb_shape_plan_t *> (&Null (hb_shape_plan_t));
}
/**
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper.hh
index 79dc5d07e09..b4138a324ff 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shaper.hh
@@ -102,7 +102,7 @@ template <enum hb_shaper_order_t order, typename Object> struct hb_shaper_object
static void destroy (Type *p) { HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (p); } \
}; \
\
- static_assert (true, "") /* Require semicolon. */
+ static_assert (true, "") /* Require semicolon after. */
template <typename Object>
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc
index 08a2f21363e..f5b7fa50a04 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-static.cc
@@ -51,6 +51,9 @@ DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
+
+/* hb_face_t */
+
unsigned int
hb_face_t::load_num_glyphs () const
{
@@ -73,4 +76,37 @@ hb_face_t::load_upem () const
return ret;
}
+
+/* hb_user_data_array_t */
+
+bool
+hb_user_data_array_t::set (hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ if (!key)
+ return false;
+
+ if (replace) {
+ if (!data && !destroy) {
+ items.remove (key, lock);
+ return true;
+ }
+ }
+ hb_user_data_item_t item = {key, data, destroy};
+ bool ret = !!items.replace_or_insert (item, lock, (bool) replace);
+
+ return ret;
+}
+
+void *
+hb_user_data_array_t::get (hb_user_data_key_t *key)
+{
+ hb_user_data_item_t item = {nullptr, nullptr, nullptr};
+
+ return items.find (key, &item, lock) ? item.data : nullptr;
+}
+
+
#endif
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-string-array.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-string-array.hh
index 1c67ab4d7c5..e7ac1192324 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-string-array.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-string-array.hh
@@ -37,6 +37,7 @@
#define HB_STRING_ARRAY_TYPE_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _msgstr_t)
#define HB_STRING_ARRAY_POOL_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _msgstr)
#define HB_STRING_ARRAY_OFFS_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _msgidx)
+#define HB_STRING_ARRAY_LENG_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _length)
static const union HB_STRING_ARRAY_TYPE_NAME {
struct {
@@ -66,6 +67,8 @@ static const unsigned int HB_STRING_ARRAY_OFFS_NAME[] =
sizeof (HB_STRING_ARRAY_TYPE_NAME)
};
+static const unsigned int HB_STRING_ARRAY_LENG_NAME = ARRAY_LENGTH_CONST (HB_STRING_ARRAY_OFFS_NAME) - 1;
+
static inline hb_bytes_t
HB_STRING_ARRAY_NAME (unsigned int i)
{
@@ -77,5 +80,6 @@ HB_STRING_ARRAY_NAME (unsigned int i)
#undef HB_STRING_ARRAY_TYPE_NAME
#undef HB_STRING_ARRAY_POOL_NAME
#undef HB_STRING_ARRAY_OFFS_NAME
+#undef HB_STRING_ARRAY_LENG_NAME
#endif /* HB_STRING_ARRAY_HH */
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 c9a880ad500..04e1db24ace 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
@@ -108,7 +108,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
fdmap.add (fd);
hb_set_destroy (set);
if (unlikely (fdmap.get_population () != subset_fd_count))
- return false;
+ return false;
}
/* update each font dict index stored as "code" in fdselect_ranges */
@@ -158,7 +158,7 @@ serialize_fdselect_3_4 (hb_serialize_context_t *c,
{
TRACE_SERIALIZE (this);
FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
- if (unlikely (p == nullptr)) return_trace (false);
+ if (unlikely (!p)) return_trace (false);
p->nRanges () = fdselect_ranges.length;
for (unsigned int i = 0; i < fdselect_ranges.length; i++)
{
@@ -184,7 +184,7 @@ hb_serialize_cff_fdselect (hb_serialize_context_t *c,
{
TRACE_SERIALIZE (this);
FDSelect *p = c->allocate_min<FDSelect> ();
- if (unlikely (p == nullptr)) return_trace (false);
+ if (unlikely (!p)) return_trace (false);
p->format = fdselect_format;
size -= FDSelect::min_size;
@@ -194,7 +194,7 @@ hb_serialize_cff_fdselect (hb_serialize_context_t *c,
case 0:
{
FDSelect0 *p = c->allocate_size<FDSelect0> (size);
- if (unlikely (p == nullptr)) return_trace (false);
+ if (unlikely (!p)) return_trace (false);
unsigned int range_index = 0;
unsigned int fd = fdselect_ranges[range_index++].code;
for (unsigned int i = 0; i < 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 3c66119603f..3400892830c 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
@@ -44,7 +44,7 @@ struct str_encoder_t
void encode_byte (unsigned char b)
{
- if (unlikely (buff.push (b) == &Crap(unsigned char)))
+ if (unlikely (buff.push (b) == &Crap (unsigned char)))
set_error ();
}
@@ -128,26 +128,17 @@ struct str_encoder_t
bool error;
};
-struct cff_sub_table_offsets_t {
- cff_sub_table_offsets_t () : privateDictsOffset (0)
+struct cff_sub_table_info_t {
+ cff_sub_table_info_t ()
+ : fd_array_link (0),
+ char_strings_link (0)
{
- topDictInfo.init ();
- FDSelectInfo.init ();
- FDArrayInfo.init ();
- charStringsInfo.init ();
- globalSubrsInfo.init ();
- localSubrsInfos.init ();
+ fd_select.init ();
}
- ~cff_sub_table_offsets_t () { localSubrsInfos.fini (); }
-
- table_info_t topDictInfo;
- table_info_t FDSelectInfo;
- table_info_t FDArrayInfo;
- table_info_t charStringsInfo;
- unsigned int privateDictsOffset;
- table_info_t globalSubrsInfo;
- hb_vector_t<table_info_t> localSubrsInfos;
+ table_info_t fd_select;
+ objidx_t fd_array_link;
+ objidx_t char_strings_link;
};
template <typename OPSTR=op_str_t>
@@ -155,40 +146,26 @@ struct cff_top_dict_op_serializer_t : op_serializer_t
{
bool serialize (hb_serialize_context_t *c,
const OPSTR &opstr,
- const cff_sub_table_offsets_t &offsets) const
+ const cff_sub_table_info_t &info) const
{
TRACE_SERIALIZE (this);
switch (opstr.op)
{
case OpCode_CharStrings:
- return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.charStringsInfo.offset));
+ return_trace (FontDict::serialize_link4_op(c, opstr.op, info.char_strings_link, whence_t::Absolute));
case OpCode_FDArray:
- return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.FDArrayInfo.offset));
+ return_trace (FontDict::serialize_link4_op(c, opstr.op, info.fd_array_link, whence_t::Absolute));
case OpCode_FDSelect:
- return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.FDSelectInfo.offset));
+ return_trace (FontDict::serialize_link4_op(c, opstr.op, info.fd_select.link, whence_t::Absolute));
default:
return_trace (copy_opstr (c, opstr));
}
return_trace (true);
}
-
- unsigned int calculate_serialized_size (const OPSTR &opstr) const
- {
- switch (opstr.op)
- {
- case OpCode_CharStrings:
- case OpCode_FDArray:
- case OpCode_FDSelect:
- return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
-
- default:
- return opstr.str.length;
- }
- }
};
struct cff_font_dict_op_serializer_t : op_serializer_t
@@ -202,33 +179,17 @@ struct cff_font_dict_op_serializer_t : op_serializer_t
if (opstr.op == OpCode_Private)
{
/* serialize the private dict size & offset as 2-byte & 4-byte integers */
- if (unlikely (!UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) ||
- !UnsizedByteStr::serialize_int4 (c, privateDictInfo.offset)))
- return_trace (false);
-
- /* serialize the opcode */
- HBUINT8 *p = c->allocate_size<HBUINT8> (1);
- if (unlikely (p == nullptr)) return_trace (false);
- *p = OpCode_Private;
-
- return_trace (true);
+ return_trace (UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) &&
+ Dict::serialize_link4_op (c, opstr.op, privateDictInfo.link, whence_t::Absolute));
}
else
{
HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
- if (unlikely (d == nullptr)) return_trace (false);
+ if (unlikely (!d)) return_trace (false);
memcpy (d, &opstr.str[0], opstr.str.length);
}
return_trace (true);
}
-
- unsigned int calculate_serialized_size (const op_str_t &opstr) const
- {
- if (opstr.op == OpCode_Private)
- return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
- else
- return opstr.str.length;
- }
};
struct cff_private_dict_op_serializer_t : op_serializer_t
@@ -238,7 +199,7 @@ struct cff_private_dict_op_serializer_t : op_serializer_t
bool serialize (hb_serialize_context_t *c,
const op_str_t &opstr,
- const unsigned int subrsOffset) const
+ objidx_t subrs_link) const
{
TRACE_SERIALIZE (this);
@@ -246,31 +207,15 @@ struct cff_private_dict_op_serializer_t : op_serializer_t
return true;
if (opstr.op == OpCode_Subrs)
{
- if (desubroutinize || (subrsOffset == 0))
+ if (desubroutinize || !subrs_link)
return_trace (true);
else
- return_trace (FontDict::serialize_offset2_op (c, opstr.op, subrsOffset));
+ return_trace (FontDict::serialize_link2_op (c, opstr.op, subrs_link));
}
else
return_trace (copy_opstr (c, opstr));
}
- unsigned int calculate_serialized_size (const op_str_t &opstr,
- bool has_localsubr=true) const
- {
- if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
- return 0;
- if (opstr.op == OpCode_Subrs)
- {
- if (desubroutinize || !has_localsubr)
- return 0;
- else
- return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (opstr.op);
- }
- else
- return opstr.str.length;
- }
-
protected:
const bool desubroutinize;
const bool drop_hints;
@@ -300,14 +245,14 @@ struct subr_flattener_t
hb_codepoint_t glyph;
if (!plan->old_gid_for_new_gid (i, &glyph))
{
- /* add an endchar only charstring for a missing glyph if CFF1 */
- if (endchar_op != OpCode_Invalid) flat_charstrings[i].push (endchar_op);
- continue;
+ /* add an endchar only charstring for a missing glyph if CFF1 */
+ if (endchar_op != OpCode_Invalid) flat_charstrings[i].push (endchar_op);
+ continue;
}
const byte_str_t str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
- return false;
+ return false;
cs_interpreter_t<ENV, OPSET, flatten_param_t> interp;
interp.env.init (str, acc, fd);
flatten_param_t param = { flat_charstrings[i], plan->drop_hints };
@@ -456,7 +401,7 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
bool vsindex_dropped;
bool has_prefix_;
op_code_t prefix_op_;
- number_t prefix_num_;
+ number_t prefix_num_;
private:
typedef parsed_values_t<parsed_cs_op_t> SUPER;
@@ -516,19 +461,19 @@ struct subr_subset_param_t
template <typename ENV>
void set_current_str (ENV &env, bool calling)
{
- parsed_cs_str_t *parsed_str = get_parsed_str_for_context (env.context);
- if (likely (parsed_str != nullptr))
+ parsed_cs_str_t *parsed_str = get_parsed_str_for_context (env.context);
+ if (unlikely (!parsed_str))
{
- /* If the called subroutine is parsed partially but not completely yet,
- * it must be because we are calling it recursively.
- * Handle it as an error. */
- if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
- env.set_error ();
- else
- current_parsed_str = parsed_str;
+ env.set_error ();
+ return;
}
- else
+ /* If the called subroutine is parsed partially but not completely yet,
+ * it must be because we are calling it recursively.
+ * Handle it as an error. */
+ if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
env.set_error ();
+ else
+ current_parsed_str = parsed_str;
}
parsed_cs_str_t *current_parsed_str;
@@ -659,11 +604,11 @@ struct subr_subsetter_t
{
hb_codepoint_t glyph;
if (!plan->old_gid_for_new_gid (i, &glyph))
- continue;
+ continue;
const byte_str_t str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
- return false;
+ return false;
cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp;
interp.env.init (str, acc, fd);
@@ -677,8 +622,8 @@ struct subr_subsetter_t
if (unlikely (!interp.interpret (param)))
return false;
- /* finalize parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
- SUBSETTER::finalize_parsed_str (interp.env, param, parsed_charstrings[i]);
+ /* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
+ SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
}
if (plan->drop_hints)
@@ -740,13 +685,13 @@ struct subr_subsetter_t
hb_codepoint_t glyph;
if (!plan->old_gid_for_new_gid (i, &glyph))
{
- /* add an endchar only charstring for a missing glyph if CFF1 */
- if (endchar_op != OpCode_Invalid) buffArray[i].push (endchar_op);
- continue;
+ /* add an endchar only charstring for a missing glyph if CFF1 */
+ if (endchar_op != OpCode_Invalid) buffArray[i].push (endchar_op);
+ continue;
}
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
- return false;
+ return false;
if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
return false;
}
@@ -900,11 +845,11 @@ struct subr_subsetter_t
{
parsed_cs_op_t &csop = str.values[pos];
if (csop.op == OpCode_return)
- break;
+ break;
if (!csop.for_drop ())
{
- drop.all_dropped = false;
- break;
+ drop.all_dropped = false;
+ break;
}
}
@@ -986,7 +931,7 @@ struct subr_subsetter_t
}
protected:
- const ACC &acc;
+ const ACC &acc;
const hb_subset_plan_t *plan;
subr_closures_t closures;
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 e9e075749e7..f3ed518f7e1 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
@@ -64,29 +64,25 @@ struct remap_sid_t : hb_inc_bimap_t
static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
};
-struct cff1_sub_table_offsets_t : cff_sub_table_offsets_t
+struct cff1_sub_table_info_t : cff_sub_table_info_t
{
- cff1_sub_table_offsets_t ()
- : cff_sub_table_offsets_t (),
- nameIndexOffset (0),
- encodingOffset (0)
- {
- stringIndexInfo.init ();
- charsetInfo.init ();
+ cff1_sub_table_info_t ()
+ : cff_sub_table_info_t (),
+ encoding_link (0),
+ charset_link (0)
+ {
privateDictInfo.init ();
}
- unsigned int nameIndexOffset;
- table_info_t stringIndexInfo;
- unsigned int encodingOffset;
- table_info_t charsetInfo;
+ objidx_t encoding_link;
+ objidx_t charset_link;
table_info_t privateDictInfo;
};
/* a copy of a parsed out cff1_top_dict_values_t augmented with additional operators */
struct cff1_top_dict_values_mod_t : cff1_top_dict_values_t
{
- void init (const cff1_top_dict_values_t *base_= &Null(cff1_top_dict_values_t))
+ void init (const cff1_top_dict_values_t *base_= &Null (cff1_top_dict_values_t))
{
SUPER::init ();
base = base_;
@@ -117,13 +113,13 @@ struct cff1_top_dict_values_mod_t : cff1_top_dict_values_t
struct top_dict_modifiers_t
{
- top_dict_modifiers_t (const cff1_sub_table_offsets_t &offsets_,
+ top_dict_modifiers_t (const cff1_sub_table_info_t &info_,
const unsigned int (&nameSIDs_)[name_dict_values_t::ValCount])
- : offsets (offsets_),
+ : info (info_),
nameSIDs (nameSIDs_)
{}
- const cff1_sub_table_offsets_t &offsets;
+ const cff1_sub_table_info_t &info;
const unsigned int (&nameSIDs)[name_dict_values_t::ValCount];
};
@@ -139,22 +135,20 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
switch (op)
{
case OpCode_charset:
- return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.charsetInfo.offset));
+ if (mod.info.charset_link)
+ return_trace (FontDict::serialize_link4_op(c, op, mod.info.charset_link, whence_t::Absolute));
+ else
+ goto fall_back;
case OpCode_Encoding:
- return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.encodingOffset));
+ if (mod.info.encoding_link)
+ return_trace (FontDict::serialize_link4_op(c, op, mod.info.encoding_link, whence_t::Absolute));
+ else
+ goto fall_back;
case OpCode_Private:
- {
- if (unlikely (!UnsizedByteStr::serialize_int2 (c, mod.offsets.privateDictInfo.size)))
- return_trace (false);
- if (unlikely (!UnsizedByteStr::serialize_int4 (c, mod.offsets.privateDictInfo.offset)))
- return_trace (false);
- HBUINT8 *p = c->allocate_size<HBUINT8> (1);
- if (unlikely (p == nullptr)) return_trace (false);
- *p = OpCode_Private;
- }
- break;
+ return_trace (UnsizedByteStr::serialize_int2 (c, mod.info.privateDictInfo.size) &&
+ Dict::serialize_link4_op (c, op, mod.info.privateDictInfo.link, whence_t::Absolute));
case OpCode_version:
case OpCode_Notice:
@@ -165,7 +159,7 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
case OpCode_PostScript:
case OpCode_BaseFontName:
case OpCode_FontName:
- return_trace (FontDict::serialize_offset2_op(c, op, mod.nameSIDs[name_dict_values_t::name_op_to_index (op)]));
+ return_trace (FontDict::serialize_int2_op (c, op, mod.nameSIDs[name_dict_values_t::name_op_to_index (op)]));
case OpCode_ROS:
{
@@ -180,86 +174,29 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
copy_opstr (c, supp_op));
}
+ fall_back:
default:
- return_trace (cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::serialize (c, opstr, mod.offsets));
+ return_trace (cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::serialize (c, opstr, mod.info));
}
return_trace (true);
}
- unsigned int calculate_serialized_size (const cff1_top_dict_val_t &opstr) const
- {
- op_code_t op = opstr.op;
- switch (op)
- {
- case OpCode_charset:
- case OpCode_Encoding:
- return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
-
- case OpCode_Private:
- return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
-
- case OpCode_version:
- case OpCode_Notice:
- case OpCode_Copyright:
- case OpCode_FullName:
- case OpCode_FamilyName:
- case OpCode_Weight:
- case OpCode_PostScript:
- case OpCode_BaseFontName:
- case OpCode_FontName:
- return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (op);
-
- case OpCode_ROS:
- return ((OpCode_Size (OpCode_shortint) + 2) * 2) + (opstr.str.length - opstr.last_arg_offset)/* supplement + op */;
-
- default:
- return cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::calculate_serialized_size (opstr);
- }
- }
-};
-
-struct font_dict_values_mod_t
-{
- void init (const cff1_font_dict_values_t *base_,
- unsigned int fontName_,
- const table_info_t &privateDictInfo_)
- {
- base = base_;
- fontName = fontName_;
- privateDictInfo = privateDictInfo_;
- }
-
- unsigned get_count () const { return base->get_count (); }
-
- const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
-
- const cff1_font_dict_values_t *base;
- table_info_t privateDictInfo;
- unsigned int fontName;
};
struct cff1_font_dict_op_serializer_t : cff_font_dict_op_serializer_t
{
bool serialize (hb_serialize_context_t *c,
const op_str_t &opstr,
- const font_dict_values_mod_t &mod) const
+ const cff1_font_dict_values_mod_t &mod) const
{
TRACE_SERIALIZE (this);
if (opstr.op == OpCode_FontName)
- return_trace (FontDict::serialize_uint2_op (c, opstr.op, mod.fontName));
+ return_trace (FontDict::serialize_int2_op (c, opstr.op, mod.fontName));
else
return_trace (SUPER::serialize (c, opstr, mod.privateDictInfo));
}
- unsigned int calculate_serialized_size (const op_str_t &opstr) const
- {
- if (opstr.op == OpCode_FontName)
- return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_FontName);
- else
- return SUPER::calculate_serialized_size (opstr);
- }
-
private:
typedef cff_font_dict_op_serializer_t SUPER;
};
@@ -331,7 +268,7 @@ struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatte
struct range_list_t : hb_vector_t<code_pair_t>
{
/* replace the first glyph ID in the "glyph" field each range with a nLeft value */
- bool finalize (unsigned int last_glyph)
+ bool complete (unsigned int last_glyph)
{
bool two_byte = false;
for (unsigned int i = (*this).length; i > 0; i--)
@@ -402,7 +339,7 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs
cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
: subr_subsetter_t (acc_, plan_) {}
- static void finalize_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+ static void complete_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
{
/* insert width at the beginning of the charstring as necessary */
if (env.has_width)
@@ -414,8 +351,8 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs
param.current_parsed_str->set_parsed ();
for (unsigned int i = 0; i < env.callStack.get_count (); i++)
{
- parsed_cs_str_t *parsed_str = param.get_parsed_str_for_context (env.callStack[i]);
- if (likely (parsed_str != nullptr))
+ parsed_cs_str_t *parsed_str = param.get_parsed_str_for_context (env.callStack[i]);
+ if (likely (parsed_str))
parsed_str->set_parsed ();
else
env.set_error ();
@@ -425,16 +362,13 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs
struct cff_subset_plan {
cff_subset_plan ()
- : final_size (0),
- offsets (),
+ : info (),
orig_fdcount (0),
subset_fdcount (1),
subset_fdselect_format (0),
drop_hints (false),
desubroutinize(false)
{
- topdict_sizes.init ();
- topdict_sizes.resize (1);
topdict_mod.init ();
subset_fdselect_ranges.init ();
fdmap.init ();
@@ -452,7 +386,6 @@ struct cff_subset_plan {
~cff_subset_plan ()
{
- topdict_sizes.fini ();
topdict_mod.fini ();
subset_fdselect_ranges.fini ();
fdmap.fini ();
@@ -466,7 +399,7 @@ struct cff_subset_plan {
sidmap.fini ();
}
- unsigned int plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+ void plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
{
const Encoding *encoding = acc.encoding;
unsigned int size0, size1, supp_size;
@@ -484,7 +417,7 @@ struct cff_subset_plan {
hb_codepoint_t old_glyph;
if (!plan->old_gid_for_new_gid (glyph, &old_glyph))
{
- /* Retain the code for the old missing glyph ID */
+ /* Retain the code for the old missing glyph ID */
old_glyph = glyph;
}
code = acc.glyph_to_code (old_glyph);
@@ -501,7 +434,7 @@ struct cff_subset_plan {
}
last_code = code;
- if (encoding != &Null(Encoding))
+ if (encoding != &Null (Encoding))
{
hb_codepoint_t sid = acc.glyph_to_sid (old_glyph);
encoding->get_supplement_codes (sid, supp_codes);
@@ -515,7 +448,7 @@ struct cff_subset_plan {
}
supp_codes.fini ();
- subset_enc_code_ranges.finalize (glyph);
+ subset_enc_code_ranges.complete (glyph);
assert (subset_enc_num_codes <= 0xFF);
size0 = Encoding0::min_size + HBUINT8::static_size * subset_enc_num_codes;
@@ -525,14 +458,9 @@ struct cff_subset_plan {
subset_enc_format = 0;
else
subset_enc_format = 1;
-
- return Encoding::calculate_serialized_size (
- subset_enc_format,
- subset_enc_format? subset_enc_code_ranges.length: subset_enc_num_codes,
- subset_enc_supp_codes.length);
}
- unsigned int plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+ void plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
{
unsigned int size0, size_ranges;
hb_codepoint_t sid, last_sid = CFF_UNDEF_CODE;
@@ -544,7 +472,7 @@ struct cff_subset_plan {
hb_codepoint_t old_glyph;
if (!plan->old_gid_for_new_gid (glyph, &old_glyph))
{
- /* Retain the SID for the old missing glyph ID */
+ /* Retain the SID for the old missing glyph ID */
old_glyph = glyph;
}
sid = acc.glyph_to_sid (old_glyph);
@@ -560,7 +488,7 @@ struct cff_subset_plan {
last_sid = sid;
}
- bool two_byte = subset_charset_ranges.finalize (glyph);
+ bool two_byte = subset_charset_ranges.complete (glyph);
size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1);
if (!two_byte)
@@ -574,10 +502,6 @@ struct cff_subset_plan {
subset_charset_format = 1;
else
subset_charset_format = 2;
-
- return Charset::calculate_serialized_size (
- subset_charset_format,
- subset_charset_format? subset_charset_ranges.length: plan->num_output_glyphs ());
}
bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
@@ -594,7 +518,7 @@ struct cff_subset_plan {
}
}
- if (acc.fdArray != &Null(CFF1FDArray))
+ if (acc.fdArray != &Null (CFF1FDArray))
for (unsigned int i = 0; i < orig_fdcount; i++)
if (fdmap.has (i))
(void)sidmap.add (acc.fontDicts[i].fontName);
@@ -609,7 +533,6 @@ struct cff_subset_plan {
hb_codepoint_t old_glyph;
if (!plan->old_gid_for_new_gid (0, &old_glyph) || (old_glyph != 0)) return false;
- final_size = 0;
num_glyphs = plan->num_output_glyphs ();
orig_fdcount = acc.fdCount;
drop_hints = plan->drop_hints;
@@ -620,7 +543,7 @@ struct cff_subset_plan {
for (hb_codepoint_t new_glyph = 0; new_glyph < plan->num_output_glyphs (); new_glyph++)
{
if (!plan->old_gid_for_new_gid(new_glyph, &old_glyph))
- continue;
+ continue;
if (new_glyph != old_glyph) {
gid_renum = true;
break;
@@ -630,13 +553,6 @@ struct cff_subset_plan {
subset_charset = gid_renum || !acc.is_predef_charset ();
subset_encoding = !acc.is_CID() && !acc.is_predef_encoding ();
- /* CFF header */
- final_size += OT::cff1::static_size;
-
- /* Name INDEX */
- offsets.nameIndexOffset = final_size;
- final_size += acc.nameIndex->get_size ();
-
/* top dict INDEX */
{
/* Add encoding/charset to a (copy of) top dict as necessary */
@@ -650,25 +566,16 @@ struct cff_subset_plan {
if (need_to_add_set)
topdict_mod.add_op (OpCode_charset);
}
- offsets.topDictInfo.offset = final_size;
- cff1_top_dict_op_serializer_t topSzr;
- unsigned int topDictSize = TopDict::calculate_serialized_size (topdict_mod, topSzr);
- offsets.topDictInfo.offSize = calcOffSize(topDictSize);
- if (unlikely (offsets.topDictInfo.offSize > 4))
- return false;
- final_size += CFF1IndexOf<TopDict>::calculate_serialized_size<cff1_top_dict_values_mod_t>
- (offsets.topDictInfo.offSize,
- &topdict_mod, 1, topdict_sizes, topSzr);
}
/* Determine re-mapping of font index as fdmap among other info */
- if (acc.fdSelect != &Null(CFF1FDSelect))
+ if (acc.fdSelect != &Null (CFF1FDSelect))
{
if (unlikely (!hb_plan_subset_cff_fdselect (plan,
orig_fdcount,
*acc.fdSelect,
subset_fdcount,
- offsets.FDSelectInfo.size,
+ info.fd_select.size,
subset_fdselect_format,
subset_fdselect_ranges,
fdmap)))
@@ -683,18 +590,11 @@ struct cff_subset_plan {
if (unlikely (!collect_sids_in_dicts (acc)))
return false;
if (unlikely (sidmap.get_population () > 0x8000)) /* assumption: a dict won't reference that many strings */
- return false;
- if (subset_charset)
- offsets.charsetInfo.size = plan_subset_charset (acc, plan);
+ return false;
- topdict_mod.reassignSIDs (sidmap);
- }
+ if (subset_charset) plan_subset_charset (acc, plan);
- /* String INDEX */
- {
- offsets.stringIndexInfo.offset = final_size;
- offsets.stringIndexInfo.size = acc.stringIndex->calculate_serialized_size (offsets.stringIndexInfo.offSize, sidmap);
- final_size += offsets.stringIndexInfo.size;
+ topdict_mod.reassignSIDs (sidmap);
}
if (desubroutinize)
@@ -704,9 +604,6 @@ struct cff_subset_plan {
flattener(acc, plan);
if (!flattener.flatten (subset_charstrings))
return false;
-
- /* no global/local subroutines */
- offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (1, 0, 0);
}
else
{
@@ -723,131 +620,48 @@ struct cff_subset_plan {
if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
return false;
- /* global subrs */
- unsigned int dataSize = subset_globalsubrs.total_size ();
- offsets.globalSubrsInfo.offSize = calcOffSize (dataSize);
- if (unlikely (offsets.globalSubrsInfo.offSize > 4))
- return false;
- offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (offsets.globalSubrsInfo.offSize, subset_globalsubrs.length, dataSize);
-
/* local subrs */
- if (!offsets.localSubrsInfos.resize (orig_fdcount))
- return false;
if (!subset_localsubrs.resize (orig_fdcount))
return false;
for (unsigned int fd = 0; fd < orig_fdcount; fd++)
{
subset_localsubrs[fd].init ();
- offsets.localSubrsInfos[fd].init ();
if (fdmap.has (fd))
{
if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
return false;
-
- unsigned int dataSize = subset_localsubrs[fd].total_size ();
- if (dataSize > 0)
- {
- offsets.localSubrsInfos[fd].offset = final_size;
- offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
- if (unlikely (offsets.localSubrsInfos[fd].offSize > 4))
- return false;
- offsets.localSubrsInfos[fd].size = CFF1Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
- }
}
}
}
- /* global subrs */
- offsets.globalSubrsInfo.offset = final_size;
- final_size += offsets.globalSubrsInfo.size;
-
/* Encoding */
- if (!subset_encoding)
- offsets.encodingOffset = acc.topDict.EncodingOffset;
- else
- {
- offsets.encodingOffset = final_size;
- final_size += plan_subset_encoding (acc, plan);
- }
-
- /* Charset */
- if (!subset_charset && acc.is_predef_charset ())
- offsets.charsetInfo.offset = acc.topDict.CharsetOffset;
- else
- offsets.charsetInfo.offset = final_size;
- final_size += offsets.charsetInfo.size;
-
- /* FDSelect */
- if (acc.fdSelect != &Null(CFF1FDSelect))
- {
- offsets.FDSelectInfo.offset = final_size;
- final_size += offsets.FDSelectInfo.size;
- }
-
- /* FDArray (FDIndex) */
- if (acc.fdArray != &Null(CFF1FDArray)) {
- offsets.FDArrayInfo.offset = final_size;
- cff1_font_dict_op_serializer_t fontSzr;
- unsigned int dictsSize = 0;
- for (unsigned int i = 0; i < acc.fontDicts.length; i++)
- if (fdmap.has (i))
- dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
-
- offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
- if (unlikely (offsets.FDArrayInfo.offSize > 4))
- return false;
- final_size += CFF1Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
- }
-
- /* CharStrings */
- {
- offsets.charStringsInfo.offset = final_size;
- unsigned int dataSize = subset_charstrings.total_size ();
- offsets.charStringsInfo.offSize = calcOffSize (dataSize);
- if (unlikely (offsets.charStringsInfo.offSize > 4))
- return false;
- final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->num_output_glyphs (), dataSize);
- }
+ if (subset_encoding)
+ plan_subset_encoding (acc, plan);
/* private dicts & local subrs */
- offsets.privateDictInfo.offset = final_size;
- for (unsigned int i = 0; i < orig_fdcount; i++)
+ if (!acc.is_CID ())
+ fontdicts_mod.push (cff1_font_dict_values_mod_t ());
+ else
{
- if (fdmap.has (i))
- {
- bool has_localsubrs = offsets.localSubrsInfos[i].size > 0;
- cff_private_dict_op_serializer_t privSzr (desubroutinize, plan->drop_hints);
- unsigned int priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
- table_info_t privInfo = { final_size, priv_size, 0 };
- font_dict_values_mod_t fontdict_mod;
- if (!acc.is_CID ())
- fontdict_mod.init ( &Null(cff1_font_dict_values_t), CFF_UNDEF_SID, privInfo );
- else
- fontdict_mod.init ( &acc.fontDicts[i], sidmap[acc.fontDicts[i].fontName], privInfo );
- fontdicts_mod.push (fontdict_mod);
- final_size += privInfo.size;
-
- if (!plan->desubroutinize && has_localsubrs)
+ + hb_iter (acc.fontDicts)
+ | hb_filter ([&] (const cff1_font_dict_values_t &_)
+ { return fdmap.has (&_ - &acc.fontDicts[0]); } )
+ | hb_map ([&] (const cff1_font_dict_values_t &_)
{
- offsets.localSubrsInfos[i].offset = final_size;
- final_size += offsets.localSubrsInfos[i].size;
- }
- }
+ cff1_font_dict_values_mod_t mod;
+ mod.init (&_, sidmap[_.fontName]);
+ return mod;
+ })
+ | hb_sink (fontdicts_mod)
+ ;
}
- if (!acc.is_CID ())
- offsets.privateDictInfo = fontdicts_mod[0].privateDictInfo;
-
return ((subset_charstrings.length == plan->num_output_glyphs ())
&& (fontdicts_mod.length == subset_fdcount));
}
- unsigned int get_final_size () const { return final_size; }
-
- unsigned int final_size;
- hb_vector_t<unsigned int> topdict_sizes;
cff1_top_dict_values_mod_t topdict_mod;
- cff1_sub_table_offsets_t offsets;
+ cff1_sub_table_info_t info;
unsigned int num_glyphs;
unsigned int orig_fdcount;
@@ -862,7 +676,7 @@ struct cff_subset_plan {
str_buff_vec_t subset_charstrings;
str_buff_vec_t subset_globalsubrs;
hb_vector_t<str_buff_vec_t> subset_localsubrs;
- hb_vector_t<font_dict_values_mod_t> fontdicts_mod;
+ hb_vector_t<cff1_font_dict_values_mod_t> fontdicts_mod;
bool drop_hints;
@@ -883,91 +697,95 @@ struct cff_subset_plan {
bool desubroutinize;
};
-static inline bool _write_cff1 (const cff_subset_plan &plan,
- const OT::cff1::accelerator_subset_t &acc,
- unsigned int num_glyphs,
- unsigned int dest_sz,
- void *dest)
+static bool _serialize_cff1 (hb_serialize_context_t *c,
+ cff_subset_plan &plan,
+ const OT::cff1::accelerator_subset_t &acc,
+ unsigned int num_glyphs)
{
- hb_serialize_context_t c (dest, dest_sz);
-
- OT::cff1 *cff = c.start_serialize<OT::cff1> ();
- if (unlikely (!c.extend_min (*cff)))
- return false;
-
- /* header */
- cff->version.major = 0x01;
- cff->version.minor = 0x00;
- cff->nameIndex = cff->min_size;
- cff->offSize = 4; /* unused? */
-
- /* name INDEX */
+ /* private dicts & local subrs */
+ for (int i = (int)acc.privateDicts.length; --i >= 0 ;)
{
- assert (cff->nameIndex == (unsigned) (c.head - c.start));
- CFF1NameIndex *dest = c.start_embed<CFF1NameIndex> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, *acc.nameIndex)))
+ if (plan.fdmap.has (i))
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF name INDEX");
- return false;
- }
- }
+ objidx_t subrs_link = 0;
+ if (plan.subset_localsubrs[i].length > 0)
+ {
+ CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
+ if (unlikely (!dest)) return false;
+ c->push ();
+ if (likely (dest && dest->serialize (c, plan.subset_localsubrs[i])))
+ subrs_link = c->pop_pack ();
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
+ }
- /* top dict INDEX */
- {
- assert (plan.offsets.topDictInfo.offset == (unsigned) (c.head - c.start));
- CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict>> ();
- if (dest == nullptr) return false;
- cff1_top_dict_op_serializer_t topSzr;
- top_dict_modifiers_t modifier (plan.offsets, plan.topDictModSIDs);
- if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize,
- &plan.topdict_mod, 1,
- plan.topdict_sizes, topSzr, modifier)))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF top dict");
- return false;
+ PrivateDict *pd = c->start_embed<PrivateDict> ();
+ if (unlikely (!pd)) return false;
+ c->push ();
+ cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+ /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
+ if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link)))
+ {
+ unsigned fd = plan.fdmap[i];
+ plan.fontdicts_mod[fd].privateDictInfo.size = c->length ();
+ plan.fontdicts_mod[fd].privateDictInfo.link = c->pop_pack ();
+ }
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
}
}
- /* String INDEX */
+ if (!acc.is_CID ())
+ plan.info.privateDictInfo = plan.fontdicts_mod[0].privateDictInfo;
+
+ /* CharStrings */
{
- assert (plan.offsets.stringIndexInfo.offset == (unsigned) (c.head - c.start));
- CFF1StringIndex *dest = c.start_embed<CFF1StringIndex> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, *acc.stringIndex, plan.offsets.stringIndexInfo.offSize, plan.sidmap)))
+ CFF1CharStrings *cs = c->start_embed<CFF1CharStrings> ();
+ if (unlikely (!cs)) return false;
+ c->push ();
+ if (likely (cs->serialize (c, plan.subset_charstrings)))
+ plan.info.char_strings_link = c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF string INDEX");
+ c->pop_discard ();
return false;
}
}
- /* global subrs */
+ /* FDArray (FD Index) */
+ if (acc.fdArray != &Null (CFF1FDArray))
{
- assert (plan.offsets.globalSubrsInfo.offset != 0);
- assert (plan.offsets.globalSubrsInfo.offset == (unsigned) (c.head - c.start));
-
- CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
+ CFF1FDArray *fda = c->start_embed<CFF1FDArray> ();
+ if (unlikely (!fda)) return false;
+ c->push ();
+ cff1_font_dict_op_serializer_t fontSzr;
+ auto it = + hb_zip (+ hb_iter (plan.fontdicts_mod), + hb_iter (plan.fontdicts_mod));
+ if (likely (fda->serialize (c, it, fontSzr)))
+ plan.info.fd_array_link = c->pop_pack (false);
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
+ c->pop_discard ();
return false;
}
}
- /* Encoding */
- if (plan.subset_encoding)
+ /* FDSelect */
+ if (acc.fdSelect != &Null (CFF1FDSelect))
{
- assert (plan.offsets.encodingOffset == (unsigned) (c.head - c.start));
- Encoding *dest = c.start_embed<Encoding> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c,
- plan.subset_enc_format,
- plan.subset_enc_num_codes,
- plan.subset_enc_code_ranges,
- plan.subset_enc_supp_codes)))
+ c->push ();
+ if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *acc.fdSelect, acc.fdCount,
+ plan.subset_fdselect_format, plan.info.fd_select.size,
+ plan.subset_fdselect_ranges)))
+ plan.info.fd_select.link = c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize Encoding");
+ c->pop_discard ();
return false;
}
}
@@ -975,129 +793,120 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* Charset */
if (plan.subset_charset)
{
- assert (plan.offsets.charsetInfo.offset == (unsigned) (c.head - c.start));
- Charset *dest = c.start_embed<Charset> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c,
- plan.subset_charset_format,
- plan.num_glyphs,
- plan.subset_charset_ranges)))
+ Charset *dest = c->start_embed<Charset> ();
+ if (unlikely (!dest)) return false;
+ c->push ();
+ if (likely (dest->serialize (c,
+ plan.subset_charset_format,
+ plan.num_glyphs,
+ plan.subset_charset_ranges)))
+ plan.info.charset_link = c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize Charset");
+ c->pop_discard ();
return false;
}
}
- /* FDSelect */
- if (acc.fdSelect != &Null(CFF1FDSelect))
+ /* Encoding */
+ if (plan.subset_encoding)
{
- assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start));
-
- if (unlikely (!hb_serialize_cff_fdselect (&c, num_glyphs, *acc.fdSelect, acc.fdCount,
- plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
- plan.subset_fdselect_ranges)))
+ Encoding *dest = c->start_embed<Encoding> ();
+ if (unlikely (!dest)) return false;
+ c->push ();
+ if (likely (dest->serialize (c,
+ plan.subset_enc_format,
+ plan.subset_enc_num_codes,
+ plan.subset_enc_code_ranges,
+ plan.subset_enc_supp_codes)))
+ plan.info.encoding_link = c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF subset FDSelect");
+ c->pop_discard ();
return false;
}
}
- /* FDArray (FD Index) */
- if (acc.fdArray != &Null(CFF1FDArray))
+ /* global subrs */
{
- assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start));
- CFF1FDArray *fda = c.start_embed<CFF1FDArray> ();
- if (unlikely (fda == nullptr)) return false;
- cff1_font_dict_op_serializer_t fontSzr;
- if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
- plan.fontdicts_mod,
- fontSzr)))
+ c->push ();
+ CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
+ if (unlikely (!dest)) return false;
+ if (likely (dest->serialize (c, plan.subset_globalsubrs)))
+ c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF FDArray");
+ c->pop_discard ();
return false;
}
}
- /* CharStrings */
+ /* String INDEX */
{
- assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start));
- CFF1CharStrings *cs = c.start_embed<CFF1CharStrings> ();
- if (unlikely (cs == nullptr)) return false;
- if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
+ CFF1StringIndex *dest = c->start_embed<CFF1StringIndex> ();
+ if (unlikely (!dest)) return false;
+ c->push ();
+ if (likely (dest->serialize (c, *acc.stringIndex, plan.sidmap)))
+ c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF CharStrings");
+ c->pop_discard ();
return false;
}
}
- /* private dicts & local subrs */
- assert (plan.offsets.privateDictInfo.offset == (unsigned) (c.head - c.start));
- for (unsigned int i = 0; i < acc.privateDicts.length; i++)
+ OT::cff1 *cff = c->allocate_min<OT::cff1> ();
+ if (unlikely (!cff))
+ return false;
+
+ /* header */
+ cff->version.major = 0x01;
+ cff->version.minor = 0x00;
+ cff->nameIndex = cff->min_size;
+ cff->offSize = 4; /* unused? */
+
+ /* name INDEX */
+ if (unlikely (!(*acc.nameIndex).copy (c))) return false;
+
+ /* top dict INDEX */
{
- if (plan.fdmap.has (i))
+ /* serialize singleton TopDict */
+ TopDict *top = c->start_embed<TopDict> ();
+ if (!top) return false;
+ c->push ();
+ cff1_top_dict_op_serializer_t topSzr;
+ unsigned top_size = 0;
+ top_dict_modifiers_t modifier (plan.info, plan.topDictModSIDs);
+ if (likely (top->serialize (c, plan.topdict_mod, topSzr, modifier)))
{
- PrivateDict *pd = c.start_embed<PrivateDict> ();
- if (unlikely (pd == nullptr)) return false;
- unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size;
- bool result;
- cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
- /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
- unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
- result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
- if (unlikely (!result))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
- return false;
- }
- if (plan.offsets.localSubrsInfos[i].size > 0)
- {
- CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
- return false;
- }
- }
+ top_size = c->length ();
+ c->pop_pack (false);
}
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
+ /* serialize INDEX header for above */
+ CFF1Index *dest = c->start_embed<CFF1Index> ();
+ if (!dest) return false;
+ return dest->serialize_header (c, hb_iter (hb_array_t<unsigned> (&top_size, 1)));
}
-
- assert (c.head == c.end);
- c.end_serialize ();
-
- return true;
}
-static inline bool
+static bool
_hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc,
- const char *data,
- hb_subset_plan_t *plan,
- hb_blob_t **prime /* OUT */)
+ hb_subset_context_t *c)
{
cff_subset_plan cff_plan;
- if (unlikely (!cff_plan.create (acc, plan)))
+ if (unlikely (!cff_plan.create (acc, c->plan)))
{
DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan.");
return false;
}
- unsigned int cff_prime_size = cff_plan.get_final_size ();
- char *cff_prime_data = (char *) calloc (1, cff_prime_size);
-
- if (unlikely (!_write_cff1 (cff_plan, acc, plan->num_output_glyphs (),
- cff_prime_size, cff_prime_data))) {
- DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff.");
- free (cff_prime_data);
- return false;
- }
-
- *prime = hb_blob_create (cff_prime_data,
- cff_prime_size,
- HB_MEMORY_MODE_READONLY,
- cff_prime_data,
- free);
- return true;
+ return _serialize_cff1 (c->serializer, cff_plan, acc, c->plan->num_output_glyphs ());
}
/**
@@ -1107,17 +916,11 @@ _hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc,
* Return value: subsetted cff table.
**/
bool
-hb_subset_cff1 (hb_subset_plan_t *plan,
- hb_blob_t **prime /* OUT */)
+hb_subset_cff1 (hb_subset_context_t *c)
{
- hb_blob_t *cff_blob = hb_sanitize_context_t().reference_table<CFF::cff1> (plan->source);
- const char *data = hb_blob_get_data(cff_blob, nullptr);
-
OT::cff1::accelerator_subset_t acc;
- acc.init(plan->source);
- bool result = likely (acc.is_valid ()) &&
- _hb_subset_cff1 (acc, data, plan, prime);
- hb_blob_destroy (cff_blob);
+ acc.init (c->plan->source);
+ bool result = likely (acc.is_valid ()) && _hb_subset_cff1 (acc, c);
acc.fini ();
return result;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh
index 1ec8678845a..aaf5def1ed5 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.hh
@@ -32,7 +32,6 @@
#include "hb-subset-plan.hh"
HB_INTERNAL bool
-hb_subset_cff1 (hb_subset_plan_t *plan,
- hb_blob_t **cff_prime /* OUT */);
+hb_subset_cff1 (hb_subset_context_t *c);
#endif /* HB_SUBSET_CFF1_HH */
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 7edc3f51535..637f38fbf82 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
@@ -38,43 +38,31 @@
using namespace CFF;
-struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t
+struct cff2_sub_table_info_t : cff_sub_table_info_t
{
- cff2_sub_table_offsets_t ()
- : cff_sub_table_offsets_t (),
- varStoreOffset (0)
+ cff2_sub_table_info_t ()
+ : cff_sub_table_info_t (),
+ var_store_link (0)
{}
- unsigned int varStoreOffset;
+ objidx_t var_store_link;
};
struct cff2_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<>
{
bool serialize (hb_serialize_context_t *c,
const op_str_t &opstr,
- const cff2_sub_table_offsets_t &offsets) const
+ const cff2_sub_table_info_t &info) const
{
TRACE_SERIALIZE (this);
switch (opstr.op)
{
case OpCode_vstore:
- return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.varStoreOffset));
+ return_trace (FontDict::serialize_link4_op(c, opstr.op, info.var_store_link));
default:
- return_trace (cff_top_dict_op_serializer_t<>::serialize (c, opstr, offsets));
- }
- }
-
- unsigned int calculate_serialized_size (const op_str_t &opstr) const
- {
- switch (opstr.op)
- {
- case OpCode_vstore:
- return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
-
- default:
- return cff_top_dict_op_serializer_t<>::calculate_serialized_size (opstr);
+ return_trace (cff_top_dict_op_serializer_t<>::serialize (c, opstr, info));
}
}
};
@@ -116,8 +104,8 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
const blend_arg_t &arg = env.argStack[i];
if (arg.blending ())
{
- if (unlikely (!((arg.numValues > 0) && (env.argStack.get_count () >= arg.numValues))))
- {
+ if (unlikely (!((arg.numValues > 0) && (env.argStack.get_count () >= arg.numValues))))
+ {
env.set_error ();
return;
}
@@ -144,8 +132,8 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
if (unlikely (!((arg1.blending () && (arg.numValues == arg1.numValues) && (arg1.valueIndex == j) &&
(arg1.deltas.length == env.get_region_count ())))))
{
- env.set_error ();
- return;
+ env.set_error ();
+ return;
}
encoder.encode_num (arg1);
}
@@ -232,7 +220,7 @@ struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs
cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
: subr_subsetter_t (acc_, plan_) {}
- static void finalize_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+ static void complete_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
{
/* vsindex is inserted at the beginning of the charstring as necessary */
if (env.seen_vsindex ())
@@ -246,9 +234,9 @@ struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs
struct cff2_subset_plan {
cff2_subset_plan ()
- : final_size (0),
- orig_fdcount (0),
+ : orig_fdcount (0),
subset_fdcount(1),
+ subset_fdselect_size (0),
subset_fdselect_format (0),
drop_hints (false),
desubroutinize (false)
@@ -258,7 +246,6 @@ struct cff2_subset_plan {
subset_charstrings.init ();
subset_globalsubrs.init ();
subset_localsubrs.init ();
- privateDictInfos.init ();
}
~cff2_subset_plan ()
@@ -268,28 +255,16 @@ struct cff2_subset_plan {
subset_charstrings.fini_deep ();
subset_globalsubrs.fini_deep ();
subset_localsubrs.fini_deep ();
- privateDictInfos.fini ();
}
bool create (const OT::cff2::accelerator_subset_t &acc,
hb_subset_plan_t *plan)
{
- final_size = 0;
orig_fdcount = acc.fdArray->count;
drop_hints = plan->drop_hints;
desubroutinize = plan->desubroutinize;
- /* CFF2 header */
- final_size += OT::cff2::static_size;
-
- /* top dict */
- {
- cff2_top_dict_op_serializer_t topSzr;
- offsets.topDictInfo.size = TopDict::calculate_serialized_size (acc.topDict, topSzr);
- final_size += offsets.topDictInfo.size;
- }
-
if (desubroutinize)
{
/* Flatten global & local subrs */
@@ -297,9 +272,6 @@ struct cff2_subset_plan {
flattener(acc, plan);
if (!flattener.flatten (subset_charstrings))
return false;
-
- /* no global/local subroutines */
- offsets.globalSubrsInfo.size = CFF2Subrs::calculate_serialized_size (1, 0, 0);
}
else
{
@@ -316,115 +288,41 @@ struct cff2_subset_plan {
if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
return false;
- /* global subrs */
- unsigned int dataSize = subset_globalsubrs.total_size ();
- offsets.globalSubrsInfo.offSize = calcOffSize (dataSize);
- offsets.globalSubrsInfo.size = CFF2Subrs::calculate_serialized_size (offsets.globalSubrsInfo.offSize, subset_globalsubrs.length, dataSize);
-
/* local subrs */
- if (!offsets.localSubrsInfos.resize (orig_fdcount))
- return false;
if (!subset_localsubrs.resize (orig_fdcount))
return false;
for (unsigned int fd = 0; fd < orig_fdcount; fd++)
{
subset_localsubrs[fd].init ();
- offsets.localSubrsInfos[fd].init ();
if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
return false;
-
- unsigned int dataSize = subset_localsubrs[fd].total_size ();
- if (dataSize > 0)
- {
- offsets.localSubrsInfos[fd].offset = final_size;
- offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
- offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
- }
}
}
- /* global subrs */
- offsets.globalSubrsInfo.offset = final_size;
- final_size += offsets.globalSubrsInfo.size;
-
- /* variation store */
- if (acc.varStore != &Null(CFF2VariationStore))
- {
- offsets.varStoreOffset = final_size;
- final_size += acc.varStore->get_size ();
- }
-
/* FDSelect */
- if (acc.fdSelect != &Null(CFF2FDSelect))
+ if (acc.fdSelect != &Null (CFF2FDSelect))
{
- offsets.FDSelectInfo.offset = final_size;
if (unlikely (!hb_plan_subset_cff_fdselect (plan,
orig_fdcount,
*(const FDSelect *)acc.fdSelect,
subset_fdcount,
- offsets.FDSelectInfo.size,
+ subset_fdselect_size,
subset_fdselect_format,
subset_fdselect_ranges,
fdmap)))
return false;
-
- final_size += offsets.FDSelectInfo.size;
}
else
fdmap.identity (1);
- /* FDArray (FDIndex) */
- {
- offsets.FDArrayInfo.offset = final_size;
- cff_font_dict_op_serializer_t fontSzr;
- unsigned int dictsSize = 0;
- for (unsigned int i = 0; i < acc.fontDicts.length; i++)
- if (fdmap.has (i))
- dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
-
- offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
- final_size += CFF2Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
- }
-
- /* CharStrings */
- {
- offsets.charStringsInfo.offset = final_size;
- unsigned int dataSize = subset_charstrings.total_size ();
- offsets.charStringsInfo.offSize = calcOffSize (dataSize);
- final_size += CFF2CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->num_output_glyphs (), dataSize);
- }
-
- /* private dicts & local subrs */
- offsets.privateDictsOffset = final_size;
- for (unsigned int i = 0; i < orig_fdcount; i++)
- {
- if (fdmap.has (i))
- {
- bool has_localsubrs = offsets.localSubrsInfos[i].size > 0;
- cff_private_dict_op_serializer_t privSzr (desubroutinize, drop_hints);
- unsigned int priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
- table_info_t privInfo = { final_size, priv_size, 0 };
- privateDictInfos.push (privInfo);
- final_size += privInfo.size;
-
- if (!plan->desubroutinize && has_localsubrs)
- {
- offsets.localSubrsInfos[i].offset = final_size;
- final_size += offsets.localSubrsInfos[i].size;
- }
- }
- }
-
return true;
}
- unsigned int get_final_size () const { return final_size; }
-
- unsigned int final_size;
- cff2_sub_table_offsets_t offsets;
+ cff2_sub_table_info_t info;
unsigned int orig_fdcount;
unsigned int subset_fdcount;
+ unsigned int subset_fdselect_size;
unsigned int subset_fdselect_format;
hb_vector_t<code_pair_t> subset_fdselect_ranges;
@@ -433,200 +331,158 @@ struct cff2_subset_plan {
str_buff_vec_t subset_charstrings;
str_buff_vec_t subset_globalsubrs;
hb_vector_t<str_buff_vec_t> subset_localsubrs;
- hb_vector_t<table_info_t> privateDictInfos;
bool drop_hints;
bool desubroutinize;
};
-static inline bool _write_cff2 (const cff2_subset_plan &plan,
- const OT::cff2::accelerator_subset_t &acc,
- unsigned int num_glyphs,
- unsigned int dest_sz,
- void *dest)
+static bool _serialize_cff2 (hb_serialize_context_t *c,
+ cff2_subset_plan &plan,
+ const OT::cff2::accelerator_subset_t &acc,
+ unsigned int num_glyphs)
{
- hb_serialize_context_t c (dest, dest_sz);
-
- OT::cff2 *cff2 = c.start_serialize<OT::cff2> ();
- if (unlikely (!c.extend_min (*cff2)))
- return false;
-
- /* header */
- cff2->version.major = 0x02;
- cff2->version.minor = 0x00;
- cff2->topDict = OT::cff2::static_size;
+ /* private dicts & local subrs */
+ hb_vector_t<table_info_t> private_dict_infos;
+ if (unlikely (!private_dict_infos.resize (plan.subset_fdcount))) return false;
- /* top dict */
+ for (int i = (int)acc.privateDicts.length; --i >= 0 ;)
{
- assert (cff2->topDict == (unsigned) (c.head - c.start));
- cff2->topDictSize = plan.offsets.topDictInfo.size;
- TopDict &dict = cff2 + cff2->topDict;
- cff2_top_dict_op_serializer_t topSzr;
- if (unlikely (!dict.serialize (&c, acc.topDict, topSzr, plan.offsets)))
+ if (plan.fdmap.has (i))
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 top dict");
- return false;
- }
- }
+ objidx_t subrs_link = 0;
- /* global subrs */
- {
- assert (cff2->topDict + plan.offsets.topDictInfo.size == (unsigned) (c.head - c.start));
- CFF2Subrs *dest = c.start_embed <CFF2Subrs> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
- return false;
+ if (plan.subset_localsubrs[i].length > 0)
+ {
+ CFF2Subrs *dest = c->start_embed <CFF2Subrs> ();
+ if (unlikely (!dest)) return false;
+ c->push ();
+ if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
+ subrs_link = c->pop_pack ();
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
+ }
+ PrivateDict *pd = c->start_embed<PrivateDict> ();
+ if (unlikely (!pd)) return false;
+ c->push ();
+ cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+ if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link)))
+ {
+ unsigned fd = plan.fdmap[i];
+ private_dict_infos[fd].size = c->length ();
+ private_dict_infos[fd].link = c->pop_pack ();
+ }
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
}
}
- /* variation store */
- if (acc.varStore != &Null(CFF2VariationStore))
+ /* CharStrings */
{
- assert (plan.offsets.varStoreOffset == (unsigned) (c.head - c.start));
- CFF2VariationStore *dest = c.start_embed<CFF2VariationStore> ();
- if (unlikely (!dest->serialize (&c, acc.varStore)))
+ CFF2CharStrings *cs = c->start_embed<CFF2CharStrings> ();
+ if (unlikely (!cs)) return false;
+ c->push ();
+ if (likely (cs->serialize (c, plan.subset_charstrings)))
+ plan.info.char_strings_link = c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Variation Store");
+ c->pop_discard ();
return false;
}
}
/* FDSelect */
- if (acc.fdSelect != &Null(CFF2FDSelect))
+ if (acc.fdSelect != &Null (CFF2FDSelect))
{
- assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start));
-
- if (unlikely (!hb_serialize_cff_fdselect (&c, num_glyphs, *(const FDSelect *)acc.fdSelect, acc.fdArray->count,
- plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
- plan.subset_fdselect_ranges)))
+ c->push ();
+ if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect, plan.orig_fdcount,
+ plan.subset_fdselect_format, plan.subset_fdselect_size,
+ plan.subset_fdselect_ranges)))
+ plan.info.fd_select.link = c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 subset FDSelect");
+ c->pop_discard ();
return false;
}
}
/* FDArray (FD Index) */
{
- assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start));
- CFF2FDArray *fda = c.start_embed<CFF2FDArray> ();
- if (unlikely (fda == nullptr)) return false;
- cff_font_dict_op_serializer_t fontSzr;
- if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
- acc.fontDicts, plan.subset_fdcount, plan.fdmap,
- fontSzr, plan.privateDictInfos)))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 FDArray");
- return false;
- }
+ c->push ();
+ CFF2FDArray *fda = c->start_embed<CFF2FDArray> ();
+ if (unlikely (!fda)) return false;
+ cff_font_dict_op_serializer_t fontSzr;
+ auto it =
+ + hb_zip (+ hb_iter (acc.fontDicts)
+ | hb_filter ([&] (const cff2_font_dict_values_t &_)
+ { return plan.fdmap.has (&_ - &acc.fontDicts[0]); }),
+ hb_iter (private_dict_infos))
+ ;
+ if (unlikely (!fda->serialize (c, it, fontSzr))) return false;
+ plan.info.fd_array_link = c->pop_pack ();
}
- /* CharStrings */
+ /* variation store */
+ if (acc.varStore != &Null (CFF2VariationStore))
{
- assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start));
- CFF2CharStrings *cs = c.start_embed<CFF2CharStrings> ();
- if (unlikely (cs == nullptr)) return false;
- if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 CharStrings");
- return false;
- }
+ c->push ();
+ CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> ();
+ if (unlikely (!dest || !dest->serialize (c, acc.varStore))) return false;
+ plan.info.var_store_link = c->pop_pack ();
}
- /* private dicts & local subrs */
- assert (plan.offsets.privateDictsOffset == (unsigned) (c.head - c.start));
- for (unsigned int i = 0; i < acc.privateDicts.length; i++)
+ OT::cff2 *cff2 = c->allocate_min<OT::cff2> ();
+ if (unlikely (!cff2)) return false;
+
+ /* header */
+ cff2->version.major = 0x02;
+ cff2->version.minor = 0x00;
+ cff2->topDict = OT::cff2::static_size;
+
+ /* top dict */
{
- if (plan.fdmap.has (i))
- {
- PrivateDict *pd = c.start_embed<PrivateDict> ();
- if (unlikely (pd == nullptr)) return false;
- unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size;
- bool result;
- cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
- /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
- unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
- result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
- if (unlikely (!result))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
- return false;
- }
- if (plan.offsets.localSubrsInfos[i].size > 0)
- {
- CFF2Subrs *dest = c.start_embed <CFF2Subrs> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
- return false;
- }
- }
- }
+ TopDict &dict = cff2 + cff2->topDict;
+ cff2_top_dict_op_serializer_t topSzr;
+ if (unlikely (!dict.serialize (c, acc.topDict, topSzr, plan.info))) return false;
+ cff2->topDictSize = c->head - (const char *)&dict;
}
- assert (c.head == c.end);
- c.end_serialize ();
-
- return true;
+ /* global subrs */
+ {
+ CFF2Subrs *dest = c->start_embed <CFF2Subrs> ();
+ if (unlikely (!dest)) return false;
+ return dest->serialize (c, plan.subset_globalsubrs);
+ }
}
-static inline bool
+static bool
_hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc,
- const char *data,
- hb_subset_plan_t *plan,
- hb_blob_t **prime /* OUT */)
+ hb_subset_context_t *c)
{
cff2_subset_plan cff2_plan;
- if (unlikely (!cff2_plan.create (acc, plan)))
- {
- DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff2 subsetting plan.");
- return false;
- }
-
- unsigned int cff2_prime_size = cff2_plan.get_final_size ();
- char *cff2_prime_data = (char *) calloc (1, cff2_prime_size);
-
- if (unlikely (!_write_cff2 (cff2_plan, acc, plan->num_output_glyphs (),
- cff2_prime_size, cff2_prime_data))) {
- DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff2.");
- free (cff2_prime_data);
- return false;
- }
-
- *prime = hb_blob_create (cff2_prime_data,
- cff2_prime_size,
- HB_MEMORY_MODE_READONLY,
- cff2_prime_data,
- free);
- return true;
+ if (unlikely (!cff2_plan.create (acc, c->plan))) return false;
+ return _serialize_cff2 (c->serializer, cff2_plan, acc, c->plan->num_output_glyphs ());
}
/**
* hb_subset_cff2:
- * Subsets the CFF2 table according to a provided plan.
- *
- * Return value: subsetted cff2 table.
+ * Subsets the CFF2 table according to a provided subset context.
**/
bool
-hb_subset_cff2 (hb_subset_plan_t *plan,
- hb_blob_t **prime /* OUT */)
+hb_subset_cff2 (hb_subset_context_t *c)
{
- hb_blob_t *cff2_blob = hb_sanitize_context_t().reference_table<CFF::cff2> (plan->source);
- const char *data = hb_blob_get_data(cff2_blob, nullptr);
-
OT::cff2::accelerator_subset_t acc;
- acc.init(plan->source);
- bool result = likely (acc.is_valid ()) &&
- _hb_subset_cff2 (acc, data, plan, prime);
-
- hb_blob_destroy (cff2_blob);
+ acc.init (c->plan->source);
+ bool result = likely (acc.is_valid ()) && _hb_subset_cff2 (acc, c);
acc.fini ();
return result;
}
-
#endif
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh
index a07dc290e5c..f10556ddd74 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.hh
@@ -32,7 +32,6 @@
#include "hb-subset-plan.hh"
HB_INTERNAL bool
-hb_subset_cff2 (hb_subset_plan_t *plan,
- hb_blob_t **cff2_prime /* OUT */);
+hb_subset_cff2 (hb_subset_context_t *c);
#endif /* HB_SUBSET_CFF2_HH */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc
index d92f33ffed0..fe9be3ce020 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.cc
@@ -46,10 +46,13 @@ hb_subset_input_create_or_fail ()
input->glyphs = hb_set_create ();
input->name_ids = hb_set_create ();
hb_set_add_range (input->name_ids, 0, 6);
+ input->name_languages = hb_set_create ();
+ hb_set_add (input->name_languages, 0x0409);
input->drop_tables = hb_set_create ();
input->drop_hints = false;
input->desubroutinize = false;
input->retain_gids = false;
+ input->name_legacy = false;
hb_tag_t default_drop_tables[] = {
// Layout disabled by default
@@ -77,8 +80,6 @@ hb_subset_input_create_or_fail ()
HB_TAG ('G', 'l', 'o', 'c'),
HB_TAG ('S', 'i', 'l', 'f'),
HB_TAG ('S', 'i', 'l', 'l'),
- // Colour
- HB_TAG ('s', 'b', 'i', 'x')
};
input->drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
@@ -116,6 +117,7 @@ hb_subset_input_destroy (hb_subset_input_t *subset_input)
hb_set_destroy (subset_input->unicodes);
hb_set_destroy (subset_input->glyphs);
hb_set_destroy (subset_input->name_ids);
+ hb_set_destroy (subset_input->name_languages);
hb_set_destroy (subset_input->drop_tables);
free (subset_input);
@@ -152,6 +154,12 @@ hb_subset_input_nameid_set (hb_subset_input_t *subset_input)
}
HB_EXTERN hb_set_t *
+hb_subset_input_namelangid_set (hb_subset_input_t *subset_input)
+{
+ return subset_input->name_languages;
+}
+
+HB_EXTERN hb_set_t *
hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input)
{
return subset_input->drop_tables;
@@ -206,3 +214,16 @@ hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input)
{
return subset_input->retain_gids;
}
+
+HB_EXTERN void
+hb_subset_input_set_name_legacy (hb_subset_input_t *subset_input,
+ hb_bool_t name_legacy)
+{
+ subset_input->name_legacy = name_legacy;
+}
+
+HB_EXTERN hb_bool_t
+hb_subset_input_get_name_legacy (hb_subset_input_t *subset_input)
+{
+ return subset_input->name_legacy;
+}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh
index f6dd4ac3197..0aeb96695b7 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh
@@ -41,11 +41,13 @@ struct hb_subset_input_t
hb_set_t *unicodes;
hb_set_t *glyphs;
hb_set_t *name_ids;
+ hb_set_t *name_languages;
hb_set_t *drop_tables;
bool drop_hints;
bool desubroutinize;
bool retain_gids;
+ bool name_legacy;
/* TODO
*
* features
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 f4912f86bad..9e59be25941 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
@@ -31,6 +31,7 @@
#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-cff1-table.hh"
+#include "hb-ot-color-colr-table.hh"
#include "hb-ot-var-fvar-table.hh"
#include "hb-ot-stat-table.hh"
@@ -50,8 +51,24 @@ _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
#endif
#ifndef HB_NO_SUBSET_LAYOUT
+#ifdef HB_EXPERIMENTAL_API
+static void
+_remap_indexes (const hb_set_t *indexes,
+ hb_map_t *mapping /* OUT */)
+{
+ unsigned count = indexes->get_population ();
+
+ for (auto _ : + hb_zip (indexes->iter (), hb_range (count)))
+ mapping->set (_.first, _.second);
+
+}
+#endif
+
static inline void
-_gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
+_gsub_closure_glyphs_lookups_features (hb_face_t *face,
+ hb_set_t *gids_to_retain,
+ hb_map_t *gsub_lookups,
+ hb_map_t *gsub_features)
{
hb_set_t lookup_indices;
hb_ot_layout_collect_lookups (face,
@@ -63,6 +80,51 @@ _gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
hb_ot_layout_lookups_substitute_closure (face,
&lookup_indices,
gids_to_retain);
+#ifdef HB_EXPERIMENTAL_API
+ hb_ot_layout_closure_lookups (face,
+ HB_OT_TAG_GSUB,
+ gids_to_retain,
+ &lookup_indices);
+ _remap_indexes (&lookup_indices, gsub_lookups);
+
+ //closure features
+ hb_set_t feature_indices;
+ hb_ot_layout_closure_features (face,
+ HB_OT_TAG_GSUB,
+ gsub_lookups,
+ &feature_indices);
+ _remap_indexes (&feature_indices, gsub_features);
+#endif
+}
+
+static inline void
+_gpos_closure_lookups_features (hb_face_t *face,
+ const hb_set_t *gids_to_retain,
+ hb_map_t *gpos_lookups,
+ hb_map_t *gpos_features)
+{
+ hb_set_t lookup_indices;
+ hb_ot_layout_collect_lookups (face,
+ HB_OT_TAG_GPOS,
+ nullptr,
+ nullptr,
+ nullptr,
+ &lookup_indices);
+#ifdef HB_EXPERIMENTAL_API
+ hb_ot_layout_closure_lookups (face,
+ HB_OT_TAG_GPOS,
+ gids_to_retain,
+ &lookup_indices);
+ _remap_indexes (&lookup_indices, gpos_lookups);
+
+ //closure features
+ hb_set_t feature_indices;
+ hb_ot_layout_closure_features (face,
+ HB_OT_TAG_GPOS,
+ gpos_lookups,
+ &feature_indices);
+ _remap_indexes (&feature_indices, gpos_features);
+#endif
}
#endif
@@ -93,14 +155,21 @@ static void
_populate_gids_to_retain (hb_subset_plan_t* plan,
const hb_set_t *unicodes,
const hb_set_t *input_glyphs_to_retain,
- bool close_over_gsub)
+ bool close_over_gsub,
+ bool close_over_gpos)
{
OT::cmap::accelerator_t cmap;
OT::glyf::accelerator_t glyf;
+#ifndef HB_NO_SUBSET_CFF
OT::cff1::accelerator_t cff;
+#endif
+ OT::COLR::accelerator_t colr;
cmap.init (plan->source);
glyf.init (plan->source);
+#ifndef HB_NO_SUBSET_CFF
cff.init (plan->source);
+#endif
+ colr.init (plan->source);
plan->_glyphset_gsub->add (0); // Not-def
hb_set_union (plan->_glyphset_gsub, input_glyphs_to_retain);
@@ -123,8 +192,11 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
#ifndef HB_NO_SUBSET_LAYOUT
if (close_over_gsub)
- // Add all glyphs needed for GSUB substitutions.
- _gsub_closure (plan->source, plan->_glyphset_gsub);
+ // closure all glyphs/lookups/features needed for GSUB substitutions.
+ _gsub_closure_glyphs_lookups_features (plan->source, plan->_glyphset_gsub, plan->gsub_lookups, plan->gsub_features);
+
+ if (close_over_gpos)
+ _gpos_closure_lookups_features (plan->source, plan->_glyphset_gsub, plan->gpos_lookups, plan->gpos_features);
#endif
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
@@ -138,11 +210,15 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
if (cff.is_valid ())
_add_cff_seac_components (cff, gid, plan->_glyphset);
#endif
+ if (colr.is_valid ())
+ colr.closure_glyphs (gid, plan->_glyphset);
}
_remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
+#ifndef HB_NO_SUBSET_CFF
cff.fini ();
+#endif
glyf.fini ();
cmap.fini ();
}
@@ -213,9 +289,11 @@ hb_subset_plan_create (hb_face_t *face,
plan->drop_hints = input->drop_hints;
plan->desubroutinize = input->desubroutinize;
plan->retain_gids = input->retain_gids;
+ plan->name_legacy = input->name_legacy;
plan->unicodes = hb_set_create ();
plan->name_ids = hb_set_reference (input->name_ids);
_nameid_closure (face, plan->name_ids);
+ plan->name_languages = hb_set_reference (input->name_languages);
plan->drop_tables = hb_set_reference (input->drop_tables);
plan->source = hb_face_reference (face);
plan->dest = hb_face_builder_create ();
@@ -225,11 +303,16 @@ hb_subset_plan_create (hb_face_t *face,
plan->codepoint_to_glyph = hb_map_create ();
plan->glyph_map = hb_map_create ();
plan->reverse_glyph_map = hb_map_create ();
+ plan->gsub_lookups = hb_map_create ();
+ plan->gpos_lookups = hb_map_create ();
+ plan->gsub_features = hb_map_create ();
+ plan->gpos_features = hb_map_create ();
_populate_gids_to_retain (plan,
input->unicodes,
input->glyphs,
- !input->drop_tables->has (HB_OT_TAG_GSUB));
+ !input->drop_tables->has (HB_OT_TAG_GSUB),
+ !input->drop_tables->has (HB_OT_TAG_GPOS));
_create_old_gid_to_new_gid_map (face,
input->retain_gids,
@@ -253,6 +336,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_set_destroy (plan->unicodes);
hb_set_destroy (plan->name_ids);
+ hb_set_destroy (plan->name_languages);
hb_set_destroy (plan->drop_tables);
hb_face_destroy (plan->source);
hb_face_destroy (plan->dest);
@@ -261,6 +345,11 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_map_destroy (plan->reverse_glyph_map);
hb_set_destroy (plan->_glyphset);
hb_set_destroy (plan->_glyphset_gsub);
+ hb_map_destroy (plan->gsub_lookups);
+ hb_map_destroy (plan->gpos_lookups);
+ hb_map_destroy (plan->gsub_features);
+ hb_map_destroy (plan->gpos_features);
+
free (plan);
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
index af2337e4948..1e247968336 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
@@ -42,6 +42,7 @@ struct hb_subset_plan_t
bool drop_hints : 1;
bool desubroutinize : 1;
bool retain_gids : 1;
+ bool name_legacy : 1;
// For each cp that we'd like to retain maps to the corresponding gid.
hb_set_t *unicodes;
@@ -49,6 +50,9 @@ struct hb_subset_plan_t
// name_ids we would like to retain
hb_set_t *name_ids;
+ // name_languages we would like to retain
+ hb_set_t *name_languages;
+
// Tables which should be dropped.
hb_set_t *drop_tables;
@@ -67,6 +71,14 @@ struct hb_subset_plan_t
hb_set_t *_glyphset;
hb_set_t *_glyphset_gsub;
+ //active lookups we'd like to retain
+ hb_map_t *gsub_lookups;
+ hb_map_t *gpos_lookups;
+
+ //active features we'd like to retain
+ hb_map_t *gsub_features;
+ hb_map_t *gpos_features;
+
public:
/*
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
index ec2f8892fde..a03b41f140c 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
@@ -37,35 +37,36 @@
#include "hb-ot-hhea-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-maxp-table.hh"
+#include "hb-ot-color-sbix-table.hh"
+#include "hb-ot-color-colr-table.hh"
#include "hb-ot-os2-table.hh"
#include "hb-ot-post-table.hh"
#include "hb-ot-cff1-table.hh"
#include "hb-ot-cff2-table.hh"
#include "hb-ot-vorg-table.hh"
#include "hb-ot-name-table.hh"
+#include "hb-ot-color-cbdt-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-var-gvar-table.hh"
+#include "hb-ot-var-hvar-table.hh"
-HB_UNUSED static inline unsigned int
-_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
- unsigned int table_len);
-static inline unsigned int
-_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
- unsigned int table_len)
+static unsigned
+_plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len)
{
- unsigned int src_glyphs = plan->source->get_num_glyphs ();
- unsigned int dst_glyphs = plan->glyphset ()->get_population ();
+ unsigned src_glyphs = plan->source->get_num_glyphs ();
+ unsigned dst_glyphs = plan->glyphset ()->get_population ();
if (unlikely (!src_glyphs))
return 512 + table_len;
- return 512 + (unsigned int) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
+ return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
}
template<typename TableType>
static bool
-_subset2 (hb_subset_plan_t *plan)
+_subset (hb_subset_plan_t *plan)
{
bool result = false;
hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
@@ -77,26 +78,26 @@ _subset2 (hb_subset_plan_t *plan)
hb_vector_t<char> buf;
/* TODO Not all tables are glyph-related. 'name' table size for example should not be
* affected by number of glyphs. Accommodate that. */
- unsigned int buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
+ unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
+ DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
{
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
+ DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
hb_blob_destroy (source_blob);
return false;
}
retry:
hb_serialize_context_t serializer ((void *) buf, buf_size);
serializer.start_serialize<TableType> ();
- hb_subset_context_t c (plan, &serializer);
+ hb_subset_context_t c (source_blob, plan, &serializer);
bool needed = table->subset (&c);
if (serializer.ran_out_of_room)
{
buf_size += (buf_size >> 1) + 32;
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
+ DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
{
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
+ DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
hb_blob_destroy (source_blob);
return false;
}
@@ -111,159 +112,119 @@ _subset2 (hb_subset_plan_t *plan)
if (needed)
{
hb_blob_t *dest_blob = serializer.copy_blob ();
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
+ DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
result = c.plan->add_table (tag, dest_blob);
hb_blob_destroy (dest_blob);
}
else
{
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
+ DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
}
}
}
else
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
+ DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
hb_blob_destroy (source_blob);
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
+ DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
return result;
}
-template<typename TableType>
static bool
-_subset (hb_subset_plan_t *plan)
+_is_table_present (hb_face_t *source, hb_tag_t tag)
{
- hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
- const TableType *table = source_blob->as<TableType> ();
-
- hb_tag_t tag = TableType::tableTag;
- hb_bool_t result = false;
- if (source_blob->data)
- result = table->subset (plan);
- else
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
-
- hb_blob_destroy (source_blob);
- DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
- return result;
+ hb_tag_t table_tags[32];
+ unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
+ while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
+ {
+ for (unsigned i = 0; i < num_tables; ++i)
+ if (table_tags[i] == tag)
+ return true;
+ offset += num_tables;
+ }
+ return false;
}
-
static bool
-_subset_table (hb_subset_plan_t *plan,
- hb_tag_t tag)
+_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
{
- DEBUG_MSG(SUBSET, nullptr, "begin subset %c%c%c%c", HB_UNTAG (tag));
- bool result = true;
- switch (tag) {
- case HB_OT_TAG_glyf:
- result = _subset2<const OT::glyf> (plan);
- break;
- case HB_OT_TAG_hdmx:
- result = _subset2<const OT::hdmx> (plan);
- break;
- case HB_OT_TAG_name:
- result = _subset2<const OT::name> (plan);
- break;
- case HB_OT_TAG_head:
- // TODO that won't work well if there is no glyf
- DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
- result = true;
- break;
- case HB_OT_TAG_hhea:
- DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
- return true;
- case HB_OT_TAG_hmtx:
- result = _subset2<const OT::hmtx> (plan);
- break;
- case HB_OT_TAG_vhea:
- DEBUG_MSG(SUBSET, nullptr, "skip vhea handled by vmtx");
- return true;
- case HB_OT_TAG_vmtx:
- result = _subset2<const OT::vmtx> (plan);
- break;
- case HB_OT_TAG_maxp:
- result = _subset2<const OT::maxp> (plan);
- break;
- case HB_OT_TAG_loca:
- DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf");
- return true;
- case HB_OT_TAG_cmap:
- result = _subset2<const OT::cmap> (plan);
- break;
- case HB_OT_TAG_OS2:
- result = _subset2<const OT::OS2> (plan);
- break;
- case HB_OT_TAG_post:
- result = _subset2<const OT::post> (plan);
- break;
+ if (plan->drop_tables->has (tag))
+ return true;
-#ifndef HB_NO_SUBSET_CFF
- case HB_OT_TAG_cff1:
- result = _subset<const OT::cff1> (plan);
- break;
- case HB_OT_TAG_cff2:
- result = _subset<const OT::cff2> (plan);
- break;
- case HB_OT_TAG_VORG:
- result = _subset2<const OT::VORG> (plan);
- break;
-#endif
+ switch (tag)
+ {
+ case HB_TAG ('c','v','a','r'): /* hint table, fallthrough */
+ case HB_TAG ('c','v','t',' '): /* hint table, fallthrough */
+ case HB_TAG ('f','p','g','m'): /* hint table, fallthrough */
+ case HB_TAG ('p','r','e','p'): /* hint table, fallthrough */
+ case HB_TAG ('h','d','m','x'): /* hint table, fallthrough */
+ case HB_TAG ('V','D','M','X'): /* hint table, fallthrough */
+ return plan->drop_hints;
-#ifndef HB_NO_SUBSET_LAYOUT
- case HB_OT_TAG_GDEF:
- result = _subset2<const OT::GDEF> (plan);
- break;
- case HB_OT_TAG_GSUB:
- result = _subset2<const OT::GSUB> (plan);
- break;
- case HB_OT_TAG_GPOS:
- result = _subset2<const OT::GPOS> (plan);
- break;
+#ifdef HB_NO_SUBSET_LAYOUT
+ // Drop Layout Tables if requested.
+ case HB_OT_TAG_GDEF:
+ case HB_OT_TAG_GPOS:
+ case HB_OT_TAG_GSUB:
+ case HB_TAG ('m','o','r','x'):
+ case HB_TAG ('m','o','r','t'):
+ case HB_TAG ('k','e','r','x'):
+ case HB_TAG ('k','e','r','n'):
+ return true;
#endif
- default:
- hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
- if (likely (source_table))
- result = plan->add_table (tag, source_table);
- else
- result = false;
- hb_blob_destroy (source_table);
- break;
+ default:
+ return false;
}
- DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG (tag), result ? "ok" : "FAILED");
- return result;
}
static bool
-_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
+_subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
{
- if (plan->drop_tables->has (tag))
- return true;
+ DEBUG_MSG (SUBSET, nullptr, "subset %c%c%c%c", HB_UNTAG (tag));
+ switch (tag)
+ {
+ case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan);
+ case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan);
+ case HB_OT_TAG_name: return _subset<const OT::name> (plan);
+ case HB_OT_TAG_head:
+ if (_is_table_present (plan->source, HB_OT_TAG_glyf) && !_should_drop_table (plan, HB_OT_TAG_glyf))
+ return true; /* skip head, handled by glyf */
+ return _subset<const OT::head> (plan);
+ case HB_OT_TAG_hhea: return true; /* skip hhea, handled by hmtx */
+ case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan);
+ case HB_OT_TAG_vhea: return true; /* skip vhea, handled by vmtx */
+ case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan);
+ case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan);
+ case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan);
+ case HB_OT_TAG_loca: return true; /* skip loca, handled by glyf */
+ case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan);
+ case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan);
+ case HB_OT_TAG_post: return _subset<const OT::post> (plan);
+ case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan);
+ case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan);
+ case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
- switch (tag) {
- case HB_TAG ('c', 'v', 'a', 'r'): /* hint table, fallthrough */
- case HB_TAG ('c', 'v', 't', ' '): /* hint table, fallthrough */
- case HB_TAG ('f', 'p', 'g', 'm'): /* hint table, fallthrough */
- case HB_TAG ('p', 'r', 'e', 'p'): /* hint table, fallthrough */
- case HB_TAG ('h', 'd', 'm', 'x'): /* hint table, fallthrough */
- case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */
- return plan->drop_hints;
+#ifndef HB_NO_SUBSET_CFF
+ case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan);
+ case HB_OT_TAG_cff2: return _subset<const OT::cff2> (plan);
+ case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan);
+#endif
-#ifdef HB_NO_SUBSET_LAYOUT
- // Drop Layout Tables if requested.
- case HB_OT_TAG_GDEF:
- case HB_OT_TAG_GPOS:
- case HB_OT_TAG_GSUB:
- case HB_TAG ('m', 'o', 'r', 'x'):
- case HB_TAG ('m', 'o', 'r', 't'):
- case HB_TAG ('k', 'e', 'r', 'x'):
- case HB_TAG ('k', 'e', 'r', 'n'):
- return true;
+#ifndef HB_NO_SUBSET_LAYOUT
+ case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan);
+ case HB_OT_TAG_GSUB: return _subset<const OT::GSUB> (plan);
+ case HB_OT_TAG_GPOS: return _subset<const OT::GPOS> (plan);
+ case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan);
+ case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan);
+ case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan);
#endif
- default:
- return false;
+ default:
+ hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
+ bool result = plan->add_table (tag, source_table);
+ hb_blob_destroy (source_table);
+ return result;
}
}
@@ -275,33 +236,29 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
* Subsets a font according to provided input.
**/
hb_face_t *
-hb_subset (hb_face_t *source,
- hb_subset_input_t *input)
+hb_subset (hb_face_t *source, hb_subset_input_t *input)
{
if (unlikely (!input || !source)) return hb_face_get_empty ();
hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
- hb_tag_t table_tags[32];
- unsigned int offset = 0, count;
- bool success = true;
hb_set_t tags_set;
- do {
- count = ARRAY_LENGTH (table_tags);
- hb_face_get_table_tags (source, offset, &count, table_tags);
- for (unsigned int i = 0; i < count; i++)
+ bool success = true;
+ hb_tag_t table_tags[32];
+ unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
+ while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
+ {
+ for (unsigned i = 0; i < num_tables; ++i)
{
hb_tag_t tag = table_tags[i];
- if (_should_drop_table (plan, tag) && !tags_set.has (tag))
- {
- DEBUG_MSG(SUBSET, nullptr, "drop %c%c%c%c", HB_UNTAG (tag));
- continue;
- }
+ if (_should_drop_table (plan, tag) && !tags_set.has (tag)) continue;
tags_set.add (tag);
- success = success && _subset_table (plan, tag);
+ success = _subset_table (plan, tag);
+ if (unlikely (!success)) goto end;
}
- offset += count;
- } while (success && count == ARRAY_LENGTH (table_tags));
+ offset += num_tables;
+ }
+end:
hb_face_t *result = success ? hb_face_reference (plan->dest) : hb_face_get_empty ();
hb_subset_plan_destroy (plan);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h
index 960afefa5bd..ddf4409734e 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.h
@@ -58,6 +58,9 @@ HB_EXTERN hb_set_t *
hb_subset_input_nameid_set (hb_subset_input_t *subset_input);
HB_EXTERN hb_set_t *
+hb_subset_input_namelangid_set (hb_subset_input_t *subset_input);
+
+HB_EXTERN hb_set_t *
hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input);
HB_EXTERN void
@@ -78,6 +81,12 @@ hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
HB_EXTERN hb_bool_t
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input);
+HB_EXTERN void
+hb_subset_input_set_name_legacy (hb_subset_input_t *subset_input,
+ hb_bool_t name_legacy);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_name_legacy (hb_subset_input_t *subset_input);
+
/* hb_subset () */
HB_EXTERN hb_face_t *
hb_subset (hb_face_t *source, hb_subset_input_t *input);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh
index b8dd07ab288..a3dfd3b87fe 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh
@@ -54,12 +54,15 @@ struct hb_subset_context_t :
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
+ hb_blob_t *source_blob;
hb_subset_plan_t *plan;
hb_serialize_context_t *serializer;
unsigned int debug_depth;
- hb_subset_context_t (hb_subset_plan_t *plan_,
+ hb_subset_context_t (hb_blob_t *source_blob_,
+ hb_subset_plan_t *plan_,
hb_serialize_context_t *serializer_) :
+ source_blob (source_blob_),
plan (plan_),
serializer (serializer_),
debug_depth (0) {}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ucd.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ucd.cc
index b29f2a9c7d1..ad72a26c04c 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ucd.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ucd.cc
@@ -136,20 +136,22 @@ hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
if ((a & 0xFFFFF800u) == 0x0000u && (b & 0xFFFFFF80) == 0x0300u)
{
uint32_t k = HB_CODEPOINT_ENCODE3_11_7_14 (a, b, 0);
- uint32_t *v = (uint32_t*) hb_bsearch (&k, _hb_ucd_dm2_u32_map,
- ARRAY_LENGTH (_hb_ucd_dm2_u32_map),
- sizeof (*_hb_ucd_dm2_u32_map),
- _cmp_pair_11_7_14);
+ const uint32_t *v = hb_bsearch (k,
+ _hb_ucd_dm2_u32_map,
+ ARRAY_LENGTH (_hb_ucd_dm2_u32_map),
+ sizeof (*_hb_ucd_dm2_u32_map),
+ _cmp_pair_11_7_14);
if (likely (!v)) return false;
u = HB_CODEPOINT_DECODE3_11_7_14_3 (*v);
}
else
{
uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0);
- uint64_t *v = (uint64_t*) hb_bsearch (&k, _hb_ucd_dm2_u64_map,
- ARRAY_LENGTH (_hb_ucd_dm2_u64_map),
- sizeof (*_hb_ucd_dm2_u64_map),
- _cmp_pair);
+ const uint64_t *v = hb_bsearch (k,
+ _hb_ucd_dm2_u64_map,
+ ARRAY_LENGTH (_hb_ucd_dm2_u64_map),
+ sizeof (*_hb_ucd_dm2_u64_map),
+ _cmp_pair);
if (likely (!v)) return false;
u = HB_CODEPOINT_DECODE3_3 (*v);
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode-emoji-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode-emoji-table.hh
index 1ff79c97785..c56a4f3339f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode-emoji-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode-emoji-table.hh
@@ -10,12 +10,12 @@
* # Date: 2019-01-15, 12:10:05 GMT
* # © 2019 Unicode®, Inc.
* # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
- * # For terms of use, see http://www.unicode.org/terms_of_use.html
+ * # For terms of use, see https://www.unicode.org/terms_of_use.html
* #
* # Emoji Data for UTS #51
* # Version: 12.0
* #
- * # For documentation and usage, see http://www.unicode.org/reports/tr51
+ * # For documentation and usage, see https://www.unicode.org/reports/tr51
*/
#ifndef HB_UNICODE_EMOJI_TABLE_HH
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 08a4054cd0c..36070a7f182 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc
@@ -212,7 +212,7 @@ DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) =
hb_unicode_funcs_t *
hb_unicode_funcs_get_empty ()
{
- return const_cast<hb_unicode_funcs_t *> (&Null(hb_unicode_funcs_t));
+ return const_cast<hb_unicode_funcs_t *> (&Null (hb_unicode_funcs_t));
}
/**
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh
index 0c355f1113b..34d66d7aa3c 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh
@@ -324,10 +324,10 @@ DECLARE_NULL_INSTANCE (hb_unicode_funcs_t);
* Modify Telugu length marks (ccc=84, ccc=91).
* These are the only matras in the main Indic scripts range that have
* a non-zero ccc. That makes them reorder with the Halant (ccc=9).
- * Assign 5 and 6, which are otherwise unassigned.
+ * Assign 4 and 5, which are otherwise unassigned.
*/
-#define HB_MODIFIED_COMBINING_CLASS_CCC84 5 /* length mark */
-#define HB_MODIFIED_COMBINING_CLASS_CCC91 6 /* ai length mark */
+#define HB_MODIFIED_COMBINING_CLASS_CCC84 4 /* length mark */
+#define HB_MODIFIED_COMBINING_CLASS_CCC91 5 /* ai length mark */
/* Thai
*
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc
index e93cf7f419a..48a5dc50adf 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc
@@ -55,7 +55,7 @@
* @short_description: Windows integration
* @include: hb-uniscribe.h
*
- * Functions for using HarfBuzz with the Windows fonts.
+ * Functions for using HarfBuzz with Windows fonts.
**/
typedef HRESULT (WINAPI *SIOT) /*ScriptItemizeOpenType*/(
@@ -453,7 +453,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
hb_blob_destroy (blob);
return hb_blob_create ((const char *) new_sfnt_data, new_length,
- HB_MEMORY_MODE_WRITABLE, nullptr, free);
+ HB_MEMORY_MODE_WRITABLE, new_sfnt_data, free);
}
hb_uniscribe_face_data_t *
@@ -583,6 +583,16 @@ _hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_font_data_t *data)
free (data);
}
+/**
+ * hb_uniscribe_font_get_logfontw:
+ * @font: The #hb_font_t to work upon
+ *
+ * Fetches the LOGFONTW structure that corresponds to the
+ * specified #hb_font_t font.
+ *
+ * Return value: a pointer to the LOGFONTW retrieved
+ *
+ **/
LOGFONTW *
hb_uniscribe_font_get_logfontw (hb_font_t *font)
{
@@ -590,6 +600,16 @@ hb_uniscribe_font_get_logfontw (hb_font_t *font)
return data ? &data->log_font : nullptr;
}
+/**
+ * hb_uniscribe_font_get_hfont:
+ * @font: The #hb_font_t to work upon
+ *
+ * Fetches the HFONT handle that corresponds to the
+ * specified #hb_font_t font.
+ *
+ * Return value: the HFONT retreieved
+ *
+ **/
HFONT
hb_uniscribe_font_get_hfont (hb_font_t *font)
{
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 7b150fba054..d979169de30 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
@@ -117,7 +117,7 @@ struct hb_vector_t
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= length))
- return Null(Type);
+ return Null (Type);
return arrayZ[i];
}
@@ -165,7 +165,7 @@ struct hb_vector_t
Type *push ()
{
if (unlikely (!resize (length + 1)))
- return &Crap(Type);
+ return &Crap (Type);
return &arrayZ[length - 1];
}
template <typename T>
@@ -228,7 +228,7 @@ struct hb_vector_t
Type pop ()
{
- if (!length) return Null(Type);
+ if (!length) return Null (Type);
return hb_move (arrayZ[--length]); /* Does this move actually work? */
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.h
index c5e7072fbac..b0cc06c9ef9 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.h
@@ -32,6 +32,7 @@
#include "hb-buffer.h"
#include "hb-common.h"
#include "hb-deprecated.h"
+#include "hb-draw.h"
#include "hb-face.h"
#include "hb-font.h"
#include "hb-map.h"
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
index fcbd330588e..3adca88ff4d 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh
@@ -176,6 +176,7 @@
#include <limits.h>
#include <math.h>
+#include <float.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
@@ -317,6 +318,18 @@ extern "C" void hb_free_impl(void *ptr);
# define HB_FALLTHROUGH /* FALLTHROUGH */
#endif
+/* A tag to enforce use of return value for a function */
+#if __cplusplus >= 201703L
+# define HB_NODISCARD [[nodiscard]]
+#elif defined(__GNUC__) || defined(__clang__)
+# define HB_NODISCARD __attribute__((warn_unused_result))
+#elif defined(_MSC_VER)
+# define HB_NODISCARD _Check_return_
+#else
+# define HB_NODISCARD
+#endif
+#define hb_success_t HB_NODISCARD bool
+
/* https://github.com/harfbuzz/harfbuzz/issues/1852 */
#if defined(__clang__) && !(defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__)))
/* Disable certain sanitizer errors. */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc
index 983cb557db7..e898e6e4b60 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/main.cc
@@ -1,5 +1,7 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2018,2019,2020 Ebrahim Byagowi
+ * Copyright © 2018 Khaled Hosny
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,48 +26,335 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#include "hb-static.cc"
-#include "hb-open-file.hh"
-#include "hb-ot-layout-gdef-table.hh"
-#include "hb-ot-layout-gsubgpos.hh"
-
-#ifdef HAVE_GLIB
-#include <glib.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
#endif
-#include <stdlib.h>
-#include <stdio.h>
+#include "hb.h"
+#include "hb-ot.h"
-using namespace OT;
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
#ifdef HB_NO_OPEN
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
#endif
-int
-main (int argc, char **argv)
+#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API)
+static void
+svg_dump (hb_face_t *face, unsigned face_index)
{
- if (argc != 2)
+ unsigned glyph_count = hb_face_get_glyph_count (face);
+
+ for (unsigned glyph_id = 0; glyph_id < glyph_count; ++glyph_id)
{
- fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
- exit (1);
+ hb_blob_t *blob = hb_ot_color_glyph_reference_svg (face, glyph_id);
+
+ if (hb_blob_get_length (blob) == 0) continue;
+
+ unsigned length;
+ const char *data = hb_blob_get_data (blob, &length);
+
+ char output_path[255];
+ sprintf (output_path, "out/svg-%u-%u.svg%s",
+ glyph_id,
+ face_index,
+ // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405
+ (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : "");
+
+ FILE *f = fopen (output_path, "wb");
+ fwrite (data, 1, length, f);
+ fclose (f);
+
+ hb_blob_destroy (blob);
}
+}
- hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
- unsigned int len;
- const char *font_data = hb_blob_get_data (blob, &len);
- printf ("Opened font file %s: %d bytes long\n", argv[1], len);
+/* _png API is so easy to use unlike the below code, don't get confused */
+static void
+png_dump (hb_face_t *face, unsigned face_index)
+{
+ unsigned glyph_count = hb_face_get_glyph_count (face);
+ hb_font_t *font = hb_font_create (face);
+
+ /* scans the font for strikes */
+ unsigned sample_glyph_id;
+ /* we don't care about different strikes for different glyphs at this point */
+ for (sample_glyph_id = 0; sample_glyph_id < glyph_count; ++sample_glyph_id)
+ {
+ hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id);
+ unsigned blob_length = hb_blob_get_length (blob);
+ hb_blob_destroy (blob);
+ if (blob_length != 0)
+ break;
+ }
+
+ unsigned upem = hb_face_get_upem (face);
+ unsigned blob_length = 0;
+ unsigned strike = 0;
+ for (unsigned ppem = 1; ppem < upem; ++ppem)
+ {
+ hb_font_set_ppem (font, ppem, ppem);
+ hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id);
+ unsigned new_blob_length = hb_blob_get_length (blob);
+ hb_blob_destroy (blob);
+ if (new_blob_length != blob_length)
+ {
+ for (unsigned glyph_id = 0; glyph_id < glyph_count; ++glyph_id)
+ {
+ hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, glyph_id);
+
+ if (hb_blob_get_length (blob) == 0) continue;
+
+ unsigned length;
+ const char *data = hb_blob_get_data (blob, &length);
+
+ char output_path[255];
+ sprintf (output_path, "out/png-%u-%u-%u.png", glyph_id, strike, face_index);
+
+ FILE *f = fopen (output_path, "wb");
+ fwrite (data, 1, length, f);
+ fclose (f);
+
+ hb_blob_destroy (blob);
+ }
+
+ strike++;
+ blob_length = new_blob_length;
+ }
+ }
+
+ hb_font_destroy (font);
+}
+
+struct user_data_t
+{
+ FILE *f;
+ hb_position_t ascender;
+};
+
+static void
+move_to (hb_position_t to_x, hb_position_t to_y, user_data_t &user_data)
+{
+ fprintf (user_data.f, "M%d,%d", to_x, user_data.ascender - to_y);
+}
+
+static void
+line_to (hb_position_t to_x, hb_position_t to_y, user_data_t &user_data)
+{
+ fprintf (user_data.f, "L%d,%d", to_x, user_data.ascender - to_y);
+}
+
+static void
+quadratic_to (hb_position_t control_x, hb_position_t control_y,
+ hb_position_t to_x, hb_position_t to_y,
+ user_data_t &user_data)
+{
+ fprintf (user_data.f, "Q%d,%d %d,%d", control_x, user_data.ascender - control_y,
+ to_x, user_data.ascender - to_y);
+}
+
+static void
+cubic_to (hb_position_t control1_x, hb_position_t control1_y,
+ hb_position_t control2_x, hb_position_t control2_y,
+ hb_position_t to_x, hb_position_t to_y,
+ user_data_t &user_data)
+{
+ fprintf (user_data.f, "C%d,%d %d,%d %d,%d", control1_x, user_data.ascender - control1_y,
+ control2_x, user_data.ascender - control2_y,
+ to_x, user_data.ascender - to_y);
+}
+
+static void
+close_path (user_data_t &user_data)
+{
+ fprintf (user_data.f, "Z");
+}
+
+static void
+layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index)
+{
+ hb_face_t *face = hb_font_get_face (font);
+ unsigned palette_count = hb_ot_color_palette_get_count (face);
+ for (unsigned palette = 0; palette < palette_count; ++palette)
+ {
+ unsigned num_colors = hb_ot_color_palette_get_colors (face, palette, 0, nullptr, nullptr);
+ if (!num_colors) continue;
+
+ hb_color_t *colors = (hb_color_t*) calloc (num_colors, sizeof (hb_color_t));
+ hb_ot_color_palette_get_colors (face, palette, 0, &num_colors, colors);
+ if (!num_colors)
+ {
+ free (colors);
+ continue;
+ }
+
+ unsigned num_glyphs = hb_face_get_glyph_count (face);
+ for (hb_codepoint_t gid = 0; gid < num_glyphs; ++gid)
+ {
+ unsigned num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, nullptr, nullptr);
+ if (!num_layers) continue;
- hb_blob_t *font_blob = hb_sanitize_context_t().sanitize_blob<OpenTypeFontFile> (blob);
+ hb_ot_color_layer_t *layers = (hb_ot_color_layer_t*) malloc (num_layers * sizeof (hb_ot_color_layer_t));
+
+ hb_ot_color_glyph_get_layers (face, gid, 0, &num_layers, layers);
+ if (num_layers)
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ hb_glyph_extents_t extents = {0};
+ if (!hb_font_get_glyph_extents (font, gid, &extents))
+ {
+ printf ("Skip gid: %d\n", gid);
+ continue;
+ }
+
+ char output_path[255];
+ sprintf (output_path, "out/colr-%u-%u-%u.svg", gid, palette, face_index);
+ FILE *f = fopen (output_path, "wb");
+ fprintf (f, "<svg xmlns=\"http://www.w3.org/2000/svg\""
+ " viewBox=\"%d %d %d %d\">\n",
+ extents.x_bearing, 0,
+ extents.x_bearing + extents.width, -extents.height);
+ user_data_t user_data;
+ user_data.ascender = extents.y_bearing;
+ user_data.f = f;
+
+ for (unsigned layer = 0; layer < num_layers; ++layer)
+ {
+ hb_color_t color = 0x000000FF;
+ if (layers[layer].color_index != 0xFFFF)
+ color = colors[layers[layer].color_index];
+ fprintf (f, "<path fill=\"#%02X%02X%02X\" ",
+ hb_color_get_red (color), hb_color_get_green (color), hb_color_get_green (color));
+ if (hb_color_get_alpha (color) != 255)
+ fprintf (f, "fill-opacity=\"%.3f\"", (double) hb_color_get_alpha (color) / 255.);
+ fprintf (f, "d=\"");
+ if (!hb_font_draw_glyph (font, layers[layer].glyph, funcs, &user_data))
+ printf ("Failed to decompose layer %d while %d\n", layers[layer].glyph, gid);
+ fprintf (f, "\"/>\n");
+ }
+
+ fprintf (f, "</svg>");
+ fclose (f);
+ }
+ free (layers);
+ }
+
+ free (colors);
+ }
+}
+
+static void
+dump_glyphs (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index)
+{
+ unsigned num_glyphs = hb_face_get_glyph_count (hb_font_get_face (font));
+ for (unsigned gid = 0; gid < num_glyphs; ++gid)
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ hb_glyph_extents_t extents = {0};
+ if (!hb_font_get_glyph_extents (font, gid, &extents))
+ {
+ printf ("Skip gid: %d\n", gid);
+ continue;
+ }
+
+ char output_path[255];
+ sprintf (output_path, "out/%u-%u.svg", face_index, gid);
+ FILE *f = fopen (output_path, "wb");
+ fprintf (f, "<svg xmlns=\"http://www.w3.org/2000/svg\""
+ " viewBox=\"%d %d %d %d\"><path d=\"",
+ extents.x_bearing, 0,
+ extents.x_bearing + extents.width, font_extents.ascender - font_extents.descender);
+ user_data_t user_data;
+ user_data.ascender = font_extents.ascender;
+ user_data.f = f;
+ if (!hb_font_draw_glyph (font, gid, funcs, &user_data))
+ printf ("Failed to decompose gid: %d\n", gid);
+ fprintf (f, "\"/></svg>");
+ fclose (f);
+ }
+}
+
+static void
+dump_glyphs (hb_blob_t *blob, const char *font_name)
+{
+ FILE *font_name_file = fopen ("out/.dumped_font_name", "r");
+ if (font_name_file)
+ {
+ fprintf (stderr, "Purge or rename ./out folder if you like to run a glyph dump,\n"
+ "run it like `rm -rf out && mkdir out && src/main font-file.ttf`\n");
+ return;
+ }
+
+ font_name_file = fopen ("out/.dumped_font_name", "w");
+ if (!font_name_file)
+ {
+ fprintf (stderr, "./out is not accessible as a folder, create it please\n");
+ return;
+ }
+ fwrite (font_name, 1, strlen (font_name), font_name_file);
+ fclose (font_name_file);
+
+ hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
+ hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to);
+ hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to);
+ hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to);
+ hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to);
+ hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path);
+
+ unsigned num_faces = hb_face_count (blob);
+ for (unsigned face_index = 0; face_index < num_faces; ++face_index)
+ {
+ hb_face_t *face = hb_face_create (blob, face_index);
+ hb_font_t *font = hb_font_create (face);
+
+ if (hb_ot_color_has_png (face))
+ printf ("Dumping png (CBDT/sbix)...\n");
+ png_dump (face, face_index);
+
+ if (hb_ot_color_has_svg (face))
+ printf ("Dumping svg (SVG )...\n");
+ svg_dump (face, face_index);
+
+ if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face))
+ printf ("Dumping layered color glyphs (COLR/CPAL)...\n");
+ layered_glyph_dump (font, funcs, face_index);
+
+ dump_glyphs (font, funcs, face_index);
+
+ hb_font_destroy (font);
+ hb_face_destroy (face);
+ }
+
+ hb_draw_funcs_destroy (funcs);
+}
+#endif
+
+#ifndef MAIN_CC_NO_PRIVATE_API
+/* Only this part of this mini app uses private API */
+#include "hb-static.cc"
+#include "hb-open-file.hh"
+#include "hb-ot-layout-gdef-table.hh"
+#include "hb-ot-layout-gsubgpos.hh"
+
+using namespace OT;
+
+static void
+print_layout_info_using_private_api (hb_blob_t *blob)
+{
+ const char *font_data = hb_blob_get_data (blob, nullptr);
+ hb_blob_t *font_blob = hb_sanitize_context_t ().sanitize_blob<OpenTypeFontFile> (blob);
const OpenTypeFontFile* sanitized = font_blob->as<OpenTypeFontFile> ();
if (!font_blob->data)
{
printf ("Sanitization of the file wasn't successful. Exit");
- return 1;
+ exit (1);
}
const OpenTypeFontFile& ot = *sanitized;
-
switch (ot.get_tag ())
{
case OpenTypeFontFile::TrueTypeTag:
@@ -91,22 +380,22 @@ main (int argc, char **argv)
break;
}
- 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++)
+ unsigned num_faces = hb_face_count (blob);
+ printf ("%d font(s) found in file\n", num_faces);
+ for (unsigned n_font = 0; n_font < num_faces; ++n_font)
{
const OpenTypeFontFace &font = ot.get_face (n_font);
- printf ("Font %d of %d:\n", n_font, num_fonts);
+ printf ("Font %d of %d:\n", n_font, num_faces);
- int num_tables = font.get_table_count ();
+ unsigned 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 (unsigned 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);
+ (unsigned) table.offset,
+ (unsigned) table.length);
switch (table.tag)
{
@@ -115,21 +404,22 @@ main (int argc, char **argv)
case HB_OT_TAG_GPOS:
{
- const GSUBGPOS &g = *CastP<GSUBGPOS> (font_data + table.offset);
+ const GSUBGPOS &g = *reinterpret_cast<const GSUBGPOS *> (font_data + table.offset);
- int num_scripts = g.get_script_count ();
+ unsigned 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 (unsigned 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())
+ if (!script.has_default_lang_sys ())
printf (" No default language system\n");
int num_langsys = script.get_lang_sys_count ();
printf (" %d language system(s) found in script\n", num_langsys);
- for (int n_langsys = script.has_default_lang_sys() ? -1 : 0; n_langsys < num_langsys; n_langsys++) {
+ for (int n_langsys = script.has_default_lang_sys () ? -1 : 0; n_langsys < num_langsys; ++n_langsys)
+ {
const LangSys &langsys = n_langsys == -1
? script.get_default_lang_sys ()
: script.get_lang_sys (n_langsys);
@@ -137,16 +427,16 @@ main (int argc, char **argv)
printf (" Default Language System\n");
else
printf (" Language System %2d of %2d: %.4s\n", n_langsys, num_langsys,
- (const char *)script.get_lang_sys_tag (n_langsys));
+ (const char *) script.get_lang_sys_tag (n_langsys));
if (!langsys.has_required_feature ())
printf (" No required feature\n");
else
printf (" Required feature index: %d\n",
langsys.get_required_feature_index ());
- int num_features = langsys.get_feature_count ();
+ unsigned 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 (unsigned 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));
@@ -154,29 +444,29 @@ main (int argc, char **argv)
}
}
- int num_features = g.get_feature_count ();
+ unsigned 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 (unsigned n_feature = 0; n_feature < num_features; ++n_feature)
{
const Feature &feature = g.get_feature (n_feature);
- int num_lookups = feature.get_lookup_count ();
+ unsigned 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++) {
+ for (unsigned 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));
}
}
- int num_lookups = g.get_lookup_count ();
+ unsigned 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 (unsigned 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 ());
}
}
@@ -185,7 +475,7 @@ main (int argc, char **argv)
case GDEF::tableTag:
{
- const GDEF &gdef = *CastP<GDEF> (font_data + table.offset);
+ const GDEF &gdef = *reinterpret_cast<const GDEF *> (font_data + table.offset);
printf (" Has %sglyph classes\n",
gdef.has_glyph_classes () ? "" : "no ");
@@ -202,6 +492,28 @@ main (int argc, char **argv)
}
}
}
+}
+/* end of private API use */
+#endif
+
+int
+main (int argc, char **argv)
+{
+ if (argc != 2)
+ {
+ fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
+ exit (1);
+ }
+
+ hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
+ printf ("Opened font file %s: %d bytes long\n", argv[1], hb_blob_get_length (blob));
+#ifndef MAIN_CC_NO_PRIVATE_API
+ print_layout_info_using_private_api (blob);
+#endif
+#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API)
+ dump_glyphs (blob, argv[1]);
+#endif
+ hb_blob_destroy (blob);
return 0;
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build b/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
new file mode 100644
index 00000000000..5193269b67f
--- /dev/null
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/meson.build
@@ -0,0 +1,669 @@
+# Base and default-included sources and headers
+hb_base_sources = [
+ 'hb-aat-fdsc-table.hh',
+ 'hb-aat-layout-ankr-table.hh',
+ 'hb-aat-layout-bsln-table.hh',
+ 'hb-aat-layout-common.hh',
+ 'hb-aat-layout-feat-table.hh',
+ 'hb-aat-layout-just-table.hh',
+ 'hb-aat-layout-kerx-table.hh',
+ 'hb-aat-layout-lcar-table.hh',
+ 'hb-aat-layout-morx-table.hh',
+ 'hb-aat-layout-opbd-table.hh',
+ 'hb-aat-layout-trak-table.hh',
+ 'hb-aat-layout.cc',
+ 'hb-aat-layout.hh',
+ 'hb-aat-ltag-table.hh',
+ 'hb-aat-map.cc',
+ 'hb-aat-map.hh',
+ 'hb-algs.hh',
+ 'hb-array.hh',
+ 'hb-atomic.hh',
+ 'hb-blob.cc',
+ 'hb-blob.hh',
+ 'hb-buffer-serialize.cc',
+ 'hb-buffer.cc',
+ 'hb-buffer.hh',
+ 'hb-cache.hh',
+ 'hb-cff-interp-common.hh',
+ 'hb-cff-interp-cs-common.hh',
+ 'hb-cff-interp-dict-common.hh',
+ 'hb-cff1-interp-cs.hh',
+ 'hb-cff2-interp-cs.hh',
+ 'hb-common.cc',
+ 'hb-config.hh',
+ 'hb-debug.hh',
+ 'hb-dispatch.hh',
+ 'hb-draw.cc',
+ 'hb-draw.hh',
+ 'hb-face.cc',
+ 'hb-face.hh',
+ 'hb-fallback-shape.cc',
+ 'hb-font.cc',
+ 'hb-font.hh',
+ 'hb-iter.hh',
+ 'hb-kern.hh',
+ 'hb-machinery.hh',
+ 'hb-map.cc',
+ 'hb-map.hh',
+ 'hb-bimap.hh',
+ 'hb-meta.hh',
+ 'hb-mutex.hh',
+ 'hb-null.hh',
+ 'hb-number.cc',
+ 'hb-number.hh',
+ 'hb-object.hh',
+ 'hb-open-file.hh',
+ 'hb-open-type.hh',
+ 'hb-ot-cff-common.hh',
+ 'hb-ot-cff1-table.cc',
+ 'hb-ot-cff1-table.hh',
+ 'hb-ot-cff1-std-str.hh',
+ 'hb-ot-cff2-table.cc',
+ 'hb-ot-cff2-table.hh',
+ 'hb-ot-cmap-table.hh',
+ 'hb-ot-color-cbdt-table.hh',
+ 'hb-ot-color-colr-table.hh',
+ 'hb-ot-color-cpal-table.hh',
+ 'hb-ot-color-sbix-table.hh',
+ 'hb-ot-color-svg-table.hh',
+ 'hb-ot-color.cc',
+ 'hb-ot-face.cc',
+ 'hb-ot-face.hh',
+ 'hb-ot-face-table-list.hh',
+ 'hb-ot-font.cc',
+ 'hb-ot-gasp-table.hh',
+ 'hb-ot-glyf-table.hh',
+ 'hb-ot-hdmx-table.hh',
+ 'hb-ot-head-table.hh',
+ 'hb-ot-hhea-table.hh',
+ 'hb-ot-hmtx-table.hh',
+ 'hb-ot-kern-table.hh',
+ 'hb-ot-layout-base-table.hh',
+ 'hb-ot-layout-common.hh',
+ 'hb-ot-layout-gdef-table.hh',
+ 'hb-ot-layout-gpos-table.hh',
+ 'hb-ot-layout-gsub-table.hh',
+ 'hb-ot-layout-gsubgpos.hh',
+ 'hb-ot-layout-jstf-table.hh',
+ 'hb-ot-layout.cc',
+ 'hb-ot-layout.hh',
+ 'hb-ot-map.cc',
+ 'hb-ot-map.hh',
+ 'hb-ot-math-table.hh',
+ 'hb-ot-math.cc',
+ 'hb-ot-maxp-table.hh',
+ 'hb-ot-meta-table.hh',
+ 'hb-ot-meta.cc',
+ 'hb-ot-metrics.cc',
+ 'hb-ot-metrics.hh',
+ 'hb-ot-name-language-static.hh',
+ 'hb-ot-name-language.hh',
+ 'hb-ot-name-table.hh',
+ 'hb-ot-name.cc',
+ 'hb-ot-os2-table.hh',
+ 'hb-ot-os2-unicode-ranges.hh',
+ 'hb-ot-post-macroman.hh',
+ 'hb-ot-post-table.hh',
+ 'hb-ot-shape-complex-arabic-fallback.hh',
+ 'hb-ot-shape-complex-arabic-table.hh',
+ 'hb-ot-shape-complex-arabic-win1256.hh',
+ 'hb-ot-shape-complex-arabic.cc',
+ 'hb-ot-shape-complex-arabic.hh',
+ 'hb-ot-shape-complex-default.cc',
+ 'hb-ot-shape-complex-hangul.cc',
+ 'hb-ot-shape-complex-hebrew.cc',
+ 'hb-ot-shape-complex-indic-table.cc',
+ 'hb-ot-shape-complex-indic.cc',
+ 'hb-ot-shape-complex-indic.hh',
+ 'hb-ot-shape-complex-khmer.cc',
+ 'hb-ot-shape-complex-khmer.hh',
+ 'hb-ot-shape-complex-myanmar.cc',
+ 'hb-ot-shape-complex-myanmar.hh',
+ 'hb-ot-shape-complex-thai.cc',
+ 'hb-ot-shape-complex-use-table.cc',
+ 'hb-ot-shape-complex-use.cc',
+ 'hb-ot-shape-complex-use.hh',
+ 'hb-ot-shape-complex-vowel-constraints.cc',
+ 'hb-ot-shape-complex-vowel-constraints.hh',
+ 'hb-ot-shape-complex.hh',
+ 'hb-ot-shape-fallback.cc',
+ 'hb-ot-shape-fallback.hh',
+ 'hb-ot-shape-normalize.cc',
+ 'hb-ot-shape-normalize.hh',
+ 'hb-ot-shape.cc',
+ 'hb-ot-shape.hh',
+ 'hb-ot-stat-table.hh',
+ 'hb-ot-tag-table.hh',
+ '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',
+ 'hb-ot-vorg-table.hh',
+ 'hb-pool.hh',
+ 'hb-sanitize.hh',
+ 'hb-serialize.hh',
+ 'hb-set-digest.hh',
+ 'hb-set.cc',
+ 'hb-set.hh',
+ 'hb-shape-plan.cc',
+ 'hb-shape-plan.hh',
+ 'hb-shape.cc',
+ 'hb-shaper-impl.hh',
+ 'hb-shaper-list.hh',
+ 'hb-shaper.cc',
+ 'hb-shaper.hh',
+ 'hb-static.cc',
+ 'hb-string-array.hh',
+ 'hb-ucd-table.hh',
+ 'hb-ucd.cc',
+ 'hb-unicode-emoji-table.hh',
+ 'hb-unicode.cc',
+ 'hb-unicode.hh',
+ 'hb-utf.hh',
+ 'hb-vector.hh',
+ 'hb.hh',
+]
+
+hb_base_ragel_generated_sources = [
+ 'hb-buffer-deserialize-json.hh',
+ 'hb-buffer-deserialize-text.hh',
+ 'hb-number-parser.hh',
+ 'hb-ot-shape-complex-indic-machine.hh',
+ 'hb-ot-shape-complex-khmer-machine.hh',
+ 'hb-ot-shape-complex-myanmar-machine.hh',
+ 'hb-ot-shape-complex-use-machine.hh',
+]
+hb_base_ragel_sources = [
+ 'hb-buffer-deserialize-json.rl',
+ 'hb-buffer-deserialize-text.rl',
+ 'hb-number-parser.rl',
+ 'hb-ot-shape-complex-indic-machine.rl',
+ 'hb-ot-shape-complex-khmer-machine.rl',
+ 'hb-ot-shape-complex-myanmar-machine.rl',
+ 'hb-ot-shape-complex-use-machine.rl',
+]
+
+hb_base_headers = [
+ 'hb-aat-layout.h',
+ 'hb-aat.h',
+ 'hb-blob.h',
+ 'hb-buffer.h',
+ 'hb-common.h',
+ 'hb-deprecated.h',
+ 'hb-draw.h',
+ 'hb-face.h',
+ 'hb-font.h',
+ 'hb-map.h',
+ 'hb-ot-color.h',
+ 'hb-ot-deprecated.h',
+ 'hb-ot-font.h',
+ 'hb-ot-layout.h',
+ 'hb-ot-math.h',
+ 'hb-ot-meta.h',
+ 'hb-ot-metrics.h',
+ 'hb-ot-name.h',
+ 'hb-ot-shape.h',
+ 'hb-ot-var.h',
+ 'hb-ot.h',
+ 'hb-set.h',
+ 'hb-shape-plan.h',
+ 'hb-shape.h',
+ 'hb-unicode.h',
+ 'hb-version.h',
+ 'hb.h',
+]
+
+# Optional Sources and Headers with external deps
+
+hb_ft_sources = ['hb-ft.cc']
+hb_ft_headers = ['hb-ft.h']
+
+hb_glib_sources = ['hb-glib.cc']
+hb_glib_headers = ['hb-glib.h']
+
+hb_graphite2_sources = ['hb-graphite2.cc']
+hb_graphite2_headers = ['hb-graphite2.h']
+
+# System-dependent sources and headers
+
+hb_coretext_sources = ['hb-coretext.cc']
+hb_coretext_headers = ['hb-coretext.h']
+
+hb_directwrite_sources = ['hb-directwrite.cc']
+hb_directwrite_headers = ['hb-directwrite.h']
+
+hb_gdi_sources = ['hb-gdi.cc']
+hb_gdi_headers = ['hb-gdi.h']
+
+hb_uniscribe_sources = ['hb-uniscribe.cc']
+hb_uniscribe_headers = ['hb-uniscribe.h']
+
+# Sources for libharfbuzz-gobject and libharfbuzz-icu
+hb_icu_sources = ['hb-icu.cc']
+hb_icu_headers = ['hb-icu.h']
+
+# Sources for libharfbuzz-subset
+hb_subset_sources = [
+ 'hb-number.cc',
+ 'hb-number.hh',
+ 'hb-ot-cff1-table.cc',
+ 'hb-ot-cff2-table.cc',
+ 'hb-static.cc',
+ 'hb-subset-cff-common.cc',
+ 'hb-subset-cff-common.hh',
+ 'hb-subset-cff1.cc',
+ 'hb-subset-cff1.hh',
+ 'hb-subset-cff2.cc',
+ 'hb-subset-cff2.hh',
+ 'hb-subset-input.cc',
+ 'hb-subset-input.hh',
+ 'hb-subset-plan.cc',
+ 'hb-subset-plan.hh',
+ 'hb-subset-plan.hh',
+ 'hb-subset.cc',
+ 'hb-subset.hh',
+ 'hb-subset.hh',
+]
+
+hb_subset_headers = ['hb-subset.h']
+
+hb_gobject_sources = [
+ 'hb-gobject-structs.cc'
+]
+
+hb_gobject_headers = [
+ 'hb-gobject.h',
+ 'hb-gobject-structs.h',
+]
+
+incsrc = include_directories('.')
+
+hb_sources = hb_base_sources + hb_base_ragel_generated_sources
+hb_headers = hb_base_headers
+
+if conf.get('HAVE_FREETYPE', 0) == 1
+ hb_sources += hb_ft_sources
+ hb_headers += hb_ft_headers
+endif
+
+if conf.get('HAVE_GDI', 0) == 1
+ hb_sources += hb_gdi_sources
+ hb_headers += hb_gdi_headers
+endif
+
+if conf.get('HAVE_GRAPHITE2', 0) == 1
+ hb_sources += hb_graphite2_sources
+ hb_headers += hb_graphite2_headers
+endif
+
+if conf.get('HAVE_GLIB', 0) == 1
+ hb_sources += hb_glib_sources
+ hb_headers += hb_glib_headers
+endif
+
+if conf.get('HAVE_UNISCRIBE', 0) == 1
+ hb_sources += hb_uniscribe_sources
+ hb_headers += hb_uniscribe_headers
+endif
+
+if conf.get('HAVE_DIRECTWRITE', 0) == 1
+ hb_sources += hb_directwrite_sources
+ hb_headers += hb_directwrite_headers
+endif
+
+if conf.get('HAVE_CORETEXT', 0) == 1
+ hb_sources += hb_coretext_sources
+ hb_headers += hb_coretext_headers
+endif
+
+if get_option('amalgam')
+ # replace the array if is amalgam build
+ hb_sources = ['harfbuzz.cc']
+endif
+
+have_icu = conf.get('HAVE_ICU', 0) == 1
+have_icu_builtin = conf.get('HAVE_ICU_BUILTIN', 0) == 1
+
+if have_icu and have_icu_builtin
+ hb_sources += hb_icu_sources
+ hb_headers += hb_icu_headers
+ deps += [icu_dep]
+endif
+
+if host_machine.system() == 'windows' or get_option('with-libstdcxx')
+ chosen_linker = 'cpp'
+else
+ # our autotools port was limiting this to HAVE_GCC as https://github.com/harfbuzz/harfbuzz/commit/e784632
+ # let's see if that is needed anymore
+
+ # Use a C linker, not C++; Don't link to libstdc++
+ chosen_linker = 'c'
+endif
+
+# harfbuzz
+gen_def = find_program('gen-def.py')
+
+harfbuzz_def_command_args = [gen_def, '@OUTPUT@', '@INPUT@']
+if get_option('experimental-api')
+ harfbuzz_def_command_args += '--experimental-api'
+endif
+
+harfbuzz_def = custom_target('harfbuzz.def',
+ command: harfbuzz_def_command_args,
+ input: hb_headers,
+ output: 'harfbuzz.def')
+defs_list = [harfbuzz_def]
+
+version = '0.' + '0'.join(meson.project_version().split('.')) + '.0'
+
+extra_hb_cpp_args = []
+if cpp.get_id() == 'msvc'
+ if get_option('default_library') == 'shared'
+ extra_hb_cpp_args += '-DHB_DLL_EXPORT'
+ endif
+ hb_so_version = ''
+else
+ hb_so_version = '0'
+endif
+
+libharfbuzz = library('harfbuzz', hb_sources,
+ include_directories: incconfig,
+ dependencies: deps,
+ cpp_args: cpp_args + extra_hb_cpp_args,
+ soversion: hb_so_version,
+ version: version,
+ install: true,
+ link_language: chosen_linker,
+)
+
+libharfbuzz_dep = declare_dependency(
+ link_with: libharfbuzz,
+ include_directories: incsrc,
+ dependencies: deps)
+
+# harfbuzz-subset
+harfbuzz_subset_def = custom_target('harfbuzz-subset.def',
+ command: [gen_def, '@OUTPUT@', '@INPUT@'],
+ input: hb_subset_headers,
+ output: 'harfbuzz-subset.def')
+defs_list += [harfbuzz_subset_def]
+
+libharfbuzz_subset = library('harfbuzz-subset', hb_subset_sources,
+ include_directories: incconfig,
+ dependencies: deps,
+ link_with: [libharfbuzz],
+ cpp_args: cpp_args + extra_hb_cpp_args,
+ soversion: hb_so_version,
+ version: version,
+ install: true,
+ link_language: chosen_linker,
+)
+
+libharfbuzz_subset_dep = declare_dependency(
+ link_with: libharfbuzz_subset,
+ include_directories: incsrc,
+ dependencies: deps)
+
+if get_option('tests').enabled()
+ # TODO: MSVC gives the following,
+ # error LNK2019: unresolved external symbol "unsigned __int64 const * const _hb_NullPool"
+ if cpp.get_id() != 'msvc'
+ noinst_programs = {
+ 'main': 'main.cc',
+ 'test-basics': 'test.cc',
+ 'test-buffer-serialize': 'test-buffer-serialize.cc',
+ 'test-ot-meta': 'test-ot-meta.cc',
+ 'test-ot-name': 'test-ot-name.cc',
+ 'test-ot-glyphname': 'test-ot-glyphname.cc',
+ 'test-ot-gpos-size-params': 'test-gpos-size-params.cc',
+ 'test-ot-gsub-would-substitute': 'test-gsub-would-substitute.cc',
+ }
+ foreach name, source : noinst_programs
+ executable(name, source,
+ include_directories: incconfig,
+ cpp_args: cpp_args,
+ dependencies: libharfbuzz_dep,
+ install: false,
+ )
+ endforeach
+ endif
+
+ check_programs = {
+ 'dump-indic-data': ['dump-indic-data.cc', 'hb-ot-shape-complex-indic-table.cc'],
+ 'dump-khmer-data': ['dump-khmer-data.cc', 'hb-ot-shape-complex-indic-table.cc'],
+ 'dump-myanmar-data': ['dump-myanmar-data.cc', 'hb-ot-shape-complex-indic-table.cc'],
+ 'dump-use-data': ['dump-use-data.cc', 'hb-ot-shape-complex-use-table.cc'],
+ }
+ foreach name, source : check_programs
+ executable(name, source,
+ include_directories: incconfig,
+ cpp_args: cpp_args,
+ dependencies: libharfbuzz_dep,
+ install: false,
+ )
+ endforeach
+
+ compiled_tests = {
+ 'test-array': 'test-array.cc',
+ 'test-number': ['test-number.cc', 'hb-number.cc'],
+ 'test-ot-tag': 'hb-ot-tag.cc',
+ 'test-unicode-ranges': 'test-unicode-ranges.cc',
+ }
+ if cpp.get_id() != 'msvc'
+ # TODO: MSVC doesn't like these, fix them
+ compiled_tests += {
+ 'test-algs': ['test-algs.cc', 'hb-static.cc'],
+ 'test-bimap': ['test-bimap.cc', 'hb-static.cc'],
+ 'test-iter': ['test-iter.cc', 'hb-static.cc'],
+ 'test-meta': ['test-meta.cc', 'hb-static.cc'],
+ }
+ endif
+ foreach name, source : compiled_tests
+ test(name, executable(name, source,
+ include_directories: incconfig,
+ cpp_args: cpp_args + ['-DMAIN', '-UNDEBUG'],
+ dependencies: libharfbuzz_dep,
+ install: false,
+ ))
+ endforeach
+
+ if host_machine.system() != 'windows' and not meson.is_cross_build()
+ # Some of them should be ported to python
+ dist_check_script = [
+ 'check-c-linkage-decls.sh',
+ 'check-externs.sh',
+ 'check-header-guards.sh',
+ 'check-static-inits.sh',
+ ]
+ if not get_option('amalgam')
+ dist_check_script += 'check-includes.sh'
+ endif
+ if false and not get_option('with-libstdcxx')
+ # enable this once https://github.com/mesonbuild/meson/pull/6838 hits a release
+ # and make that version (i.e. 0.55) our minimum build requirement
+ dist_check_script += 'check-libstdc++.sh' # See https://github.com/harfbuzz/harfbuzz/issues/2276
+ endif
+
+ env = environment()
+ env.set('srcdir', meson.current_source_dir())
+ env.set('builddir', meson.current_build_dir())
+ env.set('libs', meson.current_build_dir()) # TODO: Merge this with builddir after autotools removal
+ env.set('HBSOURCES', ' '.join(hb_sources))
+ env.set('HBHEADERS', ' '.join(hb_headers))
+
+ foreach name : dist_check_script
+ test(name, find_program(name), env: env)
+ endforeach
+ endif
+endif
+
+pkgmod.generate(libharfbuzz,
+ description: 'HarfBuzz text shaping library',
+ subdirs: [meson.project_name()],
+ version: meson.project_version(),
+)
+
+pkgmod.generate(libharfbuzz_subset,
+ description: 'HarfBuzz font subsetter',
+ subdirs: [meson.project_name()],
+ version: meson.project_version(),
+)
+
+if have_icu and not have_icu_builtin
+ harfbuzz_icu_def = custom_target('harfbuzz-icu.def',
+ command: [gen_def, '@OUTPUT@', '@INPUT@'],
+ input: [hb_icu_headers],
+ output: 'harfbuzz-icu.def')
+ defs_list += [harfbuzz_icu_def]
+
+ libharfbuzz_icu = library('harfbuzz-icu', [hb_icu_sources, hb_icu_headers],
+ include_directories: incconfig,
+ dependencies: icu_dep,
+ link_with: [libharfbuzz],
+ cpp_args: cpp_args + extra_hb_cpp_args,
+ soversion: hb_so_version,
+ version: version,
+ install: true,
+ # ICU links to stdc++ anyway so the default linker is good
+ # link_language: chosen_linker,
+ )
+
+ libharfbuzz_icu_dep = declare_dependency(
+ link_with: libharfbuzz_icu,
+ include_directories: incsrc,
+ dependencies: deps)
+
+ pkgmod.generate(libharfbuzz_icu,
+ description: 'HarfBuzz text shaping library ICU integration',
+ subdirs: [meson.project_name()],
+ version: meson.project_version(),
+ )
+
+ install_headers(hb_icu_headers, subdir: meson.project_name())
+else
+ libharfbuzz_icu_dep = dependency('', required: false)
+endif
+
+have_gobject = conf.get('HAVE_GOBJECT', 0) == 1
+
+cmake_config = configuration_data()
+cmake_config.set('libdir', '${prefix}/@0@'.format(get_option('libdir')))
+cmake_config.set('includedir', '${prefix}/@0@'.format(get_option('includedir')))
+cmake_config.set('HB_LIBTOOL_VERSION_INFO', hb_libtool_version_info)
+cmake_config.set('have_gobject', have_gobject ? 'true' : 'false')
+configure_file(input: 'harfbuzz-config.cmake.in',
+ output: 'harfbuzz-config.cmake',
+ configuration: cmake_config,
+ install_dir: join_paths(get_option('libdir'), 'cmake', 'harfbuzz'))
+
+if have_gobject
+ gnome = import('gnome')
+
+ h_templ = configure_file(
+ input: 'hb-gobject-enums.h.tmpl',
+ output: 'hb-gobject-enums-tmp.h.tmpl',
+ configuration: configuration_data(),
+ format: 'cmake')
+
+ cc_templ = configure_file(
+ input: 'hb-gobject-enums.cc.tmpl',
+ output: 'hb-gobject-enums-tmp.cc.tmpl',
+ configuration: configuration_data(),
+ format: 'cmake')
+
+ enums = gnome.mkenums('hb-gobject',
+ sources: hb_headers,
+ h_template: h_templ,
+ c_template: cc_templ,
+ identifier_prefix: 'hb_',
+ symbol_prefix: 'hb_gobject',
+ )
+
+ enum_c = custom_target('hb-gobject-enums.cc',
+ input: enums[0],
+ output: 'hb-gobject-enums.cc',
+ command: [python3, files('fix_get_types.py')[0], '@INPUT@', '@OUTPUT@']
+ )
+
+ enum_h = custom_target('hb-gobject-enums.h',
+ input: enums[1],
+ output: 'hb-gobject-enums.h',
+ command: [python3, files('fix_get_types.py')[0], '@INPUT@', '@OUTPUT@'],
+ install: true,
+ install_dir: join_paths(get_option('prefix'), get_option('includedir'), meson.project_name()),
+ )
+
+ hb_gobject_sources += [enum_c]
+
+ harfbuzz_gobject_def = custom_target('harfbuzz-gobject.def',
+ command: [gen_def, '@OUTPUT@', '@INPUT@'],
+ input: [hb_gobject_headers, enum_h],
+ output: 'harfbuzz-gobject.def')
+ defs_list += [harfbuzz_gobject_def]
+
+ libharfbuzz_gobject = library('harfbuzz-gobject', [hb_gobject_sources, enum_c, enum_h],
+ include_directories: incconfig,
+ dependencies: deps,
+ link_with: [libharfbuzz],
+ cpp_args: cpp_args + extra_hb_cpp_args,
+ soversion: hb_so_version,
+ version: version,
+ install: true,
+ link_language: chosen_linker,
+ )
+
+ gir = find_program('g-ir-scanner', required: get_option('introspection'))
+ build_gir = gir.found() and not meson.is_cross_build()
+
+ if build_gir
+ hb_gen_files_gir = gnome.generate_gir(libharfbuzz, libharfbuzz_gobject,
+ sources: [hb_headers, hb_sources, hb_gobject_headers, hb_gobject_sources, enum_h],
+ namespace: 'HarfBuzz',
+ nsversion: '0.0',
+ identifier_prefix: 'hb_',
+ symbol_prefix: ['hb', 'hb_gobject'],
+ includes: ['GObject-2.0'],
+ export_packages: ['harfbuzz-gobject'],
+ header: 'hb-gobject.h',
+ install: true,
+ extra_args: ['--cflags-begin',
+ '-DHB_H',
+ '-DHB_H_IN',
+ '-DHB_OT_H',
+ '-DHB_OT_H_IN',
+ '-DHB_AAT_H',
+ '-DHB_AAT_H_IN',
+ '-DHB_GOBJECT_H',
+ '-DHB_GOBJECT_H_IN',
+ '-DHB_EXTERN=',
+ '--cflags-end'])
+ endif
+
+ libharfbuzz_gobject_dep = declare_dependency(
+ link_with: libharfbuzz_gobject,
+ include_directories: incsrc,
+ sources: build_gir ? hb_gen_files_gir : hb_gobject_sources,
+ dependencies: deps)
+
+ pkgmod.generate(libharfbuzz_gobject,
+ description: 'HarfBuzz text shaping library GObject integration',
+ subdirs: [meson.project_name()],
+ version: meson.project_version(),
+ )
+
+ install_headers(hb_gobject_headers, subdir: meson.project_name())
+else
+ libharfbuzz_gobject_dep = dependency('', required: false)
+endif
+
+if get_option('tests').enabled() and host_machine.system() != 'windows' and not meson.is_cross_build()
+ test('check-symbols.sh', find_program('check-symbols.sh'),
+ depends: defs_list,
+ env: env)
+endif
+
+install_headers(hb_headers + hb_subset_headers, subdir: meson.project_name())
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-array.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-array.cc
new file mode 100644
index 00000000000..6c888138e74
--- /dev/null
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-array.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2020 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "hb.hh"
+#include "hb-array.hh"
+
+static void
+test_reverse ()
+{
+ int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ hb_array_t<int> a (values, 9);
+ a.reverse();
+
+ int expected_values[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};
+ hb_array_t<int> expected (expected_values, 9);
+ assert (a == expected);
+}
+
+static void
+test_reverse_range ()
+{
+ int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ hb_array_t<int> a (values, 9);
+ a.reverse(2, 6);
+
+ int expected_values[] = {1, 2, 6, 5, 4, 3, 7, 8, 9};
+ hb_array_t<int> expected (expected_values, 9);
+ assert (a == expected);
+}
+
+static void
+test_reverse_invalid ()
+{
+ int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ hb_array_t<int> a (values, 9);
+
+ a.reverse(4, 3);
+ a.reverse(2, 3);
+ a.reverse(5, 5);
+ a.reverse(12, 15);
+
+ int expected_values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ hb_array_t<int> expected (expected_values, 9);
+ assert (a == expected);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_reverse ();
+ test_reverse_range ();
+ test_reverse_invalid ();
+}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc
index 6393f0b7f68..0e78099ce9f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-buffer-serialize.cc
@@ -68,7 +68,7 @@ main (int argc, char **argv)
buf = hb_buffer_create ();
char line[BUFSIZ], out[BUFSIZ];
- while (fgets (line, sizeof(line), stdin) != nullptr)
+ while (fgets (line, sizeof(line), stdin))
{
hb_buffer_clear_contents (buf);
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 9c83171889f..fd201c85e88 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-iter.cc
@@ -105,7 +105,7 @@ test_iterator (Iter it)
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
static void
-test_iterable (const Iterable &lst = Null(Iterable))
+test_iterable (const Iterable &lst = Null (Iterable))
{
for (auto _ : lst)
(void) _;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-meta.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-meta.cc
index 0b6e02c269c..9436b9038e0 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-meta.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-meta.cc
@@ -29,6 +29,8 @@
#include <type_traits>
+template <typename T> struct U { typedef T type; };
+
int
main (int argc, char **argv)
{
@@ -122,6 +124,9 @@ main (int argc, char **argv)
static_assert (hb_is_trivial (X), "");
static_assert (hb_is_trivial (Y), "");
+ static_assert (hb_is_signed (hb_unwrap_type (U<U<U<int>>>)), "");
+ static_assert (hb_is_unsigned (hb_unwrap_type (U<U<U<U<unsigned>>>>)), "");
+
/* TODO Add more meaningful tests. */
return 0;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-number.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-number.cc
index 3591b13f278..57835288c42 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-number.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-number.cc
@@ -25,7 +25,6 @@
#include "hb.hh"
#include "hb-number.hh"
-#include "hb-number-parser.hh"
int
@@ -146,11 +145,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == 123);
assert (pp - str == 4);
assert (end - pp == 1);
-
- /* Test strtod_rl even if libc's strtod_l is used */
- char *pend;
- assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == 123);
- assert (pend - str == 4);
}
{
@@ -163,10 +157,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == 123);
assert (pp - str == 5);
assert (end - pp == 0);
-
- char *pend;
- assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == 123);
- assert (pend - str == 5);
}
{
@@ -179,10 +169,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == 123);
assert (pp - str == 7);
assert (end - pp == 0);
-
- char *pend;
- assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == 123);
- assert (pend - str == 7);
}
{
@@ -195,10 +181,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == 123);
assert (pp - str == 6);
assert (end - pp == 0);
-
- char *pend;
- assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == 123);
- assert (pend - str == 6);
}
{
@@ -211,10 +193,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == 123);
assert (pp - str == 10);
assert (end - pp == 0);
-
- char *pend;
- assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == 123);
- assert (pend - str == 10);
}
{
@@ -228,9 +206,6 @@ main (int argc, char **argv)
assert (pp - str == 13);
assert (end - pp == 0);
- char *pend;
- assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == -123);
- assert (pend - str == 13);
}
{
@@ -243,10 +218,6 @@ main (int argc, char **argv)
assert ((int) roundf (pv * 1000.) == -123);
assert (pp - str == 8);
assert (end - pp == 0);
-
- char *pend;
- assert ((int) roundf (strtod_rl (str, &pend) * 1000.) == -123);
- assert (pend - str == 8);
}
return 0;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-color.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-color.cc
deleted file mode 100644
index 88924b44734..00000000000
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-color.cc
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright © 2018 Ebrahim Byagowi
- * Copyright © 2018 Khaled Hosny
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-#include "hb.hh"
-
-#include <cairo.h>
-
-#ifdef HB_NO_OPEN
-#define hb_blob_create_from_file(x) hb_blob_get_empty ()
-#endif
-
-#if !defined(HB_NO_COLOR) && defined(CAIRO_HAS_SVG_SURFACE)
-
-#include "hb-ot.h"
-
-#include "hb-ft.h"
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_GLYPH_H
-
-#include <cairo-ft.h>
-#include <cairo-svg.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-
-static void
-svg_dump (hb_face_t *face, unsigned int face_index)
-{
- unsigned glyph_count = hb_face_get_glyph_count (face);
-
- for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++)
- {
- hb_blob_t *blob = hb_ot_color_glyph_reference_svg (face, glyph_id);
-
- if (hb_blob_get_length (blob) == 0) continue;
-
- unsigned int length;
- const char *data = hb_blob_get_data (blob, &length);
-
- char output_path[255];
- sprintf (output_path, "out/svg-%u-%u.svg%s",
- glyph_id,
- face_index,
- // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405
- (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : "");
-
- FILE *f = fopen (output_path, "wb");
- fwrite (data, 1, length, f);
- fclose (f);
-
- hb_blob_destroy (blob);
- }
-}
-
-/* _png API is so easy to use unlike the below code, don't get confused */
-static void
-png_dump (hb_face_t *face, unsigned int face_index)
-{
- unsigned glyph_count = hb_face_get_glyph_count (face);
- hb_font_t *font = hb_font_create (face);
-
- /* scans the font for strikes */
- unsigned int sample_glyph_id;
- /* we don't care about different strikes for different glyphs at this point */
- for (sample_glyph_id = 0; sample_glyph_id < glyph_count; sample_glyph_id++)
- {
- hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id);
- unsigned int blob_length = hb_blob_get_length (blob);
- hb_blob_destroy (blob);
- if (blob_length != 0)
- break;
- }
-
- unsigned int upem = hb_face_get_upem (face);
- unsigned int blob_length = 0;
- unsigned int strike = 0;
- for (unsigned int ppem = 1; ppem < upem; ppem++)
- {
- hb_font_set_ppem (font, ppem, ppem);
- hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id);
- unsigned int new_blob_length = hb_blob_get_length (blob);
- hb_blob_destroy (blob);
- if (new_blob_length != blob_length)
- {
- for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++)
- {
- hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, glyph_id);
-
- if (hb_blob_get_length (blob) == 0) continue;
-
- unsigned int length;
- const char *data = hb_blob_get_data (blob, &length);
-
- char output_path[255];
- sprintf (output_path, "out/png-%u-%u-%u.png", glyph_id, strike, face_index);
-
- FILE *f = fopen (output_path, "wb");
- fwrite (data, 1, length, f);
- fclose (f);
-
- hb_blob_destroy (blob);
- }
-
- strike++;
- blob_length = new_blob_length;
- }
- }
-
- hb_font_destroy (font);
-}
-
-static void
-layered_glyph_dump (hb_face_t *face, cairo_font_face_t *cairo_face, unsigned int face_index)
-{
- unsigned int upem = hb_face_get_upem (face);
-
- unsigned glyph_count = hb_face_get_glyph_count (face);
- for (hb_codepoint_t gid = 0; gid < glyph_count; ++gid)
- {
- unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, nullptr, nullptr);
- if (!num_layers)
- continue;
-
- hb_ot_color_layer_t *layers = (hb_ot_color_layer_t*) malloc (num_layers * sizeof (hb_ot_color_layer_t));
-
- hb_ot_color_glyph_get_layers (face, gid, 0, &num_layers, layers);
- if (num_layers)
- {
- // Measure
- cairo_text_extents_t extents;
- {
- cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
- cairo_t *cr = cairo_create (surface);
- cairo_set_font_face (cr, cairo_face);
- cairo_set_font_size (cr, upem);
-
- cairo_glyph_t *glyphs = (cairo_glyph_t *) calloc (num_layers, sizeof (cairo_glyph_t));
- for (unsigned int j = 0; j < num_layers; ++j)
- glyphs[j].index = layers[j].glyph;
- cairo_glyph_extents (cr, glyphs, num_layers, &extents);
- free (glyphs);
- cairo_surface_destroy (surface);
- cairo_destroy (cr);
- }
-
- // Add a slight margin
- extents.width += extents.width / 10;
- extents.height += extents.height / 10;
- extents.x_bearing -= extents.width / 20;
- extents.y_bearing -= extents.height / 20;
-
- // Render
- unsigned int palette_count = hb_ot_color_palette_get_count (face);
- for (unsigned int palette = 0; palette < palette_count; palette++)
- {
- unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, nullptr, nullptr);
- if (!num_colors)
- continue;
-
- hb_color_t *colors = (hb_color_t*) calloc (num_colors, sizeof (hb_color_t));
- hb_ot_color_palette_get_colors (face, palette, 0, &num_colors, colors);
- if (num_colors)
- {
- char output_path[255];
- sprintf (output_path, "out/colr-%u-%u-%u.svg", gid, palette, face_index);
-
- cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
- cairo_t *cr = cairo_create (surface);
- cairo_set_font_face (cr, cairo_face);
- cairo_set_font_size (cr, upem);
-
- for (unsigned int layer = 0; layer < num_layers; ++layer)
- {
- hb_color_t color = 0x000000FF;
- if (layers[layer].color_index != 0xFFFF)
- color = colors[layers[layer].color_index];
- cairo_set_source_rgba (cr,
- hb_color_get_red (color) / 255.,
- hb_color_get_green (color) / 255.,
- hb_color_get_blue (color) / 255.,
- hb_color_get_alpha (color) / 255.);
-
- cairo_glyph_t glyph;
- glyph.index = layers[layer].glyph;
- glyph.x = -extents.x_bearing;
- glyph.y = -extents.y_bearing;
- cairo_show_glyphs (cr, &glyph, 1);
- }
-
- cairo_surface_destroy (surface);
- cairo_destroy (cr);
- }
- free (colors);
- }
- }
-
- free (layers);
- }
-}
-
-static void
-dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem,
- unsigned int num_glyphs, unsigned int face_index)
-{
- for (unsigned int i = 0; i < num_glyphs; ++i)
- {
- cairo_text_extents_t extents;
- cairo_glyph_t glyph = {0};
- glyph.index = i;
-
- // Measure
- {
- cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
- cairo_t *cr = cairo_create (surface);
- cairo_set_font_face (cr, cairo_face);
- cairo_set_font_size (cr, upem);
-
- cairo_glyph_extents (cr, &glyph, 1, &extents);
- cairo_surface_destroy (surface);
- cairo_destroy (cr);
- }
-
- // Add a slight margin
- extents.width += extents.width / 10;
- extents.height += extents.height / 10;
- extents.x_bearing -= extents.width / 20;
- extents.y_bearing -= extents.height / 20;
-
- // Render
- {
- char output_path[255];
- sprintf (output_path, "out/%u-%u.svg", face_index, i);
- cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
- cairo_t *cr = cairo_create (surface);
- cairo_set_font_face (cr, cairo_face);
- cairo_set_font_size (cr, upem);
- glyph.x = -extents.x_bearing;
- glyph.y = -extents.y_bearing;
- cairo_show_glyphs (cr, &glyph, 1);
- cairo_surface_destroy (surface);
- cairo_destroy (cr);
- }
- }
-}
-
-int
-main (int argc, char **argv)
-{
- if (argc != 2) {
- fprintf (stderr, "usage: %s font-file.ttf\n"
- "run it like `rm -rf out && mkdir out && %s font-file.ttf`\n",
- argv[0], argv[0]);
- exit (1);
- }
-
-
- FILE *font_name_file = fopen ("out/.dumped_font_name", "r");
- if (font_name_file != nullptr)
- {
- fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n");
- exit (1);
- }
-
- font_name_file = fopen ("out/.dumped_font_name", "w");
- if (font_name_file == nullptr)
- {
- fprintf (stderr, "./out is not accessible as a folder, create it please\n");
- exit (1);
- }
- fwrite (argv[1], 1, strlen (argv[1]), font_name_file);
- fclose (font_name_file);
-
- hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
- unsigned int num_faces = hb_face_count (blob);
- if (num_faces == 0)
- {
- fprintf (stderr, "error: The file (%s) was corrupted, empty or not found", argv[1]);
- exit (1);
- }
-
- for (unsigned int face_index = 0; face_index < hb_face_count (blob); face_index++)
- {
- hb_face_t *face = hb_face_create (blob, face_index);
- hb_font_t *font = hb_font_create (face);
-
- if (hb_ot_color_has_png (face)) printf ("Dumping png (cbdt/sbix)...\n");
- png_dump (face, face_index);
-
- if (hb_ot_color_has_svg (face)) printf ("Dumping svg...\n");
- svg_dump (face, face_index);
-
- cairo_font_face_t *cairo_face;
- {
- FT_Library library;
- FT_Init_FreeType (&library);
- FT_Face ft_face;
- FT_New_Face (library, argv[1], 0, &ft_face);
- cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
- }
- if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face))
- printf ("Dumping layered color glyphs...\n");
- layered_glyph_dump (face, cairo_face, face_index);
-
- unsigned int num_glyphs = hb_face_get_glyph_count (face);
- unsigned int upem = hb_face_get_upem (face);
-
- // disabled when color font as cairo rendering of NotoColorEmoji is soooo slow
- if (!hb_ot_color_has_layers (face) &&
- !hb_ot_color_has_png (face) &&
- !hb_ot_color_has_svg (face))
- dump_glyphs (cairo_face, upem, num_glyphs, face_index);
-
- hb_font_destroy (font);
- hb_face_destroy (face);
- }
-
- hb_blob_destroy (blob);
-
- return 0;
-}
-
-#else
-int main (int argc, char **argv) { return 0; }
-#endif
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-glyphname.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-glyphname.cc
new file mode 100644
index 00000000000..dffc62b4b1c
--- /dev/null
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-glyphname.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2019 Adobe, 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb.hh"
+#include "hb-ot.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef HB_NO_OPEN
+#define hb_blob_create_from_file(x) hb_blob_get_empty ()
+#endif
+
+int
+main (int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf (stderr, "usage: %s font-file\n", argv[0]);
+ exit (1);
+ }
+
+ hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
+ hb_face_t *face = hb_face_create (blob, 0 /* first face */);
+ hb_font_t *font = hb_font_create (face);
+ hb_blob_destroy (blob);
+ blob = nullptr;
+
+
+ const unsigned int num_glyphs = hb_face_get_glyph_count (face);
+ int result = 1;
+
+ for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
+ {
+ char buf[64];
+ unsigned int buf_size = sizeof (buf);
+ if (hb_font_get_glyph_name (font, gid, buf, buf_size))
+ {
+ hb_codepoint_t gid_inv;
+ if (hb_font_get_glyph_from_name(font, buf, strlen (buf), &gid_inv))
+ {
+ if (gid == gid_inv)
+ {
+ printf ("%u <-> %s\n", gid, buf);
+ }
+ else
+ {
+ printf ("%u -> %s -> %u\n", gid, buf, gid_inv);
+ result = 0;
+ }
+ }
+ else
+ {
+ printf ("%u -> %s -> ?\n", gid, buf);
+ result = 0;
+ }
+ }
+ else
+ {
+ printf ("%u -> ?\n", gid);
+ result = 0;
+ }
+ }
+
+ hb_font_destroy (font);
+ hb_face_destroy (face);
+
+ return result;
+}