summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng')
-rw-r--r--src/3rdparty/harfbuzz-ng/CMakeLists.txt3
-rw-r--r--src/3rdparty/harfbuzz-ng/NEWS285
-rw-r--r--src/3rdparty/harfbuzz-ng/README.md6
-rw-r--r--src/3rdparty/harfbuzz-ng/TODO28
-rw-r--r--src/3rdparty/harfbuzz-ng/import_from_tarball.sh9
-rw-r--r--src/3rdparty/harfbuzz-ng/qt_attribution.json2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh110
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh51
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh128
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh21
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ExtensionSubst.hh22
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/GSUB.hh58
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh135
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh118
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh59
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh165
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh53
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubstFormat1.hh120
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh228
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh103
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh75
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh122
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh120
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookup.hh224
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookupSubTable.hh77
-rw-r--r--src/3rdparty/harfbuzz-ng/src/harfbuzz.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh20
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-kerx-table.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh42
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-algs.hh127
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-array.hh36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-atomic.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bimap.hh25
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh72
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh26
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh127
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-blob.cc4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh16
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc422
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.cc252
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.h161
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.hh267
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-common.cc78
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-common.h16
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-config.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-coretext.cc27
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-debug.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-dispatch.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-draw.cc376
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-draw.h285
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-draw.hh246
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-face.cc23
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.cc273
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.h53
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.hh33
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ft.cc98
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-iter.hh105
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-kern.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-machinery.hh20
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-map.hh128
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-meta.hh234
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.cc177
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.hh145
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-mutex.hh37
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-object.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-open-type.hh49
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc34
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh42
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc22
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh67
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh291
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh32
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color-colr-table.hh789
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color-colrv1-closure.hh55
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color-sbix-table.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color-svg-table.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h15
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-face-table-list.hh17
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-face.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc79
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh154
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh179
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh22
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh206
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh27
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh236
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh1683
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh652
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc376
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h62
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh54
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh415
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc45
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-math.h36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-meta-table.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc191
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.h5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh13
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name.h30
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh38
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh17
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh32
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc28
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc43
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.hh1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc17
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh473
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc13
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh808
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.hh1119
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc23
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc19
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.hh1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc96
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh114
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh264
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh15
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh95
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var.h2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-repacker.hh918
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh21
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-serialize.hh158
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.cc48
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.h11
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.hh35
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shape.cc18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-static.cc39
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-style.cc20
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-style.h4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh102
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc42
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc43
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh22
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc259
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh15
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc49
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.h80
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.cc61
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.h46
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-unicode.hh5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-vector.hh229
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-version.h8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/main.cc82
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-iter.cc74
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-machinery.cc46
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-map.cc139
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-meta.cc133
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-repacker.cc1041
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-serialize.cc51
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-set.cc97
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-vector.cc154
189 files changed, 13698 insertions, 6082 deletions
diff --git a/src/3rdparty/harfbuzz-ng/CMakeLists.txt b/src/3rdparty/harfbuzz-ng/CMakeLists.txt
index 0f7632dbba..d52a5b7c5b 100644
--- a/src/3rdparty/harfbuzz-ng/CMakeLists.txt
+++ b/src/3rdparty/harfbuzz-ng/CMakeLists.txt
@@ -20,6 +20,7 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
src/hb-buffer-deserialize-json.hh
src/hb-buffer-deserialize-text.hh
src/hb-buffer-serialize.cc
+ src/hb-buffer-verify.cc
src/hb-cache.hh
src/hb-common.h
src/hb-debug.hh
@@ -51,6 +52,7 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
src/hb-subset-cff2.cc
src/hb-subset-input.cc
src/hb-subset-plan.cc
+ src/hb-subset-repacker.cc src/hb-subset-repacker.h
src/hb-unicode.cc src/hb-unicode.h src/hb-unicode.hh
src/hb-utf.hh
src/hb-version.h
@@ -156,6 +158,7 @@ qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE # special case
src/hb-ot-shape-normalize.cc src/hb-ot-shape-normalize.hh
src/hb-ot-tag.cc
src/hb-ot-var.cc src/hb-ot-var.h
+ src/hb-ot-var-common.hh
src/hb-ot-var-avar-table.hh
src/hb-ot-var-fvar-table.hh
src/hb-ot-var-hvar-table.hh
diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS
index d8d219e436..0559840cf3 100644
--- a/src/3rdparty/harfbuzz-ng/NEWS
+++ b/src/3rdparty/harfbuzz-ng/NEWS
@@ -1,3 +1,282 @@
+Overview of changes leading to 4.2.1
+Sunday, April 24, 2022
+====================================
+- Make sure hb_blob_create_from_file_or_fail() always returns nullptr in case
+ of failure and not empty blob sometimes. (Khaled Hosny)
+- Add --passthrough-tables option to hb-subset. (Cosimo Lupo)
+- Reinstate a pause after basic features in Khmer shaper, fixing a regression
+ introduced in previous release. (Behdad Esfahbod)
+- Better handling of Regional_Indicator when shaped with RTL-native scripts,
+ reverting earlier fix that caused regressions in AAT shaping. (Behdad Esfahbod)
+
+
+Overview of changes leading to 4.2.0
+Wednesday, March 30, 2022
+====================================
+- Source code reorganization, splitting large hb-ot-layout files into smaller,
+ per-subtable ones under OT/Layout/*. Code for more tables will follow suit in
+ later releases. (Garret Rieger, Behdad Esfahbod)
+- Revert Indic shaper change in previous release that broke some fonts and
+ instead make per-syllable restriction of “GSUB” application limited to
+ script-specific Indic features, while applying them and discretionary
+ features in one go. (Behdad Esfahbod)
+- Fix decoding of private in gvar table. (Behdad Esfahbod)
+- Fix handling of contextual lookups that delete too many glyphs. (Behdad Esfahbod)
+- Make “morx” deleted glyphs don’t block “GPOS” application. (Behdad Esfahbod)
+- Various build fixes. (Chun-wei Fan, Khaled Hosny)
+
+- New API
++hb_set_next_many() (Andrew John)
+
+
+Overview of changes leading to 4.1.0
+Wednesday, March 23, 2022
+====================================
+- Various OSS-Fuzz fixes. (Behdad Esfahbod)
+- Make fallback vertical-origin match FreeType’s. (Behdad Esfahbod)
+- Treat visible viramas like dependent vowels in USE shaper. (David Corbett)
+- Apply presentation forms features and discretionary features in one go in
+ Indic shaper, which seems to match Uniscribe and CoreText behaviour.
+ (Behdad Esfahbod, David Corbett)
+- Various bug fixes.
+
+- New API
++hb_set_add_sorted_array() (Andrew John)
+
+
+Overview of changes leading to 4.0.1
+Friday, March 11, 2022
+====================================
+- Update OpenType to AAT mappings for “hist” and “vrtr” features.
+ (Florian Pircher)
+- Update IANA Language Subtag Registry to 2022-03-02. (David Corbett)
+- Update USE shaper to allow any non-numeric tail in a symbol cluster, and
+ remove obsolete data overrides. (David Corbett)
+- Fix handling of baseline variations to return correctly scaled values.
+ (Matthias Clasen)
+- A new experimental hb_subset_repack_or_fail() to repack an array of objects,
+ eliminating offset overflows. The API is not available unless HarfBuzz is
+ built with experimental APIs enabled. (Qunxin Liu)
+
+- New experimental API
++hb_link_t
++hb_object_t
++hb_subset_repack_or_fail()
+
+
+Overview of changes leading to 4.0.0
+Tuesday, March 1, 2022
+====================================
+- New public API to create subset plan and gather information on things like
+ glyph mappings in the final subset. The plan can then be passed on to perform
+ the subsetting operation. (Garret Rieger)
+- Draw API for extracting glyph shapes have been extended and finalized and is
+ no longer an experimental API. The draw API supports glyf, CFF and CFF2
+ glyph outlines tables, and applies variation settings set on the font as well
+ as synthetic slant. The new public API is not backward compatible with the
+ previous, non-public, experimental API. (Behdad Esfahbod)
+- The hb-view tool will use HarfBuzz draw API to render the glyphs instead of
+ cairo-ft when compiled with Cairo 1.17.5 or newer, setting HB_DRAW
+ environment variable to 1 or 0 will force using or not use the draw API,
+ respectively. (Behdad Esfahbod)
+- The hb-shape and hb-view tools now default to using HarfBuzz’s own font
+ loading functions (ot) instead of FreeType ones (ft). They also have a new
+ option, --font-slant, to apply synthetic slant to the font. (Behdad Esfahbod)
+- HarfBuzz now supports more than 65535 (the OpenType limit) glyph shapes and
+ metrics. See https://github.com/be-fonts/boring-expansion-spec/issues/6 and
+ https://github.com/be-fonts/boring-expansion-spec/issues/7 for details.
+ (Behdad Esfahbod)
+- New API to get the dominant horizontal baseline tag for a given script.
+ (Behdad Esfahbod)
+- New API to get the baseline positions from the font, and synthesize missing
+ ones. As well as new API to get font metrics and synthesize missing ones.
+ (Matthias Clasen)
+- Improvements to finding dependencies on Windows when building with Visual
+ Studio. (Chun-wei Fan)
+- New buffer flag, HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT, that must be set
+ during shaping for HB_GLYPH_FLAG_UNSAFE_TO_CONCAT flag to be reliably
+ produced. This is to limit the performance hit of producing this flag to when
+ it is actually needed. (Behdad Esfahbod)
+- Documentation improvements. (Matthias Clasen)
+
+- New API
+ - General:
+ +HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT
+ +hb_var_num_t
+
+ - Draw:
+ +hb_draw_funcs_t
+ +hb_draw_funcs_create()
+ +hb_draw_funcs_reference()
+ +hb_draw_funcs_destroy()
+ +hb_draw_funcs_is_immutable()
+ +hb_draw_funcs_make_immutable()
+ +hb_draw_move_to_func_t
+ +hb_draw_funcs_set_move_to_func()
+ +hb_draw_line_to_func_t
+ +hb_draw_funcs_set_line_to_func()
+ +hb_draw_quadratic_to_func_t
+ +hb_draw_funcs_set_quadratic_to_func()
+ +hb_draw_cubic_to_func_t
+ +hb_draw_funcs_set_cubic_to_func()
+ +hb_draw_close_path_func_t
+ +hb_draw_funcs_set_close_path_func()
+ +hb_draw_state_t
+ +HB_DRAW_STATE_DEFAULT
+ +hb_draw_move_to()
+ +hb_draw_line_to()
+ +hb_draw_quadratic_to()
+ +hb_draw_cubic_to()
+ +hb_draw_close_path()
+ +hb_font_get_glyph_shape_func_t
+ +hb_font_funcs_set_glyph_shape_func()
+ +hb_font_get_glyph_shape()
+
+ - OpenType layout
+ +HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL
+ +HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL
+ +hb_ot_layout_get_horizontal_baseline_tag_for_script()
+ +hb_ot_layout_get_baseline_with_fallback()
+
+ - Metrics:
+ +hb_ot_metrics_get_position_with_fallback()
+
+ - Subset:
+ +hb_subset_plan_t
+ +hb_subset_plan_create_or_fail()
+ +hb_subset_plan_reference()
+ +hb_subset_plan_destroy()
+ +hb_subset_plan_set_user_data()
+ +hb_subset_plan_get_user_data()
+ +hb_subset_plan_execute_or_fail()
+ +hb_subset_plan_unicode_to_old_glyph_mapping()
+ +hb_subset_plan_new_to_old_glyph_mapping()
+ +hb_subset_plan_old_to_new_glyph_mapping()
+
+
+Overview of changes leading to 3.4.0
+Sunday, February 13, 2022
+====================================
+- Perform sanity checks on shaping results is now part of “harfbuzz” library
+ and can be enabled by setting the buffer flag HB_BUFFER_FLAG_VERIFY.
+ (Behdad Esfahbod)
+- Arabic Mark Transient Reordering Algorithm have been updated to revision 6.
+ (Khaled Hosny)
+- ISO 15924 code for mathematical notation, ‘Zmth’, now maps to the OpenType
+ ‘math’ tag. (Alexis King)
+- It is now possible to get at once all math kerning values for a given glyph
+ at a given corner. (Alexis King)
+- Fix locale_t portability issues on systems the typedef’s it to a void
+ pointer. (Behdad Esfahbod)
+
+- New API:
++HB_BUFFER_FLAG_VERIFY
++HB_OT_TAG_MATH_SCRIPT
++HB_SCRIPT_MATH
++hb_ot_math_kern_entry_t
++hb_ot_math_get_glyph_kernings()
+
+- Deprecated API
++HB_OT_MATH_SCRIPT
+
+
+Overview of changes leading to 3.3.2
+Sunday, February 6, 2022
+====================================
+- Revert splitting of pair positioning values introduced in 3.3.0 as it proved
+ problematic. (Behdad Esfahbod)
+
+
+Overview of changes leading to 3.3.1
+Monday, January 31, 2022
+====================================
+- Fix heap-use-after-free in harfbuzz-subset introduced in previous release.
+ (Garret Rieger)
+
+
+Overview of changes leading to 3.3.0
+Monday, January 31, 2022
+====================================
+- Improved documentation. (Matthias Clasen)
+- Internal code cleanup, using C++ standard library more. (Behdad Esfahbod)
+- The low 16-bits of face index will be used by hb_face_create() to select a
+ face inside a font collection file format, while the high 16-bits will be
+ used by hb_font_create() to load the named instance. (Behdad Esfahbod)
+- Glyph positions and other font metrics now apply synthetic slant set by
+ hb_font_set_synthetic_slant(), for improved positioning for synthetically
+ slanted fonts. (Behdad Esfahbod)
+- Fixed unintentional locale dependency in hb_variation_to_string() for decimal
+ point representation. (Matthias Clasen)
+- When applying pair positioning (kerning) the positioning value is split
+ between the two sides of the pair for improved cursor positioning between
+ such pairs. (Behdad Esfahbod)
+- Introduced new HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, to be used in conjunction
+ with HB_GLYPH_FLAG_UNSAFE_TO_BREAK for optimizing re-shaping during line
+ breaking. Check the documentation for further details. (Behdad Esfahbod)
+- Improved handling of macrolanguages when mapping BCP 47 codes to OpenType
+ tags. (David Corbett)
+
+- New API:
++HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
++hb_segment_properties_overlay()
++hb_buffer_create_similar()
++hb_font_set_synthetic_slant()
++hb_font_get_synthetic_slant()
++hb_font_get_var_coords_design()
+
+
+Overview of changes leading to 3.2.0
+Friday, November 26, 2021
+====================================
+“harfbuzz” library improvements:
+- Fixed shaping of Apple Color Emoji flags in right-to-left context. (Behdad Esfahbod)
+- Fixed positioning of CFF fonts in HB_TINY profile. (Behdad Esfahbod)
+- OpenType 1.9 language tags update. (David Corbett)
+- Add HB_NO_VERTICAL config option.
+- Add HB_CONFIG_OVERRIDE_H for easier configuration. (Behdad Esfahbod)
+
+“harfbuzz-subset” library improvements:
+- Improved packing of cmap, loca, and Ligature tables. (Garret Rieger)
+- Significantly improved overflow-resolution strategy in the repacker. (Garret Rieger)
+
+
+Overview of changes leading to 3.1.2
+Friday, November 26, 2021
+====================================
+- hb-shape / hb-view: revert treating text on the commandline as single
+ paragraph (was introduced in 3.0.0); add new --single-par to do that.
+ (Behdad Esfahbod)
+- Subsetter bug fixes. (Garret Rieger, Qunxin Liu, Behdad Esfahbod)
+
+
+Overview of changes leading to 3.1.1
+Wednesday, November 8, 2021
+====================================
+- Work around GCC cast-align error/warning on some platforms. (Behdad Esfahbod)
+- Documentation improvements. (Matthias Clasen)
+
+
+Overview of changes leading to 3.1.0
+Wednesday, November 3, 2021
+====================================
+- Better offset-overflow handling in the subsetter library. (Garret Rieger)
+- Improved Unicode 14 properties in the USE shaper, and various other USE
+ shaper fixes. (David Corbett)
+- MATH and COLR v1 tables subsetting support, and various other subsetter fixes.
+ (Qunxin Liu)
+- Support for Pwo Karen / Ason Chin medial la. (Simon Cozens)
+- Apply GPOS positioning when substituting with morx table, if kerx is missing.
+ (Behdad Esfahbod)
+- Apply calt and clig features across syllable boundaries in Indic shaper.
+ (Behdad Esfahbod)
+- meson option for enabling Graphite 2 has been renamed to graphite2.
+- Build and documentation fixes.
+
+- New API:
++hb_buffer_set_not_found_glyph()
++hb_buffer_get_not_found_glyph()
+
+
Overview of changes leading to 3.0.0
Friday, September 17, 2021
====================================
@@ -331,7 +610,7 @@ Friday, May 24, 2019
code-base changes. We now require C++11. Support for gcc 4.8 and earlier has been
dropped.
- New hb-config.hh facility for compiling smaller library for embedded and web usecases.
-- New Unicode Character Databse implementation that is half the size of previously-used
+- New Unicode Character Database implementation that is half the size of previously-used
UCDN.
- Subsetter improvements.
- Improved documentation, thanks to Nathan Willis.
@@ -1179,7 +1458,7 @@ Thursday, February 25, 2016
due to bug in glyph class of ASCII double-quote character. This should
address "regression" introduced in 1.2.0 when we switched mark zeroing
in most shapers from BY_UNICODE_LATE to BY_GDEF_LATE.
- This fourth release in a week should finally stablize things...
+ This fourth release in a week should finally stabilize things...
- hb-ot-font's get_glyph() implementation saw some optimizations. Though,
might be really hard to measure in real-world situations.
@@ -2227,7 +2506,7 @@ o Changed API:
- hb_buffer_create() takes zero arguments now.
Use hb_buffer_pre_allocate() to pre-allocate.
- - hb_buffer_add_utf*() now accept -1 for length parameteres,
+ - hb_buffer_add_utf*() now accept -1 for length parameters,
meaning "nul-terminated".
- hb_direction_t enum values changed.
diff --git a/src/3rdparty/harfbuzz-ng/README.md b/src/3rdparty/harfbuzz-ng/README.md
index 9deb32c1e8..fc12c65568 100644
--- a/src/3rdparty/harfbuzz-ng/README.md
+++ b/src/3rdparty/harfbuzz-ng/README.md
@@ -1,12 +1,10 @@
[![Linux CI Status](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)
[![CircleCI Build Status](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main)
[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/harfbuzz.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
-[![Coverity Code Health](https://img.shields.io/coverity/scan/5450.svg)](https://scan.coverity.com/projects/behdad-harfbuzz)
-[![Codacy Code Health](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/15166/badge.svg)](https://scan.coverity.com/projects/harfbuzz)
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&utm_medium=referral&utm_content=harfbuzz/harfbuzz&utm_campaign=Badge_Grade)
[![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
-[![Coverals Code Coverage](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz)
[![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions)
-[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
This is HarfBuzz, a text shaping library.
diff --git a/src/3rdparty/harfbuzz-ng/TODO b/src/3rdparty/harfbuzz-ng/TODO
deleted file mode 100644
index d8e41050ec..0000000000
--- a/src/3rdparty/harfbuzz-ng/TODO
+++ /dev/null
@@ -1,28 +0,0 @@
-API issues:
-===========
-
-- API to accept a list of languages?
-
-- Remove hb_ot_shape_glyphs_closure()?
-
-
-API additions
-=============
-
-- Language to/from script.
-
-- Add hb-cairo glue
-
-- Add sanitize API.
-
-- Add query / enumeration API for aalt-like features?
-
-- Add segmentation API
-
-- Add hb-fribidi glue?
-
-
-hb-view / hb-shape enhancements:
-===============================
-
-- Add --width, --height, --auto-size, --ink-box, --align, etc?
diff --git a/src/3rdparty/harfbuzz-ng/import_from_tarball.sh b/src/3rdparty/harfbuzz-ng/import_from_tarball.sh
index db0e6004a4..7bcaf22cdc 100644
--- a/src/3rdparty/harfbuzz-ng/import_from_tarball.sh
+++ b/src/3rdparty/harfbuzz-ng/import_from_tarball.sh
@@ -42,7 +42,7 @@
# This is a small script to copy the required files from a harfbuzz tarball
# into 3rdparty/harfbuzz-ng/ . Documentation, tests, demos etc. are not imported.
# Steps:
-# 1. rm $QTDIR/src/3rdparty/harfbuzz-ng/src/*
+# 1. rm $QTDIR/src/3rdparty/harfbuzz-ng/src/* && rm $QTDIR/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB
# 2. source import_from_tarball.sh harfbuzz_tarball_dir/ $QTDIR/src/3rdparty/harfbuzz-ng/
# 3. Check that CMakeLists contains everything
@@ -84,7 +84,6 @@ FILES=(AUTHORS
NEWS
README.md
THANKS
- TODO
)
for i in ${FILES[*]}; do
@@ -98,3 +97,9 @@ CODEFILES=($HB_DIR/src/*.cc
for i in ${CODEFILES[*]}; do
cp $i $TARGET_DIR/src/
done
+
+GSUBFILES=($HB_DIR/src/OT/Layout/GSUB/*.hh)
+
+for i in ${GSUBFILES[*]}; do
+ cp $i $TARGET_DIR/src/OT/Layout/GSUB/
+done
diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json
index 72fdb8a0aa..d5e2bccfa0 100644
--- a/src/3rdparty/harfbuzz-ng/qt_attribution.json
+++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json
@@ -6,7 +6,7 @@
"Description": "HarfBuzz is an OpenType text shaping engine.",
"Homepage": "http://harfbuzz.org",
- "Version": "3.0.0",
+ "Version": "4.2.1",
"License": "MIT License",
"LicenseId": "MIT",
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh
new file mode 100644
index 0000000000..484f347468
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh
@@ -0,0 +1,110 @@
+#ifndef OT_LAYOUT_GSUB_ALTERNATESET_HH
+#define OT_LAYOUT_GSUB_ALTERNATESET_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct AlternateSet
+{
+ protected:
+ Array16Of<HBGlyphID16>
+ alternates; /* Array of alternate GlyphIDs--in
+ * arbitrary order */
+ public:
+ DEFINE_SIZE_ARRAY (2, alternates);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (alternates.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return hb_any (alternates, glyphs); }
+
+ void closure (hb_closure_context_t *c) const
+ { c->output->add_array (alternates.arrayZ, alternates.len); }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { c->output->add_array (alternates.arrayZ, alternates.len); }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int count = alternates.len;
+
+ if (unlikely (!count)) return_trace (false);
+
+ hb_mask_t glyph_mask = c->buffer->cur().mask;
+ hb_mask_t lookup_mask = c->lookup_mask;
+
+ /* Note: This breaks badly if two features enabled this lookup together. */
+ unsigned int shift = hb_ctz (lookup_mask);
+ unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
+
+ /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
+ if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
+ {
+ /* Maybe we can do better than unsafe-to-break all; but since we are
+ * changing random state, it would be hard to track that. Good 'nough. */
+ c->buffer->unsafe_to_break (0, c->buffer->len);
+ alt_index = c->random_number () % count + 1;
+ }
+
+ if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
+
+ c->replace_glyph (alternates[alt_index - 1]);
+
+ return_trace (true);
+ }
+
+ unsigned
+ get_alternates (unsigned start_offset,
+ unsigned *alternate_count /* IN/OUT. May be NULL. */,
+ hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
+ {
+ if (alternates.len && alternate_count)
+ {
+ + alternates.sub_array (start_offset, alternate_count)
+ | hb_sink (hb_array (alternate_glyphs, *alternate_count))
+ ;
+ }
+ return alternates.len;
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator alts)
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (alternates.serialize (c, alts));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (alternates)
+ | hb_filter (glyphset)
+ | hb_map (glyph_map)
+ ;
+
+ auto *out = c->serializer->start_embed (*this);
+ return_trace (out->serialize (c->serializer, it) &&
+ out->alternates);
+ }
+};
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_ALTERNATESET_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh
new file mode 100644
index 0000000000..e5d999261f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh
@@ -0,0 +1,51 @@
+#ifndef OT_LAYOUT_GSUB_ALTERNATESUBST_HH
+#define OT_LAYOUT_GSUB_ALTERNATESUBST_HH
+
+#include "AlternateSubstFormat1.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct AlternateSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ AlternateSubstFormat1 format1;
+ } u;
+ public:
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> alternate_len_list,
+ hb_array_t<const HBGlyphID16> alternate_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned int format = 1;
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
+ default:return_trace (false);
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_ALTERNATESUBST_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
new file mode 100644
index 0000000000..af1cd7bedb
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
@@ -0,0 +1,128 @@
+#ifndef OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
+
+#include "AlternateSet.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct AlternateSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16OfOffset16To<AlternateSet>
+ alternateSet; /* Array of AlternateSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (6, alternateSet);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, alternateSet)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ + hb_zip (this+coverage, alternateSet)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ unsigned
+ get_glyph_alternates (hb_codepoint_t gid,
+ unsigned start_offset,
+ unsigned *alternate_count /* IN/OUT. May be NULL. */,
+ hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
+ { return (this+alternateSet[(this+coverage).get_coverage (gid)])
+ .get_alternates (start_offset, alternate_count, alternate_glyphs); }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ return_trace ((this+alternateSet[index]).apply (c));
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> alternate_len_list,
+ hb_array_t<const HBGlyphID16> alternate_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
+ for (unsigned int i = 0; i < glyphs.length; i++)
+ {
+ unsigned int alternate_len = alternate_len_list[i];
+ if (unlikely (!alternateSet[i]
+ .serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
+ return_trace (false);
+ alternate_glyphs_list += alternate_len;
+ }
+ return_trace (coverage.serialize_serialize (c, glyphs));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, alternateSet)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
+ return_trace (bool (new_coverage));
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh
new file mode 100644
index 0000000000..bbb88b222f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh
@@ -0,0 +1,18 @@
+#ifndef OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH
+#define OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ChainContextSubst : ChainContext {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
new file mode 100644
index 0000000000..f4c78a9f02
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
@@ -0,0 +1,21 @@
+#ifndef OT_LAYOUT_GSUB_COMMON_HH
+#define OT_LAYOUT_GSUB_COMMON_HH
+
+#include "../../../hb-serialize.hh"
+#include "../../../hb-ot-layout-gsubgpos.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+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);
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_COMMON_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh
new file mode 100644
index 0000000000..2af54e8ff4
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh
@@ -0,0 +1,18 @@
+#ifndef OT_LAYOUT_GSUB_CONTEXTSUBST_HH
+#define OT_LAYOUT_GSUB_CONTEXTSUBST_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ContextSubst : Context {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_CONTEXTSUBST_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ExtensionSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ExtensionSubst.hh
new file mode 100644
index 0000000000..40a3ff439f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ExtensionSubst.hh
@@ -0,0 +1,22 @@
+#ifndef OT_LAYOUT_GSUB_EXTENSIONSUBST_HH
+#define OT_LAYOUT_GSUB_EXTENSIONSUBST_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ExtensionSubst : Extension<ExtensionSubst>
+{
+ typedef struct SubstLookupSubTable SubTable;
+ bool is_reverse () const;
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_EXTENSIONSUBST_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/GSUB.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/GSUB.hh
new file mode 100644
index 0000000000..ad153ce8d7
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/GSUB.hh
@@ -0,0 +1,58 @@
+#ifndef OT_LAYOUT_GSUB_GSUB_HH
+#define OT_LAYOUT_GSUB_GSUB_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+#include "SubstLookup.hh"
+
+using OT::Layout::GSUB::SubstLookup;
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+/*
+ * GSUB -- Glyph Substitution
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
+ */
+
+struct GSUB : GSUBGPOS
+{
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
+
+ const SubstLookup& get_lookup (unsigned int i) const
+ { return static_cast<const SubstLookup &> (GSUBGPOS::get_lookup (i)); }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
+ return GSUBGPOS::subset<SubstLookup> (&l);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return GSUBGPOS::sanitize<SubstLookup> (c); }
+
+ HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
+ void closure_lookups (hb_face_t *face,
+ const hb_set_t *glyphs,
+ hb_set_t *lookup_indexes /* IN/OUT */) const
+ { GSUBGPOS::closure_lookups<SubstLookup> (face, glyphs, lookup_indexes); }
+
+ typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
+};
+
+
+}
+}
+
+struct GSUB_accelerator_t : Layout::GSUB::GSUB::accelerator_t {
+ GSUB_accelerator_t (hb_face_t *face) : Layout::GSUB::GSUB::accelerator_t (face) {}
+};
+
+
+}
+
+#endif /* OT_LAYOUT_GSUB_GSUB_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
new file mode 100644
index 0000000000..0448d925d1
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
@@ -0,0 +1,135 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURE_HH
+#define OT_LAYOUT_GSUB_LIGATURE_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct Ligature
+{
+ protected:
+ HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */
+ HeadlessArrayOf<HBGlyphID16>
+ component; /* Array of component GlyphIDs--start
+ * with the second component--ordered
+ * in writing direction */
+ public:
+ DEFINE_SIZE_ARRAY (4, component);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return hb_all (component, glyphs); }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ if (!intersects (c->glyphs)) return;
+ c->output->add (ligGlyph);
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ c->input->add_array (component.arrayZ, component.get_length ());
+ c->output->add (ligGlyph);
+ }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ {
+ if (c->len != component.lenP1)
+ return false;
+
+ for (unsigned int i = 1; i < c->len; i++)
+ if (likely (c->glyphs[i] != component[i]))
+ return false;
+
+ return true;
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int count = component.lenP1;
+
+ if (unlikely (!count)) return_trace (false);
+
+ /* Special-case to make it in-place and not consider this
+ * as a "ligated" substitution. */
+ if (unlikely (count == 1))
+ {
+ c->replace_glyph (ligGlyph);
+ return_trace (true);
+ }
+
+ unsigned int total_component_count = 0;
+
+ unsigned int match_end = 0;
+ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+
+ if (likely (!match_input (c, count,
+ &component[1],
+ match_glyph,
+ nullptr,
+ &match_end,
+ match_positions,
+ &total_component_count)))
+ {
+ c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
+ return_trace (false);
+ }
+
+ ligate_input (c,
+ count,
+ match_positions,
+ match_end,
+ ligGlyph,
+ total_component_count);
+
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ hb_codepoint_t ligature,
+ Iterator components /* Starting from second */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ ligGlyph = ligature;
+ if (unlikely (!component.serialize (c, components))) return_trace (false);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
+ // Ensure Coverage table is always packed after this.
+ c->serializer->add_virtual_link (coverage_idx);
+
+ auto it =
+ + hb_iter (component)
+ | hb_map (glyph_map)
+ ;
+
+ auto *out = c->serializer->start_embed (*this);
+ return_trace (out->serialize (c->serializer,
+ glyph_map[ligGlyph],
+ it)); }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh
new file mode 100644
index 0000000000..185b324b35
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh
@@ -0,0 +1,118 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURESET_HH
+#define OT_LAYOUT_GSUB_LIGATURESET_HH
+
+#include "Common.hh"
+#include "Ligature.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct LigatureSet
+{
+ protected:
+ Array16OfOffset16To<Ligature>
+ ligature; /* Array LigatureSet tables
+ * ordered by preference */
+ public:
+ DEFINE_SIZE_ARRAY (2, ligature);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (ligature.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
+ | hb_any
+ ;
+ }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Ligature &_) { _.closure (c); })
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ {
+ return
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_map ([c] (const Ligature &_) { return _.would_apply (c); })
+ | hb_any
+ ;
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int num_ligs = ligature.len;
+ for (unsigned int i = 0; i < num_ligs; i++)
+ {
+ const Ligature &lig = this+ligature[i];
+ if (lig.apply (c)) return_trace (true);
+ }
+
+ return_trace (false);
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_array_t<const HBGlyphID16> ligatures,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> &component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
+ for (unsigned int i = 0; i < ligatures.length; i++)
+ {
+ unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
+ if (unlikely (!ligature[i].serialize_serialize (c,
+ ligatures[i],
+ component_list.sub_array (0, component_count))))
+ return_trace (false);
+ component_list += component_count;
+ }
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ + hb_iter (ligature)
+ | hb_filter (subset_offset_array (c, out->ligature, this, coverage_idx))
+ | hb_drain
+ ;
+
+ if (bool (out->ligature))
+ // Ensure Coverage table is always packed after this.
+ c->serializer->add_virtual_link (coverage_idx);
+
+ return_trace (bool (out->ligature));
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURESET_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh
new file mode 100644
index 0000000000..a029bf5e9f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh
@@ -0,0 +1,59 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURESUBST_HH
+#define OT_LAYOUT_GSUB_LIGATURESUBST_HH
+
+#include "Common.hh"
+#include "LigatureSubstFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct LigatureSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ LigatureSubstFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> first_glyphs,
+ hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+ hb_array_t<const HBGlyphID16> ligatures_list,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned int format = 1;
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c,
+ first_glyphs,
+ ligature_per_first_glyph_count_list,
+ ligatures_list,
+ component_count_list,
+ component_list));
+ default:return_trace (false);
+ }
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURESUBST_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
new file mode 100644
index 0000000000..19dfe98469
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
@@ -0,0 +1,165 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH
+
+#include "Common.hh"
+#include "LigatureSet.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct LigatureSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16OfOffset16To<LigatureSet>
+ ligatureSet; /* Array LigatureSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (6, ligatureSet);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_filter (*glyphs, hb_first)
+ | hb_map (hb_second)
+ | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
+ { return (this+_).intersects (glyphs); })
+ | hb_any
+ ;
+ }
+
+ bool may_have_non_1to1 () const
+ { return true; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ {
+ unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
+ if (likely (index == NOT_COVERED)) return false;
+
+ const LigatureSet &lig_set = this+ligatureSet[index];
+ return lig_set.would_apply (c);
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ const LigatureSet &lig_set = this+ligatureSet[index];
+ return_trace (lig_set.apply (c));
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> first_glyphs,
+ hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+ hb_array_t<const HBGlyphID16> ligatures_list,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
+ for (unsigned int i = 0; i < first_glyphs.length; i++)
+ {
+ unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
+ if (unlikely (!ligatureSet[i]
+ .serialize_serialize (c,
+ ligatures_list.sub_array (0, ligature_count),
+ component_count_list.sub_array (0, ligature_count),
+ component_list))) return_trace (false);
+ ligatures_list += ligature_count;
+ component_count_list += ligature_count;
+ }
+ return_trace (coverage.serialize_serialize (c, first_glyphs));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ // Due to a bug in some older versions of windows 7 the Coverage table must be
+ // packed after the LigatureSet and Ligature tables, so serialize Coverage first
+ // which places it last in the packed order.
+ hb_set_t new_coverage;
+ + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
+ | hb_filter (glyphset, hb_first)
+ | hb_filter ([&] (const LigatureSet& _) {
+ return _.intersects (&glyphset);
+ }, hb_second)
+ | hb_map (hb_first)
+ | hb_sink (new_coverage);
+
+ if (!c->serializer->push<Coverage> ()
+ ->serialize (c->serializer,
+ + new_coverage.iter () | hb_map_retains_sorting (glyph_map)))
+ {
+ c->serializer->pop_discard ();
+ return_trace (false);
+ }
+
+ unsigned coverage_idx = c->serializer->pop_pack ();
+ c->serializer->add_link (out->coverage, coverage_idx);
+
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_filter (new_coverage, hb_first)
+ | hb_map (hb_second)
+ // to ensure that the repacker always orders the coverage table after the LigatureSet
+ // and LigatureSubtable's they will be linked to the Coverage table via a virtual link
+ // the coverage table object idx is passed down to facilitate this.
+ | hb_apply (subset_offset_array (c, out->ligatureSet, this, coverage_idx))
+ ;
+
+ return_trace (bool (new_coverage));
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh
new file mode 100644
index 0000000000..b289175504
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh
@@ -0,0 +1,53 @@
+#ifndef OT_LAYOUT_GSUB_MULTIPLESUBST_HH
+#define OT_LAYOUT_GSUB_MULTIPLESUBST_HH
+
+#include "Common.hh"
+#include "MultipleSubstFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct MultipleSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MultipleSubstFormat1 format1;
+ } u;
+
+ public:
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> substitute_len_list,
+ hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned int format = 1;
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
+ default:return_trace (false);
+ }
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_MULTIPLESUBST_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
new file mode 100644
index 0000000000..54c6dc8478
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
@@ -0,0 +1,120 @@
+#ifndef OT_LAYOUT_GSUB_MULTIPLESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_MULTIPLESUBSTFORMAT1_HH
+
+#include "Common.hh"
+#include "Sequence.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct MultipleSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16OfOffset16To<Sequence>
+ sequence; /* Array of Sequence tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (6, sequence);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return true; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, sequence)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Sequence &_) { _.closure (c); })
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ + hb_zip (this+coverage, sequence)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ return_trace ((this+sequence[index]).apply (c));
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> substitute_len_list,
+ hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
+ for (unsigned int i = 0; i < glyphs.length; i++)
+ {
+ unsigned int substitute_len = substitute_len_list[i];
+ if (unlikely (!sequence[i]
+ .serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
+ return_trace (false);
+ substitute_glyphs_list += substitute_len;
+ }
+ return_trace (coverage.serialize_serialize (c, glyphs));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, sequence)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (subset_offset_array (c, out->sequence, this), hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
+ return_trace (bool (new_coverage));
+ }
+};
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_MULTIPLESUBSTFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
new file mode 100644
index 0000000000..435d80fd31
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
@@ -0,0 +1,36 @@
+#ifndef OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBST_HH
+#define OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBST_HH
+
+#include "Common.hh"
+#include "ReverseChainSingleSubstFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ReverseChainSingleSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ ReverseChainSingleSubstFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBST_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
new file mode 100644
index 0000000000..7a79a9df25
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
@@ -0,0 +1,228 @@
+#ifndef OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ReverseChainSingleSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of table */
+ Array16OfOffset16To<Coverage>
+ backtrack; /* Array of coverage tables
+ * in backtracking sequence, in glyph
+ * sequence order */
+ Array16OfOffset16To<Coverage>
+ lookaheadX; /* Array of coverage tables
+ * in lookahead sequence, in glyph
+ * sequence order */
+ Array16Of<HBGlyphID16>
+ substituteX; /* Array of substitute
+ * GlyphIDs--ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_MIN (10);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
+ return_trace (false);
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ if (!lookahead.sanitize (c, this))
+ return_trace (false);
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ return_trace (substitute.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ if (!(this+coverage).intersects (glyphs))
+ return false;
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+
+ unsigned int count;
+
+ count = backtrack.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+backtrack[i]).intersects (glyphs))
+ return false;
+
+ count = lookahead.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+lookahead[i]).intersects (glyphs))
+ return false;
+
+ return true;
+ }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ if (!intersects (c->glyphs)) return;
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_sink (c->output)
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+
+ unsigned int count;
+
+ count = backtrack.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ count = lookahead.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
+
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ count = substitute.len;
+ c->output->add_array (substitute.arrayZ, substitute.len);
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
+ return_trace (false); /* No chaining to this type */
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+
+ if (unlikely (index >= substitute.len)) return_trace (false);
+
+ unsigned int start_index = 0, end_index = 0;
+ if (match_backtrack (c,
+ backtrack.len, (HBUINT16 *) backtrack.arrayZ,
+ match_coverage, this,
+ &start_index) &&
+ match_lookahead (c,
+ lookahead.len, (HBUINT16 *) lookahead.arrayZ,
+ match_coverage, this,
+ c->buffer->idx + 1, &end_index))
+ {
+ c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
+ c->replace_glyph_inplace (substitute[index]);
+ /* Note: We DON'T decrease buffer->idx. The main loop does it
+ * for us. This is useful for preventing surprises if someone
+ * calls us through a Context lookup. */
+ return_trace (true);
+ }
+ else
+ {
+ c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
+ return_trace (false);
+ }
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
+
+ if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
+ return_trace (false);
+
+ for (auto& offset : it) {
+ auto *o = out->serialize_append (c->serializer);
+ if (unlikely (!o) || !o->serialize_subset (c, offset, this))
+ return_trace (false);
+ }
+
+ return_trace (true);
+ }
+
+ template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
+ hb_requires (hb_is_iterator (BacktrackIterator)),
+ hb_requires (hb_is_iterator (LookaheadIterator))>
+ bool serialize (hb_subset_context_t *c,
+ Iterator coverage_subst_iter,
+ BacktrackIterator backtrack_iter,
+ LookaheadIterator lookahead_iter) const
+ {
+ TRACE_SERIALIZE (this);
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->check_success (out))) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
+
+ if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
+ if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
+
+ auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID16>> ();
+ auto substitutes =
+ + coverage_subst_iter
+ | hb_map (hb_second)
+ ;
+
+ auto glyphs =
+ + coverage_subst_iter
+ | hb_map_retains_sorting (hb_first)
+ ;
+ if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
+ return_trace (false);
+
+ if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs)))
+ return_trace (false);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+
+ auto it =
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (glyphset, hb_second)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
+ { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+ ;
+
+ return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
+ }
+};
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
new file mode 100644
index 0000000000..ebd451e6ba
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
@@ -0,0 +1,103 @@
+#ifndef OT_LAYOUT_GSUB_SEQUENCE_HH
+#define OT_LAYOUT_GSUB_SEQUENCE_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct Sequence
+{
+ protected:
+ Array16Of<HBGlyphID16>
+ substitute; /* String of GlyphIDs to substitute */
+ public:
+ DEFINE_SIZE_ARRAY (2, substitute);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (substitute.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return hb_all (substitute, glyphs); }
+
+ void closure (hb_closure_context_t *c) const
+ { c->output->add_array (substitute.arrayZ, substitute.len); }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { c->output->add_array (substitute.arrayZ, substitute.len); }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int count = substitute.len;
+
+ /* Special-case to make it in-place and not consider this
+ * as a "multiplied" substitution. */
+ if (unlikely (count == 1))
+ {
+ c->replace_glyph (substitute.arrayZ[0]);
+ return_trace (true);
+ }
+ /* Spec disallows this, but Uniscribe allows it.
+ * https://github.com/harfbuzz/harfbuzz/issues/253 */
+ else if (unlikely (count == 0))
+ {
+ c->buffer->delete_glyph ();
+ return_trace (true);
+ }
+
+ unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
+ HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
+ unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ /* If is attached to a ligature, don't disturb that.
+ * https://github.com/harfbuzz/harfbuzz/issues/3069 */
+ if (!lig_id)
+ _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
+ c->output_glyph_for_component (substitute.arrayZ[i], klass);
+ }
+ c->buffer->skip_glyph ();
+
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator subst)
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (substitute.serialize (c, subst));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ if (!intersects (&glyphset)) return_trace (false);
+
+ auto it =
+ + hb_iter (substitute)
+ | hb_map (glyph_map)
+ ;
+
+ auto *out = c->serializer->start_embed (*this);
+ return_trace (out->serialize (c->serializer, it));
+ }
+};
+
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_SEQUENCE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh
new file mode 100644
index 0000000000..786428fe45
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh
@@ -0,0 +1,75 @@
+#ifndef OT_LAYOUT_GSUB_SINGLESUBST_HH
+#define OT_LAYOUT_GSUB_SINGLESUBST_HH
+
+#include "Common.hh"
+#include "SingleSubstFormat1.hh"
+#include "SingleSubstFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SingleSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ SingleSubstFormat1 format1;
+ SingleSubstFormat2 format2;
+ } u;
+
+ public:
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator,
+ const hb_codepoint_pair_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned format = 2;
+ unsigned delta = 0;
+ if (glyphs)
+ {
+ format = 1;
+ auto get_delta = [=] (hb_codepoint_pair_t _)
+ { return (unsigned) (_.second - _.first) & 0xFFFF; };
+ delta = get_delta (*glyphs);
+ if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
+ }
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c,
+ + glyphs
+ | hb_map_retains_sorting (hb_first),
+ delta));
+ case 2: return_trace (u.format2.serialize (c, glyphs));
+ default:return_trace (false);
+ }
+ }
+};
+
+template<typename Iterator>
+static void
+SingleSubst_serialize (hb_serialize_context_t *c,
+ Iterator it)
+{ c->start_embed<SingleSubst> ()->serialize (c, it); }
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_SINGLESUBST_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh
new file mode 100644
index 0000000000..3c6b2954ce
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh
@@ -0,0 +1,122 @@
+#ifndef OT_LAYOUT_GSUB_SINGLESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_SINGLESUBSTFORMAT1_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SingleSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ HBUINT16 deltaGlyphID; /* Add to original GlyphID to get
+ * substitute GlyphID, modulo 0x10000 */
+
+ public:
+ DEFINE_SIZE_STATIC (6);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ unsigned d = deltaGlyphID;
+
+ + hb_iter (this+coverage)
+ | hb_filter (c->parent_active_glyphs ())
+ | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
+ | hb_sink (c->output)
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ unsigned d = deltaGlyphID;
+ + hb_iter (this+coverage)
+ | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
+ | hb_sink (c->output)
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
+ unsigned int index = (this+coverage).get_coverage (glyph_id);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ /* According to the Adobe Annotated OpenType Suite, result is always
+ * limited to 16bit. */
+ glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
+ c->replace_glyph (glyph_id);
+
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator glyphs,
+ unsigned delta)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
+ c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ hb_codepoint_t delta = deltaGlyphID;
+
+ auto it =
+ + hb_iter (this+coverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting ([&] (hb_codepoint_t g) {
+ return hb_codepoint_pair_t (g,
+ (g + delta) & 0xFFFF); })
+ | hb_filter (glyphset, hb_second)
+ | hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t
+ { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+ ;
+
+ bool ret = bool (it);
+ SingleSubst_serialize (c->serializer, it);
+ return_trace (ret);
+ }
+};
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_SINGLESUBSTFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh
new file mode 100644
index 0000000000..df75bb52bb
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh
@@ -0,0 +1,120 @@
+#ifndef OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH
+#define OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SingleSubstFormat2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16Of<HBGlyphID16>
+ substitute; /* Array of substitute
+ * GlyphIDs--ordered by Coverage Index */
+
+ public:
+ DEFINE_SIZE_ARRAY (6, substitute);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_sink (c->output)
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ + hb_zip (this+coverage, substitute)
+ | hb_map (hb_second)
+ | hb_sink (c->output)
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ if (unlikely (index >= substitute.len)) return_trace (false);
+
+ c->replace_glyph (substitute[index]);
+
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator,
+ hb_codepoint_pair_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator it)
+ {
+ TRACE_SERIALIZE (this);
+ auto substitutes =
+ + it
+ | hb_map (hb_second)
+ ;
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
+ if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (glyphset, hb_second)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
+ { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+ ;
+
+ bool ret = bool (it);
+ SingleSubst_serialize (c->serializer, it);
+ return_trace (ret);
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookup.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookup.hh
new file mode 100644
index 0000000000..3419b5a734
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookup.hh
@@ -0,0 +1,224 @@
+#ifndef OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
+#define OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
+
+#include "Common.hh"
+#include "SubstLookupSubTable.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SubstLookup : Lookup
+{
+ typedef SubstLookupSubTable SubTable;
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return Lookup::sanitize<SubTable> (c); }
+
+ const SubTable& get_subtable (unsigned int i) const
+ { return Lookup::get_subtable<SubTable> (i); }
+
+ static inline bool lookup_type_is_reverse (unsigned int lookup_type)
+ { return lookup_type == SubTable::ReverseChainSingle; }
+
+ bool is_reverse () const
+ {
+ unsigned int type = get_type ();
+ if (unlikely (type == SubTable::Extension))
+ return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse ();
+ return lookup_type_is_reverse (type);
+ }
+
+ bool may_have_non_1to1 () const
+ {
+ hb_have_non_1to1_context_t c;
+ return dispatch (&c);
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ return_trace (dispatch (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c);
+ }
+
+ hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
+ {
+ if (!c->should_visit_lookup (this_index))
+ return hb_closure_context_t::default_return_value ();
+
+ c->set_recurse_func (dispatch_closure_recurse_func);
+
+ hb_closure_context_t::return_t ret = dispatch (c);
+
+ c->flush ();
+
+ return ret;
+ }
+
+ hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
+ {
+ if (c->is_lookup_visited (this_index))
+ return hb_closure_lookups_context_t::default_return_value ();
+
+ c->set_lookup_visited (this_index);
+ if (!intersects (c->glyphs))
+ {
+ c->set_lookup_inactive (this_index);
+ return hb_closure_lookups_context_t::default_return_value ();
+ }
+
+ c->set_recurse_func (dispatch_closure_lookups_recurse_func);
+
+ hb_closure_lookups_context_t::return_t ret = dispatch (c);
+ return ret;
+ }
+
+ hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
+ return dispatch (c);
+ }
+
+ template <typename set_t>
+ void collect_coverage (set_t *glyphs) const
+ {
+ hb_collect_coverage_context_t<set_t> c (glyphs);
+ dispatch (&c);
+ }
+
+ bool would_apply (hb_would_apply_context_t *c,
+ const hb_ot_layout_lookup_accelerator_t *accel) const
+ {
+ if (unlikely (!c->len)) return false;
+ if (!accel->may_have (c->glyphs[0])) return false;
+ return dispatch (c);
+ }
+
+ static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
+
+ bool serialize_single (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const HBGlyphID16> substitutes)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
+ if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ bool serialize_multiple (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> substitute_len_list,
+ hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
+ if (c->push<SubTable> ()->u.multiple.
+ serialize (c,
+ glyphs,
+ substitute_len_list,
+ substitute_glyphs_list))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ bool serialize_alternate (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> alternate_len_list,
+ hb_array_t<const HBGlyphID16> alternate_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
+
+ if (c->push<SubTable> ()->u.alternate.
+ serialize (c,
+ glyphs,
+ alternate_len_list,
+ alternate_glyphs_list))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ bool serialize_ligature (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> first_glyphs,
+ hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+ hb_array_t<const HBGlyphID16> ligatures_list,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
+ if (c->push<SubTable> ()->u.ligature.
+ serialize (c,
+ first_glyphs,
+ ligature_per_first_glyph_count_list,
+ ligatures_list,
+ component_count_list,
+ component_list))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ template <typename context_t>
+ static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+
+ static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
+
+ static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
+ {
+ if (!c->should_visit_lookup (lookup_index))
+ return hb_empty_t ();
+
+ hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
+
+ /* While in theory we should flush here, it will cause timeouts because a recursive
+ * lookup can keep growing the glyph set. Skip, and outer loop will retry up to
+ * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
+ //c->flush ();
+
+ return ret;
+ }
+
+ HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
+
+ bool subset (hb_subset_context_t *c) const
+ { return Lookup::subset<SubTable> (c); }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_SUBSTLOOKUP_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookupSubTable.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookupSubTable.hh
new file mode 100644
index 0000000000..53e963e2a2
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookupSubTable.hh
@@ -0,0 +1,77 @@
+#ifndef OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH
+#define OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH
+
+#include "Common.hh"
+#include "SingleSubst.hh"
+#include "MultipleSubst.hh"
+#include "AlternateSubst.hh"
+#include "LigatureSubst.hh"
+#include "ContextSubst.hh"
+#include "ChainContextSubst.hh"
+#include "ExtensionSubst.hh"
+#include "ReverseChainSingleSubst.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SubstLookupSubTable
+{
+ friend struct ::OT::Lookup;
+ friend struct SubstLookup;
+
+ protected:
+ union {
+ SingleSubst single;
+ MultipleSubst multiple;
+ AlternateSubst alternate;
+ LigatureSubst ligature;
+ ContextSubst context;
+ ChainContextSubst chainContext;
+ ExtensionSubst extension;
+ ReverseChainSingleSubst reverseChainContextSingle;
+ } u;
+ public:
+ DEFINE_SIZE_MIN (0);
+
+ enum Type {
+ Single = 1,
+ Multiple = 2,
+ Alternate = 3,
+ Ligature = 4,
+ Context = 5,
+ ChainContext = 6,
+ Extension = 7,
+ ReverseChainSingle = 8
+ };
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, lookup_type);
+ switch (lookup_type) {
+ case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
+ case Multiple: return_trace (u.multiple.dispatch (c, std::forward<Ts> (ds)...));
+ case Alternate: return_trace (u.alternate.dispatch (c, std::forward<Ts> (ds)...));
+ case Ligature: return_trace (u.ligature.dispatch (c, std::forward<Ts> (ds)...));
+ case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
+ case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
+ case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
+ case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, std::forward<Ts> (ds)...));
+ default: return_trace (c->default_return_value ());
+ }
+ }
+
+ bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c, lookup_type);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
index 14ee6f5e8a..b6a5957c42 100644
--- a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
+++ b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
@@ -2,6 +2,7 @@
#include "hb-aat-map.cc"
#include "hb-blob.cc"
#include "hb-buffer-serialize.cc"
+#include "hb-buffer-verify.cc"
#include "hb-buffer.cc"
#include "hb-common.cc"
#include "hb-draw.cc"
@@ -9,7 +10,6 @@
#include "hb-fallback-shape.cc"
#include "hb-font.cc"
#include "hb-map.cc"
-#include "hb-ms-feature-ranges.cc"
#include "hb-number.cc"
#include "hb-ot-cff1-table.cc"
#include "hb-ot-cff2-table.cc"
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh
index cd36fc8953..b52844e75d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh
@@ -82,7 +82,7 @@ struct BaselineTableFormat2Part
}
protected:
- HBGlyphID stdGlyph; /* The specific glyph index number in this
+ HBGlyphID16 stdGlyph; /* The specific glyph index number in this
* font that is used to set the baseline values.
* This is the standard glyph.
* This glyph must contain a set of control points
@@ -105,7 +105,7 @@ struct BaselineTableFormat3Part
}
protected:
- HBGlyphID stdGlyph; /* ditto */
+ HBGlyphID16 stdGlyph; /* ditto */
HBUINT16 ctlPoints[32]; /* ditto */
Lookup<HBUINT16>
lookupTable; /* Lookup table that maps glyphs to their
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
index e70ce97174..1db0f1df92 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
@@ -96,8 +96,8 @@ struct LookupSegmentSingle
return_trace (c->check_struct (this) && value.sanitize (c, base));
}
- HBGlyphID last; /* Last GlyphID in this segment */
- HBGlyphID first; /* First GlyphID in this segment */
+ HBGlyphID16 last; /* Last GlyphID in this segment */
+ HBGlyphID16 first; /* First GlyphID in this segment */
T value; /* The lookup value (only one) */
public:
DEFINE_SIZE_STATIC (4 + T::static_size);
@@ -162,11 +162,11 @@ struct LookupSegmentArray
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
first <= last &&
- valuesZ.sanitize (c, base, last - first + 1, hb_forward<Ts> (ds)...));
+ valuesZ.sanitize (c, base, last - first + 1, std::forward<Ts> (ds)...));
}
- HBGlyphID last; /* Last GlyphID in this segment */
- HBGlyphID first; /* First GlyphID in this segment */
+ HBGlyphID16 last; /* Last GlyphID in this segment */
+ HBGlyphID16 first; /* First GlyphID in this segment */
NNOffset16To<UnsizedArrayOf<T>>
valuesZ; /* A 16-bit offset from the start of
* the table to the data. */
@@ -225,7 +225,7 @@ struct LookupSingle
return_trace (c->check_struct (this) && value.sanitize (c, base));
}
- HBGlyphID glyph; /* Last GlyphID */
+ HBGlyphID16 glyph; /* Last GlyphID */
T value; /* The lookup value (only one) */
public:
DEFINE_SIZE_STATIC (2 + T::static_size);
@@ -287,7 +287,7 @@ struct LookupFormat8
protected:
HBUINT16 format; /* Format identifier--format = 8 */
- HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */
+ HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
* glyph minus the value of firstGlyph plus 1). */
UnsizedArrayOf<T>
@@ -329,7 +329,7 @@ struct LookupFormat10
protected:
HBUINT16 format; /* Format identifier--format = 8 */
HBUINT16 valueSize; /* Byte size of each value. */
- HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */
+ HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
* glyph minus the value of firstGlyph plus 1). */
UnsizedArrayOf<HBUINT8>
@@ -661,7 +661,7 @@ struct ClassTable
return_trace (c->check_struct (this) && classArray.sanitize (c));
}
protected:
- HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */
+ HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
Array16Of<HBUCHAR> classArray; /* The class codes (indexed by glyph index minus
* firstGlyph). */
public:
@@ -839,7 +839,7 @@ struct StateTableDriver
}
if (!c->in_place)
- buffer->swap_buffers ();
+ buffer->sync ();
}
public:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh
index 556d4ad75b..0bf9bd2912 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh
@@ -100,7 +100,7 @@ struct UnconditionalAddGlyphAction
protected:
ActionSubrecordHeader
header;
- HBGlyphID addGlyph; /* Glyph that should be added if the distance factor
+ HBGlyphID16 addGlyph; /* Glyph that should be added if the distance factor
* is growing. */
public:
@@ -121,11 +121,11 @@ struct ConditionalAddGlyphAction
HBFixed substThreshold; /* Distance growth factor (in ems) at which
* this glyph is replaced and the growth factor
* recalculated. */
- HBGlyphID addGlyph; /* Glyph to be added as kashida. If this value is
+ HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is
* 0xFFFF, no extra glyph will be added. Note that
* generally when a glyph is added, justification
* will need to be redone. */
- HBGlyphID substGlyph; /* Glyph to be substituted for this glyph if the
+ HBGlyphID16 substGlyph; /* Glyph to be substituted for this glyph if the
* growth factor equals or exceeds the value of
* substThreshold. */
public:
@@ -146,7 +146,7 @@ struct DuctileGlyphAction
HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
* This would normally be 0x64756374 ('duct'),
* but you may use any axis the font contains. */
- HBFixed minimumLimit; /* The lowest value for the ductility axis tha
+ HBFixed minimumLimit; /* The lowest value for the ductility axis that
* still yields an acceptable appearance. Normally
* this will be 1.0. */
HBFixed noStretchValue; /* This is the default value that corresponds to
@@ -170,7 +170,7 @@ struct RepeatedAddGlyphAction
ActionSubrecordHeader
header;
HBUINT16 flags; /* Currently unused; set to 0. */
- HBGlyphID glyph; /* Glyph that should be added if the distance factor
+ HBGlyphID16 glyph; /* Glyph that should be added if the distance factor
* is growing. */
public:
DEFINE_SIZE_STATIC (10);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-kerx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-kerx-table.hh
index d0eacf0e61..0354b47d5a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-kerx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-kerx-table.hh
@@ -82,8 +82,8 @@ struct KernPair
}
protected:
- HBGlyphID left;
- HBGlyphID right;
+ HBGlyphID16 left;
+ HBGlyphID16 right;
FWORD value;
public:
DEFINE_SIZE_STATIC (6);
@@ -775,11 +775,11 @@ struct KerxSubTable
unsigned int subtable_type = get_type ();
TRACE_DISPATCH (this, subtable_type);
switch (subtable_type) {
- case 0: return_trace (c->dispatch (u.format0, hb_forward<Ts> (ds)...));
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
- case 4: return_trace (c->dispatch (u.format4, hb_forward<Ts> (ds)...));
- case 6: return_trace (c->dispatch (u.format6, hb_forward<Ts> (ds)...));
+ case 0: return_trace (c->dispatch (u.format0, std::forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ case 6: return_trace (c->dispatch (u.format6, std::forward<Ts> (ds)...));
default: return_trace (c->default_return_value ());
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh
index a807bdcfc5..b77c1f4d44 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh
@@ -243,21 +243,21 @@ struct ContextualSubtable
if (buffer->idx == buffer->len && !mark_set)
return;
- const HBGlyphID *replacement;
+ const HBGlyphID16 *replacement;
replacement = nullptr;
if (Types::extended)
{
if (entry.data.markIndex != 0xFFFF)
{
- const Lookup<HBGlyphID> &lookup = subs[entry.data.markIndex];
+ const Lookup<HBGlyphID16> &lookup = subs[entry.data.markIndex];
replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
}
}
else
{
unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
- const UnsizedArrayOf<HBGlyphID> &subs_old = (const UnsizedArrayOf<HBGlyphID> &) subs;
+ const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs;
replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
if (!replacement->sanitize (&c->sanitizer) || !*replacement)
replacement = nullptr;
@@ -278,14 +278,14 @@ struct ContextualSubtable
{
if (entry.data.currentIndex != 0xFFFF)
{
- const Lookup<HBGlyphID> &lookup = subs[entry.data.currentIndex];
+ const Lookup<HBGlyphID16> &lookup = subs[entry.data.currentIndex];
replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
}
}
else
{
unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
- const UnsizedArrayOf<HBGlyphID> &subs_old = (const UnsizedArrayOf<HBGlyphID> &) subs;
+ const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs;
replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
if (!replacement->sanitize (&c->sanitizer) || !*replacement)
replacement = nullptr;
@@ -315,7 +315,7 @@ struct ContextualSubtable
bool has_glyph_classes;
unsigned int mark;
const ContextualSubtable *table;
- const UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false> &subs;
+ const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false> &subs;
};
bool apply (hb_aat_apply_context_t *c) const
@@ -359,7 +359,7 @@ struct ContextualSubtable
protected:
StateTable<Types, EntryData>
machine;
- NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false>, HBUINT>
+ NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false>, HBUINT>
substitutionTables;
public:
DEFINE_SIZE_STATIC (20);
@@ -531,7 +531,7 @@ struct LigatureSubtable
if (action & (LigActionStore | LigActionLast))
{
ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
- const HBGlyphID &ligatureData = ligature[ligature_idx];
+ const HBGlyphID16 &ligatureData = ligature[ligature_idx];
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
hb_codepoint_t lig = ligatureData;
@@ -565,7 +565,7 @@ struct LigatureSubtable
const LigatureSubtable *table;
const UnsizedArrayOf<HBUINT32> &ligAction;
const UnsizedArrayOf<HBUINT16> &component;
- const UnsizedArrayOf<HBGlyphID> &ligature;
+ const UnsizedArrayOf<HBGlyphID16> &ligature;
unsigned int match_length;
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
};
@@ -597,7 +597,7 @@ struct LigatureSubtable
ligAction; /* Offset to the ligature action table. */
NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT>
component; /* Offset to the component table. */
- NNOffsetTo<UnsizedArrayOf<HBGlyphID>, HBUINT>
+ NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT>
ligature; /* Offset to the actual ligature lists. */
public:
DEFINE_SIZE_STATIC (28);
@@ -620,7 +620,7 @@ struct NoncontextualSubtable
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++)
{
- const HBGlyphID *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
+ const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
if (replacement)
{
info[i].codepoint = *replacement;
@@ -641,7 +641,7 @@ struct NoncontextualSubtable
}
protected:
- Lookup<HBGlyphID> substitute;
+ Lookup<HBGlyphID16> substitute;
public:
DEFINE_SIZE_MIN (2);
};
@@ -744,7 +744,7 @@ struct InsertionSubtable
unsigned int count = (flags & MarkedInsertCount);
if (unlikely ((buffer->max_ops -= count) <= 0)) return;
unsigned int start = entry.data.markedInsertIndex;
- const HBGlyphID *glyphs = &insertionAction[start];
+ const HBGlyphID16 *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
bool before = flags & MarkedInsertBefore;
@@ -772,7 +772,7 @@ struct InsertionSubtable
unsigned int count = (flags & CurrentInsertCount) >> 5;
if (unlikely ((buffer->max_ops -= count) <= 0)) return;
unsigned int start = entry.data.currentInsertIndex;
- const HBGlyphID *glyphs = &insertionAction[start];
+ const HBGlyphID16 *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
bool before = flags & CurrentInsertBefore;
@@ -810,7 +810,7 @@ struct InsertionSubtable
private:
hb_aat_apply_context_t *c;
unsigned int mark;
- const UnsizedArrayOf<HBGlyphID> &insertionAction;
+ const UnsizedArrayOf<HBGlyphID16> &insertionAction;
};
bool apply (hb_aat_apply_context_t *c) const
@@ -836,7 +836,7 @@ struct InsertionSubtable
protected:
StateTable<Types, EntryData>
machine;
- NNOffsetTo<UnsizedArrayOf<HBGlyphID>, HBUINT>
+ NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT>
insertionAction; /* Byte offset from stateHeader to the start of
* the insertion glyph table. */
public:
@@ -906,11 +906,11 @@ struct ChainSubtable
unsigned int subtable_type = get_type ();
TRACE_DISPATCH (this, subtable_type);
switch (subtable_type) {
- case Rearrangement: return_trace (c->dispatch (u.rearrangement, hb_forward<Ts> (ds)...));
- case Contextual: return_trace (c->dispatch (u.contextual, hb_forward<Ts> (ds)...));
- case Ligature: return_trace (c->dispatch (u.ligature, hb_forward<Ts> (ds)...));
- case Noncontextual: return_trace (c->dispatch (u.noncontextual, hb_forward<Ts> (ds)...));
- case Insertion: return_trace (c->dispatch (u.insertion, hb_forward<Ts> (ds)...));
+ case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward<Ts> (ds)...));
+ case Contextual: return_trace (c->dispatch (u.contextual, std::forward<Ts> (ds)...));
+ case Ligature: return_trace (c->dispatch (u.ligature, std::forward<Ts> (ds)...));
+ case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward<Ts> (ds)...));
+ case Insertion: return_trace (c->dispatch (u.insertion, std::forward<Ts> (ds)...));
default: return_trace (c->default_return_value ());
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
index e2d4de2ccd..caff204d67 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
@@ -108,7 +108,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
{HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
{HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT, (hb_aat_layout_feature_selector_t) 7},
{HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
- {HB_TAG ('h','i','s','t'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
+ {HB_TAG ('h','i','s','t'), (hb_aat_layout_feature_type_t) 40, (hb_aat_layout_feature_selector_t) 0, (hb_aat_layout_feature_selector_t) 1},
{HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF},
{HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
{HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION, HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION},
@@ -170,6 +170,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
{HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF},
{HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
{HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
+ {HB_TAG ('v','r','t','r'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, (hb_aat_layout_feature_selector_t) 2, (hb_aat_layout_feature_selector_t) 3},
{HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
index bbe097fe01..c40a55cd1f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
@@ -34,6 +34,10 @@
#include "hb-null.hh"
#include "hb-number.hh"
+#include <algorithm>
+#include <initializer_list>
+#include <functional>
+#include <new>
/*
* Flags
@@ -125,7 +129,7 @@ struct BEInt<Type, 2>
template <typename Type>
struct BEInt<Type, 3>
{
- static_assert (!hb_is_signed (Type), "");
+ static_assert (!std::is_signed<Type>::value, "");
public:
BEInt () = default;
constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
@@ -179,7 +183,7 @@ struct
{
/* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
template <typename T> constexpr auto
- operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )
+ operator () (T&& v) const HB_AUTO_RETURN ( std::forward<T> (v) )
}
HB_FUNCOBJ (hb_identity);
struct
@@ -203,19 +207,30 @@ HB_FUNCOBJ (hb_ridentity);
struct
{
template <typename T> constexpr bool
- operator () (T&& v) const { return bool (hb_forward<T> (v)); }
+ operator () (T&& v) const { return bool (std::forward<T> (v)); }
}
HB_FUNCOBJ (hb_bool);
+template <typename T>
+static inline
+T hb_coerce (const T v) { return v; }
+template <typename T, typename V,
+ hb_enable_if (!hb_is_same (hb_decay<T>, hb_decay<V>) && std::is_pointer<V>::value)>
+static inline
+T hb_coerce (const V v) { return *v; }
+
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 ())
+
+ template <typename T> constexpr auto
+ impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
template <typename T,
- hb_enable_if (hb_is_integral (T))> constexpr auto
+ hb_enable_if (std::is_integral<T>::value)> constexpr auto
impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
(
/* Knuth's multiplicative method: */
@@ -237,26 +252,26 @@ struct
/* Pointer-to-member-function. */
template <typename Appl, typename T, typename ...Ts> auto
impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
- ((hb_deref (hb_forward<T> (v)).*hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
+ ((hb_deref (std::forward<T> (v)).*std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
/* Pointer-to-member. */
template <typename Appl, typename T> auto
impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
- ((hb_deref (hb_forward<T> (v))).*hb_forward<Appl> (a))
+ ((hb_deref (std::forward<T> (v))).*std::forward<Appl> (a))
/* Operator(). */
template <typename Appl, typename ...Ts> auto
impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
- (hb_deref (hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
+ (hb_deref (std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
public:
template <typename Appl, typename ...Ts> auto
operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
(
- impl (hb_forward<Appl> (a),
+ impl (std::forward<Appl> (a),
hb_prioritize,
- hb_forward<Ts> (ds)...)
+ std::forward<Ts> (ds)...)
)
}
HB_FUNCOBJ (hb_invoke);
@@ -275,9 +290,9 @@ struct hb_partial_t
hb_declval (V),
hb_declval (Ts)...))
{
- return hb_invoke (hb_forward<Appl> (a),
- hb_forward<V> (v),
- hb_forward<Ts> (ds)...);
+ return hb_invoke (std::forward<Appl> (a),
+ std::forward<V> (v),
+ std::forward<Ts> (ds)...);
}
template <typename T0, typename ...Ts,
unsigned P = Pos,
@@ -287,10 +302,10 @@ struct hb_partial_t
hb_declval (V),
hb_declval (Ts)...))
{
- return hb_invoke (hb_forward<Appl> (a),
- hb_forward<T0> (d0),
- hb_forward<V> (v),
- hb_forward<Ts> (ds)...);
+ return hb_invoke (std::forward<Appl> (a),
+ std::forward<T0> (d0),
+ std::forward<V> (v),
+ std::forward<Ts> (ds)...);
}
private:
@@ -324,14 +339,14 @@ auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
#define HB_PARTIALIZE(Pos) \
template <typename _T> \
decltype(auto) operator () (_T&& _v) const \
- { return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \
+ { return hb_partial<Pos> (this, std::forward<_T> (_v)); } \
static_assert (true, "")
#else
/* https://github.com/harfbuzz/harfbuzz/issues/1724 */
#define HB_PARTIALIZE(Pos) \
template <typename _T> \
auto operator () (_T&& _v) const HB_AUTO_RETURN \
- (hb_partial<Pos> (+this, hb_forward<_T> (_v))) \
+ (hb_partial<Pos> (+this, std::forward<_T> (_v))) \
static_assert (true, "")
#endif
@@ -343,22 +358,22 @@ struct
template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(
- hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v))
+ hb_deref (std::forward<Pred> (p)).has (std::forward<Val> (v))
)
template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
(
- hb_invoke (hb_forward<Pred> (p),
- hb_forward<Val> (v))
+ hb_invoke (std::forward<Pred> (p),
+ std::forward<Val> (v))
)
public:
template <typename Pred, typename Val> auto
operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
- impl (hb_forward<Pred> (p),
- hb_forward<Val> (v),
+ impl (std::forward<Pred> (p),
+ std::forward<Val> (v),
hb_prioritize)
)
}
@@ -371,22 +386,22 @@ struct
template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(
- hb_has (hb_forward<Pred> (p),
- hb_forward<Val> (v))
+ hb_has (std::forward<Pred> (p),
+ std::forward<Val> (v))
)
template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
(
- hb_forward<Pred> (p) == hb_forward<Val> (v)
+ std::forward<Pred> (p) == std::forward<Val> (v)
)
public:
template <typename Pred, typename Val> auto
operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
- impl (hb_forward<Pred> (p),
- hb_forward<Val> (v),
+ impl (std::forward<Pred> (p),
+ std::forward<Val> (v),
hb_prioritize)
)
}
@@ -399,20 +414,20 @@ struct
template <typename Proj, typename Val> auto
impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
(
- hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v))
+ hb_deref (std::forward<Proj> (f)).get (std::forward<Val> (v))
)
template <typename Proj, typename Val> auto
impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(
- hb_invoke (hb_forward<Proj> (f),
- hb_forward<Val> (v))
+ hb_invoke (std::forward<Proj> (f),
+ std::forward<Val> (v))
)
template <typename Proj, typename Val> auto
impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
(
- hb_forward<Proj> (f)[hb_forward<Val> (v)]
+ std::forward<Proj> (f)[std::forward<Val> (v)]
)
public:
@@ -420,8 +435,8 @@ struct
template <typename Proj, typename Val> auto
operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN
(
- impl (hb_forward<Proj> (f),
- hb_forward<Val> (v),
+ impl (std::forward<Proj> (f),
+ std::forward<Val> (v),
hb_prioritize)
)
}
@@ -432,21 +447,27 @@ struct
private:
template <typename T1, typename T2> auto
+ impl (T1&& v1, T2 &&v2, hb_priority<3>) const HB_AUTO_RETURN
+ (
+ std::forward<T2> (v2).cmp (std::forward<T1> (v1)) == 0
+ )
+
+ template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
(
- hb_forward<T2> (v2).cmp (hb_forward<T1> (v1)) == 0
+ std::forward<T1> (v1).cmp (std::forward<T2> (v2)) == 0
)
template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
(
- hb_forward<T1> (v1).cmp (hb_forward<T2> (v2)) == 0
+ std::forward<T1> (v1) == std::forward<T2> (v2)
)
template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
(
- hb_forward<T1> (v1) == hb_forward<T2> (v2)
+ std::forward<T2> (v2) == std::forward<T1> (v1)
)
public:
@@ -454,8 +475,8 @@ struct
template <typename T1, typename T2> auto
operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN
(
- impl (hb_forward<T1> (v1),
- hb_forward<T2> (v2),
+ impl (std::forward<T1> (v1),
+ std::forward<T2> (v2),
hb_prioritize)
)
}
@@ -469,11 +490,15 @@ struct hb_pair_t
typedef T2 second_t;
typedef hb_pair_t<T1, T2> pair_t;
+ template <typename U1 = T1, typename U2 = T2,
+ hb_enable_if (std::is_default_constructible<U1>::value &&
+ std::is_default_constructible<U2>::value)>
+ hb_pair_t () : first (), second () {}
hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
template <typename Q1, typename Q2,
hb_enable_if (hb_is_convertible (T1, Q1) &&
- hb_is_convertible (T2, T2))>
+ hb_is_convertible (T2, Q2))>
operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
hb_pair_t<T1, T2> reverse () const
@@ -515,24 +540,34 @@ struct
{
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a <= b ? hb_forward<T> (a) : hb_forward<T2> (b))
+ (a <= b ? std::forward<T> (a) : std::forward<T2> (b))
}
HB_FUNCOBJ (hb_min);
struct
{
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a >= b ? hb_forward<T> (a) : hb_forward<T2> (b))
+ (a >= b ? std::forward<T> (a) : std::forward<T2> (b))
}
HB_FUNCOBJ (hb_max);
struct
{
template <typename T, typename T2, typename T3> constexpr auto
operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN
- (hb_min (hb_max (hb_forward<T> (x), hb_forward<T2> (min)), hb_forward<T3> (max)))
+ (hb_min (hb_max (std::forward<T> (x), std::forward<T2> (min)), std::forward<T3> (max)))
}
HB_FUNCOBJ (hb_clamp);
+struct
+{
+ template <typename T> void
+ operator () (T& a, T& b) const
+ {
+ using std::swap; // allow ADL
+ swap (a, b);
+ }
+}
+HB_FUNCOBJ (hb_swap);
/*
* Bithacks.
@@ -795,7 +830,7 @@ hb_ceil_to_4 (unsigned int v)
template <typename T> static inline bool
hb_in_range (T u, T lo, T hi)
{
- static_assert (!hb_is_signed<T>::value, "");
+ static_assert (!std::is_signed<T>::value, "");
/* The casts below are important as if T is smaller than int,
* the subtract results will become a signed int! */
@@ -857,7 +892,7 @@ hb_bsearch_impl (unsigned *pos, /* Out */
#pragma GCC diagnostic ignored "-Wcast-align"
V* p = (V*) (((const char *) base) + (mid * stride));
#pragma GCC diagnostic pop
- int c = compar ((const void *) hb_addressof (key), (const void *) p, ds...);
+ int c = compar ((const void *) std::addressof (key), (const void *) p, ds...);
if (c < 0)
max = mid - 1;
else if (c > 0)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-array.hh
index ab0dd6ebe3..1d1476d7cd 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-array.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-array.hh
@@ -50,14 +50,20 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
/*
* Constructors.
*/
- hb_array_t () : arrayZ (nullptr), length (0), backwards_length (0) {}
- hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_), backwards_length (0) {}
+ hb_array_t () = default;
+ hb_array_t (const hb_array_t&) = default;
+ ~hb_array_t () = default;
+ hb_array_t& operator= (const hb_array_t&) = default;
+ hb_array_t& operator= (hb_array_t&&) = default;
+
+ constexpr hb_array_t (std::nullptr_t) : hb_array_t () {}
+ constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
template <unsigned int length_>
- hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_), backwards_length (0) {}
+ constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {}
template <typename U,
hb_enable_if (hb_is_cr_convertible(U, Type))>
- hb_array_t (const hb_array_t<U> &o) :
+ constexpr hb_array_t (const hb_array_t<U> &o) :
hb_iter_with_fallback_t<hb_array_t, Type&> (),
arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {}
template <typename U,
@@ -281,9 +287,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
*/
public:
- Type *arrayZ;
- unsigned int length;
- unsigned int backwards_length;
+ Type *arrayZ = nullptr;
+ unsigned int length = 0;
+ unsigned int backwards_length = 0;
};
template <typename T> inline hb_array_t<T>
hb_array (T *array, unsigned int length)
@@ -302,14 +308,20 @@ struct hb_sorted_array_t :
static constexpr bool is_random_access_iterator = true;
static constexpr bool is_sorted_iterator = true;
- hb_sorted_array_t () : hb_array_t<Type> () {}
- hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
+ hb_sorted_array_t () = default;
+ hb_sorted_array_t (const hb_sorted_array_t&) = default;
+ ~hb_sorted_array_t () = default;
+ hb_sorted_array_t& operator= (const hb_sorted_array_t&) = default;
+ hb_sorted_array_t& operator= (hb_sorted_array_t&&) = default;
+
+ constexpr hb_sorted_array_t (std::nullptr_t) : hb_sorted_array_t () {}
+ constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
template <unsigned int length_>
- hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
+ constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
template <typename U,
hb_enable_if (hb_is_cr_convertible(U, Type))>
- hb_sorted_array_t (const hb_array_t<U> &o) :
+ constexpr hb_sorted_array_t (const hb_array_t<U> &o) :
hb_iter_t<hb_sorted_array_t, Type&> (),
hb_array_t<Type> (o) {}
template <typename U,
@@ -400,7 +412,7 @@ bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
return true;
}
-/* TODO Specialize opeator== for hb_bytes_t and hb_ubytes_t. */
+/* TODO Specialize operator== for hb_bytes_t and hb_ubytes_t. */
template <>
inline uint32_t hb_array_t<const char>::hash () const {
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
index 93265f655f..e640d1b586 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
@@ -102,20 +102,12 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
-#elif defined(HB_NO_MT)
+#else /* defined(HB_NO_MT) */
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
-
#define _hb_memory_barrier() do {} while (0)
-
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
-
-#else
-
-#error "Could not find any system to define atomic_int macros."
-#error "Check hb-atomic.hh for possible resolutions."
-
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
index d409880751..a9e1278de7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
@@ -33,21 +33,6 @@
/* Bi-directional map */
struct hb_bimap_t
{
- hb_bimap_t () { init (); }
- ~hb_bimap_t () { fini (); }
-
- void init ()
- {
- forw_map.init ();
- back_map.init ();
- }
-
- void fini ()
- {
- forw_map.fini ();
- back_map.fini ();
- }
-
void reset ()
{
forw_map.reset ();
@@ -99,14 +84,6 @@ struct hb_bimap_t
/* Inremental bimap: only lhs is given, rhs is incrementally assigned */
struct hb_inc_bimap_t : hb_bimap_t
{
- hb_inc_bimap_t () { init (); }
-
- void init ()
- {
- hb_bimap_t::init ();
- next_value = 0;
- }
-
/* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
* Return the rhs value as the result.
*/
@@ -165,7 +142,7 @@ struct hb_inc_bimap_t : hb_bimap_t
}
protected:
- unsigned int next_value;
+ unsigned int next_value = 0;
};
#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 263be3d044..9759836654 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
@@ -86,6 +86,72 @@ struct hb_bit_page_t
void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
{ if (v) add_range (a, b); else del_range (a, b); }
+
+ // Writes out page values to the array p. Returns the number of values
+ // written. At most size codepoints will be written.
+ unsigned int write (uint32_t base,
+ unsigned int start_value,
+ hb_codepoint_t *p,
+ unsigned int size) const
+ {
+ unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_bit = start_value & ELT_MASK;
+ unsigned int count = 0;
+ for (unsigned i = start_v; i < len () && count < size; i++)
+ {
+ elt_t bits = v[i];
+ uint32_t v_base = base | (i << ELT_BITS_LOG_2);
+ for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
+ {
+ if ((elt_t(1) << j) & bits) {
+ *p++ = v_base | j;
+ count++;
+ }
+ }
+ start_bit = 0;
+ }
+ return count;
+ }
+
+ // Writes out the values NOT in this page to the array p. Returns the
+ // number of values written. At most size codepoints will be written.
+ // Returns the number of codepoints written. next_value holds the next value
+ // that should be written (if not present in this page). This is used to fill
+ // any missing value gaps between this page and the previous page, if any.
+ // next_value is updated to one more than the last value present in this page.
+ unsigned int write_inverted (uint32_t base,
+ unsigned int start_value,
+ hb_codepoint_t *p,
+ unsigned int size,
+ hb_codepoint_t *next_value) const
+ {
+ unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_bit = start_value & ELT_MASK;
+ unsigned int count = 0;
+ for (unsigned i = start_v; i < len () && count < size; i++)
+ {
+ elt_t bits = v[i];
+ uint32_t v_offset = i << ELT_BITS_LOG_2;
+ for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
+ {
+ if ((elt_t(1) << j) & bits)
+ {
+ hb_codepoint_t value = base | v_offset | j;
+ // Emit all the missing values from next_value up to value - 1.
+ for (hb_codepoint_t k = *next_value; k < value && count < size; k++)
+ {
+ *p++ = k;
+ count++;
+ }
+ // Skip over this value;
+ *next_value = value + 1;
+ }
+ }
+ start_bit = 0;
+ }
+ return count;
+ }
+
bool is_equal (const hb_bit_page_t &other) const
{
return 0 == hb_memcmp (&v, &other.v, sizeof (v));
@@ -179,6 +245,9 @@ struct hb_bit_page_t
typedef unsigned long long elt_t;
static constexpr unsigned PAGE_BITS = 512;
static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
+ static constexpr unsigned PAGE_BITS_LOG_2 = 9;
+ static_assert (1 << PAGE_BITS_LOG_2 == PAGE_BITS, "");
+ static constexpr unsigned PAGE_BITMASK = PAGE_BITS - 1;
static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
@@ -186,7 +255,10 @@ struct hb_bit_page_t
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
+ static constexpr unsigned ELT_BITS_LOG_2 = 6;
+ static_assert (1 << ELT_BITS_LOG_2 == ELT_BITS, "");
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
+
static constexpr unsigned BITS = sizeof (vector_t) * 8;
static constexpr unsigned MASK = BITS - 1;
static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
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 f48b72fe63..4a4ce34053 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh
@@ -35,10 +35,20 @@
struct hb_bit_set_invertible_t
{
hb_bit_set_t s;
- bool inverted;
-
- hb_bit_set_invertible_t () { init (); }
- ~hb_bit_set_invertible_t () { fini (); }
+ bool inverted = false;
+
+ hb_bit_set_invertible_t () = default;
+ hb_bit_set_invertible_t (hb_bit_set_invertible_t& o) = default;
+ hb_bit_set_invertible_t (hb_bit_set_invertible_t&& o) = default;
+ hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default;
+ hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& o) = default;
+ friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b)
+ {
+ if (likely (!a.s.successful || !b.s.successful))
+ return;
+ hb_swap (a.inverted, b.inverted);
+ hb_swap (a.s, b.s);
+ }
void init () { s.init (); inverted = false; }
void fini () { s.fini (); }
@@ -313,6 +323,14 @@ struct hb_bit_set_invertible_t
return true;
}
+ unsigned int next_many (hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size) const
+ {
+ return inverted ? s.next_many_inverted (codepoint, out, size)
+ : s.next_many (codepoint, out, size);
+ }
+
static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID;
/*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
index c21778d88e..fcaff9f3be 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
@@ -35,13 +35,22 @@
struct hb_bit_set_t
{
- hb_bit_set_t () { init (); }
- ~hb_bit_set_t () { fini (); }
+ hb_bit_set_t () = default;
+ ~hb_bit_set_t () = default;
hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other); }
- void operator= (const hb_bit_set_t& other) { set (other); }
- // TODO Add move construtor/assign
- // TODO Add constructor for Iterator; with specialization for (sorted) vector / array?
+ hb_bit_set_t ( hb_bit_set_t&& other) : hb_bit_set_t () { hb_swap (*this, other); }
+ hb_bit_set_t& operator= (const hb_bit_set_t& other) { set (other); return *this; }
+ hb_bit_set_t& operator= (hb_bit_set_t&& other) { hb_swap (*this, other); return *this; }
+ friend void swap (hb_bit_set_t &a, hb_bit_set_t &b)
+ {
+ if (likely (!a.successful || !b.successful))
+ return;
+ hb_swap (a.population, b.population);
+ hb_swap (a.last_page_lookup, b.last_page_lookup);
+ hb_swap (a.page_map, b.page_map);
+ hb_swap (a.pages, b.pages);
+ }
void init ()
{
@@ -67,9 +76,9 @@ struct hb_bit_set_t
uint32_t index;
};
- bool successful; /* Allocations successful */
- mutable unsigned int population;
- mutable unsigned int last_page_lookup;
+ bool successful = true; /* Allocations successful */
+ mutable unsigned int population = 0;
+ mutable unsigned int last_page_lookup = 0;
hb_sorted_vector_t<page_map_t> page_map;
hb_vector_t<page_t> pages;
@@ -194,7 +203,7 @@ struct hb_bit_set_t
bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
- if (!count) return true;
+ if (unlikely (!count)) return true;
dirty ();
hb_codepoint_t g = *array;
hb_codepoint_t last_g = g;
@@ -213,7 +222,7 @@ struct hb_bit_set_t
if (v || page) /* The v check is to optimize out the page check if v is true. */
page->add (g);
- array = (const T *) ((const char *) array + stride);
+ array = &StructAtOffsetUnaligned<T> (array, stride);
count--;
}
while (count && (g = *array, g < end));
@@ -691,6 +700,99 @@ struct hb_bit_set_t
return true;
}
+ unsigned int next_many (hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size) const
+ {
+ // By default, start at the first bit of the first page of values.
+ unsigned int start_page = 0;
+ unsigned int start_page_value = 0;
+ if (unlikely (codepoint != INVALID))
+ {
+ const auto* page_map_array = page_map.arrayZ;
+ unsigned int major = get_major (codepoint);
+ unsigned int i = last_page_lookup;
+ if (unlikely (i >= page_map.length || page_map_array[i].major != major))
+ {
+ page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
+ if (i >= page_map.length)
+ return 0; // codepoint is greater than our max element.
+ }
+ start_page = i;
+ start_page_value = page_remainder (codepoint + 1);
+ if (unlikely (start_page_value == 0))
+ {
+ // The export-after value was last in the page. Start on next page.
+ start_page++;
+ start_page_value = 0;
+ }
+ }
+
+ unsigned int initial_size = size;
+ for (unsigned int i = start_page; i < page_map.length && size; i++)
+ {
+ uint32_t base = major_start (page_map[i].major);
+ unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size);
+ out += n;
+ size -= n;
+ start_page_value = 0;
+ }
+ return initial_size - size;
+ }
+
+ unsigned int next_many_inverted (hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size) const
+ {
+ unsigned int initial_size = size;
+ // By default, start at the first bit of the first page of values.
+ unsigned int start_page = 0;
+ unsigned int start_page_value = 0;
+ if (unlikely (codepoint != INVALID))
+ {
+ const auto* page_map_array = page_map.arrayZ;
+ unsigned int major = get_major (codepoint);
+ unsigned int i = last_page_lookup;
+ if (unlikely (i >= page_map.length || page_map_array[i].major != major))
+ {
+ page_map.bfind(major, &i, HB_NOT_FOUND_STORE_CLOSEST);
+ if (unlikely (i >= page_map.length))
+ {
+ // codepoint is greater than our max element.
+ while (++codepoint != INVALID && size)
+ {
+ *out++ = codepoint;
+ size--;
+ }
+ return initial_size - size;
+ }
+ }
+ start_page = i;
+ start_page_value = page_remainder (codepoint + 1);
+ if (unlikely (start_page_value == 0))
+ {
+ // The export-after value was last in the page. Start on next page.
+ start_page++;
+ start_page_value = 0;
+ }
+ }
+
+ hb_codepoint_t next_value = codepoint + 1;
+ for (unsigned int i=start_page; i<page_map.length && size; i++)
+ {
+ uint32_t base = major_start (page_map[i].major);
+ unsigned int n = pages[page_map[i].index].write_inverted (base, start_page_value, out, size, &next_value);
+ out += n;
+ size -= n;
+ start_page_value = 0;
+ }
+ while (next_value < HB_SET_VALUE_INVALID && size) {
+ *out++ = next_value++;
+ size--;
+ }
+ return initial_size - size;
+ }
+
bool has_population () const { return population != UINT_MAX; }
unsigned int get_population () const
{
@@ -800,8 +902,9 @@ struct hb_bit_set_t
}
page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
- unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
- hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
+ unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; }
+ unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; }
+ hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; }
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
index f120002d17..65e44c7f6a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
@@ -631,7 +631,7 @@ hb_blob_create_from_file_or_fail (const char *file_name)
Allison Lortie permission but changed a lot to suit our need. */
#if defined(HAVE_MMAP) && !defined(HB_NO_MMAP)
hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t));
- if (unlikely (!file)) return hb_blob_get_empty ();
+ if (unlikely (!file)) return nullptr;
int fd = open (file_name, O_RDONLY | O_BINARY, 0);
if (unlikely (fd == -1)) goto fail_without_close;
@@ -671,7 +671,7 @@ fail_without_close:
#elif defined(_WIN32) && !defined(HB_NO_MMAP)
hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t));
- if (unlikely (!file)) return hb_blob_get_empty ();
+ if (unlikely (!file)) return nullptr;
HANDLE fd;
unsigned int size = strlen (file_name) + 1;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh
index b599e9667c..06a605e225 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh
@@ -478,7 +478,7 @@ _resume:
case 18:
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -535,7 +535,7 @@ _resume:
case 16:
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -635,7 +635,7 @@ _resume:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -645,7 +645,7 @@ _resume:
case 17:
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -674,7 +674,7 @@ _resume:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -701,7 +701,7 @@ _resume:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -733,7 +733,7 @@ _again:
case 16:
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -820,7 +820,7 @@ _again:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
new file mode 100644
index 0000000000..dea2c11c35
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
@@ -0,0 +1,422 @@
+/*
+ * Copyright © 2022 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_BUFFER_VERIFY
+
+#include "hb-buffer.hh"
+
+
+#define BUFFER_VERIFY_ERROR "buffer verify error: "
+static inline void
+buffer_verify_error (hb_buffer_t *buffer,
+ hb_font_t *font,
+ const char *fmt,
+ ...) HB_PRINTF_FUNC(3, 4);
+
+static inline void
+buffer_verify_error (hb_buffer_t *buffer,
+ hb_font_t *font,
+ const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ if (buffer->messaging ())
+ {
+ buffer->message_impl (font, fmt, ap);
+ }
+ else
+ {
+ fprintf (stderr, "harfbuzz ");
+ vfprintf (stderr, fmt, ap);
+ fprintf (stderr, "\n");
+ }
+ va_end (ap);
+}
+
+static bool
+buffer_verify_monotone (hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+ /* Check that clusters are monotone. */
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
+ buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ for (unsigned int i = 1; i < num_glyphs; i++)
+ if (info[i-1].cluster != info[i].cluster &&
+ (info[i-1].cluster < info[i].cluster) != is_forward)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool
+buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
+ hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+{
+ if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
+ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ /* Cannot perform this check without monotone clusters. */
+ return true;
+ }
+
+ /* Check that breaking up shaping at safe-to-break is indeed safe. */
+
+ hb_buffer_t *fragment = hb_buffer_create_similar (buffer);
+ hb_buffer_set_flags (fragment, hb_buffer_get_flags (fragment) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
+ hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY);
+
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ unsigned int num_chars;
+ hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars);
+
+ /* Chop text and shape fragments. */
+ bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+ unsigned int start = 0;
+ unsigned int text_start = forward ? 0 : num_chars;
+ unsigned int text_end = text_start;
+ for (unsigned int end = 1; end < num_glyphs + 1; end++)
+ {
+ if (end < num_glyphs &&
+ (info[end].cluster == info[end-1].cluster ||
+ info[end-(forward?0:1)].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK))
+ continue;
+
+ /* Shape segment corresponding to glyphs start..end. */
+ if (end == num_glyphs)
+ {
+ if (forward)
+ text_end = num_chars;
+ else
+ text_start = 0;
+ }
+ else
+ {
+ if (forward)
+ {
+ unsigned int cluster = info[end].cluster;
+ while (text_end < num_chars && text[text_end].cluster < cluster)
+ text_end++;
+ }
+ else
+ {
+ unsigned int cluster = info[end - 1].cluster;
+ while (text_start && text[text_start - 1].cluster >= cluster)
+ text_start--;
+ }
+ }
+ assert (text_start < text_end);
+
+ if (0)
+ printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
+
+ hb_buffer_clear_contents (fragment);
+
+ hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
+ if (0 < text_start)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
+ if (text_end < num_chars)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
+ 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;
+ }
+ hb_buffer_append (reconstruction, fragment, 0, -1);
+
+ start = end;
+ if (forward)
+ text_start = text_end;
+ else
+ text_end = text_start;
+ }
+
+ bool ret = true;
+ hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+ if (diff)
+ {
+ 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);
+ }
+
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+
+ return ret;
+}
+
+static bool
+buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
+ hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+{
+ if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
+ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ /* Cannot perform this check without monotone clusters. */
+ return true;
+ }
+
+ /* Check that shuffling up text before shaping at safe-to-concat points
+ * is indeed safe. */
+
+ /* This is what we do:
+ *
+ * 1. We shape text once. Then segment the text at all the safe-to-concat
+ * points;
+ *
+ * 2. Then we create two buffers, one containing all the even segments and
+ * one all the odd segments.
+ *
+ * 3. Because all these segments were safe-to-concat at both ends, we
+ * expect that concatenating them and shaping should NOT change the
+ * shaping results of each segment. As such, we expect that after
+ * shaping the two buffers, we still get cluster boundaries at the
+ * segment boundaries, and that those all are safe-to-concat points.
+ * Moreover, that there are NOT any safe-to-concat points within the
+ * segments.
+ *
+ * 4. Finally, we reconstruct the shaping results of the original text by
+ * simply interleaving the shaping results of the segments from the two
+ * buffers, and assert that the total shaping results is the same as
+ * the one from original buffer in step 1.
+ */
+
+ hb_buffer_t *fragments[2] {hb_buffer_create_similar (buffer),
+ hb_buffer_create_similar (buffer)};
+ hb_buffer_set_flags (fragments[0], hb_buffer_get_flags (fragments[0]) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (fragments[1], hb_buffer_get_flags (fragments[1]) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
+ hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_segment_properties_t props;
+ hb_buffer_get_segment_properties (buffer, &props);
+ hb_buffer_set_segment_properties (fragments[0], &props);
+ hb_buffer_set_segment_properties (fragments[1], &props);
+ hb_buffer_set_segment_properties (reconstruction, &props);
+
+ unsigned num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ unsigned num_chars;
+ hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars);
+
+ bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+
+ if (!forward)
+ hb_buffer_reverse (buffer);
+
+ /*
+ * Split text into segments and collect into to fragment streams.
+ */
+ {
+ unsigned fragment_idx = 0;
+ unsigned start = 0;
+ unsigned text_start = 0;
+ unsigned text_end = 0;
+ for (unsigned end = 1; end < num_glyphs + 1; end++)
+ {
+ if (end < num_glyphs &&
+ (info[end].cluster == info[end-1].cluster ||
+ info[end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT))
+ continue;
+
+ /* Accumulate segment corresponding to glyphs start..end. */
+ if (end == num_glyphs)
+ text_end = num_chars;
+ else
+ {
+ unsigned cluster = info[end].cluster;
+ while (text_end < num_chars && text[text_end].cluster < cluster)
+ text_end++;
+ }
+ assert (text_start < text_end);
+
+ if (0)
+ printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
+
+#if 0
+ hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
+ if (0 < text_start)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
+ if (text_end < num_chars)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
+ hb_buffer_set_flags (fragment, flags);
+#endif
+
+ hb_buffer_append (fragments[fragment_idx], text_buffer, text_start, text_end);
+
+ start = end;
+ text_start = text_end;
+ fragment_idx = 1 - fragment_idx;
+ }
+ }
+
+ bool ret = true;
+ hb_buffer_diff_flags_t diff;
+
+ /*
+ * 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;
+ }
+ 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;
+ goto out;
+ }
+
+ if (!forward)
+ {
+ hb_buffer_reverse (fragments[0]);
+ hb_buffer_reverse (fragments[1]);
+ }
+
+ /*
+ * Reconstruct results.
+ */
+ {
+ unsigned fragment_idx = 0;
+ unsigned fragment_start[2] {0, 0};
+ unsigned fragment_num_glyphs[2];
+ hb_glyph_info_t *fragment_info[2];
+ for (unsigned i = 0; i < 2; i++)
+ fragment_info[i] = hb_buffer_get_glyph_infos (fragments[i], &fragment_num_glyphs[i]);
+ while (fragment_start[0] < fragment_num_glyphs[0] ||
+ fragment_start[1] < fragment_num_glyphs[1])
+ {
+ unsigned fragment_end = fragment_start[fragment_idx] + 1;
+ while (fragment_end < fragment_num_glyphs[fragment_idx] &&
+ (fragment_info[fragment_idx][fragment_end].cluster == fragment_info[fragment_idx][fragment_end - 1].cluster ||
+ fragment_info[fragment_idx][fragment_end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT))
+ fragment_end++;
+
+ hb_buffer_append (reconstruction, fragments[fragment_idx], fragment_start[fragment_idx], fragment_end);
+
+ fragment_start[fragment_idx] = fragment_end;
+ fragment_idx = 1 - fragment_idx;
+ }
+ }
+
+ if (!forward)
+ {
+ hb_buffer_reverse (buffer);
+ hb_buffer_reverse (reconstruction);
+ }
+
+ /*
+ * Diff results.
+ */
+ diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+ if (diff)
+ {
+ 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);
+ }
+
+
+out:
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragments[0]);
+ hb_buffer_destroy (fragments[1]);
+
+ return ret;
+}
+
+bool
+hb_buffer_t::verify (hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+{
+ bool ret = true;
+ if (!buffer_verify_monotone (this, font))
+ ret = false;
+ if (!buffer_verify_unsafe_to_break (this, text_buffer, font, features, num_features, shapers))
+ ret = false;
+ if ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) != 0 &&
+ !buffer_verify_unsafe_to_concat (this, text_buffer, font, features, num_features, shapers))
+ ret = false;
+ if (!ret)
+ {
+ unsigned len = text_buffer->len;
+ hb_vector_t<char> bytes;
+ if (likely (bytes.resize (len * 10 + 16)))
+ {
+ hb_buffer_serialize_unicode (text_buffer,
+ 0, len,
+ bytes.arrayZ, bytes.length,
+ &len,
+ HB_BUFFER_SERIALIZE_FORMAT_TEXT,
+ HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS);
+ buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ);
+ }
+ }
+ return ret;
+}
+
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
index c6591ca230..6a9ee3ccc8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
@@ -86,7 +86,46 @@ hb_segment_properties_hash (const hb_segment_properties_t *p)
(intptr_t) (p->language);
}
+/**
+ * hb_segment_properties_overlay:
+ * @p: #hb_segment_properties_t to fill in.
+ * @src: #hb_segment_properties_t to fill in from.
+ *
+ * Fills in missing fields of @p from @src in a considered manner.
+ *
+ * First, if @p does not have direction set, direction is copied from @src.
+ *
+ * Next, if @p and @src have the same direction (which can be unset), if @p
+ * does not have script set, script is copied from @src.
+ *
+ * Finally, if @p and @src have the same direction and script (which either
+ * can be unset), if @p does not have language set, language is copied from
+ * @src.
+ *
+ * Since: 3.3.0
+ **/
+void
+hb_segment_properties_overlay (hb_segment_properties_t *p,
+ const hb_segment_properties_t *src)
+{
+ if (unlikely (!p || !src))
+ return;
+
+ if (!p->direction)
+ p->direction = src->direction;
+ if (p->direction != src->direction)
+ return;
+
+ if (!p->script)
+ p->script = src->script;
+
+ if (p->script != src->script)
+ return;
+
+ if (!p->language)
+ p->language = src->language;
+}
/* Here is how the buffer works internally:
*
@@ -96,14 +135,14 @@ hb_segment_properties_hash (const hb_segment_properties_t *p)
* As an optimization, both info and out_info may point to the
* same piece of memory, which is owned by info. This remains the
* case as long as out_len doesn't exceed i at any time.
- * In that case, swap_buffers() is mostly no-op and the glyph operations
+ * In that case, sync() is mostly no-op and the glyph operations
* operate mostly in-place.
*
* As soon as out_info gets longer than info, out_info is moved over
* to an alternate buffer (which we reuse the pos buffer for), and its
* current contents (out_len entries) are copied to the new place.
*
- * This should all remain transparent to the user. swap_buffers() then
+ * This should all remain transparent to the user. sync() then
* switches info over to out_info and does housekeeping.
*/
@@ -217,13 +256,27 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size)
/* HarfBuzz-Internal API */
void
+hb_buffer_t::similar (const hb_buffer_t &src)
+{
+ hb_unicode_funcs_destroy (unicode);
+ unicode = hb_unicode_funcs_reference (src.unicode);
+ flags = src.flags;
+ cluster_level = src.cluster_level;
+ replacement = src.invisible;
+ invisible = src.invisible;
+ not_found = src.not_found;
+}
+
+void
hb_buffer_t::reset ()
{
hb_unicode_funcs_destroy (unicode);
unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ());
flags = HB_BUFFER_FLAG_DEFAULT;
+ cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
invisible = 0;
+ not_found = 0;
clear ();
}
@@ -231,11 +284,10 @@ hb_buffer_t::reset ()
void
hb_buffer_t::clear ()
{
+ content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
props = default_props;
- scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
- content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
successful = true;
have_output = false;
have_positions = false;
@@ -245,15 +297,42 @@ hb_buffer_t::clear ()
out_len = 0;
out_info = info;
- serial = 0;
-
memset (context, 0, sizeof context);
memset (context_len, 0, sizeof context_len);
deallocate_var_all ();
+ serial = 0;
+ scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
}
void
+hb_buffer_t::enter ()
+{
+ deallocate_var_all ();
+ serial = 0;
+ scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
+ if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR)))
+ {
+ max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR,
+ (unsigned) HB_BUFFER_MAX_LEN_MIN);
+ }
+ if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR)))
+ {
+ max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR,
+ (unsigned) HB_BUFFER_MAX_OPS_MIN);
+ }
+}
+void
+hb_buffer_t::leave ()
+{
+ max_len = HB_BUFFER_MAX_LEN_DEFAULT;
+ max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
+ deallocate_var_all ();
+ serial = 0;
+}
+
+
+void
hb_buffer_t::add (hb_codepoint_t codepoint,
unsigned int cluster)
{
@@ -306,7 +385,7 @@ hb_buffer_t::clear_positions ()
}
void
-hb_buffer_t::swap_buffers ()
+hb_buffer_t::sync ()
{
assert (have_output);
@@ -325,6 +404,7 @@ hb_buffer_t::swap_buffers ()
reset:
have_output = false;
out_len = 0;
+ out_info = info;
idx = 0;
}
@@ -395,52 +475,6 @@ hb_buffer_t::set_masks (hb_mask_t value,
}
void
-hb_buffer_t::reverse_range (unsigned int start,
- unsigned int end)
-{
- if (end - start < 2)
- return;
-
- hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end);
-
- if (have_positions) {
- hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end);
- }
-}
-
-void
-hb_buffer_t::reverse ()
-{
- if (unlikely (!len))
- return;
-
- reverse_range (0, len);
-}
-
-void
-hb_buffer_t::reverse_clusters ()
-{
- unsigned int i, start, count, last_cluster;
-
- if (unlikely (!len))
- return;
-
- reverse ();
-
- count = len;
- start = 0;
- last_cluster = info[0].cluster;
- for (i = 1; i < count; i++) {
- if (last_cluster != info[i].cluster) {
- reverse_range (start, i);
- start = i;
- last_cluster = info[i].cluster;
- }
- }
- reverse_range (start, i);
-}
-
-void
hb_buffer_t::merge_clusters_impl (unsigned int start,
unsigned int end)
{
@@ -539,32 +573,6 @@ done:
}
void
-hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
-{
- unsigned int cluster = UINT_MAX;
- cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster);
- _unsafe_to_break_set_mask (info, start, end, cluster);
-}
-void
-hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end)
-{
- if (!have_output)
- {
- unsafe_to_break_impl (start, end);
- return;
- }
-
- assert (start <= out_len);
- assert (idx <= end);
-
- unsigned int cluster = UINT_MAX;
- cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster);
- cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster);
- _unsafe_to_break_set_mask (out_info, start, out_len, cluster);
- _unsafe_to_break_set_mask (info, idx, end, cluster);
-}
-
-void
hb_buffer_t::guess_segment_properties ()
{
assert_unicode ();
@@ -608,12 +616,12 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
0, /* invisible */
- HB_BUFFER_SCRATCH_FLAG_DEFAULT,
- HB_BUFFER_MAX_LEN_DEFAULT,
- HB_BUFFER_MAX_OPS_DEFAULT,
+ 0, /* not_found */
+
HB_BUFFER_CONTENT_TYPE_INVALID,
HB_SEGMENT_PROPERTIES_DEFAULT,
+
false, /* successful */
false, /* have_output */
true /* have_positions */
@@ -653,6 +661,46 @@ hb_buffer_create ()
}
/**
+ * hb_buffer_create_similar:
+ * @src: An #hb_buffer_t
+ *
+ * Creates a new #hb_buffer_t, similar to hb_buffer_create(). The only
+ * difference is that the buffer is configured similarly to @src.
+ *
+ * Return value: (transfer full):
+ * A newly allocated #hb_buffer_t, similar to hb_buffer_create().
+ *
+ * Since: 3.3.0
+ **/
+hb_buffer_t *
+hb_buffer_create_similar (const hb_buffer_t *src)
+{
+ hb_buffer_t *buffer = hb_buffer_create ();
+
+ buffer->similar (*src);
+
+ return buffer;
+}
+
+/**
+ * hb_buffer_reset:
+ * @buffer: An #hb_buffer_t
+ *
+ * Resets the buffer to its initial status, as if it was just newly created
+ * with hb_buffer_create().
+ *
+ * Since: 0.9.2
+ **/
+void
+hb_buffer_reset (hb_buffer_t *buffer)
+{
+ if (unlikely (hb_object_is_immutable (buffer)))
+ return;
+
+ buffer->reset ();
+}
+
+/**
* hb_buffer_get_empty:
*
* Fetches an empty #hb_buffer_t.
@@ -1158,26 +1206,48 @@ hb_buffer_get_invisible_glyph (hb_buffer_t *buffer)
return buffer->invisible;
}
-
/**
- * hb_buffer_reset:
+ * hb_buffer_set_not_found_glyph:
* @buffer: An #hb_buffer_t
+ * @not_found: the not-found #hb_codepoint_t
*
- * Resets the buffer to its initial status, as if it was just newly created
- * with hb_buffer_create().
+ * Sets the #hb_codepoint_t that replaces characters not found in
+ * the font during shaping.
*
- * Since: 0.9.2
+ * The not-found glyph defaults to zero, sometimes knows as the
+ * ".notdef" glyph. This API allows for differentiating the two.
+ *
+ * Since: 3.1.0
**/
void
-hb_buffer_reset (hb_buffer_t *buffer)
+hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
+ hb_codepoint_t not_found)
{
if (unlikely (hb_object_is_immutable (buffer)))
return;
- buffer->reset ();
+ buffer->not_found = not_found;
}
/**
+ * hb_buffer_get_not_found_glyph:
+ * @buffer: An #hb_buffer_t
+ *
+ * See hb_buffer_set_not_found_glyph().
+ *
+ * Return value:
+ * The @buffer not-found #hb_codepoint_t
+ *
+ * Since: 3.1.0
+ **/
+hb_codepoint_t
+hb_buffer_get_not_found_glyph (hb_buffer_t *buffer)
+{
+ return buffer->not_found;
+}
+
+
+/**
* hb_buffer_clear_contents:
* @buffer: An #hb_buffer_t
*
@@ -1719,7 +1789,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
**/
HB_EXTERN void
hb_buffer_append (hb_buffer_t *buffer,
- hb_buffer_t *source,
+ const hb_buffer_t *source,
unsigned int start,
unsigned int end)
{
@@ -1752,6 +1822,8 @@ hb_buffer_append (hb_buffer_t *buffer,
if (!buffer->have_positions && source->have_positions)
buffer->clear_positions ();
+ hb_segment_properties_overlay (&buffer->props, &source->props);
+
memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
if (buffer->have_positions)
memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
index 865ccb2273..14aaa5e1f5 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
@@ -76,18 +76,72 @@ typedef struct hb_glyph_info_t {
* @HB_GLYPH_FLAG_UNSAFE_TO_BREAK: Indicates that if input text is broken at the
* beginning of the cluster this glyph is part of,
* then both sides need to be re-shaped, as the
- * result might be different. On the flip side,
- * it means that when this flag is not present,
- * then it's safe to break the glyph-run at the
- * beginning of this cluster, and the two sides
- * represent the exact same result one would get
- * if breaking input text at the beginning of
- * this cluster and shaping the two sides
- * separately. This can be used to optimize
- * paragraph layout, by avoiding re-shaping
- * of each line after line-breaking, or limiting
- * the reshaping to a small piece around the
- * breaking point only.
+ * result might be different.
+ * On the flip side, it means that when this
+ * flag is not present, then it is safe to break
+ * the glyph-run at the beginning of this
+ * cluster, and the two sides will represent the
+ * exact same result one would get if breaking
+ * input text at the beginning of this cluster
+ * and shaping the two sides separately.
+ * This can be used to optimize paragraph
+ * layout, by avoiding re-shaping of each line
+ * after line-breaking.
+ * @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT: Indicates that if input text is changed on one
+ * side of the beginning of the cluster this glyph
+ * is part of, then the shaping results for the
+ * other side might change.
+ * Note that the absence of this flag will NOT by
+ * itself mean that it IS safe to concat text.
+ * Only two pieces of text both of which clear of
+ * this flag can be concatenated safely.
+ * This can be used to optimize paragraph
+ * layout, by avoiding re-shaping of each line
+ * after line-breaking, by limiting the
+ * reshaping to a small piece around the
+ * breaking positin only, even if the breaking
+ * position carries the
+ * #HB_GLYPH_FLAG_UNSAFE_TO_BREAK or when
+ * hyphenation or other text transformation
+ * happens at line-break position, in the following
+ * way:
+ * 1. Iterate back from the line-break position
+ * until the first cluster start position that is
+ * NOT unsafe-to-concat, 2. shape the segment from
+ * there till the end of line, 3. check whether the
+ * resulting glyph-run also is clear of the
+ * unsafe-to-concat at its start-of-text position;
+ * if it is, just splice it into place and the line
+ * is shaped; If not, move on to a position further
+ * back that is clear of unsafe-to-concat and retry
+ * from there, and repeat.
+ * At the start of next line a similar algorithm can
+ * be implemented. That is: 1. Iterate forward from
+ * the line-break position until the first cluster
+ * start position that is NOT unsafe-to-concat, 2.
+ * shape the segment from beginning of the line to
+ * that position, 3. check whether the resulting
+ * glyph-run also is clear of the unsafe-to-concat
+ * at its end-of-text position; if it is, just splice
+ * it into place and the beginning is shaped; If not,
+ * move on to a position further forward that is clear
+ * of unsafe-to-concat and retry up to there, and repeat.
+ * A slight complication will arise in the
+ * implementation of the algorithm above,
+ * because while our buffer API has a way to
+ * return flags for position corresponding to
+ * start-of-text, there is currently no position
+ * corresponding to end-of-text. This limitation
+ * can be alleviated by shaping more text than needed
+ * and looking for unsafe-to-concat flag within text
+ * clusters.
+ * The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will
+ * always imply this flag.
+ * To use this flag, you must enable the buffer flag
+ * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT during
+ * shaping, otherwise the buffer flag will not be
+ * reliably produced.
+ * Since: 4.0.0
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*
* Flags for #hb_glyph_info_t.
@@ -96,8 +150,9 @@ typedef struct hb_glyph_info_t {
*/
typedef enum { /*< flags >*/
HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
+ HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
- HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */
+ HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */
} hb_glyph_flags_t;
HB_EXTERN hb_glyph_flags_t
@@ -170,6 +225,9 @@ hb_segment_properties_equal (const hb_segment_properties_t *a,
HB_EXTERN unsigned int
hb_segment_properties_hash (const hb_segment_properties_t *p);
+HB_EXTERN void
+hb_segment_properties_overlay (hb_segment_properties_t *p,
+ const hb_segment_properties_t *src);
/**
@@ -185,6 +243,13 @@ HB_EXTERN hb_buffer_t *
hb_buffer_create (void);
HB_EXTERN hb_buffer_t *
+hb_buffer_create_similar (const hb_buffer_t *src);
+
+HB_EXTERN void
+hb_buffer_reset (hb_buffer_t *buffer);
+
+
+HB_EXTERN hb_buffer_t *
hb_buffer_get_empty (void);
HB_EXTERN hb_buffer_t *
@@ -295,7 +360,19 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* @HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE:
* flag indicating that a dotted circle should
* not be inserted in the rendering of incorrect
- * character sequences (such at <0905 093E>). Since: 2.4
+ * character sequences (such at <0905 093E>). Since: 2.4.0
+ * @HB_BUFFER_FLAG_VERIFY:
+ * flag indicating that the hb_shape() call and its variants
+ * should perform various verification processes on the results
+ * of the shaping operation on the buffer. If the verification
+ * fails, then either a buffer message is sent, if a message
+ * handler is installed on the buffer, or a message is written
+ * to standard error. In either case, the shaping result might
+ * be modified to show the failed output. Since: 3.4.0
+ * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT:
+ * flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
+ * glyph-flag should be produced by the shaper. By default
+ * it will not be produced since it incurs a cost. Since: 4.0.0
*
* Flags for #hb_buffer_t.
*
@@ -307,7 +384,9 @@ typedef enum { /*< flags >*/
HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u,
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
- HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u
+ HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u,
+ HB_BUFFER_FLAG_VERIFY = 0x00000020u,
+ HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u
} hb_buffer_flags_t;
HB_EXTERN void
@@ -383,9 +462,17 @@ hb_buffer_set_invisible_glyph (hb_buffer_t *buffer,
HB_EXTERN hb_codepoint_t
hb_buffer_get_invisible_glyph (hb_buffer_t *buffer);
-
HB_EXTERN void
-hb_buffer_reset (hb_buffer_t *buffer);
+hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
+ hb_codepoint_t not_found);
+
+HB_EXTERN hb_codepoint_t
+hb_buffer_get_not_found_glyph (hb_buffer_t *buffer);
+
+
+/*
+ * Content API.
+ */
HB_EXTERN void
hb_buffer_clear_contents (hb_buffer_t *buffer);
@@ -453,7 +540,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
HB_EXTERN void
hb_buffer_append (hb_buffer_t *buffer,
- hb_buffer_t *source,
+ const hb_buffer_t *source,
unsigned int start,
unsigned int end);
@@ -550,24 +637,24 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
HB_EXTERN unsigned int
hb_buffer_serialize_unicode (hb_buffer_t *buffer,
- unsigned int start,
- unsigned int end,
- char *buf,
- unsigned int buf_size,
- unsigned int *buf_consumed,
- hb_buffer_serialize_format_t format,
- hb_buffer_serialize_flags_t flags);
+ unsigned int start,
+ unsigned int end,
+ char *buf,
+ unsigned int buf_size,
+ unsigned int *buf_consumed,
+ hb_buffer_serialize_format_t format,
+ hb_buffer_serialize_flags_t flags);
HB_EXTERN unsigned int
hb_buffer_serialize (hb_buffer_t *buffer,
- unsigned int start,
- unsigned int end,
- char *buf,
- unsigned int buf_size,
- unsigned int *buf_consumed,
- hb_font_t *font,
- hb_buffer_serialize_format_t format,
- hb_buffer_serialize_flags_t flags);
+ unsigned int start,
+ unsigned int end,
+ char *buf,
+ unsigned int buf_size,
+ unsigned int *buf_consumed,
+ hb_font_t *font,
+ hb_buffer_serialize_format_t format,
+ hb_buffer_serialize_flags_t flags);
HB_EXTERN hb_bool_t
hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
@@ -579,10 +666,10 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
HB_EXTERN hb_bool_t
hb_buffer_deserialize_unicode (hb_buffer_t *buffer,
- const char *buf,
- int buf_len,
- const char **end_ptr,
- hb_buffer_serialize_format_t format);
+ const char *buf,
+ int buf_len,
+ const char **end_ptr,
+ hb_buffer_serialize_format_t format);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
index 8635ebd35f..bc6992905e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
@@ -67,8 +67,8 @@ enum hb_buffer_scratch_flags_t {
HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u,
HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u,
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
- HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u,
- HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000020u,
+ HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u,
+ HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u,
/* Reserved for complex shapers' internal use. */
HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
@@ -87,17 +87,21 @@ struct hb_buffer_t
{
hb_object_header_t header;
- /* Information about how the text in the buffer should be treated */
+ /*
+ * Information about how the text in the buffer should be treated.
+ */
+
hb_unicode_funcs_t *unicode; /* Unicode functions */
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
hb_buffer_cluster_level_t cluster_level;
hb_codepoint_t replacement; /* U+FFFD or something else. */
hb_codepoint_t invisible; /* 0 or something else. */
- hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
- unsigned int max_len; /* Maximum allowed len. */
- int max_ops; /* Maximum allowed operations. */
+ hb_codepoint_t not_found; /* 0 or something else. */
+
+ /*
+ * Buffer contents
+ */
- /* Buffer contents */
hb_buffer_content_type_t content_type;
hb_segment_properties_t props; /* Script, language, direction */
@@ -114,8 +118,6 @@ struct hb_buffer_t
hb_glyph_info_t *out_info;
hb_glyph_position_t *pos;
- unsigned int serial;
-
/* Text before / after the main buffer contents.
* Always in Unicode, and ordered outward.
* Index 0 is for "pre-context", 1 for "post-context". */
@@ -123,7 +125,25 @@ struct hb_buffer_t
hb_codepoint_t context[2][CONTEXT_LENGTH];
unsigned int context_len[2];
- /* Debugging API */
+
+ /*
+ * Managed by enter / leave
+ */
+
+#ifndef HB_NDEBUG
+ uint8_t allocated_var_bits;
+#endif
+ uint8_t serial;
+ hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
+ unsigned int max_len; /* Maximum allowed len. */
+ int max_ops; /* Maximum allowed operations. */
+ /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
+
+
+ /*
+ * Messaging callback
+ */
+
#ifndef HB_NO_BUFFER_MESSAGE
hb_buffer_message_func_t message_func;
void *message_data;
@@ -133,11 +153,6 @@ struct hb_buffer_t
static constexpr unsigned message_depth = 0u;
#endif
- /* Internal debugging. */
- /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
-#ifndef HB_NDEBUG
- uint8_t allocated_var_bits;
-#endif
/* Methods */
@@ -189,23 +204,88 @@ struct hb_buffer_t
hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; }
hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
+ HB_INTERNAL void similar (const hb_buffer_t &src);
HB_INTERNAL void reset ();
HB_INTERNAL void clear ();
+ /* Called around shape() */
+ HB_INTERNAL void enter ();
+ HB_INTERNAL void leave ();
+
+#ifndef HB_NO_BUFFER_VERIFY
+ HB_INTERNAL
+#endif
+ bool verify (hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+#ifndef HB_NO_BUFFER_VERIFY
+ ;
+#else
+ { return true; }
+#endif
+
unsigned int backtrack_len () const { return have_output ? out_len : idx; }
unsigned int lookahead_len () const { return len - idx; }
- unsigned int next_serial () { return serial++; }
+ uint8_t next_serial () { return ++serial ? serial : ++serial; }
HB_INTERNAL void add (hb_codepoint_t codepoint,
unsigned int cluster);
HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
- HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
- HB_INTERNAL void reverse ();
- HB_INTERNAL void reverse_clusters ();
+ void reverse_range (unsigned start, unsigned end)
+ {
+ hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end);
+ if (have_positions)
+ hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end);
+ }
+ void reverse () { reverse_range (0, len); }
+
+ template <typename FuncType>
+ void reverse_groups (const FuncType& group,
+ bool merge_clusters = false)
+ {
+ if (unlikely (!len))
+ return;
+
+ unsigned start = 0;
+ unsigned i;
+ for (i = 1; i < len; i++)
+ {
+ if (!group (info[i - 1], info[i]))
+ {
+ if (merge_clusters)
+ this->merge_clusters (start, i);
+ reverse_range (start, i);
+ start = i;
+ }
+ }
+ if (merge_clusters)
+ this->merge_clusters (start, i);
+ reverse_range (start, i);
+
+ reverse ();
+ }
+
+ template <typename FuncType>
+ unsigned group_end (unsigned start, const FuncType& group) const
+ {
+ while (++start < len && group (info[start - 1], info[start]))
+ ;
+
+ return start;
+ }
+
+ static bool _cluster_group_func (const hb_glyph_info_t& a,
+ const hb_glyph_info_t& b)
+ { return a.cluster == b.cluster; }
+
+ void reverse_clusters () { reverse_groups (_cluster_group_func); }
+
HB_INTERNAL void guess_segment_properties ();
- HB_INTERNAL void swap_buffers ();
+ HB_INTERNAL void sync ();
HB_INTERNAL void clear_output ();
HB_INTERNAL void clear_positions ();
@@ -319,15 +399,87 @@ struct hb_buffer_t
/* Merge clusters for deleting current glyph, and skip it. */
HB_INTERNAL void delete_glyph ();
- void unsafe_to_break (unsigned int start,
- unsigned int end)
+
+ /* Adds glyph flags in mask to infos with clusters between start and end.
+ * The start index will be from out-buffer if from_out_buffer is true.
+ * If interior is true, then the cluster having the minimum value is skipped. */
+ void _set_glyph_flags (hb_mask_t mask,
+ unsigned start = 0,
+ unsigned end = (unsigned) -1,
+ bool interior = false,
+ bool from_out_buffer = false)
{
- if (end - start < 2)
+ end = hb_min (end, len);
+
+ if (interior && !from_out_buffer && end - start < 2)
return;
- unsafe_to_break_impl (start, end);
+
+ scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
+
+ if (!from_out_buffer || !have_output)
+ {
+ if (!interior)
+ {
+ for (unsigned i = start; i < end; i++)
+ info[i].mask |= mask;
+ }
+ else
+ {
+ unsigned cluster = _infos_find_min_cluster (info, start, end);
+ _infos_set_glyph_flags (info, start, end, cluster, mask);
+ }
+ }
+ else
+ {
+ assert (start <= out_len);
+ assert (idx <= end);
+
+ if (!interior)
+ {
+ for (unsigned i = start; i < out_len; i++)
+ out_info[i].mask |= mask;
+ for (unsigned i = idx; i < end; i++)
+ info[i].mask |= mask;
+ }
+ else
+ {
+ unsigned cluster = _infos_find_min_cluster (info, idx, end);
+ cluster = _infos_find_min_cluster (out_info, start, out_len, cluster);
+
+ _infos_set_glyph_flags (out_info, start, out_len, cluster, mask);
+ _infos_set_glyph_flags (info, idx, end, cluster, mask);
+ }
+ }
+ }
+
+ void unsafe_to_break (unsigned int start = 0, unsigned int end = -1)
+ {
+ _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
+ start, end,
+ true);
+ }
+ 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);
+ }
+ void unsafe_to_break_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
+ {
+ _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
+ start, end,
+ true, true);
+ }
+ 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))
+ return;
+ _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
+ start, end,
+ false, true);
}
- HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
- HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
/* Internal methods */
@@ -418,67 +570,50 @@ struct hb_buffer_t
set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
{
if (inf.cluster != cluster)
- {
- if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
- inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
- else
- inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
- }
+ inf.mask = (inf.mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED);
inf.cluster = cluster;
}
-
- unsigned int
- _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
- unsigned int start, unsigned int end,
- unsigned int cluster) const
- {
- for (unsigned int i = start; i < end; i++)
- cluster = hb_min (cluster, infos[i].cluster);
- return cluster;
- }
void
- _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
- unsigned int start, unsigned int end,
- unsigned int cluster)
+ _infos_set_glyph_flags (hb_glyph_info_t *infos,
+ unsigned int start, unsigned int end,
+ unsigned int cluster,
+ hb_mask_t mask)
{
for (unsigned int i = start; i < end; i++)
if (cluster != infos[i].cluster)
{
- scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
- infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+ scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
+ infos[i].mask |= mask;
}
}
+ static unsigned
+ _infos_find_min_cluster (const hb_glyph_info_t *infos,
+ unsigned start, unsigned end,
+ unsigned cluster = UINT_MAX)
+ {
+ for (unsigned int i = start; i < end; i++)
+ cluster = hb_min (cluster, infos[i].cluster);
+ return cluster;
+ }
- void unsafe_to_break_all () { unsafe_to_break_impl (0, len); }
- void safe_to_break_all ()
+ void clear_glyph_flags (hb_mask_t mask = 0)
{
for (unsigned int i = 0; i < len; i++)
- info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+ info[i].mask = (info[i].mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED);
}
};
DECLARE_NULL_INSTANCE (hb_buffer_t);
-/* Loop over clusters. Duplicated in foreach_syllable(). */
-#define foreach_cluster(buffer, start, end) \
+#define foreach_group(buffer, start, end, group_func) \
for (unsigned int \
_count = buffer->len, \
- start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
+ start = 0, end = _count ? buffer->group_end (0, group_func) : 0; \
start < _count; \
- start = end, end = _next_cluster (buffer, start))
-
-static inline unsigned int
-_next_cluster (hb_buffer_t *buffer, unsigned int start)
-{
- hb_glyph_info_t *info = buffer->info;
- unsigned int count = buffer->len;
-
- unsigned int cluster = info[start].cluster;
- while (++start < count && cluster == info[start].cluster)
- ;
+ start = end, end = buffer->group_end (start, group_func))
- return start;
-}
+#define foreach_cluster(buffer, start, end) \
+ foreach_group (buffer, start, end, hb_buffer_t::_cluster_group_func)
#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
index c251e2d0ed..641de0eff2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
@@ -217,9 +217,6 @@ inline unsigned int OpCode_Size (op_code_t op) { return Is_OpCode_ESC (op) ? 2:
struct number_t
{
- void init () { set_real (0.0); }
- void fini () {}
-
void set_int (int v) { value = v; }
int to_int () const { return value; }
@@ -245,7 +242,7 @@ struct number_t
}
protected:
- double value;
+ double value = 0.;
};
/* byte string */
@@ -380,10 +377,8 @@ struct cff_stack_t
count = 0;
elements.init ();
elements.resize (kSizeLimit);
- for (unsigned int i = 0; i < elements.length; i++)
- elements[i].init ();
}
- void fini () { elements.fini_deep (); }
+ void fini () { elements.fini (); }
ELEM& operator [] (unsigned int i)
{
@@ -523,9 +518,6 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
/* an operator prefixed by its operands in a byte string */
struct op_str_t
{
- void init () {}
- void fini () {}
-
op_code_t op;
byte_str_t str;
};
@@ -553,7 +545,7 @@ struct parsed_values_t
opStart = 0;
values.init ();
}
- void fini () { values.fini_deep (); }
+ void fini () { values.fini (); }
void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_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 52d778ffe2..ef299369b5 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
@@ -94,12 +94,6 @@ struct biased_subrs_t
struct point_t
{
- void init ()
- {
- x.init ();
- y.init ();
- }
-
void set_int (int _x, int _y)
{
x.set_int (_x);
@@ -128,7 +122,7 @@ struct cs_interp_env_t : interp_env_t<ARG>
hstem_count = 0;
vstem_count = 0;
hintmask_size = 0;
- pt.init ();
+ pt.set_int (0, 0);
callStack.init ();
globalSubrs.init (globalSubrs_);
localSubrs.init (localSubrs_);
@@ -841,7 +835,6 @@ struct path_procs_t
if (likely (env.argStack.get_count () == 11))
{
point_t d;
- d.init ();
for (unsigned int i = 0; i < 10; i += 2)
d.move (env.eval_arg (i), env.eval_arg (i+1));
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh
index d961566447..766183760e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh
@@ -35,18 +35,6 @@ using namespace OT;
struct blend_arg_t : number_t
{
- void init ()
- {
- number_t::init ();
- deltas.init ();
- }
-
- void fini ()
- {
- number_t::fini ();
- deltas.fini_deep ();
- }
-
void set_int (int v) { reset_blends (); number_t::set_int (v); }
void set_fixed (int32_t v) { reset_blends (); number_t::set_fixed (v); }
void set_real (double v) { reset_blends (); number_t::set_real (v); }
@@ -202,7 +190,7 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
switch (op) {
case OpCode_callsubr:
case OpCode_callgsubr:
- /* a subroutine number shoudln't be a blended value */
+ /* a subroutine number shouldn't be a blended value */
if (unlikely (env.argStack.peek ().blending ()))
{
env.set_error ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-common.cc
index 26c8ad0f49..41229b9183 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-common.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-common.cc
@@ -29,10 +29,31 @@
#include "hb.hh"
#include "hb-machinery.hh"
+#if !defined(HB_NO_SETLOCALE) && (!defined(HAVE_NEWLOCALE) || !defined(HAVE_USELOCALE))
+#define HB_NO_SETLOCALE 1
+#endif
+
+#ifndef HB_NO_SETLOCALE
+
#include <locale.h>
+#ifdef HAVE_XLOCALE_H
+#include <xlocale.h> // Needed on BSD/OS X for uselocale
+#endif
+
+#ifdef WIN32
+#define hb_locale_t _locale_t
+#else
+#define hb_locale_t locale_t
+#endif
+#define hb_setlocale setlocale
+#define hb_uselocale uselocale
+
+#else
+
+#define hb_locale_t void *
+#define hb_setlocale(Category, Locale) "C"
+#define hb_uselocale(Locale) ((hb_locale_t) 0)
-#ifdef HB_NO_SETLOCALE
-#define setlocale(Category, Locale) "C"
#endif
/**
@@ -122,7 +143,7 @@ hb_tag_from_string (const char *str, int len)
* @tag: #hb_tag_t to convert
* @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t): Converted string
*
- * Converts an #hb_tag_t to a string and returns it in @buf.
+ * Converts an #hb_tag_t to a string and returns it in @buf.
* Strings will be four characters long.
*
* Since: 0.9.5
@@ -151,13 +172,13 @@ const char direction_strings[][4] = {
* @str: (array length=len) (element-type uint8_t): String to convert
* @len: Length of @str, or -1 if it is %NULL-terminated
*
- * Converts a string to an #hb_direction_t.
+ * Converts a string to an #hb_direction_t.
*
* Matching is loose and applies only to the first letter. For
* examples, "LTR" and "left-to-right" will both return #HB_DIRECTION_LTR.
*
* Unmatched strings will return #HB_DIRECTION_INVALID.
- *
+ *
* Return value: The #hb_direction_t matching @str
*
* Since: 0.9.2
@@ -413,7 +434,7 @@ hb_language_get_default ()
hb_language_t language = default_language;
if (unlikely (language == HB_LANGUAGE_INVALID))
{
- language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1);
+ language = hb_language_from_string (hb_setlocale (LC_CTYPE, nullptr), -1);
(void) default_language.cmpexch (HB_LANGUAGE_INVALID, language);
}
@@ -1039,6 +1060,47 @@ hb_variation_from_string (const char *str, int len,
return false;
}
+#ifndef HB_NO_SETLOCALE
+
+static inline void free_static_C_locale ();
+
+static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<hb_locale_t>,
+ hb_C_locale_lazy_loader_t>
+{
+ static hb_locale_t create ()
+ {
+ hb_locale_t l = newlocale (LC_ALL_MASK, "C", NULL);
+ if (!l)
+ return l;
+
+ hb_atexit (free_static_C_locale);
+
+ return l;
+ }
+ static void destroy (hb_locale_t l)
+ {
+ freelocale (l);
+ }
+ static hb_locale_t get_null ()
+ {
+ return (hb_locale_t) 0;
+ }
+} static_C_locale;
+
+static inline
+void free_static_C_locale ()
+{
+ static_C_locale.free_instance ();
+}
+
+static hb_locale_t
+get_C_locale ()
+{
+ return static_C_locale.get_unconst ();
+}
+
+#endif
+
/**
* hb_variation_to_string:
* @variation: an #hb_variation_t to convert
@@ -1064,7 +1126,11 @@ hb_variation_to_string (hb_variation_t *variation,
while (len && s[len - 1] == ' ')
len--;
s[len++] = '=';
+
+ hb_locale_t oldlocale HB_UNUSED;
+ oldlocale = hb_uselocale (get_C_locale ());
len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
+ (void) hb_uselocale (oldlocale);
assert (len < ARRAY_LENGTH (s));
len = hb_min (len, size - 1);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h
index 0384117a4d..7b897a6c51 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-common.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h
@@ -130,6 +130,16 @@ typedef union _hb_var_int_t {
int8_t i8[4];
} hb_var_int_t;
+typedef union _hb_var_num_t {
+ float f;
+ uint32_t u32;
+ int32_t i32;
+ uint16_t u16[2];
+ int16_t i16[2];
+ uint8_t u8[4];
+ int8_t i8[4];
+} hb_var_num_t;
+
/* hb_tag_t */
@@ -481,6 +491,7 @@ hb_language_get_default (void);
* @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0
* @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
* @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
+ * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0
* @HB_SCRIPT_INVALID: No script set
*
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
@@ -697,6 +708,11 @@ typedef enum
HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/
HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/
+ /*
+ * Since 3.4.0
+ */
+ HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'),
+
/* No script set. */
HB_SCRIPT_INVALID = HB_TAG_NONE,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-config.hh b/src/3rdparty/harfbuzz-ng/src/hb-config.hh
index ad800f0f74..4b46dea938 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-config.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-config.hh
@@ -55,6 +55,7 @@
#define HB_NO_ATEXIT
#define HB_NO_BUFFER_MESSAGE
#define HB_NO_BUFFER_SERIALIZE
+#define HB_NO_BUFFER_VERIFY
#define HB_NO_BITMAP
#define HB_NO_CFF
#define HB_NO_COLOR
@@ -84,10 +85,14 @@
#ifdef HB_MINI
#define HB_NO_AAT
#define HB_NO_LEGACY
+#define HB_NO_BORING_EXPANSION
#endif
-#ifdef HAVE_CONFIG_OVERRIDE_H
-#include "config-override.h"
+#if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H)
+#ifndef HB_CONFIG_OVERRIDE_H
+#define HB_CONFIG_OVERRIDE_H "config-override.h"
+#endif
+#include HB_CONFIG_OVERRIDE_H
#endif
/* Closure of options. */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
index 4b6c67c1ee..6ccc1b0a2b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
@@ -481,8 +481,8 @@ struct active_feature_t {
a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 :
0;
}
- bool operator== (const active_feature_t *f) {
- return cmp (this, f) == 0;
+ bool operator== (const active_feature_t& f) const {
+ return cmp (this, &f) == 0;
}
};
@@ -677,7 +677,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
{
active_features.push (event->feature);
} else {
- active_feature_t *feature = active_features.find (&event->feature);
+ active_feature_t *feature = active_features.lsearch (event->feature);
if (feature)
active_features.remove (feature - active_features.arrayZ);
}
@@ -897,7 +897,7 @@ resize_and_retry:
DEBUG_MSG (CORETEXT, nullptr, "Num runs: %d", num_runs);
buffer->len = 0;
- uint32_t status_and = ~0, status_or = 0;
+ uint32_t status_or = 0;
CGFloat advances_so_far = 0;
/* For right-to-left runs, CoreText returns the glyphs positioned such that
* any trailing whitespace is to the left of (0,0). Adjust coordinate system
@@ -918,7 +918,6 @@ resize_and_retry:
CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex (glyph_runs, i));
CTRunStatus run_status = CTRunGetStatus (run);
status_or |= run_status;
- status_and &= run_status;
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
CGFloat run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr);
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
@@ -1140,21 +1139,6 @@ resize_and_retry:
buffer->len += num_glyphs;
}
- /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
- * or if it does, it doesn't respect it. So we get runs with wrong
- * directions. As such, disable the assert... It wouldn't crash, but
- * cursoring will be off...
- *
- * https://crbug.com/419769
- */
- if (false)
- {
- /* Make sure all runs had the expected direction. */
- HB_UNUSED bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
- assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
- assert (bool (status_or & kCTRunStatusRightToLeft) == backward);
- }
-
buffer->clear_positions ();
unsigned int count = buffer->len;
@@ -1213,7 +1197,8 @@ resize_and_retry:
}
}
- buffer->unsafe_to_break_all ();
+ buffer->clear_glyph_flags ();
+ buffer->unsafe_to_break ();
#undef FAIL
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
index f80c8980ba..3ac7440e80 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
@@ -302,7 +302,7 @@ struct hb_auto_trace_t
{
if (unlikely (returned)) {
fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n");
- return hb_forward<T> (v);
+ return std::forward<T> (v);
}
_hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
@@ -311,7 +311,7 @@ struct hb_auto_trace_t
if (plevel) --*plevel;
plevel = nullptr;
returned = true;
- return hb_forward<T> (v);
+ return std::forward<T> (v);
}
private:
@@ -333,7 +333,7 @@ struct hb_auto_trace_t<0, ret_t>
template <typename T>
T ret (T&& v,
const char *func HB_UNUSED = nullptr,
- unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
+ unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
};
/* For disabled tracing; optimize out everything.
@@ -343,7 +343,7 @@ struct hb_no_trace_t {
template <typename T>
T ret (T&& v,
const char *func HB_UNUSED = nullptr,
- unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
+ unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
};
#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc b/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
index 8f6d73b639..f177ff31c0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
@@ -762,6 +762,9 @@ retry_getglyphs:
if (isRightToLeft) hb_buffer_reverse (buffer);
+ buffer->clear_glyph_flags ();
+ buffer->unsafe_to_break ();
+
delete [] clusterMap;
delete [] glyphIndices;
delete [] textProperties;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-dispatch.hh b/src/3rdparty/harfbuzz-ng/src/hb-dispatch.hh
index 4b2b65a8de..37ca681465 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-dispatch.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-dispatch.hh
@@ -50,7 +50,7 @@ struct hb_dispatch_context_t
bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
template <typename T, typename ...Ts>
return_t dispatch (const T &obj, Ts&&... ds)
- { return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); }
+ { return obj.dispatch (thiz (), std::forward<Ts> (ds)...); }
static return_t no_dispatch_return_value () { return Context::default_return_value (); }
static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
unsigned debug_depth = 0;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-draw.cc b/src/3rdparty/harfbuzz-ng/src/hb-draw.cc
index c0af6ce013..b31019b07e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-draw.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-draw.cc
@@ -25,237 +25,313 @@
#include "hb.hh"
#ifndef HB_NO_DRAW
-#ifdef HB_EXPERIMENTAL_API
#include "hb-draw.hh"
-#include "hb-ot.h"
-#include "hb-ot-glyf-table.hh"
-#include "hb-ot-cff1-table.hh"
-#include "hb-ot-cff2-table.hh"
/**
- * hb_draw_funcs_set_move_to_func:
- * @funcs: draw functions object
- * @move_to: move-to callback
+ * SECTION:hb-draw
+ * @title: hb-draw
+ * @short_description: Glyph drawing
+ * @include: hb.h
*
- * Sets move-to callback to the draw functions object.
- *
- * Since: EXPERIMENTAL
+ * Functions for drawing (extracting) glyph shapes.
**/
-void
-hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
- hb_draw_move_to_func_t move_to)
+
+static void
+hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ float to_x HB_UNUSED, float to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ float to_x HB_UNUSED, float to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->move_to = move_to;
+ dfuncs->emit_cubic_to (draw_data, *st,
+ (st->current_x + 2.f * control_x) / 3.f,
+ (st->current_y + 2.f * control_y) / 3.f,
+ (to_x + 2.f * control_x) / 3.f,
+ (to_y + 2.f * control_y) / 3.f,
+ to_x, to_y);
+}
+
+static void
+hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ float control1_x HB_UNUSED, float control1_y HB_UNUSED,
+ float control2_x HB_UNUSED, float control2_y HB_UNUSED,
+ float to_x HB_UNUSED, float to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+
+#define HB_DRAW_FUNC_IMPLEMENT(name) \
+ \
+void \
+hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \
+ hb_draw_##name##_func_t func, \
+ void *user_data, \
+ hb_destroy_func_t destroy) \
+{ \
+ if (hb_object_is_immutable (dfuncs)) \
+ return; \
+ \
+ if (dfuncs->destroy.name) \
+ dfuncs->destroy.name (dfuncs->user_data.name); \
+ \
+ if (func) { \
+ dfuncs->func.name = func; \
+ dfuncs->user_data.name = user_data; \
+ dfuncs->destroy.name = destroy; \
+ } else { \
+ dfuncs->func.name = hb_draw_##name##_nil; \
+ dfuncs->user_data.name = nullptr; \
+ dfuncs->destroy.name = nullptr; \
+ } \
}
+HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+
/**
- * hb_draw_funcs_set_line_to_func:
- * @funcs: draw functions object
- * @line_to: line-to callback
+ * hb_draw_funcs_create: (Xconstructor)
+ *
+ * Creates a new draw callbacks object.
*
- * Sets line-to callback to the draw functions object.
+ * Return value: (transfer full):
+ * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
+ * reference count should be released with hb_draw_funcs_destroy when you are
+ * done using the #hb_draw_funcs_t. This function never returns %NULL. If
+ * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
+ * be returned.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-void
-hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
- hb_draw_line_to_func_t line_to)
+hb_draw_funcs_t *
+hb_draw_funcs_create ()
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->line_to = line_to;
+ hb_draw_funcs_t *dfuncs;
+ if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ())))
+ return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
+
+ dfuncs->func = Null (hb_draw_funcs_t).func;
+
+ return dfuncs;
}
+DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
+{
+ HB_OBJECT_HEADER_STATIC,
+
+ {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ }
+};
+
+
/**
- * hb_draw_funcs_set_quadratic_to_func:
- * @funcs: draw functions object
- * @move_to: quadratic-to callback
+ * hb_draw_funcs_reference: (skip)
+ * @dfuncs: draw functions
+ *
+ * Increases the reference count on @dfuncs by one. This prevents @buffer from
+ * being destroyed until a matching call to hb_draw_funcs_destroy() is made.
*
- * Sets quadratic-to callback to the draw functions object.
+ * Return value: (transfer full):
+ * The referenced #hb_draw_funcs_t.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-void
-hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_quadratic_to_func_t quadratic_to)
+hb_draw_funcs_t *
+hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->quadratic_to = quadratic_to;
- funcs->is_quadratic_to_set = true;
+ return hb_object_reference (dfuncs);
}
/**
- * hb_draw_funcs_set_cubic_to_func:
- * @funcs: draw functions
- * @cubic_to: cubic-to callback
+ * hb_draw_funcs_destroy: (skip)
+ * @dfuncs: draw functions
*
- * Sets cubic-to callback to the draw functions object.
+ * Deallocate the @dfuncs.
+ * Decreases the reference count on @dfuncs by one. If the result is zero, then
+ * @dfuncs and all associated resources are freed. See hb_draw_funcs_reference().
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_cubic_to_func_t cubic_to)
+hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->cubic_to = cubic_to;
+ if (!hb_object_destroy (dfuncs)) return;
+
+#define HB_DRAW_FUNC_IMPLEMENT(name) \
+ if (dfuncs->destroy.name) dfuncs->destroy.name (dfuncs->user_data.name);
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+
+
+ hb_free (dfuncs);
}
/**
- * hb_draw_funcs_set_close_path_func:
- * @funcs: draw functions object
- * @close_path: close-path callback
+ * hb_draw_funcs_make_immutable:
+ * @dfuncs: draw functions
*
- * Sets close-path callback to the draw functions object.
+ * Makes @dfuncs object immutable.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
- hb_draw_close_path_func_t close_path)
+hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->close_path = close_path;
-}
-
-static void
-_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
-
-static void
-_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
-
-static void
-_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
- hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
- void *user_data HB_UNUSED) {}
-
-static void
-_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
- hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
- hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
- void *user_data HB_UNUSED) {}
+ if (hb_object_is_immutable (dfuncs))
+ return;
-static void
-_close_path_nil (void *user_data HB_UNUSED) {}
+ hb_object_make_immutable (dfuncs);
+}
/**
- * hb_draw_funcs_create:
+ * hb_draw_funcs_is_immutable:
+ * @dfuncs: draw functions
*
- * Creates a new draw callbacks object.
+ * Checks whether @dfuncs is immutable.
+ *
+ * Return value: %true if @dfuncs is immutable, %false otherwise
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_draw_funcs_t *
-hb_draw_funcs_create ()
+hb_bool_t
+hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs)
{
- hb_draw_funcs_t *funcs;
- if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ())))
- return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
-
- funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil;
- funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil;
- funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil;
- funcs->is_quadratic_to_set = false;
- funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil;
- funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil;
- return funcs;
+ return hb_object_is_immutable (dfuncs);
}
+
/**
- * hb_draw_funcs_reference:
- * @funcs: draw functions
+ * hb_draw_move_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Add to callbacks object refcount.
+ * Perform a "move-to" draw operation.
*
- * Returns: The same object.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_draw_funcs_t *
-hb_draw_funcs_reference (hb_draw_funcs_t *funcs)
+void
+hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y)
{
- return hb_object_reference (funcs);
+ dfuncs->move_to (draw_data, *st,
+ to_x, to_y);
}
/**
- * hb_draw_funcs_destroy:
- * @funcs: draw functions
+ * hb_draw_line_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Decreases refcount of callbacks object and deletes the object if it reaches
- * to zero.
+ * Perform a "line-to" draw operation.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
+hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y)
{
- if (!hb_object_destroy (funcs)) return;
-
- hb_free (funcs);
+ dfuncs->line_to (draw_data, *st,
+ to_x, to_y);
}
/**
- * hb_draw_funcs_make_immutable:
- * @funcs: draw functions
+ * hb_draw_quadratic_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @control_x: X component of control point
+ * @control_y: Y component of control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Makes funcs object immutable.
+ * Perform a "quadratic-to" draw operation.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs)
+hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y)
{
- if (hb_object_is_immutable (funcs))
- return;
-
- hb_object_make_immutable (funcs);
+ dfuncs->quadratic_to (draw_data, *st,
+ control_x, control_y,
+ to_x, to_y);
}
/**
- * hb_draw_funcs_is_immutable:
- * @funcs: draw functions
+ * hb_draw_cubic_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @control1_x: X component of first control point
+ * @control1_y: Y component of first control point
+ * @control2_x: X component of second control point
+ * @control2_y: Y component of second control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Checks whether funcs is immutable.
+ * Perform a "cubic-to" draw operation.
*
- * Returns: If is immutable.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_bool_t
-hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs)
+void
+hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, 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)
{
- return hb_object_is_immutable (funcs);
+ dfuncs->cubic_to (draw_data, *st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y);
}
/**
- * hb_font_draw_glyph:
- * @font: a font object
- * @glyph: a glyph id
- * @funcs: draw callbacks object
- * @user_data: parameter you like be passed to the callbacks when are called
+ * hb_draw_close_path:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
*
- * Draw a glyph.
+ * Perform a "close-path" draw operation.
*
- * Returns: Whether the font had the glyph and the operation completed successfully.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_bool_t
-hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
- const hb_draw_funcs_t *funcs,
- void *user_data)
+void
+hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st)
{
- if (unlikely (funcs == &Null (hb_draw_funcs_t) ||
- glyph >= font->face->get_num_glyphs ()))
- return false;
-
- draw_helper_t draw_helper (funcs, user_data);
- if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true;
-#ifndef HB_NO_CFF
- if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true;
- if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true;
-#endif
-
- return false;
+ dfuncs->close_path (draw_data, *st);
}
-#endif
+
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-draw.h b/src/3rdparty/harfbuzz-ng/src/hb-draw.h
index bddc876399..c45a53212a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-draw.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-draw.h
@@ -33,65 +33,292 @@
HB_BEGIN_DECLS
-#ifdef HB_EXPERIMENTAL_API
-typedef void (*hb_draw_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
-typedef void (*hb_draw_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
-typedef void (*hb_draw_quadratic_to_func_t) (hb_position_t control_x, hb_position_t control_y,
- hb_position_t to_x, hb_position_t to_y,
- void *user_data);
-typedef void (*hb_draw_cubic_to_func_t) (hb_position_t control1_x, hb_position_t control1_y,
- hb_position_t control2_x, hb_position_t control2_y,
- hb_position_t to_x, hb_position_t to_y,
- void *user_data);
-typedef void (*hb_draw_close_path_func_t) (void *user_data);
+
+/**
+ * hb_draw_state_t
+ * @path_open: Whether there is an open path
+ * @path_start_x: X component of the start of current path
+ * @path_start_y: Y component of the start of current path
+ * @current_x: X component of current point
+ * @current_y: Y component of current point
+ *
+ * Current drawing state.
+ *
+ * Since: 4.0.0
+ **/
+typedef struct hb_draw_state_t {
+ hb_bool_t path_open;
+
+ float path_start_x;
+ float path_start_y;
+
+ float current_x;
+ float current_y;
+
+ /*< private >*/
+ hb_var_num_t reserved1;
+ hb_var_num_t reserved2;
+ hb_var_num_t reserved3;
+ hb_var_num_t reserved4;
+ hb_var_num_t reserved5;
+ hb_var_num_t reserved6;
+ hb_var_num_t reserved7;
+} hb_draw_state_t;
+
+/**
+ * HB_DRAW_STATE_DEFAULT:
+ *
+ * The default #hb_draw_state_t at the start of glyph drawing.
+ */
+#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}}
+
/**
* hb_draw_funcs_t:
*
* Glyph draw callbacks.
*
- * _move_to, _line_to and _cubic_to calls are nessecary to be defined but we
- * translate _quadratic_to calls to _cubic_to if the callback isn't defined.
+ * #hb_draw_move_to_func_t, #hb_draw_line_to_func_t and
+ * #hb_draw_cubic_to_func_t calls are necessary to be defined but we translate
+ * #hb_draw_quadratic_to_func_t calls to #hb_draw_cubic_to_func_t if the
+ * callback isn't defined.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
+
typedef struct hb_draw_funcs_t hb_draw_funcs_t;
+
+/**
+ * hb_draw_move_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "move-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_move_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_line_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "line-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_line_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_quadratic_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @control_x: X component of control point
+ * @control_y: Y component of control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "quadratic-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_cubic_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @control1_x: X component of first control point
+ * @control1_y: Y component of first control point
+ * @control2_x: X component of second control point
+ * @control2_y: Y component of second control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "cubic-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_cubic_to_func_t) (hb_draw_funcs_t *dfuncs, 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,
+ void *user_data);
+
+/**
+ * hb_draw_close_path_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "close-path" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_close_path_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ void *user_data);
+
+/**
+ * hb_draw_funcs_set_move_to_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): move-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets move-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
- hb_draw_move_to_func_t move_to);
+hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_move_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_line_to_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): line-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets line-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
- hb_draw_line_to_func_t line_to);
+hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_line_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_quadratic_to_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): quadratic-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets quadratic-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_quadratic_to_func_t quadratic_to);
+hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_quadratic_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_cubic_to_func:
+ * @dfuncs: draw functions
+ * @func: (closure user_data) (destroy destroy) (scope notified): cubic-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets cubic-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_cubic_to_func_t cubic_to);
+hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_cubic_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_close_path_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): close-path callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets close-path callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
- hb_draw_close_path_func_t close_path);
+hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_close_path_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
HB_EXTERN hb_draw_funcs_t *
hb_draw_funcs_create (void);
HB_EXTERN hb_draw_funcs_t *
-hb_draw_funcs_reference (hb_draw_funcs_t *funcs);
+hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
-hb_draw_funcs_destroy (hb_draw_funcs_t *funcs);
+hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
-hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs);
+hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs);
HB_EXTERN hb_bool_t
-hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs);
-#endif
+hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs);
+
+
+HB_EXTERN void
+hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, 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);
+
+HB_EXTERN void
+hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st);
+
HB_END_DECLS
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-draw.hh b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh
index 2aa0a5b4db..28bc9218e1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-draw.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh
@@ -27,113 +27,205 @@
#include "hb.hh"
-#ifdef HB_EXPERIMENTAL_API
-struct hb_draw_funcs_t
-{
- hb_object_header_t header;
- hb_draw_move_to_func_t move_to;
- hb_draw_line_to_func_t line_to;
- hb_draw_quadratic_to_func_t quadratic_to;
- bool is_quadratic_to_set;
- hb_draw_cubic_to_func_t cubic_to;
- hb_draw_close_path_func_t close_path;
-};
+/*
+ * hb_draw_funcs_t
+ */
+
+#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \
+ HB_DRAW_FUNC_IMPLEMENT (move_to) \
+ HB_DRAW_FUNC_IMPLEMENT (line_to) \
+ HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \
+ HB_DRAW_FUNC_IMPLEMENT (cubic_to) \
+ HB_DRAW_FUNC_IMPLEMENT (close_path) \
+ /* ^--- Add new callbacks here */
-struct draw_helper_t
+struct hb_draw_funcs_t
{
- draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_)
- {
- funcs = funcs_;
- user_data = user_data_;
- path_open = false;
- path_start_x = current_x = path_start_y = current_y = 0;
- }
- ~draw_helper_t () { end_path (); }
+ hb_object_header_t header;
- void move_to (hb_position_t x, hb_position_t y)
+ struct {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name;
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ } func;
+
+ struct {
+#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ } user_data;
+
+ struct {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ } destroy;
+
+ void emit_move_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
+ { func.move_to (this, draw_data, &st,
+ to_x, to_y,
+ user_data.move_to); }
+ void emit_line_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
+ { func.line_to (this, draw_data, &st,
+ to_x, to_y,
+ user_data.line_to); }
+ void emit_quadratic_to (void *draw_data, hb_draw_state_t &st,
+ float control_x, float control_y,
+ float to_x, float to_y)
+ { func.quadratic_to (this, draw_data, &st,
+ control_x, control_y,
+ to_x, to_y,
+ user_data.quadratic_to); }
+ void emit_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)
+ { func.cubic_to (this, draw_data, &st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y,
+ user_data.cubic_to); }
+ void emit_close_path (void *draw_data, hb_draw_state_t &st)
+ { func.close_path (this, draw_data, &st,
+ user_data.close_path); }
+
+
+ void move_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
{
- if (path_open) end_path ();
- current_x = path_start_x = x;
- current_y = path_start_y = y;
+ if (st.path_open) close_path (draw_data, st);
+ st.current_x = to_x;
+ st.current_y = to_y;
}
- void line_to (hb_position_t x, hb_position_t y)
+ void line_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
{
- if (equal_to_current (x, y)) return;
- if (!path_open) start_path ();
- funcs->line_to (x, y, user_data);
- current_x = x;
- current_y = y;
+ if (!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
- quadratic_to (hb_position_t control_x, hb_position_t control_y,
- hb_position_t to_x, hb_position_t to_y)
+ quadratic_to (void *draw_data, hb_draw_state_t &st,
+ float control_x, float control_y,
+ float to_x, float to_y)
{
- if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y))
- return;
- if (!path_open) start_path ();
- if (funcs->is_quadratic_to_set)
- funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data);
- else
- funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f),
- roundf ((current_y + 2.f * control_y) / 3.f),
- roundf ((to_x + 2.f * control_x) / 3.f),
- roundf ((to_y + 2.f * control_y) / 3.f),
- to_x, to_y, user_data);
- current_x = to_x;
- current_y = to_y;
+ if (!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
- cubic_to (hb_position_t control1_x, hb_position_t control1_y,
- hb_position_t control2_x, hb_position_t control2_y,
- hb_position_t to_x, hb_position_t to_y)
+ 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 (equal_to_current (control1_x, control1_y) &&
- equal_to_current (control2_x, control2_y) &&
- equal_to_current (to_x, to_y))
- return;
- if (!path_open) start_path ();
- funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data);
- current_x = to_x;
- current_y = to_y;
+ if (!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 end_path ()
+ void
+ close_path (void *draw_data, hb_draw_state_t &st)
{
- if (path_open)
+ if (st.path_open)
{
- if ((path_start_x != current_x) || (path_start_y != current_y))
- funcs->line_to (path_start_x, path_start_y, user_data);
- funcs->close_path (user_data);
+ 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);
+ emit_close_path (draw_data, st);
}
- path_open = false;
- path_start_x = current_x = path_start_y = current_y = 0;
+ st.path_open = false;
+ st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0;
}
protected:
- bool equal_to_current (hb_position_t x, hb_position_t y)
- { return current_x == x && current_y == y; }
- void start_path ()
+ void start_path (void *draw_data, hb_draw_state_t &st)
{
- if (path_open) end_path ();
- path_open = true;
- funcs->move_to (path_start_x, path_start_y, user_data);
+ assert (!st.path_open);
+ emit_move_to (draw_data, st, st.current_x, st.current_y);
+ st.path_open = true;
+ st.path_start_x = st.current_x;
+ st.path_start_y = st.current_y;
}
+};
+DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
- hb_position_t path_start_x;
- hb_position_t path_start_y;
+struct hb_draw_session_t
+{
+ hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f)
+ : slant {slant_}, not_slanted {slant == 0.f},
+ funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
+ {}
- hb_position_t current_x;
- hb_position_t current_y;
+ ~hb_draw_session_t () { close_path (); }
- bool path_open;
- const hb_draw_funcs_t *funcs;
- void *user_data;
+ void move_to (float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->move_to (draw_data, st,
+ to_x, to_y);
+ else
+ funcs->move_to (draw_data, st,
+ to_x + to_y * slant, to_y);
+ }
+ void line_to (float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->line_to (draw_data, st,
+ to_x, to_y);
+ else
+ funcs->line_to (draw_data, st,
+ to_x + to_y * slant, to_y);
+ }
+ void
+ quadratic_to (float control_x, float control_y,
+ float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->quadratic_to (draw_data, st,
+ control_x, control_y,
+ to_x, to_y);
+ else
+ funcs->quadratic_to (draw_data, st,
+ control_x + control_y * slant, control_y,
+ to_x + to_y * slant, to_y);
+ }
+ void
+ cubic_to (float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->cubic_to (draw_data, st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y);
+ else
+ funcs->cubic_to (draw_data, st,
+ control1_x + control1_y * slant, control1_y,
+ control2_x + control2_y * slant, control2_y,
+ to_x + to_y * slant, to_y);
+ }
+ void close_path ()
+ {
+ funcs->close_path (draw_data, st);
+ }
+
+ protected:
+ float slant;
+ bool not_slanted;
+ hb_draw_funcs_t *funcs;
+ void *draw_data;
+ hb_draw_state_t st;
};
-#endif
#endif /* HB_DRAW_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.cc b/src/3rdparty/harfbuzz-ng/src/hb-face.cc
index 2c0087370c..5365598636 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-face.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-face.cc
@@ -143,7 +143,7 @@ hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
typedef struct hb_face_for_data_closure_t {
hb_blob_t *blob;
- unsigned int index;
+ uint16_t index;
} hb_face_for_data_closure_t;
static hb_face_for_data_closure_t *
@@ -156,7 +156,7 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
return nullptr;
closure->blob = blob;
- closure->index = index;
+ closure->index = (uint16_t) (index & 0xFFFFu);
return closure;
}
@@ -195,9 +195,19 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
* @index: The index of the face within @blob
*
* Constructs a new face object from the specified blob and
- * a face index into that blob. This is used for blobs of
- * file formats such as Dfont and TTC that can contain more
- * than one face.
+ * a face index into that blob.
+ *
+ * The face index is used for blobs of file formats such as TTC and
+ * and DFont that can contain more than one face. Face indices within
+ * such collections are zero-based.
+ *
+ * <note>Note: If the blob font format is not a collection, @index
+ * is ignored. Otherwise, only the lower 16-bits of @index are used.
+ * The unmodified @index can be accessed via hb_face_get_index().</note>
+ *
+ * <note>Note: The high 16-bits of @index, if non-zero, are used by
+ * hb_font_create() to load named-instances in variable fonts. See
+ * hb_font_create() for details.</note>
*
* Return value: (transfer full): The new face object
*
@@ -420,7 +430,8 @@ hb_face_reference_blob (hb_face_t *face)
* Assigns the specified face-index to @face. Fails if the
* face is immutable.
*
- * <note>Note: face indices within a collection are zero-based.</note>
+ * <note>Note: changing the index has no effect on the face itself
+ * This only changes the value returned by hb_face_get_index().</note>
*
* Since: 0.9.2
**/
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc
index c5b7c2c230..f8524ecc8e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc
@@ -117,7 +117,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
if (HB_DIRECTION_IS_BACKWARD (direction))
hb_buffer_reverse (buffer);
- buffer->safe_to_break_all ();
+ buffer->clear_glyph_flags ();
return true;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-font.cc
index fa8da96395..db05f017a5 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-font.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-font.cc
@@ -29,6 +29,7 @@
#include "hb.hh"
#include "hb-font.hh"
+#include "hb-draw.hh"
#include "hb-machinery.hh"
#include "hb-ot.h"
@@ -501,6 +502,136 @@ hb_font_get_glyph_from_name_default (hb_font_t *font,
return font->parent->get_glyph_from_name (name, len, glyph);
}
+static void
+hb_font_get_glyph_shape_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data,
+ void *user_data HB_UNUSED)
+{
+}
+
+
+typedef struct hb_font_get_glyph_shape_default_adaptor_t {
+ hb_draw_funcs_t *draw_funcs;
+ void *draw_data;
+ float x_scale;
+ float y_scale;
+} hb_font_get_glyph_shape_default_adaptor_t;
+
+static void
+hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ st->current_x *= x_scale;
+ st->current_y *= y_scale;
+
+ adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ st->current_x *= x_scale;
+ st->current_y *= y_scale;
+
+ adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
+ x_scale * control_x, y_scale * control_y,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, 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,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ st->current_x *= x_scale;
+ st->current_y *= y_scale;
+
+ adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
+ x_scale * control1_x, y_scale * control1_y,
+ x_scale * control2_x, y_scale * control2_y,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_close_path_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+
+ adaptor->draw_funcs->emit_close_path (adaptor->draw_data, *st);
+}
+
+static const hb_draw_funcs_t _hb_draw_funcs_default = {
+ HB_OBJECT_HEADER_STATIC,
+
+ {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_default,
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ }
+};
+
+static void
+hb_font_get_glyph_shape_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t adaptor = {
+ draw_funcs,
+ draw_data,
+ (float) font->x_scale / (float) font->parent->x_scale,
+ (float) font->y_scale / (float) font->parent->y_scale
+ };
+
+ font->parent->get_glyph_shape (glyph,
+ const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default),
+ &adaptor);
+}
+
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
{
HB_OBJECT_HEADER_STATIC,
@@ -631,7 +762,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
* @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
- * Attaches a user-data key/data pair to the specified font-functions structure.
+ * Attaches a user-data key/data pair to the specified font-functions structure.
*
* Return value: %true if success, %false otherwise
*
@@ -821,7 +952,7 @@ hb_font_get_glyph (hb_font_t *font,
* @glyph: (out): The glyph ID retrieved
*
* Fetches the nominal glyph ID for a Unicode code point in the
- * specified font.
+ * specified font.
*
* This version of the function should not be used to fetch glyph IDs
* for code points modified by variation selectors. For variation-selector
@@ -940,7 +1071,7 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
* @advance_stride: The stride between successive advances
*
* Fetches the advances for a sequence of glyph IDs in the specified
- * font, for horizontal text segments.
+ * font, for horizontal text segments.
*
* Since: 1.8.6
**/
@@ -964,7 +1095,7 @@ hb_font_get_glyph_h_advances (hb_font_t* font,
* @advance_stride: (out): The stride between successive advances
*
* Fetches the advances for a sequence of glyph IDs in the specified
- * font, for vertical text segments.
+ * font, for vertical text segments.
*
* Since: 1.8.6
**/
@@ -1168,6 +1299,26 @@ hb_font_get_glyph_from_name (hb_font_t *font,
return font->get_glyph_from_name (name, len, glyph);
}
+/**
+ * hb_font_get_glyph_shape:
+ * @font: #hb_font_t to work upon
+ * @glyph: : The glyph ID
+ * @dfuncs: #hb_draw_funcs_t to draw to
+ * @draw_data: User data to pass to draw callbacks
+ *
+ * Fetches the glyph shape that corresponds to a glyph in the specified @font.
+ * The shape is returned by way of calls to the callsbacks of the @dfuncs
+ * objects, with @draw_data passed to them.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_font_get_glyph_shape (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data)
+{
+ font->get_glyph_shape (glyph, dfuncs, draw_data);
+}
/* A bit higher-level, and with fallback */
@@ -1190,7 +1341,7 @@ hb_font_get_extents_for_direction (hb_font_t *font,
hb_direction_t direction,
hb_font_extents_t *extents)
{
- return font->get_extents_for_direction (direction, extents);
+ font->get_extents_for_direction (direction, extents);
}
/**
* hb_font_get_glyph_advance_for_direction:
@@ -1215,7 +1366,7 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
hb_position_t *x,
hb_position_t *y)
{
- return font->get_glyph_advance_for_direction (glyph, direction, x, y);
+ font->get_glyph_advance_for_direction (glyph, direction, x, y);
}
/**
* hb_font_get_glyph_advances_for_direction:
@@ -1278,7 +1429,7 @@ hb_font_get_glyph_origin_for_direction (hb_font_t *font,
* @font: #hb_font_t to work upon
* @glyph: The glyph ID to query
* @direction: The direction of the text segment
- * @x: (inout): Input = The original X coordinate
+ * @x: (inout): Input = The original X coordinate
* Output = The X coordinate plus the X-coordinate of the origin
* @y: (inout): Input = The original Y coordinate
* Output = The Y coordinate plus the Y-coordinate of the origin
@@ -1306,7 +1457,7 @@ hb_font_add_glyph_origin_for_direction (hb_font_t *font,
* @font: #hb_font_t to work upon
* @glyph: The glyph ID to query
* @direction: The direction of the text segment
- * @x: (inout): Input = The original X coordinate
+ * @x: (inout): Input = The original X coordinate
* Output = The X coordinate minus the X-coordinate of the origin
* @y: (inout): Input = The original Y coordinate
* Output = The Y coordinate minus the Y-coordinate of the origin
@@ -1477,6 +1628,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
1000, /* x_scale */
1000, /* y_scale */
+ 0., /* slant */
+ 0., /* slant_xy; */
1<<16, /* x_mult */
1<<16, /* y_mult */
@@ -1521,6 +1674,13 @@ _hb_font_create (hb_face_t *face)
*
* Constructs a new font object from the specified face.
*
+ * <note>Note: If @face's index value (as passed to hb_face_create()
+ * has non-zero top 16-bits, those bits minus one are passed to
+ * hb_font_set_var_named_instance(), effectively loading a named-instance
+ * of a variable font, instead of the default-instance. This allows
+ * specifying which named-instance to load by default when creating the
+ * face.</note>
+ *
* Return value: (transfer full): The new font object
*
* Since: 0.9.2
@@ -1535,6 +1695,11 @@ hb_font_create (hb_face_t *face)
hb_ot_font_set_funcs (font);
#endif
+#ifndef HB_NO_VAR
+ if (face && face->index >> 16)
+ hb_font_set_var_named_instance (font, (face->index >> 16) - 1);
+#endif
+
return font;
}
@@ -1578,6 +1743,7 @@ hb_font_create_sub_font (hb_font_t *parent)
font->x_scale = parent->x_scale;
font->y_scale = parent->y_scale;
+ font->slant = parent->slant;
font->mults_changed ();
font->x_ppem = parent->x_ppem;
font->y_ppem = parent->y_ppem;
@@ -1668,12 +1834,12 @@ hb_font_destroy (hb_font_t *font)
/**
* hb_font_set_user_data: (skip)
* @font: #hb_font_t to work upon
- * @key: The user-data key
+ * @key: The user-data key
* @data: A pointer to the user data
* @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
- * Attaches a user-data key/data pair to the specified font object.
+ * Attaches a user-data key/data pair to the specified font object.
*
* Return value: %true if success, %false otherwise
*
@@ -1875,7 +2041,7 @@ hb_font_set_funcs (hb_font_t *font,
* @font_data: (destroy destroy) (scope notified): Data to attach to @font
* @destroy: (nullable): The function to call when @font_data is not needed anymore
*
- * Replaces the user data attached to a font, updating the font's
+ * Replaces the user data attached to a font, updating the font's
* @destroy callback.
*
* Since: 0.9.2
@@ -1949,7 +2115,7 @@ hb_font_get_scale (hb_font_t *font,
* @x_ppem: Horizontal ppem value to assign
* @y_ppem: Vertical ppem value to assign
*
- * Sets the horizontal and vertical pixels-per-em (ppem) of a font.
+ * Sets the horizontal and vertical pixels-per-em (ppem) of a font.
*
* Since: 0.9.2
**/
@@ -1971,7 +2137,7 @@ hb_font_set_ppem (hb_font_t *font,
* @x_ppem: (out): Horizontal ppem value
* @y_ppem: (out): Vertical ppem value
*
- * Fetches the horizontal and vertical points-per-em (ppem) of a font.
+ * Fetches the horizontal and vertical points-per-em (ppem) of a font.
*
* Since: 0.9.2
**/
@@ -2015,7 +2181,7 @@ hb_font_set_ptem (hb_font_t *font,
*
* Return value: Point size. A value of zero means "not set."
*
- * Since: 0.9.2
+ * Since: 1.6.0
**/
float
hb_font_get_ptem (hb_font_t *font)
@@ -2023,6 +2189,53 @@ hb_font_get_ptem (hb_font_t *font)
return font->ptem;
}
+/**
+ * hb_font_set_synthetic_slant:
+ * @font: #hb_font_t to work upon
+ * @slant: synthetic slant value.
+ *
+ * Sets the "synthetic slant" of a font. By default is zero.
+ * Synthetic slant is the graphical skew applied to the font
+ * at rendering time.
+ *
+ * HarfBuzz needs to know this value to adjust shaping results,
+ * metrics, and style values to match the slanted rendering.
+ *
+ * <note>Note: The glyph shape fetched via the
+ * hb_font_get_glyph_shape() is slanted to reflect this value
+ * as well.</note>
+ *
+ * <note>Note: The slant value is a ratio. For example, a
+ * 20% slant would be represented as a 0.2 value.</note>
+ *
+ * Since: 3.3.0
+ **/
+HB_EXTERN void
+hb_font_set_synthetic_slant (hb_font_t *font, float slant)
+{
+ if (hb_object_is_immutable (font))
+ return;
+
+ font->slant = slant;
+ font->mults_changed ();
+}
+
+/**
+ * hb_font_get_synthetic_slant:
+ * @font: #hb_font_t to work upon
+ *
+ * Fetches the "synthetic slant" of a font.
+ *
+ * Return value: Synthetic slant. By default is zero.
+ *
+ * Since: 3.3.0
+ **/
+HB_EXTERN float
+hb_font_get_synthetic_slant (hb_font_t *font)
+{
+ return font->slant;
+}
+
#ifndef HB_NO_VAR
/*
* Variations
@@ -2036,6 +2249,10 @@ hb_font_get_ptem (hb_font_t *font)
*
* Applies a list of font-variation settings to a font.
*
+ * Note that this overrides all existing variations set on @font.
+ * Axes not included in @variations will be effectively set to their
+ * default values.
+ *
* Since: 1.4.2
*/
void
@@ -2091,6 +2308,10 @@ hb_font_set_variations (hb_font_t *font,
* Applies a list of variation coordinates (in design-space units)
* to a font.
*
+ * Note that this overrides all existing variations set on @font.
+ * Axes not included in @coords will be effectively set to their
+ * default values.
+ *
* Since: 1.4.2
*/
void
@@ -2154,6 +2375,10 @@ hb_font_set_var_named_instance (hb_font_t *font,
* Applies a list of variation coordinates (in normalized units)
* to a font.
*
+ * Note that this overrides all existing variations set on @font.
+ * Axes not included in @coords will be effectively set to their
+ * default values.
+ *
* <note>Note: Coordinates should be normalized to 2.14.</note>
*
* Since: 1.4.2
@@ -2196,14 +2421,19 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
/**
* hb_font_get_var_coords_normalized:
* @font: #hb_font_t to work upon
- * @length: Number of coordinates retrieved
+ * @length: (out): Number of coordinates retrieved
*
* Fetches the list of normalized variation coordinates currently
* set on a font.
*
+ * Note that this returned array may only contain values for some
+ * (or none) of the axes; omitted axes effectively have zero values.
+ *
* Return value is valid as long as variation coordinates of the font
* are not modified.
*
+ * Return value: coordinates array
+ *
* Since: 1.4.2
*/
const int *
@@ -2216,18 +2446,24 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
return font->coords;
}
-#ifdef HB_EXPERIMENTAL_API
/**
* hb_font_get_var_coords_design:
* @font: #hb_font_t to work upon
- * @length: (out): number of coordinates
+ * @length: (out): Number of coordinates retrieved
+ *
+ * Fetches the list of variation coordinates (in design-space units) currently
+ * set on a font.
+ *
+ * Note that this returned array may only contain values for some
+ * (or none) of the axes; omitted axes effectively have their default
+ * values.
*
* Return value is valid as long as variation coordinates of the font
* are not modified.
*
* Return value: coordinates array
*
- * Since: EXPERIMENTAL
+ * Since: 3.3.0
*/
const float *
hb_font_get_var_coords_design (hb_font_t *font,
@@ -2239,7 +2475,6 @@ hb_font_get_var_coords_design (hb_font_t *font,
return font->design_coords;
}
#endif
-#endif
#ifndef HB_DISABLE_DEPRECATED
/*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.h b/src/3rdparty/harfbuzz-ng/src/hb-font.h
index 15dc126523..9548857535 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-font.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-font.h
@@ -511,6 +511,25 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
hb_codepoint_t *glyph,
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
+ *
+ **/
+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);
+
/* func setters */
@@ -770,6 +789,22 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_from_name_func_t func,
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.
+ *
+ * Since: 4.0.0
+ **/
+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);
+
/* func dispatch */
HB_EXTERN hb_bool_t
@@ -850,6 +885,11 @@ hb_font_get_glyph_from_name (hb_font_t *font,
const char *name, int len, /* -1 means nul-terminated */
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);
+
/* high-level funcs, with fallback */
@@ -1024,6 +1064,12 @@ HB_EXTERN float
hb_font_get_ptem (hb_font_t *font);
HB_EXTERN void
+hb_font_set_synthetic_slant (hb_font_t *font, float slant);
+
+HB_EXTERN float
+hb_font_get_synthetic_slant (hb_font_t *font);
+
+HB_EXTERN void
hb_font_set_variations (hb_font_t *font,
const hb_variation_t *variations,
unsigned int variations_length);
@@ -1033,11 +1079,9 @@ hb_font_set_var_coords_design (hb_font_t *font,
const float *coords,
unsigned int coords_length);
-#ifdef HB_EXPERIMENTAL_API
HB_EXTERN const float *
hb_font_get_var_coords_design (hb_font_t *font,
unsigned int *length);
-#endif
HB_EXTERN void
hb_font_set_var_coords_normalized (hb_font_t *font,
@@ -1052,11 +1096,6 @@ HB_EXTERN void
hb_font_set_var_named_instance (hb_font_t *font,
unsigned instance_index);
-#ifdef HB_EXPERIMENTAL_API
-HB_EXTERN hb_bool_t
-hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
- const hb_draw_funcs_t *funcs, void *user_data);
-#endif
HB_END_DECLS
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.hh b/src/3rdparty/harfbuzz-ng/src/hb-font.hh
index 8fc7f44d44..70311b4a85 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-font.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-font.hh
@@ -57,6 +57,7 @@
HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
HB_FONT_FUNC_IMPLEMENT (glyph_name) \
HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_shape) \
/* ^--- Add new callbacks here */
struct hb_font_funcs_t
@@ -109,6 +110,8 @@ struct hb_font_t
int32_t x_scale;
int32_t y_scale;
+ float slant;
+ float slant_xy;
int64_t x_mult;
int64_t y_mult;
@@ -138,6 +141,8 @@ struct hb_font_t
hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
+ float em_fscalef_x (float v) { return em_fscalef (v, x_scale); }
+ float em_fscalef_y (float v) { return em_fscalef (v, y_scale); }
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
{ return em_mult (v, dir_mult (direction)); }
@@ -217,9 +222,10 @@ struct hb_font_t
}
hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
- hb_codepoint_t *glyph)
+ hb_codepoint_t *glyph,
+ hb_codepoint_t not_found = 0)
{
- *glyph = 0;
+ *glyph = not_found;
return klass->get.f.nominal_glyph (this, user_data,
unicode, glyph,
klass->user_data.nominal_glyph);
@@ -238,9 +244,10 @@ struct hb_font_t
}
hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph)
+ hb_codepoint_t *glyph,
+ hb_codepoint_t not_found = 0)
{
- *glyph = 0;
+ *glyph = not_found;
return klass->get.f.variation_glyph (this, user_data,
unicode, variation_selector, glyph,
klass->user_data.variation_glyph);
@@ -369,6 +376,15 @@ struct hb_font_t
klass->user_data.glyph_from_name);
}
+ void get_glyph_shape (hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data)
+ {
+ klass->get.f.glyph_shape (this, user_data,
+ glyph,
+ draw_funcs, draw_data,
+ klass->user_data.glyph_shape);
+ }
+
/* A bit higher-level, and with fallback */
@@ -615,14 +631,15 @@ struct hb_font_t
signed upem = face->get_upem ();
x_mult = ((int64_t) x_scale << 16) / upem;
y_mult = ((int64_t) y_scale << 16) / upem;
+ slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
}
hb_position_t em_mult (int16_t v, int64_t mult)
- {
- return (hb_position_t) ((v * mult) >> 16);
- }
+ { return (hb_position_t) ((v * mult + 32768) >> 16); }
hb_position_t em_scalef (float v, int scale)
- { return (hb_position_t) roundf (v * scale / face->get_upem ()); }
+ { return (hb_position_t) roundf (em_fscalef (v, scale)); }
+ float em_fscalef (float v, int scale)
+ { return v * scale / face->get_upem (); }
float em_fscale (int16_t v, int scale)
{ return (float) v * scale / face->get_upem (); }
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
index 97a2c82e68..0cfbb22e31 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
@@ -33,12 +33,14 @@
#include "hb-ft.h"
+#include "hb-draw.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-cache.hh"
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
+#include FT_OUTLINE_H
#include FT_TRUETYPE_TABLES_H
@@ -361,6 +363,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
}
}
+#ifndef HB_NO_VERTICAL
static hb_position_t
hb_ft_get_glyph_v_advance (hb_font_t *font,
void *font_data,
@@ -379,9 +382,12 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
/* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
* have a Y growing upward. Hence the extra negation. */
+
return (-v + (1<<9)) >> 10;
}
+#endif
+#ifndef HB_NO_VERTICAL
static hb_bool_t
hb_ft_get_glyph_v_origin (hb_font_t *font,
void *font_data,
@@ -409,6 +415,7 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
return true;
}
+#endif
#ifndef HB_NO_OT_SHAPE_FALLBACK
static hb_position_t
@@ -561,6 +568,82 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
return true;
}
+#ifndef HB_NO_DRAW
+
+static int
+_hb_ft_move_to (const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->move_to (to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static int
+_hb_ft_line_to (const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->line_to (to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static int
+_hb_ft_conic_to (const FT_Vector *control,
+ const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->quadratic_to (control->x, control->y,
+ to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static int
+_hb_ft_cubic_to (const FT_Vector *control1,
+ const FT_Vector *control2,
+ const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->cubic_to (control1->x, control1->y,
+ control2->x, control2->y,
+ to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static void
+hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data HB_UNUSED)
+{
+ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ hb_lock_t lock (ft_font->lock);
+ FT_Face ft_face = ft_font->ft_face;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph,
+ FT_LOAD_NO_BITMAP | ft_font->load_flags)))
+ return;
+
+ if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
+ return;
+
+ const FT_Outline_Funcs outline_funcs = {
+ (FT_Outline_MoveToFunc) _hb_ft_move_to,
+ (FT_Outline_LineToFunc) _hb_ft_line_to,
+ (FT_Outline_ConicToFunc) _hb_ft_conic_to,
+ (FT_Outline_CubicToFunc) _hb_ft_cubic_to,
+ 0, /* shift */
+ 0, /* delta */
+ };
+
+ hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
+
+ FT_Outline_Decompose (&ft_face->glyph->outline,
+ &outline_funcs,
+ &draw_session);
+}
+#endif
+
+
static inline void free_static_ft_funcs ();
static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
@@ -569,15 +652,20 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
{
hb_font_funcs_t *funcs = hb_font_funcs_create ();
- hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
- //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
+
+ hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
- hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
+
+#ifndef HB_NO_VERTICAL
+ //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
+ hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
+#endif
+
#ifndef HB_NO_OT_SHAPE_FALLBACK
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
#endif
@@ -587,6 +675,10 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
+#ifndef HB_NO_DRAW
+ hb_font_funcs_set_glyph_shape_func (funcs, hb_ft_get_glyph_shape, nullptr, nullptr);
+#endif
+
hb_font_funcs_make_immutable (funcs);
hb_atexit (free_static_ft_funcs);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc
index 540b11f911..ef13f1e966 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc
@@ -90,6 +90,7 @@ hb_gobject_##name##_get_type () \
HB_DEFINE_OBJECT_TYPE (buffer)
HB_DEFINE_OBJECT_TYPE (blob)
+HB_DEFINE_OBJECT_TYPE (draw_funcs)
HB_DEFINE_OBJECT_TYPE (face)
HB_DEFINE_OBJECT_TYPE (font)
HB_DEFINE_OBJECT_TYPE (font_funcs)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h
index 63467f80df..3914a2431a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h
@@ -49,6 +49,10 @@ hb_gobject_buffer_get_type (void);
#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
HB_EXTERN GType
+hb_gobject_draw_funcs_get_type (void);
+#define HB_GOBJECT_TYPE_DRAW_FUNCS (hb_gobject_draw_funcs_get_type ())
+
+HB_EXTERN GType
hb_gobject_face_get_type (void);
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
index 209207f1e5..63dc18b466 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
@@ -439,7 +439,8 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
if (feats) gr_featureval_destroy (feats);
gr_seg_destroy (seg);
- buffer->unsafe_to_break_all ();
+ buffer->clear_glyph_flags ();
+ buffer->unsafe_to_break ();
return true;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
index b8c4472636..43a3098f65 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
@@ -90,8 +90,8 @@ struct hb_iter_t
* it will be returning pointer to temporary rvalue.
* TODO Use a wrapper return type to fix for non-reference type. */
template <typename T = item_t,
- hb_enable_if (hb_is_reference (T))>
- hb_remove_reference<item_t>* operator -> () const { return hb_addressof (**thiz()); }
+ hb_enable_if (std::is_reference<T>::value)>
+ hb_remove_reference<item_t>* operator -> () const { return std::addressof (**thiz()); }
item_t operator * () const { return thiz()->__item__ (); }
item_t operator * () { return thiz()->__item__ (); }
item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); }
@@ -162,7 +162,7 @@ struct
{
template <typename T> hb_iter_type<T>
operator () (T&& c) const
- { return hb_deref (hb_forward<T> (c)).iter (); }
+ { return hb_deref (std::forward<T> (c)).iter (); }
/* Specialization for C arrays. */
@@ -289,7 +289,7 @@ struct hb_is_source_of
{
private:
template <typename Iter2 = Iter,
- hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<hb_add_const<Item>>))>
+ hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<const Item>))>
static hb_true_type impl (hb_priority<2>);
template <typename Iter2 = Iter>
static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) >> hb_declval (Item &), hb_true_type ());
@@ -353,7 +353,7 @@ static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).
template <typename Lhs, typename Rhs,
hb_requires (hb_is_iterator (Lhs))>
static inline auto
-operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (hb_forward<Rhs> (rhs) (hb_forward<Lhs> (lhs)))
+operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (std::forward<Rhs> (rhs) (std::forward<Lhs> (lhs)))
/* hb_map(), hb_filter(), hb_reduce() */
@@ -581,6 +581,91 @@ struct
}
HB_FUNCOBJ (hb_zip);
+/* hb_concat() */
+
+template <typename A, typename B>
+struct hb_concat_iter_t :
+ hb_iter_t<hb_concat_iter_t<A, B>, typename A::item_t>
+{
+ hb_concat_iter_t () {}
+ hb_concat_iter_t (A& a, B& b) : a (a), b (b) {}
+ hb_concat_iter_t (const A& a, const B& b) : a (a), b (b) {}
+
+
+ typedef typename A::item_t __item_t__;
+ static constexpr bool is_random_access_iterator =
+ A::is_random_access_iterator &&
+ B::is_random_access_iterator;
+ static constexpr bool is_sorted_iterator = false;
+
+ __item_t__ __item__ () const
+ {
+ if (!a)
+ return *b;
+ return *a;
+ }
+
+ __item_t__ __item_at__ (unsigned i) const
+ {
+ unsigned a_len = a.len ();
+ if (i < a_len)
+ return a[i];
+ return b[i - a_len];
+ }
+
+ bool __more__ () const { return bool (a) || bool (b); }
+
+ unsigned __len__ () const { return a.len () + b.len (); }
+
+ void __next__ ()
+ {
+ if (a)
+ ++a;
+ else
+ ++b;
+ }
+
+ void __forward__ (unsigned n)
+ {
+ if (!n) return;
+ if (!is_random_access_iterator) {
+ while (n-- && *this) {
+ (*this)++;
+ }
+ return;
+ }
+
+ unsigned a_len = a.len ();
+ if (n > a_len) {
+ n -= a_len;
+ a.__forward__ (a_len);
+ b.__forward__ (n);
+ } else {
+ a.__forward__ (n);
+ }
+ }
+
+ hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); }
+ bool operator != (const hb_concat_iter_t& o) const
+ {
+ return a != o.a
+ || b != o.b;
+ }
+
+ private:
+ A a;
+ B b;
+};
+struct
+{ HB_PARTIALIZE(2);
+ template <typename A, typename B,
+ hb_requires (hb_is_iterable (A) && hb_is_iterable (B))>
+ hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>>
+ operator () (A&& a, B&& b) const
+ { return hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); }
+}
+HB_FUNCOBJ (hb_concat);
+
/* hb_apply() */
template <typename Appl>
@@ -674,8 +759,8 @@ struct hb_iota_iter_t :
template <typename S2 = S>
auto
inc (hb_type_identity<S2> s, hb_priority<1>)
- -> hb_void_t<decltype (hb_invoke (hb_forward<S2> (s), hb_declval<T&> ()))>
- { v = hb_invoke (hb_forward<S2> (s), v); }
+ -> hb_void_t<decltype (hb_invoke (std::forward<S2> (s), hb_declval<T&> ()))>
+ { v = hb_invoke (std::forward<S2> (s), v); }
void
inc (S s, hb_priority<0>)
@@ -874,7 +959,7 @@ struct
Proj&& f = hb_identity) const
{
for (auto it = hb_iter (c); it; ++it)
- if (!hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
+ if (!hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it)))
return false;
return true;
}
@@ -891,7 +976,7 @@ struct
Proj&& f = hb_identity) const
{
for (auto it = hb_iter (c); it; ++it)
- if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
+ if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it)))
return true;
return false;
}
@@ -908,7 +993,7 @@ struct
Proj&& f = hb_identity) const
{
for (auto it = hb_iter (c); it; ++it)
- if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
+ if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it)))
return false;
return true;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-kern.hh b/src/3rdparty/harfbuzz-ng/src/hb-kern.hh
index 3f952fe7fc..9ea945caed 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-kern.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-kern.hh
@@ -49,6 +49,10 @@ struct hb_kern_machine_t
hb_mask_t kern_mask,
bool scale = true) const
{
+ if (!buffer->message (font, "start kern"))
+ return;
+
+ buffer->unsafe_to_concat ();
OT::hb_ot_apply_context_t c (1, font, buffer);
c.set_lookup_mask (kern_mask);
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
@@ -67,7 +71,8 @@ struct hb_kern_machine_t
}
skippy_iter.reset (idx, 1);
- if (!skippy_iter.next ())
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
{
idx++;
continue;
@@ -125,6 +130,8 @@ struct hb_kern_machine_t
skip:
idx = skippy_iter.idx;
}
+
+ (void) buffer->message (font, "end kern");
}
const Driver &driver;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
index 010c2570d7..e52a6a4124 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
@@ -194,7 +194,8 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
}
const Returned * operator -> () const { return get (); }
- const Returned & operator * () const { return *get (); }
+ template <typename U = Returned, hb_enable_if (!hb_is_same (U, void))>
+ const U & operator * () const { return *get (); }
explicit operator bool () const
{ return get_stored () != Funcs::get_null (); }
template <typename C> operator const C * () const { return get (); }
@@ -244,19 +245,19 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
{
Stored *p = (Stored *) hb_calloc (1, sizeof (Stored));
if (likely (p))
- p->init (data);
+ p = new (p) Stored (data);
return p;
}
static Stored *create ()
{
Stored *p = (Stored *) hb_calloc (1, sizeof (Stored));
if (likely (p))
- p->init ();
+ p = new (p) Stored ();
return p;
}
static void destroy (Stored *p)
{
- p->fini ();
+ p->~Stored ();
hb_free (p);
}
@@ -272,14 +273,19 @@ struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
hb_face_lazy_loader_t<T, WheresFace>,
hb_face_t, WheresFace> {};
-template <typename T, unsigned int WheresFace>
+template <typename T, unsigned int WheresFace, bool core=false>
struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
- hb_table_lazy_loader_t<T, WheresFace>,
+ hb_table_lazy_loader_t<T, WheresFace, core>,
hb_face_t, WheresFace,
hb_blob_t>
{
static hb_blob_t *create (hb_face_t *face)
- { return hb_sanitize_context_t ().reference_table<T> (face); }
+ {
+ auto c = hb_sanitize_context_t ();
+ if (core)
+ c.set_num_glyphs (0); // So we don't recurse ad infinitum...
+ return c.reference_table<T> (face);
+ }
static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
static const hb_blob_t *get_null ()
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-map.hh
index dcd5267d74..9341637eac 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-map.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-map.hh
@@ -35,16 +35,31 @@
*/
template <typename K, typename V,
- K kINVALID = hb_is_pointer (K) ? 0 : hb_is_signed (K) ? hb_int_min (K) : (K) -1,
- V vINVALID = hb_is_pointer (V) ? 0 : hb_is_signed (V) ? hb_int_min (V) : (V) -1>
+ typename k_invalid_t = K,
+ typename v_invalid_t = V,
+ k_invalid_t kINVALID = std::is_pointer<K>::value ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1,
+ v_invalid_t vINVALID = std::is_pointer<V>::value ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1>
struct hb_hashmap_t
{
- HB_DELETE_COPY_ASSIGN (hb_hashmap_t);
hb_hashmap_t () { init (); }
~hb_hashmap_t () { fini (); }
- static_assert (hb_is_integral (K) || hb_is_pointer (K), "");
- static_assert (hb_is_integral (V) || hb_is_pointer (V), "");
+ hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { 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) { 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 ()
+ {
+ for (auto&& item : lst)
+ set (item.first, item.second);
+ }
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
+ hb_hashmap_t (const Iterable &o) : hb_hashmap_t ()
+ {
+ hb_copy (o, *this);
+ }
struct item_t
{
@@ -52,13 +67,34 @@ struct hb_hashmap_t
V value;
uint32_t hash;
- void clear () { key = kINVALID; value = vINVALID; hash = 0; }
+ void clear ()
+ {
+ new (std::addressof (key)) K ();
+ key = hb_coerce<K> (kINVALID);
+ new (std::addressof (value)) V ();
+ value = hb_coerce<V> (vINVALID);
+ hash = 0;
+ }
bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); }
bool operator == (const item_t &o) { return *this == o.key; }
- bool is_unused () const { return key == kINVALID; }
- bool is_tombstone () const { return key != kINVALID && value == vINVALID; }
- bool is_real () const { return key != kINVALID && value != vINVALID; }
+ bool is_unused () const
+ {
+ const K inv = hb_coerce<K> (kINVALID);
+ return key == inv;
+ }
+ bool is_tombstone () const
+ {
+ const K kinv = hb_coerce<K> (kINVALID);
+ const V vinv = hb_coerce<V> (vINVALID);
+ return key != kinv && value == vinv;
+ }
+ bool is_real () const
+ {
+ const K kinv = hb_coerce<K> (kINVALID);
+ const V vinv = hb_coerce<V> (vINVALID);
+ return key != kinv && value != vinv;
+ }
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
};
@@ -70,6 +106,16 @@ struct hb_hashmap_t
unsigned int prime;
item_t *items;
+ friend void swap (hb_hashmap_t& a, hb_hashmap_t& b)
+ {
+ if (unlikely (!a.successful || !b.successful))
+ return;
+ hb_swap (a.population, b.population);
+ hb_swap (a.occupancy, b.occupancy);
+ hb_swap (a.mask, b.mask);
+ hb_swap (a.prime, b.prime);
+ hb_swap (a.items, b.items);
+ }
void init_shallow ()
{
successful = true;
@@ -85,8 +131,13 @@ struct hb_hashmap_t
}
void fini_shallow ()
{
- hb_free (items);
- items = nullptr;
+ if (likely (items)) {
+ unsigned size = mask + 1;
+ for (unsigned i = 0; i < size; i++)
+ items[i].~item_t ();
+ hb_free (items);
+ items = nullptr;
+ }
population = occupancy = 0;
}
void fini ()
@@ -130,39 +181,42 @@ struct hb_hashmap_t
/* Insert back old items. */
if (old_items)
for (unsigned int i = 0; i < old_size; i++)
+ {
if (old_items[i].is_real ())
+ {
set_with_hash (old_items[i].key,
old_items[i].hash,
- old_items[i].value);
+ std::move (old_items[i].value));
+ }
+ old_items[i].~item_t ();
+ }
hb_free (old_items);
return true;
}
- bool set (K key, V value)
- {
- return set_with_hash (key, hb_hash (key), value);
- }
+ bool set (K key, const V& value) { return set_with_hash (key, hb_hash (key), value); }
+ bool set (K key, V&& value) { return set_with_hash (key, hb_hash (key), std::move (value)); }
V get (K key) const
{
- if (unlikely (!items)) return vINVALID;
+ if (unlikely (!items)) return hb_coerce<V> (vINVALID);
unsigned int i = bucket_for (key);
- return items[i].is_real () && items[i] == key ? items[i].value : vINVALID;
+ return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID);
}
- void del (K key) { set (key, vINVALID); }
+ void del (K key) { set (key, hb_coerce<V> (vINVALID)); }
/* Has interface. */
- static constexpr V SENTINEL = vINVALID;
typedef V value_t;
value_t operator [] (K k) const { return get (k); }
bool has (K k, V *vp = nullptr) const
{
V v = (*this)[k];
if (vp) *vp = v;
- return v != SENTINEL;
+ const V vinv = hb_coerce<V> (vINVALID);
+ return v != vinv;
}
/* Projection. */
V operator () (K k) const { return get (k); }
@@ -213,14 +267,17 @@ struct hb_hashmap_t
protected:
- bool set_with_hash (K key, uint32_t hash, V value)
+ template <typename VV>
+ bool set_with_hash (K key, uint32_t hash, VV&& value)
{
if (unlikely (!successful)) return false;
- if (unlikely (key == kINVALID)) return true;
+ const K kinv = hb_coerce<K> (kINVALID);
+ if (unlikely (key == kinv)) return true;
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
unsigned int i = bucket_for_hash (key, hash);
- if (value == vINVALID && items[i].key != key)
+ const V vinv = hb_coerce<V> (vINVALID);
+ if (value == vinv && items[i].key != key)
return true; /* Trying to delete non-existent key. */
if (!items[i].is_unused ())
@@ -320,8 +377,27 @@ struct hb_hashmap_t
struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_codepoint_t,
+ hb_codepoint_t,
+ hb_codepoint_t,
HB_MAP_VALUE_INVALID,
- HB_MAP_VALUE_INVALID> {};
-
+ HB_MAP_VALUE_INVALID>
+{
+ using hashmap = hb_hashmap_t<hb_codepoint_t,
+ hb_codepoint_t,
+ hb_codepoint_t,
+ hb_codepoint_t,
+ HB_MAP_VALUE_INVALID,
+ HB_MAP_VALUE_INVALID>;
+
+ hb_map_t () = default;
+ ~hb_map_t () = default;
+ hb_map_t (hb_map_t&) = default;
+ 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) {}
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
+ hb_map_t (const Iterable &o) : hashmap (o) {}
+};
#endif /* HB_MAP_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh
index a714bc2bf0..3fea5d995e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh
@@ -29,6 +29,10 @@
#include "hb.hh"
+#include <memory>
+#include <type_traits>
+#include <utility>
+
/*
* C++ template meta-programming & fundamentals used with them.
@@ -82,30 +86,13 @@ template <> struct hb_priority<0> {};
template <typename T> struct hb_type_identity_t { typedef T type; };
template <typename T> using hb_type_identity = typename hb_type_identity_t<T>::type;
-struct
-{
- template <typename T> constexpr T*
- operator () (T& arg) const
- {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-align"
- /* https://en.cppreference.com/w/cpp/memory/addressof */
- return reinterpret_cast<T*> (
- &const_cast<char&> (
- reinterpret_cast<const volatile char&> (arg)));
-#pragma GCC diagnostic pop
- }
-}
-HB_FUNCOBJ (hb_addressof);
-
template <typename T> static inline T hb_declval ();
#define hb_declval(T) (hb_declval<T> ())
template <typename T> struct hb_match_const : hb_type_identity_t<T>, hb_false_type {};
template <typename T> struct hb_match_const<const T> : hb_type_identity_t<T>, hb_true_type {};
template <typename T> using hb_remove_const = typename hb_match_const<T>::type;
-template <typename T> using hb_add_const = const T;
-#define hb_is_const(T) hb_match_const<T>::value
+
template <typename T> struct hb_match_reference : hb_type_identity_t<T>, hb_false_type {};
template <typename T> struct hb_match_reference<T &> : hb_type_identity_t<T>, hb_true_type {};
template <typename T> struct hb_match_reference<T &&> : hb_type_identity_t<T>, hb_true_type {};
@@ -116,92 +103,39 @@ template <typename T> using hb_add_lvalue_reference = decltype (_hb_try_add_lval
template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_type_identity<T&&>;
template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
template <typename T> using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference<T> (hb_prioritize));
-#define hb_is_reference(T) hb_match_reference<T>::value
+
template <typename T> struct hb_match_pointer : hb_type_identity_t<T>, hb_false_type {};
template <typename T> struct hb_match_pointer<T *> : hb_type_identity_t<T>, hb_true_type {};
template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<hb_remove_reference<T>*>;
template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<T>;
template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (hb_prioritize));
-#define hb_is_pointer(T) hb_match_pointer<T>::value
/* TODO Add feature-parity to std::decay. */
template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
-
-template<bool B, class T, class F>
-struct _hb_conditional { typedef T type; };
-template<class T, class F>
-struct _hb_conditional<false, T, F> { typedef F type; };
-template<bool B, class T, class F>
-using hb_conditional = typename _hb_conditional<B, T, F>::type;
-
-
-template <typename From, typename To>
-struct hb_is_convertible
-{
- private:
- static constexpr bool from_void = hb_is_same (void, hb_decay<From>);
- static constexpr bool to_void = hb_is_same (void, hb_decay<To> );
- static constexpr bool either_void = from_void || to_void;
- static constexpr bool both_void = from_void && to_void;
-
- static hb_true_type impl2 (hb_conditional<to_void, int, To>);
-
- template <typename T>
- static auto impl (hb_priority<1>) -> decltype (impl2 (hb_declval (T)));
- template <typename T>
- static hb_false_type impl (hb_priority<0>);
- public:
- static constexpr bool value = both_void ||
- (!either_void &&
- decltype (impl<hb_conditional<from_void, int, From>> (hb_prioritize))::value);
-};
-#define hb_is_convertible(From,To) hb_is_convertible<From, To>::value
-
-template <typename Base, typename Derived>
-using hb_is_base_of = hb_is_convertible<hb_decay<Derived> *, hb_decay<Base> *>;
-#define hb_is_base_of(Base,Derived) hb_is_base_of<Base, Derived>::value
+#define hb_is_convertible(From,To) std::is_convertible<From, To>::value
template <typename From, typename To>
using hb_is_cr_convertible = hb_bool_constant<
hb_is_same (hb_decay<From>, hb_decay<To>) &&
- (!hb_is_const (From) || hb_is_const (To)) &&
- (!hb_is_reference (To) || hb_is_const (To) || hb_is_reference (To))
+ (!std::is_const<From>::value || std::is_const<To>::value) &&
+ (!std::is_reference<To>::value || std::is_const<To>::value || std::is_reference<To>::value)
>;
#define hb_is_cr_convertible(From,To) hb_is_cr_convertible<From, To>::value
-/* std::move and std::forward */
-
-template <typename T>
-static constexpr hb_remove_reference<T>&& hb_move (T&& t) { return (hb_remove_reference<T>&&) (t); }
-
-template <typename T>
-static constexpr T&& hb_forward (hb_remove_reference<T>& t) { return (T&&) t; }
-template <typename T>
-static constexpr T&& hb_forward (hb_remove_reference<T>&& t) { return (T&&) t; }
struct
{
template <typename T> constexpr auto
- operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
+ operator () (T&& v) const HB_AUTO_RETURN (std::forward<T> (v))
template <typename T> constexpr auto
operator () (T *v) const HB_AUTO_RETURN (*v)
}
HB_FUNCOBJ (hb_deref);
-struct
-{
- template <typename T> constexpr auto
- operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
-
- template <typename T> constexpr auto
- operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v))
-}
-HB_FUNCOBJ (hb_ref);
-
template <typename T>
struct hb_reference_wrapper
{
@@ -215,7 +149,7 @@ struct hb_reference_wrapper
template <typename T>
struct hb_reference_wrapper<T&>
{
- hb_reference_wrapper (T& v) : v (hb_addressof (v)) {}
+ 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; }
@@ -226,50 +160,6 @@ struct hb_reference_wrapper<T&>
/* Type traits */
-template <typename T>
-using hb_is_integral = hb_bool_constant<
- hb_is_same (hb_decay<T>, char) ||
- hb_is_same (hb_decay<T>, signed char) ||
- hb_is_same (hb_decay<T>, unsigned char) ||
- hb_is_same (hb_decay<T>, signed int) ||
- hb_is_same (hb_decay<T>, unsigned int) ||
- hb_is_same (hb_decay<T>, signed short) ||
- hb_is_same (hb_decay<T>, unsigned short) ||
- hb_is_same (hb_decay<T>, signed long) ||
- hb_is_same (hb_decay<T>, unsigned long) ||
- hb_is_same (hb_decay<T>, signed long long) ||
- hb_is_same (hb_decay<T>, unsigned long long) ||
- false
->;
-#define hb_is_integral(T) hb_is_integral<T>::value
-template <typename T>
-using hb_is_floating_point = hb_bool_constant<
- hb_is_same (hb_decay<T>, float) ||
- hb_is_same (hb_decay<T>, double) ||
- hb_is_same (hb_decay<T>, long double) ||
- false
->;
-#define hb_is_floating_point(T) hb_is_floating_point<T>::value
-template <typename T>
-using hb_is_arithmetic = hb_bool_constant<
- hb_is_integral (T) ||
- hb_is_floating_point (T) ||
- false
->;
-#define hb_is_arithmetic(T) hb_is_arithmetic<T>::value
-
-
-template <typename T, bool is_arithmetic> struct hb_is_signed_;
-template <typename T> struct hb_is_signed_<T, false> : hb_false_type {};
-template <typename T> struct hb_is_signed_<T, true> : hb_bool_constant<(T) -1 < (T) 0> {};
-template <typename T> struct hb_is_signed : hb_is_signed_<T, hb_is_arithmetic (T)> {};
-#define hb_is_signed(T) hb_is_signed<T>::value
-template <typename T, bool is_arithmetic> struct hb_is_unsigned_;
-template <typename T> struct hb_is_unsigned_<T, false> : hb_false_type {};
-template <typename T> struct hb_is_unsigned_<T, true> : hb_bool_constant<(T) 0 < (T) -1> {};
-template <typename T> struct hb_is_unsigned : hb_is_unsigned_<T, hb_is_arithmetic (T)> {};
-#define hb_is_unsigned(T) hb_is_unsigned<T>::value
-
template <typename T> struct hb_int_min;
template <> struct hb_int_min<char> : hb_integral_constant<char, CHAR_MIN> {};
template <> struct hb_int_min<signed char> : hb_integral_constant<signed char, SCHAR_MIN> {};
@@ -309,108 +199,6 @@ template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigne
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
-template <typename T, typename>
-struct _hb_is_destructible : hb_false_type {};
-template <typename T>
-struct _hb_is_destructible<T, hb_void_t<decltype (hb_declval (T).~T ())>> : hb_true_type {};
-template <typename T>
-using hb_is_destructible = _hb_is_destructible<T, void>;
-#define hb_is_destructible(T) hb_is_destructible<T>::value
-
-template <typename T, typename, typename ...Ts>
-struct _hb_is_constructible : hb_false_type {};
-template <typename T, typename ...Ts>
-struct _hb_is_constructible<T, hb_void_t<decltype (T (hb_declval (Ts)...))>, Ts...> : hb_true_type {};
-template <typename T, typename ...Ts>
-using hb_is_constructible = _hb_is_constructible<T, void, Ts...>;
-#define hb_is_constructible(...) hb_is_constructible<__VA_ARGS__>::value
-
-template <typename T>
-using hb_is_default_constructible = hb_is_constructible<T>;
-#define hb_is_default_constructible(T) hb_is_default_constructible<T>::value
-
-template <typename T>
-using hb_is_copy_constructible = hb_is_constructible<T, hb_add_lvalue_reference<hb_add_const<T>>>;
-#define hb_is_copy_constructible(T) hb_is_copy_constructible<T>::value
-
-template <typename T>
-using hb_is_move_constructible = hb_is_constructible<T, hb_add_rvalue_reference<hb_add_const<T>>>;
-#define hb_is_move_constructible(T) hb_is_move_constructible<T>::value
-
-template <typename T, typename U, typename>
-struct _hb_is_assignable : hb_false_type {};
-template <typename T, typename U>
-struct _hb_is_assignable<T, U, hb_void_t<decltype (hb_declval (T) = hb_declval (U))>> : hb_true_type {};
-template <typename T, typename U>
-using hb_is_assignable = _hb_is_assignable<T, U, void>;
-#define hb_is_assignable(T,U) hb_is_assignable<T, U>::value
-
-template <typename T>
-using hb_is_copy_assignable = hb_is_assignable<hb_add_lvalue_reference<T>,
- hb_add_lvalue_reference<hb_add_const<T>>>;
-#define hb_is_copy_assignable(T) hb_is_copy_assignable<T>::value
-
-template <typename T>
-using hb_is_move_assignable = hb_is_assignable<hb_add_lvalue_reference<T>,
- hb_add_rvalue_reference<T>>;
-#define hb_is_move_assignable(T) hb_is_move_assignable<T>::value
-
-/* Trivial versions. */
-
-template <typename T> union hb_trivial { T value; };
-
-template <typename T>
-using hb_is_trivially_destructible= hb_is_destructible<hb_trivial<T>>;
-#define hb_is_trivially_destructible(T) hb_is_trivially_destructible<T>::value
-
-/* Don't know how to do the following. */
-//template <typename T, typename ...Ts>
-//using hb_is_trivially_constructible= hb_is_constructible<hb_trivial<T>, hb_trivial<Ts>...>;
-//#define hb_is_trivially_constructible(...) hb_is_trivially_constructible<__VA_ARGS__>::value
-
-template <typename T>
-using hb_is_trivially_default_constructible= hb_is_default_constructible<hb_trivial<T>>;
-#define hb_is_trivially_default_constructible(T) hb_is_trivially_default_constructible<T>::value
-
-template <typename T>
-using hb_is_trivially_copy_constructible= hb_is_copy_constructible<hb_trivial<T>>;
-#define hb_is_trivially_copy_constructible(T) hb_is_trivially_copy_constructible<T>::value
-
-template <typename T>
-using hb_is_trivially_move_constructible= hb_is_move_constructible<hb_trivial<T>>;
-#define hb_is_trivially_move_constructible(T) hb_is_trivially_move_constructible<T>::value
-
-/* Don't know how to do the following. */
-//template <typename T, typename U>
-//using hb_is_trivially_assignable= hb_is_assignable<hb_trivial<T>, hb_trivial<U>>;
-//#define hb_is_trivially_assignable(T,U) hb_is_trivially_assignable<T, U>::value
-
-template <typename T>
-using hb_is_trivially_copy_assignable= hb_is_copy_assignable<hb_trivial<T>>;
-#define hb_is_trivially_copy_assignable(T) hb_is_trivially_copy_assignable<T>::value
-
-template <typename T>
-using hb_is_trivially_move_assignable= hb_is_move_assignable<hb_trivial<T>>;
-#define hb_is_trivially_move_assignable(T) hb_is_trivially_move_assignable<T>::value
-
-template <typename T>
-using hb_is_trivially_copyable= hb_bool_constant<
- hb_is_trivially_destructible (T) &&
- (!hb_is_move_assignable (T) || hb_is_trivially_move_assignable (T)) &&
- (!hb_is_move_constructible (T) || hb_is_trivially_move_constructible (T)) &&
- (!hb_is_copy_assignable (T) || hb_is_trivially_copy_assignable (T)) &&
- (!hb_is_copy_constructible (T) || hb_is_trivially_copy_constructible (T)) &&
- true
->;
-#define hb_is_trivially_copyable(T) hb_is_trivially_copyable<T>::value
-
-template <typename T>
-using hb_is_trivial= hb_bool_constant<
- hb_is_trivially_copyable (T) &&
- hb_is_trivially_default_constructible (T)
->;
-#define hb_is_trivial(T) hb_is_trivial<T>::value
-
/* hb_unwrap_type (T)
* If T has no T::type, returns T. Otherwise calls itself on T::type recursively.
*/
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.cc b/src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.cc
deleted file mode 100644
index 6d09b252d8..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright © 2011,2012,2013 Google, Inc.
- * Copyright © 2021 Khaled Hosny
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ms-feature-ranges.hh"
-
-bool
-hb_ms_setup_features (const hb_feature_t *features,
- unsigned int num_features,
- hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */
- hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */)
-{
- feature_records.shrink(0);
- range_records.shrink(0);
-
- /* Sort features by start/end events. */
- hb_vector_t<hb_ms_feature_event_t> feature_events;
- for (unsigned int i = 0; i < num_features; i++)
- {
- hb_ms_active_feature_t feature;
- feature.fea.tag_le = hb_uint32_swap (features[i].tag);
- feature.fea.value = features[i].value;
- feature.order = i;
-
- hb_ms_feature_event_t *event;
-
- event = feature_events.push ();
- event->index = features[i].start;
- event->start = true;
- event->feature = feature;
-
- event = feature_events.push ();
- event->index = features[i].end;
- event->start = false;
- event->feature = feature;
- }
- feature_events.qsort ();
- /* Add a strategic final event. */
- {
- hb_ms_active_feature_t feature;
- feature.fea.tag_le = 0;
- feature.fea.value = 0;
- feature.order = num_features + 1;
-
- auto *event = feature_events.push ();
- event->index = 0; /* This value does magic. */
- event->start = false;
- event->feature = feature;
- }
-
- /* Scan events and save features for each range. */
- hb_vector_t<hb_ms_active_feature_t> active_features;
- unsigned int last_index = 0;
- for (unsigned int i = 0; i < feature_events.length; i++)
- {
- auto *event = &feature_events[i];
-
- if (event->index != last_index)
- {
- /* Save a snapshot of active features and the range. */
- auto *range = range_records.push ();
- auto offset = feature_records.length;
-
- active_features.qsort ();
- for (unsigned int j = 0; j < active_features.length; j++)
- {
- if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le)
- {
- feature_records.push (active_features[j].fea);
- }
- else
- {
- /* Overrides value for existing feature. */
- feature_records[feature_records.length - 1].value = active_features[j].fea.value;
- }
- }
-
- /* Will convert to pointer after all is ready, since feature_records.array
- * may move as we grow it. */
- range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset);
- range->features.num_features = feature_records.length - offset;
- range->index_first = last_index;
- range->index_last = event->index - 1;
-
- last_index = event->index;
- }
-
- if (event->start)
- {
- active_features.push (event->feature);
- }
- else
- {
- auto *feature = active_features.find (&event->feature);
- if (feature)
- active_features.remove (feature - active_features.arrayZ);
- }
- }
-
- if (!range_records.length) /* No active feature found. */
- num_features = 0;
-
- /* Fixup the pointers. */
- for (unsigned int i = 0; i < range_records.length; i++)
- {
- auto *range = &range_records[i];
- range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features);
- }
-
- return !!num_features;
-}
-
-void
-hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records,
- hb_vector_t<hb_ms_range_record_t> &range_records,
- unsigned int chars_offset,
- unsigned int chars_len,
- uint16_t *log_clusters,
- hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */
- hb_vector_t<uint32_t> &range_counts /* OUT */)
-{
- range_features.shrink (0);
- range_counts.shrink (0);
-
- auto *last_range = &range_records[0];
- for (unsigned int i = chars_offset; i < chars_len; i++)
- {
- auto *range = last_range;
- while (log_clusters[i] < range->index_first)
- range--;
- while (log_clusters[i] > range->index_last)
- range++;
- if (!range_features.length ||
- &range->features != range_features[range_features.length - 1])
- {
- auto **features = range_features.push ();
- auto *c = range_counts.push ();
- if (unlikely (!features || !c))
- {
- range_features.shrink (0);
- range_counts.shrink (0);
- break;
- }
- *features = &range->features;
- *c = 1;
- }
- else
- {
- range_counts[range_counts.length - 1]++;
- }
-
- last_range = range;
- }
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.hh b/src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.hh
index 401d1e1d97..d40fdeaa82 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.hh
@@ -52,8 +52,8 @@ struct hb_ms_active_feature_t {
a->fea.value < b->fea.value ? -1 : a->fea.value > b->fea.value ? 1 :
0;
}
- bool operator== (const hb_ms_active_feature_t *f)
- { return cmp (this, f) == 0; }
+ bool operator== (const hb_ms_active_feature_t& f) const
+ { return cmp (this, &f) == 0; }
};
struct hb_ms_feature_event_t {
@@ -77,20 +77,153 @@ struct hb_ms_range_record_t {
unsigned int index_last; /* == end - 1 */
};
-HB_INTERNAL bool
+static inline bool
hb_ms_setup_features (const hb_feature_t *features,
unsigned int num_features,
hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */
- hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */);
+ hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */)
+{
+ feature_records.shrink(0);
+ range_records.shrink(0);
+ /* Sort features by start/end events. */
+ hb_vector_t<hb_ms_feature_event_t> feature_events;
+ for (unsigned int i = 0; i < num_features; i++)
+ {
+ hb_ms_active_feature_t feature;
+ feature.fea.tag_le = hb_uint32_swap (features[i].tag);
+ feature.fea.value = features[i].value;
+ feature.order = i;
+
+ hb_ms_feature_event_t *event;
+
+ event = feature_events.push ();
+ event->index = features[i].start;
+ event->start = true;
+ event->feature = feature;
+
+ event = feature_events.push ();
+ event->index = features[i].end;
+ event->start = false;
+ event->feature = feature;
+ }
+ feature_events.qsort ();
+ /* Add a strategic final event. */
+ {
+ hb_ms_active_feature_t feature;
+ feature.fea.tag_le = 0;
+ feature.fea.value = 0;
+ feature.order = num_features + 1;
+
+ auto *event = feature_events.push ();
+ event->index = 0; /* This value does magic. */
+ event->start = false;
+ event->feature = feature;
+ }
+
+ /* Scan events and save features for each range. */
+ hb_vector_t<hb_ms_active_feature_t> active_features;
+ unsigned int last_index = 0;
+ for (unsigned int i = 0; i < feature_events.length; i++)
+ {
+ auto *event = &feature_events[i];
+
+ if (event->index != last_index)
+ {
+ /* Save a snapshot of active features and the range. */
+ auto *range = range_records.push ();
+ auto offset = feature_records.length;
+
+ active_features.qsort ();
+ for (unsigned int j = 0; j < active_features.length; j++)
+ {
+ if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le)
+ {
+ feature_records.push (active_features[j].fea);
+ }
+ else
+ {
+ /* Overrides value for existing feature. */
+ feature_records[feature_records.length - 1].value = active_features[j].fea.value;
+ }
+ }
+
+ /* Will convert to pointer after all is ready, since feature_records.array
+ * may move as we grow it. */
+ range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset);
+ range->features.num_features = feature_records.length - offset;
+ range->index_first = last_index;
+ range->index_last = event->index - 1;
-HB_INTERNAL void
+ last_index = event->index;
+ }
+
+ if (event->start)
+ {
+ active_features.push (event->feature);
+ }
+ else
+ {
+ auto *feature = active_features.lsearch (event->feature);
+ if (feature)
+ active_features.remove (feature - active_features.arrayZ);
+ }
+ }
+
+ if (!range_records.length) /* No active feature found. */
+ num_features = 0;
+
+ /* Fixup the pointers. */
+ for (unsigned int i = 0; i < range_records.length; i++)
+ {
+ auto *range = &range_records[i];
+ range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features);
+ }
+
+ return !!num_features;
+}
+
+static inline void
hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records,
hb_vector_t<hb_ms_range_record_t> &range_records,
unsigned int chars_offset,
unsigned int chars_len,
uint16_t *log_clusters,
hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */
- hb_vector_t<uint32_t> &range_counts /* OUT */);
+ hb_vector_t<uint32_t> &range_counts /* OUT */)
+{
+ range_features.shrink (0);
+ range_counts.shrink (0);
+
+ auto *last_range = &range_records[0];
+ for (unsigned int i = chars_offset; i < chars_len; i++)
+ {
+ auto *range = last_range;
+ while (log_clusters[i] < range->index_first)
+ range--;
+ while (log_clusters[i] > range->index_last)
+ range++;
+ if (!range_features.length ||
+ &range->features != range_features[range_features.length - 1])
+ {
+ auto **features = range_features.push ();
+ auto *c = range_counts.push ();
+ if (unlikely (!features || !c))
+ {
+ range_features.shrink (0);
+ range_counts.shrink (0);
+ break;
+ }
+ *features = &range->features;
+ *c = 1;
+ }
+ else
+ {
+ range_counts[range_counts.length - 1]++;
+ }
+
+ last_range = range;
+ }
+}
#endif /* HB_MS_FEATURE_RANGES_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh b/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh
index a9227a741d..6914b22450 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh
@@ -47,7 +47,7 @@
/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
-#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
+#elif !defined(HB_NO_MT) && !defined(HB_MUTEX_IMPL_STD_MUTEX) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
#include <pthread.h>
typedef pthread_mutex_t hb_mutex_impl_t;
@@ -57,7 +57,7 @@ typedef pthread_mutex_t hb_mutex_impl_t;
#define hb_mutex_impl_finish(M) pthread_mutex_destroy (M)
-#elif !defined(HB_NO_MT) && defined(_WIN32)
+#elif !defined(HB_NO_MT) && !defined(HB_MUTEX_IMPL_STD_MUTEX) && defined(_WIN32)
typedef CRITICAL_SECTION hb_mutex_impl_t;
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
@@ -70,7 +70,17 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
-#elif defined(HB_NO_MT)
+#elif !defined(HB_NO_MT)
+
+#include <mutex>
+typedef std::mutex hb_mutex_impl_t;
+#define hb_mutex_impl_init(M) HB_STMT_START { new (M) hb_mutex_impl_t; } HB_STMT_END
+#define hb_mutex_impl_lock(M) (M)->lock ()
+#define hb_mutex_impl_unlock(M) (M)->unlock ()
+#define hb_mutex_impl_finish(M) HB_STMT_START { (M)->~hb_mutex_impl_t(); } HB_STMT_END
+
+
+#else /* defined(HB_NO_MT) */
typedef int hb_mutex_impl_t;
#define hb_mutex_impl_init(M) HB_STMT_START {} HB_STMT_END
@@ -79,22 +89,21 @@ typedef int hb_mutex_impl_t;
#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
-#else
-
-#error "Could not find any system to define mutex macros."
-#error "Check hb-mutex.hh for possible resolutions."
-
#endif
struct hb_mutex_t
{
- hb_mutex_impl_t m;
-
- void init () { hb_mutex_impl_init (&m); }
- void lock () { hb_mutex_impl_lock (&m); }
- void unlock () { hb_mutex_impl_unlock (&m); }
- void fini () { hb_mutex_impl_finish (&m); }
+ /* Create space for, but do not initialize m. */
+ alignas(hb_mutex_impl_t) char m[sizeof (hb_mutex_impl_t)];
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ void init () { hb_mutex_impl_init ((hb_mutex_impl_t *) m); }
+ void lock () { hb_mutex_impl_lock ((hb_mutex_impl_t *) m); }
+ void unlock () { hb_mutex_impl_unlock ((hb_mutex_impl_t *) m); }
+ void fini () { hb_mutex_impl_finish ((hb_mutex_impl_t *) m); }
+#pragma GCC diagnostic pop
};
struct hb_lock_t
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-object.hh b/src/3rdparty/harfbuzz-ng/src/hb-object.hh
index 0e15cb12c4..4b5bc32ade 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-object.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-object.hh
@@ -53,7 +53,7 @@ struct hb_lockable_set_t
item_t *replace_or_insert (T v, lock_t &l, bool replace)
{
l.lock ();
- item_t *item = items.find (v);
+ item_t *item = items.lsearch (v);
if (item) {
if (replace) {
item_t old = *item;
@@ -76,7 +76,7 @@ struct hb_lockable_set_t
void remove (T v, lock_t &l)
{
l.lock ();
- item_t *item = items.find (v);
+ item_t *item = items.lsearch (v);
if (item)
{
item_t old = *item;
@@ -93,7 +93,7 @@ struct hb_lockable_set_t
bool find (T v, item_t *i, lock_t &l)
{
l.lock ();
- item_t *item = items.find (v);
+ item_t *item = items.lsearch (v);
if (item)
*i = *item;
l.unlock ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
index 49653ce97e..7e524177f6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
@@ -64,7 +64,7 @@ struct IntType
IntType& operator = (Type i) { v = i; return *this; }
/* For reason we define cast out operator for signed/unsigned, instead of Type, see:
* https://github.com/harfbuzz/harfbuzz/pull/2875/commits/09836013995cab2b9f07577a179ad7b024130467 */
- operator hb_conditional<hb_is_signed (Type), signed, unsigned> () const { return v; }
+ operator typename std::conditional<std::is_signed<Type>::value, signed, unsigned>::type () const { return v; }
bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; }
bool operator != (const IntType &o) const { return !(*this == o); }
@@ -86,7 +86,7 @@ struct IntType
return pb->cmp (*pa);
}
template <typename Type2,
- hb_enable_if (hb_is_integral (Type2) &&
+ hb_enable_if (std::is_integral<Type2>::value &&
sizeof (Type2) < sizeof (int) &&
sizeof (Type) < sizeof (int))>
int cmp (Type2 a) const
@@ -122,6 +122,15 @@ typedef IntType<int32_t> HBINT32; /* 32-bit signed integer. */
* Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
+/* 15-bit unsigned number; top bit used for extension. */
+struct HBUINT15 : HBUINT16
+{
+ /* TODO Flesh out; actually mask top bit. */
+ HBUINT15& operator = (uint16_t i ) { HBUINT16::operator= (i); return *this; }
+ public:
+ DEFINE_SIZE_STATIC (2);
+};
+
/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
typedef HBINT16 FWORD;
@@ -182,9 +191,9 @@ struct Tag : HBUINT32
};
/* Glyph index number, same as uint16 (length = 16 bits) */
-struct HBGlyphID : HBUINT16
+struct HBGlyphID16 : HBUINT16
{
- HBGlyphID& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
+ HBGlyphID16& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
};
/* Script/language-system/feature index */
@@ -332,7 +341,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
s->push ();
- bool ret = c->dispatch (src_base+src, hb_forward<Ts> (ds)...);
+ bool ret = c->dispatch (src_base+src, std::forward<Ts> (ds)...);
if (ret || !has_null)
s->add_link (*this, s->pop_pack ());
@@ -349,7 +358,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
*this = 0;
Type* obj = c->push<Type> ();
- bool ret = obj->serialize (c, hb_forward<Ts> (ds)...);
+ bool ret = obj->serialize (c, std::forward<Ts> (ds)...);
if (ret)
c->add_link (*this, c->pop_pack ());
@@ -375,7 +384,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
c->push ();
- bool ret = c->copy (src_base+src, hb_forward<Ts> (ds)...);
+ bool ret = c->copy (src_base+src, std::forward<Ts> (ds)...);
c->add_link (*this, c->pop_pack (), whence, dst_bias);
@@ -401,7 +410,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
TRACE_SANITIZE (this);
return_trace (sanitize_shallow (c, base) &&
(this->is_null () ||
- c->dispatch (StructAtOffset<Type> (base, *this), hb_forward<Ts> (ds)...) ||
+ c->dispatch (StructAtOffset<Type> (base, *this), std::forward<Ts> (ds)...) ||
neuter (c)));
}
@@ -509,9 +518,9 @@ struct UnsizedArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
- if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
+ if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
+ if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
return_trace (false);
return_trace (true);
}
@@ -556,7 +565,7 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_
{
TRACE_SANITIZE (this);
return_trace ((UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
- ::sanitize (c, count, this, hb_forward<Ts> (ds)...)));
+ ::sanitize (c, count, this, std::forward<Ts> (ds)...)));
}
};
@@ -698,10 +707,10 @@ struct ArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
+ if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
+ if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
return_trace (false);
return_trace (true);
}
@@ -759,7 +768,7 @@ struct List16OfOffset16To : Array16OfOffset16To<Type>
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
{
TRACE_SANITIZE (this);
- return_trace (Array16OfOffset16To<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
+ return_trace (Array16OfOffset16To<Type>::sanitize (c, this, std::forward<Ts> (ds)...));
}
};
@@ -826,10 +835,10 @@ struct HeadlessArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
+ if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
+ if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
return_trace (false);
return_trace (true);
}
@@ -875,10 +884,10 @@ struct ArrayOfM1
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
+ if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
unsigned int count = lenM1 + 1;
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
+ if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
return_trace (false);
return_trace (true);
}
@@ -1061,10 +1070,10 @@ struct VarSizedBinSearchArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
+ if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(*this)[i].sanitize (c, hb_forward<Ts> (ds)...)))
+ if (unlikely (!(*this)[i].sanitize (c, std::forward<Ts> (ds)...)))
return_trace (false);
return_trace (true);
}
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 eaaf5e12ec..c102c15173 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh
@@ -68,8 +68,6 @@ struct code_pair_t
typedef hb_vector_t<unsigned char> str_buff_t;
struct str_buff_vec_t : hb_vector_t<str_buff_t>
{
- void fini () { SUPER::fini_deep (); }
-
unsigned int total_size () const
{
unsigned int size = 0;
@@ -373,7 +371,7 @@ struct Dict : UnsizedByteStr
{
TRACE_SERIALIZE (this);
for (unsigned int i = 0; i < dictval.get_count (); i++)
- if (unlikely (!opszr.serialize (c, dictval[i], hb_forward<Ts> (ds)...)))
+ if (unlikely (!opszr.serialize (c, dictval[i], std::forward<Ts> (ds)...)))
return_trace (false);
return_trace (true);
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 3298fa35ae..df4554ac00 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
@@ -442,13 +442,12 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
return true;
}
-#ifdef HB_EXPERIMENTAL_API
struct cff1_path_param_t
{
cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
- draw_helper_t &draw_helper_, point_t *delta_)
+ hb_draw_session_t &draw_session_, point_t *delta_)
{
- draw_helper = &draw_helper_;
+ draw_session = &draw_session_;
cff = cff_;
font = font_;
delta = delta_;
@@ -458,14 +457,14 @@ struct cff1_path_param_t
{
point_t point = p;
if (delta) point.move (*delta);
- draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
+ draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
}
void line_to (const point_t &p)
{
point_t point = p;
if (delta) point.move (*delta);
- draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
+ draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
}
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
@@ -477,15 +476,15 @@ struct cff1_path_param_t
point2.move (*delta);
point3.move (*delta);
}
- draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()),
- font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()),
- font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ()));
+ draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()),
+ font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()),
+ font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ()));
}
- void end_path () { draw_helper->end_path (); }
+ void end_path () { draw_session->close_path (); }
hb_font_t *font;
- draw_helper_t *draw_helper;
+ hb_draw_session_t *draw_session;
point_t *delta;
const OT::cff1::accelerator_t *cff;
@@ -513,7 +512,7 @@ struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_int
};
static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
- draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr);
+ hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr);
struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
{
@@ -530,14 +529,14 @@ struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_pa
hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
if (unlikely (!(!env.in_seac && base && accent
- && _get_path (param.cff, param.font, base, *param.draw_helper, true)
- && _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta))))
+ && _get_path (param.cff, param.font, base, *param.draw_session, true)
+ && _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta))))
env.set_error ();
}
};
bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
- draw_helper_t &draw_helper, bool in_seac, point_t *delta)
+ hb_draw_session_t &draw_session, bool in_seac, point_t *delta)
{
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
@@ -546,7 +545,7 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
const byte_str_t str = (*cff->charStrings)[glyph];
interp.env.init (str, *cff, fd);
interp.env.set_in_seac (in_seac);
- cff1_path_param_t param (cff, font, draw_helper, delta);
+ cff1_path_param_t param (cff, font, draw_session, delta);
if (unlikely (!interp.interpret (param))) return false;
/* Let's end the path specially since it is called inside seac also */
@@ -555,16 +554,15 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
return true;
}
-bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
+bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
return true;
#endif
- return _get_path (this, font, glyph, draw_helper);
+ return _get_path (this, font, glyph, draw_session);
}
-#endif
struct get_seac_param_t
{
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 5dd183e3a0..542e3f4de3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh
@@ -1144,8 +1144,8 @@ struct cff1
{
sc.end_processing ();
topDict.fini ();
- fontDicts.fini_deep ();
- privateDicts.fini_deep ();
+ fontDicts.fini ();
+ privateDicts.fini ();
hb_blob_destroy (blob);
blob = nullptr;
}
@@ -1245,32 +1245,32 @@ struct cff1
}
protected:
- hb_blob_t *blob;
+ hb_blob_t *blob = nullptr;
hb_sanitize_context_t sc;
public:
- const Encoding *encoding;
- const Charset *charset;
- const CFF1NameIndex *nameIndex;
- const CFF1TopDictIndex *topDictIndex;
- const CFF1StringIndex *stringIndex;
- const CFF1Subrs *globalSubrs;
- const CFF1CharStrings *charStrings;
- const CFF1FDArray *fdArray;
- const CFF1FDSelect *fdSelect;
- unsigned int fdCount;
+ const Encoding *encoding = nullptr;
+ const Charset *charset = nullptr;
+ const CFF1NameIndex *nameIndex = nullptr;
+ const CFF1TopDictIndex *topDictIndex = nullptr;
+ const CFF1StringIndex *stringIndex = nullptr;
+ const CFF1Subrs *globalSubrs = nullptr;
+ const CFF1CharStrings *charStrings = nullptr;
+ const CFF1FDArray *fdArray = nullptr;
+ const CFF1FDSelect *fdSelect = nullptr;
+ unsigned int fdCount = 0;
cff1_top_dict_values_t topDict;
hb_vector_t<cff1_font_dict_values_t>
fontDicts;
hb_vector_t<PRIVDICTVAL> privateDicts;
- unsigned int num_glyphs;
+ unsigned int num_glyphs = 0;
};
struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{
SUPER::init (face);
@@ -1295,8 +1295,7 @@ struct cff1
}
glyph_names.qsort ();
}
-
- void fini ()
+ ~accelerator_t ()
{
glyph_names.fini ();
@@ -1348,9 +1347,7 @@ struct cff1
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
-#ifdef HB_EXPERIMENTAL_API
- HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
-#endif
+ HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
private:
struct gname_t
@@ -1398,7 +1395,10 @@ struct cff1
DEFINE_SIZE_STATIC (4);
};
-struct cff1_accelerator_t : cff1::accelerator_t {};
+struct cff1_accelerator_t : cff1::accelerator_t {
+ cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
+};
+
} /* namespace OT */
#endif /* HB_OT_CFF1_TABLE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc
index 879b7cdb23..817fe064ce 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc
@@ -143,30 +143,29 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
return true;
}
-#ifdef HB_EXPERIMENTAL_API
struct cff2_path_param_t
{
- cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_)
+ cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
{
- draw_helper = &draw_helper_;
+ draw_session = &draw_session_;
font = font_;
}
void move_to (const point_t &p)
- { draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
+ { draw_session->move_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
void line_to (const point_t &p)
- { draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
+ { draw_session->line_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
{
- draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()),
- font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()),
- font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ()));
+ draw_session->cubic_to (font->em_fscalef_x (p1.x.to_real ()), font->em_fscalef_y (p1.y.to_real ()),
+ font->em_fscalef_x (p2.x.to_real ()), font->em_fscalef_y (p2.y.to_real ()),
+ font->em_fscalef_x (p3.x.to_real ()), font->em_fscalef_y (p3.y.to_real ()));
}
protected:
- draw_helper_t *draw_helper;
+ hb_draw_session_t *draw_session;
hb_font_t *font;
};
@@ -193,7 +192,7 @@ struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_int
struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
-bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
+bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
@@ -206,10 +205,9 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, d
cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
const byte_str_t str = (*charStrings)[glyph];
interp.env.init (str, *this, fd, font->coords, font->num_coords);
- cff2_path_param_t param (font, draw_helper);
+ cff2_path_param_t param (font, draw_session);
if (unlikely (!interp.interpret (param))) return false;
return true;
}
-#endif
#endif
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 829217feaa..b77e7f53fa 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh
@@ -397,7 +397,7 @@ struct cff2
template <typename PRIVOPSET, typename PRIVDICTVAL>
struct accelerator_templ_t
{
- void init (hb_face_t *face)
+ accelerator_templ_t (hb_face_t *face)
{
topDict.init ();
fontDicts.init ();
@@ -412,15 +412,15 @@ struct cff2
const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
if (cff2 == &Null (OT::cff2))
- { fini (); return; }
+ goto fail;
{ /* parse top dict */
byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize);
- if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
+ if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
cff2_top_dict_interpreter_t top_interp;
top_interp.env.init (topDictStr);
topDict.init ();
- if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
+ if (unlikely (!top_interp.interpret (topDict))) goto fail;
}
globalSubrs = &StructAtOffset<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize);
@@ -434,49 +434,55 @@ struct cff2
(globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
(fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
(((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
- { fini (); return; }
+ goto fail;
num_glyphs = charStrings->count;
if (num_glyphs != sc.get_num_glyphs ())
- { fini (); return; }
+ goto fail;
fdCount = fdArray->count;
if (!privateDicts.resize (fdCount))
- { fini (); return; }
+ goto fail;
/* parse font dicts and gather private dicts */
for (unsigned int i = 0; i < fdCount; i++)
{
const byte_str_t fontDictStr = (*fdArray)[i];
- if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
+ if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
cff2_font_dict_values_t *font;
cff2_font_dict_interpreter_t font_interp;
font_interp.env.init (fontDictStr);
font = fontDicts.push ();
- if (unlikely (font == &Crap (cff2_font_dict_values_t))) { fini (); return; }
+ if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail;
font->init ();
- if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
+ if (unlikely (!font_interp.interpret (*font))) goto fail;
const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
- if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+ if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp;
priv_interp.env.init(privDictStr);
privateDicts[i].init ();
- if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; }
+ if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset);
if (privateDicts[i].localSubrs != &Null (CFF2Subrs) &&
unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
- { fini (); return; }
+ goto fail;
}
- }
- void fini ()
+
+ return;
+
+ fail:
+ _fini ();
+ }
+ ~accelerator_templ_t () { _fini (); }
+ void _fini ()
{
sc.end_processing ();
topDict.fini ();
- fontDicts.fini_deep ();
- privateDicts.fini_deep ();
+ fontDicts.fini ();
+ privateDicts.fini ();
hb_blob_destroy (blob);
blob = nullptr;
}
@@ -484,32 +490,32 @@ struct cff2
bool is_valid () const { return blob; }
protected:
- hb_blob_t *blob;
+ hb_blob_t *blob = nullptr;
hb_sanitize_context_t sc;
public:
cff2_top_dict_values_t topDict;
- const CFF2Subrs *globalSubrs;
- const CFF2VariationStore *varStore;
- const CFF2CharStrings *charStrings;
- const CFF2FDArray *fdArray;
- const CFF2FDSelect *fdSelect;
- unsigned int fdCount;
+ const CFF2Subrs *globalSubrs = nullptr;
+ const CFF2VariationStore *varStore = nullptr;
+ const CFF2CharStrings *charStrings = nullptr;
+ const CFF2FDArray *fdArray = nullptr;
+ const CFF2FDSelect *fdSelect = nullptr;
+ unsigned int fdCount = 0;
hb_vector_t<cff2_font_dict_values_t> fontDicts;
hb_vector_t<PRIVDICTVAL> privateDicts;
- unsigned int num_glyphs;
+ unsigned int num_glyphs = 0;
};
struct accelerator_t : accelerator_templ_t<cff2_private_dict_opset_t, cff2_private_dict_values_t>
{
+ accelerator_t (hb_face_t *face) : accelerator_templ_t (face) {}
+
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
-#ifdef HB_EXPERIMENTAL_API
- HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
-#endif
+ 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;
@@ -525,7 +531,10 @@ struct cff2
DEFINE_SIZE_STATIC (5);
};
-struct cff2_accelerator_t : cff2::accelerator_t {};
+struct cff2_accelerator_t : cff2::accelerator_t {
+ cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_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 b904bb46a8..a8747ee5a1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
@@ -93,120 +93,192 @@ struct CmapSubtableFormat0
struct CmapSubtableFormat4
{
+
template<typename Iterator,
+ typename Writer,
hb_requires (hb_is_iterator (Iterator))>
- HBUINT16* serialize_endcode_array (hb_serialize_context_t *c,
- Iterator it)
- {
- HBUINT16 *endCode = c->start_embed<HBUINT16> ();
- hb_codepoint_t prev_endcp = 0xFFFF;
+ void to_ranges (Iterator it, Writer& range_writer)
+ {
+ hb_codepoint_t start_cp = 0, prev_run_start_cp = 0, run_start_cp = 0, end_cp = 0, last_gid = 0;
+ int run_length = 0 , delta = 0, prev_delta = 0;
+
+ enum {
+ FIRST_SUB_RANGE,
+ FOLLOWING_SUB_RANGE,
+ } mode;
+
+ while (it) {
+ // Start a new range
+ start_cp = (*it).first;
+ prev_run_start_cp = (*it).first;
+ run_start_cp = (*it).first;
+ end_cp = (*it).first;
+ last_gid = (*it).second;
+ run_length = 1;
+ prev_delta = 0;
+
+ delta = (*it).second - (*it).first;
+ mode = FIRST_SUB_RANGE;
+ it++;
+
+ while (it) {
+ // Process range
+ hb_codepoint_t next_cp = (*it).first;
+ hb_codepoint_t next_gid = (*it).second;
+ if (next_cp != end_cp + 1) {
+ // Current range is over, stop processing.
+ break;
+ }
- for (const auto& _ : +it)
- {
- if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
- {
- HBUINT16 end_code;
- end_code = prev_endcp;
- c->copy<HBUINT16> (end_code);
- }
- prev_endcp = _.first;
- }
+ if (next_gid == last_gid + 1) {
+ // The current run continues.
+ end_cp = next_cp;
+ run_length++;
+ last_gid = next_gid;
+ it++;
+ continue;
+ }
- {
- // last endCode
- HBUINT16 endcode;
- endcode = prev_endcp;
- if (unlikely (!c->copy<HBUINT16> (endcode))) return nullptr;
- // There must be a final entry with end_code == 0xFFFF.
- if (prev_endcp != 0xFFFF)
- {
- HBUINT16 finalcode;
- finalcode = 0xFFFF;
- if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr;
+ // A new run is starting, decide if we want to commit the current run.
+ int split_cost = (mode == FIRST_SUB_RANGE) ? 8 : 16;
+ int run_cost = run_length * 2;
+ if (run_cost >= split_cost) {
+ commit_current_range(start_cp,
+ prev_run_start_cp,
+ run_start_cp,
+ end_cp,
+ delta,
+ prev_delta,
+ split_cost,
+ range_writer);
+ start_cp = next_cp;
+ }
+
+ // Start the new run
+ mode = FOLLOWING_SUB_RANGE;
+ prev_run_start_cp = run_start_cp;
+ run_start_cp = next_cp;
+ end_cp = next_cp;
+ prev_delta = delta;
+ delta = next_gid - run_start_cp;
+ run_length = 1;
+ last_gid = next_gid;
+ it++;
}
+
+ // Finalize range
+ commit_current_range (start_cp,
+ prev_run_start_cp,
+ run_start_cp,
+ end_cp,
+ delta,
+ prev_delta,
+ 8,
+ range_writer);
}
- return endCode;
+ if (likely (end_cp != 0xFFFF)) {
+ range_writer (0xFFFF, 0xFFFF, 1);
+ }
}
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- HBUINT16* serialize_startcode_array (hb_serialize_context_t *c,
- Iterator it)
- {
- HBUINT16 *startCode = c->start_embed<HBUINT16> ();
- hb_codepoint_t prev_cp = 0xFFFF;
-
- for (const auto& _ : +it)
- {
- if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
- {
- HBUINT16 start_code;
- start_code = _.first;
- c->copy<HBUINT16> (start_code);
+ /*
+ * Writes the current range as either one or two ranges depending on what is most efficient.
+ */
+ template<typename Writer>
+ void commit_current_range (hb_codepoint_t start,
+ hb_codepoint_t prev_run_start,
+ hb_codepoint_t run_start,
+ hb_codepoint_t end,
+ int run_delta,
+ int previous_run_delta,
+ int split_cost,
+ Writer& range_writer) {
+ bool should_split = false;
+ if (start < run_start && run_start < end) {
+ int run_cost = (end - run_start + 1) * 2;
+ if (run_cost >= split_cost) {
+ should_split = true;
}
+ }
- prev_cp = _.first;
+ // TODO(grieger): handle case where delta is legitimately 0, mark range offset array instead?
+ if (should_split) {
+ if (start == prev_run_start)
+ range_writer (start, run_start - 1, previous_run_delta);
+ else
+ range_writer (start, run_start - 1, 0);
+ range_writer (run_start, end, run_delta);
+ return;
}
- // There must be a final entry with end_code == 0xFFFF.
- if (it.len () == 0 || prev_cp != 0xFFFF)
- {
- HBUINT16 finalcode;
- finalcode = 0xFFFF;
- if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr;
+
+ if (start == run_start) {
+ // Range is only a run
+ range_writer (start, end, run_delta);
+ return;
}
- return startCode;
+ // Write only a single non-run range.
+ range_writer (start, end, 0);
}
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
- HBINT16* serialize_idDelta_array (hb_serialize_context_t *c,
- Iterator it,
- HBUINT16 *endCode,
- HBUINT16 *startCode,
- unsigned segcount)
- {
- unsigned i = 0;
- hb_codepoint_t last_gid = 0, start_gid = 0, last_cp = 0xFFFF;
- bool use_delta = true;
-
- HBINT16 *idDelta = c->start_embed<HBINT16> ();
- if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size)
- return nullptr;
-
- for (const auto& _ : +it)
- {
- if (_.first == startCode[i])
- {
- use_delta = true;
- start_gid = _.second;
+ unsigned serialize_find_segcount (Iterator it) {
+ struct Counter {
+ unsigned segcount = 0;
+
+ void operator() (hb_codepoint_t start,
+ hb_codepoint_t end,
+ int delta) {
+ segcount++;
}
- else if (_.second != last_gid + 1) use_delta = false;
+ } counter;
+
+ to_ranges (+it, counter);
+ return counter.segcount;
+ }
- if (_.first == endCode[i])
- {
- HBINT16 delta;
- if (use_delta) delta = (int)start_gid - (int)startCode[i];
- else delta = 0;
- c->copy<HBINT16> (delta);
- i++;
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool serialize_start_end_delta_arrays (hb_serialize_context_t *c,
+ Iterator it,
+ int segcount)
+ {
+ struct Writer {
+ hb_serialize_context_t *serializer_;
+ HBUINT16* end_code_;
+ HBUINT16* start_code_;
+ HBINT16* id_delta_;
+ int index_;
+
+ Writer(hb_serialize_context_t *serializer)
+ : serializer_(serializer),
+ end_code_(nullptr),
+ start_code_(nullptr),
+ id_delta_(nullptr),
+ index_ (0) {}
+ void operator() (hb_codepoint_t start,
+ hb_codepoint_t end,
+ int delta) {
+ start_code_[index_] = start;
+ end_code_[index_] = end;
+ id_delta_[index_] = delta;
+ index_++;
}
+ } writer(c);
- last_gid = _.second;
- last_cp = _.first;
- }
+ writer.end_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
+ c->allocate_size<HBUINT16> (2); // padding
+ writer.start_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
+ writer.id_delta_ = c->allocate_size<HBINT16> (HBINT16::static_size * segcount);
- if (it.len () == 0 || last_cp != 0xFFFF)
- {
- HBINT16 delta;
- delta = 1;
- if (unlikely (!c->copy<HBINT16> (delta))) return nullptr;
- }
+ if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false;
- return idDelta;
+ to_ranges (+it, writer);
+ return true;
}
template<typename Iterator,
@@ -257,22 +329,14 @@ struct CmapSubtableFormat4
if (unlikely (!c->extend_min (this))) return;
this->format = 4;
- //serialize endCode[]
- HBUINT16 *endCode = serialize_endcode_array (c, format4_iter);
- if (unlikely (!endCode)) return;
-
- unsigned segcount = (c->length () - min_size) / HBUINT16::static_size;
-
- // 2 bytes of padding.
- if (unlikely (!c->allocate_size<HBUINT16> (HBUINT16::static_size))) return; // 2 bytes of padding.
-
- // serialize startCode[]
- HBUINT16 *startCode = serialize_startcode_array (c, format4_iter);
- if (unlikely (!startCode)) return;
+ //serialize endCode[], startCode[], idDelta[]
+ HBUINT16* endCode = c->start_embed<HBUINT16> ();
+ unsigned segcount = serialize_find_segcount (format4_iter);
+ if (unlikely (!serialize_start_end_delta_arrays (c, format4_iter, segcount)))
+ return;
- //serialize idDelta[]
- HBINT16 *idDelta = serialize_idDelta_array (c, format4_iter, endCode, startCode, segcount);
- if (unlikely (!idDelta)) return;
+ HBUINT16 *startCode = endCode + segcount + 1;
+ HBINT16 *idDelta = ((HBINT16*)startCode) + segcount;
HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
if (unlikely (!c->check_success (idRangeOffset))) return;
@@ -305,7 +369,6 @@ struct CmapSubtableFormat4
{
accelerator_t () {}
accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); }
- ~accelerator_t () { fini (); }
void init (const CmapSubtableFormat4 *subtable)
{
@@ -317,7 +380,6 @@ struct CmapSubtableFormat4
glyphIdArray = idRangeOffset + segCount;
glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
}
- void fini () {}
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
@@ -604,7 +666,7 @@ struct CmapSubtableTrimmed
UINT length; /* Byte length of this subtable. */
UINT language; /* Ignore. */
UINT startCharCode; /* First character code covered. */
- ArrayOf<HBGlyphID, UINT>
+ ArrayOf<HBGlyphID16, UINT>
glyphIdArray; /* Array of glyph index values for character
* codes in the range. */
public:
@@ -652,7 +714,7 @@ struct CmapSubtableLongSegmented
if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
end = start + (hb_codepoint_t) num_glyphs - gid;
- out->add_range (start, end);
+ out->add_range (start, hb_min (end, 0x10FFFFu));
}
}
@@ -821,7 +883,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
hb_codepoint_t first = arrayZ[i].startUnicodeValue;
hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
(hb_codepoint_t) HB_UNICODE_MAX);
- out->add_range (first, last);
+ out->add_range (first, hb_min (last, 0x10FFFFu));
}
}
@@ -900,7 +962,7 @@ struct UVSMapping
}
HBUINT24 unicodeValue; /* Base Unicode value of the UVS */
- HBGlyphID glyphID; /* Glyph ID of the UVS */
+ HBGlyphID16 glyphID; /* Glyph ID of the UVS */
public:
DEFINE_SIZE_STATIC (5);
};
@@ -1543,7 +1605,7 @@ struct cmap
unsigned format = (this + _.subtable).u.format;
if (format == 12) has_format12 = true;
- const EncodingRecord *table = hb_addressof (_);
+ const EncodingRecord *table = std::addressof (_);
if (_.platformID == 0 && _.encodingID == 3) unicode_bmp = table;
else if (_.platformID == 0 && _.encodingID == 4) unicode_ucs4 = table;
else if (_.platformID == 3 && _.encodingID == 1) ms_bmp = table;
@@ -1601,7 +1663,7 @@ struct cmap
struct accelerator_t
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{
this->table = hb_sanitize_context_t ().reference_table<cmap> (face);
bool symbol;
@@ -1636,8 +1698,7 @@ struct cmap
}
}
}
-
- void fini () { this->table.destroy (); }
+ ~accelerator_t () { this->table.destroy (); }
bool get_nominal_glyph (hb_codepoint_t unicode,
hb_codepoint_t *glyph) const
@@ -1799,7 +1860,9 @@ struct cmap
DEFINE_SIZE_ARRAY (4, encodingRecord);
};
-struct cmap_accelerator_t : cmap::accelerator_t {};
+struct cmap_accelerator_t : cmap::accelerator_t {
+ cmap_accelerator_t (hb_face_t *face) : cmap::accelerator_t (face) {}
+};
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh
index 6c31d1b53e..23fa56c4f6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh
@@ -360,6 +360,16 @@ struct IndexSubtable
struct IndexSubtableRecord
{
+ /* XXX Remove this and fix by not inserting it into vector. */
+ IndexSubtableRecord& operator = (const IndexSubtableRecord &o)
+ {
+ firstGlyphIndex = o.firstGlyphIndex;
+ lastGlyphIndex = o.lastGlyphIndex;
+ offsetToSubtable = (unsigned) o.offsetToSubtable;
+ assert (offsetToSubtable.is_null ());
+ return *this;
+ }
+
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -508,8 +518,8 @@ struct IndexSubtableRecord
offset, length, format);
}
- HBGlyphID firstGlyphIndex;
- HBGlyphID lastGlyphIndex;
+ HBGlyphID16 firstGlyphIndex;
+ HBGlyphID16 lastGlyphIndex;
Offset32To<IndexSubtable> offsetToSubtable;
public:
DEFINE_SIZE_STATIC (8);
@@ -679,8 +689,8 @@ struct BitmapSizeTable
HBUINT32 colorRef;
SBitLineMetrics horizontal;
SBitLineMetrics vertical;
- HBGlyphID startGlyphIndex;
- HBGlyphID endGlyphIndex;
+ HBGlyphID16 startGlyphIndex;
+ HBGlyphID16 endGlyphIndex;
HBUINT8 ppemX;
HBUINT8 ppemY;
HBUINT8 bitDepth;
@@ -809,15 +819,14 @@ struct CBDT
struct accelerator_t
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{
- cblc = hb_sanitize_context_t ().reference_table<CBLC> (face);
- cbdt = hb_sanitize_context_t ().reference_table<CBDT> (face);
+ this->cblc = hb_sanitize_context_t ().reference_table<CBLC> (face);
+ this->cbdt = hb_sanitize_context_t ().reference_table<CBDT> (face);
upem = hb_face_get_upem (face);
}
-
- void fini ()
+ ~accelerator_t ()
{
this->cblc.destroy ();
this->cbdt.destroy ();
@@ -978,7 +987,10 @@ CBLC::subset (hb_subset_context_t *c) const
return_trace (CBLC::sink_cbdt (c, &cbdt_prime));
}
-struct CBDT_accelerator_t : CBDT::accelerator_t {};
+struct CBDT_accelerator_t : CBDT::accelerator_t {
+ CBDT_accelerator_t (hb_face_t *face) : CBDT::accelerator_t (face) {}
+};
+
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colr-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colr-table.hh
index 007ff3f47b..dac755c02c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colr-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colr-table.hh
@@ -30,6 +30,7 @@
#include "hb-open-type.hh"
#include "hb-ot-layout-common.hh"
+#include "hb-ot-var-common.hh"
/*
* COLR -- Color
@@ -37,12 +38,12 @@
*/
#define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
-#ifndef COLRV1_MAX_NESTING_LEVEL
-#define COLRV1_MAX_NESTING_LEVEL 100
+#ifndef HB_COLRV1_MAX_NESTING_LEVEL
+#define HB_COLRV1_MAX_NESTING_LEVEL 100
#endif
#ifndef COLRV1_ENABLE_SUBSETTING
-#define COLRV1_ENABLE_SUBSETTING 0
+#define COLRV1_ENABLE_SUBSETTING 1
#endif
namespace OT {
@@ -70,7 +71,7 @@ struct hb_colrv1_closure_context_t :
bool paint_visited (const void *paint)
{
hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) paint - (uintptr_t) base);
- if (visited_paint.has (delta))
+ if (visited_paint.in_error() || visited_paint.has (delta))
return true;
visited_paint.add (delta);
@@ -101,7 +102,7 @@ struct hb_colrv1_closure_context_t :
hb_set_t *glyphs_,
hb_set_t *layer_indices_,
hb_set_t *palette_indices_,
- unsigned nesting_level_left_ = COLRV1_MAX_NESTING_LEVEL) :
+ unsigned nesting_level_left_ = HB_COLRV1_MAX_NESTING_LEVEL) :
base (base_),
glyphs (glyphs_),
layer_indices (layer_indices_),
@@ -121,7 +122,7 @@ struct LayerRecord
}
public:
- HBGlyphID glyphId; /* Glyph ID of layer glyph */
+ HBGlyphID16 glyphId; /* Glyph ID of layer glyph */
Index colorIdx; /* Index value to use with a
* selected color palette.
* An index value of 0xFFFF
@@ -148,7 +149,7 @@ struct BaseGlyphRecord
}
public:
- HBGlyphID glyphId; /* Glyph ID of reference glyph */
+ HBGlyphID16 glyphId; /* Glyph ID of reference glyph */
HBUINT16 firstLayerIdx; /* Index (from beginning of
* the Layer Records) to the
* layer record. There will be
@@ -163,15 +164,31 @@ struct BaseGlyphRecord
template <typename T>
struct Variable
{
+ Variable<T>* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed (this));
+ }
+
+ void closurev1 (hb_colrv1_closure_context_t* c) const
+ { value.closurev1 (c); }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ if (!value.subset (c)) return_trace (false);
+ return_trace (c->serializer->embed (varIdxBase));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
+ return_trace (c->check_struct (this) && value.sanitize (c));
}
protected:
T value;
- VarIdx varIdx;
+ VarIdx varIdxBase;
public:
DEFINE_SIZE_STATIC (4 + T::static_size);
};
@@ -179,51 +196,46 @@ struct Variable
template <typename T>
struct NoVariable
{
- bool sanitize (hb_sanitize_context_t *c) const
+ NoVariable<T>* copy (hb_serialize_context_t *c) const
{
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed (this));
}
- T value;
- public:
- DEFINE_SIZE_STATIC (T::static_size);
-};
-
-// Color structures
+ void closurev1 (hb_colrv1_closure_context_t* c) const
+ { value.closurev1 (c); }
-template <template<typename> class Var>
-struct ColorIndex
-{
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- auto *out = c->serializer->embed (*this);
- if (unlikely (!out)) return_trace (false);
- return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex),
- HB_SERIALIZE_ERROR_INT_OVERFLOW));
+ return_trace (value.subset (c));
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
+ return_trace (c->check_struct (this) && value.sanitize (c));
}
- HBUINT16 paletteIndex;
- Var<F2DOT14> alpha;
+ T value;
public:
- DEFINE_SIZE_STATIC (2 + Var<F2DOT14>::static_size);
+ DEFINE_SIZE_STATIC (T::static_size);
};
-template <template<typename> class Var>
+// Color structures
+
struct ColorStop
{
+ void closurev1 (hb_colrv1_closure_context_t* c) const
+ { c->add_palette_index (paletteIndex); }
+
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- if (unlikely (!c->serializer->embed (stopOffset))) return_trace (false);
- return_trace (color.subset (c));
+ auto *out = c->serializer->embed (*this);
+ if (unlikely (!out)) return_trace (false);
+ return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex),
+ HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -232,10 +244,11 @@ struct ColorStop
return_trace (c->check_struct (this));
}
- Var<F2DOT14> stopOffset;
- ColorIndex<Var> color;
+ F2DOT14 stopOffset;
+ HBUINT16 paletteIndex;
+ F2DOT14 alpha;
public:
- DEFINE_SIZE_STATIC (Var<F2DOT14>::static_size + ColorIndex<Var>::static_size);
+ DEFINE_SIZE_STATIC (2 + 2 * F2DOT14::static_size);
};
struct Extend : HBUINT8
@@ -252,6 +265,12 @@ struct Extend : HBUINT8
template <template<typename> class Var>
struct ColorLine
{
+ void closurev1 (hb_colrv1_closure_context_t* c) const
+ {
+ for (const auto &stop : stops.iter ())
+ stop.closurev1 (c);
+ }
+
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
@@ -276,8 +295,8 @@ struct ColorLine
stops.sanitize (c));
}
- Extend extend;
- Array16Of<ColorStop<Var>> stops;
+ Extend extend;
+ Array16Of<Var<ColorStop>> stops;
public:
DEFINE_SIZE_ARRAY_SIZED (3, stops);
};
@@ -331,7 +350,6 @@ struct CompositeMode : HBUINT8
DEFINE_SIZE_STATIC (1);
};
-template <template<typename> class Var>
struct Affine2x3
{
bool sanitize (hb_sanitize_context_t *c) const
@@ -340,14 +358,14 @@ struct Affine2x3
return_trace (c->check_struct (this));
}
- Var<HBFixed> xx;
- Var<HBFixed> yx;
- Var<HBFixed> xy;
- Var<HBFixed> yy;
- Var<HBFixed> dx;
- Var<HBFixed> dy;
+ HBFixed xx;
+ HBFixed yx;
+ HBFixed xy;
+ HBFixed yy;
+ HBFixed dx;
+ HBFixed dy;
public:
- DEFINE_SIZE_STATIC (6 * Var<HBFixed>::static_size);
+ DEFINE_SIZE_STATIC (6 * HBFixed::static_size);
};
struct PaintColrLayers
@@ -373,22 +391,23 @@ struct PaintColrLayers
HBUINT8 format; /* format = 1 */
HBUINT8 numLayers;
- HBUINT32 firstLayerIndex; /* index into COLRv1::layersV1 */
+ HBUINT32 firstLayerIndex; /* index into COLRv1::layerList */
public:
DEFINE_SIZE_STATIC (6);
};
-template <template<typename> class Var>
struct PaintSolid
{
void closurev1 (hb_colrv1_closure_context_t* c) const
- { c->add_palette_index (color.paletteIndex); }
+ { c->add_palette_index (paletteIndex); }
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- if (unlikely (!c->serializer->embed (format))) return_trace (false);
- return_trace (color.subset (c));
+ auto *out = c->serializer->embed (*this);
+ if (unlikely (!out)) return_trace (false);
+ return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex),
+ HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -397,20 +416,18 @@ struct PaintSolid
return_trace (c->check_struct (this));
}
- HBUINT8 format; /* format = 2(noVar) or 3(Var)*/
- ColorIndex<Var> color;
+ HBUINT8 format; /* format = 2(noVar) or 3(Var)*/
+ HBUINT16 paletteIndex;
+ F2DOT14 alpha;
public:
- DEFINE_SIZE_STATIC (1 + ColorIndex<Var>::static_size);
+ DEFINE_SIZE_STATIC (3 + F2DOT14::static_size);
};
template <template<typename> class Var>
struct PaintLinearGradient
{
void closurev1 (hb_colrv1_closure_context_t* c) const
- {
- for (const auto &stop : (this+colorLine).stops.iter ())
- c->add_palette_index (stop.color.paletteIndex);
- }
+ { (this+colorLine).closurev1 (c); }
bool subset (hb_subset_context_t *c) const
{
@@ -430,19 +447,22 @@ struct PaintLinearGradient
HBUINT8 format; /* format = 4(noVar) or 5 (Var) */
Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintLinearGradient
* table) to ColorLine subtable. */
- Var<FWORD> x0;
- Var<FWORD> y0;
- Var<FWORD> x1;
- Var<FWORD> y1;
- Var<FWORD> x2;
- Var<FWORD> y2;
+ FWORD x0;
+ FWORD y0;
+ FWORD x1;
+ FWORD y1;
+ FWORD x2;
+ FWORD y2;
public:
- DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
+ DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size);
};
template <template<typename> class Var>
struct PaintRadialGradient
{
+ void closurev1 (hb_colrv1_closure_context_t* c) const
+ { (this+colorLine).closurev1 (c); }
+
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
@@ -452,12 +472,6 @@ struct PaintRadialGradient
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
}
- void closurev1 (hb_colrv1_closure_context_t* c) const
- {
- for (const auto &stop : (this+colorLine).stops.iter ())
- c->add_palette_index (stop.color.paletteIndex);
- }
-
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -467,19 +481,22 @@ struct PaintRadialGradient
HBUINT8 format; /* format = 6(noVar) or 7 (Var) */
Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintRadialGradient
* table) to ColorLine subtable. */
- Var<FWORD> x0;
- Var<FWORD> y0;
- Var<UFWORD> radius0;
- Var<FWORD> x1;
- Var<FWORD> y1;
- Var<UFWORD> radius1;
+ FWORD x0;
+ FWORD y0;
+ UFWORD radius0;
+ FWORD x1;
+ FWORD y1;
+ UFWORD radius1;
public:
- DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
+ DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size);
};
template <template<typename> class Var>
struct PaintSweepGradient
{
+ void closurev1 (hb_colrv1_closure_context_t* c) const
+ { (this+colorLine).closurev1 (c); }
+
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
@@ -489,12 +506,6 @@ struct PaintSweepGradient
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
}
- void closurev1 (hb_colrv1_closure_context_t* c) const
- {
- for (const auto &stop : (this+colorLine).stops.iter ())
- c->add_palette_index (stop.color.paletteIndex);
- }
-
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -504,12 +515,12 @@ struct PaintSweepGradient
HBUINT8 format; /* format = 8(noVar) or 9 (Var) */
Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintSweepGradient
* table) to ColorLine subtable. */
- Var<FWORD> centerX;
- Var<FWORD> centerY;
- Var<HBFixed> startAngle;
- Var<HBFixed> endAngle;
+ FWORD centerX;
+ FWORD centerY;
+ F2DOT14 startAngle;
+ F2DOT14 endAngle;
public:
- DEFINE_SIZE_STATIC (2 * Var<FWORD>::static_size + 2 * Var<HBFixed>::static_size);
+ DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size + 2 * F2DOT14::static_size);
};
struct Paint;
@@ -580,24 +591,25 @@ struct PaintTransform
TRACE_SUBSET (this);
auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (false);
-
+ if (!out->transform.serialize_copy (c->serializer, transform, this)) return_trace (false);
return_trace (out->src.serialize_subset (c, src, this));
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && src.sanitize (c, this));
+ return_trace (c->check_struct (this) &&
+ src.sanitize (c, this) &&
+ transform.sanitize (c, this));
}
- HBUINT8 format; /* format = 12(noVar) or 13 (Var) */
- Offset24To<Paint> src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */
- Affine2x3<Var> transform;
+ HBUINT8 format; /* format = 12(noVar) or 13 (Var) */
+ Offset24To<Paint> src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */
+ Offset24To<Var<Affine2x3>> transform;
public:
- DEFINE_SIZE_STATIC (4 + Affine2x3<Var>::static_size);
+ DEFINE_SIZE_STATIC (7);
};
-template <template<typename> class Var>
struct PaintTranslate
{
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
@@ -619,14 +631,13 @@ struct PaintTranslate
HBUINT8 format; /* format = 14(noVar) or 15 (Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */
- Var<HBFixed> dx;
- Var<HBFixed> dy;
+ FWORD dx;
+ FWORD dy;
public:
- DEFINE_SIZE_STATIC (4 + Var<HBFixed>::static_size);
+ DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size);
};
-template <template<typename> class Var>
-struct PaintRotate
+struct PaintScale
{
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
@@ -646,15 +657,150 @@ struct PaintRotate
}
HBUINT8 format; /* format = 16 (noVar) or 17(Var) */
+ Offset24To<Paint> src; /* Offset (from beginning of PaintScale table) to Paint subtable. */
+ F2DOT14 scaleX;
+ F2DOT14 scaleY;
+ public:
+ DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size);
+};
+
+struct PaintScaleAroundCenter
+{
+ HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ return_trace (out->src.serialize_subset (c, src, this));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && src.sanitize (c, this));
+ }
+
+ HBUINT8 format; /* format = 18 (noVar) or 19(Var) */
+ Offset24To<Paint> src; /* Offset (from beginning of PaintScaleAroundCenter table) to Paint subtable. */
+ F2DOT14 scaleX;
+ F2DOT14 scaleY;
+ FWORD centerX;
+ FWORD centerY;
+ public:
+ DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size);
+};
+
+struct PaintScaleUniform
+{
+ HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ return_trace (out->src.serialize_subset (c, src, this));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && src.sanitize (c, this));
+ }
+
+ HBUINT8 format; /* format = 20 (noVar) or 21(Var) */
+ Offset24To<Paint> src; /* Offset (from beginning of PaintScaleUniform table) to Paint subtable. */
+ F2DOT14 scale;
+ public:
+ DEFINE_SIZE_STATIC (4 + F2DOT14::static_size);
+};
+
+struct PaintScaleUniformAroundCenter
+{
+ HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ return_trace (out->src.serialize_subset (c, src, this));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && src.sanitize (c, this));
+ }
+
+ HBUINT8 format; /* format = 22 (noVar) or 23(Var) */
+ Offset24To<Paint> src; /* Offset (from beginning of PaintScaleUniformAroundCenter table) to Paint subtable. */
+ F2DOT14 scale;
+ FWORD centerX;
+ FWORD centerY;
+ public:
+ DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size);
+};
+
+struct PaintRotate
+{
+ HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ return_trace (out->src.serialize_subset (c, src, this));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && src.sanitize (c, this));
+ }
+
+ HBUINT8 format; /* format = 24 (noVar) or 25(Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */
- Var<HBFixed> angle;
- Var<HBFixed> centerX;
- Var<HBFixed> centerY;
+ F2DOT14 angle;
public:
- DEFINE_SIZE_STATIC (4 + 3 * Var<HBFixed>::static_size);
+ DEFINE_SIZE_STATIC (4 + F2DOT14::static_size);
+};
+
+struct PaintRotateAroundCenter
+{
+ HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ return_trace (out->src.serialize_subset (c, src, this));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && src.sanitize (c, this));
+ }
+
+ HBUINT8 format; /* format = 26 (noVar) or 27(Var) */
+ Offset24To<Paint> src; /* Offset (from beginning of PaintRotateAroundCenter table) to Paint subtable. */
+ F2DOT14 angle;
+ FWORD centerX;
+ FWORD centerY;
+ public:
+ DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size);
};
-template <template<typename> class Var>
struct PaintSkew
{
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
@@ -674,14 +820,41 @@ struct PaintSkew
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
- HBUINT8 format; /* format = 18(noVar) or 19 (Var) */
+ HBUINT8 format; /* format = 28(noVar) or 29 (Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */
- Var<HBFixed> xSkewAngle;
- Var<HBFixed> ySkewAngle;
- Var<HBFixed> centerX;
- Var<HBFixed> centerY;
+ F2DOT14 xSkewAngle;
+ F2DOT14 ySkewAngle;
public:
- DEFINE_SIZE_STATIC (4 + 4 * Var<HBFixed>::static_size);
+ DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size);
+};
+
+struct PaintSkewAroundCenter
+{
+ HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ return_trace (out->src.serialize_subset (c, src, this));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && src.sanitize (c, this));
+ }
+
+ HBUINT8 format; /* format = 30(noVar) or 31 (Var) */
+ Offset24To<Paint> src; /* Offset (from beginning of PaintSkewAroundCenter table) to Paint subtable. */
+ F2DOT14 xSkewAngle;
+ F2DOT14 ySkewAngle;
+ FWORD centerX;
+ FWORD centerY;
+ public:
+ DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size);
};
struct PaintComposite
@@ -706,7 +879,7 @@ struct PaintComposite
backdrop.sanitize (c, this));
}
- HBUINT8 format; /* format = 20 */
+ HBUINT8 format; /* format = 32 */
Offset24To<Paint> src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */
CompositeMode mode; /* If mode is unrecognized use COMPOSITE_CLEAR */
Offset24To<Paint> backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */
@@ -714,65 +887,274 @@ struct PaintComposite
DEFINE_SIZE_STATIC (8);
};
+struct ClipBoxFormat1
+{
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ public:
+ HBUINT8 format; /* format = 1(noVar) or 2(Var)*/
+ FWORD xMin;
+ FWORD yMin;
+ FWORD xMax;
+ FWORD yMax;
+ public:
+ DEFINE_SIZE_STATIC (1 + 4 * FWORD::static_size);
+};
+
+struct ClipBoxFormat2 : Variable<ClipBoxFormat1> {};
+
+struct ClipBox
+{
+ ClipBox* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ switch (u.format) {
+ case 1: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format1)));
+ case 2: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format2)));
+ default:return_trace (nullptr);
+ }
+ }
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ protected:
+ union {
+ HBUINT8 format; /* Format identifier */
+ ClipBoxFormat1 format1;
+ ClipBoxFormat2 format2;
+ } u;
+};
+
+struct ClipRecord
+{
+ ClipRecord* copy (hb_serialize_context_t *c, const void *base) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+ if (!out->clipBox.serialize_copy (c, clipBox, base)) return_trace (nullptr);
+ return_trace (out);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && clipBox.sanitize (c, base));
+ }
+
+ public:
+ HBUINT16 startGlyphID; // first gid clip applies to
+ HBUINT16 endGlyphID; // last gid clip applies to, inclusive
+ Offset24To<ClipBox> clipBox; // Box or VarBox
+ public:
+ DEFINE_SIZE_STATIC (7);
+};
+
+struct ClipList
+{
+ unsigned serialize_clip_records (hb_serialize_context_t *c,
+ const hb_set_t& gids,
+ const hb_map_t& gid_offset_map) const
+ {
+ TRACE_SERIALIZE (this);
+ if (gids.is_empty () ||
+ gid_offset_map.get_population () != gids.get_population ())
+ return_trace (0);
+
+ unsigned count = 0;
+
+ hb_codepoint_t start_gid= gids.get_min ();
+ hb_codepoint_t prev_gid = start_gid;
+
+ unsigned offset = gid_offset_map.get (start_gid);
+ unsigned prev_offset = offset;
+ for (const hb_codepoint_t _ : gids.iter ())
+ {
+ if (_ == start_gid) continue;
+
+ offset = gid_offset_map.get (_);
+ if (_ == prev_gid + 1 && offset == prev_offset)
+ {
+ prev_gid = _;
+ continue;
+ }
+
+ ClipRecord record;
+ record.startGlyphID = start_gid;
+ record.endGlyphID = prev_gid;
+ record.clipBox = prev_offset;
+
+ if (!c->copy (record, this)) return_trace (0);
+ count++;
+
+ start_gid = _;
+ prev_gid = _;
+ prev_offset = offset;
+ }
+
+ //last one
+ {
+ ClipRecord record;
+ record.startGlyphID = start_gid;
+ record.endGlyphID = prev_gid;
+ record.clipBox = prev_offset;
+ if (!c->copy (record, this)) return_trace (0);
+ count++;
+ }
+ return_trace (count);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ if (!c->serializer->check_assign (out->format, format, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
+
+ const hb_set_t& glyphset = *c->plan->_glyphset_colred;
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ hb_map_t new_gid_offset_map;
+ hb_set_t new_gids;
+ for (const ClipRecord& record : clips.iter ())
+ {
+ unsigned start_gid = record.startGlyphID;
+ unsigned end_gid = record.endGlyphID;
+ for (unsigned gid = start_gid; gid <= end_gid; gid++)
+ {
+ if (!glyphset.has (gid) || !glyph_map.has (gid)) continue;
+ unsigned new_gid = glyph_map.get (gid);
+ new_gid_offset_map.set (new_gid, record.clipBox);
+ new_gids.add (new_gid);
+ }
+ }
+
+ unsigned count = serialize_clip_records (c->serializer, new_gids, new_gid_offset_map);
+ if (!count) return_trace (false);
+ return_trace (c->serializer->check_assign (out->clips.len, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && clips.sanitize (c, this));
+ }
+
+ HBUINT8 format; // Set to 1.
+ Array32Of<ClipRecord> clips; // Clip records, sorted by startGlyphID
+ public:
+ DEFINE_SIZE_ARRAY_SIZED (5, clips);
+};
+
struct Paint
{
+
+ template <typename ...Ts>
+ bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
+ {
+ TRACE_SANITIZE (this);
+
+ if (unlikely (!c->check_start_recursion (HB_COLRV1_MAX_NESTING_LEVEL)))
+ return_trace (c->no_dispatch_return_value ());
+
+ return_trace (c->end_recursion (this->dispatch (c, std::forward<Ts> (ds)...)));
+ }
+
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.paintformat1, hb_forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.paintformat2, hb_forward<Ts> (ds)...));
- case 3: return_trace (c->dispatch (u.paintformat3, hb_forward<Ts> (ds)...));
- case 4: return_trace (c->dispatch (u.paintformat4, hb_forward<Ts> (ds)...));
- case 5: return_trace (c->dispatch (u.paintformat5, hb_forward<Ts> (ds)...));
- case 6: return_trace (c->dispatch (u.paintformat6, hb_forward<Ts> (ds)...));
- case 7: return_trace (c->dispatch (u.paintformat7, hb_forward<Ts> (ds)...));
- case 8: return_trace (c->dispatch (u.paintformat8, hb_forward<Ts> (ds)...));
- case 9: return_trace (c->dispatch (u.paintformat9, hb_forward<Ts> (ds)...));
- case 10: return_trace (c->dispatch (u.paintformat10, hb_forward<Ts> (ds)...));
- case 11: return_trace (c->dispatch (u.paintformat11, hb_forward<Ts> (ds)...));
- case 12: return_trace (c->dispatch (u.paintformat12, hb_forward<Ts> (ds)...));
- case 13: return_trace (c->dispatch (u.paintformat13, hb_forward<Ts> (ds)...));
- case 14: return_trace (c->dispatch (u.paintformat14, hb_forward<Ts> (ds)...));
- case 15: return_trace (c->dispatch (u.paintformat15, hb_forward<Ts> (ds)...));
- case 16: return_trace (c->dispatch (u.paintformat16, hb_forward<Ts> (ds)...));
- case 17: return_trace (c->dispatch (u.paintformat17, hb_forward<Ts> (ds)...));
- case 18: return_trace (c->dispatch (u.paintformat18, hb_forward<Ts> (ds)...));
- case 19: return_trace (c->dispatch (u.paintformat19, hb_forward<Ts> (ds)...));
- case 20: return_trace (c->dispatch (u.paintformat20, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.paintformat1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.paintformat2, std::forward<Ts> (ds)...));
+ case 3: return_trace (c->dispatch (u.paintformat3, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.paintformat4, std::forward<Ts> (ds)...));
+ case 5: return_trace (c->dispatch (u.paintformat5, std::forward<Ts> (ds)...));
+ case 6: return_trace (c->dispatch (u.paintformat6, std::forward<Ts> (ds)...));
+ case 7: return_trace (c->dispatch (u.paintformat7, std::forward<Ts> (ds)...));
+ case 8: return_trace (c->dispatch (u.paintformat8, std::forward<Ts> (ds)...));
+ case 9: return_trace (c->dispatch (u.paintformat9, std::forward<Ts> (ds)...));
+ case 10: return_trace (c->dispatch (u.paintformat10, std::forward<Ts> (ds)...));
+ case 11: return_trace (c->dispatch (u.paintformat11, std::forward<Ts> (ds)...));
+ case 12: return_trace (c->dispatch (u.paintformat12, std::forward<Ts> (ds)...));
+ case 13: return_trace (c->dispatch (u.paintformat13, std::forward<Ts> (ds)...));
+ case 14: return_trace (c->dispatch (u.paintformat14, std::forward<Ts> (ds)...));
+ case 15: return_trace (c->dispatch (u.paintformat15, std::forward<Ts> (ds)...));
+ case 16: return_trace (c->dispatch (u.paintformat16, std::forward<Ts> (ds)...));
+ case 17: return_trace (c->dispatch (u.paintformat17, std::forward<Ts> (ds)...));
+ case 18: return_trace (c->dispatch (u.paintformat18, std::forward<Ts> (ds)...));
+ case 19: return_trace (c->dispatch (u.paintformat19, std::forward<Ts> (ds)...));
+ case 20: return_trace (c->dispatch (u.paintformat20, std::forward<Ts> (ds)...));
+ case 21: return_trace (c->dispatch (u.paintformat21, std::forward<Ts> (ds)...));
+ case 22: return_trace (c->dispatch (u.paintformat22, std::forward<Ts> (ds)...));
+ case 23: return_trace (c->dispatch (u.paintformat23, std::forward<Ts> (ds)...));
+ case 24: return_trace (c->dispatch (u.paintformat24, std::forward<Ts> (ds)...));
+ case 25: return_trace (c->dispatch (u.paintformat25, std::forward<Ts> (ds)...));
+ case 26: return_trace (c->dispatch (u.paintformat26, std::forward<Ts> (ds)...));
+ case 27: return_trace (c->dispatch (u.paintformat27, std::forward<Ts> (ds)...));
+ case 28: return_trace (c->dispatch (u.paintformat28, std::forward<Ts> (ds)...));
+ case 29: return_trace (c->dispatch (u.paintformat29, std::forward<Ts> (ds)...));
+ case 30: return_trace (c->dispatch (u.paintformat30, std::forward<Ts> (ds)...));
+ case 31: return_trace (c->dispatch (u.paintformat31, std::forward<Ts> (ds)...));
+ case 32: return_trace (c->dispatch (u.paintformat32, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- HBUINT8 format;
- PaintColrLayers paintformat1;
- PaintSolid<NoVariable> paintformat2;
- PaintSolid<Variable> paintformat3;
- PaintLinearGradient<NoVariable> paintformat4;
- PaintLinearGradient<Variable> paintformat5;
- PaintRadialGradient<NoVariable> paintformat6;
- PaintRadialGradient<Variable> paintformat7;
- PaintSweepGradient<NoVariable> paintformat8;
- PaintSweepGradient<Variable> paintformat9;
- PaintGlyph paintformat10;
- PaintColrGlyph paintformat11;
- PaintTransform<NoVariable> paintformat12;
- PaintTransform<Variable> paintformat13;
- PaintTranslate<NoVariable> paintformat14;
- PaintTranslate<Variable> paintformat15;
- PaintRotate<NoVariable> paintformat16;
- PaintRotate<Variable> paintformat17;
- PaintSkew<NoVariable> paintformat18;
- PaintSkew<Variable> paintformat19;
- PaintComposite paintformat20;
+ HBUINT8 format;
+ PaintColrLayers paintformat1;
+ PaintSolid paintformat2;
+ Variable<PaintSolid> paintformat3;
+ PaintLinearGradient<NoVariable> paintformat4;
+ Variable<PaintLinearGradient<Variable>> paintformat5;
+ PaintRadialGradient<NoVariable> paintformat6;
+ Variable<PaintRadialGradient<Variable>> paintformat7;
+ PaintSweepGradient<NoVariable> paintformat8;
+ Variable<PaintSweepGradient<Variable>> paintformat9;
+ PaintGlyph paintformat10;
+ PaintColrGlyph paintformat11;
+ PaintTransform<NoVariable> paintformat12;
+ PaintTransform<Variable> paintformat13;
+ PaintTranslate paintformat14;
+ Variable<PaintTranslate> paintformat15;
+ PaintScale paintformat16;
+ Variable<PaintScale> paintformat17;
+ PaintScaleAroundCenter paintformat18;
+ Variable<PaintScaleAroundCenter> paintformat19;
+ PaintScaleUniform paintformat20;
+ Variable<PaintScaleUniform> paintformat21;
+ PaintScaleUniformAroundCenter paintformat22;
+ Variable<PaintScaleUniformAroundCenter> paintformat23;
+ PaintRotate paintformat24;
+ Variable<PaintRotate> paintformat25;
+ PaintRotateAroundCenter paintformat26;
+ Variable<PaintRotateAroundCenter> paintformat27;
+ PaintSkew paintformat28;
+ Variable<PaintSkew> paintformat29;
+ PaintSkewAroundCenter paintformat30;
+ Variable<PaintSkewAroundCenter> paintformat31;
+ PaintComposite paintformat32;
} u;
};
-struct BaseGlyphV1Record
+struct BaseGlyphPaintRecord
{
int cmp (hb_codepoint_t g) const
{ return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
@@ -797,21 +1179,21 @@ struct BaseGlyphV1Record
}
public:
- HBGlyphID glyphId; /* Glyph ID of reference glyph */
- Offset32To<Paint> paint; /* Offset (from beginning of BaseGlyphV1Record array) to Paint,
+ HBGlyphID16 glyphId; /* Glyph ID of reference glyph */
+ Offset32To<Paint> paint; /* Offset (from beginning of BaseGlyphPaintRecord array) to Paint,
* Typically PaintColrLayers */
public:
DEFINE_SIZE_STATIC (6);
};
-struct BaseGlyphV1List : SortedArray32Of<BaseGlyphV1Record>
+struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
{
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- const hb_set_t* glyphset = c->plan->_glyphset;
+ const hb_set_t* glyphset = c->plan->_glyphset_colred;
for (const auto& _ : as_array ())
{
@@ -828,11 +1210,11 @@ struct BaseGlyphV1List : SortedArray32Of<BaseGlyphV1Record>
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (SortedArray32Of<BaseGlyphV1Record>::sanitize (c, this));
+ return_trace (SortedArray32Of<BaseGlyphPaintRecord>::sanitize (c, this));
}
};
-struct LayerV1List : Array32OfOffset32To<Paint>
+struct LayerList : Array32OfOffset32To<Paint>
{
const Paint& get_paint (unsigned i) const
{ return this+(*this)[i]; }
@@ -888,13 +1270,9 @@ struct COLR
struct accelerator_t
{
- accelerator_t () {}
- ~accelerator_t () { fini (); }
-
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{ colr = hb_sanitize_context_t ().reference_table<COLR> (face); }
-
- void fini () { this->colr.destroy (); }
+ ~accelerator_t () { this->colr.destroy (); }
bool is_valid () { return colr.get_blob ()->length; }
@@ -952,24 +1330,24 @@ struct COLR
hb_set_t visited_glyphs;
hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices);
- const BaseGlyphV1List &baseglyphV1_records = this+baseGlyphsV1List;
+ const BaseGlyphList &baseglyph_paintrecords = this+baseGlyphList;
- for (const BaseGlyphV1Record &baseglyphV1record: baseglyphV1_records.iter ())
+ for (const BaseGlyphPaintRecord &baseglyph_paintrecord: baseglyph_paintrecords.iter ())
{
- unsigned gid = baseglyphV1record.glyphId;
+ unsigned gid = baseglyph_paintrecord.glyphId;
if (!glyphset->has (gid)) continue;
- const Paint &paint = &baseglyphV1_records+baseglyphV1record.paint;
+ const Paint &paint = &baseglyph_paintrecords+baseglyph_paintrecord.paint;
paint.dispatch (&c);
}
hb_set_union (glyphset, &visited_glyphs);
}
- const LayerV1List& get_layerV1List () const
- { return (this+layersV1); }
+ const LayerList& get_layerList () const
+ { return (this+layerList); }
- const BaseGlyphV1List& get_baseglyphV1List () const
- { return (this+baseGlyphsV1List); }
+ const BaseGlyphList& get_baseglyphList () const
+ { return (this+baseGlyphList); }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -979,8 +1357,10 @@ struct COLR
(this+layersZ).sanitize (c, numLayers) &&
(version == 0 ||
(COLRV1_ENABLE_SUBSETTING && version == 1 &&
- baseGlyphsV1List.sanitize (c, this) &&
- layersV1.sanitize (c, this) &&
+ baseGlyphList.sanitize (c, this) &&
+ layerList.sanitize (c, this) &&
+ clipList.sanitize (c, this) &&
+ varIdxMap.sanitize (c, this) &&
varStore.sanitize (c, this))));
}
@@ -996,19 +1376,17 @@ struct COLR
if (unlikely (base_it.len () != layer_it.len ()))
return_trace (false);
- if (unlikely (!c->extend_min (this))) return_trace (false);
this->version = version;
numLayers = 0;
numBaseGlyphs = base_it.len ();
- if (base_it.len () == 0)
+ if (numBaseGlyphs == 0)
{
baseGlyphsZ = 0;
layersZ = 0;
return_trace (true);
}
- baseGlyphsZ = COLR::min_size;
- layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size;
+ c->push ();
for (const hb_item_type<BaseIterator> _ : + base_it.iter ())
{
auto* record = c->embed (_);
@@ -1016,26 +1394,29 @@ struct COLR
record->firstLayerIdx = numLayers;
numLayers += record->numLayers;
}
+ c->add_link (baseGlyphsZ, c->pop_pack ());
+ c->push ();
for (const hb_item_type<LayerIterator>& _ : + layer_it.iter ())
_.as_array ().copy (c);
+ c->add_link (layersZ, c->pop_pack ());
+
return_trace (true);
}
const BaseGlyphRecord* get_base_glyph_record (hb_codepoint_t gid) const
{
- if ((unsigned int) gid == 0) // Ignore notdef.
- return nullptr;
const BaseGlyphRecord* record = &(this+baseGlyphsZ).bsearch (numBaseGlyphs, (unsigned int) gid);
- if ((record && (hb_codepoint_t) record->glyphId != gid))
+ if (record == &Null (BaseGlyphRecord) ||
+ (record && (hb_codepoint_t) record->glyphId != gid))
record = nullptr;
return record;
}
- const BaseGlyphV1Record* get_base_glyphV1_record (hb_codepoint_t gid) const
+ const BaseGlyphPaintRecord* get_base_glyph_paintrecord (hb_codepoint_t gid) const
{
- const BaseGlyphV1Record* record = &(this+baseGlyphsV1List).bsearch ((unsigned) gid);
+ const BaseGlyphPaintRecord* record = &(this+baseGlyphList).bsearch ((unsigned) gid);
if ((record && (hb_codepoint_t) record->glyphId != gid))
record = nullptr;
return record;
@@ -1046,9 +1427,16 @@ struct COLR
TRACE_SUBSET (this);
const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
+ const hb_set_t& glyphset = *c->plan->_glyphset_colred;
auto base_it =
+ hb_range (c->plan->num_output_glyphs ())
+ | hb_filter ([&](hb_codepoint_t new_gid)
+ {
+ hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
+ if (glyphset.has (old_gid)) return true;
+ return false;
+ })
| hb_map_retains_sorting ([&](hb_codepoint_t new_gid)
{
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
@@ -1056,7 +1444,6 @@ struct COLR
const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid);
if (unlikely (!old_record))
return hb_pair_t<bool, BaseGlyphRecord> (false, Null (BaseGlyphRecord));
-
BaseGlyphRecord new_record = {};
new_record.glyphId = new_gid;
new_record.numLayers = old_record->numLayers;
@@ -1069,6 +1456,7 @@ struct COLR
auto layer_it =
+ hb_range (c->plan->num_output_glyphs ())
| hb_map (reverse_glyph_map)
+ | hb_filter (glyphset)
| hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
{
const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid);
@@ -1101,23 +1489,26 @@ struct COLR
return_trace (false);
COLR *colr_prime = c->serializer->start_embed<COLR> ();
- bool ret = colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it);
+ if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false);
+
+ if (version == 0)
+ return_trace (colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it));
- if (version == 0) return_trace (ret);
auto snap = c->serializer->snapshot ();
- if (!c->serializer->allocate_size<void> (3 * HBUINT32::static_size)) return_trace (false);
- if (!colr_prime->baseGlyphsV1List.serialize_subset (c, baseGlyphsV1List, this))
+ if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false);
+ if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this))
{
if (c->serializer->in_error ()) return_trace (false);
//no more COLRv1 glyphs: downgrade to version 0
c->serializer->revert (snap);
- colr_prime->version = 0;
- return_trace (true);
+ return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
}
- if (!colr_prime->layersV1.serialize_subset (c, layersV1, this)) return_trace (false);
+ if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
- colr_prime->varStore = 0;
+ colr_prime->layerList.serialize_subset (c, layerList, this);
+ colr_prime->clipList.serialize_subset (c, clipList, this);
+ colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
//TODO: subset varStore once it's implemented in fonttools
return_trace (true);
}
@@ -1131,13 +1522,19 @@ struct COLR
layersZ; /* Offset to Layer Records. */
HBUINT16 numLayers; /* Number of Layer Records. */
// Version-1 additions
- Offset32To<BaseGlyphV1List> baseGlyphsV1List;
- Offset32To<LayerV1List> layersV1;
+ Offset32To<BaseGlyphList> baseGlyphList;
+ Offset32To<LayerList> layerList;
+ Offset32To<ClipList> clipList; // Offset to ClipList table (may be NULL)
+ Offset32To<DeltaSetIndexMap> varIdxMap; // Offset to DeltaSetIndexMap table (may be NULL)
Offset32To<VariationStore> varStore;
public:
DEFINE_SIZE_MIN (14);
};
+struct COLR_accelerator_t : COLR::accelerator_t {
+ COLR_accelerator_t (hb_face_t *face) : COLR::accelerator_t (face) {}
+};
+
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colrv1-closure.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colrv1-closure.hh
index 4124efe0b1..fbaf2ec26b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colrv1-closure.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colrv1-closure.hh
@@ -40,10 +40,10 @@ namespace OT {
HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const
{
c->add_layer_indices (firstLayerIndex, numLayers);
- const LayerV1List &paint_offset_lists = c->get_colr_table ()->get_layerV1List ();
+ const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
{
- const Paint &paint = hb_addressof (paint_offset_lists) + paint_offset_lists[i];
+ const Paint &paint = std::addressof (paint_offset_lists) + paint_offset_lists[i];
paint.dispatch (c);
}
}
@@ -57,37 +57,44 @@ HB_INTERNAL void PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
{
const COLR *colr_table = c->get_colr_table ();
- const BaseGlyphV1Record* baseglyphV1_record = colr_table->get_base_glyphV1_record (gid);
- if (!baseglyphV1_record) return;
+ const BaseGlyphPaintRecord* baseglyph_paintrecord = colr_table->get_base_glyph_paintrecord (gid);
+ if (!baseglyph_paintrecord) return;
c->add_glyph (gid);
- const BaseGlyphV1List &baseglyphV1_list = colr_table->get_baseglyphV1List ();
- (&baseglyphV1_list+baseglyphV1_record->paint).dispatch (c);
+ const BaseGlyphList &baseglyph_list = colr_table->get_baseglyphList ();
+ (&baseglyph_list+baseglyph_paintrecord->paint).dispatch (c);
}
template <template<typename> class Var>
HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{
- (this+src).dispatch (c);
-}
+{ (this+src).dispatch (c); }
-template <template<typename> class Var>
-HB_INTERNAL void PaintTranslate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{
- (this+src).dispatch (c);
-}
+HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
-template <template<typename> class Var>
-HB_INTERNAL void PaintRotate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{
- (this+src).dispatch (c);
-}
+HB_INTERNAL void PaintScale::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
-template <template<typename> class Var>
-HB_INTERNAL void PaintSkew<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{
- (this+src).dispatch (c);
-}
+HB_INTERNAL void PaintScaleAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintScaleUniform::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintScaleUniformAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintRotateAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintSkewAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-sbix-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-sbix-table.hh
index d2911f19e6..9741ebd450 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-sbix-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-sbix-table.hh
@@ -202,12 +202,12 @@ struct sbix
struct accelerator_t
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{
table = hb_sanitize_context_t ().reference_table<sbix> (face);
num_glyphs = face->get_num_glyphs ();
}
- void fini () { table.destroy (); }
+ ~accelerator_t () { table.destroy (); }
bool has_data () const { return table->has_data (); }
@@ -407,7 +407,10 @@ struct sbix
DEFINE_SIZE_ARRAY (8, strikes);
};
-struct sbix_accelerator_t : sbix::accelerator_t {};
+struct sbix_accelerator_t : sbix::accelerator_t {
+ sbix_accelerator_t (hb_face_t *face) : sbix::accelerator_t (face) {}
+};
+
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-svg-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-svg-table.hh
index e022ef43b7..fc649f1006 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-svg-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-color-svg-table.hh
@@ -79,9 +79,9 @@ struct SVG
struct accelerator_t
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{ table = hb_sanitize_context_t ().reference_table<SVG> (face); }
- void fini () { table.destroy (); }
+ ~accelerator_t () { table.destroy (); }
hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
{
@@ -116,7 +116,9 @@ struct SVG
DEFINE_SIZE_STATIC (10);
};
-struct SVG_accelerator_t : SVG::accelerator_t {};
+struct SVG_accelerator_t : SVG::accelerator_t {
+ SVG_accelerator_t (hb_face_t *face) : SVG::accelerator_t (face) {}
+};
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc
index 4170b71317..16077765bd 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc
@@ -90,15 +90,15 @@ hb_ot_color_palette_get_count (hb_face_t *face)
/**
* hb_ot_color_palette_get_name_id:
* @face: #hb_face_t to work upon
- * @palette_index: The index of the color palette
+ * @palette_index: The index of the color palette
*
* Fetches the `name` table Name ID that provides display names for
- * a `CPAL` color palette.
+ * a `CPAL` color palette.
*
* Palette display names can be generic (e.g., "Default") or provide
* specific, themed names (e.g., "Spring", "Summer", "Fall", and "Winter").
*
- * Return value: the Named ID found for the palette.
+ * Return value: the Named ID found for the palette.
* If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID.
*
* Since: 2.1.0
@@ -116,7 +116,7 @@ hb_ot_color_palette_get_name_id (hb_face_t *face,
* @color_index: The index of the color
*
* Fetches the `name` table Name ID that provides display names for
- * the specificed color in a face's `CPAL` color palette.
+ * the specified color in a face's `CPAL` color palette.
*
* Display names can be generic (e.g., "Background") or specific
* (e.g., "Eye color").
@@ -256,6 +256,8 @@ hb_ot_color_has_svg (hb_face_t *face)
*
* Fetches the SVG document for a glyph. The blob may be either plain text or gzip-encoded.
*
+ * If the glyph has no SVG document, the singleton empty blob is returned.
+ *
* Return value: (transfer full): An #hb_blob_t containing the SVG document of the glyph, if available
*
* Since: 2.1.0
@@ -296,6 +298,8 @@ hb_ot_color_has_png (hb_face_t *face)
* as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font
* object. If UPEM is unset, the blob returned will be the largest PNG available.
*
+ * If the glyph has no PNG image, the singleton empty blob is returned.
+ *
* Return value: (transfer full): An #hb_blob_t containing the PNG image for the glyph, if available
*
* Since: 2.1.0
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h
index ce6b6fef11..5192ff73e3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h
@@ -50,6 +50,21 @@ HB_BEGIN_DECLS
*/
#define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER
+/* https://github.com/harfbuzz/harfbuzz/pull/3417 */
+/**
+ * HB_OT_MATH_SCRIPT:
+ *
+ * Use #HB_SCRIPT_MATH or #HB_OT_TAG_MATH_SCRIPT instead.
+ *
+ * <note>Previous versions of this documentation recommended passing
+ * #HB_OT_MATH_SCRIPT to hb_buffer_set_script() to enable math shaping, but this
+ * usage is no longer supported. Use #HB_SCRIPT_MATH instead.</note>
+ *
+ * Since: 1.3.3
+ * Deprecated: 3.4.0
+ */
+#define HB_OT_MATH_SCRIPT HB_OT_TAG_MATH_SCRIPT
+
/* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-face-table-list.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-face-table-list.hh
index ffbbb1bc53..c05034b3bb 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-face-table-list.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-face-table-list.hh
@@ -32,6 +32,11 @@
#define HB_OT_FACE_TABLE_LIST_HH
#endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */
+#ifndef HB_OT_CORE_TABLE
+#define HB_OT_CORE_TABLE(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+#define _HB_OT_CORE_TABLE_UNDEF
+#endif
+
#ifndef HB_OT_ACCELERATOR
#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
#define _HB_OT_ACCELERATOR_UNDEF
@@ -46,7 +51,8 @@
/* OpenType fundamentals. */
-HB_OT_TABLE (OT, head)
+HB_OT_CORE_TABLE (OT, head)
+HB_OT_CORE_TABLE (OT, maxp)
#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
HB_OT_ACCELERATOR (OT, cmap)
#endif
@@ -67,17 +73,20 @@ HB_OT_ACCELERATOR (OT, meta)
#endif
/* Vertical layout. */
+#ifndef HB_NO_VERTICAL
HB_OT_TABLE (OT, vhea)
HB_OT_ACCELERATOR (OT, vmtx)
+HB_OT_TABLE (OT, VORG)
+#endif
/* TrueType outlines. */
+HB_OT_CORE_TABLE (OT, loca) // Also used to determine number of glyphs
HB_OT_ACCELERATOR (OT, glyf)
/* CFF outlines. */
#ifndef HB_NO_CFF
HB_OT_ACCELERATOR (OT, cff1)
HB_OT_ACCELERATOR (OT, cff2)
-HB_OT_TABLE (OT, VORG)
#endif
/* OpenType variations. */
@@ -136,3 +145,7 @@ HB_OT_TABLE (OT, MATH)
#ifdef _HB_OT_ACCELERATOR_UNDEF
#undef HB_OT_ACCELERATOR
#endif
+
+#ifdef _HB_OT_CORE_TABLE_UNDEF
+#undef HB_OT_CORE_TABLE
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-face.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-face.hh
index e24d380bca..415dae8e20 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-face.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-face.hh
@@ -63,10 +63,13 @@ struct hb_ot_face_t
hb_face_t *face; /* MUST be JUST before the lazy loaders. */
#define HB_OT_TABLE(Namespace, Type) \
hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
+#define HB_OT_CORE_TABLE(Namespace, Type) \
+ hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type), true> Type;
#define HB_OT_ACCELERATOR(Namespace, Type) \
hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
#include "hb-ot-face-table-list.hh"
#undef HB_OT_ACCELERATOR
+#undef HB_OT_CORE_TABLE
#undef HB_OT_TABLE
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
index 5c044c1c4f..0f44ee4d5f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
@@ -118,6 +118,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
}
}
+#ifndef HB_NO_VERTICAL
static void
hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
unsigned count,
@@ -130,14 +131,30 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
- for (unsigned int i = 0; i < count; i++)
+ if (vmtx.has_data ())
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ else
{
- *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
- first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
- first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ hb_font_extents_t font_extents;
+ font->get_h_extents_with_fallback (&font_extents);
+ hb_position_t advance = -(font_extents.ascender - font_extents.descender);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = advance;
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
}
}
+#endif
+#ifndef HB_NO_VERTICAL
static hb_bool_t
hb_ot_get_glyph_v_origin (hb_font_t *font,
void *font_data,
@@ -150,21 +167,29 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
*x = font->get_glyph_h_advance (glyph) / 2;
-#ifndef HB_NO_OT_FONT_CFF
const OT::VORG &VORG = *ot_face->VORG;
if (VORG.has_data ())
{
*y = font->em_scale_y (VORG.get_y_origin (glyph));
return true;
}
-#endif
hb_glyph_extents_t extents = {0};
if (ot_face->glyf->get_extents (font, glyph, &extents))
{
- const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
- hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
- *y = extents.y_bearing + font->em_scale_y (tsb);
+ if (ot_face->vmtx->has_data ())
+ {
+ const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+ hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
+ *y = extents.y_bearing + font->em_scale_y (tsb);
+ return true;
+ }
+
+ hb_font_extents_t font_extents;
+ font->get_h_extents_with_fallback (&font_extents);
+ hb_position_t advance = font_extents.ascender - font_extents.descender;
+ int diff = advance - -extents.height;
+ *y = extents.y_bearing + (diff >> 1);
return true;
}
@@ -174,6 +199,7 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
return true;
}
+#endif
static hb_bool_t
hb_ot_get_glyph_extents (hb_font_t *font,
@@ -242,6 +268,7 @@ hb_ot_get_font_h_extents (hb_font_t *font,
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
}
+#ifndef HB_NO_VERTICAL
static hb_bool_t
hb_ot_get_font_v_extents (hb_font_t *font,
void *font_data HB_UNUSED,
@@ -252,6 +279,24 @@ hb_ot_get_font_v_extents (hb_font_t *font,
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) &&
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
}
+#endif
+
+#ifndef HB_NO_DRAW
+static void
+hb_ot_get_glyph_shape (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data)
+{
+ hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
+ if (font->face->table.glyf->get_path (font, glyph, draw_session)) return;
+#ifndef HB_NO_CFF
+ if (font->face->table.cff1->get_path (font, glyph, draw_session)) return;
+ if (font->face->table.cff2->get_path (font, glyph, draw_session)) return;
+#endif
+}
+#endif
static inline void free_static_ot_funcs ();
@@ -261,17 +306,27 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
{
hb_font_funcs_t *funcs = hb_font_funcs_create ();
- hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
- hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
+
+ hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
- hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
+
+#ifndef HB_NO_VERTICAL
+ hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
+ hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
+#endif
+
+#ifndef HB_NO_DRAW
+ hb_font_funcs_set_glyph_shape_func (funcs, hb_ot_get_glyph_shape, nullptr, nullptr);
+#endif
+
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
//hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
+
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh
index ff7b9b2d25..b4ac688344 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh
@@ -93,22 +93,16 @@ struct glyf
template<typename Iterator,
hb_requires (hb_is_source_of (Iterator, unsigned int))>
static bool
- _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets)
+ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
{
- unsigned max_offset =
- + padded_offsets
- | hb_reduce (hb_add, 0)
- ;
unsigned num_offsets = padded_offsets.len () + 1;
- bool use_short_loca = max_offset < 0x1FFFF;
unsigned entry_size = use_short_loca ? 2 : 4;
char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
if (unlikely (!loca_prime_data)) return false;
- DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d "
- "max_offset %d size %d",
- entry_size, num_offsets, max_offset, entry_size * num_offsets);
+ DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
+ entry_size, num_offsets, entry_size * num_offsets);
if (use_short_loca)
_write_loca (padded_offsets, 1, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
@@ -151,11 +145,12 @@ struct glyf
template <typename Iterator>
bool serialize (hb_serialize_context_t *c,
Iterator it,
+ bool use_short_loca,
const hb_subset_plan_t *plan)
{
TRACE_SERIALIZE (this);
unsigned init_len = c->length ();
- for (const auto &_ : it) _.serialize (c, plan);
+ for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
/* As a special case when all glyph in the font are empty, add a zero byte
* to the table, so that OTS doesn’t reject it, and to make the table work
@@ -183,16 +178,28 @@ struct glyf
hb_vector_t<SubsetGlyph> glyphs;
_populate_subset_glyphs (c->plan, &glyphs);
- glyf_prime->serialize (c->serializer, hb_iter (glyphs), c->plan);
-
auto padded_offsets =
+ hb_iter (glyphs)
| hb_map (&SubsetGlyph::padded_size)
;
+ unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
+ bool use_short_loca = max_offset < 0x1FFFF;
+
+
+ glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
+ if (!use_short_loca) {
+ padded_offsets =
+ + hb_iter (glyphs)
+ | hb_map (&SubsetGlyph::length)
+ ;
+ }
+
+
if (unlikely (c->serializer->in_error ())) return_trace (false);
return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
- padded_offsets)));
+ padded_offsets,
+ use_short_loca)));
}
template <typename SubsetGlyph>
@@ -200,8 +207,7 @@ struct glyf
_populate_subset_glyphs (const hb_subset_plan_t *plan,
hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const
{
- OT::glyf::accelerator_t glyf;
- glyf.init (plan->source);
+ OT::glyf::accelerator_t glyf (plan->source);
+ hb_range (plan->num_output_glyphs ())
| hb_map ([&] (hb_codepoint_t new_gid)
@@ -226,8 +232,6 @@ struct glyf
})
| hb_sink (glyphs)
;
-
- glyf.fini ();
}
static bool
@@ -388,7 +392,7 @@ struct glyf
protected:
HBUINT16 flags;
- HBGlyphID glyphIndex;
+ HBGlyphID16 glyphIndex;
public:
DEFINE_SIZE_MIN (4);
};
@@ -588,7 +592,7 @@ struct glyf
if (unlikely (!header.numberOfContours)) return;
unsigned flags_offset = length (instructions_length ());
- if (unlikely (length (flags_offset + 1) > bytes.length)) return;
+ if (unlikely (flags_offset + 1 > bytes.length)) return;
HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
@@ -792,10 +796,23 @@ struct glyf
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
{
for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
- int h_delta = (int) header->xMin - glyf_accelerator.hmtx->get_side_bearing (gid);
- int v_orig = (int) header->yMax + glyf_accelerator.vmtx->get_side_bearing (gid);
+ int h_delta = (int) header->xMin -
+ glyf_accelerator.hmtx->get_side_bearing (gid);
+ int v_orig = (int) header->yMax +
+#ifndef HB_NO_VERTICAL
+ glyf_accelerator.vmtx->get_side_bearing (gid)
+#else
+ 0
+#endif
+ ;
unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid);
- unsigned v_adv = glyf_accelerator.vmtx->get_advance (gid);
+ unsigned v_adv =
+#ifndef HB_NO_VERTICAL
+ glyf_accelerator.vmtx->get_advance (gid)
+#else
+ - font->face->get_upem ()
+#endif
+ ;
phantoms[PHANTOM_LEFT].x = h_delta;
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
phantoms[PHANTOM_TOP].y = v_orig;
@@ -803,8 +820,7 @@ struct glyf
}
#ifndef HB_NO_VAR
- if (unlikely (!glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ())))
- return false;
+ glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
#endif
switch (type) {
@@ -900,7 +916,7 @@ struct glyf
struct accelerator_t
{
- void init (hb_face_t *face_)
+ accelerator_t (hb_face_t *face)
{
short_offset = false;
num_glyphs = 0;
@@ -910,29 +926,30 @@ struct glyf
gvar = nullptr;
#endif
hmtx = nullptr;
+#ifndef HB_NO_VERTICAL
vmtx = nullptr;
- face = face_;
+#endif
const OT::head &head = *face->table.head;
if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
return;
short_offset = 0 == head.indexToLocFormat;
- loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
+ loca_table = face->table.loca.get_blob (); // Needs no destruct!
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
#ifndef HB_NO_VAR
gvar = face->table.gvar;
#endif
hmtx = face->table.hmtx;
+#ifndef HB_NO_VERTICAL
vmtx = face->table.vmtx;
+#endif
num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
}
-
- void fini ()
+ ~accelerator_t ()
{
- loca_table.destroy ();
glyf_table.destroy ();
}
@@ -1037,7 +1054,11 @@ struct glyf
success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
if (unlikely (!success))
- return is_vertical ? vmtx->get_advance (gid) : hmtx->get_advance (gid);
+ return
+#ifndef HB_NO_VERTICAL
+ is_vertical ? vmtx->get_advance (gid) :
+#endif
+ hmtx->get_advance (gid);
float result = is_vertical
? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y
@@ -1053,7 +1074,11 @@ struct glyf
contour_point_t phantoms[PHANTOM_COUNT];
if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms))))
- return is_vertical ? vmtx->get_side_bearing (gid) : hmtx->get_side_bearing (gid);
+ return
+#ifndef HB_NO_VERTICAL
+ is_vertical ? vmtx->get_side_bearing (gid) :
+#endif
+ hmtx->get_side_bearing (gid);
return is_vertical
? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
@@ -1118,18 +1143,17 @@ struct glyf
while (it)
{
auto item = *(it++);
- operation_count +=
+ operation_count =
add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
}
return operation_count;
}
-#ifdef HB_EXPERIMENTAL_API
struct path_builder_t
{
hb_font_t *font;
- draw_helper_t *draw_helper;
+ hb_draw_session_t *draw_session;
struct optional_point_t
{
@@ -1144,10 +1168,10 @@ struct glyf
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
} first_oncurve, first_offcurve, last_offcurve;
- path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_)
+ path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
{
font = font_;
- draw_helper = &draw_helper_;
+ draw_session = &draw_session_;
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
}
@@ -1157,10 +1181,6 @@ struct glyf
* https://stackoverflow.com/a/20772557 */
void consume_point (const contour_point_t &point)
{
- /* Skip empty contours */
- if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data))
- return;
-
bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
optional_point_t p (point.x, point.y);
if (!first_oncurve.has_data)
@@ -1168,7 +1188,7 @@ struct glyf
if (is_on_curve)
{
first_oncurve = p;
- draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
+ draw_session->move_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
}
else
{
@@ -1177,7 +1197,7 @@ struct glyf
optional_point_t mid = first_offcurve.lerp (p, .5f);
first_oncurve = mid;
last_offcurve = p;
- draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
+ draw_session->move_to (font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
}
else
first_offcurve = p;
@@ -1189,22 +1209,22 @@ struct glyf
{
if (is_on_curve)
{
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (p.x), font->em_scalef_y (p.y));
+ draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
+ font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
last_offcurve = optional_point_t ();
}
else
{
optional_point_t mid = last_offcurve.lerp (p, .5f);
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
+ draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
+ font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
last_offcurve = p;
}
}
else
{
if (is_on_curve)
- draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
+ draw_session->line_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
else
last_offcurve = p;
}
@@ -1215,24 +1235,30 @@ struct glyf
if (first_offcurve.has_data && last_offcurve.has_data)
{
optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
+ draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
+ font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
last_offcurve = optional_point_t ();
/* now check the rest */
}
if (first_offcurve.has_data && first_oncurve.has_data)
- draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y),
- font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
+ draw_session->quadratic_to (font->em_fscalef_x (first_offcurve.x), font->em_fscalef_y (first_offcurve.y),
+ font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
else if (last_offcurve.has_data && first_oncurve.has_data)
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
+ draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
+ font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
else if (first_oncurve.has_data)
- draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
+ draw_session->line_to (font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
+ else if (first_offcurve.has_data)
+ {
+ float x = font->em_fscalef_x (first_offcurve.x), y = font->em_fscalef_x (first_offcurve.y);
+ draw_session->move_to (x, y);
+ draw_session->quadratic_to (x, y, x, y);
+ }
/* Getting ready for the next contour */
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
- draw_helper->end_path ();
+ draw_session->close_path ();
}
}
void points_end () {}
@@ -1242,22 +1268,22 @@ struct glyf
};
bool
- get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const
- { return get_points (font, gid, path_builder_t (font, draw_helper)); }
-#endif
+ get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
+ { return get_points (font, gid, path_builder_t (font, draw_session)); }
#ifndef HB_NO_VAR
const gvar_accelerator_t *gvar;
#endif
const hmtx_accelerator_t *hmtx;
+#ifndef HB_NO_VERTICAL
const vmtx_accelerator_t *vmtx;
+#endif
private:
bool short_offset;
unsigned int num_glyphs;
hb_blob_ptr_t<loca> loca_table;
hb_blob_ptr_t<glyf> glyf_table;
- hb_face_t *face;
};
struct SubsetGlyph
@@ -1269,13 +1295,14 @@ struct glyf
hb_bytes_t dest_end; /* region of source_glyph to copy second */
bool serialize (hb_serialize_context_t *c,
+ bool use_short_loca,
const hb_subset_plan_t *plan) const
{
TRACE_SERIALIZE (this);
hb_bytes_t dest_glyph = dest_start.copy (c);
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
- unsigned int pad_length = padding ();
+ unsigned int pad_length = use_short_loca ? padding () : 0;
DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
HBUINT8 pad;
@@ -1323,7 +1350,10 @@ struct glyf
* defining it _MIN instead. */
};
-struct glyf_accelerator_t : glyf::accelerator_t {};
+struct glyf_accelerator_t : glyf::accelerator_t {
+ glyf_accelerator_t (hb_face_t *face) : glyf::accelerator_t (face) {}
+};
+
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh
index ac588e3af6..20991aab2b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh
@@ -72,12 +72,14 @@ struct head
UNDERLINE = 1u<<2,
OUTLINE = 1u<<3,
SHADOW = 1u<<4,
- CONDENSED = 1u<<5
+ CONDENSED = 1u<<5,
+ EXPANDED = 1u<<6,
};
bool is_bold () const { return macStyle & BOLD; }
bool is_italic () const { return macStyle & ITALIC; }
bool is_condensed () const { return macStyle & CONDENSED; }
+ bool is_expanded () const { return macStyle & EXPANDED; }
bool sanitize (hb_sanitize_context_t *c) const
{
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 4038329938..d5e1fc91d2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
@@ -28,6 +28,7 @@
#define HB_OT_HMTX_TABLE_HH
#include "hb-open-type.hh"
+#include "hb-ot-maxp-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-ot-metrics.hh"
@@ -98,12 +99,12 @@ struct hmtxvmtx
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
- unsigned num_advances)
+ unsigned num_long_metrics)
{
unsigned idx = 0;
for (auto _ : it)
{
- if (idx < num_advances)
+ if (idx < num_long_metrics)
{
LongMetric lm;
lm.advance = _.first;
@@ -127,9 +128,20 @@ struct hmtxvmtx
T *table_prime = c->serializer->start_embed <T> ();
if (unlikely (!table_prime)) return_trace (false);
- accelerator_t _mtx;
- _mtx.init (c->plan->source);
- unsigned num_advances = _mtx.num_advances_for_subset (c->plan);
+ accelerator_t _mtx (c->plan->source);
+ unsigned num_long_metrics;
+ {
+ /* Determine num_long_metrics to encode. */
+ auto& plan = c->plan;
+ num_long_metrics = plan->num_output_glyphs ();
+ hb_codepoint_t old_gid = 0;
+ unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0;
+ while (num_long_metrics > 1 &&
+ last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0))
+ {
+ num_long_metrics--;
+ }
+ }
auto it =
+ hb_range (c->plan->num_output_glyphs ())
@@ -142,15 +154,13 @@ struct hmtxvmtx
})
;
- table_prime->serialize (c->serializer, it, num_advances);
-
- _mtx.fini ();
+ table_prime->serialize (c->serializer, it, num_long_metrics);
if (unlikely (c->serializer->in_error ()))
return_trace (false);
// Amend header num hmetrics
- if (unlikely (!subset_update_header (c->plan, num_advances)))
+ if (unlikely (!subset_update_header (c->plan, num_long_metrics)))
return_trace (false);
return_trace (true);
@@ -160,49 +170,67 @@ struct hmtxvmtx
{
friend struct hmtxvmtx;
- void init (hb_face_t *face,
- unsigned int default_advance_ = 0)
+ accelerator_t (hb_face_t *face)
{
- default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
+ table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
+ var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
- num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics;
+ default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face);
- table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
+ /* Populate count variables and sort them out as we go */
- /* Cap num_metrics() and num_advances() based on table length. */
unsigned int len = table.get_length ();
- if (unlikely (num_advances * 4 > len))
- num_advances = len / 4;
- num_metrics = num_advances + (len - 4 * num_advances) / 2;
+ if (len & 1)
+ len--;
+
+ num_long_metrics = T::is_horizontal ?
+ face->table.hhea->numberOfLongMetrics :
+#ifndef HB_NO_VERTICAL
+ face->table.vhea->numberOfLongMetrics
+#else
+ 0
+#endif
+ ;
+ if (unlikely (num_long_metrics * 4 > len))
+ num_long_metrics = len / 4;
+ len -= num_long_metrics * 4;
+
+ num_bearings = face->table.maxp->get_num_glyphs ();
- /* We MUST set num_metrics to zero if num_advances is zero.
+ if (unlikely (num_bearings < num_long_metrics))
+ num_bearings = num_long_metrics;
+ if (unlikely ((num_bearings - num_long_metrics) * 2 > len))
+ num_bearings = num_long_metrics + len / 2;
+ len -= (num_bearings - num_long_metrics) * 2;
+
+ /* We MUST set num_bearings to zero if num_long_metrics is zero.
* Our get_advance() depends on that. */
- if (unlikely (!num_advances))
- {
- num_metrics = num_advances = 0;
- table.destroy ();
- table = hb_blob_get_empty ();
- }
+ if (unlikely (!num_long_metrics))
+ num_bearings = num_long_metrics = 0;
- var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
+ num_advances = num_bearings + len / 2;
+ num_glyphs = face->get_num_glyphs ();
+ if (num_glyphs < num_advances)
+ num_glyphs = num_advances;
}
-
- void fini ()
+ ~accelerator_t ()
{
table.destroy ();
var_table.destroy ();
}
+ bool has_data () const { return (bool) num_bearings; }
+
int get_side_bearing (hb_codepoint_t glyph) const
{
- if (glyph < num_advances)
+ if (glyph < num_long_metrics)
return table->longMetricZ[glyph].sb;
- if (unlikely (glyph >= num_metrics))
+ if (unlikely (glyph >= num_bearings))
return 0;
- const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
- return bearings[glyph - num_advances];
+ const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
+ return bearings[glyph - num_long_metrics];
}
int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const
@@ -210,7 +238,7 @@ struct hmtxvmtx
int side_bearing = get_side_bearing (glyph);
#ifndef HB_NO_VAR
- if (unlikely (glyph >= num_metrics) || !font->num_coords)
+ if (unlikely (glyph >= num_bearings) || !font->num_coords)
return side_bearing;
if (var_table.get_length ())
@@ -224,18 +252,35 @@ struct hmtxvmtx
unsigned int get_advance (hb_codepoint_t glyph) const
{
- if (unlikely (glyph >= num_metrics))
- {
- /* If num_metrics is zero, it means we don't have the metrics table
- * for this direction: return default advance. Otherwise, it means that the
- * glyph index is out of bound: return zero. */
- if (num_metrics)
- return 0;
- else
- return default_advance;
- }
+ /* OpenType case. */
+ if (glyph < num_bearings)
+ return table->longMetricZ[hb_min (glyph, (uint32_t) num_long_metrics - 1)].advance;
+
+ /* If num_advances is zero, it means we don't have the metrics table
+ * for this direction: return default advance. Otherwise, there's a
+ * well-defined answer. */
+ if (unlikely (!num_advances))
+ return default_advance;
- return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance;
+#ifdef HB_NO_BORING_EXPANSION
+ return 0;
+#endif
+
+ if (unlikely (glyph >= num_glyphs))
+ return 0;
+
+ /* num_bearings <= glyph < num_glyphs;
+ * num_bearings <= num_advances */
+
+ /* TODO Optimize */
+
+ if (num_bearings == num_advances)
+ return get_advance (num_bearings - 1);
+
+ const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
+ const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics];
+
+ return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)];
}
unsigned int get_advance (hb_codepoint_t glyph,
@@ -244,7 +289,7 @@ struct hmtxvmtx
unsigned int advance = get_advance (glyph);
#ifndef HB_NO_VAR
- if (unlikely (glyph >= num_metrics) || !font->num_coords)
+ if (unlikely (glyph >= num_bearings) || !font->num_coords)
return advance;
if (var_table.get_length ())
@@ -256,35 +301,13 @@ struct hmtxvmtx
#endif
}
- unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const
- {
- unsigned int num_advances = plan->num_output_glyphs ();
- unsigned int last_advance = _advance_for_new_gid (plan,
- num_advances - 1);
- while (num_advances > 1 &&
- last_advance == _advance_for_new_gid (plan,
- num_advances - 2))
- {
- num_advances--;
- }
-
- return num_advances;
- }
-
- private:
- unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan,
- hb_codepoint_t new_gid) const
- {
- hb_codepoint_t old_gid;
- if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
- return 0;
-
- return get_advance (old_gid);
- }
-
protected:
- unsigned int num_metrics;
- unsigned int num_advances;
+ // 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs
+ unsigned num_long_metrics;
+ unsigned num_bearings;
+ unsigned num_advances;
+ unsigned num_glyphs;
+
unsigned int default_advance;
private:
@@ -316,6 +339,8 @@ struct hmtxvmtx
* the end. This allows a monospaced
* font to vary the side bearing
* values for each glyph. */
+/*UnsizedArrayOf<UFWORD>advancesX;*/
+ /* TODO Document. */
public:
DEFINE_SIZE_ARRAY (0, longMetricZ);
};
@@ -331,8 +356,12 @@ struct vmtx : hmtxvmtx<vmtx, vhea> {
static constexpr bool is_horizontal = false;
};
-struct hmtx_accelerator_t : hmtx::accelerator_t {};
-struct vmtx_accelerator_t : vmtx::accelerator_t {};
+struct hmtx_accelerator_t : hmtx::accelerator_t {
+ hmtx_accelerator_t (hb_face_t *face) : hmtx::accelerator_t (face) {}
+};
+struct vmtx_accelerator_t : vmtx::accelerator_t {
+ vmtx_accelerator_t (hb_face_t *face) : vmtx::accelerator_t (face) {}
+};
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh
index 3563cab8bd..ffa11bc249 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh
@@ -134,11 +134,11 @@ struct KernSubTable
switch (subtable_type) {
case 0: return_trace (c->dispatch (u.format0));
#ifndef HB_NO_AAT_SHAPE
- case 1: return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward<Ts> (ds)...) : c->default_return_value ());
+ case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
#endif
case 2: return_trace (c->dispatch (u.format2));
#ifndef HB_NO_AAT_SHAPE
- case 3: return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward<Ts> (ds)...) : c->default_return_value ());
+ case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
#endif
default: return_trace (c->default_return_value ());
}
@@ -325,9 +325,9 @@ struct kern
unsigned int subtable_type = get_type ();
TRACE_DISPATCH (this, subtable_type);
switch (subtable_type) {
- case 0: return_trace (c->dispatch (u.ot, hb_forward<Ts> (ds)...));
+ case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
#ifndef HB_NO_AAT_SHAPE
- case 1: return_trace (c->dispatch (u.aat, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
#endif
default: return_trace (c->default_return_value ());
}
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 492947751e..1b9dfcd3f5 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
@@ -41,7 +41,10 @@ namespace OT {
struct BaseCoordFormat1
{
- hb_position_t get_coord () const { return coordinate; }
+ hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const
+ {
+ return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -58,10 +61,10 @@ struct BaseCoordFormat1
struct BaseCoordFormat2
{
- hb_position_t get_coord () const
+ hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const
{
/* TODO */
- return coordinate;
+ return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -73,7 +76,7 @@ struct BaseCoordFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
FWORD coordinate; /* X or Y value, in design units */
- HBGlyphID referenceGlyph; /* Glyph ID of control glyph */
+ HBGlyphID16 referenceGlyph; /* Glyph ID of control glyph */
HBUINT16 coordPoint; /* Index of contour point on the
* reference glyph */
public:
@@ -87,9 +90,10 @@ struct BaseCoordFormat3
hb_direction_t direction) const
{
const Device &device = this+deviceTable;
- return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ?
- device.get_y_delta (font, var_store) :
- device.get_x_delta (font, var_store));
+
+ return HB_DIRECTION_IS_HORIZONTAL (direction)
+ ? font->em_scale_y (coordinate) + device.get_y_delta (font, var_store)
+ : font->em_scale_x (coordinate) + device.get_x_delta (font, var_store);
}
@@ -120,8 +124,8 @@ struct BaseCoord
hb_direction_t direction) const
{
switch (u.format) {
- case 1: return u.format1.get_coord ();
- case 2: return u.format2.get_coord ();
+ case 1: return u.format1.get_coord (font, direction);
+ case 2: return u.format2.get_coord (font, direction);
case 3: return u.format3.get_coord (font, var_store, direction);
default:return 0;
}
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 65f499a00d..f2a58028e3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh
@@ -37,7 +37,7 @@
#ifndef HB_MAX_NESTING_LEVEL
-#define HB_MAX_NESTING_LEVEL 6
+#define HB_MAX_NESTING_LEVEL 64
#endif
#ifndef HB_MAX_CONTEXT_LENGTH
#define HB_MAX_CONTEXT_LENGTH 64
@@ -60,6 +60,10 @@
#define HB_MAX_LANGSYS 2000
#endif
+#ifndef HB_MAX_LANGSYS_FEATURE_COUNT
+#define HB_MAX_LANGSYS_FEATURE_COUNT 50000
+#endif
+
#ifndef HB_MAX_FEATURES
#define HB_MAX_FEATURES 750
#endif
@@ -68,8 +72,8 @@
#define HB_MAX_FEATURE_INDICES 1500
#endif
-#ifndef HB_MAX_LOOKUP_INDICES
-#define HB_MAX_LOOKUP_INDICES 20000
+#ifndef HB_MAX_LOOKUP_VISIT_COUNT
+#define HB_MAX_LOOKUP_VISIT_COUNT 35000
#endif
@@ -89,7 +93,7 @@ static inline void ClassDef_serialize (hb_serialize_context_t *c,
static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID> &glyphs,
+ hb_sorted_vector_t<HBGlyphID16> &glyphs,
const hb_set_t &klasses,
bool use_class_zero,
hb_map_t *klass_map /*INOUT*/);
@@ -98,54 +102,33 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
struct hb_prune_langsys_context_t
{
hb_prune_langsys_context_t (const void *table_,
- hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_,
+ hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
const hb_map_t *duplicate_feature_map_,
hb_set_t *new_collected_feature_indexes_)
:table (table_),
script_langsys_map (script_langsys_map_),
duplicate_feature_map (duplicate_feature_map_),
new_feature_indexes (new_collected_feature_indexes_),
- script_count (0),langsys_count (0) {}
-
- bool visitedScript (const void *s)
- {
- if (script_count++ > HB_MAX_SCRIPTS)
- return true;
-
- return visited (s, visited_script);
- }
-
- bool visitedLangsys (const void *l)
- {
- if (langsys_count++ > HB_MAX_LANGSYS)
- return true;
+ script_count (0),langsys_feature_count (0) {}
- return visited (l, visited_langsys);
- }
+ bool visitScript ()
+ { return script_count++ < HB_MAX_SCRIPTS; }
- private:
- template <typename T>
- bool visited (const T *p, hb_set_t &visited_set)
+ bool visitLangsys (unsigned feature_count)
{
- hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) p - (uintptr_t) table);
- if (visited_set.has (delta))
- return true;
-
- visited_set.add (delta);
- return false;
+ langsys_feature_count += feature_count;
+ return langsys_feature_count < HB_MAX_LANGSYS_FEATURE_COUNT;
}
public:
const void *table;
- hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map;
+ hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
const hb_map_t *duplicate_feature_map;
hb_set_t *new_feature_indexes;
private:
- hb_set_t visited_script;
- hb_set_t visited_langsys;
unsigned script_count;
- unsigned langsys_count;
+ unsigned langsys_feature_count;
};
struct hb_subset_layout_context_t :
@@ -173,20 +156,20 @@ struct hb_subset_layout_context_t :
bool visitLookupIndex()
{
lookup_index_count++;
- return lookup_index_count < HB_MAX_LOOKUP_INDICES;
+ return lookup_index_count < HB_MAX_LOOKUP_VISIT_COUNT;
}
hb_subset_context_t *subset_context;
const hb_tag_t table_tag;
const hb_map_t *lookup_index_map;
- const hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map;
+ const hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
const hb_map_t *feature_index_map;
unsigned cur_script_index;
hb_subset_layout_context_t (hb_subset_context_t *c_,
hb_tag_t tag_,
hb_map_t *lookup_map_,
- hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_,
+ hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
hb_map_t *feature_index_map_) :
subset_context (c_),
table_tag (tag_),
@@ -237,9 +220,9 @@ struct subset_offset_array_t
template <typename T>
bool operator () (T&& offset)
{
+ auto snap = subset_context->serializer->snapshot ();
auto *o = out.serialize_append (subset_context->serializer);
if (unlikely (!o)) return false;
- auto snap = subset_context->serializer->snapshot ();
bool ret = o->serialize_subset (subset_context, offset, base);
if (!ret)
{
@@ -268,9 +251,9 @@ struct subset_offset_array_arg_t
template <typename T>
bool operator () (T&& offset)
{
+ auto snap = subset_context->serializer->snapshot ();
auto *o = out.serialize_append (subset_context->serializer);
if (unlikely (!o)) return false;
- auto snap = subset_context->serializer->snapshot ();
bool ret = o->serialize_subset (subset_context, offset, base, arg);
if (!ret)
{
@@ -346,6 +329,43 @@ struct
}
HB_FUNCOBJ (subset_record_array);
+
+template<typename OutputArray>
+struct serialize_math_record_array_t
+{
+ serialize_math_record_array_t (hb_serialize_context_t *serialize_context_,
+ OutputArray& out_,
+ const void *base_) : serialize_context (serialize_context_),
+ out (out_), base (base_) {}
+
+ template <typename T>
+ bool operator () (T&& record)
+ {
+ if (!serialize_context->copy (record, base)) return false;
+ out.len++;
+ return true;
+ }
+
+ private:
+ hb_serialize_context_t *serialize_context;
+ OutputArray &out;
+ const void *base;
+};
+
+/*
+ * Helper to serialize an array of MATH records.
+ */
+struct
+{
+ template<typename OutputArray>
+ serialize_math_record_array_t<OutputArray>
+ operator () (hb_serialize_context_t *serialize_context, OutputArray& out,
+ const void *base) const
+ { return serialize_math_record_array_t<OutputArray> (serialize_context, out, base); }
+
+}
+HB_FUNCOBJ (serialize_math_record_array);
+
/*
*
* OpenType Layout Common Table Formats
@@ -508,8 +528,8 @@ struct RangeRecord
bool collect_coverage (set_t *glyphs) const
{ return glyphs->add_range (first, last); }
- HBGlyphID first; /* First GlyphID in the range */
- HBGlyphID last; /* Last GlyphID in the range */
+ HBGlyphID16 first; /* First GlyphID in the range */
+ HBGlyphID16 last; /* Last GlyphID in the range */
HBUINT16 value; /* Value */
public:
DEFINE_SIZE_STATIC (6);
@@ -606,11 +626,14 @@ struct LangSys
| hb_map (feature_index_map)
;
- if (iter.len () != o_iter.len ())
- return false;
+ for (; iter && o_iter; iter++, o_iter++)
+ {
+ unsigned a = *iter;
+ unsigned b = *o_iter;
+ if (a != b) return false;
+ }
- for (const auto _ : + hb_zip (iter, o_iter))
- if (_.first != _.second) return false;
+ if (iter || o_iter) return false;
return true;
}
@@ -618,7 +641,6 @@ struct LangSys
void collect_features (hb_prune_langsys_context_t *c) const
{
if (!has_required_feature () && !get_feature_count ()) return;
- if (c->visitedLangsys (this)) return;
if (has_required_feature () &&
c->duplicate_feature_map->has (reqFeatureIndex))
c->new_feature_indexes->add (get_required_feature_index ());
@@ -696,7 +718,7 @@ struct Script
unsigned script_index) const
{
if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
- if (c->visitedScript (this)) return;
+ if (!c->visitScript ()) return;
if (!c->script_langsys_map->has (script_index))
{
@@ -713,11 +735,14 @@ struct Script
{
//only collect features from non-redundant langsys
const LangSys& d = get_default_lang_sys ();
- d.collect_features (c);
+ if (c->visitLangsys (d.get_feature_count ())) {
+ d.collect_features (c);
+ }
for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
{
const LangSys& l = this+_.first.offset;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
if (l.compare (d, c->duplicate_feature_map)) continue;
l.collect_features (c);
@@ -729,6 +754,7 @@ struct Script
for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
{
const LangSys& l = this+_.first.offset;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
l.collect_features (c);
c->script_langsys_map->get (script_index)->add (_.second);
}
@@ -808,7 +834,7 @@ struct FeatureParamsSize
if (unlikely (!c->check_struct (this))) return_trace (false);
/* This subtable has some "history", if you will. Some earlier versions of
- * Adobe tools calculated the offset of the FeatureParams sutable from the
+ * Adobe tools calculated the offset of the FeatureParams subtable from the
* beginning of the FeatureList table! Now, that is dealt with in the
* Feature implementation. But we still need to be able to tell junk from
* real data. Note: We don't check that the nameID actually exists.
@@ -1249,7 +1275,7 @@ struct Lookup
TRACE_DISPATCH (this, lookup_type);
unsigned int count = get_subtable_count ();
for (unsigned int i = 0; i < count; i++) {
- typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, hb_forward<Ts> (ds)...);
+ typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, std::forward<Ts> (ds)...);
if (c->stop_sublookup_iteration (r))
return_trace (r);
}
@@ -1299,7 +1325,7 @@ struct Lookup
outMarkFilteringSet = markFilteringSet;
}
- return_trace (true);
+ return_trace (out->subTable.len);
}
template <typename TSubTable>
@@ -1320,7 +1346,7 @@ struct Lookup
if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
return_trace (false);
- if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
+ if (unlikely (get_type () == TSubTable::Extension && subtables && !c->get_edit_count ()))
{
/* The spec says all subtables of an Extension lookup should
* have the same type, which shall not be the Extension type
@@ -1454,7 +1480,7 @@ struct CoverageFormat1
protected:
HBUINT16 coverageFormat; /* Format identifier--format = 1 */
- SortedArray16Of<HBGlyphID>
+ SortedArray16Of<HBGlyphID16>
glyphArray; /* Array of GlyphIDs--in numerical order */
public:
DEFINE_SIZE_ARRAY (4, glyphArray);
@@ -1832,7 +1858,7 @@ Coverage_serialize (hb_serialize_context_t *c,
static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID> &glyphs,
+ hb_sorted_vector_t<HBGlyphID16> &glyphs,
const hb_set_t &klasses,
bool use_class_zero,
hb_map_t *klass_map /*INOUT*/)
@@ -1859,7 +1885,7 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
auto it =
+ glyphs.iter ()
- | hb_map_retains_sorting ([&] (const HBGlyphID& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
+ | hb_map_retains_sorting ([&] (const HBGlyphID16& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
{
unsigned new_klass = klass_map->get (gid_klass_map[gid]);
return hb_pair ((hb_codepoint_t)gid, new_klass);
@@ -1926,7 +1952,7 @@ struct ClassDefFormat1
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
- hb_sorted_vector_t<HBGlyphID> glyphs;
+ hb_sorted_vector_t<HBGlyphID16> glyphs;
hb_set_t orig_klasses;
hb_map_t gid_org_klass_map;
@@ -2044,9 +2070,25 @@ struct ClassDefFormat1
intersect_glyphs->add (startGlyph + i);
}
+ void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
+ {
+ if (glyphs->is_empty ()) return;
+ hb_codepoint_t end_glyph = startGlyph + classValue.len - 1;
+ if (glyphs->get_min () < startGlyph ||
+ glyphs->get_max () > end_glyph)
+ intersect_classes->add (0);
+
+ for (const auto& _ : + hb_enumerate (classValue))
+ {
+ hb_codepoint_t g = startGlyph + _.first;
+ if (glyphs->has (g))
+ intersect_classes->add (_.second);
+ }
+ }
+
protected:
HBUINT16 classFormat; /* Format identifier--format = 1 */
- HBGlyphID startGlyph; /* First GlyphID of the classValueArray */
+ HBGlyphID16 startGlyph; /* First GlyphID of the classValueArray */
Array16Of<HBUINT16>
classValue; /* Array of Class Values--one per GlyphID */
public:
@@ -2128,7 +2170,7 @@ struct ClassDefFormat2
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
- hb_sorted_vector_t<HBGlyphID> glyphs;
+ hb_sorted_vector_t<HBGlyphID16> glyphs;
hb_set_t orig_klasses;
hb_map_t gid_org_klass_map;
@@ -2277,6 +2319,31 @@ struct ClassDefFormat2
}
}
+ void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
+ {
+ if (glyphs->is_empty ()) return;
+
+ unsigned count = rangeRecord.len;
+ hb_codepoint_t g = HB_SET_VALUE_INVALID;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (!hb_set_next (glyphs, &g))
+ break;
+ if (g < rangeRecord[i].first)
+ {
+ intersect_classes->add (0);
+ break;
+ }
+ g = rangeRecord[i].last;
+ }
+ if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+ intersect_classes->add (0);
+
+ for (const RangeRecord& record : rangeRecord.iter ())
+ if (record.intersects (glyphs))
+ intersect_classes->add (record.value);
+ }
+
protected:
HBUINT16 classFormat; /* Format identifier--format = 2 */
SortedArray16Of<RangeRecord>
@@ -2429,6 +2496,16 @@ struct ClassDef
}
}
+ void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.intersected_classes (glyphs, intersect_classes);
+ case 2: return u.format2.intersected_classes (glyphs, intersect_classes);
+ default:return;
+ }
+ }
+
+
protected:
union {
HBUINT16 format; /* Format identifier */
@@ -2543,7 +2620,7 @@ struct VarRegionList
public:
HBUINT16 axisCount;
- HBUINT16 regionCount;
+ HBUINT15 regionCount;
protected:
UnsizedArrayOf<VarRegionAxis>
axesZ;
@@ -2838,8 +2915,6 @@ struct VariationStore
hb_vector_t<hb_inc_bimap_t> inner_maps;
inner_maps.resize ((unsigned) dataSets.len);
- for (unsigned i = 0; i < inner_maps.length; i++)
- inner_maps[i].init ();
for (unsigned idx : c->plan->layout_variation_indices->iter ())
{
@@ -2847,18 +2922,11 @@ struct VariationStore
uint16_t minor = idx & 0xFFFF;
if (major >= inner_maps.length)
- {
- for (unsigned i = 0; i < inner_maps.length; i++)
- inner_maps[i].fini ();
return_trace (false);
- }
inner_maps[major].add (minor);
}
varstore_prime->serialize (c->serializer, this, inner_maps.as_array ());
- for (unsigned i = 0; i < inner_maps.length; i++)
- inner_maps[i].fini ();
-
return_trace (
!c->serializer->in_error()
&& varstore_prime->dataSets);
@@ -2947,7 +3015,7 @@ struct Condition
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
index 31a4a3e84c..a76d644c4b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
@@ -84,7 +84,7 @@ struct AttachList
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
@@ -248,9 +248,9 @@ struct CaretValue
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
- case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
@@ -371,7 +371,7 @@ struct LigCaretList
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset ();
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
@@ -585,17 +585,16 @@ struct GDEF
struct accelerator_t
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{
- this->table = hb_sanitize_context_t ().reference_table<GDEF> (face);
- if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
+ table = hb_sanitize_context_t ().reference_table<GDEF> (face);
+ if (unlikely (table->is_blocklisted (table.get_blob (), face)))
{
- hb_blob_destroy (this->table.get_blob ());
- this->table = hb_blob_get_empty ();
+ hb_blob_destroy (table.get_blob ());
+ table = hb_blob_get_empty ();
}
}
-
- void fini () { this->table.destroy (); }
+ ~accelerator_t () { table.destroy (); }
hb_blob_ptr_t<GDEF> table;
};
@@ -715,7 +714,9 @@ struct GDEF
DEFINE_SIZE_MIN (12);
};
-struct GDEF_accelerator_t : GDEF::accelerator_t {};
+struct GDEF_accelerator_t : GDEF::accelerator_t {
+ GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {}
+};
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
index 1e305518f5..2f9186a2a7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
@@ -118,7 +118,13 @@ struct ValueFormat : HBUINT16
if (!format) return ret;
hb_font_t *font = c->font;
- bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
+ bool horizontal =
+#ifndef HB_NO_VERTICAL
+ HB_DIRECTION_IS_HORIZONTAL (c->direction)
+#else
+ true
+#endif
+ ;
if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
@@ -700,7 +706,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage or
float mark_x, mark_y, base_x, base_y;
- buffer->unsafe_to_break (glyph_pos, buffer->idx);
+ buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
@@ -1050,8 +1056,8 @@ struct SinglePos
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
@@ -1144,7 +1150,7 @@ struct PairValueRecord
}
protected:
- HBGlyphID secondGlyph; /* GlyphID of second glyph in the
+ HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the
* pair--first glyph is listed in the
* Coverage table */
ValueRecord values; /* Positioning data for the first glyph
@@ -1220,15 +1226,16 @@ struct PairSet
record_size);
if (record)
{
- /* Note the intentional use of "|" instead of short-circuit "||". */
- if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
- valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
+ bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
+ bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+ if (applied_first || applied_second)
buffer->unsafe_to_break (buffer->idx, pos + 1);
if (len2)
pos++;
buffer->idx = pos;
return_trace (true);
}
+ buffer->unsafe_to_concat (buffer->idx, pos + 1);
return_trace (false);
}
@@ -1356,7 +1363,12 @@ struct PairPosFormat1
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
- if (!skippy_iter.next ()) return_trace (false);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ buffer->unsafe_to_concat (buffer->idx, unsafe_to);
+ return_trace (false);
+ }
return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
}
@@ -1386,9 +1398,9 @@ struct PairPosFormat1
| hb_filter (glyphset, hb_first)
| hb_filter ([this, c, out] (const Offset16To<PairSet>& _)
{
+ auto snap = c->serializer->snapshot ();
auto *o = out->pairSet.serialize_append (c->serializer);
if (unlikely (!o)) return false;
- auto snap = c->serializer->snapshot ();
bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
if (!ret)
{
@@ -1549,7 +1561,12 @@ struct PairPosFormat2
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
- if (!skippy_iter.next ()) return_trace (false);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ buffer->unsafe_to_concat (buffer->idx, unsafe_to);
+ return_trace (false);
+ }
unsigned int len1 = valueFormat1.get_len ();
unsigned int len2 = valueFormat2.get_len ();
@@ -1557,13 +1574,89 @@ struct PairPosFormat2
unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
- if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
+ if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
+ {
+ buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+ return_trace (false);
+ }
const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
- /* Note the intentional use of "|" instead of short-circuit "||". */
- if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) |
- valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]))
+
+ bool applied_first = false, applied_second = false;
+
+
+ /* Isolate simple kerning and apply it half to each side.
+ * Results in better cursor positinoing / underline drawing.
+ *
+ * Disabled, because causes issues... :-(
+ * https://github.com/harfbuzz/harfbuzz/issues/3408
+ * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978
+ */
+#ifndef HB_SPLIT_KERN
+ if (0)
+#endif
+ {
+ if (!len2)
+ {
+ const hb_direction_t dir = buffer->props.direction;
+ const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
+ const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
+ unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
+ if (backward)
+ mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
+ /* Add Devices. */
+ mask |= mask << 4;
+
+ if (valueFormat1 & ~mask)
+ goto bail;
+
+ /* Is simple kern. Apply value on an empty position slot,
+ * then split it between sides. */
+
+ hb_glyph_position_t pos{};
+ if (valueFormat1.apply_value (c, this, v, pos))
+ {
+ hb_position_t *src = &pos.x_advance;
+ hb_position_t *dst1 = &buffer->cur_pos().x_advance;
+ hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
+ unsigned i = horizontal ? 0 : 1;
+
+ hb_position_t kern = src[i];
+ hb_position_t kern1 = kern >> 1;
+ hb_position_t kern2 = kern - kern1;
+
+ if (!backward)
+ {
+ dst1[i] += kern1;
+ dst2[i] += kern2;
+ dst2[i + 2] += kern2;
+ }
+ else
+ {
+ dst1[i] += kern1;
+ dst1[i + 2] += src[i + 2] - kern2;
+ dst2[i] += kern2;
+ }
+
+ applied_first = applied_second = kern != 0;
+ goto success;
+ }
+ goto boring;
+ }
+ }
+ bail:
+
+
+ applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
+ applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+
+ success:
+ if (applied_first || applied_second)
buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
+ else
+ boring:
+ buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+
buffer->idx = skippy_iter.idx;
if (len2)
@@ -1702,8 +1795,8 @@ struct PairPos
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
@@ -1793,10 +1886,19 @@ struct CursivePosFormat1
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
- if (!skippy_iter.prev ()) return_trace (false);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
- if (!prev_record.exitAnchor) return_trace (false);
+ if (!prev_record.exitAnchor)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
unsigned int i = skippy_iter.idx;
unsigned int j = buffer->idx;
@@ -1959,7 +2061,7 @@ struct CursivePos
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
@@ -2060,7 +2162,13 @@ struct MarkBasePosFormat1
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
do {
- if (!skippy_iter.prev ()) return_trace (false);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
/* We only want to attach to the first of a MultipleSubst sequence.
* https://github.com/harfbuzz/harfbuzz/issues/740
* Reject others...
@@ -2083,7 +2191,11 @@ struct MarkBasePosFormat1
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
- if (base_index == NOT_COVERED) return_trace (false);
+ if (base_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
}
@@ -2194,7 +2306,7 @@ struct MarkBasePos
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
@@ -2314,21 +2426,34 @@ struct MarkLigPosFormat1
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
- if (!skippy_iter.prev ()) return_trace (false);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
/* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
//if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
unsigned int j = skippy_iter.idx;
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
- if (lig_index == NOT_COVERED) return_trace (false);
+ if (lig_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
const LigatureArray& lig_array = this+ligatureArray;
const LigatureAttach& lig_attach = lig_array[lig_index];
/* Find component to attach to */
unsigned int comp_count = lig_attach.rows;
- if (unlikely (!comp_count)) return_trace (false);
+ if (unlikely (!comp_count))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
/* We must now check whether the ligature ID of the current mark glyph
* is identical to the ligature ID of the found ligature. If yes, we
@@ -2434,7 +2559,7 @@ struct MarkLigPos
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
@@ -2511,9 +2636,18 @@ struct MarkMarkPosFormat1
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
- if (!skippy_iter.prev ()) return_trace (false);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
- if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return_trace (false); }
+ if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
unsigned int j = skippy_iter.idx;
@@ -2538,11 +2672,16 @@ struct MarkMarkPosFormat1
}
/* Didn't match. */
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
good:
unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
- if (mark2_index == NOT_COVERED) return_trace (false);
+ if (mark2_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
}
@@ -2653,7 +2792,7 @@ struct MarkMarkPos
TRACE_DISPATCH (this, u.format);
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
@@ -2704,15 +2843,15 @@ struct PosLookupSubTable
{
TRACE_DISPATCH (this, lookup_type);
switch (lookup_type) {
- case Single: return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
- case Pair: return_trace (u.pair.dispatch (c, hb_forward<Ts> (ds)...));
- case Cursive: return_trace (u.cursive.dispatch (c, hb_forward<Ts> (ds)...));
- case MarkBase: return_trace (u.markBase.dispatch (c, hb_forward<Ts> (ds)...));
- case MarkLig: return_trace (u.markLig.dispatch (c, hb_forward<Ts> (ds)...));
- case MarkMark: return_trace (u.markMark.dispatch (c, hb_forward<Ts> (ds)...));
- case Context: return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
- case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
- case Extension: return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
+ case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
+ case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
+ case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
+ case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
+ case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
+ case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
default: return_trace (c->default_return_value ());
}
}
@@ -2800,7 +2939,7 @@ struct PosLookup : Lookup
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
+ { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
bool subset (hb_subset_context_t *c) const
{ return Lookup::subset<SubTable> (c); }
@@ -2945,7 +3084,7 @@ GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer H
}
void
-GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
+GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
{
_hb_buffer_assert_gsubgpos_vars (buffer);
@@ -2955,12 +3094,21 @@ GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
/* Handle attachments */
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
- for (unsigned int i = 0; i < len; i++)
+ for (unsigned i = 0; i < len; i++)
propagate_attachment_offsets (pos, len, i, direction);
+
+ if (unlikely (font->slant))
+ {
+ for (unsigned i = 0; i < len; i++)
+ if (unlikely (pos[i].y_offset))
+ pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset);
+ }
}
-struct GPOS_accelerator_t : GPOS::accelerator_t {};
+struct GPOS_accelerator_t : GPOS::accelerator_t {
+ GPOS_accelerator_t (hb_face_t *face) : GPOS::accelerator_t (face) {}
+};
/* Out-of-class implementation for methods recursing */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
index 393ada1351..bef381430b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
@@ -29,1689 +29,14 @@
#ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
#define HB_OT_LAYOUT_GSUB_TABLE_HH
-#include "hb-ot-layout-gsubgpos.hh"
-
+#include "OT/Layout/GSUB/GSUB.hh"
namespace OT {
-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);
-
-
-struct SingleSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- unsigned d = deltaGlyphID;
-
- + hb_iter (this+coverage)
- | hb_filter (c->parent_active_glyphs ())
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
- | hb_sink (c->output)
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- unsigned d = deltaGlyphID;
- + hb_iter (this+coverage)
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
- | hb_sink (c->output)
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
- unsigned int index = (this+coverage).get_coverage (glyph_id);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- /* According to the Adobe Annotated OpenType Suite, result is always
- * limited to 16bit. */
- glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
- c->replace_glyph (glyph_id);
-
- return_trace (true);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator glyphs,
- unsigned delta)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
- c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- hb_codepoint_t delta = deltaGlyphID;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting ([&] (hb_codepoint_t g) {
- return hb_codepoint_pair_t (g,
- (g + delta) & 0xFFFF); })
- | hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t
- { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
- ;
-
- bool ret = bool (it);
- SingleSubst_serialize (c->serializer, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- HBUINT16 deltaGlyphID; /* Add to original GlyphID to get
- * substitute GlyphID, modulo 0x10000 */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-
-struct SingleSubstFormat2
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, substitute)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_sink (c->output)
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- + hb_zip (this+coverage, substitute)
- | hb_map (hb_second)
- | hb_sink (c->output)
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- if (unlikely (index >= substitute.len)) return_trace (false);
-
- c->replace_glyph (substitute[index]);
-
- return_trace (true);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator,
- hb_codepoint_pair_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator it)
- {
- TRACE_SERIALIZE (this);
- auto substitutes =
- + it
- | hb_map (hb_second)
- ;
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
- if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_zip (this+coverage, substitute)
- | hb_filter (glyphset, hb_first)
- | hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t
- { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
- ;
-
- bool ret = bool (it);
- SingleSubst_serialize (c->serializer, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16Of<HBGlyphID>
- substitute; /* Array of substitute
- * GlyphIDs--ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, substitute);
-};
-
-struct SingleSubst
-{
-
- template<typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator,
- const hb_codepoint_pair_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned format = 2;
- unsigned delta = 0;
- if (glyphs)
- {
- format = 1;
- auto get_delta = [=] (hb_codepoint_pair_t _)
- { return (unsigned) (_.second - _.first) & 0xFFFF; };
- delta = get_delta (*glyphs);
- if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
- }
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c,
- + glyphs
- | hb_map_retains_sorting (hb_first),
- delta));
- case 2: return_trace (u.format2.serialize (c, glyphs));
- default:return_trace (false);
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- SingleSubstFormat1 format1;
- SingleSubstFormat2 format2;
- } u;
-};
-
-template<typename Iterator>
-static void
-SingleSubst_serialize (hb_serialize_context_t *c,
- Iterator it)
-{ c->start_embed<SingleSubst> ()->serialize (c, it); }
-
-struct Sequence
-{
- bool intersects (const hb_set_t *glyphs) const
- { return hb_all (substitute, glyphs); }
-
- void closure (hb_closure_context_t *c) const
- { c->output->add_array (substitute.arrayZ, substitute.len); }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { c->output->add_array (substitute.arrayZ, substitute.len); }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int count = substitute.len;
-
- /* Special-case to make it in-place and not consider this
- * as a "multiplied" substitution. */
- if (unlikely (count == 1))
- {
- c->replace_glyph (substitute.arrayZ[0]);
- return_trace (true);
- }
- /* Spec disallows this, but Uniscribe allows it.
- * https://github.com/harfbuzz/harfbuzz/issues/253 */
- else if (unlikely (count == 0))
- {
- c->buffer->delete_glyph ();
- return_trace (true);
- }
-
- unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
- HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
- unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
-
- for (unsigned int i = 0; i < count; i++)
- {
- /* If is attached to a ligature, don't disturb that.
- * https://github.com/harfbuzz/harfbuzz/issues/3069 */
- if (!lig_id)
- _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
- c->output_glyph_for_component (substitute.arrayZ[i], klass);
- }
- c->buffer->skip_glyph ();
-
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator subst)
- {
- TRACE_SERIALIZE (this);
- return_trace (substitute.serialize (c, subst));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- if (!intersects (&glyphset)) return_trace (false);
-
- auto it =
- + hb_iter (substitute)
- | hb_map (glyph_map)
- ;
-
- auto *out = c->serializer->start_embed (*this);
- return_trace (out->serialize (c->serializer, it));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (substitute.sanitize (c));
- }
-
- protected:
- Array16Of<HBGlyphID>
- substitute; /* String of GlyphIDs to substitute */
- public:
- DEFINE_SIZE_ARRAY (2, substitute);
-};
-
-struct MultipleSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return true; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, sequence)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.closure (c); })
- ;
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- + hb_zip (this+coverage, sequence)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- return_trace ((this+sequence[index]).apply (c));
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID> substitute_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < glyphs.length; i++)
- {
- unsigned int substitute_len = substitute_len_list[i];
- if (unlikely (!sequence[i]
- .serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
- return_trace (false);
- substitute_glyphs_list += substitute_len;
- }
- return_trace (coverage.serialize_serialize (c, glyphs));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + hb_zip (this+coverage, sequence)
- | hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->sequence, this), hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
- return_trace (bool (new_coverage));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16OfOffset16To<Sequence>
- sequence; /* Array of Sequence tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, sequence);
-};
-
-struct MultipleSubst
-{
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID> substitute_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 1;
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
- default:return_trace (false);
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MultipleSubstFormat1 format1;
- } u;
-};
-
-struct AlternateSet
-{
- bool intersects (const hb_set_t *glyphs) const
- { return hb_any (alternates, glyphs); }
-
- void closure (hb_closure_context_t *c) const
- { c->output->add_array (alternates.arrayZ, alternates.len); }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { c->output->add_array (alternates.arrayZ, alternates.len); }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int count = alternates.len;
-
- if (unlikely (!count)) return_trace (false);
-
- hb_mask_t glyph_mask = c->buffer->cur().mask;
- hb_mask_t lookup_mask = c->lookup_mask;
-
- /* Note: This breaks badly if two features enabled this lookup together. */
- unsigned int shift = hb_ctz (lookup_mask);
- unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
-
- /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
- if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
- {
- /* Maybe we can do better than unsafe-to-break all; but since we are
- * changing random state, it would be hard to track that. Good 'nough. */
- c->buffer->unsafe_to_break_all ();
- alt_index = c->random_number () % count + 1;
- }
-
- if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
-
- c->replace_glyph (alternates[alt_index - 1]);
-
- return_trace (true);
- }
-
- unsigned
- get_alternates (unsigned start_offset,
- unsigned *alternate_count /* IN/OUT. May be NULL. */,
- hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
- {
- if (alternates.len && alternate_count)
- {
- + alternates.sub_array (start_offset, alternate_count)
- | hb_sink (hb_array (alternate_glyphs, *alternate_count))
- ;
- }
- return alternates.len;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator alts)
- {
- TRACE_SERIALIZE (this);
- return_trace (alternates.serialize (c, alts));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_iter (alternates)
- | hb_filter (glyphset)
- | hb_map (glyph_map)
- ;
-
- auto *out = c->serializer->start_embed (*this);
- return_trace (out->serialize (c->serializer, it) &&
- out->alternates);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (alternates.sanitize (c));
- }
-
- protected:
- Array16Of<HBGlyphID>
- alternates; /* Array of alternate GlyphIDs--in
- * arbitrary order */
- public:
- DEFINE_SIZE_ARRAY (2, alternates);
-};
-
-struct AlternateSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, alternateSet)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- + hb_zip (this+coverage, alternateSet)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- unsigned
- get_glyph_alternates (hb_codepoint_t gid,
- unsigned start_offset,
- unsigned *alternate_count /* IN/OUT. May be NULL. */,
- hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
- { return (this+alternateSet[(this+coverage).get_coverage (gid)])
- .get_alternates (start_offset, alternate_count, alternate_glyphs); }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- return_trace ((this+alternateSet[index]).apply (c));
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID> glyphs,
- hb_array_t<const unsigned int> alternate_len_list,
- hb_array_t<const HBGlyphID> alternate_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < glyphs.length; i++)
- {
- unsigned int alternate_len = alternate_len_list[i];
- if (unlikely (!alternateSet[i]
- .serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
- return_trace (false);
- alternate_glyphs_list += alternate_len;
- }
- return_trace (coverage.serialize_serialize (c, glyphs));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + hb_zip (this+coverage, alternateSet)
- | hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
- return_trace (bool (new_coverage));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16OfOffset16To<AlternateSet>
- alternateSet; /* Array of AlternateSet tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, alternateSet);
-};
-
-struct AlternateSubst
-{
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID> glyphs,
- hb_array_t<const unsigned int> alternate_len_list,
- hb_array_t<const HBGlyphID> alternate_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 1;
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
- default:return_trace (false);
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- AlternateSubstFormat1 format1;
- } u;
-};
-
-
-struct Ligature
-{
- bool intersects (const hb_set_t *glyphs) const
- { return hb_all (component, glyphs); }
-
- void closure (hb_closure_context_t *c) const
- {
- if (!intersects (c->glyphs)) return;
- c->output->add (ligGlyph);
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- c->input->add_array (component.arrayZ, component.get_length ());
- c->output->add (ligGlyph);
- }
-
- bool would_apply (hb_would_apply_context_t *c) const
- {
- if (c->len != component.lenP1)
- return false;
-
- for (unsigned int i = 1; i < c->len; i++)
- if (likely (c->glyphs[i] != component[i]))
- return false;
-
- return true;
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int count = component.lenP1;
-
- if (unlikely (!count)) return_trace (false);
-
- /* Special-case to make it in-place and not consider this
- * as a "ligated" substitution. */
- if (unlikely (count == 1))
- {
- c->replace_glyph (ligGlyph);
- return_trace (true);
- }
-
- unsigned int total_component_count = 0;
-
- unsigned int match_length = 0;
- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-
- if (likely (!match_input (c, count,
- &component[1],
- match_glyph,
- nullptr,
- &match_length,
- match_positions,
- &total_component_count)))
- return_trace (false);
-
- ligate_input (c,
- count,
- match_positions,
- match_length,
- ligGlyph,
- total_component_count);
-
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- hb_codepoint_t ligature,
- Iterator components /* Starting from second */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- ligGlyph = ligature;
- if (unlikely (!component.serialize (c, components))) return_trace (false);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
-
- auto it =
- + hb_iter (component)
- | hb_map (glyph_map)
- ;
-
- auto *out = c->serializer->start_embed (*this);
- return_trace (out->serialize (c->serializer,
- glyph_map[ligGlyph],
- it));
- }
-
- public:
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
- }
-
- protected:
- HBGlyphID ligGlyph; /* GlyphID of ligature to substitute */
- HeadlessArrayOf<HBGlyphID>
- component; /* Array of component GlyphIDs--start
- * with the second component--ordered
- * in writing direction */
- public:
- DEFINE_SIZE_ARRAY (4, component);
-};
-
-struct LigatureSet
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
- | hb_any
- ;
- }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.closure (c); })
- ;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); })
- ;
- }
-
- bool would_apply (hb_would_apply_context_t *c) const
- {
- return
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_map ([c] (const Ligature &_) { return _.would_apply (c); })
- | hb_any
- ;
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int num_ligs = ligature.len;
- for (unsigned int i = 0; i < num_ligs; i++)
- {
- const Ligature &lig = this+ligature[i];
- if (lig.apply (c)) return_trace (true);
- }
-
- return_trace (false);
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_array_t<const HBGlyphID> ligatures,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID> &component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
- for (unsigned int i = 0; i < ligatures.length; i++)
- {
- unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
- if (unlikely (!ligature[i].serialize_serialize (c,
- ligatures[i],
- component_list.sub_array (0, component_count))))
- return_trace (false);
- component_list += component_count;
- }
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- + hb_iter (ligature)
- | hb_filter (subset_offset_array (c, out->ligature, this))
- | hb_drain
- ;
- return_trace (bool (out->ligature));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (ligature.sanitize (c, this));
- }
-
- protected:
- Array16OfOffset16To<Ligature>
- ligature; /* Array LigatureSet tables
- * ordered by preference */
- public:
- DEFINE_SIZE_ARRAY (2, ligature);
-};
-
-struct LigatureSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return
- + hb_zip (this+coverage, ligatureSet)
- | hb_filter (*glyphs, hb_first)
- | hb_map (hb_second)
- | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
- { return (this+_).intersects (glyphs); })
- | hb_any
- ;
- }
-
- bool may_have_non_1to1 () const
- { return true; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, ligatureSet)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
-
- + hb_zip (this+coverage, ligatureSet)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); })
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- {
- unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
- if (likely (index == NOT_COVERED)) return false;
-
- const LigatureSet &lig_set = this+ligatureSet[index];
- return lig_set.would_apply (c);
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- const LigatureSet &lig_set = this+ligatureSet[index];
- return_trace (lig_set.apply (c));
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID> first_glyphs,
- hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- hb_array_t<const HBGlyphID> ligatures_list,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < first_glyphs.length; i++)
- {
- unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
- if (unlikely (!ligatureSet[i]
- .serialize_serialize (c,
- ligatures_list.sub_array (0, ligature_count),
- component_count_list.sub_array (0, ligature_count),
- component_list))) return_trace (false);
- ligatures_list += ligature_count;
- component_count_list += ligature_count;
- }
- return_trace (coverage.serialize_serialize (c, first_glyphs));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + hb_zip (this+coverage, ligatureSet)
- | hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->ligatureSet, this), hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
- return_trace (bool (new_coverage));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16OfOffset16To<LigatureSet>
- ligatureSet; /* Array LigatureSet tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, ligatureSet);
-};
-
-struct LigatureSubst
-{
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID> first_glyphs,
- hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- hb_array_t<const HBGlyphID> ligatures_list,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 1;
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c,
- first_glyphs,
- ligature_per_first_glyph_count_list,
- ligatures_list,
- component_count_list,
- component_list));
- default:return_trace (false);
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- LigatureSubstFormat1 format1;
- } u;
-};
-
-
-struct ContextSubst : Context {};
-
-struct ChainContextSubst : ChainContext {};
-
-struct ExtensionSubst : Extension<ExtensionSubst>
-{
- typedef struct SubstLookupSubTable SubTable;
- bool is_reverse () const;
-};
-
-
-struct ReverseChainSingleSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- if (!(this+coverage).intersects (glyphs))
- return false;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
-
- unsigned int count;
-
- count = backtrack.len;
- for (unsigned int i = 0; i < count; i++)
- if (!(this+backtrack[i]).intersects (glyphs))
- return false;
-
- count = lookahead.len;
- for (unsigned int i = 0; i < count; i++)
- if (!(this+lookahead[i]).intersects (glyphs))
- return false;
-
- return true;
- }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- if (!intersects (c->glyphs)) return;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
-
- + hb_zip (this+coverage, substitute)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_sink (c->output)
- ;
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
-
- unsigned int count;
-
- count = backtrack.len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- count = lookahead.len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
-
- const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
- count = substitute.len;
- c->output->add_array (substitute.arrayZ, substitute.len);
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
- return_trace (false); /* No chaining to this type */
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
-
- if (unlikely (index >= substitute.len)) return_trace (false);
-
- unsigned int start_index = 0, end_index = 0;
- if (match_backtrack (c,
- backtrack.len, (HBUINT16 *) backtrack.arrayZ,
- match_coverage, this,
- &start_index) &&
- match_lookahead (c,
- lookahead.len, (HBUINT16 *) lookahead.arrayZ,
- match_coverage, this,
- 1, &end_index))
- {
- c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
- c->replace_glyph_inplace (substitute[index]);
- /* Note: We DON'T decrease buffer->idx. The main loop does it
- * for us. This is useful for preventing surprises if someone
- * calls us through a Context lookup. */
- return_trace (true);
- }
-
- return_trace (false);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
-
- if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
- return_trace (false);
-
- for (auto& offset : it) {
- auto *o = out->serialize_append (c->serializer);
- if (unlikely (!o) || !o->serialize_subset (c, offset, this))
- return_trace (false);
- }
-
- return_trace (true);
- }
-
- template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
- hb_requires (hb_is_iterator (BacktrackIterator)),
- hb_requires (hb_is_iterator (LookaheadIterator))>
- bool serialize (hb_subset_context_t *c,
- Iterator coverage_subst_iter,
- BacktrackIterator backtrack_iter,
- LookaheadIterator lookahead_iter) const
- {
- TRACE_SERIALIZE (this);
-
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->check_success (out))) return_trace (false);
- if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
- if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
-
- if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
- if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
-
- auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID>> ();
- auto substitutes =
- + coverage_subst_iter
- | hb_map (hb_second)
- ;
-
- auto glyphs =
- + coverage_subst_iter
- | hb_map_retains_sorting (hb_first)
- ;
- if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
- return_trace (false);
-
- if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs)))
- return_trace (false);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
-
- auto it =
- + hb_zip (this+coverage, substitute)
- | hb_filter (glyphset, hb_first)
- | hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t
- { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
- ;
-
- return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
- return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- if (!lookahead.sanitize (c, this))
- return_trace (false);
- const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
- return_trace (substitute.sanitize (c));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of table */
- Array16OfOffset16To<Coverage>
- backtrack; /* Array of coverage tables
- * in backtracking sequence, in glyph
- * sequence order */
- Array16OfOffset16To<Coverage>
- lookaheadX; /* Array of coverage tables
- * in lookahead sequence, in glyph
- * sequence order */
- Array16Of<HBGlyphID>
- substituteX; /* Array of substitute
- * GlyphIDs--ordered by Coverage Index */
- public:
- DEFINE_SIZE_MIN (10);
-};
-
-struct ReverseChainSingleSubst
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- ReverseChainSingleSubstFormat1 format1;
- } u;
-};
-
-
-
-/*
- * SubstLookup
- */
-
-struct SubstLookupSubTable
-{
- friend struct Lookup;
- friend struct SubstLookup;
-
- enum Type {
- Single = 1,
- Multiple = 2,
- Alternate = 3,
- Ligature = 4,
- Context = 5,
- ChainContext = 6,
- Extension = 7,
- ReverseChainSingle = 8
- };
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, lookup_type);
- switch (lookup_type) {
- case Single: return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
- case Multiple: return_trace (u.multiple.dispatch (c, hb_forward<Ts> (ds)...));
- case Alternate: return_trace (u.alternate.dispatch (c, hb_forward<Ts> (ds)...));
- case Ligature: return_trace (u.ligature.dispatch (c, hb_forward<Ts> (ds)...));
- case Context: return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
- case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
- case Extension: return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
- case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, hb_forward<Ts> (ds)...));
- default: return_trace (c->default_return_value ());
- }
- }
-
- bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c, lookup_type);
- }
-
- protected:
- union {
- SingleSubst single;
- MultipleSubst multiple;
- AlternateSubst alternate;
- LigatureSubst ligature;
- ContextSubst context;
- ChainContextSubst chainContext;
- ExtensionSubst extension;
- ReverseChainSingleSubst reverseChainContextSingle;
- } u;
- public:
- DEFINE_SIZE_MIN (0);
-};
-
-
-struct SubstLookup : Lookup
-{
- typedef SubstLookupSubTable SubTable;
-
- const SubTable& get_subtable (unsigned int i) const
- { return Lookup::get_subtable<SubTable> (i); }
-
- static inline bool lookup_type_is_reverse (unsigned int lookup_type)
- { return lookup_type == SubTable::ReverseChainSingle; }
-
- bool is_reverse () const
- {
- unsigned int type = get_type ();
- if (unlikely (type == SubTable::Extension))
- return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse ();
- return lookup_type_is_reverse (type);
- }
-
- bool may_have_non_1to1 () const
- {
- hb_have_non_1to1_context_t c;
- return dispatch (&c);
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- return_trace (dispatch (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c);
- }
-
- hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
- {
- if (!c->should_visit_lookup (this_index))
- return hb_closure_context_t::default_return_value ();
-
- c->set_recurse_func (dispatch_closure_recurse_func);
-
- hb_closure_context_t::return_t ret = dispatch (c);
-
- c->flush ();
-
- return ret;
- }
-
- hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
- {
- if (c->is_lookup_visited (this_index))
- return hb_closure_lookups_context_t::default_return_value ();
-
- c->set_lookup_visited (this_index);
- if (!intersects (c->glyphs))
- {
- c->set_lookup_inactive (this_index);
- return hb_closure_lookups_context_t::default_return_value ();
- }
-
- c->set_recurse_func (dispatch_closure_lookups_recurse_func);
-
- hb_closure_lookups_context_t::return_t ret = dispatch (c);
- return ret;
- }
-
- hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
- return dispatch (c);
- }
-
- template <typename set_t>
- void collect_coverage (set_t *glyphs) const
- {
- hb_collect_coverage_context_t<set_t> c (glyphs);
- dispatch (&c);
- }
-
- bool would_apply (hb_would_apply_context_t *c,
- const hb_ot_layout_lookup_accelerator_t *accel) const
- {
- if (unlikely (!c->len)) return false;
- if (!accel->may_have (c->glyphs[0])) return false;
- return dispatch (c);
- }
-
- static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
- bool serialize_single (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID> glyphs,
- hb_array_t<const HBGlyphID> substitutes)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
- if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- bool serialize_multiple (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID> substitute_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
- if (c->push<SubTable> ()->u.multiple.
- serialize (c,
- glyphs,
- substitute_len_list,
- substitute_glyphs_list))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- bool serialize_alternate (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID> glyphs,
- hb_array_t<const unsigned int> alternate_len_list,
- hb_array_t<const HBGlyphID> alternate_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
-
- if (c->push<SubTable> ()->u.alternate.
- serialize (c,
- glyphs,
- alternate_len_list,
- alternate_glyphs_list))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- bool serialize_ligature (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID> first_glyphs,
- hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- hb_array_t<const HBGlyphID> ligatures_list,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
- if (c->push<SubTable> ()->u.ligature.
- serialize (c,
- first_glyphs,
- ligature_per_first_glyph_count_list,
- ligatures_list,
- component_count_list,
- component_list))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- template <typename context_t>
- static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
-
- static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
-
- static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
- {
- if (!c->should_visit_lookup (lookup_index))
- return hb_empty_t ();
-
- hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
-
- /* While in theory we should flush here, it will cause timeouts because a recursive
- * lookup can keep growing the glyph set. Skip, and outer loop will retry up to
- * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
- //c->flush ();
-
- return ret;
- }
-
- HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
-
- bool subset (hb_subset_context_t *c) const
- { return Lookup::subset<SubTable> (c); }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return Lookup::sanitize<SubTable> (c); }
-};
-
-/*
- * GSUB -- Glyph Substitution
- * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
- */
-
-struct GSUB : GSUBGPOS
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
-
- const SubstLookup& get_lookup (unsigned int i) const
- { return static_cast<const SubstLookup &> (GSUBGPOS::get_lookup (i)); }
-
- bool subset (hb_subset_context_t *c) const
- {
- hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
- return GSUBGPOS::subset<SubstLookup> (&l);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return GSUBGPOS::sanitize<SubstLookup> (c); }
-
- HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
- hb_face_t *face) const;
-
- void closure_lookups (hb_face_t *face,
- const hb_set_t *glyphs,
- hb_set_t *lookup_indexes /* IN/OUT */) const
- { GSUBGPOS::closure_lookups<SubstLookup> (face, glyphs, lookup_indexes); }
-
- typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
-};
-
-
-struct GSUB_accelerator_t : GSUB::accelerator_t {};
-
+using Layout::GSUB::SubstLookup;
+using Layout::GSUB::ExtensionSubst;
+// TODO(garretrieger): Move into the new layout directory.
/* Out-of-class implementation for methods recursing */
#ifndef HB_NO_OT_LAYOUT
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 626abc5577..56e8c5b006 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh
@@ -81,12 +81,15 @@ struct hb_closure_context_t :
nesting_level_left++;
}
+ void reset_lookup_visit_count ()
+ { lookup_count = 0; }
+
bool lookup_limit_exceeded ()
- { return lookup_count > HB_MAX_LOOKUP_INDICES; }
+ { return lookup_count > HB_MAX_LOOKUP_VISIT_COUNT; }
bool should_visit_lookup (unsigned int lookup_index)
{
- if (lookup_count++ > HB_MAX_LOOKUP_INDICES)
+ if (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT)
return false;
if (is_lookup_done (lookup_index))
@@ -122,24 +125,31 @@ struct hb_closure_context_t :
hb_set_t *covered_glyph_set = done_lookups_glyph_set->get (lookup_index);
if (unlikely (covered_glyph_set->in_error ()))
return true;
- if (parent_active_glyphs ()->is_subset (*covered_glyph_set))
+ if (parent_active_glyphs ().is_subset (*covered_glyph_set))
return true;
- hb_set_union (covered_glyph_set, parent_active_glyphs ());
+ covered_glyph_set->union_ (parent_active_glyphs ());
return false;
}
- hb_set_t* parent_active_glyphs ()
+ const hb_set_t& previous_parent_active_glyphs () {
+ if (active_glyphs_stack.length <= 1)
+ return *glyphs;
+
+ return active_glyphs_stack[active_glyphs_stack.length - 2];
+ }
+
+ const hb_set_t& parent_active_glyphs ()
{
- if (active_glyphs_stack.length < 1)
- return glyphs;
+ if (!active_glyphs_stack)
+ return *glyphs;
return active_glyphs_stack.tail ();
}
- void push_cur_active_glyphs (hb_set_t* cur_active_glyph_set)
+ hb_set_t& push_cur_active_glyphs ()
{
- active_glyphs_stack.push (cur_active_glyph_set);
+ return *active_glyphs_stack.push ();
}
bool pop_cur_done_glyphs ()
@@ -153,29 +163,24 @@ struct hb_closure_context_t :
hb_face_t *face;
hb_set_t *glyphs;
- hb_set_t *cur_intersected_glyphs;
hb_set_t output[1];
- hb_vector_t<hb_set_t *> active_glyphs_stack;
+ hb_vector_t<hb_set_t> active_glyphs_stack;
recurse_func_t recurse_func;
unsigned int nesting_level_left;
hb_closure_context_t (hb_face_t *face_,
hb_set_t *glyphs_,
- hb_set_t *cur_intersected_glyphs_,
hb_map_t *done_lookups_glyph_count_,
- hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set_,
+ hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set_,
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
face (face_),
glyphs (glyphs_),
- cur_intersected_glyphs (cur_intersected_glyphs_),
recurse_func (nullptr),
nesting_level_left (nesting_level_left_),
done_lookups_glyph_count (done_lookups_glyph_count_),
done_lookups_glyph_set (done_lookups_glyph_set_),
lookup_count (0)
- {
- push_cur_active_glyphs (glyphs_);
- }
+ {}
~hb_closure_context_t () { flush (); }
@@ -183,16 +188,16 @@ struct hb_closure_context_t :
void flush ()
{
- hb_set_del_range (output, face->get_num_glyphs (), HB_SET_VALUE_INVALID); /* Remove invalid glyphs. */
- hb_set_union (glyphs, output);
- hb_set_clear (output);
+ output->del_range (face->get_num_glyphs (), HB_SET_VALUE_INVALID); /* Remove invalid glyphs. */
+ glyphs->union_ (*output);
+ output->clear ();
active_glyphs_stack.pop ();
- active_glyphs_stack.fini ();
+ active_glyphs_stack.reset ();
}
private:
hb_map_t *done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set;
+ hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set;
unsigned int lookup_count;
};
@@ -211,7 +216,11 @@ struct hb_closure_lookups_context_t :
return;
/* Return if new lookup was recursed to before. */
- if (is_lookup_visited (lookup_index))
+ if (lookup_limit_exceeded ()
+ || visited_lookups->in_error ()
+ || visited_lookups->has (lookup_index))
+ // Don't increment lookup count here, that will be done in the call to closure_lookups()
+ // made by recurse_func.
return;
nesting_level_left--;
@@ -226,12 +235,20 @@ struct hb_closure_lookups_context_t :
{ inactive_lookups->add (lookup_index); }
bool lookup_limit_exceeded ()
- { return lookup_count > HB_MAX_LOOKUP_INDICES; }
+ {
+ bool ret = lookup_count > HB_MAX_LOOKUP_VISIT_COUNT;
+ if (ret)
+ DEBUG_MSG (SUBSET, nullptr, "lookup visit count limit exceeded in lookup closure!");
+ return ret; }
bool is_lookup_visited (unsigned lookup_index)
{
- if (unlikely (lookup_count++ > HB_MAX_LOOKUP_INDICES))
+ if (unlikely (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT))
+ {
+ DEBUG_MSG (SUBSET, nullptr, "total visited lookup count %u exceeds max limit, lookup %u is dropped.",
+ lookup_count, lookup_index);
return true;
+ }
if (unlikely (visited_lookups->in_error ()))
return true;
@@ -391,12 +408,11 @@ struct hb_ot_apply_context_t :
{
matcher_t () :
lookup_props (0),
+ mask (-1),
ignore_zwnj (false),
ignore_zwj (false),
- mask (-1),
-#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
- syllable arg1(0),
-#undef arg1
+ per_syllable (false),
+ syllable {0},
match_func (nullptr),
match_data (nullptr) {}
@@ -406,7 +422,8 @@ struct hb_ot_apply_context_t :
void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
void set_mask (hb_mask_t mask_) { mask = mask_; }
- void set_syllable (uint8_t syllable_) { syllable = syllable_; }
+ void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; }
+ void set_syllable (uint8_t syllable_) { syllable = per_syllable ? syllable_ : 0; }
void set_match_func (match_func_t match_func_,
const void *match_data_)
{ match_func = match_func_; match_data = match_data_; }
@@ -452,9 +469,10 @@ struct hb_ot_apply_context_t :
protected:
unsigned int lookup_props;
+ hb_mask_t mask;
bool ignore_zwnj;
bool ignore_zwj;
- hb_mask_t mask;
+ bool per_syllable;
uint8_t syllable;
match_func_t match_func;
const void *match_data;
@@ -473,6 +491,7 @@ struct hb_ot_apply_context_t :
/* Ignore ZWJ if we are matching context, or asked to. */
matcher.set_ignore_zwj (context_match || c->auto_zwj);
matcher.set_mask (context_match ? -1 : c->lookup_mask);
+ matcher.set_per_syllable (c->per_syllable);
}
void set_lookup_props (unsigned int lookup_props)
{
@@ -505,7 +524,7 @@ struct hb_ot_apply_context_t :
may_skip (const hb_glyph_info_t &info) const
{ return matcher.may_skip (c, info); }
- bool next ()
+ bool next (unsigned *unsafe_to = nullptr)
{
assert (num_items > 0);
while (idx + num_items < end)
@@ -528,11 +547,17 @@ struct hb_ot_apply_context_t :
}
if (skip == matcher_t::SKIP_NO)
+ {
+ if (unsafe_to)
+ *unsafe_to = idx + 1;
return false;
+ }
}
+ if (unsafe_to)
+ *unsafe_to = end;
return false;
}
- bool prev ()
+ bool prev (unsigned *unsafe_from = nullptr)
{
assert (num_items > 0);
while (idx > num_items - 1)
@@ -555,8 +580,14 @@ struct hb_ot_apply_context_t :
}
if (skip == matcher_t::SKIP_NO)
+ {
+ if (unsafe_from)
+ *unsafe_from = hb_max (1u, idx) - 1u;
return false;
+ }
}
+ if (unsafe_from)
+ *unsafe_from = 0;
return false;
}
@@ -607,6 +638,7 @@ struct hb_ot_apply_context_t :
bool has_glyph_classes;
bool auto_zwnj;
bool auto_zwj;
+ bool per_syllable;
bool random;
uint32_t random_state;
@@ -635,6 +667,7 @@ struct hb_ot_apply_context_t :
has_glyph_classes (gdef.has_glyph_classes ()),
auto_zwnj (true),
auto_zwj (true),
+ per_syllable (false),
random (false),
random_state (1) { init_iters (); }
@@ -647,6 +680,7 @@ struct hb_ot_apply_context_t :
void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); }
void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); }
+ void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; init_iters (); }
void set_random (bool random_) { random = random_; }
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
@@ -697,53 +731,60 @@ struct hb_ot_apply_context_t :
return true;
}
- void _set_glyph_props (hb_codepoint_t glyph_index,
+ void _set_glyph_class (hb_codepoint_t glyph_index,
unsigned int class_guess = 0,
bool ligature = false,
bool component = false) const
{
- unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
- HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
- add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
+ unsigned int props = _hb_glyph_info_get_glyph_props (&buffer->cur());
+ props |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
if (ligature)
{
- add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
+ props |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
/* In the only place that the MULTIPLIED bit is used, Uniscribe
* seems to only care about the "last" transformation between
* Ligature and Multiple substitutions. Ie. if you ligate, expand,
* and ligate again, it forgives the multiplication and acts as
* if only ligation happened. As such, clear MULTIPLIED bit.
*/
- add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+ props &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
}
if (component)
- add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+ props |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
if (likely (has_glyph_classes))
- _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
+ {
+ props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
+ _hb_glyph_info_set_glyph_props (&buffer->cur(), props | gdef.get_glyph_props (glyph_index));
+ }
else if (class_guess)
- _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
+ {
+ props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
+ _hb_glyph_info_set_glyph_props (&buffer->cur(), props | class_guess);
+ }
+ else
+ _hb_glyph_info_set_glyph_props (&buffer->cur(), props);
}
void replace_glyph (hb_codepoint_t glyph_index) const
{
- _set_glyph_props (glyph_index);
+ _set_glyph_class (glyph_index);
(void) buffer->replace_glyph (glyph_index);
}
void replace_glyph_inplace (hb_codepoint_t glyph_index) const
{
- _set_glyph_props (glyph_index);
+ _set_glyph_class (glyph_index);
buffer->cur().codepoint = glyph_index;
}
void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
unsigned int class_guess) const
{
- _set_glyph_props (glyph_index, class_guess, true);
+ _set_glyph_class (glyph_index, class_guess, true);
(void) buffer->replace_glyph (glyph_index);
}
void output_glyph_for_component (hb_codepoint_t glyph_index,
unsigned int class_guess) const
{
- _set_glyph_props (glyph_index, class_guess, false, true);
+ _set_glyph_class (glyph_index, class_guess, false, true);
(void) buffer->output_glyph (glyph_index);
}
};
@@ -933,7 +974,7 @@ static inline bool match_input (hb_ot_apply_context_t *c,
const HBUINT16 input[], /* Array of input values--start with second glyph */
match_func_t match_func,
const void *match_data,
- unsigned int *end_offset,
+ unsigned int *end_position,
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
unsigned int *p_total_component_count = nullptr)
{
@@ -986,7 +1027,12 @@ static inline bool match_input (hb_ot_apply_context_t *c,
match_positions[0] = buffer->idx;
for (unsigned int i = 1; i < count; i++)
{
- if (!skippy_iter.next ()) return_trace (false);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ *end_position = unsafe_to;
+ return_trace (false);
+ }
match_positions[i] = skippy_iter.idx;
@@ -1040,7 +1086,7 @@ static inline bool match_input (hb_ot_apply_context_t *c,
total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
}
- *end_offset = skippy_iter.idx - buffer->idx + 1;
+ *end_position = skippy_iter.idx + 1;
if (p_total_component_count)
*p_total_component_count = total_component_count;
@@ -1050,7 +1096,7 @@ static inline bool match_input (hb_ot_apply_context_t *c,
static inline bool ligate_input (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph */
const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
- unsigned int match_length,
+ unsigned int match_end,
hb_codepoint_t lig_glyph,
unsigned int total_component_count)
{
@@ -1058,7 +1104,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
hb_buffer_t *buffer = c->buffer;
- buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
+ buffer->merge_clusters (buffer->idx, match_end);
/* - If a base and one or more marks ligate, consider that as a base, NOT
* ligature, such that all following marks can still attach to it.
@@ -1175,11 +1221,16 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
skippy_iter.set_match_func (match_func, match_data, backtrack);
for (unsigned int i = 0; i < count; i++)
- if (!skippy_iter.prev ())
+ {
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ *match_start = unsafe_from;
return_trace (false);
+ }
+ }
*match_start = skippy_iter.idx;
-
return_trace (true);
}
@@ -1188,21 +1239,26 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
const HBUINT16 lookahead[],
match_func_t match_func,
const void *match_data,
- unsigned int offset,
+ 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 (c->buffer->idx + offset - 1, count);
+ skippy_iter.reset (start_index - 1, count);
skippy_iter.set_match_func (match_func, match_data, lookahead);
for (unsigned int i = 0; i < count; i++)
- if (!skippy_iter.next ())
+ {
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ *end_index = unsafe_to;
return_trace (false);
+ }
+ }
*end_index = skippy_iter.idx + 1;
-
return_trace (true);
}
@@ -1210,15 +1266,14 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
struct LookupRecord
{
- LookupRecord* copy (hb_serialize_context_t *c,
- const hb_map_t *lookup_map) const
+ bool serialize (hb_serialize_context_t *c,
+ const hb_map_t *lookup_map) const
{
TRACE_SERIALIZE (this);
auto *out = c->embed (*this);
- if (unlikely (!out)) return_trace (nullptr);
+ if (unlikely (!out)) return_trace (false);
- out->lookupListIndex = hb_map_get (lookup_map, lookupListIndex);
- return_trace (out);
+ return_trace (c->check_assign (out->lookupListIndex, lookup_map->get (lookupListIndex), HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -1235,6 +1290,24 @@ struct LookupRecord
DEFINE_SIZE_STATIC (4);
};
+static unsigned serialize_lookuprecord_array (hb_serialize_context_t *c,
+ const hb_array_t<const LookupRecord> lookupRecords,
+ const hb_map_t *lookup_map)
+{
+ unsigned count = 0;
+ for (const LookupRecord& r : lookupRecords)
+ {
+ if (!lookup_map->has (r.lookupListIndex))
+ continue;
+
+ if (!r.serialize (c, lookup_map))
+ return 0;
+
+ count++;
+ }
+ return count;
+}
+
enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 };
static void context_closure_recurse_lookups (hb_closure_context_t *c,
@@ -1252,22 +1325,23 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
unsigned seqIndex = lookupRecord[i].sequenceIndex;
if (seqIndex >= inputCount) continue;
- hb_set_t *pos_glyphs = nullptr;
+ bool has_pos_glyphs = false;
+ hb_set_t pos_glyphs;
if (hb_set_is_empty (covered_seq_indicies) || !hb_set_has (covered_seq_indicies, seqIndex))
{
- pos_glyphs = hb_set_create ();
+ has_pos_glyphs = true;
if (seqIndex == 0)
{
switch (context_format) {
case ContextFormat::SimpleContext:
- pos_glyphs->add (value);
+ pos_glyphs.add (value);
break;
case ContextFormat::ClassBasedContext:
- intersected_glyphs_func (c->cur_intersected_glyphs, data, value, pos_glyphs);
+ intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs);
break;
case ContextFormat::CoverageBasedContext:
- hb_set_set (pos_glyphs, c->cur_intersected_glyphs);
+ pos_glyphs.set (c->parent_active_glyphs ());
break;
}
}
@@ -1281,13 +1355,16 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
input_value = input[seqIndex - 1];
}
- intersected_glyphs_func (c->glyphs, input_data, input_value, pos_glyphs);
+ intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs);
}
}
- hb_set_add (covered_seq_indicies, seqIndex);
- if (pos_glyphs)
- c->push_cur_active_glyphs (pos_glyphs);
+ covered_seq_indicies->add (seqIndex);
+ if (has_pos_glyphs) {
+ c->push_cur_active_glyphs () = pos_glyphs;
+ } else {
+ c->push_cur_active_glyphs ().set (*c->glyphs);
+ }
unsigned endIndex = inputCount;
if (context_format == ContextFormat::CoverageBasedContext)
@@ -1295,10 +1372,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
c->recurse (lookupRecord[i].lookupListIndex, covered_seq_indicies, seqIndex, endIndex);
- if (pos_glyphs) {
- c->pop_cur_done_glyphs ();
- hb_set_destroy (pos_glyphs);
- }
+ c->pop_cur_done_glyphs ();
}
hb_set_destroy (covered_seq_indicies);
@@ -1313,15 +1387,13 @@ static inline void recurse_lookups (context_t *c,
c->recurse (lookupRecord[i].lookupListIndex);
}
-static inline bool apply_lookup (hb_ot_apply_context_t *c,
+static inline void apply_lookup (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph */
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
- unsigned int match_length)
+ unsigned int match_end)
{
- TRACE_APPLY (nullptr);
-
hb_buffer_t *buffer = c->buffer;
int end;
@@ -1329,7 +1401,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
* Adjust. */
{
unsigned int bl = buffer->backtrack_len ();
- end = bl + match_length;
+ end = bl + match_end - buffer->idx;
int delta = bl - buffer->idx;
/* Convert positions to new indexing. */
@@ -1343,9 +1415,10 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
if (idx >= count)
continue;
- /* Don't recurse to ourself at same position.
- * Note that this test is too naive, it doesn't catch longer loops. */
- if (unlikely (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index))
+ unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
+
+ /* This can happen if earlier recursed lookups deleted many entries. */
+ if (unlikely (match_positions[idx] >= orig_len))
continue;
if (unlikely (!buffer->move_to (match_positions[idx])))
@@ -1354,7 +1427,6 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
if (unlikely (buffer->max_ops <= 0))
break;
- unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
if (!c->recurse (lookupRecord[i].lookupListIndex))
continue;
@@ -1380,25 +1452,27 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
* NOT the one after it.
*
* - If buffer length was decreased by n, it does not necessarily
- * mean that n match positions where removed, as there might
- * have been marks and default-ignorables in the sequence. We
- * should instead drop match positions between current-position
- * and current-position + n instead. Though, am not sure which
- * one is better. Both cases have valid uses. Sigh.
+ * mean that n match positions where removed, as there recursed-to
+ * lookup might had a different LookupFlag. Here's a constructed
+ * case of that:
+ * https://github.com/harfbuzz/harfbuzz/discussions/3538
*
* It should be possible to construct tests for both of these cases.
*/
end += delta;
- if (end <= int (match_positions[idx]))
+ if (end < int (match_positions[idx]))
{
/* End might end up being smaller than match_positions[idx] if the recursed
- * lookup ended up removing many items, more than we have had matched.
- * Just never rewind end back and get out of here.
- * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
+ * lookup ended up removing many items.
+ * Just never rewind end beyond start of current position, since that is
+ * not possible in the recursed lookup. Also adjust delta as such.
+ *
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=659496
+ * https://github.com/harfbuzz/harfbuzz/issues/1611
+ */
+ delta += match_positions[idx] - end;
end = match_positions[idx];
- /* There can't be any further changes. */
- break;
}
unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
@@ -1410,7 +1484,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
}
else
{
- /* NOTE: delta is negative. */
+ /* NOTE: delta is non-positive. */
delta = hb_max (delta, (int) next - (int) count);
next -= delta;
}
@@ -1431,8 +1505,6 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
}
(void) buffer->move_to (end);
-
- return_trace (true);
}
@@ -1520,17 +1592,25 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
const LookupRecord lookupRecord[],
ContextApplyLookupContext &lookup_context)
{
- unsigned int match_length = 0;
- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
- return match_input (c,
- inputCount, input,
- lookup_context.funcs.match, lookup_context.match_data,
- &match_length, match_positions)
- && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
- apply_lookup (c,
- inputCount, match_positions,
- lookupCount, lookupRecord,
- match_length));
+ unsigned match_end = 0;
+ unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
+ if (match_input (c,
+ inputCount, input,
+ lookup_context.funcs.match, lookup_context.match_data,
+ &match_end, match_positions))
+ {
+ c->buffer->unsafe_to_break (c->buffer->idx, match_end);
+ apply_lookup (c,
+ inputCount, match_positions,
+ lookupCount, lookupRecord,
+ match_end);
+ return true;
+ }
+ else
+ {
+ c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
+ return false;
+ }
}
struct Rule
@@ -1605,8 +1685,6 @@ struct Rule
if (unlikely (!c->extend_min (out))) return_trace (false);
out->inputCount = inputCount;
- out->lookupCount = lookupCount;
-
const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
for (const auto org : input)
{
@@ -1617,17 +1695,9 @@ struct Rule
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
(inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
- for (unsigned i = 0; i < (unsigned) lookupCount; i++)
- {
- if (!lookup_map->has (lookupRecord[i].lookupListIndex))
- {
- out->lookupCount--;
- continue;
- }
- c->copy (lookupRecord[i], lookup_map);
- }
- return_trace (true);
+ unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (lookupCount), lookup_map);
+ return_trace (c->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
bool subset (hb_subset_context_t *c,
@@ -1635,9 +1705,8 @@ struct Rule
const hb_map_t *klass_map = nullptr) const
{
TRACE_SUBSET (this);
-
- const hb_array_t<const HBUINT16> input = inputZ.as_array ((inputCount ? inputCount - 1 : 0));
- if (!input.length) return_trace (false);
+ if (unlikely (!inputCount)) return_trace (false);
+ const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map;
if (!hb_all (input, mapping)) return_trace (false);
@@ -1752,10 +1821,10 @@ struct RuleSet
for (const Offset16To<Rule>& _ : rule)
{
if (!_) continue;
+ auto o_snap = c->serializer->snapshot ();
auto *o = out->rule.serialize_append (c->serializer);
if (unlikely (!o)) continue;
- auto o_snap = c->serializer->snapshot ();
if (!o->serialize_subset (c, _, this, lookup_map, klass_map))
{
out->rule.pop ();
@@ -1809,8 +1878,9 @@ struct ContextFormat1
void closure (hb_closure_context_t *c) const
{
- c->cur_intersected_glyphs->clear ();
- get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
+ hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
+ get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ cur_active_glyphs);
struct ContextClosureLookupContext lookup_context = {
{intersects_glyph, intersected_glyph},
@@ -1819,10 +1889,14 @@ struct ContextFormat1
};
+ hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
- | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_filter ([&] (hb_codepoint_t _) {
+ return c->previous_parent_active_glyphs ().has (_);
+ }, hb_first)
| hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const RuleSet&> (_.first, this+ruleSet[_.second]); })
| hb_apply ([&] (const hb_pair_t<unsigned, const RuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
;
+
+ c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@@ -1943,12 +2017,20 @@ struct ContextFormat2
&class_def
};
+ hb_set_t retained_coverage_glyphs;
+ (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
+
+ hb_set_t coverage_glyph_classes;
+ class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
+
+
return
+ hb_iter (ruleSet)
| hb_map (hb_add (this))
| hb_enumerate
| hb_map ([&] (const hb_pair_t<unsigned, const RuleSet &> p)
{ return class_def.intersects_class (glyphs, p.first) &&
+ coverage_glyph_classes.has (p.first) &&
p.second.intersects (glyphs, lookup_context); })
| hb_any
;
@@ -1962,8 +2044,9 @@ struct ContextFormat2
if (!(this+coverage).intersects (c->gl