summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2023-08-15 10:46:23 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-08-18 15:01:43 +0000
commitea50a2deb550b34d88f5d1abd3d68947b1cb13a4 (patch)
tree93d67d5e5919314bb105af162365a5ead7dbd60b
parentb32f16b16970193dba1f85c65a85d0cb78e04c68 (diff)
Update to Harfbuzz 8.1.1
Change-Id: I886bc7d385e62ff0c9546c18bb7bb9273ef1cbd1 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit 9266b6d0914a31215d8505a363ecfd8f80b744eb) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/3rdparty/harfbuzz-ng/NEWS78
-rw-r--r--src/3rdparty/harfbuzz-ng/README.md7
-rw-r--r--src/3rdparty/harfbuzz-ng/qt_attribution.json4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh11
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh15
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh21
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh13
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh64
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh19
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh41
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh40
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh67
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh82
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh23
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/name/name.hh19
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/graph.hh222
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/serialize.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/harfbuzz.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-algs.hh183
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-array.hh70
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-atomic.hh1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bimap.hh75
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh37
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh7
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh25
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc76
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.cc6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.hh15
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cache.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cairo.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-common.h10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-config.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-debug.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-deprecated.h46
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-draw.hh30
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.cc7
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.h45
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ft.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc42
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-iter.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-kern.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-limits.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-machinery.hh11
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-map.h2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-map.hh188
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-meta.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-multimap.hh34
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-null.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-open-file.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-open-type.hh39
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh271
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh288
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh35
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh38
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh43
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh80
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh21
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh173
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh563
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc235
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h37
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc30
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh13
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh7
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc26
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.cc12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh1893
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use.cc3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh53
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh164
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh947
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh70
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh116
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh123
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh86
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-pool.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh27
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh103
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-serialize.hh36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.h2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shape.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-static.cc3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh51
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc29
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh112
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc296
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc93
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc50
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc221
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.hh112
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc186
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh77
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.cc154
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.h7
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-vector.hh122
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-version.h8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-api-blob.hh50
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-api-buffer.hh217
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-api-common.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.hh)27
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-api-face.hh109
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-api-font.hh263
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-api-shape.hh70
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-api.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.hh)29
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-api.h319
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-api.hh117
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-wasm-shape.cc470
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb.hh9
157 files changed, 7756 insertions, 2998 deletions
diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS
index ff35843192..0a7b94b58a 100644
--- a/src/3rdparty/harfbuzz-ng/NEWS
+++ b/src/3rdparty/harfbuzz-ng/NEWS
@@ -1,3 +1,81 @@
+Overview of changes leading to 8.1.1
+Wednesday, August 2, 2023
+====================================
+- Fix shaping of contextual rules at the end of string, introduced in 8.1.0
+- Fix stack-overflow in repacker with malicious fonts.
+- 30% speed up loading Noto Duployan font.
+
+
+Overview of changes leading to 8.1.0
+Tuesday, August 1, 2023
+====================================
+- Fix long-standing build issue with the AIX compiler and older Apple clang.
+
+- Revert optimization that could cause timeout during subsetting with malicious fonts.
+
+- More optimization work:
+ - 45% speed up in shaping Noto Duployan font.
+ - 10% speed up in subsetting Noto Duployan font.
+ - Another 8% speed up in shaping Gulzar.
+ - 5% speed up in loading Roboto.
+
+- New API:
++hb_ot_layout_collect_features_map()
+
+
+Overview of changes leading to 8.0.1
+Wednesday, July 12, 2023
+====================================
+- Build fix on 32-bit ARM.
+
+- More speed optimizations:
+ - 60% speed up in retain-gid (used for IFT) subsetting of SourceHanSans-VF.
+ - 16% speed up in retain-gid (used for IFT) subsetting of NotoSansCJKkr.
+ - 38% speed up in subsetting (beyond-64k) mega-merged Noto.
+
+
+Overview of changes leading to 8.0.0
+Sunday, July 9, 2023
+====================================
+- New, experimental, WebAssembly (WASM) shaper, that provides greater
+ flexibility over OpenType/AAT/Graphite shaping, using WebAssembly embedded
+ inside the font file. Currently WASM shaper is disabled by default and needs
+ to be enabled at build time. For details, see:
+
+ https://github.com/harfbuzz/harfbuzz/blob/main/docs/wasm-shaper.md
+
+ For example fonts making use of the WASM shaper, see:
+
+ https://github.com/harfbuzz/harfbuzz-wasm-examples
+
+- Improvements to Experimental features introduced in earlier releases:
+ - Support for subsetting beyond-64k and VarComposites fonts.
+ - Support for instancing variable fonts with cubic “glyf” table.
+
+- Many big speed optimizations:
+ - Up to 89% speedup loading variable fonts for shaping.
+ - Up to 88% speedup in small subsets of large (eg. CJK) fonts (both TTF and
+ OTF), essential for Incremental Font Transfer (IFT).
+ - Over 50% speedup in loading Roboto font for shaping.
+ - Up to 40% speed up in loading (sanitizing) complex fonts.
+ - 30% speed up in shaping Gulzar font.
+ - Over 25% speedup in glyph loading Roboto font.
+ - 10% speed up loading glyph shapes in VarComposite Hangul font.
+ - hb-hashmap optimizations & hashing improvements.
+
+- New macro HB_ALWAYS_INLINE. HarfBuzz now inlines functions more aggressively,
+ which results in some speedup at the expense of bigger code size. To disable
+ this feature define the macro to just inline.
+
+- New API:
++HB_CODEPOINT_INVALID
++hb_ot_layout_get_baseline2()
++hb_ot_layout_get_baseline_with_fallback2()
++hb_ot_layout_get_font_extents()
++hb_ot_layout_get_font_extents2()
++hb_subset_input_set_axis_range()
+
+
Overview of changes leading to 7.3.0
Tuesday, May 9, 2023
====================================
diff --git a/src/3rdparty/harfbuzz-ng/README.md b/src/3rdparty/harfbuzz-ng/README.md
index 4202961e04..cb075e3afd 100644
--- a/src/3rdparty/harfbuzz-ng/README.md
+++ b/src/3rdparty/harfbuzz-ng/README.md
@@ -5,13 +5,16 @@
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=harfbuzz/harfbuzz&amp;utm_campaign=Badge_Grade)
[![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
[![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions)
+[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/harfbuzz/harfbuzz/badge)](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz)
+
# HarfBuzz
HarfBuzz is a text shaping engine. It primarily supports [OpenType][1], but also
[Apple Advanced Typography][2]. HarfBuzz is used in Android, Chrome,
-ChromeOS, Firefox, GNOME, GTK+, KDE, LibreOffice, OpenJDK, PlayStation, Qt,
-XeTeX, and other places.
+ChromeOS, Firefox, GNOME, GTK+, KDE, Qt, LibreOffice, OpenJDK, XeTeX,
+PlayStation, Microsoft Edge, Photoshop, Illustrator, InDesign,
+and other places.
For bug reports, mailing list, and other information please visit:
diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json
index f2b53ef7d6..53530941d6 100644
--- a/src/3rdparty/harfbuzz-ng/qt_attribution.json
+++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json
@@ -7,8 +7,8 @@
"Description": "HarfBuzz is an OpenType text shaping engine.",
"Homepage": "http://harfbuzz.org",
- "Version": "7.3.0",
- "DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/7.3.0",
+ "Version": "8.1.1",
+ "DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/8.1.1",
"License": "MIT License",
"LicenseId": "MIT",
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh
index b125052344..457039bfc6 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh
@@ -397,7 +397,6 @@ struct IndexSubtableRecord
TRACE_SERIALIZE (this);
auto *subtable = c->serializer->start_embed<IndexSubtable> ();
- if (unlikely (!subtable)) return_trace (false);
if (unlikely (!c->serializer->extend_min (subtable))) return_trace (false);
auto *old_subtable = get_subtable (base);
@@ -545,7 +544,8 @@ struct IndexSubtableArray
const IndexSubtableRecord*>> *lookup /* OUT */) const
{
bool start_glyph_is_set = false;
- for (hb_codepoint_t new_gid = 0; new_gid < c->plan->num_output_glyphs (); new_gid++)
+ unsigned num_glyphs = c->plan->num_output_glyphs ();
+ for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
{
hb_codepoint_t old_gid;
if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) continue;
@@ -576,9 +576,6 @@ struct IndexSubtableArray
{
TRACE_SUBSET (this);
- auto *dst = c->serializer->start_embed<IndexSubtableArray> ();
- if (unlikely (!dst)) return_trace (false);
-
hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> lookup;
build_lookup (c, bitmap_size_context, &lookup);
if (unlikely (!c->serializer->propagate_error (lookup)))
@@ -993,12 +990,10 @@ CBLC::subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- auto *cblc_prime = c->serializer->start_embed<CBLC> ();
-
// Use a vector as a secondary buffer as the tables need to be built in parallel.
hb_vector_t<char> cbdt_prime;
- if (unlikely (!cblc_prime)) return_trace (false);
+ auto *cblc_prime = c->serializer->start_embed<CBLC> ();
if (unlikely (!c->serializer->extend_min (cblc_prime))) return_trace (false);
cblc_prime->version = version;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh
index 2a47984294..6591bb4380 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh
@@ -409,7 +409,6 @@ struct ColorLine
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (this);
- if (unlikely (!out)) return_trace (false);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
@@ -1434,6 +1433,7 @@ struct PaintComposite
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
+ c->check_ops (this->min_size) && // PainComposite can get exponential
src.sanitize (c, this) &&
backdrop.sanitize (c, this));
}
@@ -2167,7 +2167,7 @@ struct COLR
if (version == 0 && (!base_it || !layer_it))
return_trace (false);
- COLR *colr_prime = c->serializer->start_embed<COLR> ();
+ auto *colr_prime = c->serializer->start_embed<COLR> ();
if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false);
if (version == 0)
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh
index 46ad3fd58e..ce8693cfb1 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh
@@ -48,7 +48,6 @@ struct SBIXGlyph
{
TRACE_SERIALIZE (this);
SBIXGlyph* new_glyph = c->start_embed<SBIXGlyph> ();
- if (unlikely (!new_glyph)) return_trace (nullptr);
if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr);
new_glyph->xOffset = xOffset;
@@ -143,7 +142,6 @@ struct SBIXStrike
unsigned int num_output_glyphs = c->plan->num_output_glyphs ();
auto* out = c->serializer->start_embed<SBIXStrike> ();
- if (unlikely (!out)) return_trace (false);
auto snap = c->serializer->snapshot ();
if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false);
out->ppem = ppem;
@@ -388,7 +386,6 @@ struct sbix
TRACE_SERIALIZE (this);
auto *out = c->serializer->start_embed<Array32OfOffset32To<SBIXStrike>> ();
- if (unlikely (!out)) return_trace (false);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
hb_vector_t<Offset32To<SBIXStrike>*> new_strikes;
@@ -423,8 +420,6 @@ struct sbix
{
TRACE_SUBSET (this);
- sbix *sbix_prime = c->serializer->start_embed<sbix> ();
- if (unlikely (!sbix_prime)) return_trace (false);
if (unlikely (!c->serializer->embed (this->version))) return_trace (false);
if (unlikely (!c->serializer->embed (this->flags))) return_trace (false);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh
index 9ca88f788a..25056c9bc3 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh
@@ -57,6 +57,9 @@ struct Coverage
public:
DEFINE_SIZE_UNION (2, format);
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh
index 5d68e3d15e..3f598d40ef 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh
@@ -79,7 +79,7 @@ struct CoverageFormat1_3
{
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
{
- for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ for (auto g : *glyphs)
if (get_coverage (g) != NOT_COVERED)
return true;
return false;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh
index fa501d659d..9c87542356 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh
@@ -122,7 +122,7 @@ struct CoverageFormat2_4
{
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
{
- for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ for (auto g : *glyphs)
if (get_coverage (g) != NOT_COVERED)
return true;
return false;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh
index c1ff796199..4f85d3ce5e 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh
@@ -49,8 +49,6 @@ struct AttachPoint : Array16Of<HBUINT16>
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
-
return_trace (out->serialize (c->serializer, + iter ()));
}
};
@@ -202,7 +200,6 @@ struct CaretValueFormat3
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
if (!c->serializer->embed (caretValueFormat)) return_trace (false);
if (!c->serializer->embed (coordinate)) return_trace (false);
@@ -442,6 +439,16 @@ 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; }
+ template <typename set_t>
+ void collect_coverage (hb_vector_t<set_t> &sets) const
+ {
+ for (const auto &offset : coverage)
+ {
+ const auto &cov = this+offset;
+ cov.collect_coverage (sets.push ());
+ }
+ }
+
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
@@ -495,6 +502,15 @@ struct MarkGlyphSets
}
}
+ template <typename set_t>
+ void collect_coverage (hb_vector_t<set_t> &sets) const
+ {
+ switch (u.format) {
+ case 1: u.format1.collect_coverage (sets); return;
+ default:return;
+ }
+ }
+
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
@@ -859,6 +875,10 @@ struct GDEF
hb_blob_destroy (table.get_blob ());
table = hb_blob_get_empty ();
}
+
+#ifndef HB_NO_GDEF_CACHE
+ table->get_mark_glyph_sets ().collect_coverage (mark_glyph_set_digests);
+#endif
}
~accelerator_t () { table.destroy (); }
@@ -882,8 +902,18 @@ struct GDEF
}
+ bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+ {
+ return
+#ifndef HB_NO_GDEF_CACHE
+ mark_glyph_set_digests[set_index].may_have (glyph_id) &&
+#endif
+ table->mark_set_covers (set_index, glyph_id);
+ }
+
hb_blob_ptr_t<GDEF> table;
#ifndef HB_NO_GDEF_CACHE
+ hb_vector_t<hb_set_digest_t> mark_glyph_set_digests;
mutable hb_cache_t<21, 3, 8> glyph_props_cache;
#endif
};
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh
index e7e3c5c6d1..8684f60ca5 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh
@@ -25,7 +25,9 @@ struct AnchorFormat3
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
+ if (unlikely (!c->check_struct (this))) return_trace (false);
+
+ return_trace (xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
}
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
@@ -35,9 +37,9 @@ struct AnchorFormat3
*x = font->em_fscale_x (xCoordinate);
*y = font->em_fscale_y (yCoordinate);
- if (font->x_ppem || font->num_coords)
+ if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this))
*x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
- if (font->y_ppem || font->num_coords)
+ if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
*y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
}
@@ -45,7 +47,6 @@ struct AnchorFormat3
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
if (unlikely (!c->serializer->embed (format))) return_trace (false);
if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh
index c442efa1ea..bd9b189739 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh
@@ -21,18 +21,25 @@ struct AnchorMatrix
if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
unsigned int count = rows * cols;
if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
+
+ if (c->lazy_some_gpos)
+ return_trace (true);
+
for (unsigned int i = 0; i < count; i++)
if (!matrixZ[i].sanitize (c, this)) return_trace (false);
return_trace (true);
}
- const Anchor& get_anchor (unsigned int row, unsigned int col,
- unsigned int cols, bool *found) const
+ const Anchor& get_anchor (hb_ot_apply_context_t *c,
+ unsigned int row, unsigned int col,
+ unsigned int cols, bool *found) const
{
*found = false;
if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
- *found = !matrixZ[row * cols + col].is_null ();
- return this+matrixZ[row * cols + col];
+ auto &offset = matrixZ[row * cols + col];
+ if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor);
+ *found = !offset.is_null ();
+ return this+offset;
}
template <typename Iterator,
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
index b8773ba0aa..54852aae75 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
@@ -91,7 +91,13 @@ struct CursivePosFormat1
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
+ if (unlikely (!coverage.sanitize (c, this)))
+ return_trace (false);
+
+ if (c->lazy_some_gpos)
+ return_trace (entryExitRecord.sanitize_shallow (c));
+ else
+ return_trace (entryExitRecord.sanitize (c, this));
}
bool intersects (const hb_set_t *glyphs) const
@@ -119,10 +125,11 @@ struct CursivePosFormat1
hb_buffer_t *buffer = c->buffer;
const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
- if (!this_record.entryAnchor) return_trace (false);
+ if (!this_record.entryAnchor ||
+ unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset_fast (buffer->idx, 1);
+ skippy_iter.reset_fast (buffer->idx);
unsigned unsafe_from;
if (unlikely (!skippy_iter.prev (&unsafe_from)))
{
@@ -131,7 +138,8 @@ struct CursivePosFormat1
}
const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
- if (!prev_record.exitAnchor)
+ if (!prev_record.exitAnchor ||
+ unlikely (!prev_record.exitAnchor.sanitize (&c->sanitizer, this)))
{
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
@@ -200,8 +208,8 @@ struct CursivePosFormat1
* Arabic. */
unsigned int child = i;
unsigned int parent = j;
- hb_position_t x_offset = entry_x - exit_x;
- hb_position_t y_offset = entry_y - exit_y;
+ hb_position_t x_offset = roundf (entry_x - exit_x);
+ hb_position_t y_offset = roundf (entry_y - exit_y);
if (!(c->lookup_props & LookupFlag::RightToLeft))
{
unsigned int k = child;
@@ -278,7 +286,6 @@ struct CursivePosFormat1
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
auto it =
+ hb_zip (this+coverage, entryExitRecord)
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
index ff43ffb8c5..34e2ab8f6e 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
@@ -28,7 +28,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
const Anchor& mark_anchor = this + record.markAnchor;
bool found;
- const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
+ const Anchor& glyph_anchor = anchors.get_anchor (c, glyph_index, mark_class, class_count, &found);
/* If this subtable doesn't have an anchor for this base and this class,
* return false such that the subsequent subtables have a chance at it. */
if (unlikely (!found)) return_trace (false);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
index 9dae5ce5da..72535f4c98 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
@@ -100,7 +100,7 @@ struct MarkMarkPosFormat1_2
/* now we search backwards for a suitable mark glyph until a non-mark glyph */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset_fast (buffer->idx, 1);
+ skippy_iter.reset_fast (buffer->idx);
skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
unsigned unsafe_from;
if (unlikely (!skippy_iter.prev (&unsafe_from)))
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
index 714b4bec72..e4a2006fb9 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
@@ -110,7 +110,7 @@ struct PairPosFormat1_3
if (likely (index == NOT_COVERED)) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset_fast (buffer->idx, 1);
+ skippy_iter.reset_fast (buffer->idx);
unsigned unsafe_to;
if (unlikely (!skippy_iter.next (&unsafe_to)))
{
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
index 31329dfcb5..1bde9e755e 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
@@ -54,8 +54,9 @@ struct PairPosFormat2_4
return_trace (c->check_range ((const void *) values,
count,
stride) &&
- valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
- valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
+ (c->lazy_some_gpos ||
+ (valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
+ valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride))));
}
bool intersects (const hb_set_t *glyphs) const
@@ -130,7 +131,7 @@ struct PairPosFormat2_4
if (likely (index == NOT_COVERED)) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset_fast (buffer->idx, 1);
+ skippy_iter.reset_fast (buffer->idx);
unsigned unsafe_to;
if (unlikely (!skippy_iter.next (&unsafe_to)))
{
@@ -298,11 +299,13 @@ struct PairPosFormat2_4
out->valueFormat2 = out->valueFormat2.drop_device_table_flags ();
}
+ unsigned total_len = len1 + len2;
+ hb_vector_t<unsigned> class2_idxs (+ hb_range ((unsigned) class2Count) | hb_filter (klass2_map));
for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
{
- for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+ for (unsigned class2_idx : class2_idxs)
{
- unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * total_len;
valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], &c->plan->layout_variation_idx_delta_map);
valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &c->plan->layout_variation_idx_delta_map);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
index 9faff49909..db301bb816 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
@@ -52,8 +52,9 @@ struct PairSet
unsigned int count = len;
const PairValueRecord *record = &firstPairValueRecord;
- return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
- closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
+ return_trace (c->lazy_some_gpos ||
+ (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
+ closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)));
}
bool intersects (const hb_set_t *glyphs,
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh
index 3222477764..72bf0e99b5 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh
@@ -22,7 +22,7 @@ struct PairValueRecord
ValueRecord values; /* Positioning data for the first glyph
* followed by for second glyph */
public:
- DEFINE_SIZE_ARRAY (Types::size, values);
+ DEFINE_SIZE_ARRAY (Types::HBGlyphID::static_size, values);
int cmp (hb_codepoint_t k) const
{ return secondGlyph.cmp (k); }
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
index 623e4e66b2..dff1f7316d 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
@@ -90,6 +90,7 @@ struct SinglePosFormat1
bool
position_single (hb_font_t *font,
+ hb_blob_t *table_blob,
hb_direction_t direction,
hb_codepoint_t gid,
hb_glyph_position_t &pos) const
@@ -100,7 +101,7 @@ struct SinglePosFormat1
/* This is ugly... */
hb_buffer_t buffer;
buffer.props.direction = direction;
- OT::hb_ot_apply_context_t c (1, font, &buffer);
+ OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
valueFormat.apply_value (&c, this, values, pos);
return true;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
index e8f2d7c2c6..168ad3bb8c 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
@@ -94,6 +94,7 @@ struct SinglePosFormat2
bool
position_single (hb_font_t *font,
+ hb_blob_t *table_blob,
hb_direction_t direction,
hb_codepoint_t gid,
hb_glyph_position_t &pos) const
@@ -105,7 +106,7 @@ struct SinglePosFormat2
/* This is ugly... */
hb_buffer_t buffer;
buffer.props.direction = direction;
- OT::hb_ot_apply_context_t c (1, font, &buffer);
+ OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
valueFormat.apply_value (&c, this,
&values[index * valueFormat.get_len ()],
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
index 1aa451abcc..461a13d4b7 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
@@ -118,21 +118,25 @@ struct ValueFormat : HBUINT16
auto *cache = c->var_store_cache;
/* pixel -> fractional pixel */
- if (format & xPlaDevice) {
- if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+ if (format & xPlaDevice)
+ {
+ if (use_x_device) glyph_pos.x_offset += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache);
values++;
}
- if (format & yPlaDevice) {
- if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+ if (format & yPlaDevice)
+ {
+ if (use_y_device) glyph_pos.y_offset += get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache);
values++;
}
- if (format & xAdvDevice) {
- if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+ if (format & xAdvDevice)
+ {
+ if (horizontal && use_x_device) glyph_pos.x_advance += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache);
values++;
}
- if (format & yAdvDevice) {
+ if (format & yAdvDevice)
+ {
/* y_advance values grow downward but font-space grows upward, hence negation */
- if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+ if (!horizontal && use_y_device) glyph_pos.y_advance -= get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache);
values++;
}
return ret;
@@ -174,6 +178,9 @@ struct ValueFormat : HBUINT16
if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++);
if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++);
+ if (!has_device ())
+ return;
+
if (format & xPlaDevice)
{
add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map);
@@ -233,14 +240,12 @@ struct ValueFormat : HBUINT16
if (format & ValueFormat::xAdvDevice)
{
-
(base + get_device (&(values[i]))).collect_variation_indices (c);
i++;
}
if (format & ValueFormat::yAdvDevice)
{
-
(base + get_device (&(values[i]))).collect_variation_indices (c);
i++;
}
@@ -277,11 +282,23 @@ struct ValueFormat : HBUINT16
{
return *static_cast<Offset16To<Device> *> (value);
}
- static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
+ static inline const Offset16To<Device>& get_device (const Value* value)
{
- if (worked) *worked |= bool (*value);
return *static_cast<const Offset16To<Device> *> (value);
}
+ static inline const Device& get_device (const Value* value,
+ bool *worked,
+ const void *base,
+ hb_sanitize_context_t &c)
+ {
+ if (worked) *worked |= bool (*value);
+ auto &offset = *static_cast<const Offset16To<Device> *> (value);
+
+ if (unlikely (!offset.sanitize (&c, base)))
+ return Null(Device);
+
+ return base + offset;
+ }
void add_delta_to_value (HBINT16 *value,
const void *base,
@@ -340,25 +357,26 @@ struct ValueFormat : HBUINT16
bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
{
TRACE_SANITIZE (this);
- return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
+
+ if (unlikely (!c->check_range (values, get_size ()))) return_trace (false);
+
+ if (c->lazy_some_gpos)
+ return_trace (true);
+
+ return_trace (!has_device () || sanitize_value_devices (c, base, values));
}
bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
{
TRACE_SANITIZE (this);
- unsigned int len = get_len ();
+ unsigned size = get_size ();
- if (!c->check_range (values, count, get_size ())) return_trace (false);
+ if (!c->check_range (values, count, size)) return_trace (false);
- if (!has_device ()) return_trace (true);
+ if (c->lazy_some_gpos)
+ return_trace (true);
- for (unsigned int i = 0; i < count; i++) {
- if (!sanitize_value_devices (c, base, values))
- return_trace (false);
- values += len;
- }
-
- return_trace (true);
+ return_trace (sanitize_values_stride_unsafe (c, base, values, count, size));
}
/* Just sanitize referenced Device tables. Doesn't check the values themselves. */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
index 968bba0481..b849494d88 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
@@ -8,8 +8,6 @@ namespace OT {
namespace Layout {
namespace GSUB_impl {
-typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
-
template<typename Iterator>
static void SingleSubst_serialize (hb_serialize_context_t *c,
Iterator it);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
index 8674a52fb5..402ed12ae2 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
@@ -13,7 +13,7 @@ struct Ligature
public:
typename Types::HBGlyphID
ligGlyph; /* GlyphID of ligature to substitute */
- HeadlessArrayOf<typename Types::HBGlyphID>
+ HeadlessArray16Of<typename Types::HBGlyphID>
component; /* Array of component GlyphIDs--start
* with the second component--ordered
* in writing direction */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh
index 0ba262e901..08665438c4 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh
@@ -72,19 +72,14 @@ struct LigatureSet
;
}
- static bool match_always (hb_glyph_info_t &info HB_UNUSED, unsigned value HB_UNUSED, const void *data HB_UNUSED)
- {
- return true;
- }
-
bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
unsigned int num_ligs = ligature.len;
-#ifndef HB_NO_OT_LIGATURES_FAST_PATH
- if (HB_OPTIMIZE_SIZE_VAL || num_ligs <= 2)
+#ifndef HB_NO_OT_RULESETS_FAST_PATH
+ if (HB_OPTIMIZE_SIZE_VAL || num_ligs <= 4)
#endif
{
slow:
@@ -97,10 +92,12 @@ struct LigatureSet
}
/* This version is optimized for speed by matching the first component
- * of the ligature here, instead of calling into the ligation code. */
+ * of the ligature here, instead of calling into the ligation code.
+ *
+ * This is replicated in ChainRuleSet and RuleSet. */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (c->buffer->idx, 1);
+ skippy_iter.reset (c->buffer->idx);
skippy_iter.set_match_func (match_always, nullptr);
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
unsigned unsafe_to;
@@ -118,6 +115,8 @@ struct LigatureSet
goto slow;
}
}
+ else
+ goto slow;
bool unsafe_to_concat = false;
@@ -125,7 +124,7 @@ struct LigatureSet
{
const auto &lig = this+ligature.arrayZ[i];
if (unlikely (lig.component.lenP1 <= 1) ||
- lig.component[1] == first)
+ lig.component.arrayZ[0] == first)
{
if (lig.apply (c))
{
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
index 2c2e1aa44f..916fa281b3 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
@@ -191,7 +191,6 @@ struct ReverseChainSingleSubstFormat1
TRACE_SERIALIZE (this);
auto *out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->check_success (out))) return_trace (false);
if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
index ae3292f329..a26cf8c6a6 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
@@ -53,7 +53,7 @@ struct Sequence
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "replaced glyph at %u (multiple subtitution)",
+ "replaced glyph at %u (multiple substitution)",
c->buffer->idx - 1u);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh
index d81fadf7c8..60858a5a58 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh
@@ -90,24 +90,36 @@ struct CompositeGlyphRecord
static void transform (const float (&matrix)[4],
hb_array_t<contour_point_t> points)
{
- auto arrayZ = points.arrayZ;
- unsigned count = points.length;
-
if (matrix[0] != 1.f || matrix[1] != 0.f ||
matrix[2] != 0.f || matrix[3] != 1.f)
- for (unsigned i = 0; i < count; i++)
- arrayZ[i].transform (matrix);
+ for (auto &point : points)
+ point.transform (matrix);
}
static void translate (const contour_point_t &trans,
hb_array_t<contour_point_t> points)
{
- auto arrayZ = points.arrayZ;
- unsigned count = points.length;
-
- if (trans.x != 0.f || trans.y != 0.f)
- for (unsigned i = 0; i < count; i++)
- arrayZ[i].translate (trans);
+ if (HB_OPTIMIZE_SIZE_VAL)
+ {
+ if (trans.x != 0.f || trans.y != 0.f)
+ for (auto &point : points)
+ point.translate (trans);
+ }
+ else
+ {
+ if (trans.x != 0.f && trans.y != 0.f)
+ for (auto &point : points)
+ point.translate (trans);
+ else
+ {
+ if (trans.x != 0.f)
+ for (auto &point : points)
+ point.x += trans.x;
+ else if (trans.y != 0.f)
+ for (auto &point : points)
+ point.y += trans.y;
+ }
+ }
}
void transform_points (hb_array_t<contour_point_t> points,
@@ -131,9 +143,8 @@ struct CompositeGlyphRecord
float matrix[4];
contour_point_t trans;
get_transformation (matrix, trans);
- points.alloc (points.length + 4); // For phantom points
- if (unlikely (!points.resize (points.length + 1))) return false;
- points.arrayZ[points.length - 1] = trans;
+ if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points
+ points.push (trans);
return true;
}
@@ -382,7 +393,7 @@ struct CompositeGlyph
{
/* last 4 points in points_with_deltas are phantom points and should not be included */
if (i >= points_with_deltas.length - 4) {
- free (o);
+ hb_free (o);
return false;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
index 2bd5fe8206..2611c1e21d 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
@@ -114,8 +114,8 @@ struct Glyph
if (type != EMPTY)
{
- plan->bounds_width_map.set (new_gid, xMax - xMin);
- plan->bounds_height_map.set (new_gid, yMax - yMin);
+ plan->bounds_width_vec[new_gid] = xMax - xMin;
+ plan->bounds_height_vec[new_gid] = yMax - yMin;
}
unsigned len = all_points.length;
@@ -124,10 +124,12 @@ struct Glyph
float topSideY = all_points[len - 2].y;
float bottomSideY = all_points[len - 1].y;
+ uint32_t hash = hb_hash (new_gid);
+
signed hori_aw = roundf (rightSideX - leftSideX);
if (hori_aw < 0) hori_aw = 0;
int lsb = roundf (xMin - leftSideX);
- plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
+ plan->hmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) hori_aw, lsb));
//flag value should be computed using non-empty glyphs
if (type != EMPTY && lsb != xMin)
plan->head_maxp_info.allXMinIsLsb = false;
@@ -135,7 +137,7 @@ struct Glyph
signed vert_aw = roundf (topSideY - bottomSideY);
if (vert_aw < 0) vert_aw = 0;
int tsb = roundf (topSideY - yMax);
- plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
+ plan->vmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) vert_aw, tsb));
}
bool compile_header_bytes (const hb_subset_plan_t *plan,
@@ -369,9 +371,11 @@ struct Glyph
}
#ifndef HB_NO_VAR
- glyf_accelerator.gvar->apply_deltas_to_points (gid,
- coords,
- points.as_array ().sub_array (old_length));
+ if (coords)
+ glyf_accelerator.gvar->apply_deltas_to_points (gid,
+ coords,
+ points.as_array ().sub_array (old_length),
+ phantom_only && type == SIMPLE);
#endif
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
@@ -379,7 +383,7 @@ struct Glyph
if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
{
if (unlikely (!points_with_deltas->resize (points.length))) return false;
- points_with_deltas->copy_vector (points);
+ *points_with_deltas = points;
}
switch (type) {
@@ -417,14 +421,17 @@ struct Glyph
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
- float matrix[4];
- contour_point_t default_trans;
- item.get_transformation (matrix, default_trans);
+ if (comp_points) // Empty in case of phantom_only
+ {
+ float matrix[4];
+ contour_point_t default_trans;
+ item.get_transformation (matrix, default_trans);
- /* Apply component transformation & translation (with deltas applied) */
- item.transform_points (comp_points, matrix, points[comp_index]);
+ /* Apply component transformation & translation (with deltas applied) */
+ item.transform_points (comp_points, matrix, points[comp_index]);
+ }
- if (item.is_anchored ())
+ if (item.is_anchored () && !phantom_only)
{
unsigned int p1, p2;
item.get_anchor_points (p1, p2);
@@ -466,7 +473,10 @@ struct Glyph
assert (record_points.length == item_num_points);
auto component_coords = coords;
- if (item.is_reset_unspecified_axes ())
+ /* Copying coords is expensive; so we have put an arbitrary
+ * limit on the max number of coords for now. */
+ if (item.is_reset_unspecified_axes () ||
+ coords.length > HB_GLYF_VAR_COMPOSITE_MAX_AXES)
component_coords = hb_array<int> ();
coord_setter_t coord_setter (component_coords);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh
index 555bcee346..1d42cc2925 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh
@@ -154,10 +154,9 @@ struct SimpleGlyph
{
int v = 0;
- unsigned count = points_.length;
- for (unsigned i = 0; i < count; i++)
+ for (auto &point : points_)
{
- unsigned flag = points_.arrayZ[i].flag;
+ unsigned flag = point.flag;
if (flag & short_flag)
{
if (unlikely (p + 1 > end)) return false;
@@ -175,7 +174,7 @@ struct SimpleGlyph
p += HBINT16::static_size;
}
}
- points_.arrayZ[i].*m = v;
+ point.*m = v;
}
return true;
}
@@ -192,9 +191,10 @@ struct SimpleGlyph
unsigned old_length = points.length;
points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy
- if (!points.resize (points.length + num_points, false)) return false;
+ if (unlikely (!points.resize (points.length + num_points, false))) return false;
auto points_ = points.as_array ().sub_array (old_length);
- hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points);
+ if (!phantom_only)
+ hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points);
if (phantom_only) return true;
for (int i = 0; i < num_contours; i++)
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh
index 26dc374eab..8099d3c126 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh
@@ -22,7 +22,7 @@ struct SubsetGlyph
bool serialize (hb_serialize_context_t *c,
bool use_short_loca,
- const hb_subset_plan_t *plan)
+ const hb_subset_plan_t *plan) const
{
TRACE_SERIALIZE (this);
@@ -40,7 +40,7 @@ struct SubsetGlyph
pad = 0;
while (pad_length > 0)
{
- c->embed (pad);
+ (void) c->embed (pad);
pad_length--;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh
index 6dc6fd9ded..50cbece3ca 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh
@@ -214,7 +214,7 @@ struct VarCompositeGlyphRecord
points.alloc (points.length + num_points + 4); // For phantom points
if (unlikely (!points.resize (points.length + num_points, false))) return false;
contour_point_t *rec_points = points.arrayZ + (points.length - num_points);
- memset (rec_points, 0, num_points * sizeof (rec_points[0]));
+ hb_memset (rec_points, 0, num_points * sizeof (rec_points[0]));
unsigned fl = flags;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh
index df64ed5af7..cf05929362 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh
@@ -16,6 +16,8 @@ struct coord_setter_t
int& operator [] (unsigned idx)
{
+ if (unlikely (idx >= HB_GLYF_VAR_COMPOSITE_MAX_AXES))
+ return Crap(int);
if (coords.length < idx + 1)
coords.resize (idx + 1);
return coords[idx];
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh
index 30106b2b98..d0a5a132f0 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh
@@ -12,24 +12,44 @@ namespace OT {
namespace glyf_impl {
-template<typename IteratorIn, typename IteratorOut,
- hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
- hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
+template<typename IteratorIn, typename TypeOut,
+ hb_requires (hb_is_source_of (IteratorIn, unsigned int))>
static void
-_write_loca (IteratorIn&& it, bool short_offsets, IteratorOut&& dest)
+_write_loca (IteratorIn&& it,
+ const hb_sorted_vector_t<hb_codepoint_pair_t> new_to_old_gid_list,
+ bool short_offsets,
+ TypeOut *dest,
+ unsigned num_offsets)
{
unsigned right_shift = short_offsets ? 1 : 0;
- unsigned int offset = 0;
- dest << 0;
- + it
- | hb_map ([=, &offset] (unsigned int padded_size)
- {
- offset += padded_size;
- DEBUG_MSG (SUBSET, nullptr, "loca entry offset %u", offset);
- return offset >> right_shift;
- })
- | hb_sink (dest)
- ;
+ unsigned offset = 0;
+ TypeOut value;
+ value = 0;
+ *dest++ = value;
+ hb_codepoint_t last = 0;
+ for (auto _ : new_to_old_gid_list)
+ {
+ hb_codepoint_t gid = _.first;
+ for (; last < gid; last++)
+ {
+ DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset);
+ *dest++ = value;
+ }
+
+ unsigned padded_size = *it++;
+ offset += padded_size;
+ DEBUG_MSG (SUBSET, nullptr, "loca entry gid %u offset %u padded-size %u", gid, offset, padded_size);
+ value = offset >> right_shift;
+ *dest++ = value;
+
+ last++; // Skip over gid
+ }
+ unsigned num_glyphs = num_offsets - 1;
+ for (; last < num_glyphs; last++)
+ {
+ DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset);
+ *dest++ = value;
+ }
}
static bool
@@ -67,11 +87,14 @@ _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
template<typename Iterator,
hb_requires (hb_is_source_of (Iterator, unsigned int))>
static bool
-_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
+_add_loca_and_head (hb_subset_context_t *c,
+ Iterator padded_offsets,
+ bool use_short_loca)
{
- unsigned num_offsets = padded_offsets.len () + 1;
+ unsigned num_offsets = c->plan->num_output_glyphs () + 1;
unsigned entry_size = use_short_loca ? 2 : 4;
- char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
+
+ char *loca_prime_data = (char *) hb_malloc (entry_size * num_offsets);
if (unlikely (!loca_prime_data)) return false;
@@ -79,9 +102,9 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s
entry_size, num_offsets, entry_size * num_offsets);
if (use_short_loca)
- _write_loca (padded_offsets, true, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
+ _write_loca (padded_offsets, c->plan->new_to_old_gid_list, true, (HBUINT16 *) loca_prime_data, num_offsets);
else
- _write_loca (padded_offsets, false, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
+ _write_loca (padded_offsets, c->plan->new_to_old_gid_list, false, (HBUINT32 *) loca_prime_data, num_offsets);
hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
entry_size * num_offsets,
@@ -89,8 +112,8 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s
loca_prime_data,
hb_free);
- bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
- && _add_head_and_set_loca_version (plan, use_short_loca);
+ bool result = c->plan->add_table (HB_OT_TAG_loca, loca_blob)
+ && _add_head_and_set_loca_version (c->plan, use_short_loca);
hb_blob_destroy (loca_blob);
return result;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
index dd08dda6ee..6300cf4be0 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
@@ -85,75 +85,72 @@ struct glyf
return_trace (false);
}
- glyf *glyf_prime = c->serializer->start_embed <glyf> ();
- if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
-
hb_font_t *font = nullptr;
if (c->plan->normalized_coords)
{
font = _create_font_for_instancing (c->plan);
- if (unlikely (!font)) return false;
+ if (unlikely (!font))
+ return_trace (false);
}
hb_vector_t<unsigned> padded_offsets;
- unsigned num_glyphs = c->plan->num_output_glyphs ();
- if (unlikely (!padded_offsets.resize (num_glyphs)))
- {
- hb_font_destroy (font);
- return false;
- }
+ if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true)))
+ return_trace (false);
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
if (!_populate_subset_glyphs (c->plan, font, glyphs))
{
hb_font_destroy (font);
- return false;
+ return_trace (false);
}
if (font)
hb_font_destroy (font);
unsigned max_offset = 0;
- for (unsigned i = 0; i < num_glyphs; i++)
+ for (auto &g : glyphs)
{
- padded_offsets[i] = glyphs[i].padded_size ();
- max_offset += padded_offsets[i];
+ unsigned size = g.padded_size ();
+ padded_offsets.push (size);
+ max_offset += size;
}
bool use_short_loca = false;
if (likely (!c->plan->force_long_loca))
use_short_loca = max_offset < 0x1FFFF;
- if (!use_short_loca) {
- for (unsigned i = 0; i < num_glyphs; i++)
- padded_offsets[i] = glyphs[i].length ();
+ if (!use_short_loca)
+ {
+ padded_offsets.resize (0);
+ for (auto &g : glyphs)
+ padded_offsets.push (g.length ());
}
- bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan);
+ auto *glyf_prime = c->serializer->start_embed <glyf> ();
+ bool result = glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
if (c->plan->normalized_coords && !c->plan->pinned_at_default)
_free_compiled_subset_glyphs (glyphs);
- if (!result) return false;
-
- if (unlikely (c->serializer->in_error ())) return_trace (false);
+ if (unlikely (!c->serializer->check_success (glyf_impl::_add_loca_and_head (c,
+ padded_offsets.iter (),
+ use_short_loca))))
+ return_trace (false);
- return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
- padded_offsets.iter (),
- use_short_loca)));
+ return result;
}
bool
_populate_subset_glyphs (const hb_subset_plan_t *plan,
hb_font_t *font,
- hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
+ hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const;
hb_font_t *
_create_font_for_instancing (const hb_subset_plan_t *plan) const;
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs) const
{
- for (unsigned i = 0; i < glyphs.length; i++)
- glyphs[i].free_compiled_bytes ();
+ for (auto &g : glyphs)
+ g.free_compiled_bytes ();
}
protected:
@@ -222,13 +219,14 @@ struct glyf_accelerator_t
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only)))
return false;
+ unsigned count = all_points.length;
+ assert (count >= glyf_impl::PHANTOM_COUNT);
+ count -= glyf_impl::PHANTOM_COUNT;
+
if (consumer.is_consuming_contour_points ())
{
- unsigned count = all_points.length;
- assert (count >= glyf_impl::PHANTOM_COUNT);
- count -= glyf_impl::PHANTOM_COUNT;
- for (unsigned point_index = 0; point_index < count; point_index++)
- consumer.consume_point (all_points[point_index]);
+ for (auto &point : all_points.as_array ().sub_array (0, count))
+ consumer.consume_point (point);
consumer.points_end ();
}
@@ -236,7 +234,7 @@ struct glyf_accelerator_t
contour_point_t *phantoms = consumer.get_phantoms_sink ();
if (phantoms)
for (unsigned i = 0; i < glyf_impl::PHANTOM_COUNT; ++i)
- phantoms[i] = all_points[all_points.length - glyf_impl::PHANTOM_COUNT + i];
+ phantoms[i] = all_points.arrayZ[count + i];
return true;
}
@@ -299,6 +297,7 @@ struct glyf_accelerator_t
if (extents) bounds = contour_bounds_t ();
}
+ HB_ALWAYS_INLINE
void consume_point (const contour_point_t &point) { bounds.add (point); }
void points_end () { bounds.get_extents (font, extents, scaled); }
@@ -431,16 +430,17 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
{
OT::glyf_accelerator_t glyf (plan->source);
- unsigned num_glyphs = plan->num_output_glyphs ();
- if (!glyphs.resize (num_glyphs)) return false;
+ if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false;
- for (auto p : plan->glyph_map->iter ())
+ for (const auto &pair : plan->new_to_old_gid_list)
{
- unsigned new_gid = p.second;
- glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid];
- subset_glyph.old_gid = p.first;
+ hb_codepoint_t new_gid = pair.first;
+ hb_codepoint_t old_gid = pair.second;
+ glyf_impl::SubsetGlyph *p = glyphs.push ();
+ glyf_impl::SubsetGlyph& subset_glyph = *p;
+ subset_glyph.old_gid = old_gid;
- if (unlikely (new_gid == 0 &&
+ if (unlikely (old_gid == 0 && new_gid == 0 &&
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
!plan->normalized_coords)
subset_glyph.source_glyph = glyf_impl::Glyph ();
@@ -487,7 +487,7 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
{
hb_variation_t var;
var.tag = _.first;
- var.value = _.second;
+ var.value = _.second.middle;
vars.push (var);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh
index f7f732d336..f550524503 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh
@@ -21,11 +21,11 @@ struct path_builder_t
operator bool () const { return has_data; }
bool has_data = false;
- float x = 0.;
- float y = 0.;
+ float x;
+ float y;
- optional_point_t lerp (optional_point_t p, float t)
- { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
+ optional_point_t mid (optional_point_t p)
+ { return optional_point_t ((x + p.x) * 0.5f, (y + p.y) * 0.5f); }
} first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2;
path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) :
@@ -37,6 +37,7 @@ struct path_builder_t
* https://stackoverflow.com/a/20772557
*
* Cubic support added. */
+ HB_ALWAYS_INLINE
void consume_point (const contour_point_t &point)
{
bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
@@ -46,7 +47,7 @@ struct path_builder_t
bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
#endif
optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
- if (!first_oncurve)
+ if (unlikely (!first_oncurve))
{
if (is_on_curve)
{
@@ -62,7 +63,7 @@ struct path_builder_t
}
else if (first_offcurve)
{
- optional_point_t mid = first_offcurve.lerp (p, .5f);
+ optional_point_t mid = first_offcurve.mid (p);
first_oncurve = mid;
last_offcurve = p;
draw_session->move_to (mid.x, mid.y);
@@ -98,7 +99,7 @@ struct path_builder_t
}
else
{
- optional_point_t mid = last_offcurve.lerp (p, .5f);
+ optional_point_t mid = last_offcurve.mid (p);
if (is_cubic)
{
@@ -123,13 +124,13 @@ struct path_builder_t
}
}
- if (point.is_end_point)
+ if (unlikely (point.is_end_point))
{
if (first_offcurve && last_offcurve)
{
- optional_point_t mid = last_offcurve.lerp (first_offcurve2 ?
- first_offcurve2 :
- first_offcurve, .5f);
+ optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
+ first_offcurve2 :
+ first_offcurve);
if (last_offcurve2)
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
last_offcurve.x, last_offcurve.y,
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh b/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh
index c1839f3b68..c8de101345 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh
@@ -359,7 +359,7 @@ struct name
record.nameID = ids.name_id;
record.length = 0; // handled in NameRecord copy()
record.offset = 0;
- memcpy (name_records, &record, NameRecord::static_size);
+ hb_memcpy (name_records, &record, NameRecord::static_size);
name_records++;
}
#endif
@@ -384,10 +384,7 @@ struct name
bool subset (hb_subset_context_t *c) const
{
- TRACE_SUBSET (this);
-
- name *name_prime = c->serializer->start_embed<name> ();
- if (unlikely (!name_prime)) return_trace (false);
+ auto *name_prime = c->serializer->start_embed<name> ();
#ifdef HB_EXPERIMENTAL_API
const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides =
@@ -436,7 +433,7 @@ struct name
if (!name_table_overrides->is_empty ())
{
if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population (), true)))
- return_trace (false);
+ return false;
for (const auto& record_ids : name_table_overrides->keys ())
{
if (name_table_overrides->get (record_ids).length == 0)
@@ -448,13 +445,13 @@ struct name
}
#endif
- return (name_prime->serialize (c->serializer, it,
- std::addressof (this + stringOffset)
+ return name_prime->serialize (c->serializer, it,
+ std::addressof (this + stringOffset)
#ifdef HB_EXPERIMENTAL_API
- , insert_name_records
- , name_table_overrides
+ , insert_name_records
+ , name_table_overrides
#endif
- ));
+ );
}
bool sanitize_records (hb_sanitize_context_t *c) const
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh
index c2e24a7067..c1432883ff 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh
@@ -72,7 +72,7 @@ struct ClassDef : public OT::ClassDef
class_def_link->width = SmallTypes::size;
class_def_link->objidx = class_def_prime_id;
class_def_link->position = link_position;
- class_def_prime_vertex.parents.push (parent_id);
+ class_def_prime_vertex.add_parent (parent_id);
return true;
}
@@ -94,7 +94,13 @@ struct ClassDef : public OT::ClassDef
}
hb_bytes_t class_def_copy = serializer.copy_bytes ();
- c.add_buffer ((char *) class_def_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
+ if (!class_def_copy.arrayZ) return false;
+ // Give ownership to the context, it will cleanup the buffer.
+ if (!c.add_buffer ((char *) class_def_copy.arrayZ))
+ {
+ hb_free ((char *) class_def_copy.arrayZ);
+ return false;
+ }
auto& obj = c.graph.vertices_[dest_obj].obj;
obj.head = (char *) class_def_copy.arrayZ;
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh
index 49d0936315..4f44e076d1 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh
@@ -96,7 +96,7 @@ struct Coverage : public OT::Layout::Common::Coverage
coverage_link->width = SmallTypes::size;
coverage_link->objidx = coverage_prime_id;
coverage_link->position = link_position;
- coverage_prime_vertex.parents.push (parent_id);
+ coverage_prime_vertex.add_parent (parent_id);
return (Coverage*) coverage_prime_vertex.obj.head;
}
@@ -118,7 +118,13 @@ struct Coverage : public OT::Layout::Common::Coverage
}
hb_bytes_t coverage_copy = serializer.copy_bytes ();
- c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
+ if (!coverage_copy.arrayZ) return false;
+ // Give ownership to the context, it will cleanup the buffer.
+ if (!c.add_buffer ((char *) coverage_copy.arrayZ))
+ {
+ hb_free ((char *) coverage_copy.arrayZ);
+ return false;
+ }
auto& obj = c.graph.vertices_[dest_obj].obj;
obj.head = (char *) coverage_copy.arrayZ;
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh
index 294a999918..0680958190 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh
@@ -43,12 +43,28 @@ struct graph_t
{
hb_serialize_context_t::object_t obj;
int64_t distance = 0 ;
- int64_t space = 0 ;
- hb_vector_t<unsigned> parents;
+ unsigned space = 0 ;
unsigned start = 0;
unsigned end = 0;
unsigned priority = 0;
-
+ private:
+ unsigned incoming_edges_ = 0;
+ unsigned single_parent = (unsigned) -1;
+ hb_hashmap_t<unsigned, unsigned> parents;
+ public:
+
+ auto parents_iter () const HB_AUTO_RETURN
+ (
+ hb_concat (
+ hb_iter (&single_parent, single_parent != (unsigned) -1),
+ parents.keys_ref ()
+ )
+ )
+
+ bool in_error () const
+ {
+ return parents.in_error ();
+ }
bool link_positions_valid (unsigned num_objects, bool removed_nil)
{
@@ -143,7 +159,9 @@ struct graph_t
hb_swap (a.obj, b.obj);
hb_swap (a.distance, b.distance);
hb_swap (a.space, b.space);
+ hb_swap (a.single_parent, b.single_parent);
hb_swap (a.parents, b.parents);
+ hb_swap (a.incoming_edges_, b.incoming_edges_);
hb_swap (a.start, b.start);
hb_swap (a.end, b.end);
hb_swap (a.priority, b.priority);
@@ -154,6 +172,7 @@ struct graph_t
{
hb_hashmap_t<unsigned, unsigned> result;
+ result.alloc (obj.real_links.length);
for (const auto& l : obj.real_links) {
result.set (l.position, l.objidx);
}
@@ -163,22 +182,76 @@ struct graph_t
bool is_shared () const
{
- return parents.length > 1;
+ return parents.get_population () > 1;
}
unsigned incoming_edges () const
{
- return parents.length;
+ if (HB_DEBUG_SUBSET_REPACK)
+ {
+ assert (incoming_edges_ == (single_parent != (unsigned) -1) +
+ (parents.values_ref () | hb_reduce (hb_add, 0)));
+ }
+ return incoming_edges_;
+ }
+
+ void reset_parents ()
+ {
+ incoming_edges_ = 0;
+ single_parent = (unsigned) -1;
+ parents.reset ();
+ }
+
+ void add_parent (unsigned parent_index)
+ {
+ assert (parent_index != (unsigned) -1);
+ if (incoming_edges_ == 0)
+ {
+ single_parent = parent_index;
+ incoming_edges_ = 1;
+ return;
+ }
+ else if (single_parent != (unsigned) -1)
+ {
+ assert (incoming_edges_ == 1);
+ if (!parents.set (single_parent, 1))
+ return;
+ single_parent = (unsigned) -1;
+ }
+
+ unsigned *v;
+ if (parents.has (parent_index, &v))
+ {
+ (*v)++;
+ incoming_edges_++;
+ }
+ else if (parents.set (parent_index, 1))
+ incoming_edges_++;
}
void remove_parent (unsigned parent_index)
{
- unsigned count = parents.length;
- for (unsigned i = 0; i < count; i++)
+ if (parent_index == single_parent)
{
- if (parents.arrayZ[i] != parent_index) continue;
- parents.remove_unordered (i);
- break;
+ single_parent = (unsigned) -1;
+ incoming_edges_--;
+ return;
+ }
+
+ unsigned *v;
+ if (parents.has (parent_index, &v))
+ {
+ incoming_edges_--;
+ if (*v > 1)
+ (*v)--;
+ else
+ parents.del (parent_index);
+
+ if (incoming_edges_ == 1)
+ {
+ single_parent = *parents.keys ();
+ parents.reset ();
+ }
}
}
@@ -199,20 +272,46 @@ struct graph_t
}
}
- void remap_parents (const hb_vector_t<unsigned>& id_map)
+ bool remap_parents (const hb_vector_t<unsigned>& id_map)
{
- unsigned count = parents.length;
- for (unsigned i = 0; i < count; i++)
- parents.arrayZ[i] = id_map[parents.arrayZ[i]];
+ if (single_parent != (unsigned) -1)
+ {
+ assert (single_parent < id_map.length);
+ single_parent = id_map[single_parent];
+ return true;
+ }
+
+ hb_hashmap_t<unsigned, unsigned> new_parents;
+ new_parents.alloc (parents.get_population ());
+ for (auto _ : parents)
+ {
+ assert (_.first < id_map.length);
+ assert (!new_parents.has (id_map[_.first]));
+ new_parents.set (id_map[_.first], _.second);
+ }
+
+ if (new_parents.in_error ())
+ return false;
+
+ parents = std::move (new_parents);
+ return true;
}
void remap_parent (unsigned old_index, unsigned new_index)
{
- unsigned count = parents.length;
- for (unsigned i = 0; i < count; i++)
+ if (single_parent != (unsigned) -1)
+ {
+ if (single_parent == old_index)
+ single_parent = new_index;
+ return;
+ }
+
+ const unsigned *pv;
+ if (parents.has (old_index, &pv))
{
- if (parents.arrayZ[i] == old_index)
- parents.arrayZ[i] = new_index;
+ unsigned v = *pv;
+ parents.set (new_index, v);
+ parents.del (old_index);
}
}
@@ -359,7 +458,6 @@ struct graph_t
~graph_t ()
{
- vertices_.fini ();
for (char* b : buffers)
hb_free (b);
}
@@ -401,9 +499,10 @@ struct graph_t
return vertices_[i].obj;
}
- void add_buffer (char* buffer)
+ bool add_buffer (char* buffer)
{
buffers.push (buffer);
+ return !buffers.in_error ();
}
/*
@@ -419,7 +518,7 @@ struct graph_t
link->width = 2;
link->objidx = child_id;
link->position = (char*) offset - (char*) v.obj.head;
- vertices_[child_id].parents.push (parent_id);
+ vertices_[child_id].add_parent (parent_id);
}
/*
@@ -465,7 +564,7 @@ struct graph_t
{
unsigned next_id = queue.pop_minimum().second;
- hb_swap (sorted_graph[new_id], vertices_[next_id]);
+ sorted_graph[new_id] = std::move (vertices_[next_id]);
const vertex_t& next = sorted_graph[new_id];
if (unlikely (!check_success(new_id >= 0))) {
@@ -493,8 +592,8 @@ struct graph_t
check_success (!queue.in_error ());
check_success (!sorted_graph.in_error ());
- remap_all_obj_indices (id_map, &sorted_graph);
- hb_swap (vertices_, sorted_graph);
+ check_success (remap_all_obj_indices (id_map, &sorted_graph));
+ vertices_ = std::move (sorted_graph);
if (!check_success (new_id == -1))
print_orphaned_nodes ();
@@ -605,7 +704,7 @@ struct graph_t
{
unsigned child_idx = index_for_offset (node_idx, offset);
auto& child = vertices_[child_idx];
- for (unsigned p : child.parents)
+ for (unsigned p : child.parents_iter ())
{
if (p != node_idx) {
return duplicate (node_idx, child_idx);
@@ -688,12 +787,15 @@ struct graph_t
subgraph.set (root_idx, wide_parents (root_idx, parents));
find_subgraph (root_idx, subgraph);
}
+ if (subgraph.in_error ())
+ return false;
unsigned original_root_idx = root_idx ();
hb_map_t index_map;
bool made_changes = false;
for (auto entry : subgraph.iter ())
{
+ assert (entry.first < vertices_.length);
const auto& node = vertices_[entry.first];
unsigned subgraph_incoming_edges = entry.second;
@@ -732,8 +834,7 @@ struct graph_t
remap_obj_indices (index_map, parents.iter (), true);
// Update roots set with new indices as needed.
- uint32_t next = HB_SET_VALUE_INVALID;
- while (roots.next (&next))
+ for (auto next : roots)
{
const uint32_t *v;
if (index_map.has (next, &v))
@@ -750,10 +851,10 @@ struct graph_t
{
for (const auto& link : vertices_[node_idx].obj.all_links ())
{
- const uint32_t *v;
+ hb_codepoint_t *v;
if (subgraph.has (link.objidx, &v))
{
- subgraph.set (link.objidx, *v + 1);
+ (*v)++;
continue;
}
subgraph.set (link.objidx, 1);
@@ -825,7 +926,7 @@ struct graph_t
new_link->position = (const char*) new_offset - (const char*) new_v.obj.head;
auto& child = vertices_[child_id];
- child.parents.push (new_parent_idx);
+ child.add_parent (new_parent_idx);
old_v.remove_real_link (child_id, old_offset);
child.remove_parent (old_parent_idx);
@@ -869,18 +970,18 @@ struct graph_t
clone->obj.tail = child.obj.tail;
clone->distance = child.distance;
clone->space = child.space;
- clone->parents.reset ();
+ clone->reset_parents ();
unsigned clone_idx = vertices_.length - 2;
for (const auto& l : child.obj.real_links)
{
clone->obj.real_links.push (l);
- vertices_[l.objidx].parents.push (clone_idx);
+ vertices_[l.objidx].add_parent (clone_idx);
}
for (const auto& l : child.obj.virtual_links)
{
clone->obj.virtual_links.push (l);
- vertices_[l.objidx].parents.push (clone_idx);
+ vertices_[l.objidx].add_parent (clone_idx);
}
check_success (!clone->obj.real_links.in_error ());
@@ -1009,13 +1110,13 @@ struct graph_t
{
update_parents();
- if (root().parents)
+ if (root().incoming_edges ())
// Root cannot have parents.
return false;
for (unsigned i = 0; i < root_idx (); i++)
{
- if (!vertices_[i].parents)
+ if (!vertices_[i].incoming_edges ())
return false;
}
return true;
@@ -1079,14 +1180,14 @@ struct graph_t
parents_invalid = true;
update_parents();
- if (root().parents) {
+ if (root().incoming_edges ()) {
DEBUG_MSG (SUBSET_REPACK, nullptr, "Root node has incoming edges.");
}
for (unsigned i = 0; i < root_idx (); i++)
{
const auto& v = vertices_[i];
- if (!v.parents)
+ if (!v.incoming_edges ())
DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i);
}
}
@@ -1118,6 +1219,8 @@ struct graph_t
unsigned space_for (unsigned index, unsigned* root = nullptr) const
{
+ loop:
+ assert (index < vertices_.length);
const auto& node = vertices_[index];
if (node.space)
{
@@ -1126,14 +1229,15 @@ struct graph_t
return node.space;
}
- if (!node.parents)
+ if (!node.incoming_edges ())
{
if (root)
*root = index;
return 0;
}
- return space_for (node.parents[0], root);
+ index = *node.parents_iter ();
+ goto loop;
}
void err_other_error () { this->successful = false; }
@@ -1157,12 +1261,8 @@ struct graph_t
unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
{
unsigned count = 0;
- hb_set_t visited;
- for (unsigned p : vertices_[node_idx].parents)
+ for (unsigned p : vertices_[node_idx].parents_iter ())
{
- if (visited.has (p)) continue;
- visited.add (p);
-
// Only real links can be wide
for (const auto& l : vertices_[p].obj.real_links)
{
@@ -1192,20 +1292,18 @@ struct graph_t
unsigned count = vertices_.length;
for (unsigned i = 0; i < count; i++)
- vertices_.arrayZ[i].parents.reset ();
+ vertices_.arrayZ[i].reset_parents ();
for (unsigned p = 0; p < count; p++)
{
for (auto& l : vertices_.arrayZ[p].obj.all_links ())
- {
- vertices_[l.objidx].parents.push (p);
- }
+ vertices_[l.objidx].add_parent (p);
}
for (unsigned i = 0; i < count; i++)
// parents arrays must be accurate or downstream operations like cycle detection
// and sorting won't work correctly.
- check_success (!vertices_.arrayZ[i].parents.in_error ());
+ check_success (!vertices_.arrayZ[i].in_error ());
parents_invalid = false;
}
@@ -1249,12 +1347,8 @@ struct graph_t
// (such as a fibonacci queue) with a fast decrease priority.
unsigned count = vertices_.length;
for (unsigned i = 0; i < count; i++)
- {
- if (i == vertices_.length - 1)
- vertices_.arrayZ[i].distance = 0;
- else
- vertices_.arrayZ[i].distance = hb_int_max (int64_t);
- }
+ vertices_.arrayZ[i].distance = hb_int_max (int64_t);
+ vertices_.tail ().distance = 0;
hb_priority_queue_t queue;
queue.insert (0, vertices_.length - 1);
@@ -1274,15 +1368,15 @@ struct graph_t
{
if (visited[link.objidx]) continue;
- const auto& child = vertices_[link.objidx].obj;
+ const auto& child = vertices_.arrayZ[link.objidx].obj;
unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
int64_t child_weight = (child.tail - child.head) +
- ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
+ ((int64_t) 1 << (link_width * 8)) * (vertices_.arrayZ[link.objidx].space + 1);
int64_t child_distance = next_distance + child_weight;
- if (child_distance < vertices_[link.objidx].distance)
+ if (child_distance < vertices_.arrayZ[link.objidx].distance)
{
- vertices_[link.objidx].distance = child_distance;
+ vertices_.arrayZ[link.objidx].distance = child_distance;
queue.insert (child_distance, link.objidx);
}
}
@@ -1310,7 +1404,7 @@ struct graph_t
unsigned old_idx = link.objidx;
link.objidx = new_idx;
vertices_[old_idx].remove_parent (parent_idx);
- vertices_[new_idx].parents.push (parent_idx);
+ vertices_[new_idx].add_parent (parent_idx);
}
/*
@@ -1338,18 +1432,20 @@ struct graph_t
/*
* Updates all objidx's in all links using the provided mapping.
*/
- void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
+ bool remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
hb_vector_t<vertex_t>* sorted_graph) const
{
unsigned count = sorted_graph->length;
for (unsigned i = 0; i < count; i++)
{
- (*sorted_graph)[i].remap_parents (id_map);
+ if (!(*sorted_graph)[i].remap_parents (id_map))
+ return false;
for (auto& link : sorted_graph->arrayZ[i].obj.all_links_writer ())
{
link.objidx = id_map[link.objidx];
}
}
+ return true;
}
/*
@@ -1380,7 +1476,7 @@ struct graph_t
for (const auto& l : v.obj.all_links ())
find_connected_nodes (l.objidx, targets, visited, connected);
- for (unsigned p : v.parents)
+ for (unsigned p : v.parents_iter ())
find_connected_nodes (p, targets, visited, connected);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc
index b2044426d4..d66eb49cfd 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc
+++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc
@@ -52,7 +52,11 @@ unsigned gsubgpos_graph_context_t::create_node (unsigned size)
if (!buffer)
return -1;
- add_buffer (buffer);
+ if (!add_buffer (buffer)) {
+ // Allocation did not get stored for freeing later.
+ hb_free (buffer);
+ return -1;
+ }
return graph.new_node (buffer, buffer + size);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh
index 9fe9662e64..26b7cfe4d4 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh
+++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh
@@ -47,9 +47,9 @@ struct gsubgpos_graph_context_t
HB_INTERNAL unsigned create_node (unsigned size);
- void add_buffer (char* buffer)
+ bool add_buffer (char* buffer)
{
- graph.add_buffer (buffer);
+ return graph.add_buffer (buffer);
}
private:
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh
index c170638409..303517f687 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh
@@ -166,7 +166,7 @@ struct Lookup : public OT::Lookup
}
if (all_new_subtables) {
- add_sub_tables (c, this_index, type, all_new_subtables);
+ return add_sub_tables (c, this_index, type, all_new_subtables);
}
return true;
@@ -184,7 +184,7 @@ struct Lookup : public OT::Lookup
return sub_table->split_subtables (c, parent_idx, objidx);
}
- void add_sub_tables (gsubgpos_graph_context_t& c,
+ bool add_sub_tables (gsubgpos_graph_context_t& c,
unsigned this_index,
unsigned type,
hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids)
@@ -200,7 +200,12 @@ struct Lookup : public OT::Lookup
size_t new_size = v.table_size ()
+ new_subtable_count * OT::Offset16::static_size;
char* buffer = (char*) hb_calloc (1, new_size);
- c.add_buffer (buffer);
+ if (!buffer) return false;
+ if (!c.add_buffer (buffer))
+ {
+ hb_free (buffer);
+ return false;
+ }
hb_memcpy (buffer, v.obj.head, v.table_size());
v.obj.head = buffer;
@@ -220,7 +225,7 @@ struct Lookup : public OT::Lookup
if (is_ext)
{
unsigned ext_id = create_extension_subtable (c, subtable_id, type);
- c.graph.vertices_[subtable_id].parents.push (ext_id);
+ c.graph.vertices_[subtable_id].add_parent (ext_id);
subtable_id = ext_id;
}
@@ -229,7 +234,7 @@ struct Lookup : public OT::Lookup
link->objidx = subtable_id;
link->position = (char*) &new_lookup->subTable[offset_index++] -
(char*) new_lookup;
- c.graph.vertices_[subtable_id].parents.push (this_index);
+ c.graph.vertices_[subtable_id].add_parent (this_index);
}
}
@@ -239,6 +244,7 @@ struct Lookup : public OT::Lookup
// The head location of the lookup has changed, invalidating the lookups map entry
// in the context. Update the map.
c.lookups.set (this_index, new_lookup);
+ return true;
}
void fix_existing_subtable_links (gsubgpos_graph_context_t& c,
@@ -309,7 +315,7 @@ struct Lookup : public OT::Lookup
// Make extension point at the subtable.
auto& ext_vertex = c.graph.vertices_[ext_index];
auto& subtable_vertex = c.graph.vertices_[subtable_index];
- ext_vertex.parents.push (lookup_index);
+ ext_vertex.add_parent (lookup_index);
subtable_vertex.remap_parent (lookup_index, ext_index);
return true;
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh
index 1c13eb24f9..ad158cc9e8 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh
@@ -215,7 +215,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
auto gid_and_class =
+ coverage->iter ()
| hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
- return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1->get_class (gid));
+ return hb_codepoint_pair_t (gid, class_def_1->get_class (gid));
})
;
class_def_size_estimator_t estimator (gid_and_class);
@@ -386,14 +386,14 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
auto klass_map =
+ coverage_table->iter ()
| hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
- return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1_table->get_class (gid));
+ return hb_codepoint_pair_t (gid, class_def_1_table->get_class (gid));
})
| hb_filter ([&] (hb_codepoint_t klass) {
return klass >= start && klass < end;
}, hb_second)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, hb_codepoint_t> gid_and_class) {
+ | hb_map_retains_sorting ([&] (hb_codepoint_pair_t gid_and_class) {
// Classes must be from 0...N so subtract start
- return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid_and_class.first, gid_and_class.second - start);
+ return hb_codepoint_pair_t (gid_and_class.first, gid_and_class.second - start);
})
;
@@ -419,7 +419,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
class_def_link->width = SmallTypes::size;
class_def_link->objidx = class_def_2_id;
class_def_link->position = 10;
- graph.vertices_[class_def_2_id].parents.push (pair_pos_prime_id);
+ graph.vertices_[class_def_2_id].add_parent (pair_pos_prime_id);
graph.duplicate (pair_pos_prime_id, class_def_2_id);
return pair_pos_prime_id;
@@ -519,7 +519,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
auto klass_map =
+ coverage.table->iter ()
| hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
- return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1.table->get_class (gid));
+ return hb_codepoint_pair_t (gid, class_def_1.table->get_class (gid));
})
| hb_filter ([&] (hb_codepoint_t klass) {
return klass < count;
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh
index 2e0b845baa..06e4bf44d8 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh
@@ -226,6 +226,9 @@ inline hb_blob_t* serialize (const graph_t& graph)
{
hb_vector_t<char> buffer;
size_t size = graph.total_size_in_bytes ();
+
+ if (!size) return hb_blob_get_empty ();
+
if (!buffer.alloc (size)) {
DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
return nullptr;
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc
index 55854ff5c2..266be5e2d4 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc
+++ b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc
@@ -27,7 +27,7 @@
#include "gsubgpos-context.hh"
#include "classdef-graph.hh"
-typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> gid_and_class_t;
+typedef hb_codepoint_pair_t gid_and_class_t;
typedef hb_vector_t<gid_and_class_t> gid_and_class_list_t;
diff --git a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
index d7e8a93f39..26e2bc1450 100644
--- a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
+++ b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
@@ -58,3 +58,5 @@
#include "hb-ucd.cc"
#include "hb-unicode.cc"
#include "hb-uniscribe.cc"
+#include "hb-wasm-api.cc"
+#include "hb-wasm-shape.cc"
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh
index 2ba9355b06..c72c0865d3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh
@@ -111,13 +111,13 @@ struct TrackData
break;
}
}
- if (!trackTableEntry) return 0.;
+ if (!trackTableEntry) return 0;
/*
* Choose size.
*/
unsigned int sizes = nSizes;
- if (!sizes) return 0.;
+ if (!sizes) return 0;
if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
index da383e050a..6cabc7fb02 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
@@ -87,6 +87,19 @@ static inline constexpr uint16_t hb_uint16_swap (uint16_t v)
static inline constexpr uint32_t hb_uint32_swap (uint32_t v)
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
+#ifndef HB_FAST_INT_ACCESS
+#if defined(__OPTIMIZE__) && \
+ defined(__BYTE_ORDER) && \
+ (__BYTE_ORDER == __BIG_ENDIAN || \
+ (__BYTE_ORDER == __LITTLE_ENDIAN && \
+ hb_has_builtin(__builtin_bswap16) && \
+ hb_has_builtin(__builtin_bswap32)))
+#define HB_FAST_INT_ACCESS 1
+#else
+#define HB_FAST_INT_ACCESS 0
+#endif
+#endif
+
template <typename Type, int Bytes = sizeof (Type)>
struct BEInt;
template <typename Type>
@@ -101,21 +114,25 @@ struct BEInt<Type, 1>
template <typename Type>
struct BEInt<Type, 2>
{
+ struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
+
public:
BEInt () = default;
- constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF),
- uint8_t ((V ) & 0xFF)} {}
- struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
- constexpr operator Type () const
- {
-#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
- defined(__BYTE_ORDER) && \
- (__BYTE_ORDER == __BIG_ENDIAN || \
- (__BYTE_ORDER == __LITTLE_ENDIAN && \
- hb_has_builtin(__builtin_bswap16)))
- /* Spoon-feed the compiler a big-endian integer with alignment 1.
- * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+ BEInt (Type V)
+#if HB_FAST_INT_ACCESS
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ { ((packed_uint16_t *) v)->v = __builtin_bswap16 (V); }
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+ { ((packed_uint16_t *) v)->v = V; }
+#endif
+#else
+ : v {uint8_t ((V >> 8) & 0xFF),
+ uint8_t ((V ) & 0xFF)} {}
+#endif
+
+ constexpr operator Type () const {
+#if HB_FAST_INT_ACCESS
#if __BYTE_ORDER == __LITTLE_ENDIAN
return __builtin_bswap16 (((packed_uint16_t *) v)->v);
#else /* __BYTE_ORDER == __BIG_ENDIAN */
@@ -146,22 +163,27 @@ struct BEInt<Type, 3>
template <typename Type>
struct BEInt<Type, 4>
{
+ struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+
public:
BEInt () = default;
- constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF),
- uint8_t ((V >> 16) & 0xFF),
- uint8_t ((V >> 8) & 0xFF),
- uint8_t ((V ) & 0xFF)} {}
- struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+ BEInt (Type V)
+#if HB_FAST_INT_ACCESS
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ { ((packed_uint32_t *) v)->v = __builtin_bswap32 (V); }
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+ { ((packed_uint32_t *) v)->v = V; }
+#endif
+#else
+ : v {uint8_t ((V >> 24) & 0xFF),
+ uint8_t ((V >> 16) & 0xFF),
+ uint8_t ((V >> 8) & 0xFF),
+ uint8_t ((V ) & 0xFF)} {}
+#endif
+
constexpr operator Type () const {
-#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
- defined(__BYTE_ORDER) && \
- (__BYTE_ORDER == __BIG_ENDIAN || \
- (__BYTE_ORDER == __LITTLE_ENDIAN && \
- hb_has_builtin(__builtin_bswap32)))
- /* Spoon-feed the compiler a big-endian integer with alignment 1.
- * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+#if HB_FAST_INT_ACCESS
#if __BYTE_ORDER == __LITTLE_ENDIAN
return __builtin_bswap32 (((packed_uint32_t *) v)->v);
#else /* __BYTE_ORDER == __BIG_ENDIAN */
@@ -231,12 +253,119 @@ struct
}
HB_FUNCOBJ (hb_bool);
+
+/* The MIT License
+
+ Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+
+// Compression function for Merkle-Damgard construction.
+// This function is generated using the framework provided.
+#define mix(h) ( \
+ (void) ((h) ^= (h) >> 23), \
+ (void) ((h) *= 0x2127599bf4325c37ULL), \
+ (h) ^= (h) >> 47)
+
+static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
+{
+ struct __attribute__((packed)) packed_uint64_t { uint64_t v; };
+ const uint64_t m = 0x880355f21e6d1965ULL;
+ const packed_uint64_t *pos = (const packed_uint64_t *)buf;
+ const packed_uint64_t *end = pos + (len / 8);
+ const unsigned char *pos2;
+ uint64_t h = seed ^ (len * m);
+ uint64_t v;
+
+#ifndef HB_OPTIMIZE_SIZE
+ if (((uintptr_t) pos & 7) == 0)
+ {
+ while (pos != end)
+ {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ v = * (const uint64_t *) (pos++);
+#pragma GCC diagnostic pop
+ h ^= mix(v);
+ h *= m;
+ }
+ }
+ else
+#endif
+ {
+ while (pos != end)
+ {
+ v = pos++->v;
+ h ^= mix(v);
+ h *= m;
+ }
+ }
+
+ pos2 = (const unsigned char*)pos;
+ v = 0;
+
+ switch (len & 7) {
+ case 7: v ^= (uint64_t)pos2[6] << 48; HB_FALLTHROUGH;
+ case 6: v ^= (uint64_t)pos2[5] << 40; HB_FALLTHROUGH;
+ case 5: v ^= (uint64_t)pos2[4] << 32; HB_FALLTHROUGH;
+ case 4: v ^= (uint64_t)pos2[3] << 24; HB_FALLTHROUGH;
+ case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH;
+ case 2: v ^= (uint64_t)pos2[1] << 8; HB_FALLTHROUGH;
+ case 1: v ^= (uint64_t)pos2[0];
+ h ^= mix(v);
+ h *= m;
+ }
+
+ return mix(h);
+}
+
+static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
+{
+ // the following trick converts the 64-bit hashcode to Fermat
+ // residue, which shall retain information from both the higher
+ // and lower parts of hashcode.
+ uint64_t h = fasthash64(buf, len, seed);
+ return h - (h >> 32);
+}
+
struct
{
private:
template <typename T> constexpr auto
- impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
+ impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
+
+ // Horrible: std:hash() of integers seems to be identity in gcc / clang?!
+ // https://github.com/harfbuzz/harfbuzz/pull/4228
+ //
+ // For performance characteristics see:
+ // https://github.com/harfbuzz/harfbuzz/pull/4228#issuecomment-1565079537
+ template <typename T,
+ hb_enable_if (std::is_integral<T>::value && sizeof (T) <= sizeof (uint32_t))> constexpr auto
+ impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) v * 2654435761u /* Knuh's multiplicative hash */)
+ template <typename T,
+ hb_enable_if (std::is_integral<T>::value && sizeof (T) > sizeof (uint32_t))> constexpr auto
+ impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) (v ^ (v >> 32)) * 2654435761u /* Knuth's multiplicative hash */)
template <typename T> constexpr auto
impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
@@ -551,6 +680,8 @@ struct hb_pair_t
template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
+typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
+
struct
{
template <typename Pair> constexpr typename Pair::first_t
@@ -853,7 +984,7 @@ static inline void *
hb_memset (void *s, int c, unsigned int n)
{
/* It's illegal to pass NULL to memset(), even if n is zero. */
- if (unlikely (!n)) return 0;
+ if (unlikely (!n)) return s;
return memset (s, c, n);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-array.hh
index 1a22e15c0f..760f90259c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-array.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-array.hh
@@ -75,11 +75,25 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
*/
typedef Type& __item_t__;
static constexpr bool is_random_access_iterator = true;
+ static constexpr bool has_fast_len = true;
+ Type& __item__ () const
+ {
+ if (unlikely (!length)) return CrapOrNull (Type);
+ return *arrayZ;
+ }
Type& __item_at__ (unsigned i) const
{
if (unlikely (i >= length)) return CrapOrNull (Type);
return arrayZ[i];
}
+ void __next__ ()
+ {
+ if (unlikely (!length))
+ return;
+ length--;
+ backwards_length++;
+ arrayZ++;
+ }
void __forward__ (unsigned n)
{
if (unlikely (n > length))
@@ -88,6 +102,14 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
backwards_length += n;
arrayZ += n;
}
+ void __prev__ ()
+ {
+ if (unlikely (!backwards_length))
+ return;
+ length++;
+ backwards_length--;
+ arrayZ--;
+ }
void __rewind__ (unsigned n)
{
if (unlikely (n > backwards_length))
@@ -123,6 +145,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
uint32_t hash () const
{
// FNV-1a hash function
+ // https://github.com/harfbuzz/harfbuzz/pull/4228
uint32_t current = /*cbf29ce4*/0x84222325;
for (auto &v : *this)
{
@@ -326,6 +349,7 @@ struct hb_sorted_array_t :
HB_ITER_USING (iter_base_t);
static constexpr bool is_random_access_iterator = true;
static constexpr bool is_sorted_iterator = true;
+ static constexpr bool has_fast_len = true;
hb_sorted_array_t () = default;
hb_sorted_array_t (const hb_sorted_array_t&) = default;
@@ -453,55 +477,21 @@ inline bool hb_array_t<const unsigned char>::operator == (const hb_array_t<const
/* Specialize hash() for byte arrays. */
+#ifndef HB_OPTIMIZE_SIZE_MORE
template <>
inline uint32_t hb_array_t<const char>::hash () const
{
- // FNV-1a hash function
- uint32_t current = /*cbf29ce4*/0x84222325;
- unsigned i = 0;
-
-#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
- ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
- struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
- for (; i + 4 <= this->length; i += 4)
- {
- current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v);
- current = current * 16777619;
- }
-#endif
-
- for (; i < this->length; i++)
- {
- current = current ^ hb_hash (this->arrayZ[i]);
- current = current * 16777619;
- }
- return current;
+ // https://github.com/harfbuzz/harfbuzz/pull/4228
+ return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */);
}
template <>
inline uint32_t hb_array_t<const unsigned char>::hash () const
{
- // FNV-1a hash function
- uint32_t current = /*cbf29ce4*/0x84222325;
- unsigned i = 0;
-
-#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
- ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
- struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
- for (; i + 4 <= this->length; i += 4)
- {
- current = current ^ hb_hash ((uint32_t) ((const packed_uint32_t *) &this->arrayZ[i])->v);
- current = current * 16777619;
- }
-#endif
-
- for (; i < this->length; i++)
- {
- current = current ^ hb_hash (this->arrayZ[i]);
- current = current * 16777619;
- }
- return current;
+ // https://github.com/harfbuzz/harfbuzz/pull/4228
+ return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */);
}
+#endif
typedef hb_array_t<const char> hb_bytes_t;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
index a6283de140..303dfe6d04 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
@@ -204,6 +204,7 @@ struct hb_atomic_ptr_t
hb_atomic_ptr_t () = default;
constexpr hb_atomic_ptr_t (T* v) : v (v) {}
+ hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete;
void init (T* v_ = nullptr) { set_relaxed (v_); }
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
index 9edefd9710..64dbf2e869 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
@@ -39,10 +39,10 @@ struct hb_bimap_t
back_map.reset ();
}
- void resize (unsigned pop)
+ void alloc (unsigned pop)
{
- forw_map.resize (pop);
- back_map.resize (pop);
+ forw_map.alloc (pop);
+ back_map.alloc (pop);
}
bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
@@ -83,7 +83,6 @@ struct hb_bimap_t
unsigned int get_population () const { return forw_map.get_population (); }
-
protected:
hb_map_t forw_map;
hb_map_t back_map;
@@ -95,8 +94,30 @@ struct hb_bimap_t
};
/* Inremental bimap: only lhs is given, rhs is incrementally assigned */
-struct hb_inc_bimap_t : hb_bimap_t
+struct hb_inc_bimap_t
{
+ bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
+
+ unsigned int get_population () const { return forw_map.get_population (); }
+
+ void reset ()
+ {
+ forw_map.reset ();
+ back_map.reset ();
+ }
+
+ void alloc (unsigned pop)
+ {
+ forw_map.alloc (pop);
+ back_map.alloc (pop);
+ }
+
+ void clear ()
+ {
+ forw_map.clear ();
+ back_map.resize (0);
+ }
+
/* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
* Return the rhs value as the result.
*/
@@ -105,32 +126,42 @@ struct hb_inc_bimap_t : hb_bimap_t
hb_codepoint_t rhs = forw_map[lhs];
if (rhs == HB_MAP_VALUE_INVALID)
{
- rhs = next_value++;
- set (lhs, rhs);
+ rhs = back_map.length;
+ forw_map.set (lhs, rhs);
+ back_map.push (lhs);
}
return rhs;
}
hb_codepoint_t skip ()
- { return next_value++; }
+ {
+ hb_codepoint_t start = back_map.length;
+ back_map.push (HB_MAP_VALUE_INVALID);
+ return start;
+ }
hb_codepoint_t skip (unsigned count)
- { return next_value += count; }
+ {
+ hb_codepoint_t start = back_map.length;
+ back_map.alloc (back_map.length + count);
+ for (unsigned i = 0; i < count; i++)
+ back_map.push (HB_MAP_VALUE_INVALID);
+ return start;
+ }
hb_codepoint_t get_next_value () const
- { return next_value; }
+ { return back_map.length; }
void add_set (const hb_set_t *set)
{
- hb_codepoint_t i = HB_SET_VALUE_INVALID;
- while (hb_set_next (set, &i)) add (i);
+ for (auto i : *set) add (i);
}
/* Create an identity map. */
bool identity (unsigned int size)
{
clear ();
- for (hb_codepoint_t i = 0; i < size; i++) set (i, i);
+ for (hb_codepoint_t i = 0; i < size; i++) add (i);
return !in_error ();
}
@@ -145,20 +176,30 @@ struct hb_inc_bimap_t : hb_bimap_t
{
hb_codepoint_t count = get_population ();
hb_vector_t <hb_codepoint_t> work;
- work.resize (count);
+ if (unlikely (!work.resize (count, false))) return;
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
- work[rhs] = back_map[rhs];
+ work.arrayZ[rhs] = back_map[rhs];
work.qsort (cmp_id);
clear ();
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
- set (work[rhs], rhs);
+ add (work.arrayZ[rhs]);
}
+ hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
+ hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; }
+
+ hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
+ bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); }
+
protected:
- unsigned int next_value = 0;
+ hb_map_t forw_map;
+ hb_vector_t<hb_codepoint_t> back_map;
+
+ public:
+ auto keys () const HB_AUTO_RETURN (+ back_map.iter())
};
#endif /* HB_BIMAP_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
index 9b027ac590..e1826e12a5 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
@@ -89,14 +89,17 @@ struct hb_vector_size_t
struct hb_bit_page_t
{
- void init0 () { v.init0 (); }
- void init1 () { v.init1 (); }
+ void init0 () { v.init0 (); population = 0; }
+ void init1 () { v.init1 (); population = PAGE_BITS; }
+
+ void dirty () { population = UINT_MAX; }
static inline constexpr unsigned len ()
{ return ARRAY_LENGTH_CONST (v); }
bool is_empty () const
{
+ if (has_population ()) return !population;
return
+ hb_iter (v)
| hb_none
@@ -104,14 +107,11 @@ struct hb_bit_page_t
}
uint32_t hash () const
{
- return
- + hb_iter (v)
- | hb_reduce ([] (uint32_t h, const elt_t &_) { return h * 31 + hb_hash (_); }, (uint32_t) 0u)
- ;
+ return hb_bytes_t ((const char *) &v, sizeof (v)).hash ();
}
- void add (hb_codepoint_t g) { elt (g) |= mask (g); }
- void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
+ void add (hb_codepoint_t g) { elt (g) |= mask (g); dirty (); }
+ void del (hb_codepoint_t g) { elt (g) &= ~mask (g); dirty (); }
void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
@@ -123,20 +123,21 @@ struct hb_bit_page_t
*la |= (mask (b) << 1) - mask(a);
else
{
- *la |= ~(mask (a) - 1);
+ *la |= ~(mask (a) - 1llu);
la++;
hb_memset (la, 0xff, (char *) lb - (char *) la);
- *lb |= ((mask (b) << 1) - 1);
+ *lb |= ((mask (b) << 1) - 1llu);
}
+ dirty ();
}
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));
+ *la &= ~((mask (b) << 1llu) - mask(a));
else
{
*la &= mask (a) - 1;
@@ -144,8 +145,9 @@ struct hb_bit_page_t
hb_memset (la, 0, (char *) lb - (char *) la);
- *lb &= ~((mask (b) << 1) - 1);
+ *lb &= ~((mask (b) << 1) - 1llu);
}
+ dirty ();
}
void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
{ if (v) add_range (a, b); else del_range (a, b); }
@@ -225,18 +227,25 @@ struct hb_bit_page_t
}
bool is_subset (const hb_bit_page_t &larger_page) const
{
+ if (has_population () && larger_page.has_population () &&
+ population > larger_page.population)
+ return false;
+
for (unsigned i = 0; i < len (); i++)
if (~larger_page.v[i] & v[i])
return false;
return true;
}
+ bool has_population () const { return population != UINT_MAX; }
unsigned int get_population () const
{
- return
+ if (has_population ()) return population;
+ population =
+ hb_iter (v)
| hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u)
;
+ return population;
}
bool next (hb_codepoint_t *codepoint) const
@@ -332,9 +341,9 @@ struct hb_bit_page_t
const elt_t& elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
+ mutable unsigned population;
vector_t v;
};
-static_assert (hb_bit_page_t::PAGE_BITS == sizeof (hb_bit_page_t) * 8, "");
#endif /* HB_BIT_PAGE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh
index 1eb1b1c209..e765a479ae 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh
@@ -136,7 +136,7 @@ struct hb_bit_set_invertible_t
/* Sink interface. */
hb_bit_set_invertible_t& operator << (hb_codepoint_t v)
{ add (v); return *this; }
- hb_bit_set_invertible_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+ hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range)
{ add_range (range.first, range.second); return *this; }
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
@@ -162,7 +162,7 @@ struct hb_bit_set_invertible_t
auto it1 = iter ();
auto it2 = other.iter ();
return hb_all (+ hb_zip (it1, it2)
- | hb_map ([](hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) { return _.first == _.second; }));
+ | hb_map ([](hb_codepoint_pair_t _) { return _.first == _.second; }));
}
}
@@ -345,6 +345,7 @@ struct hb_bit_set_invertible_t
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
{
static constexpr bool is_sorted_iterator = true;
+ static constexpr bool has_fast_len = true;
iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t),
bool init = true) : s (&s_), v (INVALID), l(0)
{
@@ -363,7 +364,7 @@ struct hb_bit_set_invertible_t
unsigned __len__ () const { return l; }
iter_t end () const { return iter_t (*s, false); }
bool operator != (const iter_t& o) const
- { return s != o.s || v != o.v; }
+ { return v != o.v || s != o.s; }
protected:
const hb_bit_set_invertible_t *s;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
index d290f6114c..9e60cb934a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
@@ -30,7 +30,6 @@
#include "hb.hh"
#include "hb-bit-page.hh"
-#include "hb-machinery.hh"
struct hb_bit_set_t
@@ -134,7 +133,11 @@ struct hb_bit_set_t
{
uint32_t h = 0;
for (auto &map : page_map)
- h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]);
+ {
+ auto &page = pages.arrayZ[map.index];
+ if (unlikely (page.is_empty ())) continue;
+ h = h * 31 + hb_hash (map.major) + hb_hash (page);
+ }
return h;
}
@@ -179,6 +182,16 @@ struct hb_bit_set_t
return true;
}
+ /* Duplicated here from hb-machinery.hh to avoid including it. */
+ template<typename Type>
+ static inline const Type& StructAtOffsetUnaligned(const void *P, unsigned int offset)
+ {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ return * reinterpret_cast<const Type*> ((const char *) P + offset);
+#pragma GCC diagnostic pop
+ }
+
template <typename T>
void set_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
@@ -342,7 +355,7 @@ struct hb_bit_set_t
/* Sink interface. */
hb_bit_set_t& operator << (hb_codepoint_t v)
{ add (v); return *this; }
- hb_bit_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+ hb_bit_set_t& operator << (const hb_codepoint_pair_t& range)
{ add_range (range.first, range.second); return *this; }
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
@@ -549,6 +562,7 @@ struct hb_bit_set_t
count--;
page_map.arrayZ[count] = page_map.arrayZ[a];
page_at (count).v = op (page_at (a).v, other.page_at (b).v);
+ page_at (count).dirty ();
}
else if (page_map.arrayZ[a - 1].major > other.page_map.arrayZ[b - 1].major)
{
@@ -567,7 +581,7 @@ struct hb_bit_set_t
count--;
page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
page_map.arrayZ[count].index = next_page++;
- page_at (count).v = other.page_at (b).v;
+ page_at (count) = other.page_at (b);
}
}
}
@@ -585,7 +599,7 @@ struct hb_bit_set_t
count--;
page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
page_map.arrayZ[count].index = next_page++;
- page_at (count).v = other.page_at (b).v;
+ page_at (count) = other.page_at (b);
}
assert (!count);
resize (newCount);
@@ -862,6 +876,7 @@ struct hb_bit_set_t
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
{
static constexpr bool is_sorted_iterator = true;
+ static constexpr bool has_fast_len = true;
iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t),
bool init = true) : s (&s_), v (INVALID), l(0)
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
index f111b2d8dc..15a53919de 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
@@ -162,14 +162,8 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
hb_buffer_set_flags (fragment, flags);
hb_buffer_append (fragment, text_buffer, text_start, text_end);
- if (!hb_shape_full (font, fragment, features, num_features, shapers))
- {
- buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
- hb_buffer_destroy (reconstruction);
- hb_buffer_destroy (fragment);
- return false;
- }
- else if (!fragment->successful || fragment->shaping_failed)
+ if (!hb_shape_full (font, fragment, features, num_features, shapers) ||
+ fragment->successful || fragment->shaping_failed)
{
hb_buffer_destroy (reconstruction);
hb_buffer_destroy (fragment);
@@ -185,15 +179,18 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
}
bool ret = true;
- hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
- if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
+ if (likely (reconstruction->successful))
{
- buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed.");
- ret = false;
+ hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+ if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed.");
+ ret = false;
- /* Return the reconstructed result instead so it can be inspected. */
- hb_buffer_set_length (buffer, 0);
- hb_buffer_append (buffer, reconstruction, 0, -1);
+ /* Return the reconstructed result instead so it can be inspected. */
+ hb_buffer_set_length (buffer, 0);
+ hb_buffer_append (buffer, reconstruction, 0, -1);
+ }
}
hb_buffer_destroy (reconstruction);
@@ -316,28 +313,13 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
/*
* Shape the two fragment streams.
*/
- if (!hb_shape_full (font, fragments[0], features, num_features, shapers))
- {
- buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
- ret = false;
- goto out;
- }
- else if (!fragments[0]->successful || fragments[0]->shaping_failed)
- {
- ret = true;
- goto out;
- }
- if (!hb_shape_full (font, fragments[1], features, num_features, shapers))
- {
- buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
- ret = false;
+ if (!hb_shape_full (font, fragments[0], features, num_features, shapers) ||
+ !fragments[0]->successful || fragments[0]->shaping_failed)
goto out;
- }
- else if (!fragments[1]->successful || fragments[1]->shaping_failed)
- {
- ret = true;
+
+ if (!hb_shape_full (font, fragments[1], features, num_features, shapers) ||
+ !fragments[1]->successful || fragments[1]->shaping_failed)
goto out;
- }
if (!forward)
{
@@ -377,21 +359,23 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
hb_buffer_reverse (reconstruction);
}
- /*
- * Diff results.
- */
- diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
- if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
+ if (likely (reconstruction->successful))
{
- buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed.");
- ret = false;
+ /*
+ * Diff results.
+ */
+ diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+ if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed.");
+ ret = false;
- /* Return the reconstructed result instead so it can be inspected. */
- hb_buffer_set_length (buffer, 0);
- hb_buffer_append (buffer, reconstruction, 0, -1);
+ /* Return the reconstructed result instead so it can be inspected. */
+ hb_buffer_set_length (buffer, 0);
+ hb_buffer_append (buffer, reconstruction, 0, -1);
+ }
}
-
out:
hb_buffer_destroy (reconstruction);
hb_buffer_destroy (fragments[0]);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
index ace2a104fd..749ef9bd49 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
@@ -499,12 +499,12 @@ hb_buffer_t::set_masks (hb_mask_t value,
unsigned int cluster_start,
unsigned int cluster_end)
{
- hb_mask_t not_mask = ~mask;
- value &= mask;
-
if (!mask)
return;
+ hb_mask_t not_mask = ~mask;
+ value &= mask;
+
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
index 7a97fc7168..f04ad58f11 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
@@ -464,13 +464,16 @@ struct hb_buffer_t
start, end,
true);
}
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
{
if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
return;
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
- true);
+ false);
}
void unsafe_to_break_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
{
@@ -478,6 +481,9 @@ struct hb_buffer_t
start, end,
true, true);
}
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
{
if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
@@ -493,6 +499,13 @@ struct hb_buffer_t
HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size);
+ HB_NODISCARD bool resize (unsigned length)
+ {
+ assert (!have_output);
+ if (unlikely (!ensure (length))) return false;
+ len = length;
+ return true;
+ }
HB_NODISCARD bool ensure (unsigned int size)
{ return likely (!size || size < allocated) ? true : enlarge (size); }
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh
index 8371465c6c..6d8a54cf10 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh
@@ -62,14 +62,12 @@ struct hb_cache_t
static_assert ((key_bits >= cache_bits), "");
static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), "");
- hb_cache_t () { init (); }
-
- void init () { clear (); }
+ hb_cache_t () { clear (); }
void clear ()
{
- for (unsigned i = 0; i < ARRAY_LENGTH (values); i++)
- values[i] = -1;
+ for (auto &v : values)
+ v = -1;
}
bool get (unsigned int key, unsigned int *value) const
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc
index 0f94d8169f..ec1499e861 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc
@@ -80,7 +80,7 @@ hb_cairo_read_blob (void *closure,
if (r->offset + length > size)
return CAIRO_STATUS_READ_ERROR;
- memcpy (data, d + r->offset, length);
+ hb_memcpy (data, d + r->offset, length);
r->offset += length;
return CAIRO_STATUS_SUCCESS;
@@ -763,7 +763,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
}
//assert (angles[0] + k * span <= 0 && 0 < angles[n_stops - 1] + k * span);
- span = fabs (span);
+ span = fabsf (span);
for (signed l = k; l < 1000; l++)
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc b/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc
index f005afd17e..68c7bc064f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc
@@ -956,7 +956,7 @@ hb_cairo_glyphs_from_buffer (hb_buffer_t *buffer,
if (clusters && *num_clusters && utf8)
{
- memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0]));
+ hb_memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0]));
hb_bool_t backward = HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (buffer));
*cluster_flags = backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : (cairo_text_cluster_flags_t) 0;
unsigned int cluster = 0;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
index 949bfebf9b..1d1f10f2bf 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
@@ -26,6 +26,8 @@
#ifndef HB_CFF_INTERP_COMMON_HH
#define HB_CFF_INTERP_COMMON_HH
+extern HB_INTERNAL const unsigned char *endchar_str;
+
namespace CFF {
using namespace OT;
@@ -336,8 +338,6 @@ struct byte_str_ref_t
hb_ubytes_t str;
};
-using byte_str_array_t = hb_vector_t<hb_ubytes_t>;
-
/* stack */
template <typename ELEM, int LIMIT>
struct cff_stack_t
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh
index f40be51f0d..28a777eb0d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh
@@ -883,14 +883,12 @@ struct cs_interpreter_t : interpreter_t<ENV>
unsigned max_ops = HB_CFF_MAX_OPS;
for (;;) {
- if (unlikely (!--max_ops))
+ OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
+ if (unlikely (SUPER::env.in_error () || !--max_ops))
{
SUPER::env.set_error ();
- break;
- }
- OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
- if (unlikely (SUPER::env.in_error ()))
return false;
+ }
if (SUPER::env.is_endchar ())
break;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h
index a5da4e76a3..a9fe666b39 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-common.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h
@@ -104,6 +104,16 @@ typedef int hb_bool_t;
*
**/
typedef uint32_t hb_codepoint_t;
+
+/**
+ * HB_CODEPOINT_INVALID:
+ *
+ * Unused #hb_codepoint_t value.
+ *
+ * Since: 8.0.0
+ */
+#define HB_CODEPOINT_INVALID ((hb_codepoint_t) -1)
+
/**
* hb_position_t:
*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-config.hh b/src/3rdparty/harfbuzz-ng/src/hb-config.hh
index 26f7cba83e..816c55c7d3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-config.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-config.hh
@@ -113,7 +113,6 @@
/* Closure of options. */
#ifdef HB_NO_BORING_EXPANSION
-#define HB_NO_AVAR2
#define HB_NO_BEYOND_64K
#define HB_NO_CUBIC_GLYF
#define HB_NO_VAR_COMPOSITES
@@ -184,7 +183,7 @@
#endif
#ifdef HB_OPTIMIZE_SIZE_MORE
-#define HB_NO_OT_LIGATURES_FAST_PATH
+#define HB_NO_OT_RULESETS_FAST_PATH
#endif
#ifdef HB_MINIMIZE_MEMORY_USAGE
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
index 0ac4515fa8..6055fce962 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
@@ -389,6 +389,10 @@ struct hb_no_trace_t {
#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
#endif
+#ifndef HB_DEBUG_WASM
+#define HB_DEBUG_WASM (HB_DEBUG+0)
+#endif
+
/*
* With tracing.
*/
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h
index b032a941b2..9fcce6d9ac 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h
@@ -255,6 +255,52 @@ HB_EXTERN hb_position_t
hb_font_get_glyph_v_kerning (hb_font_t *font,
hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
+
+/**
+ * hb_font_get_glyph_shape_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @draw_funcs: The draw functions to send the shape data to
+ * @draw_data: The data accompanying the draw functions
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
+ *
+ * Since: 4.0.0
+ * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead
+ **/
+typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data);
+
+/**
+ * hb_font_funcs_set_glyph_shape_func:
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets the implementation function for #hb_font_get_glyph_shape_func_t,
+ * which is the same as #hb_font_draw_glyph_func_t.
+ *
+ * Since: 4.0.0
+ * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead
+ **/
+HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func)
+HB_EXTERN void
+hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_shape_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
+HB_DEPRECATED_FOR (hb_font_draw_glyph)
+HB_EXTERN void
+hb_font_get_glyph_shape (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data);
+
+
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-draw.hh b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh
index 768f51a875..25dee1261e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-draw.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh
@@ -93,50 +93,57 @@ struct hb_draw_funcs_t
!user_data ? nullptr : user_data->close_path); }
- void move_to (void *draw_data, hb_draw_state_t &st,
- float to_x, float to_y)
+ void
+ HB_ALWAYS_INLINE
+ move_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
{
- if (st.path_open) close_path (draw_data, st);
+ if (unlikely (st.path_open)) close_path (draw_data, st);
st.current_x = to_x;
st.current_y = to_y;
}
- void line_to (void *draw_data, hb_draw_state_t &st,
- float to_x, float to_y)
+ void
+ HB_ALWAYS_INLINE
+ line_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
{
- if (!st.path_open) start_path (draw_data, st);
+ if (unlikely (!st.path_open)) start_path (draw_data, st);
emit_line_to (draw_data, st, to_x, to_y);
st.current_x = to_x;
st.current_y = to_y;
}
void
+ HB_ALWAYS_INLINE
quadratic_to (void *draw_data, hb_draw_state_t &st,
float control_x, float control_y,
float to_x, float to_y)
{
- if (!st.path_open) start_path (draw_data, st);
+ if (unlikely (!st.path_open)) start_path (draw_data, st);
emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
st.current_x = to_x;
st.current_y = to_y;
}
void
+ HB_ALWAYS_INLINE
cubic_to (void *draw_data, hb_draw_state_t &st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y)
{
- if (!st.path_open) start_path (draw_data, st);
+ if (unlikely (!st.path_open)) start_path (draw_data, st);
emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
st.current_x = to_x;
st.current_y = to_y;
}
void
+ HB_ALWAYS_INLINE
close_path (void *draw_data, hb_draw_state_t &st)
{
- if (st.path_open)
+ if (likely (st.path_open))
{
if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y))
emit_line_to (draw_data, st, st.path_start_x, st.path_start_y);
@@ -168,6 +175,7 @@ struct hb_draw_session_t
~hb_draw_session_t () { close_path (); }
+ HB_ALWAYS_INLINE
void move_to (float to_x, float to_y)
{
if (likely (not_slanted))
@@ -177,6 +185,7 @@ struct hb_draw_session_t
funcs->move_to (draw_data, st,
to_x + to_y * slant, to_y);
}
+ HB_ALWAYS_INLINE
void line_to (float to_x, float to_y)
{
if (likely (not_slanted))
@@ -187,6 +196,7 @@ struct hb_draw_session_t
to_x + to_y * slant, to_y);
}
void
+ HB_ALWAYS_INLINE
quadratic_to (float control_x, float control_y,
float to_x, float to_y)
{
@@ -200,6 +210,7 @@ struct hb_draw_session_t
to_x + to_y * slant, to_y);
}
void
+ HB_ALWAYS_INLINE
cubic_to (float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y)
@@ -215,6 +226,7 @@ struct hb_draw_session_t
control2_x + control2_y * slant, control2_y,
to_x + to_y * slant, to_y);
}
+ HB_ALWAYS_INLINE
void close_path ()
{
funcs->close_path (draw_data, st);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-font.cc
index 688513112a..f062bfaf75 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-font.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-font.cc
@@ -1389,6 +1389,7 @@ hb_font_get_glyph_from_name (hb_font_t *font,
return font->get_glyph_from_name (name, len, glyph);
}
+#ifndef HB_DISABLE_DEPRECATED
/**
* hb_font_get_glyph_shape:
* @font: #hb_font_t to work upon
@@ -1410,6 +1411,7 @@ hb_font_get_glyph_shape (hb_font_t *font,
{
hb_font_draw_glyph (font, glyph, dfuncs, draw_data);
}
+#endif
/**
* hb_font_draw_glyph:
@@ -2648,7 +2650,6 @@ hb_font_set_variations (hb_font_t *font,
if (axes[axis_index].axisTag == tag)
design_coords[axis_index] = v;
}
- font->face->table.avar->map_coords (normalized, coords_length);
hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized);
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
@@ -2720,8 +2721,6 @@ hb_font_set_variation (hb_font_t *font,
if (axes[axis_index].axisTag == tag)
design_coords[axis_index] = value;
- font->face->table.avar->map_coords (normalized, coords_length);
-
hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized);
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
@@ -3058,6 +3057,7 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
#endif
+#ifndef HB_DISABLE_DEPRECATED
void
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_shape_func_t func,
@@ -3066,3 +3066,4 @@ hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
{
hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
}
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.h b/src/3rdparty/harfbuzz-ng/src/hb-font.h
index f3b589bd0d..3c2355af2d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-font.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-font.h
@@ -486,25 +486,6 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
void *user_data);
/**
- * hb_font_get_glyph_shape_func_t:
- * @font: #hb_font_t to work upon
- * @font_data: @font user data pointer
- * @glyph: The glyph ID to query
- * @draw_funcs: The draw functions to send the shape data to
- * @draw_data: The data accompanying the draw functions
- * @user_data: User data pointer passed by the caller
- *
- * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
- *
- * Since: 4.0.0
- * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead
- **/
-typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- hb_draw_funcs_t *draw_funcs, void *draw_data,
- void *user_data);
-
-/**
* hb_font_draw_glyph_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
@@ -804,32 +785,13 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
void *user_data, hb_destroy_func_t destroy);
/**
- * hb_font_funcs_set_glyph_shape_func:
- * @ffuncs: A font-function structure
- * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
- * @user_data: Data to pass to @func
- * @destroy: (nullable): The function to call when @user_data is not needed anymore
- *
- * Sets the implementation function for #hb_font_get_glyph_shape_func_t,
- * which is the same as #hb_font_draw_glyph_func_t.
- *
- * Since: 4.0.0
- * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_shape_func_t func,
- void *user_data, hb_destroy_func_t destroy);
-
-/**
* hb_font_funcs_set_draw_glyph_func:
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore
*
- * Sets the implementation function for #hb_font_draw_glyph_func_t,
- * which is the same as #hb_font_get_glyph_shape_func_t.
+ * Sets the implementation function for #hb_font_draw_glyph_func_t.
*
* Since: 7.0.0
**/
@@ -935,11 +897,6 @@ hb_font_get_glyph_from_name (hb_font_t *font,
hb_codepoint_t *glyph);
HB_EXTERN void
-hb_font_get_glyph_shape (hb_font_t *font,
- hb_codepoint_t glyph,
- hb_draw_funcs_t *dfuncs, void *draw_data);
-
-HB_EXTERN void
hb_font_draw_glyph (hb_font_t *font,
hb_codepoint_t glyph,
hb_draw_funcs_t *dfuncs, void *draw_data);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
index 1105862fbc..6ca3f85465 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
@@ -114,7 +114,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
ft_font->cached_serial = (unsigned) -1;
- ft_font->advance_cache.init ();
+ new (&ft_font->advance_cache) hb_ft_advance_cache_t;
return ft_font;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc
index 332cc84888..d66de0b237 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc
@@ -29,7 +29,7 @@
#ifdef HAVE_GOBJECT
-/**
+/*
* SECTION:hb-gobject
* @title: hb-gobject
* @short_description: GObject integration support
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
index 9e068f8d84..7ea0386223 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
@@ -248,6 +248,21 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
gr_fref_set_feature_value (fref, features[i].value, feats);
}
+ hb_direction_t direction = buffer->props.direction;
+ hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script);
+ /* TODO vertical:
+ * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
+ * Ogham fonts are supposed to be implemented BTT or not. Need to research that
+ * first. */
+ if ((HB_DIRECTION_IS_HORIZONTAL (direction) &&
+ direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) ||
+ (HB_DIRECTION_IS_VERTICAL (direction) &&
+ direction != HB_DIRECTION_TTB))
+ {
+ hb_buffer_reverse_clusters (buffer);
+ direction = HB_DIRECTION_REVERSE (direction);
+ }
+
gr_segment *seg = nullptr;
const gr_slot *is;
unsigned int ci = 0, ic = 0;
@@ -261,21 +276,11 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
for (unsigned int i = 0; i < buffer->len; ++i)
chars[i] = buffer->info[i].codepoint;
- /* TODO ensure_native_direction. */
-
- hb_tag_t script_tag[HB_OT_MAX_TAGS_PER_SCRIPT];
- unsigned int count = HB_OT_MAX_TAGS_PER_SCRIPT;
- hb_ot_tags_from_script_and_language (hb_buffer_get_script (buffer),
- HB_LANGUAGE_INVALID,
- &count,
- script_tag,
- nullptr, nullptr);
-
seg = gr_make_seg (nullptr, grface,
- count ? script_tag[count - 1] : HB_OT_TAG_DEFAULT_SCRIPT,
+ HB_TAG_NONE, // https://github.com/harfbuzz/harfbuzz/issues/3439#issuecomment-1442650148
feats,
gr_utf32, chars, buffer->len,
- 2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
+ 2 | (direction == HB_DIRECTION_RTL ? 1 : 0));
if (unlikely (!seg)) {
if (feats) gr_featureval_destroy (feats);
@@ -327,7 +332,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
float yscale = (float) font->y_scale / upem;
yscale *= yscale / xscale;
unsigned int curradv = 0;
- if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
+ if (HB_DIRECTION_IS_BACKWARD (direction))
{
curradv = gr_slot_origin_X(gr_seg_first_slot(seg)) * xscale;
clusters[0].advance = gr_seg_advance_X(seg) * xscale - curradv;
@@ -356,16 +361,17 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
c->num_chars = before - c->base_char;
c->base_glyph = ic;
c->num_glyphs = 0;
- if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
+ if (HB_DIRECTION_IS_BACKWARD (direction))
{
c->advance = curradv - gr_slot_origin_X(is) * xscale;
curradv -= c->advance;
}
else
{
+ auto origin_X = gr_slot_origin_X (is) * xscale;
c->advance = 0;
- clusters[ci].advance += gr_slot_origin_X(is) * xscale - curradv;
- curradv += clusters[ci].advance;
+ clusters[ci].advance += origin_X - curradv;
+ curradv = origin_X;
}
ci++;
}
@@ -375,7 +381,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
clusters[ci].num_chars = after + 1 - clusters[ci].base_char;
}
- if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
+ if (HB_DIRECTION_IS_BACKWARD (direction))
clusters[ci].advance += curradv;
else
clusters[ci].advance += gr_seg_advance_X(seg) * xscale - curradv;
@@ -397,7 +403,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
unsigned int currclus = UINT_MAX;
const hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, nullptr);
- if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
+ if (!HB_DIRECTION_IS_BACKWARD (direction))
{
curradvx = 0;
for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is))
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
index b123b2f27c..61e05180be 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
@@ -63,6 +63,7 @@ struct hb_iter_t
static constexpr bool is_iterator = true;
static constexpr bool is_random_access_iterator = false;
static constexpr bool is_sorted_iterator = false;
+ static constexpr bool has_fast_len = false; // Should be checked in combination with is_random_access_iterator.
private:
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
@@ -393,7 +394,7 @@ struct hb_map_iter_t :
private:
Iter it;
- hb_reference_wrapper<Proj> f;
+ mutable hb_reference_wrapper<Proj> f;
};
template <typename Proj, hb_function_sortedness_t Sorted>
@@ -456,8 +457,8 @@ struct hb_filter_iter_t :
private:
Iter it;
- hb_reference_wrapper<Pred> p;
- hb_reference_wrapper<Proj> f;
+ mutable hb_reference_wrapper<Pred> p;
+ mutable hb_reference_wrapper<Proj> f;
};
template <typename Pred, typename Proj>
struct hb_filter_iter_factory_t
@@ -841,7 +842,7 @@ struct
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
auto operator () (Iterable&& it, unsigned count) const HB_AUTO_RETURN
- ( hb_zip (hb_range (count), it) | hb_map (hb_second) )
+ ( hb_zip (hb_range (count), it) | hb_map_retains_sorting (hb_second) )
/* Specialization arrays. */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-kern.hh b/src/3rdparty/harfbuzz-ng/src/hb-kern.hh
index 9ea945caed..0462a0ea8e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-kern.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-kern.hh
@@ -53,7 +53,7 @@ struct hb_kern_machine_t
return;
buffer->unsafe_to_concat ();
- OT::hb_ot_apply_context_t c (1, font, buffer);
+ OT::hb_ot_apply_context_t c (1, font, buffer, hb_blob_get_empty ());
c.set_lookup_mask (kern_mask);
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
auto &skippy_iter = c.iter_input;
@@ -70,7 +70,7 @@ struct hb_kern_machine_t
continue;
}
- skippy_iter.reset (idx, 1);
+ skippy_iter.reset (idx);
unsigned unsafe_to;
if (!skippy_iter.next (&unsafe_to))
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-limits.hh b/src/3rdparty/harfbuzz-ng/src/hb-limits.hh
index 0f60e9e210..c503b30652 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-limits.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-limits.hh
@@ -89,6 +89,10 @@
#endif
+#ifndef HB_GLYF_VAR_COMPOSITE_MAX_AXES
+#define HB_GLYF_VAR_COMPOSITE_MAX_AXES 4096
+#endif
+
#ifndef HB_GLYF_MAX_POINTS
#define HB_GLYF_MAX_POINTS 20000
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
index 1084725af2..ecff94f1b6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
@@ -180,6 +180,9 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
hb_lazy_loader_t<Returned,Subclass,Data,WheresData,Stored>
>::value Funcs;
+ hb_lazy_loader_t () = default;
+ hb_lazy_loader_t (const hb_lazy_loader_t &other) = delete;
+
void init0 () {} /* Init, when memory is already set to 0. No-op for us. */
void init () { instance.set_relaxed (nullptr); }
void fini () { do_destroy (instance.get_acquire ()); init (); }
@@ -278,7 +281,11 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
template <typename T, unsigned int WheresFace>
struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
hb_face_lazy_loader_t<T, WheresFace>,
- hb_face_t, WheresFace> {};
+ hb_face_t, WheresFace>
+{
+ // Hack; have them here for API parity with hb_table_lazy_loader_t
+ hb_blob_t *get_blob () { return this->get ()->get_blob (); }
+};
template <typename T, unsigned int WheresFace, bool core=false>
struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
@@ -288,7 +295,7 @@ struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
{
static hb_blob_t *create (hb_face_t *face)
{
- auto c = hb_sanitize_context_t ();
+ hb_sanitize_context_t c;
if (core)
c.set_num_glyphs (0); // So we don't recurse ad infinitum, or doesn't need num_glyphs
return c.reference_table<T> (face);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.h b/src/3rdparty/harfbuzz-ng/src/hb-map.h
index e928628fa7..0ae171714e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-map.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-map.h
@@ -44,7 +44,7 @@ HB_BEGIN_DECLS
*
* Since: 1.7.7
*/
-#define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1)
+#define HB_MAP_VALUE_INVALID HB_CODEPOINT_INVALID
/**
* hb_map_t:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-map.hh
index c685a9a3e1..42604ef7c2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-map.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-map.hh
@@ -45,9 +45,9 @@ struct hb_hashmap_t
hb_hashmap_t () { init (); }
~hb_hashmap_t () { fini (); }
- hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (o.population); hb_copy (o, *this); }
+ hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { alloc (o.population); hb_copy (o, *this); }
hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
- hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); resize (o.population); hb_copy (o, *this); return *this; }
+ hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); alloc (o.population); hb_copy (o, *this); return *this; }
hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; }
hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t ()
@@ -60,29 +60,32 @@ struct hb_hashmap_t
hb_hashmap_t (const Iterable &o) : hb_hashmap_t ()
{
auto iter = hb_iter (o);
- if (iter.is_random_access_iterator)
- resize (hb_len (iter));
+ if (iter.is_random_access_iterator || iter.has_fast_len)
+ alloc (hb_len (iter));
hb_copy (iter, *this);
}
struct item_t
{
K key;
- uint32_t hash : 30;
+ uint32_t is_real_ : 1;
uint32_t is_used_ : 1;
- uint32_t is_tombstone_ : 1;
+ uint32_t hash : 30;
V value;
item_t () : key (),
+ is_real_ (false), is_used_ (false),
hash (0),
- is_used_ (false), is_tombstone_ (false),
value () {}
+ // Needed for https://github.com/harfbuzz/harfbuzz/issues/4138
+ K& get_key () { return key; }
+ V& get_value () { return value; }
+
bool is_used () const { return is_used_; }
void set_used (bool is_used) { is_used_ = is_used; }
- bool is_tombstone () const { return is_tombstone_; }
- void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; }
- bool is_real () const { return is_used_ && !is_tombstone_; }
+ void set_real (bool is_real) { is_real_ = is_real; }
+ bool is_real () const { return is_real_; }
template <bool v = minus_one,
hb_enable_if (v == false)>
@@ -98,10 +101,15 @@ struct hb_hashmap_t
bool operator == (const K &o) const { return hb_deref (key) == hb_deref (o); }
bool operator == (const item_t &o) const { return *this == o.key; }
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
- hb_pair_t<const K &, const V &> get_pair_ref() const { return hb_pair_t<const K &, const V &> (key, value); }
+ hb_pair_t<const K &, V &> get_pair_ref() { return hb_pair_t<const K &, V &> (key, value); }
uint32_t total_hash () const
{ return (hash * 31) + hb_hash (value); }
+
+ static constexpr bool is_trivial = std::is_trivially_constructible<K>::value &&
+ std::is_trivially_destructible<K>::value &&
+ std::is_trivially_constructible<V>::value &&
+ std::is_trivially_destructible<V>::value;
};
hb_object_header_t header;
@@ -110,6 +118,7 @@ struct hb_hashmap_t
unsigned int occupancy; /* Including tombstones. */
unsigned int mask;
unsigned int prime;
+ unsigned int max_chain_length;
item_t *items;
friend void swap (hb_hashmap_t& a, hb_hashmap_t& b)
@@ -123,6 +132,7 @@ struct hb_hashmap_t
hb_swap (a.occupancy, b.occupancy);
hb_swap (a.mask, b.mask);
hb_swap (a.prime, b.prime);
+ hb_swap (a.max_chain_length, b.max_chain_length);
hb_swap (a.items, b.items);
}
void init ()
@@ -133,16 +143,19 @@ struct hb_hashmap_t
population = occupancy = 0;
mask = 0;
prime = 0;
+ max_chain_length = 0;
items = nullptr;
}
void fini ()
{
hb_object_fini (this);
- if (likely (items)) {
+ if (likely (items))
+ {
unsigned size = mask + 1;
- for (unsigned i = 0; i < size; i++)
- items[i].~item_t ();
+ if (!item_t::is_trivial)
+ for (unsigned i = 0; i < size; i++)
+ items[i].~item_t ();
hb_free (items);
items = nullptr;
}
@@ -157,7 +170,7 @@ struct hb_hashmap_t
bool in_error () const { return !successful; }
- bool resize (unsigned new_population = 0)
+ bool alloc (unsigned new_population = 0)
{
if (unlikely (!successful)) return false;
@@ -171,8 +184,11 @@ struct hb_hashmap_t
successful = false;
return false;
}
- for (auto &_ : hb_iter (new_items, new_size))
- new (&_) item_t ();
+ if (!item_t::is_trivial)
+ for (auto &_ : hb_iter (new_items, new_size))
+ new (&_) item_t ();
+ else
+ hb_memset (new_items, 0, (size_t) new_size * sizeof (item_t));
unsigned int old_size = size ();
item_t *old_items = items;
@@ -181,6 +197,7 @@ struct hb_hashmap_t
population = occupancy = 0;
mask = new_size - 1;
prime = prime_for (power);
+ max_chain_length = power * 2;
items = new_items;
/* Insert back old items. */
@@ -192,7 +209,8 @@ struct hb_hashmap_t
old_items[i].hash,
std::move (old_items[i].value));
}
- old_items[i].~item_t ();
+ if (!item_t::is_trivial)
+ old_items[i].~item_t ();
}
hb_free (old_items);
@@ -201,72 +219,124 @@ struct hb_hashmap_t
}
template <typename KK, typename VV>
- bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool is_delete=false)
+ bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool overwrite = true)
{
if (unlikely (!successful)) return false;
- if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
- item_t &item = item_for_hash (key, hash);
+ if (unlikely ((occupancy + occupancy / 2) >= mask && !alloc ())) return false;
- if (is_delete && !(item == key))
- return true; /* Trying to delete non-existent key. */
+ hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
+ unsigned int tombstone = (unsigned int) -1;
+ unsigned int i = hash % prime;
+ unsigned length = 0;
+ unsigned step = 0;
+ while (items[i].is_used ())
+ {
+ if ((std::is_integral<K>::value || items[i].hash == hash) &&
+ items[i] == key)
+ {
+ if (!overwrite)
+ return false;
+ else
+ break;
+ }
+ if (!items[i].is_real () && tombstone == (unsigned) -1)
+ tombstone = i;
+ i = (i + ++step) & mask;
+ length++;
+ }
+
+ item_t &item = items[tombstone == (unsigned) -1 ? i : tombstone];
if (item.is_used ())
{
occupancy--;
- if (!item.is_tombstone ())
- population--;
+ population -= item.is_real ();
}
item.key = std::forward<KK> (key);
item.value = std::forward<VV> (value);
item.hash = hash;
item.set_used (true);
- item.set_tombstone (is_delete);
+ item.set_real (true);
occupancy++;
- if (!is_delete)
- population++;
+ population++;
+
+ if (unlikely (length > max_chain_length) && occupancy * 8 > mask)
+ alloc (mask - 8); // This ensures we jump to next larger size
return true;
}
template <typename VV>
- bool set (const K &key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
+ bool set (const K &key, VV&& value, bool overwrite = true) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value), overwrite); }
template <typename VV>
- bool set (K &&key, VV&& value) { return set_with_hash (std::move (key), hb_hash (key), std::forward<VV> (value)); }
+ bool set (K &&key, VV&& value, bool overwrite = true)
+ {
+ uint32_t hash = hb_hash (key);
+ return set_with_hash (std::move (key), hash, std::forward<VV> (value), overwrite);
+ }
const V& get_with_hash (const K &key, uint32_t hash) const
{
- if (unlikely (!items)) return item_t::default_value ();
- auto &item = item_for_hash (key, hash);
- return item.is_real () && item == key ? item.value : item_t::default_value ();
+ if (!items) return item_t::default_value ();
+ auto *item = fetch_item (key, hb_hash (key));
+ if (item)
+ return item->value;
+ return item_t::default_value ();
}
const V& get (const K &key) const
{
- if (unlikely (!items)) return item_t::default_value ();
+ if (!items) return item_t::default_value ();
return get_with_hash (key, hb_hash (key));
}
- void del (const K &key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
+ void del (const K &key)
+ {
+ if (!items) return;
+ auto *item = fetch_item (key, hb_hash (key));
+ if (item)
+ {
+ item->set_real (false);
+ population--;
+ }
+ }
/* Has interface. */
const V& operator [] (K k) const { return get (k); }
template <typename VV=V>
- bool has (K key, VV **vp = nullptr) const
+ bool has (const K &key, VV **vp = nullptr) const
{
- if (unlikely (!items))
- return false;
- auto &item = item_for_hash (key, hb_hash (key));
- if (item.is_real () && item == key)
+ if (!items) return false;
+ auto *item = fetch_item (key, hb_hash (key));
+ if (item)
{
- if (vp) *vp = std::addressof (item.value);
+ if (vp) *vp = std::addressof (item->value);
return true;
}
- else
- return false;
+ return false;
+ }
+ item_t *fetch_item (const K &key, uint32_t hash) const
+ {
+ hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
+ unsigned int i = hash % prime;
+ unsigned step = 0;
+ while (items[i].is_used ())
+ {
+ if ((std::is_integral<K>::value || items[i].hash == hash) &&
+ items[i] == key)
+ {
+ if (items[i].is_real ())
+ return &items[i];
+ else
+ return nullptr;
+ }
+ i = (i + ++step) & mask;
+ }
+ return nullptr;
}
/* Projection. */
- V operator () (K k) const { return get (k); }
+ const V& operator () (K k) const { return get (k); }
unsigned size () const { return mask ? mask + 1 : 0; }
@@ -339,23 +409,21 @@ struct hb_hashmap_t
auto keys_ref () const HB_AUTO_RETURN
(
+ iter_items ()
- | hb_map (&item_t::key)
+ | hb_map (&item_t::get_key)
)
auto keys () const HB_AUTO_RETURN
(
- + iter_items ()
- | hb_map (&item_t::key)
+ + keys_ref ()
| hb_map (hb_ridentity)
)
auto values_ref () const HB_AUTO_RETURN
(
+ iter_items ()
- | hb_map (&item_t::value)
+ | hb_map (&item_t::get_value)
)
auto values () const HB_AUTO_RETURN
(
- + iter_items ()
- | hb_map (&item_t::value)
+ + values_ref ()
| hb_map (hb_ridentity)
)
@@ -393,24 +461,6 @@ struct hb_hashmap_t
hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v)
{ set (std::move (v.first), std::move (v.second)); return *this; }
- item_t& item_for_hash (const K &key, uint32_t hash) const
- {
- hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
- unsigned int i = hash % prime;
- unsigned int step = 0;
- unsigned int tombstone = (unsigned) -1;
- while (items[i].is_used ())
- {
- if ((hb_is_same (K, hb_codepoint_t) || items[i].hash == hash) &&
- items[i] == key)
- return items[i];
- if (tombstone == (unsigned) -1 && items[i].is_tombstone ())
- tombstone = i;
- i = (i + ++step) & mask;
- }
- return items[tombstone == (unsigned) -1 ? i : tombstone];
- }
-
static unsigned int prime_for (unsigned int shift)
{
/* Following comment and table copied from glib. */
@@ -481,7 +531,7 @@ struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {}
hb_map_t& operator= (const hb_map_t&) = default;
hb_map_t& operator= (hb_map_t&&) = default;
- hb_map_t (std::initializer_list<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> lst) : hashmap (lst) {}
+ hb_map_t (std::initializer_list<hb_codepoint_pair_t> lst) : hashmap (lst) {}
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
hb_map_t (const Iterable &o) : hashmap (o) {}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh
index 31aa7fa6f1..52ff4a8412 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh
@@ -153,8 +153,8 @@ struct hb_reference_wrapper
hb_reference_wrapper (T v) : v (v) {}
bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
- operator T () const { return v; }
- T get () const { return v; }
+ operator T& () { return v; }
+ T& get () { return v; }
T v;
};
template <typename T>
@@ -163,8 +163,8 @@ struct hb_reference_wrapper<T&>
hb_reference_wrapper (T& v) : v (std::addressof (v)) {}
bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
- operator T& () const { return *v; }
- T& get () const { return *v; }
+ operator T& () { return *v; }
+ T& get () { return *v; }
T* v;
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh
index b4a8cc62a3..0184279c12 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh
@@ -38,10 +38,10 @@ struct hb_multimap_t
{
void add (hb_codepoint_t k, hb_codepoint_t v)
{
- hb_codepoint_t *i;
- if (multiples_indices.has (k, &i))
+ hb_vector_t<hb_codepoint_t> *m;
+ if (multiples.has (k, &m))
{
- multiples_values[*i].push (v);
+ m->push (v);
return;
}
@@ -51,12 +51,7 @@ struct hb_multimap_t
hb_codepoint_t old = *old_v;
singulars.del (k);
- multiples_indices.set (k, multiples_values.length);
- auto *vec = multiples_values.push ();
-
- vec->push (old);
- vec->push (v);
-
+ multiples.set (k, hb_vector_t<hb_codepoint_t> {old, v});
return;
}
@@ -69,22 +64,31 @@ struct hb_multimap_t
if (singulars.has (k, &v))
return hb_array (v, 1);
- hb_codepoint_t *i;
- if (multiples_indices.has (k, &i))
- return multiples_values[*i].as_array ();
+ hb_vector_t<hb_codepoint_t> *m;
+ if (multiples.has (k, &m))
+ return m->as_array ();
return hb_array_t<const hb_codepoint_t> ();
}
bool in_error () const
{
- return singulars.in_error () || multiples_indices.in_error () || multiples_values.in_error ();
+ if (singulars.in_error () || multiples.in_error ())
+ return true;
+ for (const auto &m : multiples.values_ref ())
+ if (m.in_error ())
+ return true;
+ return false;
+ }
+
+ void alloc (unsigned size)
+ {
+ singulars.alloc (size);
}
protected:
hb_map_t singulars;
- hb_map_t multiples_indices;
- hb_vector_t<hb_vector_t<hb_codepoint_t>> multiples_values;
+ hb_hashmap_t<hb_codepoint_t, hb_vector_t<hb_codepoint_t>> multiples;
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-null.hh b/src/3rdparty/harfbuzz-ng/src/hb-null.hh
index 3da2d75ef5..6796906ba8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-null.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-null.hh
@@ -37,7 +37,7 @@
/* Global nul-content Null pool. Enlarge as necessary. */
-#define HB_NULL_POOL_SIZE 520
+#define HB_NULL_POOL_SIZE 640
template <typename T, typename>
struct _hb_has_min_size : hb_false_type {};
@@ -176,7 +176,7 @@ template <typename Type>
static inline Type& Crap () {
static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
- memcpy (obj, &Null (Type), sizeof (*obj));
+ memcpy (obj, std::addressof (Null (Type)), sizeof (*obj));
return *obj;
}
template <typename QType>
@@ -211,11 +211,11 @@ struct hb_nonnull_ptr_t
T * operator = (T *v_) { return v = v_; }
T * operator -> () const { return get (); }
T & operator * () const { return *get (); }
- T ** operator & () const { return &v; }
+ T ** operator & () const { return std::addressof (v); }
/* Only auto-cast to const types. */
template <typename C> operator const C * () const { return get (); }
operator const char * () const { return (const char *) get (); }
- T * get () const { return v ? v : const_cast<T *> (&Null (T)); }
+ T * get () const { return v ? v : const_cast<T *> (std::addressof (Null (T))); }
T * get_raw () const { return v; }
private:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh
index 13570a46e0..04f144a72c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh
@@ -131,7 +131,7 @@ typedef struct OpenTypeOffsetTable
sfnt_version = sfnt_tag;
/* Take space for numTables, searchRange, entrySelector, RangeShift
* and the TableRecords themselves. */
- unsigned num_items = it.len ();
+ unsigned num_items = hb_len (it);
if (unlikely (!tables.serialize (c, num_items))) return_trace (false);
const char *dir_end = (const char *) c->head;
@@ -145,7 +145,7 @@ typedef struct OpenTypeOffsetTable
unsigned len = blob->length;
/* Allocate room for the table and copy it. */
- char *start = (char *) c->allocate_size<void> (len);
+ char *start = (char *) c->allocate_size<void> (len, false);
if (unlikely (!start)) return false;
TableRecord &rec = tables.arrayZ[i];
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
index 4c9bfebcec..d3fdd1caf5 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
@@ -312,6 +312,8 @@ struct _hb_has_null<Type, true>
template <typename Type, typename OffsetType, bool has_null=true>
struct OffsetTo : Offset<OffsetType, has_null>
{
+ using target_t = Type;
+
// Make sure Type is not unbounded; works only for types that are fully defined at OffsetTo time.
static_assert (has_null == false ||
(hb_has_null_size (Type) || !hb_has_min_size (Type)), "");
@@ -416,12 +418,15 @@ struct OffsetTo : Offset<OffsetType, has_null>
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this))) return_trace (false);
- if (unlikely (this->is_null ())) return_trace (true);
+ //if (unlikely (this->is_null ())) return_trace (true);
if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false);
return_trace (true);
}
template <typename ...Ts>
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
{
TRACE_SANITIZE (this);
@@ -462,24 +467,16 @@ struct UnsizedArrayOf
HB_DELETE_CREATE_COPY_ASSIGN (UnsizedArrayOf);
- const Type& operator [] (int i_) const
+ const Type& operator [] (unsigned int i) const
{
- unsigned int i = (unsigned int) i_;
- const Type *p = &arrayZ[i];
- if (unlikely ((const void *) p < (const void *) arrayZ)) return Null (Type); /* Overflowed. */
- _hb_compiler_memory_r_barrier ();
- return *p;
+ return arrayZ[i];
}
- Type& operator [] (int i_)
+ Type& operator [] (unsigned int i)
{
- unsigned int i = (unsigned int) i_;
- Type *p = &arrayZ[i];
- if (unlikely ((const void *) p < (const void *) arrayZ)) return Crap (Type); /* Overflowed. */
- _hb_compiler_memory_r_barrier ();
- return *p;
+ return arrayZ[i];
}
- unsigned int get_size (unsigned int len) const
+ static unsigned int get_size (unsigned int len)
{ return len * Type::static_size; }
template <typename T> operator T * () { return arrayZ; }
@@ -533,6 +530,7 @@ struct UnsizedArrayOf
}
template <typename ...Ts>
+ HB_ALWAYS_INLINE
bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
{
TRACE_SANITIZE (this);
@@ -721,6 +719,7 @@ struct ArrayOf
}
template <typename ...Ts>
+ HB_ALWAYS_INLINE
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
{
TRACE_SANITIZE (this);
@@ -736,7 +735,7 @@ struct ArrayOf
bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (len.sanitize (c) && c->check_array (arrayZ, len));
+ return_trace (len.sanitize (c) && c->check_array_sized (arrayZ, len, sizeof (LenType)));
}
public:
@@ -797,7 +796,7 @@ template <typename Type>
using List16OfOffset16To = List16OfOffsetTo<Type, HBUINT16>;
/* An array starting at second element. */
-template <typename Type, typename LenType=HBUINT16>
+template <typename Type, typename LenType>
struct HeadlessArrayOf
{
static constexpr unsigned item_size = Type::static_size;
@@ -861,6 +860,7 @@ struct HeadlessArrayOf
}
template <typename ...Ts>
+ HB_ALWAYS_INLINE
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
{
TRACE_SANITIZE (this);
@@ -878,7 +878,7 @@ struct HeadlessArrayOf
{
TRACE_SANITIZE (this);
return_trace (lenP1.sanitize (c) &&
- (!lenP1 || c->check_array (arrayZ, lenP1 - 1)));
+ (!lenP1 || c->check_array_sized (arrayZ, lenP1 - 1, sizeof (LenType))));
}
public:
@@ -887,6 +887,7 @@ struct HeadlessArrayOf
public:
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
+template <typename Type> using HeadlessArray16Of = HeadlessArrayOf<Type, HBUINT16>;
/* An array storing length-1. */
template <typename Type, typename LenType=HBUINT16>
@@ -912,6 +913,7 @@ struct ArrayOfM1
{ return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
template <typename ...Ts>
+ HB_ALWAYS_INLINE
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
{
TRACE_SANITIZE (this);
@@ -929,7 +931,7 @@ struct ArrayOfM1
{
TRACE_SANITIZE (this);
return_trace (lenM1.sanitize (c) &&
- (c->check_array (arrayZ, lenM1 + 1)));
+ (c->check_array_sized (arrayZ, lenM1 + 1, sizeof (LenType))));
}
public:
@@ -1096,6 +1098,7 @@ struct VarSizedBinSearchArrayOf
{ return header.static_size + header.nUnits * header.unitSize; }
template <typename ...Ts>
+ HB_ALWAYS_INLINE
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
{
TRACE_SANITIZE (this);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh
index f22824fc69..923a32b26f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh
@@ -48,12 +48,24 @@ static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offs
struct code_pair_t
{
- hb_codepoint_t code;
+ unsigned code;
hb_codepoint_t glyph;
};
+
using str_buff_t = hb_vector_t<unsigned char>;
using str_buff_vec_t = hb_vector_t<str_buff_t>;
+using glyph_to_sid_map_t = hb_vector_t<code_pair_t>;
+
+struct length_f_t
+{
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
+ unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); }
+
+ unsigned operator () (unsigned _) const { return _; }
+}
+HB_FUNCOBJ (length_f);
/* CFF INDEX */
template <typename COUNT>
@@ -62,42 +74,52 @@ struct CFFIndex
unsigned int offset_array_size () const
{ return offSize * (count + 1); }
- CFFIndex *copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- unsigned int size = get_size ();
- CFFIndex *out = c->allocate_size<CFFIndex> (size, false);
- if (likely (out))
- hb_memcpy (out, this, size);
- return_trace (out);
- }
-
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
bool serialize (hb_serialize_context_t *c,
- const Iterable &iterable)
+ const Iterable &iterable,
+ const unsigned *p_data_size = nullptr)
{
TRACE_SERIALIZE (this);
+ unsigned data_size;
+ if (p_data_size)
+ data_size = *p_data_size;
+ else
+ total_size (iterable, &data_size);
+
auto it = hb_iter (iterable);
- serialize_header(c, + it | hb_map (hb_iter) | hb_map (hb_len));
+ if (unlikely (!serialize_header (c, +it, data_size))) return_trace (false);
+ unsigned char *ret = c->allocate_size<unsigned char> (data_size, false);
+ if (unlikely (!ret)) return_trace (false);
for (const auto &_ : +it)
- hb_iter (_).copy (c);
+ {
+ unsigned len = _.length;
+ if (!len)
+ continue;
+ if (len <= 1)
+ {
+ *ret++ = *_.arrayZ;
+ continue;
+ }
+ hb_memcpy (ret, _.arrayZ, len);
+ ret += len;
+ }
return_trace (true);
}
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool serialize_header (hb_serialize_context_t *c,
- Iterator it)
+ Iterator it,
+ unsigned data_size)
{
TRACE_SERIALIZE (this);
- unsigned total = + it | hb_reduce (hb_add, 0);
- unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
+ unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8;
/* serialize CFFIndex header */
if (unlikely (!c->extend_min (this))) return_trace (false);
- this->count = it.len ();
+ this->count = hb_len (it);
if (!this->count) return_trace (true);
if (unlikely (!c->extend (this->offSize))) return_trace (false);
this->offSize = off_size;
@@ -106,25 +128,88 @@ struct CFFIndex
/* serialize indices */
unsigned int offset = 1;
- unsigned int i = 0;
- for (unsigned _ : +it)
+ if (HB_OPTIMIZE_SIZE_VAL)
{
- set_offset_at (i++, offset);
- offset += _;
+ unsigned int i = 0;
+ for (const auto &_ : +it)
+ {
+ set_offset_at (i++, offset);
+ offset += length_f (_);
+ }
+ set_offset_at (i, offset);
}
- set_offset_at (i, offset);
-
+ else
+ switch (off_size)
+ {
+ case 1:
+ {
+ HBUINT8 *p = (HBUINT8 *) offsets;
+ for (const auto &_ : +it)
+ {
+ *p++ = offset;
+ offset += length_f (_);
+ }
+ *p = offset;
+ }
+ break;
+ case 2:
+ {
+ HBUINT16 *p = (HBUINT16 *) offsets;
+ for (const auto &_ : +it)
+ {
+ *p++ = offset;
+ offset += length_f (_);
+ }
+ *p = offset;
+ }
+ break;
+ case 3:
+ {
+ HBUINT24 *p = (HBUINT24 *) offsets;
+ for (const auto &_ : +it)
+ {
+ *p++ = offset;
+ offset += length_f (_);
+ }
+ *p = offset;
+ }
+ break;
+ case 4:
+ {
+ HBUINT32 *p = (HBUINT32 *) offsets;
+ for (const auto &_ : +it)
+ {
+ *p++ = offset;
+ offset += length_f (_);
+ }
+ *p = offset;
+ }
+ break;
+ default:
+ break;
+ }
+
+ assert (offset == data_size + 1);
return_trace (true);
}
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
- static unsigned total_size (const Iterable &iterable)
+ static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr)
{
- auto it = + hb_iter (iterable) | hb_map (hb_iter) | hb_map (hb_len);
- if (!it) return 0;
+ auto it = + hb_iter (iterable);
+ if (!it)
+ {
+ if (data_size) *data_size = 0;
+ return min_size;
+ }
+
+ unsigned total = 0;
+ for (const auto &_ : +it)
+ total += length_f (_);
+
+ if (data_size) *data_size = total;
- unsigned total = + it | hb_reduce (hb_add, 0);
unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
@@ -133,13 +218,16 @@ struct CFFIndex
void set_offset_at (unsigned int index, unsigned int offset)
{
assert (index <= count);
- HBUINT8 *p = offsets + offSize * index + offSize;
+
unsigned int size = offSize;
- for (; size; size--)
+ const HBUINT8 *p = offsets;
+ switch (size)
{
- --p;
- *p = offset & 0xFF;
- offset >>= 8;
+ case 1: ((HBUINT8 *) p)[index] = offset; break;
+ case 2: ((HBUINT16 *) p)[index] = offset; break;
+ case 3: ((HBUINT24 *) p)[index] = offset; break;
+ case 4: ((HBUINT32 *) p)[index] = offset; break;
+ default: return;
}
}
@@ -149,37 +237,30 @@ struct CFFIndex
assert (index <= count);
unsigned int size = offSize;
- const HBUINT8 *p = offsets + size * index;
+ const HBUINT8 *p = offsets;
switch (size)
{
- case 1: return * (HBUINT8 *) p;
- case 2: return * (HBUINT16 *) p;
- case 3: return * (HBUINT24 *) p;
- case 4: return * (HBUINT32 *) p;
+ case 1: return ((HBUINT8 *) p)[index];
+ case 2: return ((HBUINT16 *) p)[index];
+ case 3: return ((HBUINT24 *) p)[index];
+ case 4: return ((HBUINT32 *) p)[index];
default: return 0;
}
}
- unsigned int length_at (unsigned int index) const
- {
- unsigned offset0 = offset_at (index);
- unsigned offset1 = offset_at (index + 1);
- if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
- return 0;
- return offset1 - offset0;
- }
-
const unsigned char *data_base () const
- { return (const unsigned char *) this + min_size + offSize.static_size + offset_array_size (); }
+ { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); }
public:
hb_ubytes_t operator [] (unsigned int index) const
{
if (unlikely (index >= count)) return hb_ubytes_t ();
_hb_compiler_memory_r_barrier ();
- unsigned length = length_at (index);
- if (unlikely (!length)) return hb_ubytes_t ();
- return hb_ubytes_t (data_base () + offset_at (index) - 1, length);
+ unsigned offset0 = offset_at (index);
+ unsigned offset1 = offset_at (index + 1);
+ if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
+ return hb_ubytes_t ();
+ return hb_ubytes_t (data_base () + offset0, offset1 - offset0);
}
unsigned int get_size () const
@@ -197,7 +278,7 @@ struct CFFIndex
(count < count + 1u &&
c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 &&
c->check_array (offsets, offSize, count + 1u) &&
- c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count) - 1)))));
+ c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count))))));
}
public:
@@ -211,47 +292,6 @@ struct CFFIndex
DEFINE_SIZE_MIN (COUNT::static_size);
};
-template <typename COUNT, typename TYPE>
-struct CFFIndexOf : CFFIndex<COUNT>
-{
- template <typename DATA, typename PARAM1, typename PARAM2>
- bool serialize (hb_serialize_context_t *c,
- unsigned int offSize_,
- const DATA *dataArray,
- unsigned int dataArrayLen,
- const hb_vector_t<unsigned int> &dataSizeArray,
- const PARAM1 &param1,
- const PARAM2 &param2)
- {
- TRACE_SERIALIZE (this);
- /* serialize CFFIndex header */
- if (unlikely (!c->extend_min (this))) return_trace (false);
- this->count = dataArrayLen;
- this->offSize = offSize_;
- if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1), false)))
- return_trace (false);
-
- /* serialize indices */
- unsigned int offset = 1;
- unsigned int i = 0;
- for (; i < dataArrayLen; i++)
- {
- this->set_offset_at (i, offset);
- offset += dataSizeArray[i];
- }
- this->set_offset_at (i, offset);
-
- /* serialize data */
- for (unsigned int i = 0; i < dataArrayLen; i++)
- {
- TYPE *dest = c->start_embed<TYPE> ();
- if (unlikely (!dest || !dest->serialize (c, dataArray[i], param1, param2)))
- return_trace (false);
- }
- return_trace (true);
- }
-};
-
/* Top Dict, Font Dict, Private Dict */
struct Dict : UnsizedByteStr
{
@@ -327,7 +367,7 @@ struct table_info_t
};
template <typename COUNT>
-struct FDArray : CFFIndexOf<COUNT, FontDict>
+struct FDArray : CFFIndex<COUNT>
{
template <typename DICTVAL, typename INFO, typename Iterator, typename OP_SERIALIZER>
bool serialize (hb_serialize_context_t *c,
@@ -338,7 +378,11 @@ struct FDArray : CFFIndexOf<COUNT, FontDict>
/* serialize INDEX data */
hb_vector_t<unsigned> sizes;
+ if (it.is_random_access_iterator)
+ sizes.alloc (hb_len (it));
+
c->push ();
+ char *data_base = c->head;
+ it
| hb_map ([&] (const hb_pair_t<const DICTVAL&, const INFO&> &_)
{
@@ -348,10 +392,16 @@ struct FDArray : CFFIndexOf<COUNT, FontDict>
})
| hb_sink (sizes)
;
+ unsigned data_size = c->head - data_base;
c->pop_pack (false);
+ if (unlikely (sizes.in_error ())) return_trace (false);
+
+ /* It just happens that the above is packed right after the header below.
+ * Such a hack. */
+
/* serialize INDEX header */
- return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes)));
+ return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes), data_size));
}
};
@@ -368,8 +418,11 @@ struct FDSelect0 {
return_trace (true);
}
- hb_codepoint_t get_fd (hb_codepoint_t glyph) const
- { return (hb_codepoint_t) fds[glyph]; }
+ unsigned get_fd (hb_codepoint_t glyph) const
+ { return fds[glyph]; }
+
+ hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
+ { return {fds[glyph], glyph + 1}; }
unsigned int get_size (unsigned int num_glyphs) const
{ return HBUINT8::static_size * num_glyphs; }
@@ -427,12 +480,20 @@ struct FDSelect3_4
return +1;
}
- hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+ unsigned get_fd (hb_codepoint_t glyph) const
{
auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
return range ? range->fd : ranges[nRanges () - 1].fd;
}
+ hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
+ {
+ auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
+ unsigned fd = range ? range->fd : ranges[nRanges () - 1].fd;
+ hb_codepoint_t end = range ? range[1].first : ranges[nRanges () - 1].first;
+ return {fd, end};
+ }
+
GID_TYPE &nRanges () { return ranges.len; }
GID_TYPE nRanges () const { return ranges.len; }
GID_TYPE &sentinel () { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
@@ -469,7 +530,7 @@ struct FDSelect
}
}
- hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+ unsigned get_fd (hb_codepoint_t glyph) const
{
if (this == &Null (FDSelect)) return 0;
@@ -480,6 +541,18 @@ struct FDSelect
default:return 0;
}
}
+ /* Returns pair of fd and one after last glyph in range. */
+ hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
+ {
+ if (this == &Null (FDSelect)) return {0, 1};
+
+ switch (format)
+ {
+ case 0: return u.format0.get_fd_range (glyph);
+ case 3: return u.format3.get_fd_range (glyph);
+ default:return {0, 1};
+ }
+ }
bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
index 5040c74623..66df28aae1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
@@ -574,11 +574,11 @@ bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h
struct get_seac_param_t
{
- get_seac_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) {}
+ get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {}
bool has_seac () const { return base && accent; }
- const OT::cff1::accelerator_t *cff;
+ const OT::cff1::accelerator_subset_t *cff;
hb_codepoint_t base = 0;
hb_codepoint_t accent = 0;
};
@@ -596,7 +596,7 @@ struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_par
}
};
-bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
+bool OT::cff1::accelerator_subset_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
{
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh
index 4d0a965eee..1e81dcb5e3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh
@@ -28,7 +28,7 @@
#define HB_OT_CFF1_TABLE_HH
#include "hb-ot-cff-common.hh"
-#include "hb-subset-cff1.hh"
+#include "hb-subset-cff-common.hh"
#include "hb-draw.hh"
#include "hb-paint.hh"
@@ -52,7 +52,6 @@ enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
typedef CFFIndex<HBUINT16> CFF1Index;
-template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
typedef CFFIndex<HBUINT16> CFF1Index;
typedef CFF1Index CFF1CharStrings;
@@ -110,6 +109,7 @@ struct Encoding1 {
hb_codepoint_t get_code (hb_codepoint_t glyph) const
{
+ /* TODO: Add cache like get_sid. */
assert (glyph > 0);
glyph--;
for (unsigned int i = 0; i < nRanges (); i++)
@@ -173,11 +173,7 @@ struct Encoding
bool serialize (hb_serialize_context_t *c, const Encoding &src)
{
TRACE_SERIALIZE (this);
- unsigned int size = src.get_size ();
- Encoding *dest = c->allocate_size<Encoding> (size);
- if (unlikely (!dest)) return_trace (false);
- hb_memcpy (dest, &src, size);
- return_trace (true);
+ return_trace (c->embed (src));
}
/* serialize a subset Encoding */
@@ -312,26 +308,29 @@ struct Encoding
};
/* Charset */
-struct Charset0 {
- bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+struct Charset0
+{
+ bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
{
TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
+ if (num_charset_entries) *num_charset_entries = num_glyphs;
+ return_trace (sids.sanitize (c, num_glyphs - 1));
}
hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
{
if (unlikely (glyph >= num_glyphs)) return 0;
- if (glyph == 0)
+ if (unlikely (glyph == 0))
return 0;
else
return sids[glyph - 1];
}
- void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
{
+ mapping->resize (num_glyphs, false);
for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
- mapping->set (gid, sids[gid - 1]);
+ mapping->arrayZ[gid] = {sids[gid - 1], gid};
}
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
@@ -347,13 +346,13 @@ struct Charset0 {
return 0;
}
- unsigned int get_size (unsigned int num_glyphs) const
+ static unsigned int get_size (unsigned int num_glyphs)
{
assert (num_glyphs > 0);
- return HBUINT16::static_size * (num_glyphs - 1);
+ return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1);
}
- HBUINT16 sids[HB_VAR_ARRAY];
+ UnsizedArrayOf<HBUINT16> sids;
DEFINE_SIZE_ARRAY(0, sids);
};
@@ -374,38 +373,62 @@ struct Charset_Range {
template <typename TYPE>
struct Charset1_2 {
- bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+ bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this)))
return_trace (false);
num_glyphs--;
- for (unsigned int i = 0; num_glyphs > 0; i++)
+ unsigned i;
+ for (i = 0; num_glyphs > 0; i++)
{
if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
return_trace (false);
num_glyphs -= (ranges[i].nLeft + 1);
}
+ if (num_charset_entries)
+ *num_charset_entries = i;
return_trace (true);
}
- hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
+ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs,
+ code_pair_t *cache = nullptr) const
{
if (unlikely (glyph >= num_glyphs)) return 0;
- if (glyph == 0) return 0;
- glyph--;
- for (unsigned int i = 0;; i++)
+ unsigned i;
+ hb_codepoint_t start_glyph;
+ if (cache && likely (cache->glyph <= glyph))
{
- if (glyph <= ranges[i].nLeft)
- return (hb_codepoint_t) ranges[i].first + glyph;
- glyph -= (ranges[i].nLeft + 1);
+ i = cache->code;
+ start_glyph = cache->glyph;
+ }
+ else
+ {
+ if (unlikely (glyph == 0)) return 0;
+ i = 0;
+ start_glyph = 1;
+ }
+ glyph -= start_glyph;
+ for (;; i++)
+ {
+ unsigned count = ranges[i].nLeft;
+ if (glyph <= count)
+ {
+ if (cache)
+ *cache = {i, start_glyph};
+ return ranges[i].first + glyph;
+ }
+ count++;
+ start_glyph += count;
+ glyph -= count;
}
return 0;
}
- void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
{
+ mapping->resize (num_glyphs, false);
hb_codepoint_t gid = 1;
if (gid >= num_glyphs)
return;
@@ -413,8 +436,9 @@ struct Charset1_2 {
{
hb_codepoint_t sid = ranges[i].first;
unsigned count = ranges[i].nLeft + 1;
+ unsigned last = gid + count;
for (unsigned j = 0; j < count; j++)
- mapping->set (gid++, sid++);
+ mapping->arrayZ[gid++] = {sid++, last - 1};
if (gid >= num_glyphs)
break;
@@ -439,21 +463,26 @@ struct Charset1_2 {
unsigned int get_size (unsigned int num_glyphs) const
{
- unsigned int size = HBUINT8::static_size;
- int glyph = (int)num_glyphs;
+ int glyph = (int) num_glyphs;
+ unsigned num_ranges = 0;
assert (glyph > 0);
glyph--;
for (unsigned int i = 0; glyph > 0; i++)
{
glyph -= (ranges[i].nLeft + 1);
- size += Charset_Range<TYPE>::static_size;
+ num_ranges++;
}
- return size;
+ return get_size_for_ranges (num_ranges);
+ }
+
+ static unsigned int get_size_for_ranges (unsigned int num_ranges)
+ {
+ return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges);
}
- Charset_Range<TYPE> ranges[HB_VAR_ARRAY];
+ UnsizedArrayOf<Charset_Range<TYPE>> ranges;
DEFINE_SIZE_ARRAY (0, ranges);
};
@@ -469,11 +498,7 @@ struct Charset
bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
{
TRACE_SERIALIZE (this);
- unsigned int size = src.get_size (num_glyphs);
- Charset *dest = c->allocate_size<Charset> (size);
- if (unlikely (!dest)) return_trace (false);
- hb_memcpy (dest, &src, size);
- return_trace (true);
+ return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs)));
}
/* serialize a subset Charset */
@@ -490,13 +515,13 @@ struct Charset
{
case 0:
{
- Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
+ Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false);
if (unlikely (!fmt0)) return_trace (false);
unsigned int glyph = 0;
for (unsigned int i = 0; i < sid_ranges.length; i++)
{
- hb_codepoint_t sid = sid_ranges[i].code;
- for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
+ hb_codepoint_t sid = sid_ranges.arrayZ[i].code;
+ for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--)
fmt0->sids[glyph++] = sid++;
}
}
@@ -504,29 +529,35 @@ struct Charset
case 1:
{
- Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
+ Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false);
if (unlikely (!fmt1)) return_trace (false);
+ hb_codepoint_t all_glyphs = 0;
for (unsigned int i = 0; i < sid_ranges.length; i++)
{
- if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
- return_trace (false);
- fmt1->ranges[i].first = sid_ranges[i].code;
- fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
+ auto &_ = sid_ranges.arrayZ[i];
+ all_glyphs |= _.glyph;
+ fmt1->ranges[i].first = _.code;
+ fmt1->ranges[i].nLeft = _.glyph;
}
+ if (unlikely (!(all_glyphs <= 0xFF)))
+ return_trace (false);
}
break;
case 2:
{
- Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
+ Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false);
if (unlikely (!fmt2)) return_trace (false);
+ hb_codepoint_t all_glyphs = 0;
for (unsigned int i = 0; i < sid_ranges.length; i++)
{
- if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
- return_trace (false);
- fmt2->ranges[i].first = sid_ranges[i].code;
- fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
+ auto &_ = sid_ranges.arrayZ[i];
+ all_glyphs |= _.glyph;
+ fmt2->ranges[i].first = _.code;
+ fmt2->ranges[i].nLeft = _.glyph;
}
+ if (unlikely (!(all_glyphs <= 0xFFFF)))
+ return_trace (false);
}
break;
@@ -545,18 +576,19 @@ struct Charset
}
}
- hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
+ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs,
+ code_pair_t *cache = nullptr) const
{
switch (format)
{
case 0: return u.format0.get_sid (glyph, num_glyphs);
- case 1: return u.format1.get_sid (glyph, num_glyphs);
- case 2: return u.format2.get_sid (glyph, num_glyphs);
+ case 1: return u.format1.get_sid (glyph, num_glyphs, cache);
+ case 2: return u.format2.get_sid (glyph, num_glyphs, cache);
default:return 0;
}
}
- void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const
{
switch (format)
{
@@ -578,7 +610,7 @@ struct Charset
}
}
- bool sanitize (hb_sanitize_context_t *c) const
+ bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this)))
@@ -586,9 +618,9 @@ struct Charset
switch (format)
{
- case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
- case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
- case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
+ case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+ case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+ case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
default:return_trace (false);
}
}
@@ -606,10 +638,10 @@ struct Charset
struct CFF1StringIndex : CFF1Index
{
bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
- const hb_inc_bimap_t &sidmap)
+ const hb_vector_t<unsigned> &sidmap)
{
TRACE_SERIALIZE (this);
- if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
+ if (unlikely ((strings.count == 0) || (sidmap.length == 0)))
{
if (unlikely (!c->extend_min (this->count)))
return_trace (false);
@@ -617,15 +649,13 @@ struct CFF1StringIndex : CFF1Index
return_trace (true);
}
- byte_str_array_t bytesArray;
- if (!bytesArray.resize (sidmap.get_population ()))
- return_trace (false);
- for (unsigned int i = 0; i < strings.count; i++)
- {
- hb_codepoint_t j = sidmap[i];
- if (j != HB_MAP_VALUE_INVALID)
- bytesArray[j] = strings[i];
- }
+ if (unlikely (sidmap.in_error ())) return_trace (false);
+
+ // Save this in a vector since serialize() iterates it twice.
+ hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap)
+ | hb_map (strings));
+
+ if (unlikely (bytesArray.in_error ())) return_trace (false);
bool result = CFF1Index::serialize (c, bytesArray);
return_trace (result);
@@ -932,7 +962,7 @@ struct cff1_private_dict_opset_t : dict_opset_t
}
};
-struct cff1_private_dict_opset_subset : dict_opset_t
+struct cff1_private_dict_opset_subset_t : dict_opset_t
{
static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
{
@@ -978,7 +1008,7 @@ typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_t
typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
typedef CFF1Index CFF1NameIndex;
-typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
+typedef CFF1Index CFF1TopDictIndex;
struct cff1_font_dict_values_mod_t
{
@@ -1031,8 +1061,12 @@ struct cff1
template <typename PRIVOPSET, typename PRIVDICTVAL>
struct accelerator_templ_t
{
- void init (hb_face_t *face)
+ static constexpr hb_tag_t tableTag = cff1::tableTag;
+
+ accelerator_templ_t (hb_face_t *face)
{
+ if (!face) return;
+
topDict.init ();
fontDicts.init ();
privateDicts.init ();
@@ -1046,22 +1080,22 @@ struct cff1
const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
if (cff == &Null (OT::cff1))
- { fini (); return; }
+ goto fail;
nameIndex = &cff->nameIndex (cff);
if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
- { fini (); return; }
+ goto fail;
topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
- { fini (); return; }
+ goto fail;
{ /* parse top dict */
const hb_ubytes_t topDictStr = (*topDictIndex)[0];
- if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
+ if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
cff1_top_dict_interp_env_t env (topDictStr);
cff1_top_dict_interpreter_t top_interp (env);
- if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
+ if (unlikely (!top_interp.interpret (topDict))) goto fail;
}
if (is_predef_charset ())
@@ -1069,7 +1103,7 @@ struct cff1
else
{
charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
- if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
+ if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries))) goto fail;
}
fdCount = 1;
@@ -1079,7 +1113,7 @@ struct cff1
fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
(fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
- { fini (); return; }
+ goto fail;
fdCount = fdArray->count;
}
@@ -1092,36 +1126,36 @@ struct cff1
encoding = &Null (Encoding);
if (is_CID ())
{
- if (unlikely (charset == &Null (Charset))) { fini (); return; }
+ if (unlikely (charset == &Null (Charset))) goto fail;
}
else
{
if (!is_predef_encoding ())
{
encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
- if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
+ if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) goto fail;
}
}
stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
- { fini (); return; }
+ goto fail;
globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
- { fini (); return; }
+ goto fail;
charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
- { fini (); return; }
+ goto fail;
num_glyphs = charStrings->count;
if (num_glyphs != sc.get_num_glyphs ())
- { fini (); return; }
+ goto fail;
if (unlikely (!privateDicts.resize (fdCount)))
- { fini (); return; }
+ goto fail;
for (unsigned int i = 0; i < fdCount; i++)
privateDicts[i].init ();
@@ -1131,27 +1165,27 @@ struct cff1
for (unsigned int i = 0; i < fdCount; i++)
{
hb_ubytes_t fontDictStr = (*fdArray)[i];
- if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
+ if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
cff1_font_dict_values_t *font;
cff1_top_dict_interp_env_t env (fontDictStr);
cff1_font_dict_interpreter_t font_interp (env);
font = fontDicts.push ();
- if (unlikely (fontDicts.in_error ())) { fini (); return; }
+ if (unlikely (fontDicts.in_error ())) goto fail;
font->init ();
- if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
+ if (unlikely (!font_interp.interpret (*font))) goto fail;
PRIVDICTVAL *priv = &privateDicts[i];
const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
- if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+ if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
num_interp_env_t env2 (privDictStr);
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
priv->init ();
- if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+ if (unlikely (!priv_interp.interpret (*priv))) goto fail;
priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
if (priv->localSubrs != &Null (CFF1Subrs) &&
unlikely (!priv->localSubrs->sanitize (&sc)))
- { fini (); return; }
+ goto fail;
}
}
else /* non-CID */
@@ -1160,20 +1194,25 @@ struct cff1
PRIVDICTVAL *priv = &privateDicts[0];
const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
- if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+ if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
num_interp_env_t env (privDictStr);
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
priv->init ();
- if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+ if (unlikely (!priv_interp.interpret (*priv))) goto fail;
priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
if (priv->localSubrs != &Null (CFF1Subrs) &&
unlikely (!priv->localSubrs->sanitize (&sc)))
- { fini (); return; }
+ goto fail;
}
- }
- void fini ()
+ return;
+
+ fail:
+ _fini ();
+ }
+ ~accelerator_templ_t () { _fini (); }
+ void _fini ()
{
sc.end_processing ();
topDict.fini ();
@@ -1183,6 +1222,8 @@ struct cff1
blob = nullptr;
}
+ hb_blob_t *get_blob () const { return blob; }
+
bool is_valid () const { return blob; }
bool is_CID () const { return topDict.is_CID (); }
@@ -1203,13 +1244,14 @@ struct cff1
bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
- hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
+ hb_codepoint_t glyph_to_code (hb_codepoint_t glyph,
+ code_pair_t *glyph_to_sid_cache = nullptr) const
{
if (encoding != &Null (Encoding))
return encoding->get_code (glyph);
else
{
- hb_codepoint_t sid = glyph_to_sid (glyph);
+ hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache);
if (sid == 0) return 0;
hb_codepoint_t code = 0;
switch (topDict.EncodingOffset)
@@ -1227,12 +1269,14 @@ struct cff1
}
}
- hb_map_t *create_glyph_to_sid_map () const
+ glyph_to_sid_map_t *create_glyph_to_sid_map () const
{
if (charset != &Null (Charset))
{
- hb_map_t *mapping = hb_map_create ();
- mapping->set (0, 0);
+ auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t));
+ if (unlikely (!mapping)) return nullptr;
+ mapping = new (mapping) glyph_to_sid_map_t ();
+ mapping->push (code_pair_t {0, 1});
charset->collect_glyph_to_sid_map (mapping, num_glyphs);
return mapping;
}
@@ -1240,10 +1284,11 @@ struct cff1
return nullptr;
}
- hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
+ hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph,
+ code_pair_t *cache = nullptr) const
{
if (charset != &Null (Charset))
- return charset->get_sid (glyph, num_glyphs);
+ return charset->get_sid (glyph, num_glyphs, cache);
else
{
hb_codepoint_t sid = 0;
@@ -1312,19 +1357,17 @@ struct cff1
hb_vector_t<PRIVDICTVAL> privateDicts;
unsigned int num_glyphs = 0;
+ unsigned int num_charset_entries = 0;
};
struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
{
- accelerator_t (hb_face_t *face)
+ accelerator_t (hb_face_t *face) : SUPER (face)
{
- SUPER::init (face);
-
glyph_names.set_relaxed (nullptr);
if (!is_valid ()) return;
if (is_CID ()) return;
-
}
~accelerator_t ()
{
@@ -1334,8 +1377,6 @@ struct cff1
names->fini ();
hb_free (names);
}
-
- SUPER::fini ();
}
bool get_glyph_name (hb_codepoint_t glyph,
@@ -1386,9 +1427,10 @@ struct cff1
/* TODO */
/* fill glyph names */
+ code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
{
- hb_codepoint_t sid = glyph_to_sid (gid);
+ hb_codepoint_t sid = glyph_to_sid (gid, &glyph_to_sid_cache);
gname_t gname;
gname.sid = sid;
if (sid < cff1_std_strings_length)
@@ -1426,7 +1468,6 @@ struct cff1
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
- HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
private:
@@ -1453,9 +1494,24 @@ struct cff1
typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
};
- struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {};
+ struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t>
+ {
+ accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
+ ~accelerator_subset_t ()
+ {
+ if (cff_accelerator)
+ cff_subset_accelerator_t::destroy (cff_accelerator);
+ }
- bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); }
+ HB_INTERNAL bool subset (hb_subset_context_t *c) const;
+ HB_INTERNAL bool serialize (hb_serialize_context_t *c,
+ struct cff1_subset_plan &plan) const;
+ HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
+
+ mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
+
+ typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER;
+ };
protected:
HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
@@ -1479,6 +1535,10 @@ struct cff1_accelerator_t : cff1::accelerator_t {
cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
};
+struct cff1_subset_accelerator_t : cff1::accelerator_subset_t {
+ cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {}
+};
+
} /* namespace OT */
#endif /* HB_OT_CFF1_TABLE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh
index 2134d48660..af24bb9986 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh
@@ -28,7 +28,7 @@
#define HB_OT_CFF2_TABLE_HH
#include "hb-ot-cff-common.hh"
-#include "hb-subset-cff2.hh"
+#include "hb-subset-cff-common.hh"
#include "hb-draw.hh"
#include "hb-paint.hh"
@@ -41,7 +41,6 @@ namespace CFF {
#define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2')
typedef CFFIndex<HBUINT32> CFF2Index;
-template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {};
typedef CFF2Index CFF2CharStrings;
typedef Subrs<HBUINT32> CFF2Subrs;
@@ -391,8 +390,12 @@ struct cff2
template <typename PRIVOPSET, typename PRIVDICTVAL>
struct accelerator_templ_t
{
+ static constexpr hb_tag_t tableTag = cff2::tableTag;
+
accelerator_templ_t (hb_face_t *face)
{
+ if (!face) return;
+
topDict.init ();
fontDicts.init ();
privateDicts.init ();
@@ -464,7 +467,6 @@ struct cff2
goto fail;
}
-
return;
fail:
@@ -481,11 +483,13 @@ struct cff2
blob = nullptr;
}
- hb_map_t *create_glyph_to_sid_map () const
+ hb_vector_t<uint16_t> *create_glyph_to_sid_map () const
{
return nullptr;
}
+ hb_blob_t *get_blob () const { return blob; }
+
bool is_valid () const { return blob; }
protected:
@@ -518,9 +522,24 @@ struct cff2
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
};
- typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
+ struct accelerator_subset_t : accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t>
+ {
+ accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
+ ~accelerator_subset_t ()
+ {
+ if (cff_accelerator)
+ cff_subset_accelerator_t::destroy (cff_accelerator);
+ }
+
+ HB_INTERNAL bool subset (hb_subset_context_t *c) const;
+ HB_INTERNAL bool serialize (hb_serialize_context_t *c,
+ struct cff2_subset_plan &plan,
+ hb_array_t<int> normalized_coords) const;
+
+ mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
- bool subset (hb_subset_context_t *c) const { return hb_subset_cff2 (c); }
+ typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> SUPER;
+ };
public:
FixedVersion<HBUINT8> version; /* Version of CFF2 table. set to 0x0200u */
@@ -535,6 +554,10 @@ struct cff2_accelerator_t : cff2::accelerator_t {
cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {}
};
+struct cff2_subset_accelerator_t : cff2::accelerator_subset_t {
+ cff2_subset_accelerator_t (hb_face_t *face) : cff2::accelerator_subset_t (face) {}
+};
+
} /* namespace OT */
#endif /* HB_OT_CFF2_TABLE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
index cf5ccd53e9..30401b1926 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
@@ -277,10 +277,10 @@ struct CmapSubtableFormat4
}
} writer(c);
- writer.end_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
- c->allocate_size<HBUINT16> (2); // padding
- writer.start_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
- writer.id_delta_ = c->allocate_size<HBINT16> (HBINT16::static_size * segcount);
+ writer.end_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount, false);
+ (void) c->allocate_size<HBUINT16> (2); // padding
+ writer.start_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount, false);
+ writer.id_delta_ = c->allocate_size<HBINT16> (HBINT16::static_size * segcount, false);
if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false;
@@ -325,7 +325,7 @@ struct CmapSubtableFormat4
{
auto format4_iter =
+ it
- | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
+ | hb_filter ([&] (const hb_codepoint_pair_t _)
{ return _.first <= 0xFFFF; })
;
@@ -335,7 +335,7 @@ struct CmapSubtableFormat4
if (unlikely (!c->extend_min (this))) return;
this->format = 4;
- hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> cp_to_gid {
+ hb_vector_t<hb_codepoint_pair_t> cp_to_gid {
format4_iter
};
@@ -757,8 +757,7 @@ struct CmapSubtableLongSegmented
hb_codepoint_t gid = this->groups[i].glyphID;
if (!gid)
{
- /* Intention is: if (hb_is_same (T, CmapSubtableFormat13)) continue; */
- if (! T::group_get_glyph (this->groups[i], end)) continue;
+ if (T::formatNumber == 13) continue;
start++;
gid++;
}
@@ -766,11 +765,13 @@ struct CmapSubtableLongSegmented
if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
end = start + (hb_codepoint_t) num_glyphs - gid;
+ mapping->alloc (mapping->get_population () + end - start + 1);
+
for (unsigned cp = start; cp <= end; cp++)
{
unicodes->add (cp);
mapping->set (cp, gid);
- gid++;
+ gid += T::increment;
}
}
}
@@ -794,6 +795,9 @@ struct CmapSubtableLongSegmented
struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
{
+ static constexpr int increment = 1;
+ static constexpr int formatNumber = 12;
+
static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
hb_codepoint_t u)
{ return likely (group.startCharCode <= group.endCharCode) ?
@@ -866,6 +870,9 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
{
+ static constexpr int increment = 0;
+ static constexpr int formatNumber = 13;
+
static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
hb_codepoint_t u HB_UNUSED)
{ return group.glyphID; }
@@ -917,8 +924,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
DefaultUVS* copy (hb_serialize_context_t *c,
const hb_set_t *unicodes) const
{
- DefaultUVS *out = c->start_embed<DefaultUVS> ();
- if (unlikely (!out)) return nullptr;
+ auto *out = c->start_embed<DefaultUVS> ();
auto snap = c->snapshot ();
HBUINT32 len;
@@ -931,8 +937,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
hb_codepoint_t start = HB_SET_VALUE_INVALID;
hb_codepoint_t end = HB_SET_VALUE_INVALID;
- for (hb_codepoint_t u = HB_SET_VALUE_INVALID;
- unicodes->next (&u);)
+ for (auto u : *unicodes)
{
if (!as_array ().bsearch (u))
continue;
@@ -1067,9 +1072,7 @@ struct NonDefaultUVS : SortedArray32Of<UVSMapping>
const hb_set_t *glyphs_requested,
const hb_map_t *glyph_map) const
{
- NonDefaultUVS *out = c->start_embed<NonDefaultUVS> ();
- if (unlikely (!out)) return nullptr;
-
+ auto *out = c->start_embed<NonDefaultUVS> ();
auto it =
+ as_array ()
| hb_filter ([&] (const UVSMapping& _)
@@ -1767,7 +1770,6 @@ struct cmap
TRACE_SUBSET (this);
cmap *cmap_prime = c->serializer->start_embed<cmap> ();
- if (unlikely (!c->serializer->check_success (cmap_prime))) return_trace (false);
auto encodingrec_iter =
+ hb_iter (encodingRecord)
@@ -1798,7 +1800,7 @@ struct cmap
auto it =
+ c->plan->unicode_to_new_gid_list.iter ()
- | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
+ | hb_filter ([&] (const hb_codepoint_pair_t _)
{ return (_.second != HB_MAP_VALUE_INVALID); })
;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
index c89a1954a9..b3677c6a4c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
@@ -38,8 +38,8 @@
#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
-#include "hb-ot-cff1-table.hh"
#include "hb-ot-cff2-table.hh"
+#include "hb-ot-cff1-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-post-table.hh"
#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
@@ -98,7 +98,7 @@ _hb_ot_font_create (hb_font_t *font)
{
cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t));
if (unlikely (!cmap_cache)) goto out;
- cmap_cache->init ();
+ new (cmap_cache) hb_ot_font_cmap_cache_t ();
if (unlikely (!hb_face_set_user_data (font->face,
&hb_ot_font_cmap_cache_user_data_key,
cmap_cache,
@@ -230,8 +230,8 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
use_cache = false;
goto out;
}
+ new (cache) hb_ot_font_advance_cache_t;
- cache->init ();
if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
{
hb_free (cache);
@@ -255,7 +255,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
{ /* Use cache. */
if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords)
{
- ot_font->advance_cache->init ();
+ ot_font->advance_cache->clear ();
ot_font->cached_coords_serial.set_release (font->serial_coords);
}
@@ -436,8 +436,8 @@ hb_ot_get_glyph_extents (hb_font_t *font,
#endif
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
#ifndef HB_NO_OT_FONT_CFF
- if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
+ if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
#endif
return false;
@@ -525,8 +525,8 @@ hb_ot_draw_glyph (hb_font_t *font,
embolden ? &outline : draw_data, font->slant_xy);
if (!font->face->table.glyf->get_path (font, glyph, draw_session))
#ifndef HB_NO_CFF
- if (!font->face->table.cff1->get_path (font, glyph, draw_session))
if (!font->face->table.cff2->get_path (font, glyph, draw_session))
+ if (!font->face->table.cff1->get_path (font, glyph, draw_session))
#endif
{}
}
@@ -565,8 +565,8 @@ hb_ot_paint_glyph (hb_font_t *font,
#endif
if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
#ifndef HB_NO_CFF
- if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
+ if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
#endif
}
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh
index 3bfd75502a..cbcf6f5f22 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh
@@ -46,21 +46,23 @@ struct DeviceRecord
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
- bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it)
+ bool serialize (hb_serialize_context_t *c,
+ unsigned pixelSize,
+ Iterator it,
+ const hb_vector_t<hb_codepoint_pair_t> new_to_old_gid_list,
+ unsigned num_glyphs)
{
TRACE_SERIALIZE (this);
- unsigned length = it.len ();
-
- if (unlikely (!c->extend (this, length))) return_trace (false);
+ if (unlikely (!c->extend (this, num_glyphs))) return_trace (false);
this->pixelSize = pixelSize;
this->maxWidth =
+ it
| hb_reduce (hb_max, 0u);
- + it
- | hb_sink (widthsZ.as_array (length));
+ for (auto &_ : new_to_old_gid_list)
+ widthsZ[_.first] = *it++;
return_trace (true);
}
@@ -89,7 +91,11 @@ struct hdmx
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
- bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
+ bool serialize (hb_serialize_context_t *c,
+ unsigned version,
+ Iterator it,
+ const hb_vector_t<hb_codepoint_pair_t> &new_to_old_gid_list,
+ unsigned num_glyphs)
{
TRACE_SERIALIZE (this);
@@ -97,10 +103,10 @@ struct hdmx
this->version = version;
this->numRecords = it.len ();
- this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0);
+ this->sizeDeviceRecord = DeviceRecord::get_size (num_glyphs);
for (const hb_item_type<Iterator>& _ : +it)
- c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
+ c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second, new_to_old_gid_list, num_glyphs);
return_trace (c->successful ());
}
@@ -110,31 +116,30 @@ struct hdmx
{
TRACE_SUBSET (this);
- hdmx *hdmx_prime = c->serializer->start_embed <hdmx> ();
- if (unlikely (!hdmx_prime)) return_trace (false);
+ auto *hdmx_prime = c->serializer->start_embed <hdmx> ();
+ unsigned num_input_glyphs = get_num_glyphs ();
auto it =
+ hb_range ((unsigned) numRecords)
- | hb_map ([c, this] (unsigned _)
+ | hb_map ([c, num_input_glyphs, this] (unsigned _)
{
const DeviceRecord *device_record =
&StructAtOffset<DeviceRecord> (&firstDeviceRecord,
_ * sizeDeviceRecord);
auto row =
- + hb_range (c->plan->num_output_glyphs ())
- | hb_map (c->plan->reverse_glyph_map)
- | hb_map ([this, c, device_record] (hb_codepoint_t _)
+ + hb_iter (c->plan->new_to_old_gid_list)
+ | hb_map ([num_input_glyphs, device_record] (hb_codepoint_pair_t _)
{
- if (c->plan->is_empty_glyph (_))
- return Null (HBUINT8);
- return device_record->widthsZ.as_array (get_num_glyphs ()) [_];
+ return device_record->widthsZ.as_array (num_input_glyphs) [_.second];
})
;
return hb_pair ((unsigned) device_record->pixelSize, +row);
})
;
- hdmx_prime->serialize (c->serializer, version, it);
+ hdmx_prime->serialize (c->serializer, version, it,
+ c->plan->new_to_old_gid_list,
+ c->plan->num_output_glyphs ());
return_trace (true);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
index 835a1a585e..89640b43f1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
@@ -83,7 +83,7 @@ struct hmtxvmtx
bool subset_update_header (hb_subset_context_t *c,
unsigned int num_hmetrics,
const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map,
- const hb_map_t *bounds_map) const
+ const hb_vector_t<unsigned> &bounds_vec) const
{
hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (c->plan->source, H::tableTag);
hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
@@ -114,6 +114,7 @@ struct hmtxvmtx
HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET, caretOffset);
}
+ bool empty = true;
int min_lsb = 0x7FFF;
int min_rsb = 0x7FFF;
int max_extent = -0x7FFF;
@@ -125,9 +126,10 @@ struct hmtxvmtx
int lsb = _.second.second;
max_adv = hb_max (max_adv, adv);
- if (bounds_map->has (gid))
+ if (bounds_vec[gid] != 0xFFFFFFFF)
{
- unsigned bound_width = bounds_map->get (gid);
+ empty = false;
+ unsigned bound_width = bounds_vec[gid];
int rsb = adv - lsb - bound_width;
int extent = lsb + bound_width;
min_lsb = hb_min (min_lsb, lsb);
@@ -137,7 +139,7 @@ struct hmtxvmtx
}
table->advanceMax = max_adv;
- if (!bounds_map->is_empty ())
+ if (!empty)
{
table->minLeadingBearing = min_lsb;
table->minTrailingBearing = min_rsb;
@@ -156,32 +158,32 @@ struct hmtxvmtx
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
- unsigned num_long_metrics)
+ const hb_vector_t<hb_codepoint_pair_t> new_to_old_gid_list,
+ unsigned num_long_metrics,
+ unsigned total_num_metrics)
{
- unsigned idx = 0;
- for (auto _ : it)
+ LongMetric* long_metrics = c->allocate_size<LongMetric> (num_long_metrics * LongMetric::static_size);
+ FWORD* short_metrics = c->allocate_size<FWORD> ((total_num_metrics - num_long_metrics) * FWORD::static_size);
+ if (!long_metrics || !short_metrics) return;
+
+ short_metrics -= num_long_metrics;
+
+ for (auto _ : new_to_old_gid_list)
{
- if (idx < num_long_metrics)
- {
- LongMetric lm;
- lm.advance = _.first;
- lm.sb = _.second;
- if (unlikely (!c->embed<LongMetric> (&lm))) return;
- }
- else if (idx < 0x10000u)
+ hb_codepoint_t gid = _.first;
+ auto mtx = *it++;
+
+ if (gid < num_long_metrics)
{
- FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
- if (unlikely (!sb)) return;
- *sb = _.second;
+ LongMetric& lm = long_metrics[gid];
+ lm.advance = mtx.first;
+ lm.sb = mtx.second;
}
+ // TODO(beyond-64k): This assumes that maxp.numGlyphs is 0xFFFF.
+ else if (gid < 0x10000u)
+ short_metrics[gid] = mtx.second;
else
- {
- // TODO: This does not do tail optimization.
- UFWORD *adv = c->allocate_size<UFWORD> (UFWORD::static_size);
- if (unlikely (!adv)) return;
- *adv = _.first;
- }
- idx++;
+ ((UFWORD*) short_metrics)[gid] = mtx.first;
}
}
@@ -189,8 +191,7 @@ struct hmtxvmtx
{
TRACE_SUBSET (this);
- T *table_prime = c->serializer->start_embed <T> ();
- if (unlikely (!table_prime)) return_trace (false);
+ auto *table_prime = c->serializer->start_embed <T> ();
accelerator_t _mtx (c->plan->source);
unsigned num_long_metrics;
@@ -199,6 +200,8 @@ struct hmtxvmtx
/* Determine num_long_metrics to encode. */
auto& plan = c->plan;
+ // TODO Don't consider retaingid holes here.
+
num_long_metrics = hb_min (plan->num_output_glyphs (), 0xFFFFu);
unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx);
while (num_long_metrics > 1 &&
@@ -209,31 +212,36 @@ struct hmtxvmtx
}
auto it =
- + hb_range (c->plan->num_output_glyphs ())
- | hb_map ([c, &_mtx, mtx_map] (unsigned _)
+ + hb_iter (c->plan->new_to_old_gid_list)
+ | hb_map ([c, &_mtx, mtx_map] (hb_codepoint_pair_t _)
{
- if (!mtx_map->has (_))
+ hb_codepoint_t new_gid = _.first;
+ hb_codepoint_t old_gid = _.second;
+
+ hb_pair_t<unsigned, int> *v = nullptr;
+ if (!mtx_map->has (new_gid, &v))
{
- hb_codepoint_t old_gid;
- if (!c->plan->old_gid_for_new_gid (_, &old_gid))
- return hb_pair (0u, 0);
int lsb = 0;
if (!_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
(void) _glyf_get_leading_bearing_without_var_unscaled (c->plan->source, old_gid, !T::is_horizontal, &lsb);
return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
}
- return mtx_map->get (_);
+ return *v;
})
;
- table_prime->serialize (c->serializer, it, num_long_metrics);
+ table_prime->serialize (c->serializer,
+ it,
+ c->plan->new_to_old_gid_list,
+ num_long_metrics,
+ c->plan->num_output_glyphs ());
if (unlikely (c->serializer->in_error ()))
return_trace (false);
// Amend header num hmetrics
if (unlikely (!subset_update_header (c, num_long_metrics, mtx_map,
- T::is_horizontal ? &c->plan->bounds_width_map : &c->plan->bounds_height_map)))
+ T::is_horizontal ? c->plan->bounds_width_vec : c->plan->bounds_height_vec)))
return_trace (false);
return_trace (true);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh
index 8179e5acd5..2b7e9e4b18 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh
@@ -170,8 +170,8 @@ struct FeatMinMaxRecord
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
- minCoord.sanitize (c, this) &&
- maxCoord.sanitize (c, this)));
+ minCoord.sanitize (c, base) &&
+ maxCoord.sanitize (c, base)));
}
protected:
@@ -187,7 +187,6 @@ struct FeatMinMaxRecord
* of MinMax table (may be NULL) */
public:
DEFINE_SIZE_STATIC (8);
-
};
struct MinMax
@@ -274,7 +273,7 @@ struct BaseLangSysRecord
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
- minMax.sanitize (c, this)));
+ minMax.sanitize (c, base)));
}
protected:
@@ -297,7 +296,8 @@ struct BaseScript
const BaseCoord &get_base_coord (int baseline_tag_index) const
{ return (this+baseValues).get_base_coord (baseline_tag_index); }
- bool has_data () const { return baseValues; }
+ bool has_values () const { return baseValues; }
+ bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -383,7 +383,7 @@ struct Axis
const BaseCoord **coord) const
{
const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
- if (!base_script.has_data ())
+ if (!base_script.has_values ())
{
*coord = nullptr;
return false;
@@ -410,7 +410,7 @@ struct Axis
const BaseCoord **max_coord) const
{
const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
- if (!base_script.has_data ())
+ if (!base_script.has_min_max ())
{
*min_coord = *max_coord = nullptr;
return false;
@@ -425,8 +425,8 @@ struct Axis
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
- (this+baseTagList).sanitize (c) &&
- (this+baseScriptList).sanitize (c)));
+ baseTagList.sanitize (c, this) &&
+ baseScriptList.sanitize (c, this)));
}
protected:
@@ -473,14 +473,13 @@ struct BASE
return true;
}
- /* TODO: Expose this separately sometime? */
bool get_min_max (hb_font_t *font,
hb_direction_t direction,
hb_tag_t script_tag,
hb_tag_t language_tag,
hb_tag_t feature_tag,
hb_position_t *min,
- hb_position_t *max)
+ hb_position_t *max) const
{
const BaseCoord *min_coord, *max_coord;
if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh
index 36f123b559..0831e4499e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh
@@ -55,19 +55,22 @@ static bool ClassDef_remap_and_serialize (
hb_serialize_context_t *c,
const hb_set_t &klasses,
bool use_class_zero,
- hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_sorted_vector_t<hb_codepoint_pair_t> &glyph_and_klass, /* IN/OUT */
hb_map_t *klass_map /*IN/OUT*/);
struct hb_collect_feature_substitutes_with_var_context_t
{
const hb_map_t *axes_index_tag_map;
- const hb_hashmap_t<hb_tag_t, int> *axes_location;
+ const hb_hashmap_t<hb_tag_t, Triple> *axes_location;
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map;
hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
+ bool& insert_catch_all_feature_variation_record;
// not stored in subset_plan
hb_set_t *feature_indices;
bool apply;
+ bool variation_applied;
+ bool universal;
unsigned cur_record_idx;
hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map;
};
@@ -807,7 +810,7 @@ struct Feature
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->featureParams.serialize_subset (c, featureParams, this, tag);
@@ -981,7 +984,7 @@ struct RecordListOfFeature : RecordListOf<Feature>
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ hb_enumerate (*this)
| hb_filter (l->feature_index_map, hb_first)
@@ -1078,7 +1081,7 @@ struct LangSys
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
const uint32_t *v;
out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
@@ -1188,7 +1191,7 @@ struct Script
return false;
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
bool defaultLang = false;
if (has_default_lang_sys ())
@@ -1247,7 +1250,7 @@ struct RecordListOfScript : RecordListOf<Script>
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
for (auto _ : + hb_enumerate (*this))
{
@@ -1367,7 +1370,7 @@ struct Lookup
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->lookupType = lookupType;
out->lookupFlag = lookupFlag;
@@ -1456,7 +1459,7 @@ struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ hb_enumerate (*this)
| hb_filter (l->lookup_index_map, hb_first)
@@ -1482,7 +1485,7 @@ struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
static bool ClassDef_remap_and_serialize (hb_serialize_context_t *c,
const hb_set_t &klasses,
bool use_class_zero,
- hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_sorted_vector_t<hb_codepoint_pair_t> &glyph_and_klass, /* IN/OUT */
hb_map_t *klass_map /*IN/OUT*/)
{
if (!klass_map)
@@ -1573,7 +1576,7 @@ struct ClassDefFormat1_3
TRACE_SUBSET (this);
const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
- hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
+ hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass;
hb_set_t orig_klasses;
hb_codepoint_t start = startGlyph;
@@ -1592,10 +1595,13 @@ struct ClassDefFormat1_3
orig_klasses.add (klass);
}
- unsigned glyph_count = glyph_filter
- ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter))
- : glyph_map.get_population ();
- use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+ if (use_class_zero)
+ {
+ unsigned glyph_count = glyph_filter
+ ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter))
+ : glyph_map.get_population ();
+ use_class_zero = glyph_count <= glyph_and_klass.length;
+ }
if (!ClassDef_remap_and_serialize (c->serializer,
orig_klasses,
use_class_zero,
@@ -1830,7 +1836,7 @@ struct ClassDefFormat2_4
const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
const hb_set_t &glyph_set = *c->plan->glyphset_gsub ();
- hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
+ hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass;
hb_set_t orig_klasses;
if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2
@@ -1916,7 +1922,7 @@ struct ClassDefFormat2_4
{
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
{
- for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ for (auto g : *glyphs)
if (get_class (g))
return true;
return false;
@@ -1931,13 +1937,22 @@ struct ClassDefFormat2_4
{
/* Match if there's any glyph that is not listed! */
hb_codepoint_t g = HB_SET_VALUE_INVALID;
- for (auto &range : rangeRecord)
+ hb_codepoint_t last = HB_SET_VALUE_INVALID;
+ auto it = hb_iter (rangeRecord);
+ for (auto &range : it)
{
+ if (it->first == last + 1)
+ {
+ it++;
+ continue;
+ }
+
if (!glyphs->next (&g))
break;
if (g < range.first)
return true;
g = range.last;
+ last = g;
}
if (g != HB_SET_VALUE_INVALID && glyphs->next (&g))
return true;
@@ -1976,8 +1991,7 @@ struct ClassDefFormat2_4
unsigned count = rangeRecord.len;
if (count > glyphs->get_population () * hb_bit_storage (count) * 8)
{
- for (hb_codepoint_t g = HB_SET_VALUE_INVALID;
- glyphs->next (&g);)
+ for (auto g : *glyphs)
{
unsigned i;
if (rangeRecord.as_array ().bfind (g, &i) &&
@@ -2377,7 +2391,7 @@ struct VarRegionList
return_trace (c->check_struct (this) && axesZ.sanitize (c, axisCount * regionCount));
}
- bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_bimap_t &region_map)
+ bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_inc_bimap_t &region_map)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
@@ -2494,7 +2508,7 @@ struct VarData
bool serialize (hb_serialize_context_t *c,
const VarData *src,
const hb_inc_bimap_t &inner_map,
- const hb_bimap_t &region_map)
+ const hb_inc_bimap_t &region_map)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
@@ -2905,9 +2919,9 @@ struct VariationStore
enum Cond_with_Var_flag_t
{
KEEP_COND_WITH_VAR = 0,
- DROP_COND_WITH_VAR = 1,
- DROP_RECORD_WITH_VAR = 2,
- MEM_ERR_WITH_VAR = 3,
+ KEEP_RECORD_WITH_VAR = 1,
+ DROP_COND_WITH_VAR = 2,
+ DROP_RECORD_WITH_VAR = 3,
};
struct ConditionFormat1
@@ -2923,9 +2937,29 @@ struct ConditionFormat1
const hb_map_t *index_map = &c->plan->axes_index_map;
if (index_map->is_empty ()) return_trace (true);
- if (!index_map->has (axisIndex))
+ const hb_map_t& axes_old_index_tag_map = c->plan->axes_old_index_tag_map;
+ hb_codepoint_t *axis_tag;
+ if (!axes_old_index_tag_map.has (axisIndex, &axis_tag) ||
+ !index_map->has (axisIndex))
return_trace (false);
+ const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location = c->plan->axes_location;
+ Triple axis_limit{-1.f, 0.f, 1.f};
+ Triple *normalized_limit;
+ if (normalized_axes_location.has (*axis_tag, &normalized_limit))
+ axis_limit = *normalized_limit;
+
+ const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances = c->plan->axes_triple_distances;
+ TripleDistances axis_triple_distances{1.f, 1.f};
+ TripleDistances *triple_dists;
+ if (axes_triple_distances.has (*axis_tag, &triple_dists))
+ axis_triple_distances = *triple_dists;
+
+ float normalized_min = renormalizeValue (filterRangeMinValue.to_float (), axis_limit, axis_triple_distances, false);
+ float normalized_max = renormalizeValue (filterRangeMaxValue.to_float (), axis_limit, axis_triple_distances, false);
+ out->filterRangeMinValue.set_float (normalized_min);
+ out->filterRangeMaxValue.set_float (normalized_max);
+
return_trace (c->serializer->check_assign (out->axisIndex, index_map->get (axisIndex),
HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
@@ -2940,29 +2974,45 @@ struct ConditionFormat1
hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
- //axis not pinned, keep the condition
- if (!c->axes_location->has (axis_tag))
+ Triple axis_range (-1.f, 0.f, 1.f);
+ Triple *axis_limit;
+ if (c->axes_location->has (axis_tag, &axis_limit))
+ axis_range = *axis_limit;
+
+ float axis_min_val = axis_range.minimum;
+ float axis_default_val = axis_range.middle;
+ float axis_max_val = axis_range.maximum;
+
+ float filter_min_val = filterRangeMinValue.to_float ();
+ float filter_max_val = filterRangeMaxValue.to_float ();
+
+ if (axis_default_val < filter_min_val ||
+ axis_default_val > filter_max_val)
+ c->apply = false;
+
+ //condition not met, drop the entire record
+ if (axis_min_val > filter_max_val || axis_max_val < filter_min_val ||
+ filter_min_val > filter_max_val)
+ return DROP_RECORD_WITH_VAR;
+
+ //condition met and axis pinned, drop the condition
+ if (c->axes_location->has (axis_tag) &&
+ c->axes_location->get (axis_tag).is_point ())
+ return DROP_COND_WITH_VAR;
+
+ if (filter_max_val != axis_max_val || filter_min_val != axis_min_val)
{
// add axisIndex->value into the hashmap so we can check if the record is
// unique with variations
- int16_t min_val = filterRangeMinValue.to_int ();
- int16_t max_val = filterRangeMaxValue.to_int ();
- hb_codepoint_t val = (max_val << 16) + min_val;
+ int16_t int_filter_max_val = filterRangeMaxValue.to_int ();
+ int16_t int_filter_min_val = filterRangeMinValue.to_int ();
+ hb_codepoint_t val = (int_filter_max_val << 16) + int_filter_min_val;
condition_map->set (axisIndex, val);
return KEEP_COND_WITH_VAR;
}
- //axis pinned, check if condition is met
- //TODO: add check for axis Ranges
- int v = c->axes_location->get (axis_tag);
-
- //condition not met, drop the entire record
- if (v < filterRangeMinValue.to_int () || v > filterRangeMaxValue.to_int ())
- return DROP_RECORD_WITH_VAR;
-
- //axis pinned and condition met, drop the condition
- return DROP_COND_WITH_VAR;
+ return KEEP_RECORD_WITH_VAR;
}
bool evaluate (const int *coords, unsigned int coord_len) const
@@ -3001,7 +3051,7 @@ struct Condition
{
switch (u.format) {
case 1: return u.format1.keep_with_variations (c, condition_map);
- default:return KEEP_COND_WITH_VAR;
+ default: c->apply = false; return KEEP_COND_WITH_VAR;
}
}
@@ -3046,45 +3096,50 @@ struct ConditionSet
return true;
}
- Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+ void keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
{
hb_map_t *condition_map = hb_map_create ();
- if (unlikely (!condition_map)) return MEM_ERR_WITH_VAR;
+ if (unlikely (!condition_map)) return;
hb::shared_ptr<hb_map_t> p {condition_map};
hb_set_t *cond_set = hb_set_create ();
- if (unlikely (!cond_set)) return MEM_ERR_WITH_VAR;
+ if (unlikely (!cond_set)) return;
hb::shared_ptr<hb_set_t> s {cond_set};
+ c->apply = true;
+ bool should_keep = false;
unsigned num_kept_cond = 0, cond_idx = 0;
for (const auto& offset : conditions)
{
Cond_with_Var_flag_t ret = (this+offset).keep_with_variations (c, condition_map);
- // one condition is not met, drop the entire record
+ // condition is not met or condition out of range, drop the entire record
if (ret == DROP_RECORD_WITH_VAR)
- return DROP_RECORD_WITH_VAR;
+ return;
- // axis not pinned, keep this condition
if (ret == KEEP_COND_WITH_VAR)
{
+ should_keep = true;
cond_set->add (cond_idx);
num_kept_cond++;
}
+
+ if (ret == KEEP_RECORD_WITH_VAR)
+ should_keep = true;
+
cond_idx++;
}
- // all conditions met
- if (num_kept_cond == 0) return DROP_COND_WITH_VAR;
+ if (!should_keep) return;
//check if condition_set is unique with variations
if (c->conditionset_map->has (p))
//duplicate found, drop the entire record
- return DROP_RECORD_WITH_VAR;
+ return;
c->conditionset_map->set (p, 1);
c->record_cond_idx_map->set (c->cur_record_idx, s);
-
- return KEEP_COND_WITH_VAR;
+ if (should_keep && num_kept_cond == 0)
+ c->universal = true;
}
bool subset (hb_subset_context_t *c,
@@ -3289,12 +3344,11 @@ struct FeatureVariationRecord
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
const void *base) const
{
- // ret == 1, all conditions met
- if ((base+conditions).keep_with_variations (c) == DROP_COND_WITH_VAR &&
- c->apply)
+ (base+conditions).keep_with_variations (c);
+ if (c->apply && !c->variation_applied)
{
(base+substitutions).collect_feature_substitutes_with_variations (c);
- c->apply = false; // set variations only once
+ c->variation_applied = true; // set variations only once
}
}
@@ -3361,7 +3415,12 @@ struct FeatureVariations
{
c->cur_record_idx = i;
varRecords[i].collect_feature_substitutes_with_variations (c, this);
+ if (c->universal)
+ break;
}
+ if (c->variation_applied && !c->universal &&
+ !c->record_cond_idx_map->is_empty ())
+ c->insert_catch_all_feature_variation_record = true;
}
FeatureVariations* copy (hb_serialize_context_t *c) const
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh
index 8e5be92d12..662ec9d3e8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh
@@ -143,9 +143,12 @@ struct hb_closure_context_t :
return active_glyphs_stack.tail ();
}
- hb_set_t& push_cur_active_glyphs ()
+ hb_set_t* push_cur_active_glyphs ()
{
- return *active_glyphs_stack.push ();
+ hb_set_t *s = active_glyphs_stack.push ();
+ if (unlikely (active_glyphs_stack.in_error ()))
+ return nullptr;
+ return s;
}
bool pop_cur_done_glyphs ()
@@ -399,16 +402,6 @@ struct hb_ot_apply_context_t :
{
struct matcher_t
{
- matcher_t () :
- lookup_props (0),
- mask (-1),
- ignore_zwnj (false),
- ignore_zwj (false),
- per_syllable (false),
- syllable {0},
- match_func (nullptr),
- match_data (nullptr) {}
-
typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
@@ -427,6 +420,9 @@ struct hb_ot_apply_context_t :
MATCH_MAYBE
};
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
may_match_t may_match (hb_glyph_info_t &info,
hb_codepoint_t glyph_data) const
{
@@ -446,6 +442,9 @@ struct hb_ot_apply_context_t :
SKIP_MAYBE
};
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
may_skip_t may_skip (const hb_ot_apply_context_t *c,
const hb_glyph_info_t &info) const
{
@@ -461,14 +460,14 @@ struct hb_ot_apply_context_t :
}
protected:
- unsigned int lookup_props;
- hb_mask_t mask;
- bool ignore_zwnj;
- bool ignore_zwj;
- bool per_syllable;
- uint8_t syllable;
- match_func_t match_func;
- const void *match_data;
+ unsigned int lookup_props = 0;
+ hb_mask_t mask = -1;
+ bool ignore_zwnj = false;
+ bool ignore_zwj = false;
+ bool per_syllable = false;
+ uint8_t syllable = 0;
+ match_func_t match_func = nullptr;
+ const void *match_data = nullptr;
};
struct skipping_iterator_t
@@ -516,30 +515,34 @@ struct hb_ot_apply_context_t :
}
#endif
- void reset (unsigned int start_index_,
- unsigned int num_items_)
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
+ void reset (unsigned int start_index_)
{
idx = start_index_;
- num_items = num_items_;
end = c->buffer->len;
matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
}
- void reset_fast (unsigned int start_index_,
- unsigned int num_items_)
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
+ void reset_fast (unsigned int start_index_)
{
// Doesn't set end or syllable. Used by GPOS which doesn't care / change.
idx = start_index_;
- num_items = num_items_;
}
void reject ()
{
- num_items++;
backup_glyph_data ();
}
matcher_t::may_skip_t
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
may_skip (const hb_glyph_info_t &info) const
{ return matcher.may_skip (c, info); }
@@ -549,6 +552,9 @@ struct hb_ot_apply_context_t :
SKIP
};
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
match_t match (hb_glyph_info_t &info)
{
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
@@ -567,14 +573,12 @@ struct hb_ot_apply_context_t :
return SKIP;
}
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool next (unsigned *unsafe_to = nullptr)
{
- assert (num_items > 0);
- /* The alternate condition below is faster at string boundaries,
- * but produces subpar "unsafe-to-concat" values. */
- signed stop = (signed) end - (signed) num_items;
- if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT)
- stop = (signed) end - 1;
+ const signed stop = (signed) end - 1;
while ((signed) idx < stop)
{
idx++;
@@ -582,7 +586,6 @@ struct hb_ot_apply_context_t :
{
case MATCH:
{
- num_items--;
advance_glyph_data ();
return true;
}
@@ -600,14 +603,12 @@ struct hb_ot_apply_context_t :
*unsafe_to = end;
return false;
}
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool prev (unsigned *unsafe_from = nullptr)
{
- assert (num_items > 0);
- /* The alternate condition below is faster at string boundaries,
- * but produces subpar "unsafe-to-concat" values. */
- unsigned stop = num_items - 1;
- if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT)
- stop = 1 - 1;
+ const unsigned stop = 0;
while (idx > stop)
{
idx--;
@@ -615,7 +616,6 @@ struct hb_ot_apply_context_t :
{
case MATCH:
{
- num_items--;
advance_glyph_data ();
return true;
}
@@ -634,6 +634,7 @@ struct hb_ot_apply_context_t :
return false;
}
+ HB_ALWAYS_INLINE
hb_codepoint_t
get_glyph_data ()
{
@@ -644,6 +645,7 @@ struct hb_ot_apply_context_t :
#endif
return 0;
}
+ HB_ALWAYS_INLINE
void
advance_glyph_data ()
{
@@ -672,7 +674,6 @@ struct hb_ot_apply_context_t :
const HBUINT24 *match_glyph_data24;
#endif
- unsigned int num_items;
unsigned int end;
};
@@ -703,6 +704,7 @@ struct hb_ot_apply_context_t :
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
+ hb_sanitize_context_t sanitizer;
recurse_func_t recurse_func = nullptr;
const GDEF &gdef;
const GDEF::accelerator_t &gdef_accel;
@@ -729,9 +731,11 @@ struct hb_ot_apply_context_t :
hb_ot_apply_context_t (unsigned int table_index_,
hb_font_t *font_,
- hb_buffer_t *buffer_) :
+ hb_buffer_t *buffer_,
+ hb_blob_t *table_blob_) :
table_index (table_index_),
font (font_), face (font->face), buffer (buffer_),
+ sanitizer (table_blob_),
gdef (
#ifndef HB_NO_OT_LAYOUT
*face->table.GDEF->table
@@ -796,7 +800,7 @@ struct hb_ot_apply_context_t :
* match_props has the set index.
*/
if (match_props & LookupFlag::UseMarkFilteringSet)
- return gdef.mark_set_covers (match_props >> 16, glyph);
+ return gdef_accel.mark_set_covers (match_props >> 16, glyph);
/* The second byte of match_props has the meaning
* "ignore marks of attachment type different than
@@ -808,6 +812,9 @@ struct hb_ot_apply_context_t :
return true;
}
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool check_glyph_property (const hb_glyph_info_t *info,
unsigned int match_props) const
{
@@ -1165,6 +1172,10 @@ static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
}
+static inline bool match_always (hb_glyph_info_t &info HB_UNUSED, unsigned value HB_UNUSED, const void *data HB_UNUSED)
+{
+ return true;
+}
static inline bool match_glyph (hb_glyph_info_t &info, unsigned value, const void *data HB_UNUSED)
{
return info.codepoint == value;
@@ -1185,6 +1196,28 @@ static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, co
info.syllable() = klass;
return klass == value;
}
+static inline bool match_class_cached1 (hb_glyph_info_t &info, unsigned value, const void *data)
+{
+ unsigned klass = info.syllable() & 0x0F;
+ if (klass < 15)
+ return klass == value;
+ const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+ klass = class_def.get_class (info.codepoint);
+ if (likely (klass < 15))
+ info.syllable() = (info.syllable() & 0xF0) | klass;
+ return klass == value;
+}
+static inline bool match_class_cached2 (hb_glyph_info_t &info, unsigned value, const void *data)
+{
+ unsigned klass = (info.syllable() & 0xF0) >> 4;
+ if (klass < 15)
+ return klass == value;
+ const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+ klass = class_def.get_class (info.codepoint);
+ if (likely (klass < 15))
+ info.syllable() = (info.syllable() & 0x0F) | (klass << 4);
+ return klass == value;
+}
static inline bool match_coverage (hb_glyph_info_t &info, unsigned value, const void *data)
{
Offset16To<Coverage> coverage;
@@ -1213,14 +1246,17 @@ static inline bool would_match_input (hb_would_apply_context_t *c,
return true;
}
template <typename HBUINT>
-static inline bool match_input (hb_ot_apply_context_t *c,
- unsigned int count, /* Including the first glyph (not matched) */
- const HBUINT input[], /* Array of input values--start with second glyph */
- match_func_t match_func,
- const void *match_data,
- unsigned int *end_position,
- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
- unsigned int *p_total_component_count = nullptr)
+#ifndef HB_OPTIMIZE_SIZE
+HB_ALWAYS_INLINE
+#endif
+static bool match_input (hb_ot_apply_context_t *c,
+ unsigned int count, /* Including the first glyph (not matched) */
+ const HBUINT input[], /* Array of input values--start with second glyph */
+ match_func_t match_func,
+ const void *match_data,
+ unsigned int *end_position,
+ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
+ unsigned int *p_total_component_count = nullptr)
{
TRACE_APPLY (nullptr);
@@ -1229,7 +1265,7 @@ static inline bool match_input (hb_ot_apply_context_t *c,
hb_buffer_t *buffer = c->buffer;
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, count - 1);
+ skippy_iter.reset (buffer->idx);
skippy_iter.set_match_func (match_func, match_data);
skippy_iter.set_glyph_data (input);
@@ -1456,17 +1492,20 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
}
template <typename HBUINT>
-static inline bool match_backtrack (hb_ot_apply_context_t *c,
- unsigned int count,
- const HBUINT backtrack[],
- match_func_t match_func,
- const void *match_data,
- unsigned int *match_start)
+#ifndef HB_OPTIMIZE_SIZE
+HB_ALWAYS_INLINE
+#endif
+static bool match_backtrack (hb_ot_apply_context_t *c,
+ unsigned int count,
+ const HBUINT backtrack[],
+ match_func_t match_func,
+ const void *match_data,
+ unsigned int *match_start)
{
TRACE_APPLY (nullptr);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
- skippy_iter.reset (c->buffer->backtrack_len (), count);
+ skippy_iter.reset (c->buffer->backtrack_len ());
skippy_iter.set_match_func (match_func, match_data);
skippy_iter.set_glyph_data (backtrack);
@@ -1485,18 +1524,21 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
}
template <typename HBUINT>
-static inline bool match_lookahead (hb_ot_apply_context_t *c,
- unsigned int count,
- const HBUINT lookahead[],
- match_func_t match_func,
- const void *match_data,
- unsigned int start_index,
- unsigned int *end_index)
+#ifndef HB_OPTIMIZE_SIZE
+HB_ALWAYS_INLINE
+#endif
+static bool match_lookahead (hb_ot_apply_context_t *c,
+ unsigned int count,
+ const HBUINT lookahead[],
+ match_func_t match_func,
+ const void *match_data,
+ unsigned int start_index,
+ unsigned int *end_index)
{
TRACE_APPLY (nullptr);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
- skippy_iter.reset (start_index - 1, count);
+ skippy_iter.reset (start_index - 1);
skippy_iter.set_match_func (match_func, match_data);
skippy_iter.set_glyph_data (lookahead);
@@ -1615,10 +1657,13 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
}
covered_seq_indicies.add (seqIndex);
+ hb_set_t *cur_active_glyphs = c->push_cur_active_glyphs ();
+ if (unlikely (!cur_active_glyphs))
+ return;
if (has_pos_glyphs) {
- c->push_cur_active_glyphs () = std::move (pos_glyphs);
+ *cur_active_glyphs = std::move (pos_glyphs);
} else {
- c->push_cur_active_glyphs ().set (*c->glyphs);
+ *cur_active_glyphs = *c->glyphs;
}
unsigned endIndex = inputCount;
@@ -1868,12 +1913,13 @@ static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
}
template <typename HBUINT>
-static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
- unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT input[], /* Array of input values--start with second glyph */
- unsigned int lookupCount,
- const LookupRecord lookupRecord[],
- const ContextApplyLookupContext &lookup_context)
+HB_ALWAYS_INLINE
+static bool context_apply_lookup (hb_ot_apply_context_t *c,
+ unsigned int inputCount, /* Including the first glyph (not matched) */
+ const HBUINT input[], /* Array of input values--start with second glyph */
+ unsigned int lookupCount,
+ const LookupRecord lookupRecord[],
+ const ContextApplyLookupContext &lookup_context)
{
unsigned match_end = 0;
unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
@@ -1899,6 +1945,9 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
template <typename Types>
struct Rule
{
+ template <typename T>
+ friend struct RuleSet;
+
bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
{
return context_intersects (glyphs,
@@ -2001,8 +2050,7 @@ struct Rule
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (inputCount.sanitize (c) &&
- lookupCount.sanitize (c) &&
+ return_trace (c->check_struct (this) &&
c->check_range (inputZ.arrayZ,
inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
LookupRecord::static_size * lookupCount));
@@ -2086,13 +2134,105 @@ struct RuleSet
const ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
- return_trace (
- + hb_iter (rule)
- | hb_map (hb_add (this))
- | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); })
- | hb_any
- )
- ;
+
+ unsigned num_rules = rule.len;
+
+#ifndef HB_NO_OT_RULESETS_FAST_PATH
+ if (HB_OPTIMIZE_SIZE_VAL || num_rules <= 4)
+#endif
+ {
+ slow:
+ return_trace (
+ + hb_iter (rule)
+ | hb_map (hb_add (this))
+ | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); })
+ | hb_any
+ )
+ ;
+ }
+
+ /* This version is optimized for speed by matching the first & second
+ * components of the rule here, instead of calling into the matching code.
+ *
+ * Replicated from LigatureSet::apply(). */
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (c->buffer->idx);
+ skippy_iter.set_match_func (match_always, nullptr);
+ skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
+ unsigned unsafe_to = (unsigned) -1, unsafe_to1 = 0, unsafe_to2 = 0;
+ hb_glyph_info_t *first = nullptr, *second = nullptr;
+ bool matched = skippy_iter.next ();
+ if (likely (matched))
+ {
+ first = &c->buffer->info[skippy_iter.idx];
+ unsafe_to = skippy_iter.idx + 1;
+
+ if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
+ {
+ /* Can't use the fast path if eg. the next char is a default-ignorable
+ * or other skippable. */
+ goto slow;
+ }
+ }
+ else
+ {
+ /* Failed to match a next glyph. Only try applying rules that have
+ * no further input. */
+ return_trace (
+ + hb_iter (rule)
+ | hb_map (hb_add (this))
+ | hb_filter ([&] (const Rule &_) { return _.inputCount <= 1; })
+ | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); })
+ | hb_any
+ )
+ ;
+ }
+ matched = skippy_iter.next ();
+ if (likely (matched && !skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])))
+ {
+ second = &c->buffer->info[skippy_iter.idx];
+ unsafe_to2 = skippy_iter.idx + 1;
+ }
+
+ auto match_input = lookup_context.funcs.match;
+ auto *input_data = lookup_context.match_data;
+ for (unsigned int i = 0; i < num_rules; i++)
+ {
+ const auto &r = this+rule.arrayZ[i];
+
+ const auto &input = r.inputZ;
+
+ if (r.inputCount <= 1 ||
+ (!match_input ||
+ match_input (*first, input.arrayZ[0], input_data)))
+ {
+ if (!second ||
+ (r.inputCount <= 2 ||
+ (!match_input ||
+ match_input (*second, input.arrayZ[1], input_data)))
+ )
+ {
+ if (r.apply (c, lookup_context))
+ {
+ if (unsafe_to != (unsigned) -1)
+ c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
+ return_trace (true);
+ }
+ }
+ else
+ unsafe_to = unsafe_to2;
+ }
+ else
+ {
+ if (unsafe_to == (unsigned) -1)
+ unsafe_to = unsafe_to1;
+ }
+ }
+ if (likely (unsafe_to != (unsigned) -1))
+ c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
+
+ return_trace (false);
}
bool subset (hb_subset_context_t *c,
@@ -2168,8 +2308,9 @@ struct ContextFormat1_4
void closure (hb_closure_context_t *c) const
{
- hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
- get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs);
+ hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+ if (unlikely (!cur_active_glyphs)) return;
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (), *cur_active_glyphs);
struct ContextClosureLookupContext lookup_context = {
{intersects_glyph, intersected_glyph},
@@ -2338,9 +2479,10 @@ struct ContextFormat2_5
if (!(this+coverage).intersects (c->glyphs))
return;
- hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+ if (unlikely (!cur_active_glyphs)) return;
get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
- cur_active_glyphs);
+ *cur_active_glyphs);
const ClassDef &class_def = this+classDef;
@@ -2469,11 +2611,7 @@ struct ContextFormat2_5
if (cached && c->buffer->cur().syllable() < 255)
index = c->buffer->cur().syllable ();
else
- {
index = class_def.get_class (c->buffer->cur().codepoint);
- if (cached && index < 255)
- c->buffer->cur().syllable() = index;
- }
const RuleSet &rule_set = this+ruleSet[index];
return_trace (rule_set.apply (c, lookup_context));
}
@@ -2583,10 +2721,10 @@ struct ContextFormat3
if (!(this+coverageZ[0]).intersects (c->glyphs))
return;
- hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+ if (unlikely (!cur_active_glyphs)) return;
get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
- cur_active_glyphs);
-
+ *cur_active_glyphs);
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
struct ContextClosureLookupContext lookup_context = {
@@ -2687,14 +2825,14 @@ struct ContextFormat3
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- if (!c->check_struct (this)) return_trace (false);
+ if (unlikely (!c->check_struct (this))) return_trace (false);
unsigned int count = glyphCount;
- if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
- if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false);
+ if (unlikely (!count)) return_trace (false); /* We want to access coverageZ[0] freely. */
+ if (unlikely (!c->check_array (coverageZ.arrayZ, count))) return_trace (false);
for (unsigned int i = 0; i < count; i++)
- if (!coverageZ[i].sanitize (c, this)) return_trace (false);
+ if (unlikely (!coverageZ[i].sanitize (c, this))) return_trace (false);
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
- return_trace (c->check_array (lookupRecord, lookupCount));
+ return_trace (likely (c->check_array (lookupRecord, lookupCount)));
}
protected:
@@ -2867,16 +3005,17 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c
}
template <typename HBUINT>
-static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
- unsigned int backtrackCount,
- const HBUINT backtrack[],
- unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT input[], /* Array of input values--start with second glyph */
- unsigned int lookaheadCount,
- const HBUINT lookahead[],
- unsigned int lookupCount,
- const LookupRecord lookupRecord[],
- const ChainContextApplyLookupContext &lookup_context)
+HB_ALWAYS_INLINE
+static bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
+ unsigned int backtrackCount,
+ const HBUINT backtrack[],
+ unsigned int inputCount, /* Including the first glyph (not matched) */
+ const HBUINT input[], /* Array of input values--start with second glyph */
+ unsigned int lookaheadCount,
+ const HBUINT lookahead[],
+ unsigned int lookupCount,
+ const LookupRecord lookupRecord[],
+ const ChainContextApplyLookupContext &lookup_context)
{
unsigned end_index = c->buffer->idx;
unsigned match_end = 0;
@@ -2915,6 +3054,9 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
template <typename Types>
struct ChainRule
{
+ template <typename T>
+ friend struct ChainRuleSet;
+
bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
{
const auto &input = StructAfter<decltype (inputX)> (backtrack);
@@ -3014,8 +3156,6 @@ struct ChainRule
const hb_map_t *lookahead_map = nullptr) const
{
TRACE_SERIALIZE (this);
- auto *out = c->start_embed (this);
- if (unlikely (!out)) return_trace (false);
const hb_map_t *mapping = backtrack_map;
serialize_array (c, backtrack.len, + backtrack.iter ()
@@ -3077,13 +3217,14 @@ struct ChainRule
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- if (!backtrack.sanitize (c)) return_trace (false);
+ /* Hyper-optimized sanitized because this is really hot. */
+ if (unlikely (!backtrack.len.sanitize (c))) return_trace (false);
const auto &input = StructAfter<decltype (inputX)> (backtrack);
- if (!input.sanitize (c)) return_trace (false);
+ if (unlikely (!input.lenP1.sanitize (c))) return_trace (false);
const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
- if (!lookahead.sanitize (c)) return_trace (false);
+ if (unlikely (!lookahead.len.sanitize (c))) return_trace (false);
const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
- return_trace (lookup.sanitize (c));
+ return_trace (likely (lookup.sanitize (c)));
}
protected:
@@ -3091,7 +3232,7 @@ struct ChainRule
backtrack; /* Array of backtracking values
* (to be matched before the input
* sequence) */
- HeadlessArrayOf<typename Types::HBUINT>
+ HeadlessArray16Of<typename Types::HBUINT>
inputX; /* Array of input values (start with
* second glyph) */
Array16Of<typename Types::HBUINT>
@@ -3164,13 +3305,119 @@ struct ChainRuleSet
const ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
- return_trace (
- + hb_iter (rule)
- | hb_map (hb_add (this))
- | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); })
- | hb_any
- )
- ;
+
+ unsigned num_rules = rule.len;
+
+#ifndef HB_NO_OT_RULESETS_FAST_PATH
+ if (HB_OPTIMIZE_SIZE_VAL || num_rules <= 4)
+#endif
+ {
+ slow:
+ return_trace (
+ + hb_iter (rule)
+ | hb_map (hb_add (this))
+ | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); })
+ | hb_any
+ )
+ ;
+ }
+
+ /* This version is optimized for speed by matching the first & second
+ * components of the rule here, instead of calling into the matching code.
+ *
+ * Replicated from LigatureSet::apply(). */
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (c->buffer->idx);
+ skippy_iter.set_match_func (match_always, nullptr);
+ skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
+ unsigned unsafe_to = (unsigned) -1, unsafe_to1 = 0, unsafe_to2 = 0;
+ hb_glyph_info_t *first = nullptr, *second = nullptr;
+ bool matched = skippy_iter.next ();
+ if (likely (matched))
+ {
+ first = &c->buffer->info[skippy_iter.idx];
+ unsafe_to1 = skippy_iter.idx + 1;
+
+ if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
+ {
+ /* Can't use the fast path if eg. the next char is a default-ignorable
+ * or other skippable. */
+ goto slow;
+ }
+ }
+ else
+ {
+ /* Failed to match a next glyph. Only try applying rules that have
+ * no further input and lookahead. */
+ return_trace (
+ + hb_iter (rule)
+ | hb_map (hb_add (this))
+ | hb_filter ([&] (const ChainRule &_)
+ {
+ const auto &input = StructAfter<decltype (_.inputX)> (_.backtrack);
+ const auto &lookahead = StructAfter<decltype (_.lookaheadX)> (input);
+ return input.lenP1 <= 1 && lookahead.len == 0;
+ })
+ | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); })
+ | hb_any
+ )
+ ;
+ }
+ matched = skippy_iter.next ();
+ if (likely (matched && !skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])))
+ {
+ second = &c->buffer->info[skippy_iter.idx];
+ unsafe_to2 = skippy_iter.idx + 1;
+ }
+
+ auto match_input = lookup_context.funcs.match[1];
+ auto match_lookahead = lookup_context.funcs.match[2];
+ auto *input_data = lookup_context.match_data[1];
+ auto *lookahead_data = lookup_context.match_data[2];
+ for (unsigned int i = 0; i < num_rules; i++)
+ {
+ const auto &r = this+rule.arrayZ[i];
+
+ const auto &input = StructAfter<decltype (r.inputX)> (r.backtrack);
+ const auto &lookahead = StructAfter<decltype (r.lookaheadX)> (input);
+
+ unsigned lenP1 = hb_max ((unsigned) input.lenP1, 1u);
+ if (lenP1 > 1 ?
+ (!match_input ||
+ match_input (*first, input.arrayZ[0], input_data))
+ :
+ (!lookahead.len || !match_lookahead ||
+ match_lookahead (*first, lookahead.arrayZ[0], lookahead_data)))
+ {
+ if (!second ||
+ (lenP1 > 2 ?
+ (!match_input ||
+ match_input (*second, input.arrayZ[1], input_data))
+ :
+ (lookahead.len <= 2 - lenP1 || !match_lookahead ||
+ match_lookahead (*second, lookahead.arrayZ[2 - lenP1], lookahead_data))))
+ {
+ if (r.apply (c, lookup_context))
+ {
+ if (unsafe_to != (unsigned) -1)
+ c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
+ return_trace (true);
+ }
+ }
+ else
+ unsafe_to = unsafe_to2;
+ }
+ else
+ {
+ if (unsafe_to == (unsigned) -1)
+ unsafe_to = unsafe_to1;
+ }
+ }
+ if (likely (unsafe_to != (unsigned) -1))
+ c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
+
+ return_trace (false);
}
bool subset (hb_subset_context_t *c,
@@ -3251,9 +3498,10 @@ struct ChainContextFormat1_4
void closure (hb_closure_context_t *c) const
{
- hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+ if (unlikely (!cur_active_glyphs)) return;
get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
- cur_active_glyphs);
+ *cur_active_glyphs);
struct ChainContextClosureLookupContext lookup_context = {
{intersects_glyph, intersected_glyph},
@@ -3423,10 +3671,10 @@ struct ChainContextFormat2_5
if (!(this+coverage).intersects (c->glyphs))
return;
- hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+ if (unlikely (!cur_active_glyphs)) return;
get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
- cur_active_glyphs);
-
+ *cur_active_glyphs);
const ClassDef &backtrack_class_def = this+backtrackClassDef;
const ClassDef &input_class_def = this+inputClassDef;
@@ -3568,26 +3816,22 @@ struct ChainContextFormat2_5
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
- /* For ChainContextFormat2_5 we cache the LookaheadClassDef instead of InputClassDef.
- * The reason is that most heavy fonts want to identify a glyph in context and apply
- * a lookup to it. In this scenario, the length of the input sequence is one, whereas
- * the lookahead / backtrack are typically longer. The one glyph in input sequence is
- * looked-up below and no input glyph is looked up in individual rules, whereas the
- * lookahead and backtrack glyphs are tried. Since we match lookahead before backtrack,
- * we should cache lookahead. This decisions showed a 20% improvement in shaping of
- * the Gulzar font.
- */
-
+ /* match_class_caches1 is slightly faster. Use it for lookahead,
+ * which is typically longer. */
struct ChainContextApplyLookupContext lookup_context = {
- {{cached && &backtrack_class_def == &lookahead_class_def ? match_class_cached : match_class,
- cached && &input_class_def == &lookahead_class_def ? match_class_cached : match_class,
- cached ? match_class_cached : match_class}},
+ {{cached && &backtrack_class_def == &lookahead_class_def ? match_class_cached1 : match_class,
+ cached ? match_class_cached2 : match_class,
+ cached ? match_class_cached1 : match_class}},
{&backtrack_class_def,
&input_class_def,
&lookahead_class_def}
};
- index = input_class_def.get_class (c->buffer->cur().codepoint);
+ // Note: Corresponds to match_class_cached2
+ if (cached && ((c->buffer->cur().syllable() & 0xF0) >> 4) < 15)
+ index = (c->buffer->cur().syllable () & 0xF0) >> 4;
+ else
+ index = input_class_def.get_class (c->buffer->cur().codepoint);
const ChainRuleSet &rule_set = this+ruleSet[index];
return_trace (rule_set.apply (c, lookup_context));
}
@@ -3727,10 +3971,11 @@ struct ChainContextFormat3
if (!(this+input[0]).intersects (c->glyphs))
return;
- hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
+ if (unlikely (!cur_active_glyphs))
+ return;
get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
- cur_active_glyphs);
-
+ *cur_active_glyphs);
const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
@@ -3849,8 +4094,6 @@ struct ChainContextFormat3
{
TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!out)) return_trace (false);
if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
if (!serialize_coverage_offsets (c, backtrack.iter (), this))
@@ -3877,14 +4120,14 @@ struct ChainContextFormat3
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- if (!backtrack.sanitize (c, this)) return_trace (false);
+ if (unlikely (!backtrack.sanitize (c, this))) return_trace (false);
const auto &input = StructAfter<decltype (inputX)> (backtrack);
- if (!input.sanitize (c, this)) return_trace (false);
- if (!input.len) return_trace (false); /* To be consistent with Context. */
+ if (unlikely (!input.sanitize (c, this))) return_trace (false);
+ if (unlikely (!input.len)) return_trace (false); /* To be consistent with Context. */
const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
- if (!lookahead.sanitize (c, this)) return_trace (false);
+ if (unlikely (!lookahead.sanitize (c, this))) return_trace (false);
const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
- return_trace (lookup.sanitize (c));
+ return_trace (likely (lookup.sanitize (c)));
}
protected:
@@ -3974,7 +4217,7 @@ struct ExtensionFormat1
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->format = format;
out->extensionLookupType = extensionLookupType;
@@ -4092,6 +4335,9 @@ struct hb_ot_layout_lookup_accelerator_t
bool may_have (hb_codepoint_t g) const
{ return digest.may_have (g); }
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool apply (hb_ot_apply_context_t *c, unsigned subtables_count, bool use_cache) const
{
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
@@ -4503,7 +4749,10 @@ struct GSUBGPOS
{
accelerator_t (hb_face_t *face)
{
- this->table = hb_sanitize_context_t ().reference_table<T> (face);
+ hb_sanitize_context_t sc;
+ sc.lazy_some_gpos = true;
+ this->table = sc.reference_table<T> (face);
+
if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
{
hb_blob_destroy (this->table.get_blob ());
@@ -4528,6 +4777,8 @@ struct GSUBGPOS
this->table.destroy ();
}
+ hb_blob_t *get_blob () const { return table.get_blob (); }
+
hb_ot_layout_lookup_accelerator_t *get_accel (unsigned lookup_index) const
{
if (unlikely (lookup_index >= lookup_count)) return nullptr;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
index c66ee8cfd0..5ce36693a8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
@@ -1241,7 +1241,7 @@ script_collect_features (hb_collect_features_context_t *c,
* terminated by %HB_TAG_NONE
* @features: (nullable) (array zero-terminated=1): The array of features to collect,
* terminated by %HB_TAG_NONE
- * @feature_indexes: (out): The array of feature indexes found for the query
+ * @feature_indexes: (out): The set of feature indexes found for the query
*
* Fetches a list of all feature indexes in the specified face's GSUB table
* or GPOS table, underneath the specified scripts, languages, and features.
@@ -1282,6 +1282,44 @@ hb_ot_layout_collect_features (hb_face_t *face,
}
}
+/**
+ * hb_ot_layout_collect_features_map:
+ * @face: #hb_face_t to work upon
+ * @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_map: (out): The map of feature tag to feature index.
+ *
+ * Fetches the mapping from feature tags to feature indexes for
+ * the specified script and language.
+ *
+ * Since: 8.1.0
+ **/
+void
+hb_ot_layout_collect_features_map (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned script_index,
+ unsigned language_index,
+ hb_map_t *feature_map /* 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);
+
+ unsigned int count = l.get_feature_indexes (0, nullptr, nullptr);
+ feature_map->alloc (count);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ unsigned feature_index = 0;
+ unsigned feature_count = 1;
+ l.get_feature_indexes (i, &feature_count, &feature_index);
+ if (!feature_count)
+ break;
+ hb_tag_t feature_tag = g.get_feature_tag (feature_index);
+ feature_map->set (feature_tag, feature_index);
+ }
+}
+
/**
* hb_ot_layout_collect_lookups:
@@ -1316,8 +1354,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
hb_set_t feature_indexes;
hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
- for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
- hb_set_next (&feature_indexes, &feature_index);)
+ for (auto feature_index : feature_indexes)
g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
g.feature_variation_collect_lookups (&feature_indexes, nullptr, lookup_indexes);
@@ -1570,7 +1607,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
glyphs_length = glyphs->get_population ();
if (lookups)
{
- for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);)
+ for (auto lookup_index : *lookups)
gsub.get_lookup (lookup_index).closure (&c, lookup_index);
}
else
@@ -1953,7 +1990,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
{
const unsigned int table_index = proxy.table_index;
unsigned int i = 0;
- OT::hb_ot_apply_context_t c (table_index, font, buffer);
+ OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob ());
c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func<OT::hb_ot_apply_context_t>);
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++)
@@ -2011,20 +2048,20 @@ void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, h
{
GSUBProxy proxy (font->face);
if (buffer->messaging () &&
- !buffer->message (font, "start table GSUB")) return;
+ !buffer->message (font, "start table GSUB script tag '%c%c%c%c'", HB_UNTAG (chosen_script[0]))) return;
apply (proxy, plan, font, buffer);
if (buffer->messaging ())
- (void) buffer->message (font, "end table GSUB");
+ (void) buffer->message (font, "end table GSUB script tag '%c%c%c%c'", HB_UNTAG (chosen_script[0]));
}
void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
{
GPOSProxy proxy (font->face);
if (buffer->messaging () &&
- !buffer->message (font, "start table GPOS")) return;
+ !buffer->message (font, "start table GPOS script tag '%c%c%c%c'", HB_UNTAG (chosen_script[1]))) return;
apply (proxy, plan, font, buffer);
if (buffer->messaging ())
- (void) buffer->message (font, "end table GPOS");
+ (void) buffer->message (font, "end table GPOS script tag '%c%c%c%c'", HB_UNTAG (chosen_script[1]));
}
void
@@ -2036,6 +2073,112 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
}
#ifndef HB_NO_BASE
+
+static void
+choose_base_tags (hb_script_t script,
+ hb_language_t language,
+ hb_tag_t *script_tag,
+ hb_tag_t *language_tag)
+{
+ hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
+ unsigned script_count = ARRAY_LENGTH (script_tags);
+
+ hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
+ unsigned language_count = ARRAY_LENGTH (language_tags);
+
+ hb_ot_tags_from_script_and_language (script, language,
+ &script_count, script_tags,
+ &language_count, language_tags);
+
+ *script_tag = script_count ? script_tags[script_count - 1] : HB_OT_TAG_DEFAULT_SCRIPT;
+ *language_tag = language_count ? language_tags[language_count - 1] : HB_OT_TAG_DEFAULT_LANGUAGE;
+}
+
+/**
+ * hb_ot_layout_get_font_extents:
+ * @font: a font
+ * @direction: text direction.
+ * @script_tag: script tag.
+ * @language_tag: language tag.
+ * @extents: (out) (nullable): font extents if found.
+ *
+ * Fetches script/language-specific font extents. These values are
+ * looked up in the `BASE` table's `MinMax` records.
+ *
+ * If no such extents are found, the default extents for the font are
+ * fetched. As such, the return value of this function can for the
+ * most part be ignored. Note that the per-script/language extents
+ * do not have a line-gap value, and the line-gap is set to zero in
+ * that case.
+ *
+ * Return value: `true` if found script/language-specific font extents.
+ *
+ * Since: 8.0.0
+ **/
+hb_bool_t
+hb_ot_layout_get_font_extents (hb_font_t *font,
+ hb_direction_t direction,
+ hb_tag_t script_tag,
+ hb_tag_t language_tag,
+ hb_font_extents_t *extents)
+{
+ hb_position_t min, max;
+ if (font->face->table.BASE->get_min_max (font, direction, script_tag, language_tag, HB_TAG_NONE,
+ &min, &max))
+ {
+ if (extents)
+ {
+ extents->ascender = max;
+ extents->descender = min;
+ extents->line_gap = 0;
+ }
+ return true;
+ }
+
+ hb_font_get_extents_for_direction (font, direction, extents);
+ return false;
+}
+
+/**
+ * hb_ot_layout_get_font_extents2:
+ * @font: a font
+ * @direction: text direction.
+ * @script: script.
+ * @language: (nullable): language.
+ * @extents: (out) (nullable): font extents if found.
+ *
+ * Fetches script/language-specific font extents. These values are
+ * looked up in the `BASE` table's `MinMax` records.
+ *
+ * If no such extents are found, the default extents for the font are
+ * fetched. As such, the return value of this function can for the
+ * most part be ignored. Note that the per-script/language extents
+ * do not have a line-gap value, and the line-gap is set to zero in
+ * that case.
+ *
+ * This function is like hb_ot_layout_get_font_extents() but takes
+ * #hb_script_t and #hb_language_t instead of OpenType #hb_tag_t.
+ *
+ * Return value: `true` if found script/language-specific font extents.
+ *
+ * Since: 8.0.0
+ **/
+hb_bool_t
+hb_ot_layout_get_font_extents2 (hb_font_t *font,
+ hb_direction_t direction,
+ hb_script_t script,
+ hb_language_t language,
+ hb_font_extents_t *extents)
+{
+ hb_tag_t script_tag, language_tag;
+ choose_base_tags (script, language, &script_tag, &language_tag);
+ return hb_ot_layout_get_font_extents (font,
+ direction,
+ script_tag,
+ language_tag,
+ extents);
+}
+
/**
* hb_ot_layout_get_horizontal_baseline_tag_for_script:
* @script: a script tag.
@@ -2134,6 +2277,42 @@ hb_ot_layout_get_baseline (hb_font_t *font,
}
/**
+ * hb_ot_layout_get_baseline2:
+ * @font: a font
+ * @baseline_tag: a baseline tag
+ * @direction: text direction.
+ * @script: script.
+ * @language: (nullable): language, currently unused.
+ * @coord: (out) (nullable): baseline value if found.
+ *
+ * Fetches a baseline value from the face.
+ *
+ * This function is like hb_ot_layout_get_baseline() but takes
+ * #hb_script_t and #hb_language_t instead of OpenType #hb_tag_t.
+ *
+ * Return value: `true` if found baseline value in the font.
+ *
+ * Since: 8.0.0
+ **/
+hb_bool_t
+hb_ot_layout_get_baseline2 (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_script_t script,
+ hb_language_t language,
+ hb_position_t *coord /* OUT. May be NULL. */)
+{
+ hb_tag_t script_tag, language_tag;
+ choose_base_tags (script, language, &script_tag, &language_tag);
+ return hb_ot_layout_get_baseline (font,
+ baseline_tag,
+ direction,
+ script_tag,
+ language_tag,
+ coord);
+}
+
+/**
* hb_ot_layout_get_baseline_with_fallback:
* @font: a font
* @baseline_tag: a baseline tag
@@ -2355,6 +2534,41 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
}
}
+/**
+ * hb_ot_layout_get_baseline_with_fallback2:
+ * @font: a font
+ * @baseline_tag: a baseline tag
+ * @direction: text direction.
+ * @script: script.
+ * @language: (nullable): language, currently unused.
+ * @coord: (out): baseline value if found.
+ *
+ * Fetches a baseline value from the face, and synthesizes
+ * it if the font does not have it.
+ *
+ * This function is like hb_ot_layout_get_baseline_with_fallback() but takes
+ * #hb_script_t and #hb_language_t instead of OpenType #hb_tag_t.
+ *
+ * Since: 8.0.0
+ **/
+void
+hb_ot_layout_get_baseline_with_fallback2 (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_script_t script,
+ hb_language_t language,
+ hb_position_t *coord /* OUT */)
+{
+ hb_tag_t script_tag, language_tag;
+ choose_base_tags (script, language, &script_tag, &language_tag);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ baseline_tag,
+ direction,
+ script_tag,
+ language_tag,
+ coord);
+}
+
#endif
@@ -2451,9 +2665,10 @@ hb_ot_layout_lookup_get_optical_bound (hb_font_t *font,
hb_codepoint_t glyph)
{
const OT::PosLookup &lookup = font->face->table.GPOS->table->get_lookup (lookup_index);
+ hb_blob_t *blob = font->face->table.GPOS->get_blob ();
hb_glyph_position_t pos = {0};
hb_position_single_dispatch_t c;
- lookup.dispatch (&c, font, direction, glyph, pos);
+ lookup.dispatch (&c, font, blob, direction, glyph, pos);
hb_position_t ret = 0;
switch (direction)
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
index 10dcc65ac0..386b98d580 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
@@ -325,6 +325,13 @@ hb_ot_layout_collect_features (hb_face_t *face,
hb_set_t *feature_indexes /* OUT */);
HB_EXTERN void
+hb_ot_layout_collect_features_map (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned script_index,
+ unsigned language_index,
+ hb_map_t *feature_map /* OUT */);
+
+HB_EXTERN void
hb_ot_layout_collect_lookups (hb_face_t *face,
hb_tag_t table_tag,
const hb_tag_t *scripts,
@@ -447,6 +454,20 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
* BASE
*/
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_font_extents (hb_font_t *font,
+ hb_direction_t direction,
+ hb_tag_t script_tag,
+ hb_tag_t language_tag,
+ hb_font_extents_t *extents);
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_font_extents2 (hb_font_t *font,
+ hb_direction_t direction,
+ hb_script_t script,
+ hb_language_t language,
+ hb_font_extents_t *extents);
+
/**
* hb_ot_layout_baseline_tag_t:
* @HB_OT_LAYOUT_BASELINE_TAG_ROMAN: The baseline used by alphabetic scripts such as Latin, Cyrillic and Greek.
@@ -499,6 +520,14 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */);
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_baseline2 (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_script_t script,
+ hb_language_t language,
+ hb_position_t *coord /* OUT. May be NULL. */);
+
HB_EXTERN void
hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
hb_ot_layout_baseline_tag_t baseline_tag,
@@ -507,6 +536,14 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT */);
+HB_EXTERN void
+hb_ot_layout_get_baseline_with_fallback2 (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_script_t script,
+ hb_language_t language,
+ hb_position_t *coord /* OUT */);
+
HB_END_DECLS
#endif /* HB_OT_LAYOUT_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
index 9505d5f147..d71889331d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
@@ -448,7 +448,7 @@ _hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
static inline bool
_hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
{
- return !!(info->lig_props() & IS_LIG_BASE);
+ return info->lig_props() & IS_LIG_BASE;
}
static inline unsigned int
@@ -496,37 +496,37 @@ _hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
static inline bool
_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
{
- return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
+ return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
}
static inline bool
_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
{
- return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
+ return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
}
static inline bool
_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
{
- return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
+ return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK;
}
static inline bool
_hb_glyph_info_substituted (const hb_glyph_info_t *info)
{
- return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
+ return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
}
static inline bool
_hb_glyph_info_ligated (const hb_glyph_info_t *info)
{
- return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
+ return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
}
static inline bool
_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
{
- return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+ return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
}
static inline bool
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
index 8882dbaccb..fac73eb34e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
@@ -213,7 +213,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
/* Sort features and merge duplicates */
if (feature_infos.length)
{
- feature_infos.qsort ();
+ if (!is_simple)
+ feature_infos.qsort ();
auto *f = feature_infos.arrayZ;
unsigned int j = 0;
unsigned count = feature_infos.length;
@@ -238,6 +239,13 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
feature_infos.shrink (j + 1);
}
+ hb_map_t feature_indices[2];
+ for (unsigned int table_index = 0; table_index < 2; table_index++)
+ hb_ot_layout_collect_features_map (face,
+ table_tags[table_index],
+ script_index[table_index],
+ language_index[table_index],
+ &feature_indices[table_index]);
/* Allocate bits now */
static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
@@ -260,7 +268,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
if (!info->max_value || next_bit + bits_needed >= global_bit_shift)
continue; /* Feature disabled, or not enough bits. */
-
bool found = false;
unsigned int feature_index[2];
for (unsigned int table_index = 0; table_index < 2; table_index++)
@@ -268,12 +275,14 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
if (required_feature_tag[table_index] == info->tag)
required_feature_stage[table_index] = info->stage[table_index];
- found |= (bool) hb_ot_layout_language_find_feature (face,
- table_tags[table_index],
- script_index[table_index],
- language_index[table_index],
- info->tag,
- &feature_index[table_index]);
+ hb_codepoint_t *index;
+ if (feature_indices[table_index].has (info->tag, &index))
+ {
+ feature_index[table_index] = *index;
+ found = true;
+ }
+ else
+ feature_index[table_index] = HB_OT_LAYOUT_NO_FEATURE_INDEX;
}
if (!found && (info->flags & F_GLOBAL_SEARCH))
{
@@ -314,7 +323,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
map->needs_fallback = !found;
}
//feature_infos.shrink (0); /* Done with these */
-
+ if (is_simple)
+ m.features.qsort ();
add_gsub_pause (nullptr);
add_gpos_pause (nullptr);
@@ -350,7 +360,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
}
/* Sort lookups and merge duplicates */
- if (last_num_lookups < lookups.length)
+ if (last_num_lookups + 1 < lookups.length)
{
lookups.as_array ().sub_array (last_num_lookups, lookups.length - last_num_lookups).qsort ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh
index efc8cae96a..8af8129ceb 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh
@@ -60,6 +60,13 @@ struct hb_ot_map_t
int cmp (const hb_tag_t tag_) const
{ return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
+
+ HB_INTERNAL static int cmp (const void *pa, const void *pb)
+ {
+ const feature_map_t *a = (const feature_map_t *) pa;
+ const feature_map_t *b = (const feature_map_t *) pb;
+ return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0;
+ }
};
struct lookup_map_t {
@@ -273,6 +280,7 @@ struct hb_ot_map_builder_t
hb_face_t *face;
hb_segment_properties_t props;
+ bool is_simple;
hb_tag_t chosen_script[2];
bool found_script[2];
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
index dccf720f46..b11da464b2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
@@ -73,7 +73,6 @@ struct MathConstants
{
TRACE_SERIALIZE (this);
auto *out = c->start_embed (this);
- if (unlikely (!out)) return_trace (nullptr);
HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2);
if (unlikely (!p)) return_trace (nullptr);
@@ -310,7 +309,6 @@ struct MathKern
{
TRACE_SERIALIZE (this);
auto *out = c->start_embed (this);
- if (unlikely (!out)) return_trace (nullptr);
if (unlikely (!c->embed (heightCount))) return_trace (nullptr);
@@ -572,6 +570,7 @@ struct MathGlyphInfo
auto it =
+ hb_iter (this+extendedShapeCoverage)
+ | hb_take (c->plan->source->get_num_glyphs ())
| hb_filter (glyphset)
| hb_map_retains_sorting (glyph_map)
;
@@ -757,8 +756,6 @@ struct MathGlyphAssembly
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
if (!c->serializer->copy (italicsCorrection, this)) return_trace (false);
if (!c->serializer->copy<HBUINT16> (partRecords.len)) return_trace (false);
@@ -945,13 +942,13 @@ struct MathVariants
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
if (!c->serializer->check_assign (out->minConnectorOverlap, minConnectorOverlap, HB_SERIALIZE_ERROR_INT_OVERFLOW))
return_trace (false);
-
+
hb_sorted_vector_t<hb_codepoint_t> new_vert_coverage;
hb_sorted_vector_t<hb_codepoint_t> new_hori_coverage;
hb_set_t indices;
collect_coverage_and_indices (new_vert_coverage, vertGlyphCoverage, 0, vertGlyphCount, indices, glyphset, glyph_map);
collect_coverage_and_indices (new_hori_coverage, horizGlyphCoverage, vertGlyphCount, vertGlyphCount + horizGlyphCount, indices, glyphset, glyph_map);
-
+
if (!c->serializer->check_assign (out->vertGlyphCount, new_vert_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
return_trace (false);
if (!c->serializer->check_assign (out->horizGlyphCount, new_hori_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
@@ -963,10 +960,10 @@ struct MathVariants
if (!o) return_trace (false);
o->serialize_subset (c, glyphConstruction[i], this);
}
-
+
if (new_vert_coverage)
out->vertGlyphCoverage.serialize_serialize (c->serializer, new_vert_coverage.iter ());
-
+
if (new_hori_coverage)
out->horizGlyphCoverage.serialize_serialize (c->serializer, new_hori_coverage.iter ());
return_trace (true);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh
index 97d18b9d75..72cb662473 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh
@@ -249,7 +249,7 @@ struct OS2
if (c->plan->user_axes_location.has (HB_TAG ('w','g','h','t')) &&
!c->plan->pinned_at_default)
{
- float weight_class = c->plan->user_axes_location.get (HB_TAG ('w','g','h','t'));
+ float weight_class = c->plan->user_axes_location.get (HB_TAG ('w','g','h','t')).middle;
if (!c->serializer->check_assign (os2_prime->usWeightClass,
roundf (hb_clamp (weight_class, 1.0f, 1000.0f)),
HB_SERIALIZE_ERROR_INT_OVERFLOW))
@@ -259,7 +259,7 @@ struct OS2
if (c->plan->user_axes_location.has (HB_TAG ('w','d','t','h')) &&
!c->plan->pinned_at_default)
{
- float width = c->plan->user_axes_location.get (HB_TAG ('w','d','t','h'));
+ float width = c->plan->user_axes_location.get (HB_TAG ('w','d','t','h')).middle;
if (!c->serializer->check_assign (os2_prime->usWidthClass,
roundf (map_wdth_to_widthclass (width)),
HB_SERIALIZE_ERROR_INT_OVERFLOW))
@@ -287,8 +287,7 @@ struct OS2
/* This block doesn't show up in profiles. If it ever did,
* we can rewrite it to iterate over OS/2 ranges and use
* set iteration to check if the range matches. */
- for (hb_codepoint_t cp = HB_SET_VALUE_INVALID;
- codepoints->next (&cp);)
+ for (auto cp : *codepoints)
{
unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
if (bit < 128)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh
index 951e6395d6..d44233610a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh
@@ -79,6 +79,11 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
post::accelerator_t _post (c->plan->source);
hb_hashmap_t<hb_bytes_t, uint32_t, true> glyph_name_to_new_index;
+
+ old_new_index_map.alloc (num_glyphs);
+ old_gid_new_index_map.alloc (num_glyphs);
+ glyph_name_to_new_index.alloc (num_glyphs);
+
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
{
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
@@ -86,11 +91,12 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
unsigned new_index;
const uint32_t *new_index2;
- if (old_index <= 257) new_index = old_index;
+ if (old_index <= 257)
+ new_index = old_index;
else if (old_new_index_map.has (old_index, &new_index2))
- {
new_index = *new_index2;
- } else {
+ else
+ {
hb_bytes_t s = _post.find_glyph_name (old_gid);
new_index = glyph_name_to_new_index.get (s);
if (new_index == (unsigned)-1)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh
index 042fa611ad..761e49d119 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh
@@ -96,8 +96,7 @@ struct post
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- post *post_prime = c->serializer->start_embed<post> ();
- if (unlikely (!post_prime)) return_trace (false);
+ auto *post_prime = c->serializer->start_embed<post> ();
bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
if (!serialize (c->serializer, glyph_names))
@@ -117,7 +116,7 @@ struct post
if (c->plan->user_axes_location.has (HB_TAG ('s','l','n','t')) &&
!c->plan->pinned_at_default)
{
- float italic_angle = c->plan->user_axes_location.get (HB_TAG ('s','l','n','t'));
+ float italic_angle = c->plan->user_axes_location.get (HB_TAG ('s','l','n','t')).middle;
italic_angle = hb_max (-90.f, hb_min (italic_angle, 90.f));
post_prime->italicAngle.set_float (italic_angle);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
index 3d207e0681..9c1c2a950e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
@@ -313,6 +313,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
{
hb_ot_map_builder_t *map = &planner->map;
+ map->is_simple = true;
+
map->enable_feature (HB_TAG('r','v','r','n'));
map->add_gsub_pause (nullptr);
@@ -354,7 +356,10 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */
if (planner->shaper->collect_features)
+ {
+ map->is_simple = false;
planner->shaper->collect_features (planner);
+ }
map->enable_feature (HB_TAG ('B','u','z','z')); /* Considered required. */
map->enable_feature (HB_TAG ('B','U','Z','Z')); /* Considered discretionary. */
@@ -378,6 +383,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
}
+ if (num_user_features)
+ map->is_simple = false;
for (unsigned int i = 0; i < num_user_features; i++)
{
const hb_feature_t *feature = &user_features[i];
@@ -469,9 +476,18 @@ hb_set_unicode_props (hb_buffer_t *buffer)
{
_hb_glyph_info_set_unicode_props (&info[i], buffer);
+ unsigned gen_cat = _hb_glyph_info_get_general_category (&info[i]);
+ if (FLAG_UNSAFE (gen_cat) &
+ (FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR)))
+ continue;
+
/* Marks are already set as continuation by the above line.
* Handle Emoji_Modifier and ZWJ-continuation. */
- if (unlikely (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL &&
+ if (unlikely (gen_cat == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL &&
hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F3FBu, 0x1F3FFu)))
{
_hb_glyph_info_set_continuation (&info[i]);
@@ -749,6 +765,14 @@ hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c)
_hb_glyph_info_get_general_category (&info[end]) ==
HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
end++;
+ if (start == i || end == i + 1)
+ {
+ if (start == i)
+ buffer->unsafe_to_concat (start, start + 1);
+ if (end == i + 1)
+ buffer->unsafe_to_concat (end - 1, end);
+ continue;
+ }
buffer->unsafe_to_break (start, end);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh
index e7a69008b7..66a8bfbd28 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh
@@ -368,7 +368,7 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
- OT::hb_ot_apply_context_t c (0, font, buffer);
+ OT::hb_ot_apply_context_t c (0, font, buffer, hb_blob_get_empty ());
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
if (fallback_plan->lookup_array[i]) {
c.set_lookup_mask (fallback_plan->mask_array[i]);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh
index 353e32d32c..7dd47755af 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh
@@ -53,7 +53,7 @@ enum indic_syllable_type_t {
};
-#line 57 "hb-ot-shaper-indic-machine.hh"
+#line 54 "hb-ot-shaper-indic-machine.hh"
#define indic_syllable_machine_ex_A 9u
#define indic_syllable_machine_ex_C 1u
#define indic_syllable_machine_ex_CM 16u
@@ -76,7 +76,7 @@ enum indic_syllable_type_t {
#define indic_syllable_machine_ex_ZWNJ 5u
-#line 80 "hb-ot-shaper-indic-machine.hh"
+#line 75 "hb-ot-shaper-indic-machine.hh"
static const unsigned char _indic_syllable_machine_trans_keys[] = {
8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
@@ -460,7 +460,7 @@ find_syllables_indic (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
-#line 464 "hb-ot-shaper-indic-machine.hh"
+#line 453 "hb-ot-shaper-indic-machine.hh"
{
cs = indic_syllable_machine_start;
ts = 0;
@@ -476,7 +476,7 @@ find_syllables_indic (hb_buffer_t *buffer)
unsigned int syllable_serial = 1;
-#line 480 "hb-ot-shaper-indic-machine.hh"
+#line 465 "hb-ot-shaper-indic-machine.hh"
{
int _slen;
int _trans;
@@ -490,7 +490,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 494 "hb-ot-shaper-indic-machine.hh"
+#line 477 "hb-ot-shaper-indic-machine.hh"
}
_keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -593,7 +593,7 @@ _eof_trans:
#line 114 "hb-ot-shaper-indic-machine.rl"
{act = 6;}
break;
-#line 597 "hb-ot-shaper-indic-machine.hh"
+#line 559 "hb-ot-shaper-indic-machine.hh"
}
_again:
@@ -602,7 +602,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 606 "hb-ot-shaper-indic-machine.hh"
+#line 566 "hb-ot-shaper-indic-machine.hh"
}
if ( ++p != pe )
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.cc
index 89226ae4a1..97f62035c6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.cc
@@ -40,6 +40,14 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return false;
if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE)))
+ {
+ if (buffer->messaging ())
+ (void) buffer->message (font, "skipped inserting dotted-circles because there is no broken syllables");
+ return false;
+ }
+
+ if (buffer->messaging () &&
+ !buffer->message (font, "start inserting dotted-circles"))
return false;
hb_codepoint_t dottedcircle_glyph;
@@ -84,6 +92,10 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
(void) buffer->next_glyph ();
}
buffer->sync ();
+
+ if (buffer->messaging ())
+ (void) buffer->message (font, "end inserting dotted-circles");
+
return true;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh
index 7249c33356..80a9b09d8e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh
@@ -1,32 +1,31 @@
-
#line 1 "hb-ot-shaper-use-machine.rl"
/*
- * Copyright © 2015 Mozilla Foundation.
- * Copyright © 2015 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.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
+* Copyright © 2015 Mozilla Foundation.
+* Copyright © 2015 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.
+*
+* Mozilla Author(s): Jonathan Kew
+* Google Author(s): Behdad Esfahbod
+*/
#ifndef HB_OT_SHAPER_USE_MACHINE_HH
#define HB_OT_SHAPER_USE_MACHINE_HH
@@ -41,15 +40,15 @@
#define USE(Cat) use_syllable_machine_ex_##Cat
enum use_syllable_type_t {
- use_virama_terminated_cluster,
- use_sakot_terminated_cluster,
- use_standard_cluster,
- use_number_joiner_terminated_cluster,
- use_numeral_cluster,
- use_symbol_cluster,
- use_hieroglyph_cluster,
- use_broken_cluster,
- use_non_cluster,
+ use_virama_terminated_cluster,
+ use_sakot_terminated_cluster,
+ use_standard_cluster,
+ use_number_joiner_terminated_cluster,
+ use_numeral_cluster,
+ use_symbol_cluster,
+ use_hieroglyph_cluster,
+ use_broken_cluster,
+ use_non_cluster,
};
@@ -99,724 +98,592 @@ enum use_syllable_type_t {
#line 96 "hb-ot-shaper-use-machine.hh"
static const unsigned char _use_syllable_machine_trans_keys[] = {
- 0u, 53u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u,
- 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u,
- 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u,
- 12u, 53u, 11u, 53u, 1u, 14u, 1u, 48u, 11u, 53u, 14u, 42u, 14u, 42u, 11u, 53u,
- 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u,
- 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u,
- 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u,
- 1u, 14u, 1u, 14u, 1u, 48u, 13u, 14u, 4u, 14u, 11u, 53u, 11u, 53u, 1u, 53u,
- 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u,
- 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u,
- 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 14u, 1u, 14u,
- 1u, 48u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u,
- 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u,
- 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u,
- 12u, 53u, 11u, 53u, 1u, 14u, 1u, 48u, 4u, 14u, 13u, 14u, 1u, 53u, 11u, 53u,
- 14u, 42u, 14u, 42u, 1u, 5u, 14u, 52u, 14u, 52u, 14u, 51u, 0
+ 0u, 39u, 5u, 39u, 5u, 39u, 1u, 39u,
+ 8u, 34u, 8u, 33u, 8u, 33u, 8u, 33u,
+ 8u, 32u, 8u, 32u, 8u, 8u, 8u, 34u,
+ 8u, 34u, 8u, 34u, 1u, 8u, 8u, 34u,
+ 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
+ 6u, 39u, 8u, 39u, 6u, 39u, 6u, 39u,
+ 6u, 39u, 5u, 39u, 1u, 8u, 1u, 34u,
+ 8u, 28u, 8u, 28u, 5u, 39u, 1u, 39u,
+ 8u, 34u, 8u, 33u, 8u, 33u, 8u, 33u,
+ 8u, 32u, 8u, 32u, 8u, 8u, 8u, 34u,
+ 8u, 34u, 8u, 34u, 1u, 8u, 8u, 34u,
+ 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
+ 6u, 39u, 8u, 39u, 6u, 39u, 6u, 39u,
+ 6u, 39u, 5u, 39u, 1u, 8u, 1u, 8u,
+ 1u, 34u, 7u, 8u, 3u, 8u, 5u, 39u,
+ 5u, 39u, 1u, 39u, 8u, 34u, 8u, 33u,
+ 8u, 33u, 8u, 33u, 8u, 32u, 8u, 32u,
+ 8u, 8u, 8u, 34u, 8u, 34u, 8u, 34u,
+ 1u, 8u, 8u, 34u, 8u, 39u, 8u, 39u,
+ 8u, 39u, 8u, 39u, 6u, 39u, 8u, 39u,
+ 6u, 39u, 6u, 39u, 6u, 39u, 5u, 39u,
+ 1u, 8u, 1u, 8u, 1u, 34u, 5u, 39u,
+ 1u, 39u, 8u, 34u, 8u, 33u, 8u, 33u,
+ 8u, 33u, 8u, 32u, 8u, 32u, 8u, 8u,
+ 8u, 34u, 8u, 34u, 8u, 34u, 1u, 8u,
+ 8u, 34u, 8u, 39u, 8u, 39u, 8u, 39u,
+ 8u, 39u, 6u, 39u, 8u, 39u, 6u, 39u,
+ 6u, 39u, 6u, 39u, 5u, 39u, 1u, 8u,
+ 1u, 34u, 3u, 8u, 7u, 8u, 1u, 39u,
+ 8u, 28u, 8u, 28u, 1u, 4u, 8u, 38u,
+ 8u, 38u, 8u, 37u, 0u
};
-static const char _use_syllable_machine_key_spans[] = {
- 54, 43, 43, 53, 35, 34, 34, 34,
- 33, 33, 1, 35, 35, 35, 14, 35,
- 40, 40, 40, 40, 42, 40, 42, 42,
- 42, 43, 14, 48, 43, 29, 29, 43,
- 43, 53, 35, 34, 34, 34, 33, 33,
- 1, 35, 35, 35, 14, 35, 40, 40,
- 40, 40, 42, 40, 42, 42, 42, 43,
- 14, 14, 48, 2, 11, 43, 43, 53,
- 35, 34, 34, 34, 33, 33, 1, 35,
- 35, 35, 14, 35, 40, 40, 40, 40,
- 42, 40, 42, 42, 42, 43, 14, 14,
- 48, 43, 43, 53, 35, 34, 34, 34,
- 33, 33, 1, 35, 35, 35, 14, 35,
- 40, 40, 40, 40, 42, 40, 42, 42,
- 42, 43, 14, 48, 11, 2, 53, 43,
- 29, 29, 5, 39, 39, 38
+static const signed char _use_syllable_machine_char_class[] = {
+ 0, 1, 2, 2, 3, 4, 2, 2,
+ 2, 2, 2, 5, 6, 7, 8, 2,
+ 2, 2, 9, 2, 2, 2, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 2, 24, 25, 26,
+ 2, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 0
};
static const short _use_syllable_machine_index_offsets[] = {
- 0, 55, 99, 143, 197, 233, 268, 303,
- 338, 372, 406, 408, 444, 480, 516, 531,
- 567, 608, 649, 690, 731, 774, 815, 858,
- 901, 944, 988, 1003, 1052, 1096, 1126, 1156,
- 1200, 1244, 1298, 1334, 1369, 1404, 1439, 1473,
- 1507, 1509, 1545, 1581, 1617, 1632, 1668, 1709,
- 1750, 1791, 1832, 1875, 1916, 1959, 2002, 2045,
- 2089, 2104, 2119, 2168, 2171, 2183, 2227, 2271,
- 2325, 2361, 2396, 2431, 2466, 2500, 2534, 2536,
- 2572, 2608, 2644, 2659, 2695, 2736, 2777, 2818,
- 2859, 2902, 2943, 2986, 3029, 3072, 3116, 3131,
- 3146, 3195, 3239, 3283, 3337, 3373, 3408, 3443,
- 3478, 3512, 3546, 3548, 3584, 3620, 3656, 3671,
- 3707, 3748, 3789, 3830, 3871, 3914, 3955, 3998,
- 4041, 4084, 4128, 4143, 4192, 4204, 4207, 4261,
- 4305, 4335, 4365, 4371, 4411, 4451
+ 0, 40, 75, 110, 149, 176, 202, 228,
+ 254, 279, 304, 305, 332, 359, 386, 394,
+ 421, 453, 485, 517, 549, 583, 615, 649,
+ 683, 717, 752, 760, 794, 815, 836, 871,
+ 910, 937, 963, 989, 1015, 1040, 1065, 1066,
+ 1093, 1120, 1147, 1155, 1182, 1214, 1246, 1278,
+ 1310, 1344, 1376, 1410, 1444, 1478, 1513, 1521,
+ 1529, 1563, 1565, 1571, 1606, 1641, 1680, 1707,
+ 1733, 1759, 1785, 1810, 1835, 1836, 1863, 1890,
+ 1917, 1925, 1952, 1984, 2016, 2048, 2080, 2114,
+ 2146, 2180, 2214, 2248, 2283, 2291, 2299, 2333,
+ 2368, 2407, 2434, 2460, 2486, 2512, 2537, 2562,
+ 2563, 2590, 2617, 2644, 2652, 2679, 2711, 2743,
+ 2775, 2807, 2841, 2873, 2907, 2941, 2975, 3010,
+ 3018, 3052, 3058, 3060, 3099, 3120, 3141, 3145,
+ 3176, 3207, 0
+};
+
+static const short _use_syllable_machine_indicies[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 6, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 30, 34, 3, 35, 3, 36,
+ 38, 39, 37, 40, 37, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 38, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58,
+ 37, 59, 60, 61, 62, 59, 37, 37,
+ 37, 37, 63, 38, 39, 37, 40, 37,
+ 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 38, 50, 51, 52, 53, 54, 55,
+ 56, 37, 37, 37, 59, 60, 61, 62,
+ 59, 37, 37, 37, 37, 63, 38, 37,
+ 37, 37, 37, 37, 37, 40, 37, 37,
+ 42, 43, 44, 45, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 54, 55, 56,
+ 37, 37, 37, 37, 60, 61, 62, 64,
+ 37, 37, 37, 37, 42, 40, 37, 37,
+ 42, 43, 44, 45, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 54, 55, 56,
+ 37, 37, 37, 37, 60, 61, 62, 64,
+ 40, 37, 37, 37, 43, 44, 45, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 60,
+ 61, 62, 40, 37, 37, 37, 37, 44,
+ 45, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 60, 61, 62, 40, 37, 37, 37,
+ 37, 37, 45, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 60, 61, 62, 40, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 60, 61, 40,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 61,
+ 40, 40, 37, 37, 37, 43, 44, 45,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 54, 55, 56, 37, 37, 37, 37,
+ 60, 61, 62, 64, 40, 37, 37, 37,
+ 43, 44, 45, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 55, 56, 37,
+ 37, 37, 37, 60, 61, 62, 64, 40,
+ 37, 37, 37, 43, 44, 45, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 56, 37, 37, 37, 37, 60, 61,
+ 62, 64, 65, 37, 37, 37, 37, 37,
+ 37, 40, 40, 37, 37, 37, 43, 44,
+ 45, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 60, 61, 62, 64, 40, 37, 41,
+ 42, 43, 44, 45, 37, 37, 37, 37,
+ 37, 37, 51, 52, 53, 54, 55, 56,
+ 37, 37, 37, 37, 60, 61, 62, 64,
+ 37, 37, 37, 37, 42, 40, 37, 37,
+ 42, 43, 44, 45, 37, 37, 37, 37,
+ 37, 37, 51, 52, 53, 54, 55, 56,
+ 37, 37, 37, 37, 60, 61, 62, 64,
+ 37, 37, 37, 37, 42, 40, 37, 37,
+ 42, 43, 44, 45, 37, 37, 37, 37,
+ 37, 37, 37, 52, 53, 54, 55, 56,
+ 37, 37, 37, 37, 60, 61, 62, 64,
+ 37, 37, 37, 37, 42, 40, 37, 37,
+ 42, 43, 44, 45, 37, 37, 37, 37,
+ 37, 37, 37, 37, 53, 54, 55, 56,
+ 37, 37, 37, 37, 60, 61, 62, 64,
+ 37, 37, 37, 37, 42, 66, 37, 40,
+ 37, 41, 42, 43, 44, 45, 37, 47,
+ 48, 37, 37, 37, 51, 52, 53, 54,
+ 55, 56, 37, 37, 37, 37, 60, 61,
+ 62, 64, 37, 37, 37, 37, 42, 40,
+ 37, 37, 42, 43, 44, 45, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 54,
+ 55, 56, 37, 37, 37, 37, 60, 61,
+ 62, 64, 37, 37, 37, 37, 42, 66,
+ 37, 40, 37, 41, 42, 43, 44, 45,
+ 37, 37, 48, 37, 37, 37, 51, 52,
+ 53, 54, 55, 56, 37, 37, 37, 37,
+ 60, 61, 62, 64, 37, 37, 37, 37,
+ 42, 66, 37, 40, 37, 41, 42, 43,
+ 44, 45, 37, 37, 37, 37, 37, 37,
+ 51, 52, 53, 54, 55, 56, 37, 37,
+ 37, 37, 60, 61, 62, 64, 37, 37,
+ 37, 37, 42, 66, 37, 40, 37, 41,
+ 42, 43, 44, 45, 46, 47, 48, 37,
+ 37, 37, 51, 52, 53, 54, 55, 56,
+ 37, 37, 37, 37, 60, 61, 62, 64,
+ 37, 37, 37, 37, 42, 38, 39, 37,
+ 40, 37, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 37, 50, 51, 52, 53,
+ 54, 55, 56, 37, 37, 37, 59, 60,
+ 61, 62, 59, 37, 37, 37, 37, 63,
+ 38, 37, 37, 37, 37, 37, 37, 40,
+ 38, 37, 37, 37, 37, 37, 37, 40,
+ 37, 37, 42, 43, 44, 45, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 54,
+ 55, 56, 37, 37, 37, 37, 60, 61,
+ 62, 64, 40, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 57, 58, 40,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 58, 2, 68, 67, 69,
+ 67, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 2, 79, 80, 81, 82, 83,
+ 84, 85, 67, 67, 67, 86, 87, 88,
+ 89, 90, 67, 67, 67, 67, 91, 2,
+ 67, 67, 67, 67, 67, 67, 69, 67,
+ 67, 71, 72, 73, 74, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 83, 84,
+ 85, 67, 67, 67, 67, 87, 88, 89,
+ 92, 67, 67, 67, 67, 71, 69, 67,
+ 67, 71, 72, 73, 74, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 83, 84,
+ 85, 67, 67, 67, 67, 87, 88, 89,
+ 92, 69, 67, 67, 67, 72, 73, 74,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 87, 88, 89, 69, 67, 67, 67, 67,
+ 73, 74, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 87, 88, 89, 69, 67, 67,
+ 67, 67, 67, 74, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 87, 88, 89, 69,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 87, 88,
+ 69, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 88, 69, 69, 67, 67, 67, 72, 73,
+ 74, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 83, 84, 85, 67, 67, 67,
+ 67, 87, 88, 89, 92, 69, 67, 67,
+ 67, 72, 73, 74, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 84, 85,
+ 67, 67, 67, 67, 87, 88, 89, 92,
+ 69, 67, 67, 67, 72, 73, 74, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 85, 67, 67, 67, 67, 87,
+ 88, 89, 92, 94, 93, 93, 93, 93,
+ 93, 93, 95, 69, 67, 67, 67, 72,
+ 73, 74, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 87, 88, 89, 92, 69, 67,
+ 70, 71, 72, 73, 74, 67, 67, 67,
+ 67, 67, 67, 80, 81, 82, 83, 84,
+ 85, 67, 67, 67, 67, 87, 88, 89,
+ 92, 67, 67, 67, 67, 71, 69, 67,
+ 67, 71, 72, 73, 74, 67, 67, 67,
+ 67, 67, 67, 80, 81, 82, 83, 84,
+ 85, 67, 67, 67, 67, 87, 88, 89,
+ 92, 67, 67, 67, 67, 71, 69, 67,
+ 67, 71, 72, 73, 74, 67, 67, 67,
+ 67, 67, 67, 67, 81, 82, 83, 84,
+ 85, 67, 67, 67, 67, 87, 88, 89,
+ 92, 67, 67, 67, 67, 71, 69, 67,
+ 67, 71, 72, 73, 74, 67, 67, 67,
+ 67, 67, 67, 67, 67, 82, 83, 84,
+ 85, 67, 67, 67, 67, 87, 88, 89,
+ 92, 67, 67, 67, 67, 71, 96, 67,
+ 69, 67, 70, 71, 72, 73, 74, 67,
+ 76, 77, 67, 67, 67, 80, 81, 82,
+ 83, 84, 85, 67, 67, 67, 67, 87,
+ 88, 89, 92, 67, 67, 67, 67, 71,
+ 69, 67, 67, 71, 72, 73, 74, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 83, 84, 85, 67, 67, 67, 67, 87,
+ 88, 89, 92, 67, 67, 67, 67, 71,
+ 96, 67, 69, 67, 70, 71, 72, 73,
+ 74, 67, 67, 77, 67, 67, 67, 80,
+ 81, 82, 83, 84, 85, 67, 67, 67,
+ 67, 87, 88, 89, 92, 67, 67, 67,
+ 67, 71, 96, 67, 69, 67, 70, 71,
+ 72, 73, 74, 67, 67, 67, 67, 67,
+ 67, 80, 81, 82, 83, 84, 85, 67,
+ 67, 67, 67, 87, 88, 89, 92, 67,
+ 67, 67, 67, 71, 96, 67, 69, 67,
+ 70, 71, 72, 73, 74, 75, 76, 77,
+ 67, 67, 67, 80, 81, 82, 83, 84,
+ 85, 67, 67, 67, 67, 87, 88, 89,
+ 92, 67, 67, 67, 67, 71, 2, 68,
+ 67, 69, 67, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 67, 79, 80, 81,
+ 82, 83, 84, 85, 67, 67, 67, 86,
+ 87, 88, 89, 90, 67, 67, 67, 67,
+ 91, 2, 97, 97, 97, 97, 97, 97,
+ 98, 2, 93, 93, 93, 93, 93, 93,
+ 95, 2, 67, 67, 67, 67, 67, 67,
+ 69, 67, 67, 71, 72, 73, 74, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 83, 84, 85, 67, 67, 67, 67, 87,
+ 88, 89, 92, 100, 101, 4, 102, 102,
+ 102, 102, 103, 104, 105, 67, 69, 67,
+ 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 104, 115, 116, 117, 118, 119, 120,
+ 121, 57, 58, 67, 122, 123, 124, 125,
+ 126, 67, 67, 67, 67, 127, 104, 105,
+ 67, 69, 67, 106, 107, 108, 109, 110,
+ 111, 112, 113, 114, 104, 115, 116, 117,
+ 118, 119, 120, 121, 67, 67, 67, 122,
+ 123, 124, 125, 126, 67, 67, 67, 67,
+ 127, 104, 67, 67, 67, 67, 67, 67,
+ 69, 67, 67, 107, 108, 109, 110, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 119, 120, 121, 67, 67, 67, 67, 123,
+ 124, 125, 128, 67, 67, 67, 67, 107,
+ 69, 67, 67, 107, 108, 109, 110, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 119, 120, 121, 67, 67, 67, 67, 123,
+ 124, 125, 128, 69, 67, 67, 67, 108,
+ 109, 110, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 123, 124, 125, 69, 67, 67,
+ 67, 67, 109, 110, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 123, 124, 125, 69,
+ 67, 67, 67, 67, 67, 110, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 123, 124,
+ 125, 69, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 123, 124, 69, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 124, 69, 69, 67, 67, 67,
+ 108, 109, 110, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 119, 120, 121, 67,
+ 67, 67, 67, 123, 124, 125, 128, 69,
+ 67, 67, 67, 108, 109, 110, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 120, 121, 67, 67, 67, 67, 123, 124,
+ 125, 128, 69, 67, 67, 67, 108, 109,
+ 110, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 121, 67, 67, 67,
+ 67, 123, 124, 125, 128, 129, 93, 93,
+ 93, 93, 93, 93, 95, 69, 67, 67,
+ 67, 108, 109, 110, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 123, 124, 125, 128,
+ 69, 67, 106, 107, 108, 109, 110, 67,
+ 67, 67, 67, 67, 67, 116, 117, 118,
+ 119, 120, 121, 67, 67, 67, 67, 123,
+ 124, 125, 128, 67, 67, 67, 67, 107,
+ 69, 67, 67, 107, 108, 109, 110, 67,
+ 67, 67, 67, 67, 67, 116, 117, 118,
+ 119, 120, 121, 67, 67, 67, 67, 123,
+ 124, 125, 128, 67, 67, 67, 67, 107,
+ 69, 67, 67, 107, 108, 109, 110, 67,
+ 67, 67, 67, 67, 67, 67, 117, 118,
+ 119, 120, 121, 67, 67, 67, 67, 123,
+ 124, 125, 128, 67, 67, 67, 67, 107,
+ 69, 67, 67, 107, 108, 109, 110, 67,
+ 67, 67, 67, 67, 67, 67, 67, 118,
+ 119, 120, 121, 67, 67, 67, 67, 123,
+ 124, 125, 128, 67, 67, 67, 67, 107,
+ 130, 67, 69, 67, 106, 107, 108, 109,
+ 110, 67, 112, 113, 67, 67, 67, 116,
+ 117, 118, 119, 120, 121, 67, 67, 67,
+ 67, 123, 124, 125, 128, 67, 67, 67,
+ 67, 107, 69, 67, 67, 107, 108, 109,
+ 110, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 119, 120, 121, 67, 67, 67,
+ 67, 123, 124, 125, 128, 67, 67, 67,
+ 67, 107, 130, 67, 69, 67, 106, 107,
+ 108, 109, 110, 67, 67, 113, 67, 67,
+ 67, 116, 117, 118, 119, 120, 121, 67,
+ 67, 67, 67, 123, 124, 125, 128, 67,
+ 67, 67, 67, 107, 130, 67, 69, 67,
+ 106, 107, 108, 109, 110, 67, 67, 67,
+ 67, 67, 67, 116, 117, 118, 119, 120,
+ 121, 67, 67, 67, 67, 123, 124, 125,
+ 128, 67, 67, 67, 67, 107, 130, 67,
+ 69, 67, 106, 107, 108, 109, 110, 111,
+ 112, 113, 67, 67, 67, 116, 117, 118,
+ 119, 120, 121, 67, 67, 67, 67, 123,
+ 124, 125, 128, 67, 67, 67, 67, 107,
+ 104, 105, 67, 69, 67, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 67, 115,
+ 116, 117, 118, 119, 120, 121, 67, 67,
+ 67, 122, 123, 124, 125, 126, 67, 67,
+ 67, 67, 127, 104, 97, 97, 97, 97,
+ 97, 97, 98, 104, 93, 93, 93, 93,
+ 93, 93, 95, 104, 67, 67, 67, 67,
+ 67, 67, 69, 67, 67, 107, 108, 109,
+ 110, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 119, 120, 121, 67, 67, 67,
+ 67, 123, 124, 125, 128, 6, 7, 131,
+ 9, 131, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 6, 20, 21, 22, 23,
+ 24, 25, 26, 131, 131, 131, 30, 31,
+ 32, 33, 30, 131, 131, 131, 131, 36,
+ 6, 131, 131, 131, 131, 131, 131, 9,
+ 131, 131, 12, 13, 14, 15, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 24,
+ 25, 26, 131, 131, 131, 131, 31, 32,
+ 33, 132, 131, 131, 131, 131, 12, 9,
+ 131, 131, 12, 13, 14, 15, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 24,
+ 25, 26, 131, 131, 131, 131, 31, 32,
+ 33, 132, 9, 131, 131, 131, 13, 14,
+ 15, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 31, 32, 33, 9, 131, 131, 131,
+ 131, 14, 15, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 31, 32, 33, 9, 131,
+ 131, 131, 131, 131, 15, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 31, 32, 33,
+ 9, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 31,
+ 32, 9, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 32, 9, 9, 131, 131, 131, 13,
+ 14, 15, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 24, 25, 26, 131, 131,
+ 131, 131, 31, 32, 33, 132, 9, 131,
+ 131, 131, 13, 14, 15, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 25,
+ 26, 131, 131, 131, 131, 31, 32, 33,
+ 132, 9, 131, 131, 131, 13, 14, 15,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 26, 131, 131, 131, 131,
+ 31, 32, 33, 132, 133, 131, 131, 131,
+ 131, 131, 131, 9, 9, 131, 131, 131,
+ 13, 14, 15, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 31, 32, 33, 132, 9,
+ 131, 11, 12, 13, 14, 15, 131, 131,
+ 131, 131, 131, 131, 21, 22, 23, 24,
+ 25, 26, 131, 131, 131, 131, 31, 32,
+ 33, 132, 131, 131, 131, 131, 12, 9,
+ 131, 131, 12, 13, 14, 15, 131, 131,
+ 131, 131, 131, 131, 21, 22, 23, 24,
+ 25, 26, 131, 131, 131, 131, 31, 32,
+ 33, 132, 131, 131, 131, 131, 12, 9,
+ 131, 131, 12, 13, 14, 15, 131, 131,
+ 131, 131, 131, 131, 131, 22, 23, 24,
+ 25, 26, 131, 131, 131, 131, 31, 32,
+ 33, 132, 131, 131, 131, 131, 12, 9,
+ 131, 131, 12, 13, 14, 15, 131, 131,
+ 131, 131, 131, 131, 131, 131, 23, 24,
+ 25, 26, 131, 131, 131, 131, 31, 32,
+ 33, 132, 131, 131, 131, 131, 12, 134,
+ 131, 9, 131, 11, 12, 13, 14, 15,
+ 131, 17, 18, 131, 131, 131, 21, 22,
+ 23, 24, 25, 26, 131, 131, 131, 131,
+ 31, 32, 33, 132, 131, 131, 131, 131,
+ 12, 9, 131, 131, 12, 13, 14, 15,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 24, 25, 26, 131, 131, 131, 131,
+ 31, 32, 33, 132, 131, 131, 131, 131,
+ 12, 134, 131, 9, 131, 11, 12, 13,
+ 14, 15, 131, 131, 18, 131, 131, 131,
+ 21, 22, 23, 24, 25, 26, 131, 131,
+ 131, 131, 31, 32, 33, 132, 131, 131,
+ 131, 131, 12, 134, 131, 9, 131, 11,
+ 12, 13, 14, 15, 131, 131, 131, 131,
+ 131, 131, 21, 22, 23, 24, 25, 26,
+ 131, 131, 131, 131, 31, 32, 33, 132,
+ 131, 131, 131, 131, 12, 134, 131, 9,
+ 131, 11, 12, 13, 14, 15, 16, 17,
+ 18, 131, 131, 131, 21, 22, 23, 24,
+ 25, 26, 131, 131, 131, 131, 31, 32,
+ 33, 132, 131, 131, 131, 131, 12, 6,
+ 7, 131, 9, 131, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 131, 20, 21,
+ 22, 23, 24, 25, 26, 131, 131, 131,
+ 30, 31, 32, 33, 30, 131, 131, 131,
+ 131, 36, 6, 131, 131, 131, 131, 131,
+ 131, 9, 6, 131, 131, 131, 131, 131,
+ 131, 9, 131, 131, 12, 13, 14, 15,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 24, 25, 26, 131, 131, 131, 131,
+ 31, 32, 33, 132, 135, 131, 131, 131,
+ 131, 9, 8, 9, 2, 131, 131, 2,
+ 6, 7, 8, 9, 131, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 6, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28,
+ 131, 30, 31, 32, 33, 30, 131, 131,
+ 131, 131, 36, 9, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 27, 28,
+ 9, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 28, 2, 136, 136,
+ 2, 138, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 139, 137, 34,
+ 138, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 34, 139, 137, 139, 138,
+ 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 137, 137,
+ 137, 137, 34, 137, 35, 0
};
-static const unsigned char _use_syllable_machine_indicies[] = {
- 0, 1, 2, 2, 3, 4, 2, 2,
- 2, 2, 2, 5, 6, 7, 8, 2,
- 2, 2, 9, 2, 2, 2, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 2, 24, 25, 26,
- 2, 27, 28, 29, 30, 31, 32, 33,
- 30, 34, 2, 35, 2, 36, 2, 38,
- 39, 37, 40, 37, 37, 37, 37, 37,
- 37, 37, 41, 42, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, 52, 53, 54,
- 37, 55, 56, 57, 37, 58, 59, 37,
- 60, 61, 62, 63, 60, 37, 37, 37,
- 37, 64, 37, 38, 39, 37, 40, 37,
- 37, 37, 37, 37, 37, 37, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 51,
- 51, 52, 53, 54, 37, 55, 56, 57,
- 37, 37, 37, 37, 60, 61, 62, 63,
- 60, 37, 37, 37, 37, 64, 37, 38,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 40, 37, 37, 37,
- 37, 37, 37, 37, 37, 42, 43, 44,
- 45, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 55, 56, 57, 37, 37,
- 37, 37, 37, 61, 62, 63, 65, 37,
- 37, 37, 37, 42, 37, 40, 37, 37,
- 37, 37, 37, 37, 37, 37, 42, 43,
- 44, 45, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 55, 56, 57, 37,
- 37, 37, 37, 37, 61, 62, 63, 65,
- 37, 40, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 43, 44, 45, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 61, 62, 63, 37, 40, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 44,
- 45, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 61, 62, 63, 37, 40,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 45, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 61, 62,
- 63, 37, 40, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 61, 62, 37, 40, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 62, 37, 40, 37,
- 40, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 43, 44, 45, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 55,
- 56, 57, 37, 37, 37, 37, 37, 61,
- 62, 63, 65, 37, 40, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 43, 44,
- 45, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 56, 57, 37, 37,
- 37, 37, 37, 61, 62, 63, 65, 37,
- 40, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 43, 44, 45, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 57, 37, 37, 37, 37, 37, 61,
- 62, 63, 65, 37, 66, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 40, 37, 40, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 43, 44, 45,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 61, 62, 63, 65, 37, 40,
- 37, 37, 37, 37, 37, 37, 37, 41,
- 42, 43, 44, 45, 37, 37, 37, 37,
- 37, 37, 52, 53, 54, 37, 55, 56,
- 57, 37, 37, 37, 37, 37, 61, 62,
- 63, 65, 37, 37, 37, 37, 42, 37,
- 40, 37, 37, 37, 37, 37, 37, 37,
- 37, 42, 43, 44, 45, 37, 37, 37,
- 37, 37, 37, 52, 53, 54, 37, 55,
- 56, 57, 37, 37, 37, 37, 37, 61,
- 62, 63, 65, 37, 37, 37, 37, 42,
- 37, 40, 37, 37, 37, 37, 37, 37,
- 37, 37, 42, 43, 44, 45, 37, 37,
- 37, 37, 37, 37, 37, 53, 54, 37,
- 55, 56, 57, 37, 37, 37, 37, 37,
- 61, 62, 63, 65, 37, 37, 37, 37,
- 42, 37, 40, 37, 37, 37, 37, 37,
- 37, 37, 37, 42, 43, 44, 45, 37,
- 37, 37, 37, 37, 37, 37, 37, 54,
- 37, 55, 56, 57, 37, 37, 37, 37,
- 37, 61, 62, 63, 65, 37, 37, 37,
- 37, 42, 37, 67, 37, 40, 37, 37,
- 37, 37, 37, 37, 37, 41, 42, 43,
- 44, 45, 37, 47, 48, 37, 37, 37,
- 52, 53, 54, 37, 55, 56, 57, 37,
- 37, 37, 37, 37, 61, 62, 63, 65,
- 37, 37, 37, 37, 42, 37, 40, 37,
- 37, 37, 37, 37, 37, 37, 37, 42,
- 43, 44, 45, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 55, 56, 57,
- 37, 37, 37, 37, 37, 61, 62, 63,
- 65, 37, 37, 37, 37, 42, 37, 67,
- 37, 40, 37, 37, 37, 37, 37, 37,
- 37, 41, 42, 43, 44, 45, 37, 37,
- 48, 37, 37, 37, 52, 53, 54, 37,
- 55, 56, 57, 37, 37, 37, 37, 37,
- 61, 62, 63, 65, 37, 37, 37, 37,
- 42, 37, 67, 37, 40, 37, 37, 37,
- 37, 37, 37, 37, 41, 42, 43, 44,
- 45, 37, 37, 37, 37, 37, 37, 52,
- 53, 54, 37, 55, 56, 57, 37, 37,
- 37, 37, 37, 61, 62, 63, 65, 37,
- 37, 37, 37, 42, 37, 67, 37, 40,
- 37, 37, 37, 37, 37, 37, 37, 41,
- 42, 43, 44, 45, 46, 47, 48, 37,
- 37, 37, 52, 53, 54, 37, 55, 56,
- 57, 37, 37, 37, 37, 37, 61, 62,
- 63, 65, 37, 37, 37, 37, 42, 37,
- 38, 39, 37, 40, 37, 37, 37, 37,
- 37, 37, 37, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 37, 51, 52, 53,
- 54, 37, 55, 56, 57, 37, 37, 37,
- 37, 60, 61, 62, 63, 60, 37, 37,
- 37, 37, 64, 37, 38, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 40, 37, 38, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 40, 37, 37, 37, 37, 37, 37, 37,
- 37, 42, 43, 44, 45, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 55,
- 56, 57, 37, 37, 37, 37, 37, 61,
- 62, 63, 65, 37, 38, 39, 37, 40,
- 37, 37, 37, 37, 37, 37, 37, 41,
- 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 37, 55, 56,
- 57, 37, 37, 37, 37, 60, 61, 62,
- 63, 60, 37, 37, 37, 37, 64, 37,
- 40, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 58, 59, 37, 40, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 59, 37, 69, 70, 68, 71,
- 68, 68, 68, 68, 68, 68, 68, 72,
- 73, 74, 75, 76, 77, 78, 79, 80,
- 1, 81, 82, 83, 84, 68, 85, 86,
- 87, 68, 68, 68, 68, 88, 89, 90,
- 91, 92, 68, 68, 68, 68, 93, 68,
- 69, 70, 68, 71, 68, 68, 68, 68,
- 68, 68, 68, 72, 73, 74, 75, 76,
- 77, 78, 79, 80, 81, 81, 82, 83,
- 84, 68, 85, 86, 87, 68, 68, 68,
- 68, 88, 89, 90, 91, 92, 68, 68,
- 68, 68, 93, 68, 69, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 71, 68, 68, 68, 68, 68, 68,
- 68, 68, 73, 74, 75, 76, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 85, 86, 87, 68, 68, 68, 68, 68,
- 89, 90, 91, 94, 68, 68, 68, 68,
- 73, 68, 71, 68, 68, 68, 68, 68,
- 68, 68, 68, 73, 74, 75, 76, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 85, 86, 87, 68, 68, 68, 68,
- 68, 89, 90, 91, 94, 68, 71, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 74, 75, 76, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 89, 90, 91,
- 68, 71, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 75, 76, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 89, 90, 91, 68, 71, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 76, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 89, 90, 91, 68, 71,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 89, 90,
- 68, 71, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 90, 68, 71, 68, 71, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 74,
- 75, 76, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 85, 86, 87, 68,
- 68, 68, 68, 68, 89, 90, 91, 94,
- 68, 71, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 74, 75, 76, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 86, 87, 68, 68, 68, 68, 68,
- 89, 90, 91, 94, 68, 71, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 74,
- 75, 76, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 87, 68,
- 68, 68, 68, 68, 89, 90, 91, 94,
- 68, 96, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 97, 95,
- 71, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 74, 75, 76, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 89,
- 90, 91, 94, 68, 71, 68, 68, 68,
- 68, 68, 68, 68, 72, 73, 74, 75,
- 76, 68, 68, 68, 68, 68, 68, 82,
- 83, 84, 68, 85, 86, 87, 68, 68,
- 68, 68, 68, 89, 90, 91, 94, 68,
- 68, 68, 68, 73, 68, 71, 68, 68,
- 68, 68, 68, 68, 68, 68, 73, 74,
- 75, 76, 68, 68, 68, 68, 68, 68,
- 82, 83, 84, 68, 85, 86, 87, 68,
- 68, 68, 68, 68, 89, 90, 91, 94,
- 68, 68, 68, 68, 73, 68, 71, 68,
- 68, 68, 68, 68, 68, 68, 68, 73,
- 74, 75, 76, 68, 68, 68, 68, 68,
- 68, 68, 83, 84, 68, 85, 86, 87,
- 68, 68, 68, 68, 68, 89, 90, 91,
- 94, 68, 68, 68, 68, 73, 68, 71,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 73, 74, 75, 76, 68, 68, 68, 68,
- 68, 68, 68, 68, 84, 68, 85, 86,
- 87, 68, 68, 68, 68, 68, 89, 90,
- 91, 94, 68, 68, 68, 68, 73, 68,
- 98, 68, 71, 68, 68, 68, 68, 68,
- 68, 68, 72, 73, 74, 75, 76, 68,
- 78, 79, 68, 68, 68, 82, 83, 84,
- 68, 85, 86, 87, 68, 68, 68, 68,
- 68, 89, 90, 91, 94, 68, 68, 68,
- 68, 73, 68, 71, 68, 68, 68, 68,
- 68, 68, 68, 68, 73, 74, 75, 76,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 85, 86, 87, 68, 68, 68,
- 68, 68, 89, 90, 91, 94, 68, 68,
- 68, 68, 73, 68, 98, 68, 71, 68,
- 68, 68, 68, 68, 68, 68, 72, 73,
- 74, 75, 76, 68, 68, 79, 68, 68,
- 68, 82, 83, 84, 68, 85, 86, 87,
- 68, 68, 68, 68, 68, 89, 90, 91,
- 94, 68, 68, 68, 68, 73, 68, 98,
- 68, 71, 68, 68, 68, 68, 68, 68,
- 68, 72, 73, 74, 75, 76, 68, 68,
- 68, 68, 68, 68, 82, 83, 84, 68,
- 85, 86, 87, 68, 68, 68, 68, 68,
- 89, 90, 91, 94, 68, 68, 68, 68,
- 73, 68, 98, 68, 71, 68, 68, 68,
- 68, 68, 68, 68, 72, 73, 74, 75,
- 76, 77, 78, 79, 68, 68, 68, 82,
- 83, 84, 68, 85, 86, 87, 68, 68,
- 68, 68, 68, 89, 90, 91, 94, 68,
- 68, 68, 68, 73, 68, 69, 70, 68,
- 71, 68, 68, 68, 68, 68, 68, 68,
- 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 68, 81, 82, 83, 84, 68, 85,
- 86, 87, 68, 68, 68, 68, 88, 89,
- 90, 91, 92, 68, 68, 68, 68, 93,
- 68, 69, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 100, 99,
- 69, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 97, 95, 69,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 71, 68, 68, 68,
- 68, 68, 68, 68, 68, 73, 74, 75,
- 76, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 85, 86, 87, 68, 68,
- 68, 68, 68, 89, 90, 91, 94, 68,
- 102, 103, 101, 3, 104, 104, 104, 104,
- 104, 104, 104, 104, 104, 105, 104, 106,
- 107, 68, 71, 68, 68, 68, 68, 68,
- 68, 68, 108, 109, 110, 111, 112, 113,
- 114, 115, 116, 117, 118, 119, 120, 121,
- 68, 122, 123, 124, 68, 58, 59, 68,
- 125, 126, 127, 128, 129, 68, 68, 68,
- 68, 130, 68, 106, 107, 68, 71, 68,
- 68, 68, 68, 68, 68, 68, 108, 109,
- 110, 111, 112, 113, 114, 115, 116, 118,
- 118, 119, 120, 121, 68, 122, 123, 124,
- 68, 68, 68, 68, 125, 126, 127, 128,
- 129, 68, 68, 68, 68, 130, 68, 106,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 71, 68, 68, 68,
- 68, 68, 68, 68, 68, 109, 110, 111,
- 112, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 122, 123, 124, 68, 68,
- 68, 68, 68, 126, 127, 128, 131, 68,
- 68, 68, 68, 109, 68, 71, 68, 68,
- 68, 68, 68, 68, 68, 68, 109, 110,
- 111, 112, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 122, 123, 124, 68,
- 68, 68, 68, 68, 126, 127, 128, 131,
- 68, 71, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 110, 111, 112, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 126, 127, 128, 68, 71, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 111,
- 112, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 126, 127, 128, 68, 71,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 112, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 126, 127,
- 128, 68, 71, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 126, 127, 68, 71, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 127, 68, 71, 68,
- 71, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 110, 111, 112, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 122,
- 123, 124, 68, 68, 68, 68, 68, 126,
- 127, 128, 131, 68, 71, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 110, 111,
- 112, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 123, 124, 68, 68,
- 68, 68, 68, 126, 127, 128, 131, 68,
- 71, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 110, 111, 112, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 124, 68, 68, 68, 68, 68, 126,
- 127, 128, 131, 68, 132, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 97, 95, 71, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 110, 111, 112,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 126, 127, 128, 131, 68, 71,
- 68, 68, 68, 68, 68, 68, 68, 108,
- 109, 110, 111, 112, 68, 68, 68, 68,
- 68, 68, 119, 120, 121, 68, 122, 123,
- 124, 68, 68, 68, 68, 68, 126, 127,
- 128, 131, 68, 68, 68, 68, 109, 68,
- 71, 68, 68, 68, 68, 68, 68, 68,
- 68, 109, 110, 111, 112, 68, 68, 68,
- 68, 68, 68, 119, 120, 121, 68, 122,
- 123, 124, 68, 68, 68, 68, 68, 126,
- 127, 128, 131, 68, 68, 68, 68, 109,
- 68, 71, 68, 68, 68, 68, 68, 68,
- 68, 68, 109, 110, 111, 112, 68, 68,
- 68, 68, 68, 68, 68, 120, 121, 68,
- 122, 123, 124, 68, 68, 68, 68, 68,
- 126, 127, 128, 131, 68, 68, 68, 68,
- 109, 68, 71, 68, 68, 68, 68, 68,
- 68, 68, 68, 109, 110, 111, 112, 68,
- 68, 68, 68, 68, 68, 68, 68, 121,
- 68, 122, 123, 124, 68, 68, 68, 68,
- 68, 126, 127, 128, 131, 68, 68, 68,
- 68, 109, 68, 133, 68, 71, 68, 68,
- 68, 68, 68, 68, 68, 108, 109, 110,
- 111, 112, 68, 114, 115, 68, 68, 68,
- 119, 120, 121, 68, 122, 123, 124, 68,
- 68, 68, 68, 68, 126, 127, 128, 131,
- 68, 68, 68, 68, 109, 68, 71, 68,
- 68, 68, 68, 68, 68, 68, 68, 109,
- 110, 111, 112, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 122, 123, 124,
- 68, 68, 68, 68, 68, 126, 127, 128,
- 131, 68, 68, 68, 68, 109, 68, 133,
- 68, 71, 68, 68, 68, 68, 68, 68,
- 68, 108, 109, 110, 111, 112, 68, 68,
- 115, 68, 68, 68, 119, 120, 121, 68,
- 122, 123, 124, 68, 68, 68, 68, 68,
- 126, 127, 128, 131, 68, 68, 68, 68,
- 109, 68, 133, 68, 71, 68, 68, 68,
- 68, 68, 68, 68, 108, 109, 110, 111,
- 112, 68, 68, 68, 68, 68, 68, 119,
- 120, 121, 68, 122, 123, 124, 68, 68,
- 68, 68, 68, 126, 127, 128, 131, 68,
- 68, 68, 68, 109, 68, 133, 68, 71,
- 68, 68, 68, 68, 68, 68, 68, 108,
- 109, 110, 111, 112, 113, 114, 115, 68,
- 68, 68, 119, 120, 121, 68, 122, 123,
- 124, 68, 68, 68, 68, 68, 126, 127,
- 128, 131, 68, 68, 68, 68, 109, 68,
- 106, 107, 68, 71, 68, 68, 68, 68,
- 68, 68, 68, 108, 109, 110, 111, 112,
- 113, 114, 115, 116, 68, 118, 119, 120,
- 121, 68, 122, 123, 124, 68, 68, 68,
- 68, 125, 126, 127, 128, 129, 68, 68,
- 68, 68, 130, 68, 106, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 100, 99, 106, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95,
- 97, 95, 106, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 71,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 109, 110, 111, 112, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 122, 123,
- 124, 68, 68, 68, 68, 68, 126, 127,
- 128, 131, 68, 106, 107, 68, 71, 68,
- 68, 68, 68, 68, 68, 68, 108, 109,
- 110, 111, 112, 113, 114, 115, 116, 117,
- 118, 119, 120, 121, 68, 122, 123, 124,
- 68, 68, 68, 68, 125, 126, 127, 128,
- 129, 68, 68, 68, 68, 130, 68, 5,
- 6, 134, 8, 134, 134, 134, 134, 134,
- 134, 134, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 20, 20, 21, 22, 23,
- 134, 24, 25, 26, 134, 134, 134, 134,
- 30, 31, 32, 33, 30, 134, 134, 134,
- 134, 36, 134, 5, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 8, 134, 134, 134, 134, 134, 134, 134,
- 134, 11, 12, 13, 14, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 24,
- 25, 26, 134, 134, 134, 134, 134, 31,
- 32, 33, 135, 134, 134, 134, 134, 11,
- 134, 8, 134, 134, 134, 134, 134, 134,
- 134, 134, 11, 12, 13, 14, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 24, 25, 26, 134, 134, 134, 134, 134,
- 31, 32, 33, 135, 134, 8, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 12,
- 13, 14, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 31, 32, 33, 134,
- 8, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 13, 14, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 31,
- 32, 33, 134, 8, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 14,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 31, 32, 33, 134, 8, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 31, 32, 134,
- 8, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 32, 134, 8, 134, 8, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 12, 13,
- 14, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 24, 25, 26, 134, 134,
- 134, 134, 134, 31, 32, 33, 135, 134,
- 8, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 12, 13, 14, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 25, 26, 134, 134, 134, 134, 134, 31,
- 32, 33, 135, 134, 8, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 12, 13,
- 14, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 26, 134, 134,
- 134, 134, 134, 31, 32, 33, 135, 134,
- 136, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 8, 134, 8,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 12, 13, 14, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 31, 32,
- 33, 135, 134, 8, 134, 134, 134, 134,
- 134, 134, 134, 10, 11, 12, 13, 14,
- 134, 134, 134, 134, 134, 134, 21, 22,
- 23, 134, 24, 25, 26, 134, 134, 134,
- 134, 134, 31, 32, 33, 135, 134, 134,
- 134, 134, 11, 134, 8, 134, 134, 134,
- 134, 134, 134, 134, 134, 11, 12, 13,
- 14, 134, 134, 134, 134, 134, 134, 21,
- 22, 23, 134, 24, 25, 26, 134, 134,
- 134, 134, 134, 31, 32, 33, 135, 134,
- 134, 134, 134, 11, 134, 8, 134, 134,
- 134, 134, 134, 134, 134, 134, 11, 12,
- 13, 14, 134, 134, 134, 134, 134, 134,
- 134, 22, 23, 134, 24, 25, 26, 134,
- 134, 134, 134, 134, 31, 32, 33, 135,
- 134, 134, 134, 134, 11, 134, 8, 134,
- 134, 134, 134, 134, 134, 134, 134, 11,
- 12, 13, 14, 134, 134, 134, 134, 134,
- 134, 134, 134, 23, 134, 24, 25, 26,
- 134, 134, 134, 134, 134, 31, 32, 33,
- 135, 134, 134, 134, 134, 11, 134, 137,
- 134, 8, 134, 134, 134, 134, 134, 134,
- 134, 10, 11, 12, 13, 14, 134, 16,
- 17, 134, 134, 134, 21, 22, 23, 134,
- 24, 25, 26, 134, 134, 134, 134, 134,
- 31, 32, 33, 135, 134, 134, 134, 134,
- 11, 134, 8, 134, 134, 134, 134, 134,
- 134, 134, 134, 11, 12, 13, 14, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 24, 25, 26, 134, 134, 134, 134,
- 134, 31, 32, 33, 135, 134, 134, 134,
- 134, 11, 134, 137, 134, 8, 134, 134,
- 134, 134, 134, 134, 134, 10, 11, 12,
- 13, 14, 134, 134, 17, 134, 134, 134,
- 21, 22, 23, 134, 24, 25, 26, 134,
- 134, 134, 134, 134, 31, 32, 33, 135,
- 134, 134, 134, 134, 11, 134, 137, 134,
- 8, 134, 134, 134, 134, 134, 134, 134,
- 10, 11, 12, 13, 14, 134, 134, 134,
- 134, 134, 134, 21, 22, 23, 134, 24,
- 25, 26, 134, 134, 134, 134, 134, 31,
- 32, 33, 135, 134, 134, 134, 134, 11,
- 134, 137, 134, 8, 134, 134, 134, 134,
- 134, 134, 134, 10, 11, 12, 13, 14,
- 15, 16, 17, 134, 134, 134, 21, 22,
- 23, 134, 24, 25, 26, 134, 134, 134,
- 134, 134, 31, 32, 33, 135, 134, 134,
- 134, 134, 11, 134, 5, 6, 134, 8,
- 134, 134, 134, 134, 134, 134, 134, 10,
- 11, 12, 13, 14, 15, 16, 17, 18,
- 134, 20, 21, 22, 23, 134, 24, 25,
- 26, 134, 134, 134, 134, 30, 31, 32,
- 33, 30, 134, 134, 134, 134, 36, 134,
- 5, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 8, 134, 5,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 8, 134, 134, 134,
- 134, 134, 134, 134, 134, 11, 12, 13,
- 14, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 24, 25, 26, 134, 134,
- 134, 134, 134, 31, 32, 33, 135, 134,
- 138, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 8, 134, 7, 8, 134, 1,
- 134, 134, 134, 1, 134, 134, 134, 134,
- 134, 5, 6, 7, 8, 134, 134, 134,
- 134, 134, 134, 134, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 134, 24, 25, 26, 134, 27,
- 28, 134, 30, 31, 32, 33, 30, 134,
- 134, 134, 134, 36, 134, 5, 6, 134,
- 8, 134, 134, 134, 134, 134, 134, 134,
- 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 134, 24,
- 25, 26, 134, 134, 134, 134, 30, 31,
- 32, 33, 30, 134, 134, 134, 134, 36,
- 134, 8, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 27, 28, 134, 8,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 134, 134, 134, 134, 134,
- 134, 134, 134, 28, 134, 1, 139, 139,
- 139, 1, 139, 141, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 142,
- 140, 34, 140, 141, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 34, 142,
- 140, 142, 140, 141, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 34, 140,
- 35, 140, 0
+static const short _use_syllable_machine_index_defaults[] = {
+ 3, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 93, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 97, 93,
+ 67, 99, 102, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 93, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 97, 93, 67, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 136, 137,
+ 137, 137, 0
};
-static const char _use_syllable_machine_trans_targs[] = {
- 1, 31, 0, 59, 61, 90, 91, 116,
- 0, 118, 104, 92, 93, 94, 95, 108,
- 110, 111, 112, 119, 113, 105, 106, 107,
- 99, 100, 101, 120, 121, 122, 114, 96,
- 97, 98, 123, 125, 115, 0, 2, 3,
- 0, 16, 4, 5, 6, 7, 20, 22,
- 23, 24, 28, 25, 17, 18, 19, 11,
- 12, 13, 29, 30, 26, 8, 9, 10,
- 27, 14, 15, 21, 0, 32, 33, 0,
- 46, 34, 35, 36, 37, 50, 52, 53,
- 54, 55, 47, 48, 49, 41, 42, 43,
- 56, 38, 39, 40, 57, 58, 44, 0,
- 45, 0, 51, 0, 0, 0, 60, 0,
- 0, 0, 62, 63, 76, 64, 65, 66,
- 67, 80, 82, 83, 84, 89, 85, 77,
- 78, 79, 71, 72, 73, 86, 68, 69,
- 70, 87, 88, 74, 75, 81, 0, 102,
- 103, 109, 117, 0, 0, 0, 124
+static const signed char _use_syllable_machine_cond_targs[] = {
+ 0, 1, 30, 0, 57, 59, 87, 88,
+ 113, 0, 115, 101, 89, 90, 91, 92,
+ 105, 107, 108, 109, 110, 102, 103, 104,
+ 96, 97, 98, 116, 117, 118, 111, 93,
+ 94, 95, 119, 121, 112, 0, 2, 3,
+ 0, 16, 4, 5, 6, 7, 20, 22,
+ 23, 24, 25, 17, 18, 19, 11, 12,
+ 13, 28, 29, 26, 8, 9, 10, 27,
+ 14, 15, 21, 0, 31, 0, 44, 32,
+ 33, 34, 35, 48, 50, 51, 52, 53,
+ 45, 46, 47, 39, 40, 41, 54, 36,
+ 37, 38, 55, 56, 42, 0, 43, 0,
+ 49, 0, 0, 0, 58, 0, 0, 0,
+ 60, 61, 74, 62, 63, 64, 65, 78,
+ 80, 81, 82, 83, 75, 76, 77, 69,
+ 70, 71, 84, 66, 67, 68, 85, 86,
+ 72, 73, 79, 0, 99, 100, 106, 114,
+ 0, 0, 0, 120, 0
};
-static const char _use_syllable_machine_trans_actions[] = {
- 0, 0, 3, 0, 0, 0, 0, 0,
- 4, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 5, 0, 0,
- 6, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 7, 0, 0, 8,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 9,
- 0, 10, 0, 11, 12, 13, 0, 14,
- 15, 16, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 17, 0,
- 0, 0, 0, 18, 19, 20, 0
+static const signed char _use_syllable_machine_cond_actions[] = {
+ 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 7, 0, 8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 9, 0, 10,
+ 0, 11, 12, 13, 0, 14, 15, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 17, 0, 0, 0, 0,
+ 18, 19, 20, 0, 0
};
-static const char _use_syllable_machine_to_state_actions[] = {
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0
+static const signed char _use_syllable_machine_to_state_actions[] = {
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
};
-static const char _use_syllable_machine_from_state_actions[] = {
- 2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0
+static const signed char _use_syllable_machine_from_state_actions[] = {
+ 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
};
static const short _use_syllable_machine_eof_trans[] = {
- 0, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 96, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 100, 96, 69, 102, 105, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 96, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 100, 96,
- 69, 69, 135, 135, 135, 135, 135, 135,
- 135, 135, 135, 135, 135, 135, 135, 135,
- 135, 135, 135, 135, 135, 135, 135, 135,
- 135, 135, 135, 135, 135, 135, 135, 135,
- 135, 135, 140, 141, 141, 141
+ 1, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 94, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 98, 94,
+ 68, 100, 103, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 94, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 98, 94, 68, 132,
+ 132, 132, 132, 132, 132, 132, 132, 132,
+ 132, 132, 132, 132, 132, 132, 132, 132,
+ 132, 132, 132, 132, 132, 132, 132, 132,
+ 132, 132, 132, 132, 132, 132, 137, 138,
+ 138, 138, 0
};
static const int use_syllable_machine_start = 0;
@@ -834,65 +701,65 @@ static const int use_syllable_machine_en_main = 0;
#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %u..%u %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
- for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (syllable_serial == 16) syllable_serial = 1; \
- } HB_STMT_END
+HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %u..%u %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
+ for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (syllable_serial == 16) syllable_serial = 1; \
+ } HB_STMT_END
template <typename Iter>
struct machine_index_t :
- hb_iter_with_fallback_t<machine_index_t<Iter>,
- typename Iter::item_t>
+hb_iter_with_fallback_t<machine_index_t<Iter>,
+typename Iter::item_t>
{
- machine_index_t (const Iter& it) : it (it) {}
- machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
- typename Iter::item_t> (),
- it (o.it), is_null (o.is_null) {}
-
- static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
- static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
-
- typename Iter::item_t __item__ () const { return *it; }
- typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
- unsigned __len__ () const { return it.len (); }
- void __next__ () { ++it; }
- void __forward__ (unsigned n) { it += n; }
- void __prev__ () { --it; }
- void __rewind__ (unsigned n) { it -= n; }
-
- void operator = (unsigned n)
- {
- assert (n == 0);
- is_null = true;
- }
- explicit operator bool () { return !is_null; }
-
- void operator = (const machine_index_t& o)
- {
- is_null = o.is_null;
- unsigned index = (*it).first;
- unsigned n = (*o.it).first;
- if (index < n) it += n - index; else if (index > n) it -= index - n;
- }
- bool operator == (const machine_index_t& o) const
- { return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
- bool operator != (const machine_index_t& o) const { return !(*this == o); }
-
- private:
- Iter it;
- bool is_null = false;
+ machine_index_t (const Iter& it) : it (it) {}
+ machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
+ typename Iter::item_t> (),
+ it (o.it), is_null (o.is_null) {}
+
+ static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
+ static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
+
+ typename Iter::item_t __item__ () const { return *it; }
+ typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
+ unsigned __len__ () const { return it.len (); }
+ void __next__ () { ++it; }
+ void __forward__ (unsigned n) { it += n; }
+ void __prev__ () { --it; }
+ void __rewind__ (unsigned n) { it -= n; }
+
+ void operator = (unsigned n)
+ {
+ assert (n == 0);
+ is_null = true;
+ }
+ explicit operator bool () { return !is_null; }
+
+ void operator = (const machine_index_t& o)
+ {
+ is_null = o.is_null;
+ unsigned index = (*it).first;
+ unsigned n = (*o.it).first;
+ if (index < n) it += n - index; else if (index > n) it -= index - n;
+ }
+ bool operator == (const machine_index_t& o) const
+ { return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
+ bool operator != (const machine_index_t& o) const { return !(*this == o); }
+
+ private:
+ Iter it;
+ bool is_null = false;
};
struct
{
- template <typename Iter,
- hb_requires (hb_is_iterable (Iter))>
- machine_index_t<hb_iter_type<Iter>>
- operator () (Iter&& it) const
- { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
+ template <typename Iter,
+ hb_requires (hb_is_iterable (Iter))>
+ machine_index_t<hb_iter_type<Iter>>
+ operator () (Iter&& it) const
+ { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
}
HB_FUNCOBJ (machine_index);
@@ -905,172 +772,352 @@ not_ccs_default_ignorable (const hb_glyph_info_t &i)
static inline void
find_syllables_use (hb_buffer_t *buffer)
{
- hb_glyph_info_t *info = buffer->info;
- auto p =
- + hb_iter (info, buffer->len)
- | hb_enumerate
- | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
- hb_second)
- | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
- {
- if (p.second.use_category() == USE(ZWNJ))
- for (unsigned i = p.first + 1; i < buffer->len; ++i)
- if (not_ccs_default_ignorable (info[i]))
- return !_hb_glyph_info_is_unicode_mark (&info[i]);
- return true;
- })
- | hb_enumerate
- | machine_index
- ;
- auto pe = p + p.len ();
- auto eof = +pe;
- auto ts = +p;
- auto te = +p;
- unsigned int act HB_UNUSED;
- int cs;
-
-#line 922 "hb-ot-shaper-use-machine.hh"
+ hb_glyph_info_t *info = buffer->info;
+ auto p =
+ + hb_iter (info, buffer->len)
+ | hb_enumerate
+ | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
+ hb_second)
+ | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
{
- cs = use_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
+ if (p.second.use_category() == USE(ZWNJ))
+ for (unsigned i = p.first + 1; i < buffer->len; ++i)
+ if (not_ccs_default_ignorable (info[i]))
+ return !_hb_glyph_info_is_unicode_mark (&info[i]);
+ return true;
+ })
+ | hb_enumerate
+ | machine_index
+ ;
+ auto pe = p + p.len ();
+ auto eof = +pe;
+ auto ts = +p;
+ auto te = +p;
+ unsigned int act HB_UNUSED;
+ int cs;
+#line 792 "hb-ot-shaper-use-machine.hh"
+ {
+ cs = (int)use_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ }
+
#line 282 "hb-ot-shaper-use-machine.rl"
+
+ unsigned int syllable_serial = 1;
- unsigned int syllable_serial = 1;
-
-#line 931 "hb-ot-shaper-use-machine.hh"
+#line 801 "hb-ot-shaper-use-machine.hh"
{
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const unsigned char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _use_syllable_machine_from_state_actions[cs] ) {
- case 2:
+ unsigned int _trans = 0;
+ const unsigned char * _keys;
+ const short * _inds;
+ int _ic;
+ _resume: {}
+ if ( p == pe && p != eof )
+ goto _out;
+ switch ( _use_syllable_machine_from_state_actions[cs] ) {
+ case 2: {
+ {
#line 1 "NONE"
- {ts = p;}
- break;
-#line 943 "hb-ot-shaper-use-machine.hh"
- }
-
- _keys = _use_syllable_machine_trans_keys + (cs<<1);
- _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
+ {ts = p;}}
+
+#line 815 "hb-ot-shaper-use-machine.hh"
- _slen = _use_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( (*p).second.second.use_category()) &&
- ( (*p).second.second.use_category()) <= _keys[1] ?
- ( (*p).second.second.use_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _use_syllable_machine_trans_targs[_trans];
-
- if ( _use_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _use_syllable_machine_trans_actions[_trans] ) {
- case 12:
+
+ break;
+ }
+ }
+
+ if ( p == eof ) {
+ if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = (unsigned int)_use_syllable_machine_eof_trans[cs] - 1;
+ }
+ }
+ else {
+ _keys = ( _use_syllable_machine_trans_keys + ((cs<<1)));
+ _inds = ( _use_syllable_machine_indicies + (_use_syllable_machine_index_offsets[cs]));
+
+ if ( ((*p).second.second.use_category()) <= 53 ) {
+ _ic = (int)_use_syllable_machine_char_class[(int)((*p).second.second.use_category()) - 0];
+ if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) )
+ _trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) ));
+ else
+ _trans = (unsigned int)_use_syllable_machine_index_defaults[cs];
+ }
+ else {
+ _trans = (unsigned int)_use_syllable_machine_index_defaults[cs];
+ }
+
+ }
+ cs = (int)_use_syllable_machine_cond_targs[_trans];
+
+ if ( _use_syllable_machine_cond_actions[_trans] != 0 ) {
+
+ switch ( _use_syllable_machine_cond_actions[_trans] ) {
+ case 12: {
+ {
+#line 170 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{
#line 170 "hb-ot-shaper-use-machine.rl"
- {te = p+1;{ found_syllable (use_virama_terminated_cluster); }}
- break;
- case 10:
+ found_syllable (use_virama_terminated_cluster); }
+ }}
+
+#line 855 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 10: {
+ {
+#line 171 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{
#line 171 "hb-ot-shaper-use-machine.rl"
- {te = p+1;{ found_syllable (use_sakot_terminated_cluster); }}
- break;
- case 8:
+ found_syllable (use_sakot_terminated_cluster); }
+ }}
+
+#line 867 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 8: {
+ {
+#line 172 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{
#line 172 "hb-ot-shaper-use-machine.rl"
- {te = p+1;{ found_syllable (use_standard_cluster); }}
- break;
- case 16:
+ found_syllable (use_standard_cluster); }
+ }}
+
+#line 879 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 16: {
+ {
+#line 173 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{
#line 173 "hb-ot-shaper-use-machine.rl"
- {te = p+1;{ found_syllable (use_number_joiner_terminated_cluster); }}
- break;
- case 14:
+ found_syllable (use_number_joiner_terminated_cluster); }
+ }}
+
+#line 891 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 14: {
+ {
+#line 174 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{
#line 174 "hb-ot-shaper-use-machine.rl"
- {te = p+1;{ found_syllable (use_numeral_cluster); }}
- break;
- case 6:
+ found_syllable (use_numeral_cluster); }
+ }}
+
+#line 903 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 6: {
+ {
+#line 175 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{
#line 175 "hb-ot-shaper-use-machine.rl"
- {te = p+1;{ found_syllable (use_symbol_cluster); }}
- break;
- case 20:
+ found_syllable (use_symbol_cluster); }
+ }}
+
+#line 915 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 20: {
+ {
#line 176 "hb-ot-shaper-use-machine.rl"
- {te = p+1;{ found_syllable (use_hieroglyph_cluster); }}
- break;
- case 4:
+ {te = p+1;{
+#line 176 "hb-ot-shaper-use-machine.rl"
+ found_syllable (use_hieroglyph_cluster); }
+ }}
+
+#line 927 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 4: {
+ {
#line 177 "hb-ot-shaper-use-machine.rl"
- {te = p+1;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
- break;
- case 3:
+ {te = p+1;{
+#line 177 "hb-ot-shaper-use-machine.rl"
+ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+ }}
+
+#line 939 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 3: {
+ {
#line 178 "hb-ot-shaper-use-machine.rl"
- {te = p+1;{ found_syllable (use_non_cluster); }}
- break;
- case 11:
+ {te = p+1;{
+#line 178 "hb-ot-shaper-use-machine.rl"
+ found_syllable (use_non_cluster); }
+ }}
+
+#line 951 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 11: {
+ {
#line 170 "hb-ot-shaper-use-machine.rl"
- {te = p;p--;{ found_syllable (use_virama_terminated_cluster); }}
- break;
- case 9:
+ {te = p;p = p - 1;{
+#line 170 "hb-ot-shaper-use-machine.rl"
+ found_syllable (use_virama_terminated_cluster); }
+ }}
+
+#line 963 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 9: {
+ {
#line 171 "hb-ot-shaper-use-machine.rl"
- {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
- break;
- case 7:
+ {te = p;p = p - 1;{
+#line 171 "hb-ot-shaper-use-machine.rl"
+ found_syllable (use_sakot_terminated_cluster); }
+ }}
+
+#line 975 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 7: {
+ {
#line 172 "hb-ot-shaper-use-machine.rl"
- {te = p;p--;{ found_syllable (use_standard_cluster); }}
- break;
- case 15:
+ {te = p;p = p - 1;{
+#line 172 "hb-ot-shaper-use-machine.rl"
+ found_syllable (use_standard_cluster); }
+ }}
+
+#line 987 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 15: {
+ {
#line 173 "hb-ot-shaper-use-machine.rl"
- {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
- break;
- case 13:
+ {te = p;p = p - 1;{
+#line 173 "hb-ot-shaper-use-machine.rl"
+ found_syllable (use_number_joiner_terminated_cluster); }
+ }}
+
+#line 999 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 13: {
+ {
+#line 174 "hb-ot-shaper-use-machine.rl"
+ {te = p;p = p - 1;{
#line 174 "hb-ot-shaper-use-machine.rl"
- {te = p;p--;{ found_syllable (use_numeral_cluster); }}
- break;
- case 5:
+ found_syllable (use_numeral_cluster); }
+ }}
+
+#line 1011 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 5: {
+ {
+#line 175 "hb-ot-shaper-use-machine.rl"
+ {te = p;p = p - 1;{
#line 175 "hb-ot-shaper-use-machine.rl"
- {te = p;p--;{ found_syllable (use_symbol_cluster); }}
- break;
- case 19:
+ found_syllable (use_symbol_cluster); }
+ }}
+
+#line 1023 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 19: {
+ {
+#line 176 "hb-ot-shaper-use-machine.rl"
+ {te = p;p = p - 1;{
#line 176 "hb-ot-shaper-use-machine.rl"
- {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
- break;
- case 17:
+ found_syllable (use_hieroglyph_cluster); }
+ }}
+
+#line 1035 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 17: {
+ {
+#line 177 "hb-ot-shaper-use-machine.rl"
+ {te = p;p = p - 1;{
#line 177 "hb-ot-shaper-use-machine.rl"
- {te = p;p--;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
- break;
- case 18:
+ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+ }}
+
+#line 1047 "hb-ot-shaper-use-machine.hh"
+
+
+ break;
+ }
+ case 18: {
+ {
#line 178 "hb-ot-shaper-use-machine.rl"
- {te = p;p--;{ found_syllable (use_non_cluster); }}
- break;
-#line 1014 "hb-ot-shaper-use-machine.hh"
- }
+ {te = p;p = p - 1;{
+#line 178 "hb-ot-shaper-use-machine.rl"
+ found_syllable (use_non_cluster); }
+ }}
+
+#line 1059 "hb-ot-shaper-use-machine.hh"
-_again:
- switch ( _use_syllable_machine_to_state_actions[cs] ) {
- case 1:
+
+ break;
+ }
+ }
+
+ }
+
+ if ( p == eof ) {
+ if ( cs >= 0 )
+ goto _out;
+ }
+ else {
+ switch ( _use_syllable_machine_to_state_actions[cs] ) {
+ case 1: {
+ {
#line 1 "NONE"
- {ts = 0;}
- break;
-#line 1021 "hb-ot-shaper-use-machine.hh"
- }
+ {ts = 0;}}
+
+#line 1078 "hb-ot-shaper-use-machine.hh"
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _use_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
+
+ break;
+ }
+ }
+
+ p += 1;
+ goto _resume;
+ }
+ _out: {}
}
-
- }
-
+
#line 287 "hb-ot-shaper-use-machine.rl"
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use.cc
index 342aba1235..c35765af95 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use.cc
@@ -377,6 +377,9 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
#define POST_BASE_FLAGS64 (FLAG64 (USE(FAbv)) | \
FLAG64 (USE(FBlw)) | \
FLAG64 (USE(FPst)) | \
+ FLAG64 (USE(FMAbv)) | \
+ FLAG64 (USE(FMBlw)) | \
+ FLAG64 (USE(FMPst)) | \
FLAG64 (USE(MAbv)) | \
FLAG64 (USE(MBlw)) | \
FLAG64 (USE(MPst)) | \
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh
index de553dd72f..f7bb3791ca 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh
@@ -57,6 +57,16 @@ enum
// Reserved = 0xFFFC /* Reserved for future use — set to zero. */
};
+static bool axis_value_is_outside_axis_range (hb_tag_t axis_tag, float axis_value,
+ const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location)
+{
+ if (!user_axes_location->has (axis_tag))
+ return false;
+
+ Triple axis_range = user_axes_location->get (axis_tag);
+ return (axis_value < axis_range.minimum || axis_value > axis_range.maximum);
+}
+
struct StatAxisRecord
{
int cmp (hb_tag_t key) const { return tag.cmp (key); }
@@ -96,23 +106,19 @@ struct AxisValueFormat1
}
bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
- const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
{
hb_tag_t axis_tag = get_axis_tag (axis_records);
float axis_value = get_value ();
- if (!user_axes_location->has (axis_tag) ||
- fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
- return true;
-
- return false;
+ return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location);
}
bool subset (hb_subset_context_t *c,
const hb_array_t<const StatAxisRecord> axis_records) const
{
TRACE_SUBSET (this);
- const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location;
if (keep_axis_value (axis_records, user_axes_location))
return_trace (c->serializer->embed (this));
@@ -155,23 +161,19 @@ struct AxisValueFormat2
}
bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
- const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
{
hb_tag_t axis_tag = get_axis_tag (axis_records);
float axis_value = get_value ();
- if (!user_axes_location->has (axis_tag) ||
- fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
- return true;
-
- return false;
+ return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location);
}
bool subset (hb_subset_context_t *c,
const hb_array_t<const StatAxisRecord> axis_records) const
{
TRACE_SUBSET (this);
- const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location;
if (keep_axis_value (axis_records, user_axes_location))
return_trace (c->serializer->embed (this));
@@ -218,23 +220,19 @@ struct AxisValueFormat3
}
bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
- const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
{
hb_tag_t axis_tag = get_axis_tag (axis_records);
float axis_value = get_value ();
- if (!user_axes_location->has (axis_tag) ||
- fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
- return true;
-
- return false;
+ return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location);
}
bool subset (hb_subset_context_t *c,
const hb_array_t<const StatAxisRecord> axis_records) const
{
TRACE_SUBSET (this);
- const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location;
if (keep_axis_value (axis_records, user_axes_location))
return_trace (c->serializer->embed (this));
@@ -291,7 +289,7 @@ struct AxisValueFormat4
{ return axisValues.as_array (axisCount)[axis_index]; }
bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
- const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
{
hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount);
@@ -301,8 +299,7 @@ struct AxisValueFormat4
float axis_value = rec.get_value ();
hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag ();
- if (user_axes_location->has (axis_tag) &&
- fabsf(axis_value - user_axes_location->get (axis_tag)) > 0.001f)
+ if (axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location))
return false;
}
@@ -313,7 +310,7 @@ struct AxisValueFormat4
const hb_array_t<const StatAxisRecord> axis_records) const
{
TRACE_SUBSET (this);
- const hb_hashmap_t<hb_tag_t, float> *user_axes_location = &c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location = &c->plan->user_axes_location;
if (!keep_axis_value (axis_records, user_axes_location))
return_trace (false);
@@ -402,7 +399,7 @@ struct AxisValue
}
bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
- hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
{
switch (u.format)
{
@@ -451,8 +448,6 @@ struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>>
const hb_array_t<const StatAxisRecord> axis_records) const
{
TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!out)) return_trace (false);
auto axisValueOffsets = as_array (axisValueCount);
count = 0;
@@ -517,7 +512,7 @@ struct STAT
return axis_value.get_value_name_id ();
}
- void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ void collect_name_ids (hb_hashmap_t<hb_tag_t, Triple> *user_axes_location,
hb_set_t *nameids_to_retain /* OUT */) const
{
if (!has_data ()) return;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
index 547f9573d0..53b6b38f66 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
@@ -412,7 +412,7 @@ parse_private_use_subtag (const char *private_use_subtag,
/**
* hb_ot_tags_from_script_and_language:
* @script: an #hb_script_t to convert.
- * @language: an #hb_language_t to convert.
+ * @language: (nullable): an #hb_language_t to convert.
* @script_count: (inout) (optional): maximum number of script tags to retrieve (IN)
* and actual number of script tags retrieved (OUT)
* @script_tags: (out) (optional): array of size at least @script_count to store the
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh
index 3449b30499..f3754aa6b8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh
@@ -72,6 +72,65 @@ struct AxisValueMap
return_trace (c->check_struct (this));
}
+ void set_mapping (float from_coord, float to_coord)
+ {
+ coords[0].set_float (from_coord);
+ coords[1].set_float (to_coord);
+ }
+
+ bool is_outside_axis_range (const Triple& axis_range) const
+ {
+ float from_coord = coords[0].to_float ();
+ return !axis_range.contains (from_coord);
+ }
+
+ bool must_include () const
+ {
+ float from_coord = coords[0].to_float ();
+ float to_coord = coords[1].to_float ();
+ return (from_coord == -1.f && to_coord == -1.f) ||
+ (from_coord == 0.f && to_coord == 0.f) ||
+ (from_coord == 1.f && to_coord == 1.f);
+ }
+
+ void instantiate (const Triple& axis_range,
+ const Triple& unmapped_range,
+ const TripleDistances& triple_distances)
+ {
+ float from_coord = coords[0].to_float ();
+ float to_coord = coords[1].to_float ();
+
+ from_coord = renormalizeValue (from_coord, unmapped_range, triple_distances);
+ to_coord = renormalizeValue (to_coord, axis_range, triple_distances);
+
+ coords[0].set_float (from_coord);
+ coords[1].set_float (to_coord);
+ }
+
+ HB_INTERNAL static int cmp (const void *pa, const void *pb)
+ {
+ const AxisValueMap *a = (const AxisValueMap *) pa;
+ const AxisValueMap *b = (const AxisValueMap *) pb;
+
+ int a_from = a->coords[0].to_int ();
+ int b_from = b->coords[0].to_int ();
+ if (a_from != b_from)
+ return a_from - b_from;
+
+ /* this should never be reached. according to the spec, all of the axis
+ * value map records for a given axis must have different fromCoord values
+ * */
+ int a_to = a->coords[1].to_int ();
+ int b_to = b->coords[1].to_int ();
+ return a_to - b_to;
+ }
+
+ bool serialize (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed (this));
+ }
+
public:
F2DOT14 coords[2];
// F2DOT14 fromCoord; /* A normalized coordinate value obtained using
@@ -122,6 +181,78 @@ struct SegmentMaps : Array16Of<AxisValueMap>
int unmap (int value) const { return map (value, 1, 0); }
+ Triple unmap_axis_range (const Triple& axis_range) const
+ {
+ F2DOT14 val, unmapped_val;
+
+ val.set_float (axis_range.minimum);
+ unmapped_val.set_int (unmap (val.to_int ()));
+ float unmapped_min = unmapped_val.to_float ();
+
+ val.set_float (axis_range.middle);
+ unmapped_val.set_int (unmap (val.to_int ()));
+ float unmapped_middle = unmapped_val.to_float ();
+
+ val.set_float (axis_range.maximum);
+ unmapped_val.set_int (unmap (val.to_int ()));
+ float unmapped_max = unmapped_val.to_float ();
+
+ return Triple{unmapped_min, unmapped_middle, unmapped_max};
+ }
+
+ bool subset (hb_subset_context_t *c, hb_tag_t axis_tag) const
+ {
+ TRACE_SUBSET (this);
+ /* avar mapped normalized axis range*/
+ Triple *axis_range;
+ if (!c->plan->axes_location.has (axis_tag, &axis_range))
+ return c->serializer->embed (*this);
+
+ TripleDistances *axis_triple_distances;
+ if (!c->plan->axes_triple_distances.has (axis_tag, &axis_triple_distances))
+ return_trace (false);
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ Triple unmapped_range = unmap_axis_range (*axis_range);
+
+ /* create a vector of retained mappings and sort */
+ hb_vector_t<AxisValueMap> value_mappings;
+ for (const auto& _ : as_array ())
+ {
+ if (_.is_outside_axis_range (unmapped_range))
+ continue;
+ AxisValueMap mapping;
+ mapping = _;
+ mapping.instantiate (*axis_range, unmapped_range, *axis_triple_distances);
+ /* (-1, -1), (0, 0), (1, 1) mappings will be added later, so avoid
+ * duplicates here */
+ if (mapping.must_include ())
+ continue;
+ value_mappings.push (std::move (mapping));
+ }
+
+ AxisValueMap m;
+ m.set_mapping (-1.f, -1.f);
+ value_mappings.push (m);
+
+ m.set_mapping (0.f, 0.f);
+ value_mappings.push (m);
+
+ m.set_mapping (1.f, 1.f);
+ value_mappings.push (m);
+
+ value_mappings.qsort ();
+
+ for (const auto& _ : value_mappings)
+ {
+ if (!_.serialize (c->serializer))
+ return_trace (false);
+ }
+ return_trace (c->serializer->check_assign (out->len, value_mappings.length, HB_SERIALIZE_ERROR_INT_OVERFLOW));
+ }
+
public:
DEFINE_SIZE_ARRAY (2, *this);
};
@@ -225,6 +356,39 @@ struct avar
}
}
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ unsigned retained_axis_count = c->plan->axes_index_map.get_population ();
+ if (!retained_axis_count) //all axes are pinned/dropped
+ return_trace (false);
+
+ avar *out = c->serializer->allocate_min<avar> ();
+ if (unlikely (!out)) return_trace (false);
+
+ out->version.major = 1;
+ out->version.minor = 0;
+ if (!c->serializer->check_assign (out->axisCount, retained_axis_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+
+ const hb_map_t& axes_index_map = c->plan->axes_index_map;
+ const SegmentMaps *map = &firstAxisSegmentMaps;
+ unsigned count = axisCount;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (axes_index_map.has (i))
+ {
+ hb_tag_t *axis_tag;
+ if (!c->plan->axes_old_index_tag_map.has (i, &axis_tag))
+ return_trace (false);
+ if (!map->subset (c, *axis_tag))
+ return_trace (false);
+ }
+ map = &StructAfter<SegmentMaps> (*map);
+ }
+ return_trace (true);
+ }
+
protected:
FixedVersion<>version; /* Version of the avar table
* initially set to 0x00010000u */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
index 7d4bf2241c..9e813f6d2d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
@@ -36,19 +36,14 @@ struct DeltaSetIndexMapFormat01
{
friend struct DeltaSetIndexMap;
+ unsigned get_size () const
+ { return min_size + mapCount * get_width (); }
+
private:
DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
- auto *out = c->start_embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- unsigned total_size = min_size + mapCount * get_width ();
- HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
- if (unlikely (!p)) return_trace (nullptr);
-
- hb_memcpy (p, this, HBUINT8::static_size * total_size);
- return_trace (out);
+ return_trace (c->embed (this));
}
template <typename T>
@@ -69,14 +64,17 @@ struct DeltaSetIndexMapFormat01
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;)
+ unsigned int v = output_map.arrayZ[i];
+ if (v)
{
- p[--w] = u;
- u >>= 8;
+ 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;
}
@@ -242,6 +240,7 @@ struct VarStoreInstancer
/* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
struct TupleVariationHeader
{
+ friend struct tuple_delta_t;
unsigned get_size (unsigned axis_count) const
{ return min_size + get_all_tuples (axis_count).get_size (); }
@@ -250,14 +249,67 @@ struct TupleVariationHeader
const TupleVariationHeader &get_next (unsigned axis_count) const
{ return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count)); }
+ bool unpack_axis_tuples (unsigned axis_count,
+ const hb_array_t<const F2DOT14> shared_tuples,
+ const hb_map_t *axes_old_index_tag_map,
+ hb_hashmap_t<hb_tag_t, Triple>& axis_tuples /* OUT */) const
+ {
+ const F2DOT14 *peak_tuple = nullptr;
+ if (has_peak ())
+ peak_tuple = get_peak_tuple (axis_count).arrayZ;
+ else
+ {
+ unsigned int index = get_index ();
+ if (unlikely ((index + 1) * axis_count > shared_tuples.length))
+ return false;
+ peak_tuple = shared_tuples.sub_array (axis_count * index, axis_count).arrayZ;
+ }
+
+ const F2DOT14 *start_tuple = nullptr;
+ const F2DOT14 *end_tuple = nullptr;
+ bool has_interm = has_intermediate ();
+
+ if (has_interm)
+ {
+ start_tuple = get_start_tuple (axis_count).arrayZ;
+ end_tuple = get_end_tuple (axis_count).arrayZ;
+ }
+
+ for (unsigned i = 0; i < axis_count; i++)
+ {
+ float peak = peak_tuple[i].to_float ();
+ if (peak == 0.f) continue;
+
+ hb_tag_t *axis_tag;
+ if (!axes_old_index_tag_map->has (i, &axis_tag))
+ return false;
+
+ float start, end;
+ if (has_interm)
+ {
+ start = start_tuple[i].to_float ();
+ end = end_tuple[i].to_float ();
+ }
+ else
+ {
+ start = hb_min (peak, 0.f);
+ end = hb_max (peak, 0.f);
+ }
+ axis_tuples.set (*axis_tag, Triple (start, peak, end));
+ }
+
+ return true;
+ }
+
float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
const hb_array_t<const F2DOT14> shared_tuples,
- const hb_vector_t<int> *shared_tuple_active_idx = nullptr) const
+ const hb_vector_t<hb_pair_t<int,int>> *shared_tuple_active_idx = nullptr) const
{
const F2DOT14 *peak_tuple;
unsigned start_idx = 0;
unsigned end_idx = coord_count;
+ unsigned step = 1;
if (has_peak ())
peak_tuple = get_peak_tuple (coord_count).arrayZ;
@@ -272,10 +324,16 @@ struct TupleVariationHeader
{
if (unlikely (index >= shared_tuple_active_idx->length))
return 0.f;
- int v = (*shared_tuple_active_idx).arrayZ[index];
- if (v != -1)
+ auto _ = (*shared_tuple_active_idx).arrayZ[index];
+ if (_.second != -1)
{
- start_idx = v;
+ start_idx = _.first;
+ end_idx = _.second + 1;
+ step = _.second - _.first;
+ }
+ else if (_.first != -1)
+ {
+ start_idx = _.first;
end_idx = start_idx + 1;
}
}
@@ -291,7 +349,7 @@ struct TupleVariationHeader
}
float scalar = 1.f;
- for (unsigned int i = start_idx; i < end_idx; i++)
+ for (unsigned int i = start_idx; i < end_idx; i += step)
{
int peak = peak_tuple[i].to_int ();
if (!peak) continue;
@@ -333,6 +391,7 @@ struct TupleVariationHeader
TupleIndexMask = 0x0FFFu
};
+ TuppleIndex& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
DEFINE_SIZE_STATIC (2);
};
@@ -365,6 +424,454 @@ struct TupleVariationHeader
DEFINE_SIZE_MIN (4);
};
+enum packed_delta_flag_t
+{
+ DELTAS_ARE_ZERO = 0x80,
+ DELTAS_ARE_WORDS = 0x40,
+ DELTA_RUN_COUNT_MASK = 0x3F
+};
+
+struct tuple_delta_t
+{
+ public:
+ hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
+
+ /* indices_length = point_count, indice[i] = 1 means point i is referenced */
+ hb_vector_t<bool> indices;
+
+ hb_vector_t<float> deltas_x;
+ /* empty for cvar tuples */
+ hb_vector_t<float> deltas_y;
+
+ /* compiled data: header and deltas
+ * compiled point data is saved in a hashmap within tuple_variations_t cause
+ * some point sets might be reused by different tuple variations */
+ hb_vector_t<char> compiled_tuple_header;
+ hb_vector_t<char> compiled_deltas;
+
+ tuple_delta_t () = default;
+ tuple_delta_t (const tuple_delta_t& o) = default;
+
+ tuple_delta_t (tuple_delta_t&& o) : tuple_delta_t ()
+ {
+ axis_tuples = std::move (o.axis_tuples);
+ indices = std::move (o.indices);
+ deltas_x = std::move (o.deltas_x);
+ deltas_y = std::move (o.deltas_y);
+ }
+
+ tuple_delta_t& operator = (tuple_delta_t&& o)
+ {
+ hb_swap (*this, o);
+ return *this;
+ }
+
+ void remove_axis (hb_tag_t axis_tag)
+ { axis_tuples.del (axis_tag); }
+
+ bool set_tent (hb_tag_t axis_tag, Triple tent)
+ { return axis_tuples.set (axis_tag, tent); }
+
+ tuple_delta_t& operator += (const tuple_delta_t& o)
+ {
+ unsigned num = indices.length;
+ for (unsigned i = 0; i < num; i++)
+ {
+ if (indices.arrayZ[i])
+ {
+ if (o.indices.arrayZ[i])
+ {
+ deltas_x[i] += o.deltas_x[i];
+ if (deltas_y && o.deltas_y)
+ deltas_y[i] += o.deltas_y[i];
+ }
+ }
+ else
+ {
+ if (!o.indices.arrayZ[i]) continue;
+ indices.arrayZ[i] = true;
+ deltas_x[i] = o.deltas_x[i];
+ if (deltas_y && o.deltas_y)
+ deltas_y[i] = o.deltas_y[i];
+ }
+ }
+ return *this;
+ }
+
+ tuple_delta_t& operator *= (float scalar)
+ {
+ if (scalar == 1.0f)
+ return *this;
+
+ unsigned num = indices.length;
+ for (unsigned i = 0; i < num; i++)
+ {
+ if (!indices.arrayZ[i]) continue;
+
+ deltas_x[i] *= scalar;
+ if (deltas_y)
+ deltas_y[i] *= scalar;
+ }
+ return *this;
+ }
+
+ hb_vector_t<tuple_delta_t> change_tuple_var_axis_limit (hb_tag_t axis_tag, Triple axis_limit,
+ TripleDistances axis_triple_distances) const
+ {
+ hb_vector_t<tuple_delta_t> out;
+ Triple *tent;
+ if (!axis_tuples.has (axis_tag, &tent))
+ {
+ out.push (*this);
+ return out;
+ }
+
+ if ((tent->minimum < 0.f && tent->maximum > 0.f) ||
+ !(tent->minimum <= tent->middle && tent->middle <= tent->maximum))
+ return out;
+
+ if (tent->middle == 0.f)
+ {
+ out.push (*this);
+ return out;
+ }
+
+ result_t solutions = rebase_tent (*tent, axis_limit, axis_triple_distances);
+ for (auto t : solutions)
+ {
+ tuple_delta_t new_var = *this;
+ if (t.second == Triple ())
+ new_var.remove_axis (axis_tag);
+ else
+ new_var.set_tent (axis_tag, t.second);
+
+ new_var *= t.first;
+ out.push (std::move (new_var));
+ }
+
+ return out;
+ }
+
+ /* deltas should be compiled already before we compile tuple
+ * variation header cause we need to fill in the size of the
+ * serialized data for this tuple variation */
+ //TODO(qxliu):add option to use sharedTuples in gvar
+ bool compile_tuple_var_header (const hb_map_t& axes_index_map,
+ unsigned points_data_length,
+ const hb_map_t& axes_old_index_tag_map)
+ {
+ if (!compiled_deltas) return false;
+
+ unsigned cur_axis_count = axes_index_map.get_population ();
+ /* allocate enough memory: 1 peak + 2 intermediate coords + fixed header size */
+ unsigned alloc_len = 3 * cur_axis_count * (F2DOT14::static_size) + 4;
+ if (unlikely (!compiled_tuple_header.resize (alloc_len))) return false;
+
+ unsigned flag = 0;
+ /* skip the first 4 header bytes: variationDataSize+tupleIndex */
+ F2DOT14* p = reinterpret_cast<F2DOT14 *> (compiled_tuple_header.begin () + 4);
+ F2DOT14* end = reinterpret_cast<F2DOT14 *> (compiled_tuple_header.end ());
+ hb_array_t<F2DOT14> coords (p, end - p);
+
+ /* encode peak coords */
+ unsigned peak_count = encode_peak_coords(coords, flag, axes_index_map, axes_old_index_tag_map);
+ if (!peak_count) return false;
+
+ /* encode interim coords, it's optional so returned num could be 0 */
+ unsigned interim_count = encode_interm_coords (coords.sub_array (peak_count), flag, axes_index_map, axes_old_index_tag_map);
+
+ //TODO(qxliu): add option to use shared_points in gvar
+ flag |= TupleVariationHeader::TuppleIndex::PrivatePointNumbers;
+
+ unsigned serialized_data_size = points_data_length + compiled_deltas.length;
+ TupleVariationHeader *o = reinterpret_cast<TupleVariationHeader *> (compiled_tuple_header.begin ());
+ o->varDataSize = serialized_data_size;
+ o->tupleIndex = flag;
+
+ unsigned total_header_len = 4 + (peak_count + interim_count) * (F2DOT14::static_size);
+ return compiled_tuple_header.resize (total_header_len);
+ }
+
+ unsigned encode_peak_coords (hb_array_t<F2DOT14> peak_coords,
+ unsigned& flag,
+ const hb_map_t& axes_index_map,
+ const hb_map_t& axes_old_index_tag_map) const
+ {
+ unsigned orig_axis_count = axes_old_index_tag_map.get_population ();
+ auto it = peak_coords.iter ();
+ unsigned count = 0;
+ for (unsigned i = 0; i < orig_axis_count; i++)
+ {
+ if (!axes_index_map.has (i)) /* axis pinned */
+ continue;
+ hb_tag_t axis_tag = axes_old_index_tag_map.get (i);
+ Triple *coords;
+ if (!axis_tuples.has (axis_tag, &coords))
+ (*it).set_int (0);
+ else
+ (*it).set_float (coords->middle);
+ it++;
+ count++;
+ }
+ flag |= TupleVariationHeader::TuppleIndex::EmbeddedPeakTuple;
+ return count;
+ }
+
+ /* if no need to encode intermediate coords, then just return p */
+ unsigned encode_interm_coords (hb_array_t<F2DOT14> coords,
+ unsigned& flag,
+ const hb_map_t& axes_index_map,
+ const hb_map_t& axes_old_index_tag_map) const
+ {
+ unsigned orig_axis_count = axes_old_index_tag_map.get_population ();
+ unsigned cur_axis_count = axes_index_map.get_population ();
+
+ auto start_coords_iter = coords.sub_array (0, cur_axis_count).iter ();
+ auto end_coords_iter = coords.sub_array (cur_axis_count).iter ();
+ bool encode_needed = false;
+ unsigned count = 0;
+ for (unsigned i = 0; i < orig_axis_count; i++)
+ {
+ if (!axes_index_map.has (i)) /* axis pinned */
+ continue;
+ hb_tag_t axis_tag = axes_old_index_tag_map.get (i);
+ Triple *coords;
+ float min_val = 0.f, val = 0.f, max_val = 0.f;
+ if (axis_tuples.has (axis_tag, &coords))
+ {
+ min_val = coords->minimum;
+ val = coords->middle;
+ max_val = coords->maximum;
+ }
+
+ (*start_coords_iter).set_float (min_val);
+ (*end_coords_iter).set_float (max_val);
+
+ start_coords_iter++;
+ end_coords_iter++;
+ count += 2;
+ if (min_val != hb_min (val, 0.f) || max_val != hb_max (val, 0.f))
+ encode_needed = true;
+ }
+
+ if (encode_needed)
+ {
+ flag |= TupleVariationHeader::TuppleIndex::IntermediateRegion;
+ return count;
+ }
+ return 0;
+ }
+
+ bool compile_deltas ()
+ {
+ hb_vector_t<int> rounded_deltas;
+ if (unlikely (!rounded_deltas.alloc (indices.length)))
+ return false;
+
+ for (unsigned i = 0; i < indices.length; i++)
+ {
+ if (!indices[i]) continue;
+ int rounded_delta = (int) roundf (deltas_x[i]);
+ rounded_deltas.push (rounded_delta);
+ }
+
+ if (!rounded_deltas) return false;
+ /* allocate enough memories 3 * num_deltas */
+ unsigned alloc_len = 3 * rounded_deltas.length;
+ if (deltas_y)
+ alloc_len *= 2;
+
+ if (unlikely (!compiled_deltas.resize (alloc_len))) return false;
+
+ unsigned i = 0;
+ unsigned encoded_len = encode_delta_run (i, compiled_deltas.as_array (), rounded_deltas);
+
+ if (deltas_y)
+ {
+ /* reuse the rounded_deltas vector, check that deltas_y have the same num of deltas as deltas_x */
+ unsigned j = 0;
+ for (unsigned idx = 0; idx < indices.length; idx++)
+ {
+ if (!indices[idx]) continue;
+ int rounded_delta = (int) roundf (deltas_y[idx]);
+
+ if (j >= rounded_deltas.length) return false;
+
+ rounded_deltas[j++] = rounded_delta;
+ }
+
+ if (j != rounded_deltas.length) return false;
+ /* reset i because we reuse rounded_deltas for deltas_y */
+ i = 0;
+ encoded_len += encode_delta_run (i, compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas);
+ }
+ return compiled_deltas.resize (encoded_len);
+ }
+
+ unsigned encode_delta_run (unsigned& i,
+ hb_array_t<char> encoded_bytes,
+ const hb_vector_t<int>& deltas) const
+ {
+ unsigned num_deltas = deltas.length;
+ unsigned encoded_len = 0;
+ while (i < num_deltas)
+ {
+ int val = deltas[i];
+ if (val == 0)
+ encoded_len += encode_delta_run_as_zeroes (i, encoded_bytes.sub_array (encoded_len), deltas);
+ else if (val >= -128 && val <= 127)
+ encoded_len += encode_delta_run_as_bytes (i, encoded_bytes.sub_array (encoded_len), deltas);
+ else
+ encoded_len += encode_delta_run_as_words (i, encoded_bytes.sub_array (encoded_len), deltas);
+ }
+ return encoded_len;
+ }
+
+ unsigned encode_delta_run_as_zeroes (unsigned& i,
+ hb_array_t<char> encoded_bytes,
+ const hb_vector_t<int>& deltas) const
+ {
+ unsigned num_deltas = deltas.length;
+ unsigned run_length = 0;
+ auto it = encoded_bytes.iter ();
+ unsigned encoded_len = 0;
+ while (i < num_deltas && deltas[i] == 0)
+ {
+ i++;
+ run_length++;
+ }
+
+ while (run_length >= 64)
+ {
+ *it++ = char (DELTAS_ARE_ZERO | 63);
+ run_length -= 64;
+ encoded_len++;
+ }
+
+ if (run_length)
+ {
+ *it++ = char (DELTAS_ARE_ZERO | (run_length - 1));
+ encoded_len++;
+ }
+ return encoded_len;
+ }
+
+ unsigned encode_delta_run_as_bytes (unsigned &i,
+ hb_array_t<char> encoded_bytes,
+ const hb_vector_t<int>& deltas) const
+ {
+ unsigned start = i;
+ unsigned num_deltas = deltas.length;
+ while (i < num_deltas)
+ {
+ int val = deltas[i];
+ if (val > 127 || val < -128)
+ break;
+
+ /* from fonttools: if there're 2 or more zeros in a sequence,
+ * it is better to start a new run to save bytes. */
+ if (val == 0 && i + 1 < num_deltas && deltas[i+1] == 0)
+ break;
+
+ i++;
+ }
+ unsigned run_length = i - start;
+
+ unsigned encoded_len = 0;
+ auto it = encoded_bytes.iter ();
+
+ while (run_length >= 64)
+ {
+ *it++ = 63;
+ encoded_len++;
+
+ for (unsigned j = 0; j < 64; j++)
+ {
+ *it++ = static_cast<char> (deltas[start + j]);
+ encoded_len++;
+ }
+
+ start += 64;
+ run_length -= 64;
+ }
+
+ if (run_length)
+ {
+ *it++ = run_length - 1;
+ encoded_len++;
+
+ while (start < i)
+ {
+ *it++ = static_cast<char> (deltas[start++]);
+ encoded_len++;
+ }
+ }
+
+ return encoded_len;
+ }
+
+ unsigned encode_delta_run_as_words (unsigned &i,
+ hb_array_t<char> encoded_bytes,
+ const hb_vector_t<int>& deltas) const
+ {
+ unsigned start = i;
+ unsigned num_deltas = deltas.length;
+ while (i < num_deltas)
+ {
+ int val = deltas[i];
+
+ /* start a new run for a single zero value*/
+ if (val == 0) break;
+
+ /* from fonttools: continue word-encoded run if there's only one
+ * single value in the range [-128, 127] because it is more compact.
+ * Only start a new run when there're 2 continuous such values. */
+ if (val >= -128 && val <= 127 &&
+ i + 1 < num_deltas &&
+ deltas[i+1] >= -128 && deltas[i+1] <= 127)
+ break;
+
+ i++;
+ }
+
+ unsigned run_length = i - start;
+ auto it = encoded_bytes.iter ();
+ unsigned encoded_len = 0;
+ while (run_length >= 64)
+ {
+ *it++ = (DELTAS_ARE_WORDS | 63);
+ encoded_len++;
+
+ for (unsigned j = 0; j < 64; j++)
+ {
+ int16_t delta_val = deltas[start + j];
+ *it++ = static_cast<char> (delta_val >> 8);
+ *it++ = static_cast<char> (delta_val & 0xFF);
+
+ encoded_len += 2;
+ }
+
+ start += 64;
+ run_length -= 64;
+ }
+
+ if (run_length)
+ {
+ *it++ = (DELTAS_ARE_WORDS | (run_length - 1));
+ encoded_len++;
+ while (start < i)
+ {
+ int16_t delta_val = deltas[start++];
+ *it++ = static_cast<char> (delta_val >> 8);
+ *it++ = static_cast<char> (delta_val & 0xFF);
+
+ encoded_len += 2;
+ }
+ }
+ return encoded_len;
+ }
+};
+
struct TupleVariationData
{
bool sanitize (hb_sanitize_context_t *c) const
@@ -378,7 +885,7 @@ struct TupleVariationData
unsigned get_size (unsigned axis_count) const
{
unsigned total_size = min_size;
- unsigned count = tupleVarCount;
+ unsigned count = tupleVarCount.get_count ();
const TupleVariationHeader *tuple_var_header = &(get_tuple_var_header());
for (unsigned i = 0; i < count; i++)
{
@@ -392,8 +899,358 @@ struct TupleVariationData
const TupleVariationHeader &get_tuple_var_header (void) const
{ return StructAfter<TupleVariationHeader> (data); }
+ struct tuple_iterator_t;
+ struct tuple_variations_t
+ {
+ hb_vector_t<tuple_delta_t> tuple_vars;
+
+ private:
+ /* referenced point set->compiled point data map */
+ hb_hashmap_t<const hb_vector_t<bool>*, hb_bytes_t> point_data_map;
+ /* referenced point set-> count map, used in finding shared points */
+ hb_hashmap_t<const hb_vector_t<bool>*, unsigned> point_set_count_map;
+
+ public:
+ ~tuple_variations_t () { fini (); }
+ void fini ()
+ {
+ for (auto _ : point_data_map.values ())
+ _.fini ();
+
+ point_set_count_map.fini ();
+ tuple_vars.fini ();
+ }
+
+ unsigned get_var_count () const
+ { return tuple_vars.length; }
+
+ bool create_from_tuple_var_data (tuple_iterator_t iterator,
+ unsigned tuple_var_count,
+ unsigned point_count,
+ bool is_gvar,
+ const hb_map_t *axes_old_index_tag_map,
+ const hb_vector_t<unsigned> &shared_indices,
+ const hb_array_t<const F2DOT14> shared_tuples)
+ {
+ do
+ {
+ const HBUINT8 *p = iterator.get_serialized_data ();
+ unsigned int length = iterator.current_tuple->get_data_size ();
+ if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
+ { fini (); return false; }
+
+ hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
+ if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, axes_old_index_tag_map, axis_tuples)
+ || axis_tuples.is_empty ())
+ { fini (); return false; }
+
+ hb_vector_t<unsigned> private_indices;
+ bool has_private_points = iterator.current_tuple->has_private_points ();
+ const HBUINT8 *end = p + length;
+ if (has_private_points &&
+ !TupleVariationData::unpack_points (p, private_indices, end))
+ { fini (); return false; }
+
+ const hb_vector_t<unsigned> &indices = has_private_points ? private_indices : shared_indices;
+ bool apply_to_all = (indices.length == 0);
+ unsigned num_deltas = apply_to_all ? point_count : indices.length;
+
+ hb_vector_t<int> deltas_x;
+
+ if (unlikely (!deltas_x.resize (num_deltas, false) ||
+ !TupleVariationData::unpack_deltas (p, deltas_x, end)))
+ { fini (); return false; }
+
+ hb_vector_t<int> deltas_y;
+ if (is_gvar)
+ {
+ if (unlikely (!deltas_y.resize (num_deltas, false) ||
+ !TupleVariationData::unpack_deltas (p, deltas_y, end)))
+ { fini (); return false; }
+ }
+
+ tuple_delta_t var;
+ var.axis_tuples = std::move (axis_tuples);
+ if (unlikely (!var.indices.resize (point_count) ||
+ !var.deltas_x.resize (point_count, false)))
+ { fini (); return false; }
+
+ if (is_gvar && unlikely (!var.deltas_y.resize (point_count, false)))
+ { fini (); return false; }
+
+ for (unsigned i = 0; i < num_deltas; i++)
+ {
+ unsigned idx = apply_to_all ? i : indices[i];
+ if (idx >= point_count) continue;
+ var.indices[idx] = true;
+ var.deltas_x[idx] = static_cast<float> (deltas_x[i]);
+ if (is_gvar)
+ var.deltas_y[idx] = static_cast<float> (deltas_y[i]);
+ }
+ tuple_vars.push (std::move (var));
+ } while (iterator.move_to_next ());
+ return true;
+ }
+
+ void change_tuple_variations_axis_limits (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location,
+ const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances)
+ {
+ for (auto _ : normalized_axes_location)
+ {
+ hb_tag_t axis_tag = _.first;
+ Triple axis_limit = _.second;
+ TripleDistances axis_triple_distances{1.f, 1.f};
+ if (axes_triple_distances.has (axis_tag))
+ axis_triple_distances = axes_triple_distances.get (axis_tag);
+
+ hb_vector_t<tuple_delta_t> new_vars;
+ for (const tuple_delta_t& var : tuple_vars)
+ {
+ hb_vector_t<tuple_delta_t> out = var.change_tuple_var_axis_limit (axis_tag, axis_limit, axis_triple_distances);
+ if (!out) continue;
+ unsigned new_len = new_vars.length + out.length;
+
+ if (unlikely (!new_vars.alloc (new_len, false)))
+ { fini (); return;}
+
+ for (unsigned i = 0; i < out.length; i++)
+ new_vars.push (std::move (out[i]));
+ }
+ tuple_vars.fini ();
+ tuple_vars = std::move (new_vars);
+ }
+ }
+
+ /* merge tuple variations with overlapping tents */
+ void merge_tuple_variations ()
+ {
+ hb_vector_t<tuple_delta_t> new_vars;
+ hb_hashmap_t<hb_hashmap_t<hb_tag_t, Triple>, unsigned> m;
+ unsigned i = 0;
+ for (const tuple_delta_t& var : tuple_vars)
+ {
+ /* if all axes are pinned, drop the tuple variation */
+ if (var.axis_tuples.is_empty ()) continue;
+
+ unsigned *idx;
+ if (m.has (var.axis_tuples, &idx))
+ {
+ new_vars[*idx] += var;
+ }
+ else
+ {
+ new_vars.push (var);
+ m.set (var.axis_tuples, i);
+ i++;
+ }
+ }
+ tuple_vars.fini ();
+ tuple_vars = std::move (new_vars);
+ }
+
+ hb_bytes_t compile_point_set (const hb_vector_t<bool> &point_indices)
+ {
+ unsigned num_points = 0;
+ for (bool i : point_indices)
+ if (i) num_points++;
+
+ unsigned indices_length = point_indices.length;
+ /* If the points set consists of all points in the glyph, it's encoded with a
+ * single zero byte */
+ if (num_points == indices_length)
+ {
+ char *p = (char *) hb_calloc (1, sizeof (char));
+ if (unlikely (!p)) return hb_bytes_t ();
+
+ return hb_bytes_t (p, 1);
+ }
+
+ /* allocate enough memories: 2 bytes for count + 3 bytes for each point */
+ unsigned num_bytes = 2 + 3 *num_points;
+ char *p = (char *) hb_calloc (num_bytes, sizeof (char));
+ if (unlikely (!p)) return hb_bytes_t ();
+
+ unsigned pos = 0;
+ /* binary data starts with the total number of reference points */
+ if (num_points < 0x80)
+ p[pos++] = num_points;
+ else
+ {
+ p[pos++] = ((num_points >> 8) | 0x80);
+ p[pos++] = num_points & 0xFF;
+ }
+
+ const unsigned max_run_length = 0x7F;
+ unsigned i = 0;
+ unsigned last_value = 0;
+ unsigned num_encoded = 0;
+ while (i < indices_length && num_encoded < num_points)
+ {
+ unsigned run_length = 0;
+ unsigned header_pos = pos;
+ p[pos++] = 0;
+
+ bool use_byte_encoding = false;
+ bool new_run = true;
+ while (i < indices_length && num_encoded < num_points &&
+ run_length <= max_run_length)
+ {
+ // find out next referenced point index
+ while (i < indices_length && !point_indices[i])
+ i++;
+
+ if (i >= indices_length) break;
+
+ unsigned cur_value = i;
+ unsigned delta = cur_value - last_value;
+
+ if (new_run)
+ {
+ use_byte_encoding = (delta <= 0xFF);
+ new_run = false;
+ }
+
+ if (use_byte_encoding && delta > 0xFF)
+ break;
+
+ if (use_byte_encoding)
+ p[pos++] = delta;
+ else
+ {
+ p[pos++] = delta >> 8;
+ p[pos++] = delta & 0xFF;
+ }
+ i++;
+ last_value = cur_value;
+ run_length++;
+ num_encoded++;
+ }
+
+ if (use_byte_encoding)
+ p[header_pos] = run_length - 1;
+ else
+ p[header_pos] = (run_length - 1) | 0x80;
+ }
+ return hb_bytes_t (p, pos);
+ }
+
+ /* compile all point set and store byte data in a point_set->hb_bytes_t hashmap,
+ * also update point_set->count map, which will be used in finding shared
+ * point set*/
+ bool compile_all_point_sets ()
+ {
+ for (const auto& tuple: tuple_vars)
+ {
+ const hb_vector_t<bool>* points_set = &(tuple.indices);
+ if (point_data_map.has (points_set))
+ {
+ unsigned *count;
+ if (unlikely (!point_set_count_map.has (points_set, &count) ||
+ !point_set_count_map.set (points_set, (*count) + 1)))
+ return false;
+ continue;
+ }
+
+ hb_bytes_t compiled_data = compile_point_set (*points_set);
+ if (unlikely (compiled_data == hb_bytes_t ()))
+ return false;
+
+ if (!point_data_map.set (points_set, compiled_data) ||
+ !point_set_count_map.set (points_set, 1))
+ return false;
+ }
+ return true;
+ }
+
+ /* find shared points set which saves most bytes */
+ hb_bytes_t find_shared_points ()
+ {
+ unsigned max_saved_bytes = 0;
+ hb_bytes_t res{};
+
+ for (const auto& _ : point_data_map.iter ())
+ {
+ const hb_vector_t<bool>* points_set = _.first;
+ unsigned data_length = _.second.length;
+ unsigned *count;
+ if (unlikely (!point_set_count_map.has (points_set, &count) ||
+ *count <= 1))
+ return hb_bytes_t ();
+
+ unsigned saved_bytes = data_length * ((*count) -1);
+ if (saved_bytes > max_saved_bytes)
+ {
+ max_saved_bytes = saved_bytes;
+ res = _.second;
+ }
+ }
+ return res;
+ }
+
+ void instantiate (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location,
+ const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances)
+ {
+ change_tuple_variations_axis_limits (normalized_axes_location, axes_triple_distances);
+ merge_tuple_variations ();
+ }
+
+ bool compile_bytes (const hb_map_t& axes_index_map,
+ const hb_map_t& axes_old_index_tag_map)
+ {
+ // compile points set and store data in hashmap
+ if (!compile_all_point_sets ())
+ return false;
+ // compile delta and tuple var header for each tuple variation
+ for (auto& tuple: tuple_vars)
+ {
+ const hb_vector_t<bool>* points_set = &(tuple.indices);
+ hb_bytes_t *points_data;
+ if (unlikely (!point_data_map.has (points_set, &points_data)))
+ return false;
+
+ if (!tuple.compile_deltas ())
+ return false;
+
+ if (!tuple.compile_tuple_var_header (axes_index_map, points_data->length, axes_old_index_tag_map))
+ return false;
+ }
+ return true;
+ }
+
+ bool serialize_var_headers (hb_serialize_context_t *c, unsigned& total_header_len) const
+ {
+ TRACE_SERIALIZE (this);
+ for (const auto& tuple: tuple_vars)
+ {
+ tuple.compiled_tuple_header.as_array ().copy (c);
+ if (c->in_error ()) return_trace (false);
+ total_header_len += tuple.compiled_tuple_header.length;
+ }
+ return_trace (true);
+ }
+
+ bool serialize_var_data (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ for (const auto& tuple: tuple_vars)
+ {
+ const hb_vector_t<bool>* points_set = &(tuple.indices);
+ hb_bytes_t *point_data;
+ if (!point_data_map.has (points_set, &point_data))
+ return_trace (false);
+
+ point_data->copy (c);
+ tuple.compiled_deltas.as_array ().copy (c);
+ if (c->in_error ()) return_trace (false);
+ }
+ return_trace (true);
+ }
+ };
+
struct tuple_iterator_t
{
+ unsigned get_axis_count () const { return axis_count; }
+
void init (hb_bytes_t var_data_bytes_, unsigned int axis_count_, const void *table_base_)
{
var_data_bytes = var_data_bytes_;
@@ -517,13 +1374,6 @@ struct TupleVariationData
hb_vector_t<int> &deltas /* IN/OUT */,
const HBUINT8 *end)
{
- enum packed_delta_flag_t
- {
- DELTAS_ARE_ZERO = 0x80,
- DELTAS_ARE_WORDS = 0x40,
- DELTA_RUN_COUNT_MASK = 0x3F
- };
-
unsigned i = 0;
unsigned count = deltas.length;
while (i < count)
@@ -561,11 +1411,50 @@ struct TupleVariationData
bool has_data () const { return tupleVarCount; }
+ bool decompile_tuple_variations (unsigned point_count,
+ bool is_gvar,
+ tuple_iterator_t iterator,
+ const hb_map_t *axes_old_index_tag_map,
+ const hb_vector_t<unsigned> &shared_indices,
+ const hb_array_t<const F2DOT14> shared_tuples,
+ tuple_variations_t& tuple_variations /* OUT */) const
+ {
+ return tuple_variations.create_from_tuple_var_data (iterator, tupleVarCount,
+ point_count, is_gvar,
+ axes_old_index_tag_map,
+ shared_indices,
+ shared_tuples);
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ bool is_gvar,
+ tuple_variations_t& tuple_variations) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->start_embed (this);
+ if (unlikely (!c->extend_min (out))) return_trace (false);
+
+ if (!c->check_assign (out->tupleVarCount, tuple_variations.get_var_count (),
+ HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
+
+ unsigned total_header_len = 0;
+
+ if (!tuple_variations.serialize_var_headers (c, total_header_len))
+ return_trace (false);
+
+ unsigned data_offset = min_size + total_header_len;
+ if (!is_gvar) data_offset += 4;
+ if (!c->check_assign (out->data, data_offset, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
+
+ return tuple_variations.serialize_var_data (c);
+ }
+
protected:
struct TupleVarCount : HBUINT16
{
bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); }
unsigned int get_count () const { return (*this) & CountMask; }
+ TupleVarCount& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
protected:
enum Flags
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh
index 7fd0f1d79d..fee39eff38 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-cvar-table.hh
@@ -27,6 +27,7 @@
#define HB_OT_VAR_CVAR_TABLE_HH
#include "hb-ot-var-common.hh"
+#include "hb-ot-var-fvar-table.hh"
namespace OT {
@@ -51,6 +52,27 @@ struct cvar
const TupleVariationData* get_tuple_var_data (void) const
{ return &tupleVariationData; }
+ bool decompile_tuple_variations (unsigned axis_count,
+ unsigned point_count,
+ bool is_gvar,
+ const hb_map_t *axes_old_index_tag_map,
+ TupleVariationData::tuple_variations_t& tuple_variations /* OUT */) const
+ {
+ hb_vector_t<unsigned> shared_indices;
+ TupleVariationData::tuple_iterator_t iterator;
+ unsigned var_data_length = tupleVariationData.get_size (axis_count);
+ hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast<const char*> (get_tuple_var_data ()), var_data_length);
+ if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, this,
+ shared_indices, &iterator))
+ return false;
+
+ return tupleVariationData.decompile_tuple_variations (point_count, is_gvar, iterator,
+ axes_old_index_tag_map,
+ shared_indices,
+ hb_array<const F2DOT14> (),
+ tuple_variations);
+ }
+
static bool calculate_cvt_deltas (unsigned axis_count,
hb_array_t<int> coords,
unsigned num_cvt_item,
@@ -104,6 +126,54 @@ struct cvar
return true;
}
+
+ bool serialize (hb_serialize_context_t *c,
+ TupleVariationData::tuple_variations_t& tuple_variations) const
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->embed (version))) return_trace (false);
+
+ return_trace (tupleVariationData.serialize (c, false, tuple_variations));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ if (c->plan->all_axes_pinned)
+ return_trace (false);
+
+ /* subset() for cvar is called by partial instancing only, we always pass
+ * through cvar table in other cases */
+ if (!c->plan->normalized_coords)
+ {
+ unsigned axis_count = c->plan->source->table.fvar->get_axis_count ();
+ unsigned total_size = min_size + tupleVariationData.get_size (axis_count);
+ char *out = c->serializer->allocate_size<char> (total_size);
+ if (unlikely (!out)) return_trace (false);
+
+ hb_memcpy (out, this, total_size);
+ return_trace (true);
+ }
+
+ OT::TupleVariationData::tuple_variations_t tuple_variations;
+ unsigned axis_count = c->plan->axes_old_index_tag_map.get_population ();
+
+ const hb_tag_t cvt = HB_TAG('c','v','t',' ');
+ hb_blob_t *cvt_blob = hb_face_reference_table (c->plan->source, cvt);
+ unsigned point_count = hb_blob_get_length (cvt_blob) / FWORD::static_size;
+ hb_blob_destroy (cvt_blob);
+
+ if (!decompile_tuple_variations (axis_count, point_count, false,
+ &(c->plan->axes_old_index_tag_map),
+ tuple_variations))
+ return_trace (false);
+
+ tuple_variations.instantiate (c->plan->axes_location, c->plan->axes_triple_distances);
+ if (!tuple_variations.compile_bytes (c->plan->axes_index_map, c->plan->axes_old_index_tag_map))
+ return_trace (false);
+
+ return_trace (serialize (c->serializer, tuple_variations));
+ }
static bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan,
const TupleVariationData *tuple_var_data,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
index a384dfa531..4c4957bd71 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
@@ -39,6 +39,24 @@
namespace OT {
+static bool axis_coord_pinned_or_within_axis_range (const hb_array_t<const F16DOT16> coords,
+ unsigned axis_index,
+ Triple axis_limit)
+{
+ float axis_coord = coords[axis_index].to_float ();
+ if (axis_limit.is_point ())
+ {
+ if (axis_limit.minimum != axis_coord)
+ return false;
+ }
+ else
+ {
+ if (axis_coord < axis_limit.minimum ||
+ axis_coord > axis_limit.maximum)
+ return false;
+ }
+ return true;
+}
struct InstanceRecord
{
@@ -47,6 +65,27 @@ struct InstanceRecord
hb_array_t<const F16DOT16> get_coordinates (unsigned int axis_count) const
{ return coordinatesZ.as_array (axis_count); }
+ bool keep_instance (unsigned axis_count,
+ const hb_map_t *axes_index_tag_map,
+ const hb_hashmap_t<hb_tag_t, Triple> *axes_location) const
+ {
+ if (axes_location->is_empty ()) return true;
+ const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count);
+ for (unsigned i = 0 ; i < axis_count; i++)
+ {
+ uint32_t *axis_tag;
+ if (!axes_index_tag_map->has (i, &axis_tag))
+ return false;
+ if (!axes_location->has (*axis_tag))
+ continue;
+
+ Triple axis_limit = axes_location->get (*axis_tag);
+ if (!axis_coord_pinned_or_within_axis_range (coords, i, axis_limit))
+ return false;
+ }
+ return true;
+ }
+
bool subset (hb_subset_context_t *c,
unsigned axis_count,
bool has_postscript_nameid) const
@@ -56,19 +95,22 @@ struct InstanceRecord
if (unlikely (!c->serializer->embed (flags))) return_trace (false);
const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count);
- const hb_hashmap_t<hb_tag_t, float> *axes_location = &c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, Triple> *axes_location = &c->plan->user_axes_location;
for (unsigned i = 0 ; i < axis_count; i++)
{
uint32_t *axis_tag;
+ Triple *axis_limit;
// only keep instances whose coordinates == pinned axis location
- if (!c->plan->axes_old_index_tag_map.has (i, &axis_tag)) continue;
-
- if (axes_location->has (*axis_tag) &&
- fabsf (axes_location->get (*axis_tag) - coords[i].to_float ()) > 0.001f)
- return_trace (false);
-
- if (!c->plan->axes_index_map.has (i))
- continue;
+ if (!c->plan->axes_old_index_tag_map.has (i, &axis_tag)) return_trace (false);
+ if (axes_location->has (*axis_tag, &axis_limit))
+ {
+ if (!axis_coord_pinned_or_within_axis_range (coords, i, *axis_limit))
+ return_trace (false);
+
+ //skip pinned axis
+ if (axis_limit->is_point ())
+ continue;
+ }
if (!c->serializer->embed (coords[i]))
return_trace (false);
@@ -186,6 +228,30 @@ struct AxisRecord
return defaultValue.to_float ();
}
+ TripleDistances get_triple_distances () const
+ {
+ float min, default_, max;
+ get_coordinates (min, default_, max);
+ return TripleDistances (min, default_, max);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ const hb_hashmap_t<hb_tag_t, Triple>& user_axes_location = c->plan->user_axes_location;
+ Triple *axis_limit;
+ if (user_axes_location.has (axisTag, &axis_limit))
+ {
+ out->minValue.set_float (axis_limit->minimum);
+ out->defaultValue.set_float (axis_limit->middle);
+ out->maxValue.set_float (axis_limit->maximum);
+ }
+ return_trace (true);
+ }
+
public:
Tag axisTag; /* Tag identifying the design variation for the axis. */
protected:
@@ -216,7 +282,8 @@ struct fvar
axisSize == 20 && /* Assumed in our code. */
instanceSize >= axisCount * 4 + 4 &&
get_axes ().sanitize (c) &&
- c->check_range (get_instance (0), instanceCount, instanceSize));
+ c->check_range (&StructAfter<InstanceRecord> (get_axes ()),
+ instanceCount, instanceSize));
}
unsigned int get_axis_count () const { return axisCount; }
@@ -314,21 +381,19 @@ struct fvar
return axisCount;
}
- void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ void collect_name_ids (hb_hashmap_t<hb_tag_t, Triple> *user_axes_location,
+ hb_map_t *axes_old_index_tag_map,
hb_set_t *nameids /* IN/OUT */) const
{
if (!has_data ()) return;
- hb_map_t pinned_axes;
auto axis_records = get_axes ();
for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
{
hb_tag_t axis_tag = axis_records[i].get_axis_tag ();
- if (user_axes_location->has (axis_tag))
- {
- pinned_axes.set (i, axis_tag);
+ if (user_axes_location->has (axis_tag) &&
+ user_axes_location->get (axis_tag).is_point ())
continue;
- }
nameids->add (axis_records[i].get_name_id ());
}
@@ -337,16 +402,7 @@ struct fvar
{
const InstanceRecord *instance = get_instance (i);
- if (hb_any (+ hb_enumerate (instance->get_coordinates (axisCount))
- | hb_filter (pinned_axes, hb_first)
- | hb_map ([&] (const hb_pair_t<unsigned, const F16DOT16&>& _)
- {
- hb_tag_t axis_tag = pinned_axes.get (_.first);
- float location = user_axes_location->get (axis_tag);
- if (fabs ((double)location - (double)_.second.to_float ()) > 0.001) return true;
- return false;
- })
- ))
+ if (!instance->keep_instance (axisCount, axes_old_index_tag_map, user_axes_location))
continue;
nameids->add (instance->subfamilyNameID);
@@ -384,21 +440,25 @@ struct fvar
for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
{
if (!c->plan->axes_index_map.has (i)) continue;
- if (unlikely (!c->serializer->embed (axes_records[i])))
+ if (unlikely (!axes_records[i].subset (c)))
return_trace (false);
}
if (!c->serializer->check_assign (out->firstAxis, get_size (), HB_SERIALIZE_ERROR_INT_OVERFLOW))
return_trace (false);
+ unsigned num_retained_instances = 0;
for (unsigned i = 0 ; i < (unsigned)instanceCount; i++)
{
const InstanceRecord *instance = get_instance (i);
auto snap = c->serializer->snapshot ();
if (!instance->subset (c, axisCount, has_postscript_nameid))
c->serializer->revert (snap);
+ else
+ num_retained_instances++;
}
- return_trace (true);
+
+ return_trace (c->serializer->check_assign (out->instanceCount, num_retained_instances, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
public:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh
index ece892e1dd..b5099ac074 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh
@@ -50,13 +50,14 @@ struct contour_point_t
y = x * matrix[1] + y * matrix[3];
x = x_;
}
+ HB_ALWAYS_INLINE
void translate (const contour_point_t &p) { x += p.x; y += p.y; }
- float x = 0.f;
- float y = 0.f;
- uint8_t flag = 0;
- bool is_end_point = false;
+ float x;
+ float y;
+ uint8_t flag;
+ bool is_end_point;
};
struct contour_point_vector_t : hb_vector_t<contour_point_t>
@@ -110,20 +111,20 @@ struct gvar
unsigned int num_glyphs = c->plan->num_output_glyphs ();
out->glyphCountX = hb_min (0xFFFFu, num_glyphs);
+ auto it = hb_iter (c->plan->new_to_old_gid_list);
+ if (it->first == 0 && !(c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+ it++;
unsigned int subset_data_size = 0;
- for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
- gid < num_glyphs;
- gid++)
+ for (auto &_ : it)
{
- hb_codepoint_t old_gid;
- if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue;
+ hb_codepoint_t old_gid = _.second;
subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length;
}
bool long_offset = subset_data_size & ~0xFFFFu;
out->flags = long_offset ? 1 : 0;
- HBUINT8 *subset_offsets = c->serializer->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1));
+ HBUINT8 *subset_offsets = c->serializer->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1), false);
if (!subset_offsets) return_trace (false);
/* shared tuples */
@@ -138,36 +139,61 @@ struct gvar
hb_memcpy (tuples, this+sharedTuples, shared_tuple_size);
}
- char *subset_data = c->serializer->allocate_size<char> (subset_data_size);
+ char *subset_data = c->serializer->allocate_size<char> (subset_data_size, false);
if (!subset_data) return_trace (false);
out->dataZ = subset_data - (char *) out;
+
+ if (long_offset)
+ {
+ ((HBUINT32 *) subset_offsets)[0] = 0;
+ subset_offsets += 4;
+ }
+ else
+ {
+ ((HBUINT16 *) subset_offsets)[0] = 0;
+ subset_offsets += 2;
+ }
unsigned int glyph_offset = 0;
- for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
- gid < num_glyphs;
- gid++)
+
+ hb_codepoint_t last = 0;
+ it = hb_iter (c->plan->new_to_old_gid_list);
+ if (it->first == 0 && !(c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+ it++;
+ for (auto &_ : it)
{
- hb_codepoint_t old_gid;
- hb_bytes_t var_data_bytes = c->plan->old_gid_for_new_gid (gid, &old_gid)
- ? get_glyph_var_data_bytes (c->source_blob,
+ hb_codepoint_t gid = _.first;
+ hb_codepoint_t old_gid = _.second;
+
+ if (long_offset)
+ for (; last < gid; last++)
+ ((HBUINT32 *) subset_offsets)[last] = glyph_offset;
+ else
+ for (; last < gid; last++)
+ ((HBUINT16 *) subset_offsets)[last] = glyph_offset / 2;
+
+ hb_bytes_t var_data_bytes = get_glyph_var_data_bytes (c->source_blob,
glyph_count,
- old_gid)
- : hb_bytes_t ();
+ old_gid);
+
+ hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
+ subset_data += var_data_bytes.length;
+ glyph_offset += var_data_bytes.length;
if (long_offset)
((HBUINT32 *) subset_offsets)[gid] = glyph_offset;
else
((HBUINT16 *) subset_offsets)[gid] = glyph_offset / 2;
- if (var_data_bytes.length > 0)
- hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
- subset_data += var_data_bytes.length;
- glyph_offset += var_data_bytes.length;
+ last++; // Skip over gid
}
+
if (long_offset)
- ((HBUINT32 *) subset_offsets)[num_glyphs] = glyph_offset;
+ for (; last < num_glyphs; last++)
+ ((HBUINT32 *) subset_offsets)[last] = glyph_offset;
else
- ((HBUINT16 *) subset_offsets)[num_glyphs] = glyph_offset / 2;
+ for (; last < num_glyphs; last++)
+ ((HBUINT16 *) subset_offsets)[last] = glyph_offset / 2;
return_trace (true);
}
@@ -216,21 +242,24 @@ struct gvar
for (unsigned i = 0; i < count; i++)
{
hb_array_t<const F2DOT14> tuple = shared_tuples.sub_array (axis_count * i, axis_count);
- int idx = -1;
+ int idx1 = -1, idx2 = -1;
for (unsigned j = 0; j < axis_count; j++)
{
const F2DOT14 &peak = tuple.arrayZ[j];
if (peak.to_int () != 0)
{
- if (idx != -1)
+ if (idx1 == -1)
+ idx1 = j;
+ else if (idx2 == -1)
+ idx2 = j;
+ else
{
- idx = -1;
+ idx1 = idx2 = -1;
break;
}
- idx = j;
}
}
- shared_tuple_active_idx.arrayZ[i] = idx;
+ shared_tuple_active_idx.arrayZ[i] = {idx1, idx2};
}
}
~accelerator_t () { table.destroy (); }
@@ -266,10 +295,9 @@ struct gvar
public:
bool apply_deltas_to_points (hb_codepoint_t glyph,
hb_array_t<int> coords,
- const hb_array_t<contour_point_t> points) const
+ const hb_array_t<contour_point_t> points,
+ bool phantom_only = false) const
{
- if (!coords) return true;
-
if (unlikely (glyph >= glyphCount)) return true;
hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyphCount, glyph);
@@ -297,6 +325,7 @@ struct gvar
hb_vector_t<unsigned int> private_indices;
hb_vector_t<int> x_deltas;
hb_vector_t<int> y_deltas;
+ unsigned count = points.length;
bool flush = false;
do
{
@@ -310,9 +339,10 @@ struct gvar
if (!deltas)
{
- if (unlikely (!deltas_vec.resize (points.length, false))) return false;
+ if (unlikely (!deltas_vec.resize (count, false))) return false;
deltas = deltas_vec.as_array ();
- hb_memset (deltas.arrayZ, 0, deltas.get_size ()); // Faster than vector resize
+ hb_memset (deltas.arrayZ + (phantom_only ? count - 4 : 0), 0,
+ (phantom_only ? 4 : count) * sizeof (deltas[0]));
}
const HBUINT8 *end = p + length;
@@ -332,7 +362,7 @@ struct gvar
if (!apply_to_all)
{
- if (!orig_points)
+ if (!orig_points && !phantom_only)
{
orig_points_vec.extend (points);
if (unlikely (orig_points_vec.in_error ())) return false;
@@ -341,13 +371,13 @@ struct gvar
if (flush)
{
- unsigned count = points.length;
- for (unsigned int i = 0; i < count; i++)
+ for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
points.arrayZ[i].translate (deltas.arrayZ[i]);
flush = false;
}
- hb_memset (deltas.arrayZ, 0, deltas.get_size ());
+ hb_memset (deltas.arrayZ + (phantom_only ? count - 4 : 0), 0,
+ (phantom_only ? 4 : count) * sizeof (deltas[0]));
}
if (HB_OPTIMIZE_SIZE_VAL)
@@ -362,6 +392,7 @@ struct gvar
pt_index = indices[i];
if (unlikely (pt_index >= deltas.length)) continue;
}
+ if (phantom_only && pt_index < count - 4) continue;
auto &delta = deltas.arrayZ[pt_index];
delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
delta.x += x_deltas.arrayZ[i] * scalar;
@@ -374,7 +405,7 @@ struct gvar
if (scalar != 1.0f)
{
if (apply_to_all)
- for (unsigned int i = 0; i < num_deltas; i++)
+ for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
{
unsigned int pt_index = i;
auto &delta = deltas.arrayZ[pt_index];
@@ -386,6 +417,7 @@ struct gvar
{
unsigned int pt_index = indices[i];
if (unlikely (pt_index >= deltas.length)) continue;
+ if (phantom_only && pt_index < count - 4) continue;
auto &delta = deltas.arrayZ[pt_index];
delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
delta.x += x_deltas.arrayZ[i] * scalar;
@@ -395,7 +427,7 @@ struct gvar
else
{
if (apply_to_all)
- for (unsigned int i = 0; i < num_deltas; i++)
+ for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
{
unsigned int pt_index = i;
auto &delta = deltas.arrayZ[pt_index];
@@ -407,6 +439,7 @@ struct gvar
{
unsigned int pt_index = indices[i];
if (unlikely (pt_index >= deltas.length)) continue;
+ if (phantom_only && pt_index < count - 4) continue;
auto &delta = deltas.arrayZ[pt_index];
delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
delta.x += x_deltas.arrayZ[i];
@@ -416,11 +449,10 @@ struct gvar
}
/* infer deltas for unreferenced points */
- if (!apply_to_all)
+ if (!apply_to_all && !phantom_only)
{
if (!end_points)
{
- unsigned count = points.length;
for (unsigned i = 0; i < count; ++i)
if (points.arrayZ[i].is_end_point)
end_points.push (i);
@@ -482,8 +514,7 @@ struct gvar
if (flush)
{
- unsigned count = points.length;
- for (unsigned int i = 0; i < count; i++)
+ for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
points.arrayZ[i].translate (deltas.arrayZ[i]);
}
@@ -495,7 +526,7 @@ struct gvar
private:
hb_blob_ptr_t<gvar> table;
unsigned glyphCount;
- hb_vector_t<signed> shared_tuple_active_idx;
+ hb_vector_t<hb_pair_t<int, int>> shared_tuple_active_idx;
};
protected:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
index 461b2b9cdb..490f883fcc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
@@ -45,7 +45,8 @@ struct index_map_subset_plan_t
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)
+ const hb_subset_plan_t *plan,
+ bool bypass_empty = true)
{
map_count = 0;
outer_bit_count = 0;
@@ -53,55 +54,51 @@ struct index_map_subset_plan_t
max_inners.init ();
output_map.init ();
- if (&index_map == &Null (DeltaSetIndexMap)) return;
+ if (bypass_empty && !index_map.get_map_count ()) return;
unsigned int last_val = (unsigned int)-1;
- hb_codepoint_t last_gid = (hb_codepoint_t)-1;
- hb_codepoint_t gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ());
+ hb_codepoint_t last_gid = HB_CODEPOINT_INVALID;
outer_bit_count = (index_map.get_width () * 8) - index_map.get_inner_bit_count ();
max_inners.resize (inner_sets.length);
for (unsigned i = 0; i < inner_sets.length; i++) max_inners[i] = 0;
/* Search backwards for a map value different from the last map value */
- for (; gid > 0; gid--)
+ auto &new_to_old_gid_list = plan->new_to_old_gid_list;
+ unsigned count = new_to_old_gid_list.length;
+ for (unsigned j = count; j; j--)
{
- hb_codepoint_t old_gid;
- if (!plan->old_gid_for_new_gid (gid - 1, &old_gid))
- {
- if (last_gid == (hb_codepoint_t) -1)
- continue;
- else
- break;
- }
+ hb_codepoint_t gid = new_to_old_gid_list.arrayZ[j - 1].first;
+ hb_codepoint_t old_gid = new_to_old_gid_list.arrayZ[j - 1].second;
unsigned int v = index_map.map (old_gid);
- if (last_gid == (hb_codepoint_t) -1)
+ if (last_gid == HB_CODEPOINT_INVALID)
{
last_val = v;
last_gid = gid;
continue;
}
- if (v != last_val) break;
+ 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++)
+ map_count = last_gid + 1;
+ for (auto _ : plan->new_to_old_gid_list)
{
- hb_codepoint_t old_gid;
- if (plan->old_gid_for_new_gid (gid, &old_gid))
- {
- unsigned int v = index_map.map (old_gid);
- unsigned int outer = v >> 16;
- unsigned int inner = v & 0xFFFF;
- outer_map.add (outer);
- if (inner > max_inners[outer]) max_inners[outer] = inner;
- if (outer >= inner_sets.length) return;
- inner_sets[outer]->add (inner);
- }
+ hb_codepoint_t gid = _.first;
+ if (gid >= map_count) break;
+
+ hb_codepoint_t old_gid = _.second;
+ unsigned int v = index_map.map (old_gid);
+ unsigned int outer = v >> 16;
+ unsigned int inner = v & 0xFFFF;
+ outer_map.add (outer);
+ if (inner > max_inners[outer]) max_inners[outer] = inner;
+ if (outer >= inner_sets.length) return;
+ inner_sets[outer]->add (inner);
}
}
@@ -116,8 +113,6 @@ struct index_map_subset_plan_t
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;
@@ -125,18 +120,17 @@ struct index_map_subset_plan_t
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++)
+ if (unlikely (!output_map.resize (map_count))) return;
+ for (const auto &_ : plan->new_to_old_gid_list)
{
- hb_codepoint_t old_gid;
- if (plan->old_gid_for_new_gid (gid, &old_gid))
- {
- uint32_t v = input_map->map (old_gid);
- unsigned int outer = v >> 16;
- output_map[gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]);
- }
- else
- output_map[gid] = 0; /* Map unused glyph to outer/inner=0/0 */
+ hb_codepoint_t new_gid = _.first;
+ hb_codepoint_t old_gid = _.second;
+
+ if (unlikely (new_gid >= map_count)) break;
+
+ uint32_t v = input_map->map (old_gid);
+ unsigned int outer = v >> 16;
+ output_map.arrayZ[new_gid] = (outer_map[outer] << 16) | (inner_maps[outer][v & 0xFFFF]);
}
}
@@ -180,7 +174,7 @@ struct hvarvvar_subset_plan_t
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);
+ index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan, false);
if (index_maps[0] == &Null (DeltaSetIndexMap))
{
retain_adv_map = plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS;
@@ -197,12 +191,10 @@ struct hvarvvar_subset_plan_t
if (retain_adv_map)
{
- for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
+ for (const auto &_ : plan->new_to_old_gid_list)
{
- if (inner_sets[0]->has (gid))
- inner_maps[0].add (gid);
- else
- inner_maps[0].skip ();
+ hb_codepoint_t old_gid = _.second;
+ inner_maps[0].add (old_gid);
}
}
else
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh
index 811e13919e..671b6d2c29 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh
@@ -90,7 +90,7 @@ struct VORG
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- VORG *vorg_prime = c->serializer->start_embed<VORG> ();
+ auto *vorg_prime = c->serializer->start_embed<VORG> ();
if (unlikely (!c->serializer->check_success (vorg_prime))) return_trace (false);
auto it =
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-pool.hh b/src/3rdparty/harfbuzz-ng/src/hb-pool.hh
index d6eb778f5d..fcf10666b0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-pool.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-pool.hh
@@ -58,7 +58,7 @@ struct hb_pool_t
if (unlikely (!next))
{
if (unlikely (!chunks.alloc (chunks.length + 1))) return nullptr;
- chunk_t *chunk = (chunk_t *) hb_calloc (1, sizeof (chunk_t));
+ chunk_t *chunk = (chunk_t *) hb_malloc (sizeof (chunk_t));
if (unlikely (!chunk)) return nullptr;
chunks.push (chunk);
next = chunk->thread ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh b/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh
index bf1b282d3d..baac7e1e69 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh
@@ -54,6 +54,9 @@ struct hb_priority_queue_t
bool in_error () const { return heap.in_error (); }
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
void insert (int64_t priority, unsigned value)
{
heap.push (item_t (priority, value));
@@ -61,6 +64,9 @@ struct hb_priority_queue_t
bubble_up (heap.length - 1);
}
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
item_t pop_minimum ()
{
assert (!is_empty ());
@@ -106,8 +112,10 @@ struct hb_priority_queue_t
return 2 * index + 2;
}
+ HB_ALWAYS_INLINE
void bubble_down (unsigned index)
{
+ repeat:
assert (index < heap.length);
unsigned left = left_child (index);
@@ -123,19 +131,21 @@ struct hb_priority_queue_t
&& (!has_right || heap.arrayZ[index].first <= heap.arrayZ[right].first))
return;
+ unsigned child;
if (!has_right || heap.arrayZ[left].first < heap.arrayZ[right].first)
- {
- swap (index, left);
- bubble_down (left);
- return;
- }
+ child = left;
+ else
+ child = right;
- swap (index, right);
- bubble_down (right);
+ swap (index, child);
+ index = child;
+ goto repeat;
}
+ HB_ALWAYS_INLINE
void bubble_up (unsigned index)
{
+ repeat:
assert (index < heap.length);
if (index == 0) return;
@@ -145,7 +155,8 @@ struct hb_priority_queue_t
return;
swap (index, parent_index);
- bubble_up (parent_index);
+ index = parent_index;
+ goto repeat;
}
void swap (unsigned a, unsigned b)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
index 5259891b7e..efb5adde5f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
@@ -122,12 +122,14 @@ struct hb_sanitize_context_t :
{
hb_sanitize_context_t () :
start (nullptr), end (nullptr),
+ length (0),
max_ops (0), max_subtables (0),
recursion_depth (0),
writable (false), edit_count (0),
blob (nullptr),
num_glyphs (65536),
- num_glyphs_set (false) {}
+ num_glyphs_set (false),
+ lazy_some_gpos (false) {}
const char *get_name () { return "SANITIZE"; }
template <typename T, typename F>
@@ -155,6 +157,19 @@ struct hb_sanitize_context_t :
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
+ hb_sanitize_context_t (hb_blob_t *b) : hb_sanitize_context_t ()
+ {
+ init (b);
+
+ if (blob)
+ start_processing ();
+ }
+
+ ~hb_sanitize_context_t ()
+ {
+ if (blob)
+ end_processing ();
+ }
void init (hb_blob_t *b)
{
@@ -180,11 +195,15 @@ struct hb_sanitize_context_t :
const char *obj_start = (const char *) obj;
if (unlikely (obj_start < this->start || this->end <= obj_start))
+ {
this->start = this->end = nullptr;
+ this->length = 0;
+ }
else
{
this->start = obj_start;
this->end = obj_start + hb_min (size_t (this->end - obj_start), obj->get_size ());
+ this->length = this->end - this->start;
}
}
@@ -192,6 +211,7 @@ struct hb_sanitize_context_t :
{
this->start = this->blob->data;
this->end = this->start + this->blob->length;
+ this->length = this->end - this->start;
assert (this->start <= this->end); /* Must not overflow. */
}
@@ -224,6 +244,7 @@ struct hb_sanitize_context_t :
hb_blob_destroy (this->blob);
this->blob = nullptr;
this->start = this->end = nullptr;
+ this->length = 0;
}
unsigned get_edit_count () { return edit_count; }
@@ -237,18 +258,20 @@ struct hb_sanitize_context_t :
this->max_ops = -1;
return false;
}
- return (this->max_ops -= (int) count) > 0;
+ this->max_ops -= (int) count;
+ return true;
}
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool check_range (const void *base,
unsigned int len) const
{
const char *p = (const char *) base;
- bool ok = !len ||
- (this->start <= p &&
- p <= this->end &&
- (unsigned int) (this->end - p) >= len &&
- (this->max_ops -= len) > 0);
+ bool ok = (uintptr_t) (p - this->start) <= this->length &&
+ (unsigned int) (this->end - p) >= len &&
+ ((this->max_ops -= len) > 0);
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"check_range [%p..%p]"
@@ -259,6 +282,43 @@ struct hb_sanitize_context_t :
return likely (ok);
}
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
+ bool check_range_fast (const void *base,
+ unsigned int len) const
+ {
+ const char *p = (const char *) base;
+ bool ok = ((uintptr_t) (p - this->start) <= this->length &&
+ (unsigned int) (this->end - p) >= len);
+
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+ "check_range_fast [%p..%p]"
+ " (%u bytes) in [%p..%p] -> %s",
+ p, p + len, len,
+ this->start, this->end,
+ ok ? "OK" : "OUT-OF-RANGE");
+
+ return likely (ok);
+ }
+
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
+ bool check_point (const void *base) const
+ {
+ const char *p = (const char *) base;
+ bool ok = (uintptr_t) (p - this->start) <= this->length;
+
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+ "check_point [%p]"
+ " in [%p..%p] -> %s",
+ p,
+ this->start, this->end,
+ ok ? "OK" : "OUT-OF-RANGE");
+
+ return likely (ok);
+ }
template <typename T>
bool check_range (const T *base,
@@ -282,6 +342,20 @@ struct hb_sanitize_context_t :
}
template <typename T>
+ HB_ALWAYS_INLINE
+ bool check_array_sized (const T *base, unsigned int len, unsigned len_size) const
+ {
+ if (len_size >= 4)
+ {
+ if (unlikely (hb_unsigned_mul_overflows (len, hb_static_size (T), &len)))
+ return false;
+ }
+ else
+ len = len * hb_static_size (T);
+ return this->check_range (base, len);
+ }
+
+ template <typename T>
bool check_array (const T *base, unsigned int len) const
{
return this->check_range (base, len, hb_static_size (T));
@@ -292,7 +366,7 @@ struct hb_sanitize_context_t :
unsigned int a,
unsigned int b) const
{
- return this->check_range (base, a, b, hb_static_size (T));
+ return this->check_range (base, hb_static_size (T), a, b);
}
bool check_start_recursion (int max_depth)
@@ -308,8 +382,16 @@ struct hb_sanitize_context_t :
}
template <typename Type>
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool check_struct (const Type *obj) const
- { return likely (this->check_range (obj, obj->min_size)); }
+ {
+ if (sizeof (uintptr_t) == sizeof (uint32_t))
+ return likely (this->check_range_fast (obj, obj->min_size));
+ else
+ return likely (this->check_point ((const char *) obj + obj->min_size));
+ }
bool may_edit (const void *base, unsigned int len)
{
@@ -416,6 +498,7 @@ struct hb_sanitize_context_t :
}
const char *start, *end;
+ unsigned length;
mutable int max_ops, max_subtables;
private:
int recursion_depth;
@@ -424,6 +507,8 @@ struct hb_sanitize_context_t :
hb_blob_t *blob;
unsigned int num_glyphs;
bool num_glyphs_set;
+ public:
+ bool lazy_some_gpos;
};
struct hb_sanitize_with_object_t
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh b/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
index 61ec0253a0..15eccb6a09 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
@@ -113,7 +113,7 @@ struct hb_serialize_context_t
{
// Virtual links aren't considered for equality since they don't affect the functionality
// of the object.
- return hb_bytes_t (head, tail - head).hash () ^
+ return hb_bytes_t (head, hb_min (128, tail - head)).hash () ^
real_links.as_bytes ().hash ();
}
@@ -172,8 +172,14 @@ struct hb_serialize_context_t
};
snapshot_t snapshot ()
- { return snapshot_t {
- head, tail, current, current->real_links.length, current->virtual_links.length, errors }; }
+ {
+ return snapshot_t {
+ head, tail, current,
+ current ? current->real_links.length : 0,
+ current ? current->virtual_links.length : 0,
+ errors
+ };
+ }
hb_serialize_context_t (void *start_, unsigned int size) :
start ((char *) start_),
@@ -260,7 +266,8 @@ struct hb_serialize_context_t
propagate_error (std::forward<Ts> (os)...); }
/* To be called around main operation. */
- template <typename Type>
+ template <typename Type=char>
+ __attribute__((returns_nonnull))
Type *start_serialize ()
{
DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
@@ -303,6 +310,7 @@ struct hb_serialize_context_t
}
template <typename Type = void>
+ __attribute__((returns_nonnull))
Type *push ()
{
if (unlikely (in_error ())) return start_embed<Type> ();
@@ -323,6 +331,8 @@ struct hb_serialize_context_t
{
object_t *obj = current;
if (unlikely (!obj)) return;
+ // Allow cleanup when we've error'd out on int overflows which don't compromise
+ // the serializer state.
if (unlikely (in_error() && !only_overflow ())) return;
current = current->next;
@@ -340,7 +350,9 @@ struct hb_serialize_context_t
{
object_t *obj = current;
if (unlikely (!obj)) return 0;
- if (unlikely (in_error())) return 0;
+ // Allow cleanup when we've error'd out on int overflows which don't compromise
+ // the serializer state.
+ if (unlikely (in_error() && !only_overflow ())) return 0;
current = current->next;
obj->tail = head;
@@ -405,8 +417,11 @@ struct hb_serialize_context_t
// Overflows that happened after the snapshot will be erased by the revert.
if (unlikely (in_error () && !only_overflow ())) return;
assert (snap.current == current);
- current->real_links.shrink (snap.num_real_links);
- current->virtual_links.shrink (snap.num_virtual_links);
+ if (current)
+ {
+ current->real_links.shrink (snap.num_real_links);
+ current->virtual_links.shrink (snap.num_virtual_links);
+ }
errors = snap.errors;
revert (snap.head, snap.tail);
}
@@ -563,13 +578,15 @@ struct hb_serialize_context_t
{
unsigned int l = length () % alignment;
if (l)
- allocate_size<void> (alignment - l);
+ (void) allocate_size<void> (alignment - l);
}
template <typename Type = void>
+ __attribute__((returns_nonnull))
Type *start_embed (const Type *obj HB_UNUSED = nullptr) const
{ return reinterpret_cast<Type *> (this->head); }
template <typename Type>
+ __attribute__((returns_nonnull))
Type *start_embed (const Type &obj) const
{ return start_embed (std::addressof (obj)); }
@@ -597,6 +614,7 @@ struct hb_serialize_context_t
}
template <typename Type>
+ HB_NODISCARD
Type *allocate_size (size_t size, bool clear = true)
{
if (unlikely (in_error ())) return nullptr;
@@ -618,6 +636,7 @@ struct hb_serialize_context_t
{ return this->allocate_size<Type> (Type::min_size); }
template <typename Type>
+ HB_NODISCARD
Type *embed (const Type *obj)
{
unsigned int size = obj->get_size ();
@@ -627,6 +646,7 @@ struct hb_serialize_context_t
return ret;
}
template <typename Type>
+ HB_NODISCARD
Type *embed (const Type &obj)
{ return embed (std::addressof (obj)); }
char *embed (const char *obj, unsigned size)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh
index dab713729b..5681641baa 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh
@@ -88,14 +88,19 @@ struct hb_set_digest_bits_pattern_t
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
{
+ if (mask == (mask_t) -1) return false;
if ((b >> shift) - (a >> shift) >= mask_bits - 1)
+ {
mask = (mask_t) -1;
- else {
+ return false;
+ }
+ else
+ {
mask_t ma = mask_for (a);
mask_t mb = mask_for (b);
mask |= mb + (mb - ma) - (mb < ma);
+ return true;
}
- return true;
}
template <typename T>
@@ -154,8 +159,7 @@ struct hb_set_digest_combiner_t
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
{
- return head.add_range (a, b) &&
- tail.add_range (a, b);
+ return (int) head.add_range (a, b) | (int) tail.add_range (a, b);
}
template <typename T>
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.h b/src/3rdparty/harfbuzz-ng/src/hb-set.h
index de53231030..192abf6f63 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.h
@@ -43,7 +43,7 @@ HB_BEGIN_DECLS
*
* Since: 0.9.21
*/
-#define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1)
+#define HB_SET_VALUE_INVALID HB_CODEPOINT_INVALID
/**
* hb_set_t:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-set.hh
index 604802381b..7d1c941e4d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.hh
@@ -115,7 +115,7 @@ struct hb_sparseset_t
/* Sink interface. */
hb_sparseset_t& operator << (hb_codepoint_t v)
{ add (v); return *this; }
- hb_sparseset_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+ hb_sparseset_t& operator << (const hb_codepoint_pair_t& range)
{ add_range (range.first, range.second); return *this; }
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
@@ -174,7 +174,7 @@ struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t>
hb_set_t& operator << (hb_codepoint_t v)
{ sparseset::operator<< (v); return *this; }
- hb_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+ hb_set_t& operator << (const hb_codepoint_pair_t& range)
{ sparseset::operator<< (range); return *this; }
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
index d9598fc704..844f7b9e80 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
@@ -220,7 +220,7 @@ reset_buffer (hb_buffer_t *buffer,
assert (buffer->ensure (text.length));
buffer->have_positions = false;
buffer->len = text.length;
- memcpy (buffer->info, text.arrayZ, text.length * sizeof (buffer->info[0]));
+ hb_memcpy (buffer->info, text.arrayZ, text.length * sizeof (buffer->info[0]));
hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh b/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh
index 4158b7094c..f079caf4d3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh
@@ -33,6 +33,11 @@
/* v--- Add new shapers in the right place here. */
+#ifdef HAVE_WASM
+/* Only picks up fonts that have a "Wasm" table. */
+HB_SHAPER_IMPLEMENT (wasm)
+#endif
+
#ifdef HAVE_GRAPHITE2
/* Only picks up fonts that have a "Silf" table. */
HB_SHAPER_IMPLEMENT (graphite2)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-static.cc b/src/3rdparty/harfbuzz-ng/src/hb-static.cc
index a1a2522edf..c9bd0a61bf 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-static.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-static.cc
@@ -31,6 +31,7 @@
#include "hb-aat-layout-common.hh"
#include "hb-aat-layout-feat-table.hh"
+#include "hb-cff-interp-common.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-cmap-table.hh"
#include "OT/Color/COLR/COLR.hh"
@@ -58,6 +59,8 @@ DEFINE_NULL_NAMESPACE_BYTES (AAT, Lookup) = {0xFF,0xFF};
/* hb_map_t */
const hb_codepoint_t minus_1 = -1;
+static const unsigned char static_endchar_str[] = {OpCode_endchar};
+const unsigned char *endchar_str = static_endchar_str;
/* hb_face_t */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh
index bb7c62d064..9258383d28 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh
@@ -42,7 +42,9 @@ struct cff_subset_accelerator_t;
namespace OT {
struct SubtableUnicodesCache;
-};
+struct cff1_subset_accelerator_t;
+struct cff2_subset_accelerator_t;
+}
struct hb_subset_accelerator_t
{
@@ -51,8 +53,8 @@ struct hb_subset_accelerator_t
return &_hb_subset_accelerator_user_data_key;
}
- static hb_subset_accelerator_t* create(const hb_map_t& unicode_to_gid_,
- const hb_multimap_t gid_to_unicodes_,
+ static hb_subset_accelerator_t* create(hb_face_t *source,
+ const hb_map_t& unicode_to_gid_,
const hb_set_t& unicodes_,
bool has_seac_) {
hb_subset_accelerator_t* accel =
@@ -60,8 +62,8 @@ struct hb_subset_accelerator_t
if (unlikely (!accel)) return accel;
- new (accel) hb_subset_accelerator_t (unicode_to_gid_,
- gid_to_unicodes_,
+ new (accel) hb_subset_accelerator_t (source,
+ unicode_to_gid_,
unicodes_,
has_seac_);
@@ -79,36 +81,36 @@ struct hb_subset_accelerator_t
hb_free (accel);
}
- hb_subset_accelerator_t (const hb_map_t& unicode_to_gid_,
- const hb_multimap_t& gid_to_unicodes_,
+ hb_subset_accelerator_t (hb_face_t *source,
+ const hb_map_t& unicode_to_gid_,
const hb_set_t& unicodes_,
bool has_seac_) :
unicode_to_gid(unicode_to_gid_),
- gid_to_unicodes (gid_to_unicodes_),
unicodes(unicodes_),
cmap_cache(nullptr),
destroy_cmap_cache(nullptr),
has_seac(has_seac_),
- cff_accelerator(nullptr),
- destroy_cff_accelerator(nullptr) {}
-
- ~hb_subset_accelerator_t ()
+ source(hb_face_reference (source))
{
- if (cff_accelerator && destroy_cff_accelerator)
- destroy_cff_accelerator ((void*) cff_accelerator);
-
- if (cmap_cache && destroy_cmap_cache)
- destroy_cmap_cache ((void*) cmap_cache);
+ gid_to_unicodes.alloc (unicode_to_gid.get_population ());
+ for (const auto &_ : unicode_to_gid)
+ {
+ auto unicode = _.first;
+ auto gid = _.second;
+ gid_to_unicodes.add (gid, unicode);
+ }
}
+ HB_INTERNAL ~hb_subset_accelerator_t ();
+
// Generic
mutable hb_mutex_t sanitized_table_cache_lock;
mutable hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>> sanitized_table_cache;
- const hb_map_t unicode_to_gid;
- const hb_multimap_t gid_to_unicodes;
- const hb_set_t unicodes;
+ hb_map_t unicode_to_gid;
+ hb_multimap_t gid_to_unicodes;
+ hb_set_t unicodes;
// cmap
const OT::SubtableUnicodesCache* cmap_cache;
@@ -116,8 +118,6 @@ struct hb_subset_accelerator_t
// CFF
bool has_seac;
- const CFF::cff_subset_accelerator_t* cff_accelerator;
- hb_destroy_func_t destroy_cff_accelerator;
// TODO(garretrieger): cumulative glyf checksum map
@@ -128,6 +128,13 @@ struct hb_subset_accelerator_t
unicodes.in_error () ||
sanitized_table_cache.in_error ();
}
+
+ hb_face_t *source;
+#ifndef HB_NO_SUBSET_CFF
+ // These have to be immediately after source:
+ mutable hb_face_lazy_loader_t<OT::cff1_subset_accelerator_t, 1> cff1_accel;
+ mutable hb_face_lazy_loader_t<OT::cff2_subset_accelerator_t, 2> cff2_accel;
+#endif
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc
index 6e1b6f713d..5e4ea5fe7c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc
@@ -68,24 +68,35 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
/* use hb_set to determine the subset of font dicts */
hb_set_t set;
hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
- for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
+ hb_pair_t<unsigned, hb_codepoint_t> last_range {0, 0};
+ auto it = hb_iter (plan->new_to_old_gid_list);
+ auto _ = *it;
+ for (hb_codepoint_t gid = 0; gid < subset_num_glyphs; gid++)
{
- hb_codepoint_t glyph;
- hb_codepoint_t fd;
- if (!plan->old_gid_for_new_gid (i, &glyph))
+ hb_codepoint_t old_glyph;
+ if (gid == _.first)
+ {
+ old_glyph = _.second;
+ _ = *++it;
+ }
+ else
{
/* fonttools retains FDSelect & font dicts for missing glyphs. do the same */
- glyph = i;
+ old_glyph = gid;
}
- fd = src.get_fd (glyph);
- set.add (fd);
+ if (old_glyph >= last_range.second)
+ last_range = src.get_fd_range (old_glyph);
+ unsigned fd = last_range.first;
if (fd != prev_fd)
{
+ set.add (fd);
num_ranges++;
prev_fd = fd;
- code_pair_t pair = { fd, i };
- fdselect_ranges.push (pair);
+ fdselect_ranges.push (code_pair_t { fd, gid });
+
+ if (gid == old_glyph)
+ gid = hb_min (_.first - 1, last_range.second - 1);
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
index ff50b0e518..462e99cf8c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
@@ -480,6 +480,7 @@ struct cff_subset_accelerator_t
const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs) {
cff_subset_accelerator_t* accel =
(cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t));
+ if (unlikely (!accel)) return nullptr;
new (accel) cff_subset_accelerator_t (original_blob,
parsed_charstrings,
parsed_global_subrs,
@@ -510,15 +511,21 @@ struct cff_subset_accelerator_t
original_blob = hb_blob_reference (original_blob_);
}
- ~cff_subset_accelerator_t() {
+ ~cff_subset_accelerator_t()
+ {
hb_blob_destroy (original_blob);
- hb_map_destroy (glyph_to_sid_map.get_relaxed ());
+ auto *mapping = glyph_to_sid_map.get_relaxed ();
+ if (mapping)
+ {
+ mapping->~glyph_to_sid_map_t ();
+ hb_free (mapping);
+ }
}
parsed_cs_str_vec_t parsed_charstrings;
parsed_cs_str_vec_t parsed_global_subrs;
hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
- mutable hb_atomic_ptr_t<hb_map_t> glyph_to_sid_map = nullptr;
+ mutable hb_atomic_ptr_t<glyph_to_sid_map_t> glyph_to_sid_map;
private:
hb_blob_t* original_blob;
@@ -600,9 +607,8 @@ struct subr_remap_t : hb_inc_bimap_t
* no optimization based on usage counts. fonttools doesn't appear doing that either.
*/
- resize (closure->get_population ());
- hb_codepoint_t old_num = HB_SET_VALUE_INVALID;
- while (hb_set_next (closure, &old_num))
+ alloc (closure->get_population ());
+ for (auto old_num : *closure)
add (old_num);
if (get_population () < 1240)
@@ -672,8 +678,8 @@ struct subr_subsetter_t
{
unsigned fd_count = acc.fdCount;
const cff_subset_accelerator_t* cff_accelerator = nullptr;
- if (plan->accelerator && plan->accelerator->cff_accelerator) {
- cff_accelerator = plan->accelerator->cff_accelerator;
+ if (acc.cff_accelerator) {
+ cff_accelerator = acc.cff_accelerator;
fd_count = cff_accelerator->parsed_local_subrs.length;
}
@@ -709,14 +715,13 @@ struct subr_subsetter_t
}
/* phase 1 & 2 */
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+ for (auto _ : plan->new_to_old_gid_list)
{
- hb_codepoint_t glyph;
- if (!plan->old_gid_for_new_gid (i, &glyph))
- continue;
+ hb_codepoint_t new_glyph = _.first;
+ hb_codepoint_t old_glyph = _.second;
- const hb_ubytes_t str = (*acc.charStrings)[glyph];
- unsigned int fd = acc.fdSelect->get_fd (glyph);
+ const hb_ubytes_t str = (*acc.charStrings)[old_glyph];
+ unsigned int fd = acc.fdSelect->get_fd (old_glyph);
if (unlikely (fd >= acc.fdCount))
return false;
@@ -725,9 +730,9 @@ struct subr_subsetter_t
// parsed string already exists in accelerator, copy it and move
// on.
if (cached_charstrings)
- cached_charstrings[i] = &cff_accelerator->parsed_charstrings[glyph];
+ cached_charstrings[new_glyph] = &cff_accelerator->parsed_charstrings[old_glyph];
else
- parsed_charstrings[i] = cff_accelerator->parsed_charstrings[glyph];
+ parsed_charstrings[new_glyph] = cff_accelerator->parsed_charstrings[old_glyph];
continue;
}
@@ -735,8 +740,8 @@ struct subr_subsetter_t
ENV env (str, acc, fd);
cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env);
- parsed_charstrings[i].alloc (str.length);
- subr_subset_param_t param (&parsed_charstrings[i],
+ parsed_charstrings[new_glyph].alloc (str.length);
+ subr_subset_param_t param (&parsed_charstrings[new_glyph],
&parsed_global_subrs_storage,
&parsed_local_subrs_storage[fd],
&closures.global_closure,
@@ -747,12 +752,12 @@ struct subr_subsetter_t
return false;
/* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
- SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
+ SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[new_glyph]);
/* mark hint ops and arguments for drop */
if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING) || plan->inprogress_accelerator)
{
- subr_subset_param_t param (&parsed_charstrings[i],
+ subr_subset_param_t param (&parsed_charstrings[new_glyph],
&parsed_global_subrs_storage,
&parsed_local_subrs_storage[fd],
&closures.global_closure,
@@ -760,21 +765,21 @@ struct subr_subsetter_t
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
drop_hints_param_t drop;
- if (drop_hints_in_str (parsed_charstrings[i], param, drop))
+ if (drop_hints_in_str (parsed_charstrings[new_glyph], param, drop))
{
- parsed_charstrings[i].set_hint_dropped ();
+ parsed_charstrings[new_glyph].set_hint_dropped ();
if (drop.vsindex_dropped)
- parsed_charstrings[i].set_vsindex_dropped ();
+ parsed_charstrings[new_glyph].set_vsindex_dropped ();
}
}
- /* Doing this here one by one instead of compacting all at the en
+ /* Doing this here one by one instead of compacting all at the end
* has massive peak-memory saving.
*
* The compacting both saves memory and makes further operations
* faster.
*/
- parsed_charstrings[i].compact ();
+ parsed_charstrings[new_glyph].compact ();
}
/* Since parsed strings were loaded from accelerator, we still need
@@ -797,23 +802,40 @@ struct subr_subsetter_t
bool encode_charstrings (str_buff_vec_t &buffArray, bool encode_prefix = true) const
{
- if (unlikely (!buffArray.resize_exact (plan->num_output_glyphs ())))
+ unsigned num_glyphs = plan->num_output_glyphs ();
+ if (unlikely (!buffArray.resize_exact (num_glyphs)))
return false;
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+ hb_codepoint_t last = 0;
+ for (auto _ : plan->new_to_old_gid_list)
{
- hb_codepoint_t glyph;
- if (!plan->old_gid_for_new_gid (i, &glyph))
- {
- /* add an endchar only charstring for a missing glyph if CFF1 */
- if (endchar_op != OpCode_Invalid) buffArray.arrayZ[i].push (endchar_op);
- continue;
- }
- unsigned int fd = acc.fdSelect->get_fd (glyph);
+ hb_codepoint_t gid = _.first;
+ hb_codepoint_t old_glyph = _.second;
+
+ if (endchar_op != OpCode_Invalid)
+ for (; last < gid; last++)
+ {
+ // Hack to point vector to static string.
+ auto &b = buffArray.arrayZ[last];
+ b.length = 1;
+ b.arrayZ = const_cast<unsigned char *>(endchar_str);
+ }
+
+ last++; // Skip over gid
+ unsigned int fd = acc.fdSelect->get_fd (old_glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- if (unlikely (!encode_str (get_parsed_charstring (i), fd, buffArray.arrayZ[i], encode_prefix)))
+ if (unlikely (!encode_str (get_parsed_charstring (gid), fd, buffArray.arrayZ[gid], encode_prefix)))
return false;
}
+ if (endchar_op != OpCode_Invalid)
+ for (; last < num_glyphs; last++)
+ {
+ // Hack to point vector to static string.
+ auto &b = buffArray.arrayZ[last];
+ b.length = 1;
+ b.arrayZ = const_cast<unsigned char *>(endchar_str);
+ }
+
return true;
}
@@ -980,24 +1002,23 @@ struct subr_subsetter_t
const hb_vector_t<parsed_cs_str_vec_t>& local_subrs)
{
closures.reset ();
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+ for (auto _ : plan->new_to_old_gid_list)
{
- hb_codepoint_t glyph;
- if (!plan->old_gid_for_new_gid (i, &glyph))
- continue;
- unsigned int fd = acc.fdSelect->get_fd (glyph);
+ hb_codepoint_t new_glyph = _.first;
+ hb_codepoint_t old_glyph = _.second;
+ unsigned int fd = acc.fdSelect->get_fd (old_glyph);
if (unlikely (fd >= acc.fdCount))
return false;
// Note: const cast is safe here because the collect_subr_refs_in_str only performs a
// closure and does not modify any of the charstrings.
- subr_subset_param_t param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (i)),
+ subr_subset_param_t param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (new_glyph)),
const_cast<parsed_cs_str_vec_t*> (&global_subrs),
const_cast<parsed_cs_str_vec_t*> (&local_subrs[fd]),
&closures.global_closure,
&closures.local_closures[fd],
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
- collect_subr_refs_in_str (get_parsed_charstring (i), param);
+ collect_subr_refs_in_str (get_parsed_charstring (new_glyph), param);
}
return true;
@@ -1105,14 +1126,11 @@ struct subr_subsetter_t
compact_parsed_subrs ();
- plan->inprogress_accelerator->cff_accelerator =
+ acc.cff_accelerator =
cff_subset_accelerator_t::create(acc.blob,
parsed_charstrings,
parsed_global_subrs_storage,
parsed_local_subrs_storage);
- plan->inprogress_accelerator->destroy_cff_accelerator =
- cff_subset_accelerator_t::destroy;
-
}
const parsed_cs_str_t& get_parsed_charstring (unsigned i) const
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
index 1d7ed6444a..872cba6672 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
@@ -32,36 +32,59 @@
#include "hb-ot-cff1-table.hh"
#include "hb-set.h"
#include "hb-bimap.hh"
-#include "hb-subset-cff1.hh"
#include "hb-subset-plan.hh"
#include "hb-subset-cff-common.hh"
#include "hb-cff1-interp-cs.hh"
using namespace CFF;
-struct remap_sid_t : hb_inc_bimap_t
+struct remap_sid_t
{
+ unsigned get_population () const { return vector.length; }
+
+ void alloc (unsigned size)
+ {
+ map.alloc (size);
+ vector.alloc (size, true);
+ }
+
+ bool in_error () const
+ { return map.in_error () || vector.in_error (); }
+
unsigned int add (unsigned int sid)
{
- if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
- return offset_sid (hb_inc_bimap_t::add (unoffset_sid (sid)));
- else
+ if (is_std_str (sid) || (sid == CFF_UNDEF_SID))
return sid;
+
+ sid = unoffset_sid (sid);
+ unsigned v = next;
+ if (map.set (sid, v, false))
+ {
+ vector.push (sid);
+ next++;
+ }
+ else
+ v = map.get (sid); // already exists
+ return offset_sid (v);
}
unsigned int operator[] (unsigned int sid) const
{
- if (is_std_std (sid) || (sid == CFF_UNDEF_SID))
+ if (is_std_str (sid) || (sid == CFF_UNDEF_SID))
return sid;
- else
- return offset_sid (get (unoffset_sid (sid)));
+
+ return offset_sid (map.get (unoffset_sid (sid)));
}
static const unsigned int num_std_strings = 391;
- static bool is_std_std (unsigned int sid) { return sid < num_std_strings; }
+ static bool is_std_str (unsigned int sid) { return sid < num_std_strings; }
static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
+ unsigned next = 0;
+
+ hb_map_t map;
+ hb_vector_t<unsigned> vector;
};
struct cff1_sub_table_info_t : cff_sub_table_info_t
@@ -271,16 +294,17 @@ struct range_list_t : hb_vector_t<code_pair_t>
/* replace the first glyph ID in the "glyph" field each range with a nLeft value */
bool complete (unsigned int last_glyph)
{
- bool two_byte = false;
+ hb_codepoint_t all_glyphs = 0;
unsigned count = this->length;
for (unsigned int i = count; i; i--)
{
code_pair_t &pair = arrayZ[i - 1];
unsigned int nLeft = last_glyph - pair.glyph - 1;
- two_byte |= nLeft >= 0x100;
+ all_glyphs |= nLeft;
last_glyph = pair.glyph;
pair.glyph = nLeft;
}
+ bool two_byte = all_glyphs >= 0x100;
return two_byte;
}
};
@@ -391,8 +415,10 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs
}
};
-struct cff_subset_plan {
- cff_subset_plan ()
+namespace OT {
+struct cff1_subset_plan
+{
+ cff1_subset_plan ()
{
for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
topDictModSIDs[i] = CFF_UNDEF_SID;
@@ -402,7 +428,7 @@ struct cff_subset_plan {
{
const Encoding *encoding = acc.encoding;
unsigned int size0, size1;
- hb_codepoint_t code, last_code = CFF_UNDEF_CODE;
+ unsigned code, last_code = CFF_UNDEF_CODE - 1;
hb_vector_t<hb_codepoint_t> supp_codes;
if (unlikely (!subset_enc_code_ranges.resize (0)))
@@ -413,39 +439,42 @@ struct cff_subset_plan {
supp_codes.init ();
+ code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
subset_enc_num_codes = plan->num_output_glyphs () - 1;
unsigned int glyph;
- for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
+ auto it = hb_iter (plan->new_to_old_gid_list);
+ if (it->first == 0) it++;
+ auto _ = *it;
+ for (glyph = 1; glyph < num_glyphs; glyph++)
{
- hb_codepoint_t old_glyph;
- if (!plan->old_gid_for_new_gid (glyph, &old_glyph))
+ hb_codepoint_t old_glyph;
+ if (glyph == _.first)
{
- /* Retain the code for the old missing glyph ID */
+ old_glyph = _.second;
+ _ = *++it;
+ }
+ else
+ {
+ /* Retain the SID for the old missing glyph ID */
old_glyph = glyph;
}
- code = acc.glyph_to_code (old_glyph);
+ code = acc.glyph_to_code (old_glyph, &glyph_to_sid_cache);
if (code == CFF_UNDEF_CODE)
{
subset_enc_num_codes = glyph - 1;
break;
}
- if ((last_code == CFF_UNDEF_CODE) || (code != last_code + 1))
- {
- code_pair_t pair = { code, glyph };
- subset_enc_code_ranges.push (pair);
- }
+ if (code != last_code + 1)
+ subset_enc_code_ranges.push (code_pair_t {code, glyph});
last_code = code;
if (encoding != &Null (Encoding))
{
- hb_codepoint_t sid = acc.glyph_to_sid (old_glyph);
+ hb_codepoint_t sid = acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache);
encoding->get_supplement_codes (sid, supp_codes);
for (unsigned int i = 0; i < supp_codes.length; i++)
- {
- code_pair_t pair = { supp_codes[i], sid };
- subset_enc_supp_codes.push (pair);
- }
+ subset_enc_supp_codes.push (code_pair_t {supp_codes[i], sid});
}
}
supp_codes.fini ();
@@ -462,65 +491,93 @@ struct cff_subset_plan {
subset_enc_format = 1;
}
- void plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+ bool plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
{
unsigned int size0, size_ranges;
- hb_codepoint_t sid, last_sid = CFF_UNDEF_CODE;
+ unsigned last_sid = CFF_UNDEF_CODE - 1;
if (unlikely (!subset_charset_ranges.resize (0)))
{
plan->check_success (false);
- return;
+ return false;
+ }
+
+ code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
+
+ unsigned num_glyphs = plan->num_output_glyphs ();
+
+ if (unlikely (!subset_charset_ranges.alloc (hb_min (num_glyphs,
+ acc.num_charset_entries))))
+ {
+ plan->check_success (false);
+ return false;
}
- hb_map_t *glyph_to_sid_map = (plan->accelerator && plan->accelerator->cff_accelerator) ?
- plan->accelerator->cff_accelerator->glyph_to_sid_map :
- nullptr;
+ glyph_to_sid_map_t *glyph_to_sid_map = acc.cff_accelerator ?
+ acc.cff_accelerator->glyph_to_sid_map.get_acquire () :
+ nullptr;
bool created_map = false;
- if (!glyph_to_sid_map &&
- ((plan->accelerator && plan->accelerator->cff_accelerator) ||
- plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.))
+ if (!glyph_to_sid_map && acc.cff_accelerator)
{
created_map = true;
glyph_to_sid_map = acc.create_glyph_to_sid_map ();
}
- unsigned int glyph;
- for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
+ auto it = hb_iter (plan->new_to_old_gid_list);
+ if (it->first == 0) it++;
+ auto _ = *it;
+ bool not_is_cid = !acc.is_CID ();
+ bool skip = !not_is_cid && glyph_to_sid_map;
+ if (not_is_cid)
+ sidmap.alloc (num_glyphs);
+ for (hb_codepoint_t glyph = 1; glyph < num_glyphs; glyph++)
{
- hb_codepoint_t old_glyph;
- if (!plan->old_gid_for_new_gid (glyph, &old_glyph))
+ hb_codepoint_t old_glyph;
+ if (glyph == _.first)
+ {
+ old_glyph = _.second;
+ _ = *++it;
+ }
+ else
{
/* Retain the SID for the old missing glyph ID */
old_glyph = glyph;
}
- sid = glyph_to_sid_map ? glyph_to_sid_map->get (old_glyph) : acc.glyph_to_sid (old_glyph);
+ unsigned sid = glyph_to_sid_map ?
+ glyph_to_sid_map->arrayZ[old_glyph].code :
+ acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache);
- if (!acc.is_CID ())
+ if (not_is_cid)
sid = sidmap.add (sid);
- if ((last_sid == CFF_UNDEF_CODE) || (sid != last_sid + 1))
+ if (sid != last_sid + 1)
+ subset_charset_ranges.push (code_pair_t {sid, glyph});
+
+ if (glyph == old_glyph && skip)
{
- code_pair_t pair = { sid, glyph };
- subset_charset_ranges.push (pair);
+ glyph = hb_min (_.first - 1, glyph_to_sid_map->arrayZ[old_glyph].glyph);
+ sid += glyph - old_glyph;
}
last_sid = sid;
}
if (created_map)
{
- if (!(plan->accelerator && plan->accelerator->cff_accelerator) ||
- !plan->accelerator->cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map))
- hb_map_destroy (glyph_to_sid_map);
+ if ((!plan->accelerator && acc.cff_accelerator) ||
+ !acc.cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map))
+ {
+ glyph_to_sid_map->~glyph_to_sid_map_t ();
+ hb_free (glyph_to_sid_map);
+ }
}
- bool two_byte = subset_charset_ranges.complete (glyph);
+ bool two_byte = subset_charset_ranges.complete (num_glyphs);
- size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1);
+ size0 = Charset0::get_size (plan->num_output_glyphs ());
if (!two_byte)
- size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length;
+ size_ranges = Charset1::get_size_for_ranges (subset_charset_ranges.length);
else
- size_ranges = Charset2::min_size + Charset2_Range::static_size * subset_charset_ranges.length;
+ size_ranges = Charset2::get_size_for_ranges (subset_charset_ranges.length);
if (size0 < size_ranges)
subset_charset_format = 0;
@@ -528,19 +585,18 @@ struct cff_subset_plan {
subset_charset_format = 1;
else
subset_charset_format = 2;
+
+ return true;
}
bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
{
- sidmap.reset ();
-
for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
{
unsigned int sid = acc.topDict.nameSIDs[i];
if (sid != CFF_UNDEF_SID)
{
- (void)sidmap.add (sid);
- topDictModSIDs[i] = sidmap[sid];
+ topDictModSIDs[i] = sidmap.add (sid);
}
}
@@ -564,19 +620,18 @@ struct cff_subset_plan {
drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE;
- /* check whether the subset renumbers any glyph IDs */
- gid_renum = false;
- for (hb_codepoint_t new_glyph = 0; new_glyph < plan->num_output_glyphs (); new_glyph++)
- {
- if (!plan->old_gid_for_new_gid(new_glyph, &old_glyph))
- continue;
- if (new_glyph != old_glyph) {
- gid_renum = true;
- break;
+ subset_charset = !acc.is_predef_charset ();
+ if (!subset_charset)
+ /* check whether the subset renumbers any glyph IDs */
+ for (const auto &_ : plan->new_to_old_gid_list)
+ {
+ if (_.first != _.second)
+ {
+ subset_charset = true;
+ break;
+ }
}
- }
- subset_charset = gid_renum || !acc.is_predef_charset ();
subset_encoding = !acc.is_CID() && !acc.is_predef_encoding ();
/* top dict INDEX */
@@ -618,7 +673,8 @@ struct cff_subset_plan {
if (unlikely (sidmap.get_population () > 0x8000)) /* assumption: a dict won't reference that many strings */
return false;
- if (subset_charset) plan_subset_charset (acc, plan);
+ if (subset_charset && !plan_subset_charset (acc, plan))
+ return false;
topdict_mod.reassignSIDs (sidmap);
}
@@ -682,8 +738,9 @@ struct cff_subset_plan {
;
}
- return ((subset_charstrings.length == plan->num_output_glyphs ())
- && (fontdicts_mod.length == subset_fdcount));
+ return !plan->in_error () &&
+ (subset_charstrings.length == plan->num_output_glyphs ()) &&
+ (fontdicts_mod.length == subset_fdcount);
}
cff1_top_dict_values_mod_t topdict_mod;
@@ -722,24 +779,22 @@ struct cff_subset_plan {
bool desubroutinize = false;
};
+} // namespace OT
-static bool _serialize_cff1 (hb_serialize_context_t *c,
- cff_subset_plan &plan,
- const OT::cff1::accelerator_subset_t &acc,
- unsigned int num_glyphs)
+bool
+OT::cff1::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+ struct OT::cff1_subset_plan &plan) const
{
/* private dicts & local subrs */
- for (int i = (int)acc.privateDicts.length; --i >= 0 ;)
+ for (int i = (int) privateDicts.length; --i >= 0 ;)
{
if (plan.fdmap.has (i))
{
objidx_t subrs_link = 0;
if (plan.subset_localsubrs[i].length > 0)
{
- CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
- if (unlikely (!dest)) return false;
- c->push ();
- if (likely (dest && dest->serialize (c, plan.subset_localsubrs[i])))
+ auto *dest = c->push <CFF1Subrs> ();
+ if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
subrs_link = c->pop_pack ();
else
{
@@ -748,12 +803,10 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
}
}
- PrivateDict *pd = c->start_embed<PrivateDict> ();
- if (unlikely (!pd)) return false;
- c->push ();
+ auto *pd = c->push<PrivateDict> ();
cff1_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
- if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link)))
+ if (likely (pd->serialize (c, privateDicts[i], privSzr, subrs_link)))
{
unsigned fd = plan.fdmap[i];
plan.fontdicts_mod[fd].privateDictInfo.size = c->length ();
@@ -767,21 +820,20 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
}
}
- if (!acc.is_CID ())
+ if (!is_CID ())
plan.info.privateDictInfo = plan.fontdicts_mod[0].privateDictInfo;
/* CharStrings */
{
c->push<CFF1CharStrings> ();
- unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings);
+ unsigned data_size = 0;
+ unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size);
if (unlikely (!c->start_zerocopy (total_size)))
return false;
- CFF1CharStrings *cs = c->start_embed<CFF1CharStrings> ();
- if (unlikely (!cs)) return false;
-
- if (likely (cs->serialize (c, plan.subset_charstrings)))
+ auto *cs = c->start_embed<CFF1CharStrings> ();
+ if (likely (cs->serialize (c, plan.subset_charstrings, &data_size)))
plan.info.char_strings_link = c->pop_pack (false);
else
{
@@ -791,11 +843,9 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
}
/* FDArray (FD Index) */
- if (acc.fdArray != &Null (CFF1FDArray))
+ if (fdArray != &Null (CFF1FDArray))
{
- CFF1FDArray *fda = c->start_embed<CFF1FDArray> ();
- if (unlikely (!fda)) return false;
- c->push ();
+ auto *fda = c->push<CFF1FDArray> ();
cff1_font_dict_op_serializer_t fontSzr;
auto it = + hb_zip (+ hb_iter (plan.fontdicts_mod), + hb_iter (plan.fontdicts_mod));
if (likely (fda->serialize (c, it, fontSzr)))
@@ -808,10 +858,10 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
}
/* FDSelect */
- if (acc.fdSelect != &Null (CFF1FDSelect))
+ if (fdSelect != &Null (CFF1FDSelect))
{
c->push ();
- if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *acc.fdSelect, acc.fdCount,
+ if (likely (hb_serialize_cff_fdselect (c, plan.num_glyphs, *fdSelect, fdCount,
plan.subset_fdselect_format, plan.info.fd_select.size,
plan.subset_fdselect_ranges)))
plan.info.fd_select.link = c->pop_pack ();
@@ -825,9 +875,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
/* Charset */
if (plan.subset_charset)
{
- Charset *dest = c->start_embed<Charset> ();
- if (unlikely (!dest)) return false;
- c->push ();
+ auto *dest = c->push<Charset> ();
if (likely (dest->serialize (c,
plan.subset_charset_format,
plan.num_glyphs,
@@ -843,9 +891,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
/* Encoding */
if (plan.subset_encoding)
{
- Encoding *dest = c->start_embed<Encoding> ();
- if (unlikely (!dest)) return false;
- c->push ();
+ auto *dest = c->push<Encoding> ();
if (likely (dest->serialize (c,
plan.subset_enc_format,
plan.subset_enc_num_codes,
@@ -861,9 +907,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
/* global subrs */
{
- c->push ();
- CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
- if (unlikely (!dest)) return false;
+ auto *dest = c->push <CFF1Subrs> ();
if (likely (dest->serialize (c, plan.subset_globalsubrs)))
c->pop_pack (false);
else
@@ -875,10 +919,9 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
/* String INDEX */
{
- CFF1StringIndex *dest = c->start_embed<CFF1StringIndex> ();
- if (unlikely (!dest)) return false;
- c->push ();
- if (likely (dest->serialize (c, *acc.stringIndex, plan.sidmap)))
+ auto *dest = c->push<CFF1StringIndex> ();
+ if (likely (!plan.sidmap.in_error () &&
+ dest->serialize (c, *stringIndex, plan.sidmap.vector)))
c->pop_pack ();
else
{
@@ -898,14 +941,12 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
cff->offSize = 4; /* unused? */
/* name INDEX */
- if (unlikely (!(*acc.nameIndex).copy (c))) return false;
+ if (unlikely (!c->embed (*nameIndex))) return false;
/* top dict INDEX */
{
/* serialize singleton TopDict */
- TopDict *top = c->start_embed<TopDict> ();
- if (!top) return false;
- c->push ();
+ auto *top = c->push<TopDict> ();
cff1_top_dict_op_serializer_t topSzr;
unsigned top_size = 0;
top_dict_modifiers_t modifier (plan.info, plan.topDictModSIDs);
@@ -920,36 +961,23 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
return false;
}
/* serialize INDEX header for above */
- CFF1Index *dest = c->start_embed<CFF1Index> ();
- if (!dest) return false;
- return dest->serialize_header (c, hb_iter (hb_array_t<unsigned> (&top_size, 1)));
+ auto *dest = c->start_embed<CFF1Index> ();
+ return dest->serialize_header (c, hb_iter (&top_size, 1), top_size);
}
}
-static bool
-_hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc,
- hb_subset_context_t *c)
+bool
+OT::cff1::accelerator_subset_t::subset (hb_subset_context_t *c) const
{
- cff_subset_plan cff_plan;
+ cff1_subset_plan cff_plan;
- if (unlikely (!cff_plan.create (acc, c->plan)))
+ if (unlikely (!cff_plan.create (*this, c->plan)))
{
DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan.");
return false;
}
- return _serialize_cff1 (c->serializer, cff_plan, acc, c->plan->num_output_glyphs ());
-}
-
-bool
-hb_subset_cff1 (hb_subset_context_t *c)
-{
- OT::cff1::accelerator_subset_t acc;
- acc.init (c->plan->source);
- bool result = likely (acc.is_valid ()) && _hb_subset_cff1 (acc, c);
- acc.fini ();
-
- return result;
+ return serialize (c->serializer, cff_plan);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
index 8ab4620194..3c52fb9c2c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
@@ -31,7 +31,6 @@
#include "hb-open-type.hh"
#include "hb-ot-cff2-table.hh"
#include "hb-set.h"
-#include "hb-subset-cff2.hh"
#include "hb-subset-plan.hh"
#include "hb-subset-cff-common.hh"
#include "hb-cff2-interp-cs.hh"
@@ -422,11 +421,17 @@ struct cff2_private_dict_op_serializer_t : op_serializer_t
};
+namespace OT {
struct cff2_subset_plan
{
bool create (const OT::cff2::accelerator_subset_t &acc,
hb_subset_plan_t *plan)
{
+ /* make sure notdef is first */
+ hb_codepoint_t old_glyph;
+ if (!plan->old_gid_for_new_gid (0, &old_glyph) || (old_glyph != 0)) return false;
+
+ num_glyphs = plan->num_output_glyphs ();
orig_fdcount = acc.fdArray->count;
drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
@@ -489,6 +494,7 @@ struct cff2_subset_plan
cff2_sub_table_info_t info;
+ unsigned int num_glyphs;
unsigned int orig_fdcount = 0;
unsigned int subset_fdcount = 1;
unsigned int subset_fdselect_size = 0;
@@ -505,18 +511,18 @@ struct cff2_subset_plan
bool drop_hints = false;
bool desubroutinize = false;
};
+} // namespace OT
-static bool _serialize_cff2 (hb_serialize_context_t *c,
- cff2_subset_plan &plan,
- const OT::cff2::accelerator_subset_t &acc,
- unsigned int num_glyphs,
- hb_array_t<int> normalized_coords)
+bool
+OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+ struct cff2_subset_plan &plan,
+ hb_array_t<int> normalized_coords) const
{
/* private dicts & local subrs */
hb_vector_t<table_info_t> private_dict_infos;
if (unlikely (!private_dict_infos.resize (plan.subset_fdcount))) return false;
- for (int i = (int)acc.privateDicts.length; --i >= 0 ;)
+ for (int i = (int)privateDicts.length; --i >= 0 ;)
{
if (plan.fdmap.has (i))
{
@@ -524,9 +530,7 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
if (plan.subset_localsubrs[i].length > 0)
{
- CFF2Subrs *dest = c->start_embed <CFF2Subrs> ();
- if (unlikely (!dest)) return false;
- c->push ();
+ auto *dest = c->push <CFF2Subrs> ();
if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
subrs_link = c->pop_pack (false);
else
@@ -535,12 +539,10 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
return false;
}
}
- PrivateDict *pd = c->start_embed<PrivateDict> ();
- if (unlikely (!pd)) return false;
- c->push ();
+ auto *pd = c->push<PrivateDict> ();
cff2_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints, plan.pinned,
- acc.varStore, normalized_coords);
- if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link)))
+ varStore, normalized_coords);
+ if (likely (pd->serialize (c, privateDicts[i], privSzr, subrs_link)))
{
unsigned fd = plan.fdmap[i];
private_dict_infos[fd].size = c->length ();
@@ -558,14 +560,13 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
{
c->push ();
- unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings);
+ unsigned data_size = 0;
+ unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings, &data_size);
if (unlikely (!c->start_zerocopy (total_size)))
return false;
- CFF2CharStrings *cs = c->start_embed<CFF2CharStrings> ();
- if (unlikely (!cs)) return false;
-
- if (likely (cs->serialize (c, plan.subset_charstrings)))
+ auto *cs = c->start_embed<CFF2CharStrings> ();
+ if (likely (cs->serialize (c, plan.subset_charstrings, &data_size)))
plan.info.char_strings_link = c->pop_pack (false);
else
{
@@ -575,10 +576,10 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
}
/* FDSelect */
- if (acc.fdSelect != &Null (CFF2FDSelect))
+ if (fdSelect != &Null (CFF2FDSelect))
{
c->push ();
- if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect,
+ if (likely (hb_serialize_cff_fdselect (c, plan.num_glyphs, *(const FDSelect *)fdSelect,
plan.orig_fdcount,
plan.subset_fdselect_format, plan.subset_fdselect_size,
plan.subset_fdselect_ranges)))
@@ -592,27 +593,32 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
/* FDArray (FD Index) */
{
- c->push ();
- CFF2FDArray *fda = c->start_embed<CFF2FDArray> ();
- if (unlikely (!fda)) return false;
+ auto *fda = c->push<CFF2FDArray> ();
cff_font_dict_op_serializer_t fontSzr;
auto it =
- + hb_zip (+ hb_iter (acc.fontDicts)
+ + hb_zip (+ hb_iter (fontDicts)
| hb_filter ([&] (const cff2_font_dict_values_t &_)
- { return plan.fdmap.has (&_ - &acc.fontDicts[0]); }),
+ { return plan.fdmap.has (&_ - &fontDicts[0]); }),
hb_iter (private_dict_infos))
;
- if (unlikely (!fda->serialize (c, it, fontSzr))) return false;
+ if (unlikely (!fda->serialize (c, it, fontSzr)))
+ {
+ c->pop_discard ();
+ return false;
+ }
plan.info.fd_array_link = c->pop_pack (false);
}
/* variation store */
- if (acc.varStore != &Null (CFF2VariationStore) &&
+ if (varStore != &Null (CFF2VariationStore) &&
!plan.pinned)
{
- c->push ();
- CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> ();
- if (unlikely (!dest || !dest->serialize (c, acc.varStore))) return false;
+ auto *dest = c->push<CFF2VariationStore> ();
+ if (unlikely (!dest->serialize (c, varStore)))
+ {
+ c->pop_discard ();
+ return false;
+ }
plan.info.var_store_link = c->pop_pack (false);
}
@@ -628,34 +634,25 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
{
TopDict &dict = cff2 + cff2->topDict;
cff2_top_dict_op_serializer_t topSzr;
- if (unlikely (!dict.serialize (c, acc.topDict, topSzr, plan.info))) return false;
+ if (unlikely (!dict.serialize (c, topDict, topSzr, plan.info))) return false;
cff2->topDictSize = c->head - (const char *)&dict;
}
/* global subrs */
{
- CFF2Subrs *dest = c->start_embed <CFF2Subrs> ();
- if (unlikely (!dest)) return false;
+ auto *dest = c->start_embed <CFF2Subrs> ();
return dest->serialize (c, plan.subset_globalsubrs);
}
}
-static bool
-_hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc,
- hb_subset_context_t *c)
+bool
+OT::cff2::accelerator_subset_t::subset (hb_subset_context_t *c) const
{
cff2_subset_plan cff2_plan;
- if (unlikely (!cff2_plan.create (acc, c->plan))) return false;
- return _serialize_cff2 (c->serializer, cff2_plan, acc, c->plan->num_output_glyphs (),
- c->plan->normalized_coords.as_array ());
-}
-
-bool
-hb_subset_cff2 (hb_subset_context_t *c)
-{
- OT::cff2::accelerator_subset_t acc (c->plan->source);
- return acc.is_valid () && _hb_subset_cff2 (acc, c);
+ if (unlikely (!cff2_plan.create (*this, c->plan))) return false;
+ return serialize (c->serializer, cff2_plan,
+ c->plan->normalized_coords.as_array ());
}
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
index 465af50814..93f961f2d8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
@@ -69,7 +69,6 @@ hb_subset_input_t::hb_subset_input_t ()
sets.drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
hb_tag_t default_no_subset_tables[] = {
- HB_TAG ('a', 'v', 'a', 'r'),
HB_TAG ('g', 'a', 's', 'p'),
HB_TAG ('f', 'p', 'g', 'm'),
HB_TAG ('p', 'r', 'e', 'p'),
@@ -438,7 +437,8 @@ hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
return false;
- return input->axes_location.set (axis_tag, axis_info.default_value);
+ float default_val = axis_info.default_value;
+ return input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val));
}
/**
@@ -468,8 +468,52 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
return false;
float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value);
- return input->axes_location.set (axis_tag, val);
+ return input->axes_location.set (axis_tag, Triple (val, val, val));
}
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_subset_input_set_axis_range: (skip)
+ * @input: a #hb_subset_input_t object.
+ * @face: a #hb_face_t object.
+ * @axis_tag: Tag of the axis
+ * @axis_min_value: Minimum value of the axis variation range to set
+ * @axis_max_value: Maximum value of the axis variation range to set
+ *
+ * Restricting the range of variation on an axis in the given subset input object.
+ * New min/max values will be clamped if they're not within the fvar axis range.
+ * If the fvar axis default value is not within the new range, the new default
+ * value will be changed to the new min or max value, whichever is closer to the fvar
+ * axis default.
+ *
+ * Note: input min value can not be bigger than input max value
+ * Note: currently this API does not support changing axis limits yet.It'd be only
+ * used internally for setting axis limits in the internal data structures
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * XSince: EXPERIMENTAL
+ **/
+HB_EXTERN hb_bool_t
+hb_subset_input_set_axis_range (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag,
+ float axis_min_value,
+ float axis_max_value)
+{
+ if (axis_min_value > axis_max_value)
+ return false;
+
+ hb_ot_var_axis_info_t axis_info;
+ if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+ return false;
+
+ float new_min_val = hb_clamp(axis_min_value, axis_info.min_value, axis_info.max_value);
+ float new_max_val = hb_clamp(axis_max_value, axis_info.min_value, axis_info.max_value);
+ float new_default_val = hb_clamp(axis_info.default_value, new_min_val, new_max_val);
+ return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val));
+}
+#endif
#endif
/**
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
index 1970f795b9..6ae311e613 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
@@ -35,6 +35,7 @@
#include "hb-set.hh"
#include "hb-cplusplus.hh"
#include "hb-font.hh"
+#include "hb-subset-instancer-solver.hh"
struct hb_ot_name_record_ids_t
{
@@ -118,7 +119,7 @@ struct hb_subset_input_t
// If set loca format will always be the long version.
bool force_long_loca = false;
- hb_hashmap_t<hb_tag_t, float> axes_location;
+ hb_hashmap_t<hb_tag_t, Triple> axes_location;
hb_map_t glyph_map;
#ifdef HB_EXPERIMENTAL_API
hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> name_table_overrides;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc
index 7a2735c529..4cb3f8a485 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc
@@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#include "hb.hh"
+#include "hb-subset-instancer-solver.hh"
/* This file is a straight port of the following:
*
@@ -35,26 +35,6 @@
constexpr static float EPSILON = 1.f / (1 << 14);
constexpr static float MAX_F2DOT14 = float (0x7FFF) / (1 << 14);
-struct Triple {
-
- Triple () :
- minimum (0.f), middle (0.f), maximum (0.f) {}
-
- Triple (float minimum_, float middle_, float maximum_) :
- minimum (minimum_), middle (middle_), maximum (maximum_) {}
-
- bool operator == (const Triple &o) const
- {
- return minimum == o.minimum &&
- middle == o.middle &&
- maximum == o.maximum;
- }
-
- float minimum;
- float middle;
- float maximum;
-};
-
static inline Triple _reverse_negate(const Triple &v)
{ return {-v.maximum, -v.middle, -v.minimum}; }
@@ -82,10 +62,6 @@ static inline float supportScalar (float coord, const Triple &tent)
return (end - coord) / (end - peak);
}
-
-using result_item_t = hb_pair_t<float, Triple>;
-using result_t = hb_vector_t<result_item_t>;
-
static inline result_t
_solve (Triple tent, Triple axisLimit, bool negative = false)
{
@@ -195,9 +171,9 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
if (gain > outGain)
{
// Crossing point on the axis.
- float crossing = peak + ((1 - gain) * (upper - peak) / (1 - outGain));
+ float crossing = peak + (1 - gain) * (upper - peak);
- Triple loc{peak, peak, crossing};
+ Triple loc{axisDef, peak, crossing};
float scalar = 1.f;
// The part before the crossing point.
@@ -213,7 +189,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
if (upper >= axisMax)
{
Triple loc {crossing, axisMax, axisMax};
- float scalar = supportScalar (axisMax, tent);
+ float scalar = outGain;
out.push (hb_pair (scalar - gain, loc));
}
@@ -247,89 +223,82 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
// Eternity justify.
Triple loc2 {upper, axisMax, axisMax};
- float scalar2 = 1.f; // supportScalar({"tag": axisMax}, {"tag": tent})
+ float scalar2 = 0.f;
out.push (hb_pair (scalar1 - gain, loc1));
out.push (hb_pair (scalar2 - gain, loc2));
}
}
- /* Case 3: Outermost limit still fits within F2Dot14 bounds;
- * we keep deltas as is and only scale the axes bounds. Deltas beyond -1.0
- * or +1.0 will never be applied as implementations must clamp to that range.
- *
- * A second tent is needed for cases when gain is positive, though we add it
- * unconditionally and it will be dropped because scalar ends up 0.
- *
- * TODO: See if we can just move upper closer to adjust the slope, instead of
- * second tent.
- *
- * | peak |
- * 1.........|............o...|..................
- * | /x\ |
- * | /xxx\ |
- * | /xxxxx\|
- * | /xxxxxxx+
- * | /xxxxxxxx|\
- * 0---|-----|------oxxxxxxxxx|xo---------------1
- * axisMin | lower | upper
- * | |
- * axisDef axisMax
- */
- else if (axisDef + (axisMax - axisDef) * 2 >= upper)
+ else
{
- if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper)
- {
- // we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience
- upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14;
- assert (peak < upper);
- }
-
// Special-case if peak is at axisMax.
if (axisMax == peak)
upper = peak;
- Triple loc1 {hb_max (axisDef, lower), peak, upper};
- float scalar1 = 1.f;
+ /* Case 3:
+ * we keep deltas as is and only scale the axis upper to achieve
+ * the desired new tent if feasible.
+ *
+ * peak
+ * 1.....................o....................
+ * / \_|
+ * ..................../....+_.........outGain
+ * / | \
+ * gain..............+......|..+_.............
+ * /| | | \
+ * 0---|-----------o | | | o----------1
+ * axisMin lower| | | upper
+ * | | newUpper
+ * axisDef axisMax
+ */
+ float newUpper = peak + (1 - gain) * (upper - peak);
+ assert (axisMax <= newUpper); // Because outGain >= gain
+ if (newUpper <= axisDef + (axisMax - axisDef) * 2)
+ {
+ upper = newUpper;
+ if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper)
+ {
+ // we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience
+ upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14;
+ assert (peak < upper);
+ }
- Triple loc2 {peak, upper, upper};
- float scalar2 = 0.f;
+ Triple loc {hb_max (axisDef, lower), peak, upper};
+ float scalar = 1.f;
- // Don't add a dirac delta!
- if (axisDef < upper)
- out.push (hb_pair (scalar1 - gain, loc1));
- if (peak < upper)
- out.push (hb_pair (scalar2 - gain, loc2));
- }
+ out.push (hb_pair (scalar - gain, loc));
+ }
- /* Case 4: New limit doesn't fit; we need to chop into two tents,
- * because the shape of a triangle with part of one side cut off
- * cannot be represented as a triangle itself.
- *
- * | peak |
- * 1.........|......o.|...................
- * | /x\|
- * | |xxy|\_
- * | /xxxy| \_
- * | |xxxxy| \_
- * | /xxxxy| \_
- * 0---|-----|-oxxxxxx| o----------1
- * axisMin | lower | upper
- * | |
- * axisDef axisMax
- */
- else
- {
- Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
- float scalar1 = 1.f;
+ /* Case 4: New limit doesn't fit; we need to chop into two tents,
+ * because the shape of a triangle with part of one side cut off
+ * cannot be represented as a triangle itself.
+ *
+ * | peak |
+ * 1.........|......o.|....................
+ * ..........|...../x\|.............outGain
+ * | |xxy|\_
+ * | /xxxy| \_
+ * | |xxxxy| \_
+ * | /xxxxy| \_
+ * 0---|-----|-oxxxxxx| o----------1
+ * axisMin | lower | upper
+ * | |
+ * axisDef axisMax
+ */
+ else
+ {
+ Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
+ float scalar1 = 1.f;
- Triple loc2 {peak, axisMax, axisMax};
- float scalar2 = supportScalar (axisMax, tent);
+ Triple loc2 {peak, axisMax, axisMax};
+ float scalar2 = outGain;
- out.push (hb_pair (scalar1 - gain, loc1));
- // Don't add a dirac delta!
- if (peak < axisMax)
- out.push (hb_pair (scalar2 - gain, loc2));
+ out.push (hb_pair (scalar1 - gain, loc1));
+ // Don't add a dirac delta!
+ if (peak < axisMax)
+ out.push (hb_pair (scalar2 - gain, loc2));
+ }
}
/* Now, the negative side
@@ -392,51 +361,47 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
return out;
}
-/* Normalizes value based on a min/default/max triple. */
-static inline float normalizeValue (float v, const Triple &triple, bool extrapolate = false)
+static inline TripleDistances _reverse_triple_distances (const TripleDistances &v)
+{ return TripleDistances (v.positive, v.negative); }
+
+float renormalizeValue (float v, const Triple &triple,
+ const TripleDistances &triple_distances, bool extrapolate)
{
- /*
- >>> normalizeValue(400, (100, 400, 900))
- 0.0
- >>> normalizeValue(100, (100, 400, 900))
- -1.0
- >>> normalizeValue(650, (100, 400, 900))
- 0.5
- */
float lower = triple.minimum, def = triple.middle, upper = triple.maximum;
assert (lower <= def && def <= upper);
if (!extrapolate)
v = hb_max (hb_min (v, upper), lower);
- if ((v == def) || (lower == upper))
+ if (v == def)
return 0.f;
- if ((v < def && lower != def) || (v > def && upper == def))
+ if (def < 0.f)
+ return -renormalizeValue (-v, _reverse_negate (triple),
+ _reverse_triple_distances (triple_distances), extrapolate);
+
+ /* default >= 0 and v != default */
+ if (v > def)
+ return (v - def) / (upper - def);
+
+ /* v < def */
+ if (lower >= 0.f)
return (v - def) / (def - lower);
+
+ /* lower < 0 and v < default */
+ float total_distance = triple_distances.negative * (-lower) + triple_distances.positive * def;
+
+ float v_distance;
+ if (v >= 0.f)
+ v_distance = (def - v) * triple_distances.positive;
else
- {
- assert ((v > def && upper != def) ||
- (v < def && lower == def));
- return (v - def) / (upper - def);
- }
-}
+ v_distance = (-v) * triple_distances.negative + triple_distances.positive * def;
-/* Given a tuple (lower,peak,upper) "tent" and new axis limits
- * (axisMin,axisDefault,axisMax), solves how to represent the tent
- * under the new axis configuration. All values are in normalized
- * -1,0,+1 coordinate system. Tent values can be outside this range.
- *
- * Return value: a list of tuples. Each tuple is of the form
- * (scalar,tent), where scalar is a multipler to multiply any
- * delta-sets by, and tent is a new tent for that output delta-set.
- * If tent value is Triple{}, that is a special deltaset that should
- * be always-enabled (called "gain").
- */
-HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit);
+ return (-v_distance) /total_distance;
+}
result_t
-rebase_tent (Triple tent, Triple axisLimit)
+rebase_tent (Triple tent, Triple axisLimit, TripleDistances axis_triple_distances)
{
assert (-1.f <= axisLimit.minimum && axisLimit.minimum <= axisLimit.middle && axisLimit.middle <= axisLimit.maximum && axisLimit.maximum <= +1.f);
assert (-2.f <= tent.minimum && tent.minimum <= tent.middle && tent.middle <= tent.maximum && tent.maximum <= +2.f);
@@ -444,7 +409,7 @@ rebase_tent (Triple tent, Triple axisLimit)
result_t sols = _solve (tent, axisLimit);
- auto n = [&axisLimit] (float v) { return normalizeValue (v, axisLimit, true); };
+ auto n = [&axisLimit, &axis_triple_distances] (float v) { return renormalizeValue (v, axisLimit, axis_triple_distances); };
result_t out;
for (auto &p : sols)
@@ -460,5 +425,5 @@ rebase_tent (Triple tent, Triple axisLimit)
Triple{n (t.minimum), n (t.middle), n (t.maximum)}));
}
- return sols;
+ return out;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.hh
new file mode 100644
index 0000000000..563fccbb59
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.hh
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_SUBSET_INSTANCER_SOLVER_HH
+#define HB_SUBSET_INSTANCER_SOLVER_HH
+
+#include "hb.hh"
+
+/* pre-normalized distances */
+struct TripleDistances
+{
+ TripleDistances (): negative (1.f), positive (1.f) {}
+ TripleDistances (float neg_, float pos_): negative (neg_), positive (pos_) {}
+ TripleDistances (float min, float default_, float max)
+ {
+ negative = default_ - min;
+ positive = max - default_;
+ }
+
+ float negative;
+ float positive;
+};
+
+struct Triple {
+
+ Triple () :
+ minimum (0.f), middle (0.f), maximum (0.f) {}
+
+ Triple (float minimum_, float middle_, float maximum_) :
+ minimum (minimum_), middle (middle_), maximum (maximum_) {}
+
+ bool operator == (const Triple &o) const
+ {
+ return minimum == o.minimum &&
+ middle == o.middle &&
+ maximum == o.maximum;
+ }
+
+ bool operator != (const Triple o) const
+ { return !(*this == o); }
+
+ bool is_point () const
+ { return minimum == middle && middle == maximum; }
+
+ bool contains (float point) const
+ { return minimum <= point && point <= maximum; }
+
+ /* from hb_array_t hash ()*/
+ uint32_t hash () const
+ {
+ uint32_t current = /*cbf29ce4*/0x84222325;
+ current = current ^ hb_hash (minimum);
+ current = current * 16777619;
+
+ current = current ^ hb_hash (middle);
+ current = current * 16777619;
+
+ current = current ^ hb_hash (maximum);
+ current = current * 16777619;
+ return current;
+ }
+
+
+ float minimum;
+ float middle;
+ float maximum;
+};
+
+using result_item_t = hb_pair_t<float, Triple>;
+using result_t = hb_vector_t<result_item_t>;
+
+/* renormalize a normalized value v to the range of an axis,
+ * considering the prenormalized distances as well as the new axis limits.
+ * Ported from fonttools */
+HB_INTERNAL float renormalizeValue (float v, const Triple &triple,
+ const TripleDistances &triple_distances,
+ bool extrapolate = true);
+/* Given a tuple (lower,peak,upper) "tent" and new axis limits
+ * (axisMin,axisDefault,axisMax), solves how to represent the tent
+ * under the new axis configuration. All values are in normalized
+ * -1,0,+1 coordinate system. Tent values can be outside this range.
+ *
+ * Return value: a list of tuples. Each tuple is of the form
+ * (scalar,tent), where scalar is a multipler to multiply any
+ * delta-sets by, and tent is a new tent for that output delta-set.
+ * If tent value is Triple{}, that is a special deltaset that should
+ * be always-enabled (called "gain").
+ */
+HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit, TripleDistances axis_triple_distances);
+
+#endif /* HB_SUBSET_INSTANCER_SOLVER_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh
index acf508c32d..8e61055f4a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan-member-list.hh
@@ -33,7 +33,9 @@
// For each cp that we'd like to retain maps to the corresponding gid.
HB_SUBSET_PLAN_MEMBER (hb_set_t, unicodes)
-HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t E(<hb_pair_t<hb_codepoint_t, hb_codepoint_t>>), unicode_to_new_gid_list)
+HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t<hb_codepoint_pair_t>, unicode_to_new_gid_list)
+
+HB_SUBSET_PLAN_MEMBER (hb_sorted_vector_t<hb_codepoint_pair_t>, new_to_old_gid_list)
// name_ids we would like to retain
HB_SUBSET_PLAN_MEMBER (hb_set_t, name_ids)
@@ -97,12 +99,14 @@ HB_SUBSET_PLAN_MEMBER (hb_vector_t<hb_inc_bimap_t>, gdef_varstore_inner_maps)
HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, hb::unique_ptr<hb_blob_t>>), sanitized_table_cache)
-//normalized axes location map
-HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, int>), axes_location)
+//normalized axes range map
+HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, Triple>), axes_location)
HB_SUBSET_PLAN_MEMBER (hb_vector_t<int>, normalized_coords)
-//user specified axes location map
-HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, float>), user_axes_location)
+//user specified axes range map
+HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, Triple>), user_axes_location)
+//axis->TripleDistances map (distances in the pre-normalized space)
+HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<hb_tag_t, TripleDistances>), axes_triple_distances)
//retained old axis index -> new axis index mapping in fvar axis array
HB_SUBSET_PLAN_MEMBER (hb_map_t, axes_index_map)
@@ -115,9 +119,9 @@ HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<hb_codepoint_t, hb_pair_t E(<unsi
//vmtx metrics map: new gid->(advance, lsb)
HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<hb_codepoint_t, hb_pair_t E(<unsigned, int>)>), vmtx_map)
//boundsWidth map: new gid->boundsWidth, boundWidth=xMax - xMin
-HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_width_map)
+HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_width_vec)
//boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin
-HB_SUBSET_PLAN_MEMBER (mutable hb_map_t, bounds_height_map)
+HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_height_vec)
#ifdef HB_EXPERIMENTAL_API
// name table overrides map: hb_ot_name_record_ids_t-> name string new value or
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
index 791f92d02d..a2090b727c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
@@ -48,10 +48,24 @@
using OT::Layout::GSUB;
using OT::Layout::GPOS;
+
+hb_subset_accelerator_t::~hb_subset_accelerator_t ()
+{
+ if (cmap_cache && destroy_cmap_cache)
+ destroy_cmap_cache ((void*) cmap_cache);
+
+#ifndef HB_NO_SUBSET_CFF
+ cff1_accel.fini ();
+ cff2_accel.fini ();
+#endif
+ hb_face_destroy (source);
+}
+
+
typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
#ifndef HB_NO_SUBSET_CFF
static inline bool
-_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
+_add_cff_seac_components (const OT::cff1::accelerator_subset_t &cff,
hb_codepoint_t gid,
hb_set_t *gids_to_retain)
{
@@ -135,7 +149,8 @@ static void _collect_layout_indices (hb_subset_plan_t *plan,
hb_set_t *lookup_indices, /* OUT */
hb_set_t *feature_indices, /* OUT */
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */
- hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map /* OUT */)
+ hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, /* OUT */
+ bool& insert_catch_all_feature_variation_record)
{
unsigned num_features = table.get_feature_count ();
hb_vector_t<hb_tag_t> features;
@@ -171,8 +186,11 @@ static void _collect_layout_indices (hb_subset_plan_t *plan,
&plan->axes_location,
feature_record_cond_idx_map,
feature_substitutes_map,
+ insert_catch_all_feature_variation_record,
feature_indices,
- true,
+ false,
+ false,
+ false,
0,
&conditionset_map
};
@@ -283,7 +301,8 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
hb_map_t *features,
script_langsys_map *langsys_map,
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
- hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map)
+ hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
+ bool& insert_catch_all_feature_variation_record)
{
hb_blob_ptr_t<T> table = plan->source_table<T> ();
hb_tag_t table_tag = table->tableTag;
@@ -293,7 +312,8 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
&lookup_indices,
&feature_indices,
feature_record_cond_idx_map,
- feature_substitutes_map);
+ feature_substitutes_map,
+ insert_catch_all_feature_variation_record);
if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE))
hb_ot_layout_lookups_substitute_closure (plan->source,
@@ -329,7 +349,7 @@ _generate_varstore_inner_maps (const hb_set_t& varidx_set,
{
if (varidx_set.is_empty () || subtable_count == 0) return;
- inner_maps.resize (subtable_count);
+ if (unlikely (!inner_maps.resize (subtable_count))) return;
for (unsigned idx : varidx_set)
{
uint16_t major = idx >> 16;
@@ -356,7 +376,7 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan)
{
hb_variation_t var;
var.tag = _.first;
- var.value = _.second;
+ var.value = _.second.middle;
vars.push (var);
}
@@ -541,6 +561,8 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
unicodes->get_population () < cmap_unicodes->get_population () &&
glyphs->get_population () < cmap_unicodes->get_population ())
{
+ plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ());
+
auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes;
for (hb_codepoint_t gid : *glyphs)
{
@@ -569,6 +591,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
}
else
{
+ plan->codepoint_to_glyph->alloc (cmap_unicodes->get_population ());
for (hb_codepoint_t cp : *cmap_unicodes)
{
hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
@@ -581,11 +604,15 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
}
/* Add gids which where requested, but not mapped in cmap */
- for (hb_codepoint_t gid : *glyphs)
+ unsigned num_glyphs = plan->source->get_num_glyphs ();
+ hb_codepoint_t first = HB_SET_VALUE_INVALID, last = HB_SET_VALUE_INVALID;
+ for (; glyphs->next_range (&first, &last); )
{
- if (gid >= plan->source->get_num_glyphs ())
+ if (first >= num_glyphs)
break;
- plan->_glyphset_gsub.add (gid);
+ if (last >= num_glyphs)
+ last = num_glyphs - 1;
+ plan->_glyphset_gsub.add_range (first, last);
}
}
@@ -616,7 +643,9 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
if (unlikely (--operation_count < 0)) return operation_count;
- for (auto &item : glyf.glyph_for_gid (gid).get_composite_iterator ())
+ auto glyph = glyf.glyph_for_gid (gid);
+
+ for (auto &item : glyph.get_composite_iterator ())
operation_count =
_glyf_add_gid_and_children (glyf,
item.get_gid (),
@@ -625,7 +654,7 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
depth);
#ifndef HB_NO_VAR_COMPOSITES
- for (auto &item : glyf.glyph_for_gid (gid).get_var_composite_iterator ())
+ for (auto &item : glyph.get_var_composite_iterator ())
{
operation_count =
_glyf_add_gid_and_children (glyf,
@@ -648,7 +677,7 @@ _nameid_closure (hb_subset_plan_t* plan,
#endif
#ifndef HB_NO_VAR
if (!plan->all_axes_pinned)
- plan->source->table.fvar->collect_name_ids (&plan->user_axes_location, &plan->name_ids);
+ plan->source->table.fvar->collect_name_ids (&plan->user_axes_location, &plan->axes_old_index_tag_map, &plan->name_ids);
#endif
#ifndef HB_NO_COLOR
if (!drop_tables->has (HB_OT_TAG_CPAL))
@@ -677,7 +706,11 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
{
OT::glyf_accelerator_t glyf (plan->source);
#ifndef HB_NO_SUBSET_CFF
- OT::cff1::accelerator_t cff (plan->source);
+ // Note: we cannot use inprogress_accelerator here, since it has not been
+ // created yet. So in case of preprocessed-face (and otherwise), we do an
+ // extra sanitize pass here, which is not ideal.
+ OT::cff1::accelerator_subset_t stack_cff (plan->accelerator ? nullptr : plan->source);
+ const OT::cff1::accelerator_subset_t *cff (plan->accelerator ? plan->accelerator->cff1_accel.get () : &stack_cff);
#endif
plan->_glyphset_gsub.add (0); // Not-def
@@ -694,7 +727,8 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
&plan->gsub_features,
&plan->gsub_langsys,
&plan->gsub_feature_record_cond_idx_map,
- &plan->gsub_feature_substitutes_map);
+ &plan->gsub_feature_substitutes_map,
+ plan->gsub_insert_catch_all_feature_variation_rec);
if (!drop_tables->has (HB_OT_TAG_GPOS))
_closure_glyphs_lookups_features<GPOS> (
@@ -704,7 +738,8 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
&plan->gpos_features,
&plan->gpos_langsys,
&plan->gpos_feature_record_cond_idx_map,
- &plan->gpos_feature_substitutes_map);
+ &plan->gpos_feature_substitutes_map,
+ plan->gpos_insert_catch_all_feature_variation_rec);
#endif
_remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ());
@@ -737,9 +772,9 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
if (!plan->accelerator || plan->accelerator->has_seac)
{
bool has_seac = false;
- if (cff.is_valid ())
+ if (cff->is_valid ())
for (hb_codepoint_t gid : cur_glyphset)
- if (_add_cff_seac_components (cff, gid, &plan->_glyphset))
+ if (_add_cff_seac_components (*cff, gid, &plan->_glyphset))
has_seac = true;
plan->has_seac = has_seac;
}
@@ -747,7 +782,6 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
_remove_invalid_gids (&plan->_glyphset, plan->source->get_num_glyphs ());
-
#ifndef HB_NO_VAR
if (!drop_tables->has (HB_OT_TAG_GDEF))
_collect_layout_variation_indices (plan);
@@ -759,10 +793,10 @@ _create_glyph_map_gsub (const hb_set_t* glyph_set_gsub,
const hb_map_t* glyph_map,
hb_map_t* out)
{
+ out->alloc (glyph_set_gsub->get_population ());
+ hb_iter (glyph_set_gsub)
| hb_map ([&] (hb_codepoint_t gid) {
- return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid,
- glyph_map->get (gid));
+ return hb_codepoint_pair_t (gid, glyph_map->get (gid));
})
| hb_sink (out)
;
@@ -775,11 +809,13 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
const hb_map_t *requested_glyph_map,
hb_map_t *glyph_map, /* OUT */
hb_map_t *reverse_glyph_map, /* OUT */
+ hb_sorted_vector_t<hb_codepoint_pair_t> *new_to_old_gid_list /* OUT */,
unsigned int *num_glyphs /* OUT */)
{
unsigned pop = all_gids_to_retain->get_population ();
- reverse_glyph_map->resize (pop);
- glyph_map->resize (pop);
+ reverse_glyph_map->alloc (pop);
+ glyph_map->alloc (pop);
+ new_to_old_gid_list->alloc (pop);
if (*requested_glyph_map)
{
@@ -803,45 +839,44 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
for (auto old_gid : all_gids_to_retain->iter ())
{
if (old_gid == 0) {
- reverse_glyph_map->set(0, 0);
+ new_to_old_gid_list->push (hb_pair<hb_codepoint_t, hb_codepoint_t> (0u, 0u));
continue;
}
hb_codepoint_t* new_gid;
if (!requested_glyph_map->has (old_gid, &new_gid))
{
- remaining.add(old_gid);
+ remaining.add(old_gid);
continue;
}
if (*new_gid > max_glyph)
max_glyph = *new_gid;
- reverse_glyph_map->set (*new_gid, old_gid);
+ new_to_old_gid_list->push (hb_pair (*new_gid, old_gid));
}
+ new_to_old_gid_list->qsort ();
// Anything that wasn't mapped by the requested mapping should
// be placed after the requested mapping.
for (auto old_gid : remaining)
- {
- reverse_glyph_map->set(++max_glyph, old_gid);
- }
+ new_to_old_gid_list->push (hb_pair (++max_glyph, old_gid));
*num_glyphs = max_glyph + 1;
}
else if (!retain_gids)
{
+ hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0)
- | hb_sink (reverse_glyph_map)
+ | hb_sink (new_to_old_gid_list)
;
- *num_glyphs = reverse_glyph_map->get_population ();
+ *num_glyphs = new_to_old_gid_list->length;
}
else
{
+ hb_iter (all_gids_to_retain)
| hb_map ([] (hb_codepoint_t _) {
- return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, _);
+ return hb_codepoint_pair_t (_, _);
})
- | hb_sink (reverse_glyph_map)
+ | hb_sink (new_to_old_gid_list)
;
hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID;
@@ -850,8 +885,11 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
*num_glyphs = max_glyph + 1;
}
- + reverse_glyph_map->iter ()
- | hb_map (&hb_pair_t<hb_codepoint_t, hb_codepoint_t>::reverse)
+ + hb_iter (new_to_old_gid_list)
+ | hb_sink (reverse_glyph_map)
+ ;
+ + hb_iter (new_to_old_gid_list)
+ | hb_map (&hb_codepoint_pair_t::reverse)
| hb_sink (glyph_map)
;
@@ -884,24 +922,37 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
hb_tag_t axis_tag = axis.get_axis_tag ();
plan->axes_old_index_tag_map.set (old_axis_idx, axis_tag);
- if (!plan->user_axes_location.has (axis_tag))
+ if (!plan->user_axes_location.has (axis_tag) ||
+ !plan->user_axes_location.get (axis_tag).is_point ())
{
axis_not_pinned = true;
plan->axes_index_map.set (old_axis_idx, new_axis_idx);
new_axis_idx++;
}
- else
+
+ Triple *axis_range;
+ if (plan->user_axes_location.has (axis_tag, &axis_range))
{
- int normalized_v = axis.normalize_axis_value (plan->user_axes_location.get (axis_tag));
+ plan->axes_triple_distances.set (axis_tag, axis.get_triple_distances ());
+
+ int normalized_min = axis.normalize_axis_value (axis_range->minimum);
+ int normalized_default = axis.normalize_axis_value (axis_range->middle);
+ int normalized_max = axis.normalize_axis_value (axis_range->maximum);
+
if (has_avar && old_axis_idx < avar_axis_count)
{
- normalized_v = seg_maps->map (normalized_v);
+ normalized_min = seg_maps->map (normalized_min);
+ normalized_default = seg_maps->map (normalized_default);
+ normalized_max = seg_maps->map (normalized_max);
}
- plan->axes_location.set (axis_tag, normalized_v);
- if (normalized_v != 0)
+ plan->axes_location.set (axis_tag, Triple (static_cast<float> (normalized_min / 16384.f),
+ static_cast<float> (normalized_default / 16384.f),
+ static_cast<float> (normalized_max / 16384.f)));
+
+ if (normalized_default != 0)
plan->pinned_at_default = false;
- plan->normalized_coords[old_axis_idx] = normalized_v;
+ plan->normalized_coords[old_axis_idx] = normalized_default;
}
old_axis_idx++;
@@ -968,7 +1019,7 @@ _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
continue;
}
plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
- plan->bounds_width_map.set (new_gid, extents.width);
+ plan->bounds_width_vec[new_gid] = extents.width;
}
if (_vmtx.has_data ())
@@ -985,7 +1036,7 @@ _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
continue;
}
plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
- plan->bounds_height_map.set (new_gid, extents.height);
+ plan->bounds_height_vec[new_gid] = extents.height;
}
}
hb_font_destroy (font);
@@ -1018,6 +1069,8 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
glyph_map = hb_map_create ();
reverse_glyph_map = hb_map_create ();
+ gsub_insert_catch_all_feature_variation_rec = false;
+ gpos_insert_catch_all_feature_variation_rec = false;
gdef_varstore_inner_maps.init ();
user_axes_location = input->axes_location;
@@ -1065,6 +1118,7 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
&input->glyph_map,
glyph_map,
reverse_glyph_map,
+ &new_to_old_gid_list,
&_num_output_glyphs))) {
return;
}
@@ -1082,6 +1136,13 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
glyph_map->get(unicode_to_new_gid_list.arrayZ[i].second);
}
+ bounds_width_vec.resize (_num_output_glyphs, false);
+ for (auto &v : bounds_width_vec)
+ v = 0xFFFFFFFF;
+ bounds_height_vec.resize (_num_output_glyphs, false);
+ for (auto &v : bounds_height_vec)
+ v = 0xFFFFFFFF;
+
if (unlikely (in_error ()))
return;
@@ -1091,19 +1152,9 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
if (attach_accelerator_data)
{
- hb_multimap_t gid_to_unicodes;
-
- hb_map_t &unicode_to_gid = *codepoint_to_glyph;
-
- for (auto unicode : unicodes)
- {
- auto gid = unicode_to_gid[unicode];
- gid_to_unicodes.add (gid, unicode);
- }
-
inprogress_accelerator =
- hb_subset_accelerator_t::create (*codepoint_to_glyph,
- gid_to_unicodes,
+ hb_subset_accelerator_t::create (source,
+ *codepoint_to_glyph,
unicodes,
has_seac);
@@ -1115,6 +1166,29 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
#undef HB_SUBSET_PLAN_MEMBER
}
+hb_subset_plan_t::~hb_subset_plan_t()
+{
+ hb_face_destroy (dest);
+
+ hb_map_destroy (codepoint_to_glyph);
+ hb_map_destroy (glyph_map);
+ hb_map_destroy (reverse_glyph_map);
+#ifndef HB_NO_SUBSET_CFF
+ cff1_accel.fini ();
+ cff2_accel.fini ();
+#endif
+ hb_face_destroy (source);
+
+#ifdef HB_EXPERIMENTAL_API
+ for (auto _ : name_table_overrides.iter_ref ())
+ _.second.fini ();
+#endif
+
+ if (inprogress_accelerator)
+ hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
+}
+
+
/**
* hb_subset_plan_create_or_fail:
* @face: font face to create the plan for.
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
index 19470ff83e..d156de05d7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
@@ -67,28 +67,17 @@ struct head_maxp_info_t
typedef struct head_maxp_info_t head_maxp_info_t;
+namespace OT {
+ struct cff1_subset_accelerator_t;
+ struct cff2_subset_accelerator_t;
+}
+
struct hb_subset_plan_t
{
HB_INTERNAL hb_subset_plan_t (hb_face_t *,
const hb_subset_input_t *input);
- ~hb_subset_plan_t()
- {
- hb_face_destroy (source);
- hb_face_destroy (dest);
-
- hb_map_destroy (codepoint_to_glyph);
- hb_map_destroy (glyph_map);
- hb_map_destroy (reverse_glyph_map);
-
-#ifdef HB_EXPERIMENTAL_API
- for (auto _ : name_table_overrides)
- _.second.fini ();
-#endif
-
- if (inprogress_accelerator)
- hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
- }
+ HB_INTERNAL ~hb_subset_plan_t();
hb_object_header_t header;
@@ -106,6 +95,12 @@ struct hb_subset_plan_t
// Plan is only good for a specific source/dest so keep them with it
hb_face_t *source;
+#ifndef HB_NO_SUBSET_CFF
+ // These have to be immediately after source:
+ hb_face_lazy_loader_t<OT::cff1_subset_accelerator_t, 1> cff1_accel;
+ hb_face_lazy_loader_t<OT::cff2_subset_accelerator_t, 2> cff2_accel;
+#endif
+
hb_face_t *dest;
unsigned int _num_output_glyphs;
@@ -114,6 +109,10 @@ struct hb_subset_plan_t
bool pinned_at_default;
bool has_seac;
+ // whether to insert a catch-all FeatureVariationRecord
+ bool gsub_insert_catch_all_feature_variation_rec;
+ bool gpos_insert_catch_all_feature_variation_rec;
+
#define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name;
#include "hb-subset-plan-member-list.hh"
#undef HB_SUBSET_PLAN_MEMBER
@@ -127,25 +126,31 @@ struct hb_subset_plan_t
public:
template<typename T>
- hb_blob_ptr_t<T> source_table()
+ struct source_table_loader
{
- hb_lock_t lock (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
+ hb_blob_ptr_t<T> operator () (hb_subset_plan_t *plan)
+ {
+ hb_lock_t lock (plan->accelerator ? &plan->accelerator->sanitized_table_cache_lock : nullptr);
- auto *cache = accelerator ? &accelerator->sanitized_table_cache : &sanitized_table_cache;
- if (cache
- && !cache->in_error ()
- && cache->has (+T::tableTag)) {
- return hb_blob_reference (cache->get (+T::tableTag).get ());
- }
+ auto *cache = plan->accelerator ? &plan->accelerator->sanitized_table_cache : &plan->sanitized_table_cache;
+ if (cache
+ && !cache->in_error ()
+ && cache->has (+T::tableTag)) {
+ return hb_blob_reference (cache->get (+T::tableTag).get ());
+ }
- hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)};
- hb_blob_t* ret = hb_blob_reference (table_blob.get ());
+ hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (plan->source)};
+ hb_blob_t* ret = hb_blob_reference (table_blob.get ());
- if (likely (cache))
- cache->set (+T::tableTag, std::move (table_blob));
+ if (likely (cache))
+ cache->set (+T::tableTag, std::move (table_blob));
- return ret;
- }
+ return ret;
+ }
+ };
+
+ template<typename T>
+ auto source_table() HB_AUTO_RETURN (source_table_loader<T> {} (this))
bool in_error () const { return !successful; }
@@ -184,15 +189,6 @@ struct hb_subset_plan_t
return _num_output_glyphs;
}
- /*
- * Given an output gid , returns true if that glyph id is an empty
- * glyph (ie. it's a gid that we are dropping all data for).
- */
- inline bool is_empty_glyph (hb_codepoint_t gid) const
- {
- return !_glyphset.has (gid);
- }
-
inline bool new_gid_for_codepoint (hb_codepoint_t codepoint,
hb_codepoint_t *new_gid) const
{
@@ -242,4 +238,5 @@ struct hb_subset_plan_t
}
};
+
#endif /* HB_SUBSET_PLAN_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
index 9c066e6d78..1f97dbed29 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
@@ -50,6 +50,7 @@
#include "hb-ot-name-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-var-avar-table.hh"
#include "hb-ot-var-cvar-table.hh"
#include "hb-ot-var-fvar-table.hh"
#include "hb-ot-var-gvar-table.hh"
@@ -62,6 +63,27 @@
using OT::Layout::GSUB;
using OT::Layout::GPOS;
+
+#ifndef HB_NO_SUBSET_CFF
+template<>
+struct hb_subset_plan_t::source_table_loader<const OT::cff1>
+{
+ auto operator () (hb_subset_plan_t *plan)
+ HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff1_accel :
+ plan->inprogress_accelerator ? plan->inprogress_accelerator->cff1_accel :
+ plan->cff1_accel)
+};
+template<>
+struct hb_subset_plan_t::source_table_loader<const OT::cff2>
+{
+ auto operator () (hb_subset_plan_t *plan)
+ HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff2_accel :
+ plan->inprogress_accelerator ? plan->inprogress_accelerator->cff2_accel :
+ plan->cff2_accel)
+};
+#endif
+
+
/**
* SECTION:hb-subset
* @title: hb-subset
@@ -192,15 +214,36 @@ _get_table_tags (const hb_subset_plan_t* plan,
static unsigned
_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
unsigned table_len,
- bool same_size)
+ hb_tag_t table_tag)
{
unsigned src_glyphs = plan->source->get_num_glyphs ();
unsigned dst_glyphs = plan->glyphset ()->get_population ();
+ unsigned bulk = 8192;
+ /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's
+ * because those are expensive to subset, so giving them more room is fine. */
+ bool same_size = table_tag == HB_OT_TAG_GSUB ||
+ table_tag == HB_OT_TAG_GPOS ||
+ table_tag == HB_OT_TAG_name;
+
+ if (plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS)
+ {
+ if (table_tag == HB_OT_TAG_CFF1)
+ {
+ /* Add some extra room for the CFF charset. */
+ bulk += src_glyphs * 16;
+ }
+ else if (table_tag == HB_OT_TAG_CFF2)
+ {
+ /* Just extra CharString offsets. */
+ bulk += src_glyphs * 4;
+ }
+ }
+
if (unlikely (!src_glyphs) || same_size)
- return 512 + table_len;
+ return bulk + table_len;
- return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
+ return bulk + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
}
/*
@@ -231,7 +274,7 @@ _try_subset (const TableType *table,
hb_vector_t<char>* buf,
hb_subset_context_t* c /* OUT */)
{
- c->serializer->start_serialize<TableType> ();
+ c->serializer->start_serialize ();
if (c->serializer->in_error ()) return false;
bool needed = table->subset (c);
@@ -262,45 +305,46 @@ _try_subset (const TableType *table,
return _try_subset (table, buf, c);
}
+template <typename T>
+static auto _do_destroy (T &t, hb_priority<1>) HB_RETURN (void, t.destroy ())
+
+template <typename T>
+static void _do_destroy (T &t, hb_priority<0>) {}
+
template<typename TableType>
static bool
_subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
{
- hb_blob_ptr_t<TableType> source_blob = plan->source_table<TableType> ();
- const TableType *table = source_blob.get ();
+ auto &&source_blob = plan->source_table<TableType> ();
+ auto *table = source_blob.get ();
hb_tag_t tag = TableType::tableTag;
- if (!source_blob.get_blob()->data)
+ hb_blob_t *blob = source_blob.get_blob();
+ if (unlikely (!blob || !blob->data))
{
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
- source_blob.destroy ();
+ _do_destroy (source_blob, hb_prioritize);
return false;
}
- /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's
- * because those are expensive to subset, so giving them more room is fine. */
- bool same_size_table = TableType::tableTag == HB_OT_TAG_GSUB ||
- TableType::tableTag == HB_OT_TAG_GPOS ||
- TableType::tableTag == HB_OT_TAG_name;
-
- unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob.get_length (), same_size_table);
+ unsigned buf_size = _plan_estimate_subset_table_size (plan, blob->length, TableType::tableTag);
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
- source_blob.destroy ();
+ _do_destroy (source_blob, hb_prioritize);
return false;
}
bool needed = false;
hb_serialize_context_t serializer (buf.arrayZ, buf.allocated);
{
- hb_subset_context_t c (source_blob.get_blob (), plan, &serializer, tag);
+ hb_subset_context_t c (blob, plan, &serializer, tag);
needed = _try_subset (table, &buf, &c);
}
- source_blob.destroy ();
+ _do_destroy (source_blob, hb_prioritize);
if (serializer.in_error () && !serializer.only_offset_overflow ())
{
@@ -473,10 +517,11 @@ _subset_table (hb_subset_plan_t *plan,
case HB_OT_TAG_fvar:
if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
return _subset<const OT::fvar> (plan, buf);
+ case HB_OT_TAG_avar:
+ if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
+ return _subset<const OT::avar> (plan, buf);
case HB_OT_TAG_STAT:
- /*TODO(qxliu): change the condition as we support more complex
- * instancing operation*/
- if (plan->all_axes_pinned) return _subset<const OT::STAT> (plan, buf);
+ if (!plan->user_axes_location.is_empty ()) return _subset<const OT::STAT> (plan, buf);
else return _passthrough (plan, tag);
case HB_TAG ('c', 'v', 't', ' '):
@@ -587,46 +632,49 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
offset += num_tables;
}
- hb_vector_t<char> buf;
- buf.alloc (4096 - 16);
-
-
bool success = true;
- while (!pending_subset_tags.is_empty ())
{
- if (subsetted_tags.in_error ()
- || pending_subset_tags.in_error ()) {
- success = false;
- goto end;
- }
+ // Grouping to deallocate buf before calling hb_face_reference (plan->dest).
- bool made_changes = false;
- for (hb_tag_t tag : pending_subset_tags)
+ hb_vector_t<char> buf;
+ buf.alloc (8192 - 16);
+
+ while (!pending_subset_tags.is_empty ())
{
- if (!_dependencies_satisfied (plan, tag,
- subsetted_tags,
- pending_subset_tags))
- {
- // delayed subsetting for some tables since they might have dependency on other tables
- // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated
- // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values
- continue;
+ if (subsetted_tags.in_error ()
+ || pending_subset_tags.in_error ()) {
+ success = false;
+ goto end;
}
- pending_subset_tags.del (tag);
- subsetted_tags.add (tag);
- made_changes = true;
-
- success = _subset_table (plan, buf, tag);
- if (unlikely (!success)) goto end;
- }
+ bool made_changes = false;
+ for (hb_tag_t tag : pending_subset_tags)
+ {
+ if (!_dependencies_satisfied (plan, tag,
+ subsetted_tags,
+ pending_subset_tags))
+ {
+ // delayed subsetting for some tables since they might have dependency on other tables
+ // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated
+ // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values
+ continue;
+ }
+
+ pending_subset_tags.del (tag);
+ subsetted_tags.add (tag);
+ made_changes = true;
+
+ success = _subset_table (plan, buf, tag);
+ if (unlikely (!success)) goto end;
+ }
- if (!made_changes)
- {
- DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed.");
- success = false;
- goto end;
+ if (!made_changes)
+ {
+ DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed.");
+ success = false;
+ goto end;
+ }
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.h b/src/3rdparty/harfbuzz-ng/src/hb-subset.h
index 6368ff93f0..93f1f7f10c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.h
@@ -177,6 +177,13 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
#ifdef HB_EXPERIMENTAL_API
HB_EXTERN hb_bool_t
+hb_subset_input_set_axis_range (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag,
+ float axis_min_value,
+ float axis_max_value);
+
+HB_EXTERN hb_bool_t
hb_subset_input_override_name_table (hb_subset_input_t *input,
hb_ot_name_id_t name_id,
unsigned platform_id,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc b/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc
index 9648e02663..1b8ac367e1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc
@@ -699,7 +699,7 @@ retry:
script_tags,
&item_count);
if (unlikely (FAILED (hr)))
- FAIL ("ScriptItemizeOpenType() failed: 0x%08lx", hr);
+ FAIL ("ScriptItemizeOpenType() failed: 0x%08lx", (unsigned long) hr);
#undef MAX_ITEMS
@@ -785,7 +785,7 @@ retry:
}
if (unlikely (FAILED (hr)))
{
- FAIL ("ScriptShapeOpenType() failed: 0x%08lx", hr);
+ FAIL ("ScriptShapeOpenType() failed: 0x%08lx", (unsigned long) hr);
}
for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
@@ -811,7 +811,7 @@ retry:
offsets + glyphs_offset,
nullptr);
if (unlikely (FAILED (hr)))
- FAIL ("ScriptPlaceOpenType() failed: 0x%08lx", hr);
+ FAIL ("ScriptPlaceOpenType() failed: 0x%08lx", (unsigned long) hr);
if (DEBUG_ENABLED (UNISCRIBE))
fprintf (stderr, "Item %d RTL %d LayoutRTL %d LogicalOrder %d ScriptTag %c%c%c%c\n",
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
index d61ce48c01..23a96d7081 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
@@ -54,7 +54,7 @@ struct hb_vector_t
hb_vector_t (const Iterable &o) : hb_vector_t ()
{
auto iter = hb_iter (o);
- if (iter.is_random_access_iterator)
+ if (iter.is_random_access_iterator || iter.has_fast_len)
alloc (hb_len (iter), true);
hb_copy (iter, *this);
}
@@ -62,7 +62,19 @@ struct hb_vector_t
{
alloc (o.length, true);
if (unlikely (in_error ())) return;
- copy_vector (o);
+ copy_array (o.as_array ());
+ }
+ hb_vector_t (array_t o) : hb_vector_t ()
+ {
+ alloc (o.length, true);
+ if (unlikely (in_error ())) return;
+ copy_array (o);
+ }
+ hb_vector_t (c_array_t o) : hb_vector_t ()
+ {
+ alloc (o.length, true);
+ if (unlikely (in_error ())) return;
+ copy_array (o);
}
hb_vector_t (hb_vector_t &&o)
{
@@ -74,7 +86,7 @@ struct hb_vector_t
~hb_vector_t () { fini (); }
public:
- int allocated = 0; /* == -1 means allocation failed. */
+ int allocated = 0; /* < 0 means allocation failed. */
unsigned int length = 0;
public:
Type *arrayZ = nullptr;
@@ -90,19 +102,21 @@ struct hb_vector_t
void fini ()
{
- shrink_vector (0);
- hb_free (arrayZ);
+ /* We allow a hack to make the vector point to a foriegn array
+ * by the user. In that case length/arrayZ are non-zero but
+ * allocated is zero. Don't free anything. */
+ if (allocated)
+ {
+ shrink_vector (0);
+ hb_free (arrayZ);
+ }
init ();
}
void reset ()
{
if (unlikely (in_error ()))
- /* Big Hack! We don't know the true allocated size before
- * an allocation failure happened. But we know it was at
- * least as big as length. Restore it to that and continue
- * as if error did not happen. */
- allocated = length;
+ reset_error ();
resize (0);
}
@@ -119,7 +133,7 @@ struct hb_vector_t
alloc (o.length, true);
if (unlikely (in_error ())) return *this;
- copy_vector (o);
+ copy_array (o.as_array ());
return *this;
}
@@ -191,7 +205,7 @@ struct hb_vector_t
Type *push ()
{
if (unlikely (!resize (length + 1)))
- return &Crap (Type);
+ return std::addressof (Crap (Type));
return std::addressof (arrayZ[length - 1]);
}
template <typename T,
@@ -201,7 +215,7 @@ struct hb_vector_t
Type *push (T&& v)
{
Type *p = push ();
- if (p == &Crap (Type))
+ if (p == std::addressof (Crap (Type)))
// If push failed to allocate then don't copy v, since this may cause
// the created copy to leak memory since we won't have stored a
// reference to it.
@@ -214,24 +228,33 @@ struct hb_vector_t
hb_enable_if (std::is_copy_constructible<T2>::value)>
Type *push (T&& v)
{
- if (unlikely (!alloc (length + 1)))
+ if (unlikely ((int) length >= allocated && !alloc (length + 1)))
// If push failed to allocate then don't copy v, since this may cause
// the created copy to leak memory since we won't have stored a
// reference to it.
- return &Crap (Type);
+ return std::addressof (Crap (Type));
/* Emplace. */
- length++;
- Type *p = std::addressof (arrayZ[length - 1]);
+ Type *p = std::addressof (arrayZ[length++]);
return new (p) Type (std::forward<T> (v));
}
bool in_error () const { return allocated < 0; }
+ void set_error ()
+ {
+ assert (allocated >= 0);
+ allocated = -allocated - 1;
+ }
+ void reset_error ()
+ {
+ assert (allocated < 0);
+ allocated = -(allocated + 1);
+ }
template <typename T = Type,
hb_enable_if (hb_is_trivially_copy_assignable(T))>
Type *
- realloc_vector (unsigned new_allocated)
+ realloc_vector (unsigned new_allocated, hb_priority<0>)
{
if (!new_allocated)
{
@@ -243,7 +266,7 @@ struct hb_vector_t
template <typename T = Type,
hb_enable_if (!hb_is_trivially_copy_assignable(T))>
Type *
- realloc_vector (unsigned new_allocated)
+ realloc_vector (unsigned new_allocated, hb_priority<0>)
{
if (!new_allocated)
{
@@ -263,31 +286,52 @@ struct hb_vector_t
}
return new_array;
}
+ /* Specialization for hb_vector_t<hb_{vector,array}_t<U>> to speed up. */
+ template <typename T = Type,
+ hb_enable_if (hb_is_same (T, hb_vector_t<typename T::item_t>) ||
+ hb_is_same (T, hb_array_t <typename T::item_t>))>
+ Type *
+ realloc_vector (unsigned new_allocated, hb_priority<1>)
+ {
+ if (!new_allocated)
+ {
+ hb_free (arrayZ);
+ return nullptr;
+ }
+ return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
+ }
template <typename T = Type,
hb_enable_if (hb_is_trivially_constructible(T))>
void
- grow_vector (unsigned size)
+ grow_vector (unsigned size, hb_priority<0>)
{
- memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
+ hb_memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
length = size;
}
template <typename T = Type,
hb_enable_if (!hb_is_trivially_constructible(T))>
void
- grow_vector (unsigned size)
+ grow_vector (unsigned size, hb_priority<0>)
{
- while (length < size)
- {
- length++;
- new (std::addressof (arrayZ[length - 1])) Type ();
- }
+ for (; length < size; length++)
+ new (std::addressof (arrayZ[length])) Type ();
+ }
+ /* Specialization for hb_vector_t<hb_{vector,array}_t<U>> to speed up. */
+ template <typename T = Type,
+ hb_enable_if (hb_is_same (T, hb_vector_t<typename T::item_t>) ||
+ hb_is_same (T, hb_array_t <typename T::item_t>))>
+ void
+ grow_vector (unsigned size, hb_priority<1>)
+ {
+ hb_memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
+ length = size;
}
template <typename T = Type,
hb_enable_if (hb_is_trivially_copyable (T))>
void
- copy_vector (const hb_vector_t &other)
+ copy_array (hb_array_t<const Type> other)
{
length = other.length;
if (!HB_OPTIMIZE_SIZE_VAL && sizeof (T) >= sizeof (long long))
@@ -301,7 +345,7 @@ struct hb_vector_t
hb_enable_if (!hb_is_trivially_copyable (T) &&
std::is_copy_constructible<T>::value)>
void
- copy_vector (const hb_vector_t &other)
+ copy_array (hb_array_t<const Type> other)
{
length = 0;
while (length < other.length)
@@ -316,7 +360,7 @@ struct hb_vector_t
std::is_default_constructible<T>::value &&
std::is_copy_assignable<T>::value)>
void
- copy_vector (const hb_vector_t &other)
+ copy_array (hb_array_t<const Type> other)
{
length = 0;
while (length < other.length)
@@ -330,11 +374,15 @@ struct hb_vector_t
void
shrink_vector (unsigned size)
{
- while ((unsigned) length > size)
+ assert (size <= length);
+ if (!std::is_trivially_destructible<Type>::value)
{
- arrayZ[(unsigned) length - 1].~Type ();
- length--;
+ unsigned count = length - size;
+ Type *p = arrayZ + length - 1;
+ while (count--)
+ p--->~Type ();
}
+ length = size;
}
void
@@ -381,18 +429,18 @@ struct hb_vector_t
if (unlikely (overflows))
{
- allocated = -1;
+ set_error ();
return false;
}
- Type *new_array = realloc_vector (new_allocated);
+ Type *new_array = realloc_vector (new_allocated, hb_prioritize);
if (unlikely (new_allocated && !new_array))
{
if (new_allocated <= (unsigned) allocated)
return true; // shrinking failed; it's okay; happens in our fuzzer
- allocated = -1;
+ set_error ();
return false;
}
@@ -411,7 +459,7 @@ struct hb_vector_t
if (size > length)
{
if (initialize)
- grow_vector (size);
+ grow_vector (size, hb_prioritize);
}
else if (size < length)
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-version.h b/src/3rdparty/harfbuzz-ng/src/hb-version.h
index 08d1f55a35..773395fb25 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-version.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-version.h
@@ -41,26 +41,26 @@ HB_BEGIN_DECLS
*
* The major component of the library version available at compile-time.
*/
-#define HB_VERSION_MAJOR 7
+#define HB_VERSION_MAJOR 8
/**
* HB_VERSION_MINOR:
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 3
+#define HB_VERSION_MINOR 1
/**
* HB_VERSION_MICRO:
*
* The micro component of the library version available at compile-time.
*/
-#define HB_VERSION_MICRO 0
+#define HB_VERSION_MICRO 1
/**
* HB_VERSION_STRING:
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "7.3.0"
+#define HB_VERSION_STRING "8.1.1"
/**
* HB_VERSION_ATLEAST:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-blob.hh b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-blob.hh
new file mode 100644
index 0000000000..310f4023fc
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-blob.hh
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_BLOB_HH
+#define HB_WASM_API_BLOB_HH
+
+#include "hb-wasm-api.hh"
+
+namespace hb {
+namespace wasm {
+
+
+HB_WASM_API (void, blob_free) (HB_WASM_EXEC_ENV
+ ptr_d(blob_t, blob))
+{
+ HB_PTR_PARAM (blob_t, blob);
+ if (unlikely (!blob))
+ return;
+
+ module_free (blob->data);
+
+ blob->data = nullref;
+ blob->length = 0;
+}
+
+
+}}
+
+#endif /* HB_WASM_API_BLOB_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-buffer.hh b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-buffer.hh
new file mode 100644
index 0000000000..64217a041f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-buffer.hh
@@ -0,0 +1,217 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_BUFFER_HH
+#define HB_WASM_API_BUFFER_HH
+
+#include "hb-wasm-api.hh"
+
+#include "hb-buffer.hh"
+
+namespace hb {
+namespace wasm {
+
+static_assert (sizeof (glyph_info_t) == sizeof (hb_glyph_info_t), "");
+static_assert (sizeof (glyph_position_t) == sizeof (hb_glyph_position_t), "");
+
+HB_WASM_API (bool_t, buffer_contents_realloc) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_contents_t, contents),
+ uint32_t size)
+{
+ HB_PTR_PARAM (buffer_contents_t, contents);
+ if (unlikely (!contents))
+ return false;
+
+ if (size <= contents->length)
+ return true;
+
+ unsigned bytes;
+ if (hb_unsigned_mul_overflows (size, sizeof (glyph_info_t), &bytes))
+ return false;
+
+ glyph_info_t *info = HB_ARRAY_APP2NATIVE (glyph_info_t, contents->info, contents->length);
+ glyph_position_t *pos = HB_ARRAY_APP2NATIVE (glyph_position_t, contents->pos, contents->length);
+
+ if (unlikely (!info || !pos))
+ return false;
+
+ glyph_info_t *new_info = nullptr;
+ uint32_t new_inforef = module_malloc (bytes, (void **) &new_info);
+ glyph_position_t *new_pos = nullptr;
+ uint32_t new_posref = module_malloc (bytes, (void **) &new_pos);
+
+ unsigned old_bytes = contents->length * sizeof (glyph_info_t);
+ if (likely (new_inforef))
+ {
+ hb_memcpy (new_info, info, old_bytes);
+ module_free (contents->info);
+ contents->info = new_inforef;
+ }
+ if (likely (new_posref))
+ {
+ hb_memcpy (new_pos, pos, old_bytes);
+ module_free (contents->pos);
+ contents->pos = new_posref;
+ }
+
+ if (likely (new_info && new_pos))
+ {
+ contents->length = size;
+ return true;
+ }
+
+ return false;
+}
+
+HB_WASM_API (void, buffer_contents_free) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_contents_t, contents))
+{
+ HB_PTR_PARAM (buffer_contents_t, contents);
+ if (unlikely (!contents))
+ return;
+
+ module_free (contents->info);
+ module_free (contents->pos);
+
+ contents->info = nullref;
+ contents->pos = nullref;
+ contents->length = 0;
+}
+
+HB_WASM_API (bool_t, buffer_copy_contents) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer),
+ ptr_d(buffer_contents_t, contents))
+{
+ HB_REF2OBJ (buffer);
+ HB_PTR_PARAM (buffer_contents_t, contents);
+ if (unlikely (!contents))
+ return false;
+
+ if (buffer->have_output)
+ buffer->sync ();
+ if (!buffer->have_positions)
+ buffer->clear_positions ();
+
+ unsigned length = buffer->len;
+
+ if (length <= contents->length)
+ {
+ glyph_info_t *info = HB_ARRAY_APP2NATIVE (glyph_info_t, contents->info, length);
+ glyph_position_t *pos = HB_ARRAY_APP2NATIVE (glyph_position_t, contents->pos, length);
+
+ if (unlikely (!info || !pos))
+ {
+ contents->length = 0;
+ return false;
+ }
+
+ unsigned bytes = length * sizeof (hb_glyph_info_t);
+ hb_memcpy (info, buffer->info, bytes);
+ hb_memcpy (pos, buffer->pos, bytes);
+
+ return true;
+ }
+
+ module_free (contents->info);
+ module_free (contents->pos);
+
+ contents->length = length;
+ unsigned bytes = length * sizeof (hb_glyph_info_t);
+ contents->info = wasm_runtime_module_dup_data (module_inst, (const char *) buffer->info, bytes);
+ contents->pos = wasm_runtime_module_dup_data (module_inst, (const char *) buffer->pos, bytes);
+
+ if (length && (!contents->info || !contents->pos))
+ {
+ contents->length = 0;
+ return false;
+ }
+
+ return true;
+}
+
+HB_WASM_API (bool_t, buffer_set_contents) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer),
+ ptr_d(const buffer_contents_t, contents))
+{
+ HB_REF2OBJ (buffer);
+ HB_PTR_PARAM (buffer_contents_t, contents);
+ if (unlikely (!contents))
+ return false;
+
+ unsigned length = contents->length;
+ unsigned bytes;
+ if (unlikely (hb_unsigned_mul_overflows (length, sizeof (buffer->info[0]), &bytes)))
+ return false;
+
+ if (unlikely (!buffer->resize (length)))
+ return false;
+
+ glyph_info_t *info = (glyph_info_t *) (validate_app_addr (contents->info, bytes) ? addr_app_to_native (contents->info) : nullptr);
+ glyph_position_t *pos = (glyph_position_t *) (validate_app_addr (contents->pos, bytes) ? addr_app_to_native (contents->pos) : nullptr);
+
+ if (!buffer->have_positions)
+ buffer->clear_positions (); /* This is wasteful. */
+
+ hb_memcpy (buffer->info, info, bytes);
+ hb_memcpy (buffer->pos, pos, bytes);
+ buffer->len = length;
+
+ return true;
+}
+
+HB_WASM_API (direction_t, buffer_get_direction) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer))
+{
+ HB_REF2OBJ (buffer);
+
+ return (direction_t) hb_buffer_get_direction (buffer);
+}
+
+HB_WASM_API (script_t, buffer_get_script) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer))
+{
+ HB_REF2OBJ (buffer);
+
+ return hb_script_to_iso15924_tag (hb_buffer_get_script (buffer));
+}
+
+HB_WASM_API (void, buffer_reverse) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer))
+{
+ HB_REF2OBJ (buffer);
+
+ hb_buffer_reverse (buffer);
+}
+
+HB_WASM_API (void, buffer_reverse_clusters) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer))
+{
+ HB_REF2OBJ (buffer);
+
+ hb_buffer_reverse_clusters (buffer);
+}
+
+}}
+
+#endif /* HB_WASM_API_BUFFER_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.hh b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-common.hh
index f10556ddd7..c38ca9cedd 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-common.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2018 Adobe Inc.
+ * Copyright © 2023 Behdad Esfahbod
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -20,18 +20,25 @@
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Adobe Author(s): Michiharu Ariza
*/
-#ifndef HB_SUBSET_CFF2_HH
-#define HB_SUBSET_CFF2_HH
+#ifndef HB_WASM_API_COMMON_HH
+#define HB_WASM_API_COMMON_HH
+
+#include "hb-wasm-api.hh"
+
+namespace hb {
+namespace wasm {
+
-#include "hb.hh"
+HB_WASM_API (direction_t, script_get_horizontal_direction) (HB_WASM_EXEC_ENV
+ script_t script)
+{
+ return (direction_t)
+ hb_script_get_horizontal_direction (hb_script_from_iso15924_tag (script));
+}
-#include "hb-subset-plan.hh"
-HB_INTERNAL bool
-hb_subset_cff2 (hb_subset_context_t *c);
+}}
-#endif /* HB_SUBSET_CFF2_HH */
+#endif /* HB_WASM_API_COMMON_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-face.hh b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-face.hh
new file mode 100644
index 0000000000..22e50e9446
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-face.hh
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_FACE_HH
+#define HB_WASM_API_FACE_HH
+
+#include "hb-wasm-api.hh"
+
+namespace hb {
+namespace wasm {
+
+
+HB_WASM_API (ptr_t(face_t), face_create) (HB_WASM_EXEC_ENV
+ ptr_d(blob_t, blob),
+ unsigned int index)
+{
+ HB_PTR_PARAM (blob_t, blob);
+ hb_blob_t *hb_blob = hb_blob_create(
+ HB_ARRAY_APP2NATIVE (char, blob->data, blob->length),
+ blob->length,
+ HB_MEMORY_MODE_DUPLICATE,
+ NULL,
+ NULL);
+
+ hb_face_t *face = hb_face_create(hb_blob, index);
+
+ HB_OBJ2REF (face);
+ return faceref;
+}
+
+HB_WASM_API (bool_t, face_copy_table) (HB_WASM_EXEC_ENV
+ ptr_d(face_t, face),
+ tag_t table_tag,
+ ptr_d(blob_t, blob))
+{
+ HB_REF2OBJ (face);
+ HB_PTR_PARAM (blob_t, blob);
+ if (unlikely (!blob))
+ return false;
+
+ hb_blob_t *hb_blob = hb_face_reference_table (face, table_tag);
+
+ unsigned length;
+ const char *hb_data = hb_blob_get_data (hb_blob, &length);
+
+ if (length <= blob->length)
+ {
+ char *data = HB_ARRAY_APP2NATIVE (char, blob->data, length);
+
+ if (unlikely (!data))
+ {
+ blob->length = 0;
+ return false;
+ }
+
+ hb_memcpy (data, hb_data, length);
+
+ return true;
+ }
+
+ module_free (blob->data);
+
+ blob->length = length;
+ blob->data = wasm_runtime_module_dup_data (module_inst, hb_data, length);
+
+ hb_blob_destroy (hb_blob);
+
+ if (blob->length && !blob->data)
+ {
+ blob->length = 0;
+ return false;
+ }
+
+ return true;
+}
+
+HB_WASM_API (unsigned, face_get_upem) (HB_WASM_EXEC_ENV
+ ptr_d(face_t, face))
+{
+ HB_REF2OBJ (face);
+
+ return hb_face_get_upem (face);
+}
+
+
+}}
+
+#endif /* HB_WASM_API_FACE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-font.hh b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-font.hh
new file mode 100644
index 0000000000..2d85db4aac
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-font.hh
@@ -0,0 +1,263 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_FONT_HH
+#define HB_WASM_API_FONT_HH
+
+#include "hb-wasm-api.hh"
+
+#include "hb-outline.hh"
+
+namespace hb {
+namespace wasm {
+
+
+HB_WASM_API (ptr_t(font_t), font_create) (HB_WASM_EXEC_ENV
+ ptr_d(face_t, face))
+{
+ HB_REF2OBJ (face);
+
+ hb_font_t *font = hb_font_create (face);
+
+ HB_OBJ2REF (font);
+ return fontref;
+}
+
+HB_WASM_API (ptr_t(face_t), font_get_face) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font))
+{
+ HB_REF2OBJ (font);
+
+ hb_face_t *face = hb_font_get_face (font);
+
+ HB_OBJ2REF (face);
+ return faceref;
+}
+
+HB_WASM_API (void, font_get_scale) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ ptr_d(int32_t, x_scale),
+ ptr_d(int32_t, y_scale))
+{
+ HB_REF2OBJ (font);
+
+ HB_PTR_PARAM(int32_t, x_scale);
+ HB_PTR_PARAM(int32_t, y_scale);
+
+ hb_font_get_scale (font, x_scale, y_scale);
+}
+
+HB_WASM_API (codepoint_t, font_get_glyph) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t unicode,
+ codepoint_t variation_selector)
+{
+ HB_REF2OBJ (font);
+ codepoint_t glyph;
+
+ hb_font_get_glyph (font, unicode, variation_selector, &glyph);
+ return glyph;
+}
+
+HB_WASM_API (position_t, font_get_glyph_h_advance) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph)
+{
+ HB_REF2OBJ (font);
+ return hb_font_get_glyph_h_advance (font, glyph);
+}
+
+HB_WASM_API (position_t, font_get_glyph_v_advance) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph)
+{
+ HB_REF2OBJ (font);
+ return hb_font_get_glyph_v_advance (font, glyph);
+}
+
+static_assert (sizeof (glyph_extents_t) == sizeof (hb_glyph_extents_t), "");
+
+HB_WASM_API (bool_t, font_get_glyph_extents) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph,
+ ptr_d(glyph_extents_t, extents))
+{
+ HB_REF2OBJ (font);
+ HB_PTR_PARAM (glyph_extents_t, extents);
+ if (unlikely (!extents))
+ return false;
+
+ return hb_font_get_glyph_extents (font, glyph,
+ (hb_glyph_extents_t *) extents);
+}
+
+HB_WASM_API (void, font_glyph_to_string) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph,
+ char *s, uint32_t size)
+{
+ HB_REF2OBJ (font);
+
+ hb_font_glyph_to_string (font, glyph, s, size);
+}
+
+static_assert (sizeof (glyph_outline_point_t) == sizeof (hb_outline_point_t), "");
+static_assert (sizeof (uint32_t) == sizeof (hb_outline_t::contours[0]), "");
+
+HB_WASM_API (bool_t, font_copy_glyph_outline) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph,
+ ptr_d(glyph_outline_t, outline))
+{
+ HB_REF2OBJ (font);
+ HB_PTR_PARAM (glyph_outline_t, outline);
+ if (unlikely (!outline))
+ return false;
+
+ hb_outline_t hb_outline;
+ auto *funcs = hb_outline_recording_pen_get_funcs ();
+
+ hb_font_draw_glyph (font, glyph, funcs, &hb_outline);
+
+ if (unlikely (hb_outline.points.in_error () ||
+ hb_outline.contours.in_error ()))
+ {
+ outline->n_points = outline->n_contours = 0;
+ return false;
+ }
+
+ // TODO Check two buffers separately
+ if (hb_outline.points.length <= outline->n_points &&
+ hb_outline.contours.length <= outline->n_contours)
+ {
+ glyph_outline_point_t *points = HB_ARRAY_APP2NATIVE (glyph_outline_point_t, outline->points, hb_outline.points.length);
+ uint32_t *contours = HB_ARRAY_APP2NATIVE (uint32_t, outline->contours, hb_outline.contours.length);
+
+ if (unlikely (!points || !contours))
+ {
+ outline->n_points = outline->n_contours = 0;
+ return false;
+ }
+
+ hb_memcpy (points, hb_outline.points.arrayZ, hb_outline.points.get_size ());
+ hb_memcpy (contours, hb_outline.contours.arrayZ, hb_outline.contours.get_size ());
+
+ return true;
+ }
+
+ outline->n_points = hb_outline.points.length;
+ outline->points = wasm_runtime_module_dup_data (module_inst,
+ (const char *) hb_outline.points.arrayZ,
+ hb_outline.points.get_size ());
+ outline->n_contours = hb_outline.contours.length;
+ outline->contours = wasm_runtime_module_dup_data (module_inst,
+ (const char *) hb_outline.contours.arrayZ,
+ hb_outline.contours.get_size ());
+
+ if ((outline->n_points && !outline->points) ||
+ (!outline->n_contours && !outline->contours))
+ {
+ outline->n_points = outline->n_contours = 0;
+ return false;
+ }
+
+ return true;
+}
+
+HB_WASM_API (void, glyph_outline_free) (HB_WASM_EXEC_ENV
+ ptr_d(glyph_outline_t, outline))
+{
+ HB_PTR_PARAM (glyph_outline_t, outline);
+ if (unlikely (!outline))
+ return;
+
+ module_free (outline->points);
+ module_free (outline->contours);
+
+ outline->n_points = 0;
+ outline->points = nullref;
+ outline->n_contours = 0;
+ outline->contours = nullref;
+}
+
+HB_WASM_API (bool_t, font_copy_coords) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ ptr_d(coords_t, coords))
+{
+ HB_REF2OBJ (font);
+ HB_PTR_PARAM (coords_t, coords);
+ if (unlikely (!coords))
+ return false;
+
+ unsigned our_length;
+ const int* our_coords = hb_font_get_var_coords_normalized(font, &our_length);
+
+ if (our_length <= coords->length) {
+ int *their_coords = HB_ARRAY_APP2NATIVE (int, coords->coords, our_length);
+ if (unlikely(!their_coords)) {
+ coords->length = 0;
+ return false;
+ }
+ unsigned bytes = our_length * sizeof (int);
+ hb_memcpy (their_coords, our_coords, bytes);
+
+ return true;
+ }
+
+ module_free (coords->coords);
+ coords->length = our_length;
+ unsigned bytes = our_length * sizeof (int);
+ coords->coords = wasm_runtime_module_dup_data (module_inst, (const char *) our_coords, bytes);
+ if (our_length && !coords->coords)
+ {
+ coords->length = 0;
+ return false;
+ }
+
+ return true;
+}
+
+HB_WASM_API (bool_t, font_set_coords) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ ptr_d(coords_t, coords))
+{
+ HB_REF2OBJ (font);
+ HB_PTR_PARAM (coords_t, coords);
+ if (unlikely (!coords))
+ return false;
+
+ unsigned length = coords->length;
+ unsigned bytes;
+ if (unlikely (hb_unsigned_mul_overflows (length, sizeof (int), &bytes)))
+ return false;
+
+ const int *our_coords = (const int *) (validate_app_addr (coords->coords, bytes) ? addr_app_to_native (coords->coords) : nullptr);
+ hb_font_set_var_coords_normalized(font, our_coords, length);
+ return true;
+}
+
+
+}}
+
+#endif /* HB_WASM_API_FONT_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-shape.hh b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-shape.hh
new file mode 100644
index 0000000000..622ff052b2
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api-shape.hh
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_SHAPE_HH
+#define HB_WASM_API_SHAPE_HH
+
+#include "hb-wasm-api.hh"
+
+namespace hb {
+namespace wasm {
+
+
+static_assert (sizeof (feature_t) == sizeof (hb_feature_t), "");
+
+HB_WASM_INTERFACE (bool_t, shape_with) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ ptr_d(buffer_t, buffer),
+ ptr_d(const feature_t, features),
+ uint32_t num_features,
+ const char *shaper)
+{
+ if (unlikely (0 == strcmp (shaper, "wasm")))
+ return false;
+
+ HB_REF2OBJ (font);
+ HB_REF2OBJ (buffer);
+
+ /* Pre-conditions that make hb_shape_full() crash should be checked here. */
+
+ if (unlikely (!buffer->ensure_unicode ()))
+ return false;
+
+ if (unlikely (!HB_DIRECTION_IS_VALID (buffer->props.direction)))
+ return false;
+
+ HB_ARRAY_PARAM (const feature_t, features, num_features);
+ if (unlikely (!features && num_features))
+ return false;
+
+ const char * shaper_list[] = {shaper, nullptr};
+ return hb_shape_full (font, buffer,
+ (hb_feature_t *) features, num_features,
+ shaper_list);
+}
+
+
+}}
+
+#endif /* HB_WASM_API_SHAPE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.hh b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api.cc
index aaf5def1ed..1da8347a08 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api.cc
@@ -1,5 +1,5 @@
/*
- * Copyright © 2018 Adobe Inc.
+ * Copyright © 2023 Behdad Esfahbod
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -20,18 +20,27 @@
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Adobe Author(s): Michiharu Ariza
*/
-#ifndef HB_SUBSET_CFF1_HH
-#define HB_SUBSET_CFF1_HH
-
#include "hb.hh"
-#include "hb-subset-plan.hh"
+#ifdef HAVE_WASM
+
+#include "hb-wasm-api.hh"
+
+#define module_inst wasm_runtime_get_module_inst (exec_env)
+
+
+#include "hb-wasm-api-blob.hh"
+#include "hb-wasm-api-buffer.hh"
+#include "hb-wasm-api-common.hh"
+#include "hb-wasm-api-face.hh"
+#include "hb-wasm-api-font.hh"
+#include "hb-wasm-api-shape.hh"
+
+
+#undef module_inst
-HB_INTERNAL bool
-hb_subset_cff1 (hb_subset_context_t *c);
+hb_user_data_key_t _hb_wasm_ref_type_key = {};
-#endif /* HB_SUBSET_CFF1_HH */
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-wasm-api.h b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api.h
new file mode 100644
index 0000000000..f9bd98e5ea
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api.h
@@ -0,0 +1,319 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_H
+#define HB_WASM_API_H
+
+/*
+#include "hb.h"
+*/
+
+#include <stdint.h>
+
+
+#ifndef HB_WASM_BEGIN_DECLS
+# ifdef __cplusplus
+# define HB_WASM_BEGIN_DECLS extern "C" {
+# define HB_WASM_END_DECLS }
+# else /* !__cplusplus */
+# define HB_WASM_BEGIN_DECLS
+# define HB_WASM_END_DECLS
+# endif /* !__cplusplus */
+#endif
+
+
+HB_WASM_BEGIN_DECLS
+
+#ifndef HB_WASM_API
+#define HB_WASM_API(ret_t, name) ret_t name
+#endif
+#ifndef HB_WASM_API_COMPOUND /* compound return type */
+#define HB_WASM_API_COMPOUND(ret_t, name) HB_WASM_API(ret_t, name)
+#endif
+#ifndef HB_WASM_INTERFACE
+#define HB_WASM_INTERFACE(ret_t, name) ret_t name
+#endif
+#ifndef HB_WASM_EXEC_ENV
+#define HB_WASM_EXEC_ENV
+#endif
+#ifndef HB_WASM_EXEC_ENV_COMPOUND
+#define HB_WASM_EXEC_ENV_COMPOUND HB_WASM_EXEC_ENV
+#endif
+
+
+#ifndef bool_t
+#define bool_t uint32_t
+#endif
+#ifndef ptr_t
+#define ptr_t(type_t) type_t *
+#endif
+#ifndef ptr_d
+#define ptr_d(type_t, name) type_t *name
+#endif
+
+typedef uint32_t codepoint_t;
+typedef int32_t position_t;
+typedef uint32_t mask_t;
+typedef uint32_t tag_t;
+#define TAG(c1,c2,c3,c4) ((tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF)))
+
+typedef enum {
+ DIRECTION_INVALID = 0,
+ DIRECTION_LTR = 4,
+ DIRECTION_RTL,
+ DIRECTION_TTB,
+ DIRECTION_BTT
+} direction_t;
+#define DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4)
+#define DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 4)
+#define DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 6)
+#define DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 4)
+#define DIRECTION_IS_BACKWARD(dir) ((((unsigned int) (dir)) & ~2U) == 5)
+#define DIRECTION_REVERSE(dir) ((direction_t) (((unsigned int) (dir)) ^ 1))
+
+typedef tag_t script_t; /* ISO 15924 representation of Unicode scripts. */
+
+
+/* common */
+
+HB_WASM_API (direction_t, script_get_horizontal_direction) (HB_WASM_EXEC_ENV
+ script_t script);
+
+
+/* blob */
+
+typedef struct
+{
+ uint32_t length;
+ ptr_t(char) data;
+} blob_t;
+#define BLOB_INIT {0, 0}
+
+HB_WASM_API (void, blob_free) (HB_WASM_EXEC_ENV
+ ptr_d(blob_t, blob));
+
+/* buffer */
+
+typedef struct
+{
+ uint32_t codepoint;
+ uint32_t mask;
+ uint32_t cluster;
+ uint32_t var1;
+ uint32_t var2;
+} glyph_info_t;
+
+typedef struct
+{
+ position_t x_advance;
+ position_t y_advance;
+ position_t x_offset;
+ position_t y_offset;
+ uint32_t var;
+} glyph_position_t;
+
+typedef struct
+{
+ uint32_t length;
+ ptr_t(glyph_info_t) info;
+ ptr_t(glyph_position_t) pos;
+} buffer_contents_t;
+#define BUFFER_CONTENTS_INIT {0, 0, 0}
+
+HB_WASM_API (bool_t, buffer_contents_realloc) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_contents_t, contents),
+ uint32_t size);
+
+HB_WASM_API (void, buffer_contents_free) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_contents_t, contents));
+
+typedef struct buffer_t buffer_t;
+
+HB_WASM_API (bool_t, buffer_copy_contents) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer),
+ ptr_d(buffer_contents_t, contents));
+
+HB_WASM_API (bool_t, buffer_set_contents) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer),
+ ptr_d(const buffer_contents_t, contents));
+
+HB_WASM_API (direction_t, buffer_get_direction) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer));
+
+HB_WASM_API (script_t, buffer_get_script) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer));
+
+HB_WASM_API (void, buffer_reverse) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer));
+
+HB_WASM_API (void, buffer_reverse_clusters) (HB_WASM_EXEC_ENV
+ ptr_d(buffer_t, buffer));
+
+/* face */
+
+typedef struct face_t face_t;
+
+HB_WASM_API (ptr_t(face_t), face_create) (HB_WASM_EXEC_ENV
+ ptr_d(blob_t, blob),
+ unsigned int);
+
+HB_WASM_API (bool_t, face_copy_table) (HB_WASM_EXEC_ENV
+ ptr_d(face_t, face),
+ tag_t table_tag,
+ ptr_d(blob_t, blob));
+
+HB_WASM_API (unsigned, face_get_upem) (HB_WASM_EXEC_ENV
+ ptr_d(face_t, face));
+
+/* font */
+
+typedef struct font_t font_t;
+
+HB_WASM_API (ptr_t(font_t), font_create) (HB_WASM_EXEC_ENV
+ ptr_d(face_t, face));
+
+HB_WASM_API (ptr_t(face_t), font_get_face) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font));
+
+HB_WASM_API (void, font_get_scale) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ ptr_d(int32_t, x_scale),
+ ptr_d(int32_t, y_scale));
+
+HB_WASM_API (codepoint_t, font_get_glyph) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t unicode,
+ codepoint_t variation_selector);
+
+HB_WASM_API (position_t, font_get_glyph_h_advance) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph);
+
+HB_WASM_API (position_t, font_get_glyph_v_advance) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph);
+
+typedef struct
+{
+ position_t x_bearing;
+ position_t y_bearing;
+ position_t width;
+ position_t height;
+} glyph_extents_t;
+
+HB_WASM_API (bool_t, font_get_glyph_extents) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph,
+ ptr_d(glyph_extents_t, extents));
+
+HB_WASM_API (void, font_glyph_to_string) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph,
+ char *s, uint32_t size);
+
+
+typedef struct
+{
+ unsigned int length;
+ ptr_t(int) coords;
+} coords_t;
+
+HB_WASM_API (bool_t, font_copy_coords) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ ptr_d(coords_t, coords));
+
+HB_WASM_API (bool_t, font_set_coords) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ ptr_d(coords_t, coords));
+
+/* outline */
+
+enum glyph_outline_point_type_t
+{
+ MOVE_TO,
+ LINE_TO,
+ QUADRATIC_TO,
+ CUBIC_TO,
+};
+
+typedef struct
+{
+ float x;
+ float y;
+ uint32_t type;
+} glyph_outline_point_t;
+
+typedef struct
+{
+ uint32_t n_points;
+ ptr_t(glyph_outline_point_t) points;
+ uint32_t n_contours;
+ ptr_t(uint32_t) contours;
+} glyph_outline_t;
+#define GLYPH_OUTLINE_INIT {0, 0, 0, 0}
+
+HB_WASM_API (void, glyph_outline_free) (HB_WASM_EXEC_ENV
+ ptr_d(glyph_outline_t, outline));
+
+HB_WASM_API (bool_t, font_copy_glyph_outline) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ codepoint_t glyph,
+ ptr_d(glyph_outline_t, outline));
+
+
+/* shape */
+
+typedef struct
+{
+ tag_t tag;
+ uint32_t value;
+ uint32_t start;
+ uint32_t end;
+} feature_t;
+#define FEATURE_GLOBAL_START 0
+#define FEATURE_GLOBAL_END ((uint32_t) -1)
+
+HB_WASM_API (bool_t, shape_with) (HB_WASM_EXEC_ENV
+ ptr_d(font_t, font),
+ ptr_d(buffer_t, buffer),
+ ptr_d(const feature_t, features),
+ uint32_t num_features,
+ const char *shaper);
+
+/* Implement these in your shaper. */
+
+HB_WASM_INTERFACE (ptr_t(void), shape_plan_create) (ptr_d(face_t, face));
+
+HB_WASM_INTERFACE (bool_t, shape) (ptr_d(void, shape_plan),
+ ptr_d(font_t, font),
+ ptr_d(buffer_t, buffer),
+ ptr_d(const feature_t, features),
+ uint32_t num_features);
+
+HB_WASM_INTERFACE (void, shape_plan_destroy) (ptr_d(void, shape_plan));
+
+
+HB_WASM_END_DECLS
+
+#endif /* HB_WASM_API_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-wasm-api.hh b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api.hh
new file mode 100644
index 0000000000..4ead01c1f7
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-api.hh
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_WASM_API_HH
+#define HB_WASM_API_HH
+
+#include "hb.hh"
+
+#include <wasm_export.h>
+
+#define HB_WASM_BEGIN_DECLS namespace hb { namespace wasm {
+#define HB_WASM_END_DECLS }}
+
+#define HB_WASM_API(ret_t, name) HB_INTERNAL ret_t name
+#define HB_WASM_API_COMPOUND(ret_t, name) HB_INTERNAL void name
+
+#define HB_WASM_EXEC_ENV wasm_exec_env_t exec_env,
+#define HB_WASM_EXEC_ENV_COMPOUND wasm_exec_env_t exec_env, ptr_t() retptr,
+
+#define ptr_t(type_t) uint32_t
+#define ptr_d(type_t, name) uint32_t name##ptr
+
+#include "hb-wasm-api.h"
+
+#undef HB_WASM_BEGIN_DECLS
+#undef HB_WASM_END_DECLS
+
+
+enum {
+ hb_wasm_ref_type_none,
+ hb_wasm_ref_type_face,
+ hb_wasm_ref_type_font,
+ hb_wasm_ref_type_buffer,
+};
+
+HB_INTERNAL extern hb_user_data_key_t _hb_wasm_ref_type_key;
+
+#define nullref 0
+
+#define HB_REF2OBJ(obj) \
+ hb_##obj##_t *obj = nullptr; \
+ HB_STMT_START { \
+ (void) wasm_externref_ref2obj (obj##ptr, (void **) &obj); \
+ /* Check object type. */ \
+ /* This works because all our objects have the same hb_object_t layout. */ \
+ if (unlikely (hb_##obj##_get_user_data (obj, &_hb_wasm_ref_type_key) != \
+ (void *) hb_wasm_ref_type_##obj)) \
+ obj = hb_##obj##_get_empty (); \
+ } HB_STMT_END
+
+#define HB_OBJ2REF(obj) \
+ uint32_t obj##ref = nullref; \
+ HB_STMT_START { \
+ hb_##obj##_set_user_data (obj, &_hb_wasm_ref_type_key, \
+ (void *) hb_wasm_ref_type_##obj, \
+ nullptr, false); \
+ (void) wasm_externref_obj2ref (module_inst, obj, &obj##ref); \
+ } HB_STMT_END
+
+#define HB_RETURN_STRUCT(type, name) \
+ type *_name_ptr = nullptr; \
+ { \
+ if (likely (wasm_runtime_validate_app_addr (module_inst, \
+ retptr, sizeof (type)))) \
+ { \
+ _name_ptr = (type *) wasm_runtime_addr_app_to_native (module_inst, retptr); \
+ if (unlikely (!_name_ptr)) \
+ return; \
+ } \
+ } \
+ type &name = *_name_ptr
+
+#define HB_PTR_PARAM(type, name) \
+ type *name = nullptr; \
+ HB_STMT_START { \
+ if (likely (wasm_runtime_validate_app_addr (module_inst, \
+ name##ptr, sizeof (type)))) \
+ name = (type *) wasm_runtime_addr_app_to_native (module_inst, name##ptr); \
+ } HB_STMT_END
+
+#define HB_ARRAY_PARAM(type, name, length) \
+ type *name = nullptr; \
+ HB_STMT_START { \
+ if (likely (!hb_unsigned_mul_overflows (length, sizeof (type)) && \
+ wasm_runtime_validate_app_addr (module_inst, \
+ name##ptr, length * sizeof (type)))) \
+ name = (type *) wasm_runtime_addr_app_to_native (module_inst, name##ptr); \
+ } HB_STMT_END
+
+#define HB_ARRAY_APP2NATIVE(type, name, length) \
+ ((type *) (!hb_unsigned_mul_overflows (length, sizeof (type)) && \
+ validate_app_addr (name, (length) * sizeof (type)) ? \
+ addr_app_to_native (name) : nullptr))
+
+
+#endif /* HB_WASM_API_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-wasm-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-wasm-shape.cc
new file mode 100644
index 0000000000..79442e99ed
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-wasm-shape.cc
@@ -0,0 +1,470 @@
+/*
+ * Copyright © 2011 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#undef HB_DEBUG_WASM
+#define HB_DEBUG_WASM 1
+
+#include "hb-shaper-impl.hh"
+
+#ifdef HAVE_WASM
+
+/* Compile wasm-micro-runtime with:
+ *
+ * $ cmake -DWAMR_BUILD_MULTI_MODULE=1 -DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_FAST_JIT=1
+ * $ make
+ *
+ * If you manage to build a wasm shared module successfully and want to use it,
+ * do the following:
+ *
+ * - Add -DWAMR_BUILD_MULTI_MODULE=1 to your cmake build for wasm-micro-runtime,
+ *
+ * - Remove the #define HB_WASM_NO_MODULES line below,
+ *
+ * - Install your shared module with name ending in .wasm in
+ * $(prefix)/$(libdir)/harfbuzz/wasm/
+ *
+ * - Build your font's wasm code importing the shared modules with the desired
+ * name. This can be done eg.: __attribute__((import_module("graphite2")))
+ * before each symbol in the the shared-module's headers.
+ *
+ * - Try shaping your font and hope for the best...
+ *
+ * I haven't been able to get this to work since emcc's support for shared libraries
+ * requires support from the host that seems to be missing from wasm-micro-runtime?
+ */
+
+#include "hb-wasm-api.hh"
+#include "hb-wasm-api-list.hh"
+
+#ifndef HB_WASM_NO_MODULES
+#define HB_WASM_NO_MODULES
+#endif
+
+
+#ifndef HB_WASM_NO_MODULES
+static bool HB_UNUSED
+_hb_wasm_module_reader (const char *module_name,
+ uint8_t **p_buffer, uint32_t *p_size)
+{
+ char path[sizeof (HB_WASM_MODULE_DIR) + 64] = HB_WASM_MODULE_DIR "/";
+ strncat (path, module_name, sizeof (path) - sizeof (HB_WASM_MODULE_DIR) - 16);
+ strncat (path, ".wasm", 6);
+
+ auto *blob = hb_blob_create_from_file (path);
+
+ unsigned length;
+ auto *data = hb_blob_get_data (blob, &length);
+
+ *p_buffer = (uint8_t *) hb_malloc (length);
+
+ if (length && !p_buffer)
+ return false;
+
+ memcpy (*p_buffer, data, length);
+ *p_size = length;
+
+ hb_blob_destroy (blob);
+
+ return true;
+}
+
+static void HB_UNUSED
+_hb_wasm_module_destroyer (uint8_t *buffer, uint32_t size)
+{
+ hb_free (buffer);
+}
+#endif
+
+/*
+ * shaper face data
+ */
+
+#define HB_WASM_TAG_WASM HB_TAG('W','a','s','m')
+
+struct hb_wasm_shape_plan_t {
+ wasm_module_inst_t module_inst;
+ wasm_exec_env_t exec_env;
+ ptr_d(void, wasm_shape_plan);
+};
+
+struct hb_wasm_face_data_t {
+ hb_blob_t *wasm_blob;
+ wasm_module_t wasm_module;
+ mutable hb_atomic_ptr_t<hb_wasm_shape_plan_t> plan;
+};
+
+static bool
+_hb_wasm_init ()
+{
+ /* XXX
+ *
+ * Umm. Make this threadsafe. How?!
+ * It's clunky that we can't allocate a static mutex.
+ * So we have to first allocate one on the heap atomically...
+ *
+ * Do we also need to lock around module creation?
+ *
+ * Also, wasm-micro-runtime uses a singleton instance. So if
+ * another library or client uses it, all bets are off. :-(
+ * If nothing else, around HB_REF2OBJ().
+ */
+
+ static bool initialized;
+ if (initialized)
+ return true;
+
+ RuntimeInitArgs init_args;
+ hb_memset (&init_args, 0, sizeof (RuntimeInitArgs));
+
+ init_args.mem_alloc_type = Alloc_With_Allocator;
+ init_args.mem_alloc_option.allocator.malloc_func = (void *) hb_malloc;
+ init_args.mem_alloc_option.allocator.realloc_func = (void *) hb_realloc;
+ init_args.mem_alloc_option.allocator.free_func = (void *) hb_free;
+
+ // Native symbols need below registration phase
+ init_args.n_native_symbols = ARRAY_LENGTH (_hb_wasm_native_symbols);
+ init_args.native_module_name = "env";
+ init_args.native_symbols = _hb_wasm_native_symbols;
+
+ if (unlikely (!wasm_runtime_full_init (&init_args)))
+ {
+ DEBUG_MSG (WASM, nullptr, "Init runtime environment failed.");
+ return false;
+ }
+
+#ifndef HB_WASM_NO_MODULES
+ wasm_runtime_set_module_reader (_hb_wasm_module_reader,
+ _hb_wasm_module_destroyer);
+#endif
+
+ initialized = true;
+ return true;
+}
+
+hb_wasm_face_data_t *
+_hb_wasm_shaper_face_data_create (hb_face_t *face)
+{
+ char error[128];
+ hb_wasm_face_data_t *data = nullptr;
+ hb_blob_t *wasm_blob = nullptr;
+ wasm_module_t wasm_module = nullptr;
+
+ wasm_blob = hb_face_reference_table (face, HB_WASM_TAG_WASM);
+ unsigned length = hb_blob_get_length (wasm_blob);
+ if (!length)
+ goto fail;
+
+ if (!_hb_wasm_init ())
+ goto fail;
+
+ wasm_module = wasm_runtime_load ((uint8_t *) hb_blob_get_data_writable (wasm_blob, nullptr),
+ length, error, sizeof (error));
+ if (unlikely (!wasm_module))
+ {
+ DEBUG_MSG (WASM, nullptr, "Load wasm module failed: %s", error);
+ goto fail;
+ }
+
+ data = (hb_wasm_face_data_t *) hb_calloc (1, sizeof (hb_wasm_face_data_t));
+ if (unlikely (!data))
+ goto fail;
+
+ data->wasm_blob = wasm_blob;
+ data->wasm_module = wasm_module;
+
+ return data;
+
+fail:
+ if (wasm_module)
+ wasm_runtime_unload (wasm_module);
+ hb_blob_destroy (wasm_blob);
+ hb_free (data);
+ return nullptr;
+}
+
+static hb_wasm_shape_plan_t *
+acquire_shape_plan (hb_face_t *face,
+ const hb_wasm_face_data_t *face_data)
+{
+ char error[128];
+
+ /* Fetch cached one if available. */
+ hb_wasm_shape_plan_t *plan = face_data->plan.get_acquire ();
+ if (likely (plan && face_data->plan.cmpexch (plan, nullptr)))
+ return plan;
+
+ plan = (hb_wasm_shape_plan_t *) hb_calloc (1, sizeof (hb_wasm_shape_plan_t));
+
+ wasm_module_inst_t module_inst = nullptr;
+ wasm_exec_env_t exec_env = nullptr;
+ wasm_function_inst_t func = nullptr;
+
+ constexpr uint32_t stack_size = 32 * 1024, heap_size = 2 * 1024 * 1024;
+
+ module_inst = plan->module_inst = wasm_runtime_instantiate (face_data->wasm_module,
+ stack_size, heap_size,
+ error, sizeof (error));
+ if (unlikely (!module_inst))
+ {
+ DEBUG_MSG (WASM, face_data, "Create wasm module instance failed: %s", error);
+ goto fail;
+ }
+
+ exec_env = plan->exec_env = wasm_runtime_create_exec_env (module_inst,
+ stack_size);
+ if (unlikely (!exec_env)) {
+ DEBUG_MSG (WASM, face_data, "Create wasm execution environment failed.");
+ goto fail;
+ }
+
+ func = wasm_runtime_lookup_function (module_inst, "shape_plan_create", nullptr);
+ if (func)
+ {
+ wasm_val_t results[1];
+ wasm_val_t arguments[1];
+
+ HB_OBJ2REF (face);
+ if (unlikely (!faceref))
+ {
+ DEBUG_MSG (WASM, face_data, "Failed to register face object.");
+ goto fail;
+ }
+
+ results[0].kind = WASM_I32;
+ arguments[0].kind = WASM_I32;
+ arguments[0].of.i32 = faceref;
+ bool ret = wasm_runtime_call_wasm_a (exec_env, func,
+ ARRAY_LENGTH (results), results,
+ ARRAY_LENGTH (arguments), arguments);
+
+ if (unlikely (!ret))
+ {
+ DEBUG_MSG (WASM, module_inst, "Calling shape_plan_create() failed: %s",
+ wasm_runtime_get_exception (module_inst));
+ goto fail;
+ }
+ plan->wasm_shape_planptr = results[0].of.i32;
+ }
+
+ return plan;
+
+fail:
+
+ if (exec_env)
+ wasm_runtime_destroy_exec_env (exec_env);
+ if (module_inst)
+ wasm_runtime_deinstantiate (module_inst);
+ hb_free (plan);
+ return nullptr;
+}
+
+static void
+release_shape_plan (const hb_wasm_face_data_t *face_data,
+ hb_wasm_shape_plan_t *plan,
+ bool cache = false)
+{
+ if (cache && face_data->plan.cmpexch (nullptr, plan))
+ return;
+
+ auto *module_inst = plan->module_inst;
+ auto *exec_env = plan->exec_env;
+
+ /* Is there even any point to having a shape_plan_destroy function
+ * and calling it? */
+ if (plan->wasm_shape_planptr)
+ {
+
+ auto *func = wasm_runtime_lookup_function (module_inst, "shape_plan_destroy", nullptr);
+ if (func)
+ {
+ wasm_val_t arguments[1];
+
+ arguments[0].kind = WASM_I32;
+ arguments[0].of.i32 = plan->wasm_shape_planptr;
+ bool ret = wasm_runtime_call_wasm_a (exec_env, func,
+ 0, nullptr,
+ ARRAY_LENGTH (arguments), arguments);
+
+ if (unlikely (!ret))
+ {
+ DEBUG_MSG (WASM, module_inst, "Calling shape_plan_destroy() failed: %s",
+ wasm_runtime_get_exception (module_inst));
+ }
+ }
+ }
+
+ wasm_runtime_destroy_exec_env (exec_env);
+ wasm_runtime_deinstantiate (module_inst);
+ hb_free (plan);
+}
+
+void
+_hb_wasm_shaper_face_data_destroy (hb_wasm_face_data_t *data)
+{
+ if (data->plan.get_relaxed ())
+ release_shape_plan (data, data->plan);
+ wasm_runtime_unload (data->wasm_module);
+ hb_blob_destroy (data->wasm_blob);
+ hb_free (data);
+}
+
+
+/*
+ * shaper font data
+ */
+
+struct hb_wasm_font_data_t {};
+
+hb_wasm_font_data_t *
+_hb_wasm_shaper_font_data_create (hb_font_t *font HB_UNUSED)
+{
+ return (hb_wasm_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+}
+
+void
+_hb_wasm_shaper_font_data_destroy (hb_wasm_font_data_t *data HB_UNUSED)
+{
+}
+
+
+/*
+ * shaper
+ */
+
+hb_bool_t
+_hb_wasm_shape (hb_shape_plan_t *shape_plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features)
+{
+ if (unlikely (buffer->in_error ()))
+ return false;
+
+ bool ret = true;
+ hb_face_t *face = font->face;
+ const hb_wasm_face_data_t *face_data = face->data.wasm;
+
+ bool retried = false;
+ if (0)
+ {
+retry:
+ DEBUG_MSG (WASM, font, "Retrying...");
+ }
+
+ wasm_function_inst_t func = nullptr;
+
+ hb_wasm_shape_plan_t *plan = acquire_shape_plan (face, face_data);
+ if (unlikely (!plan))
+ {
+ DEBUG_MSG (WASM, face_data, "Acquiring shape-plan failed.");
+ return false;
+ }
+
+ auto *module_inst = plan->module_inst;
+ auto *exec_env = plan->exec_env;
+
+ HB_OBJ2REF (font);
+ HB_OBJ2REF (buffer);
+ if (unlikely (!fontref || !bufferref))
+ {
+ DEBUG_MSG (WASM, module_inst, "Failed to register objects.");
+ goto fail;
+ }
+
+ func = wasm_runtime_lookup_function (module_inst, "shape", nullptr);
+ if (unlikely (!func))
+ {
+ DEBUG_MSG (WASM, module_inst, "Shape function not found.");
+ goto fail;
+ }
+
+ wasm_val_t results[1];
+ wasm_val_t arguments[5];
+
+ results[0].kind = WASM_I32;
+ arguments[0].kind = WASM_I32;
+ arguments[0].of.i32 = plan->wasm_shape_planptr;
+ arguments[1].kind = WASM_I32;
+ arguments[1].of.i32 = fontref;
+ arguments[2].kind = WASM_I32;
+ arguments[2].of.i32 = bufferref;
+ arguments[3].kind = WASM_I32;
+ arguments[3].of.i32 = num_features ? wasm_runtime_module_dup_data (module_inst,
+ (const char *) features,
+ num_features * sizeof (features[0])) : 0;
+ arguments[4].kind = WASM_I32;
+ arguments[4].of.i32 = num_features;
+
+ ret = wasm_runtime_call_wasm_a (exec_env, func,
+ ARRAY_LENGTH (results), results,
+ ARRAY_LENGTH (arguments), arguments);
+
+ if (num_features)
+ wasm_runtime_module_free (module_inst, arguments[2].of.i32);
+
+ if (unlikely (!ret || !results[0].of.i32))
+ {
+ DEBUG_MSG (WASM, module_inst, "Calling shape() failed: %s",
+ wasm_runtime_get_exception (module_inst));
+ if (!buffer->ensure_unicode ())
+ {
+ DEBUG_MSG (WASM, font, "Shape failed but buffer is not in Unicode; failing...");
+ goto fail;
+ }
+ if (retried)
+ {
+ DEBUG_MSG (WASM, font, "Giving up...");
+ goto fail;
+ }
+ buffer->successful = true;
+ retried = true;
+ release_shape_plan (face_data, plan);
+ plan = nullptr;
+ goto retry;
+ }
+
+ /* TODO Regularize clusters according to direction & cluster level,
+ * such that client doesn't crash with unmet expectations. */
+
+ if (!results[0].of.i32)
+ {
+fail:
+ ret = false;
+ }
+
+ release_shape_plan (face_data, plan, ret);
+
+ if (ret)
+ {
+ buffer->clear_glyph_flags ();
+ buffer->unsafe_to_break ();
+ }
+
+ return ret;
+}
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb.hh b/src/3rdparty/harfbuzz-ng/src/hb.hh
index 205f8cf196..972608d6a3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb.hh
@@ -64,6 +64,7 @@
#pragma GCC diagnostic error "-Wbitwise-instead-of-logical"
#pragma GCC diagnostic error "-Wcast-align"
#pragma GCC diagnostic error "-Wcast-function-type"
+#pragma GCC diagnostic error "-Wconstant-conversion"
#pragma GCC diagnostic error "-Wcomma"
#pragma GCC diagnostic error "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic error "-Wembedded-directive"
@@ -315,6 +316,14 @@ extern "C" void hb_free_impl(void *ptr);
#define __restrict
#endif
+#ifndef HB_ALWAYS_INLINE
+#if defined(_MSC_VER)
+#define HB_ALWAYS_INLINE __forceinline
+#else
+#define HB_ALWAYS_INLINE __attribute__((always_inline)) inline
+#endif
+#endif
+
/*
* Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
* HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch