summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2022-05-19 09:58:31 +0200
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2022-05-23 19:25:46 +0000
commitd88da0b2b0a8abaaa521bef864378fe1dbf86709 (patch)
tree4795f260c1ceaaeeb2cbe64f8314d604e0a7cbe7 /src/3rdparty/harfbuzz-ng
parent0d97723ee2778203af0cfd13599572110fb69dd5 (diff)
Update Harfbuzz to version 4.2.1
[ChangeLog][QtGui][Text] Updated the Harfbuzz code included with Qt to version 4.2.1. Pick-to: 6.2 6.3 Fixes: QTBUG-103603 Change-Id: I45fdde8fd0772e4470304c5f6f5a876666356d04 Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
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/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
188 files changed, 13697 insertions, 6081 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&amp;utm_medium=referral&amp;utm_content=harfbuzz/harfbuzz&amp;utm_campaign=Badge_Grade)
[![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
-[![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/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->glyphs))
return;
- 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);
const ClassDef &class_def = this+classDef;
@@ -1973,10 +2056,9 @@ struct ContextFormat2
&class_def
};
- return
+ hb_enumerate (ruleSet)
| hb_filter ([&] (unsigned _)
- { return class_def.intersects_class (c->cur_intersected_glyphs, _); },
+ { return class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
| hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<RuleSet>&> _)
{
@@ -1984,6 +2066,8 @@ struct ContextFormat2
rule_set.closure (c, _.first, lookup_context);
})
;
+
+ c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@@ -2069,9 +2153,16 @@ struct ContextFormat2
hb_map_t klass_map;
out->classDef.serialize_subset (c, classDef, this, &klass_map);
+ const hb_set_t* glyphset = c->plan->glyphset_gsub ();
+ hb_set_t retained_coverage_glyphs;
+ (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
+
+ hb_set_t coverage_glyph_classes;
+ (this+classDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
+
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
bool ret = true;
- int non_zero_index = 0, index = 0;
+ int non_zero_index = -1, index = 0;
for (const auto& _ : + hb_enumerate (ruleSet)
| hb_filter (klass_map, hb_first))
{
@@ -2082,13 +2173,14 @@ struct ContextFormat2
break;
}
- if (o->serialize_subset (c, _.second, this, lookup_map, &klass_map))
+ if (coverage_glyph_classes.has (_.first) &&
+ o->serialize_subset (c, _.second, this, lookup_map, &klass_map))
non_zero_index = index;
index++;
}
- if (!ret) return_trace (ret);
+ if (!ret || non_zero_index == -1) return_trace (false);
//prune empty trailing ruleSets
--index;
@@ -2148,8 +2240,10 @@ struct ContextFormat3
if (!(this+coverageZ[0]).intersects (c->glyphs))
return;
- c->cur_intersected_glyphs->clear ();
- get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
+ hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
+ get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ cur_active_glyphs);
+
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
struct ContextClosureLookupContext lookup_context = {
@@ -2161,6 +2255,8 @@ struct ContextFormat3
glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
lookupCount, lookupRecord,
0, lookup_context);
+
+ c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@@ -2226,7 +2322,6 @@ struct ContextFormat3
out->format = format;
out->glyphCount = glyphCount;
- out->lookupCount = lookupCount;
auto coverages = coverageZ.as_array (glyphCount);
@@ -2238,19 +2333,12 @@ struct ContextFormat3
if (!o->serialize_subset (c, offset, this)) return_trace (false);
}
- const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+ const UnsizedArrayOf<LookupRecord>& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount));
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
- for (unsigned i = 0; i < (unsigned) lookupCount; i++)
- {
- if (!lookup_map->has (lookupRecord[i].lookupListIndex))
- {
- out->lookupCount--;
- continue;
- }
- c->serializer->copy (lookupRecord[i], lookup_map);
- }
- return_trace (true);
+
+ unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (lookupCount), lookup_map);
+ return_trace (c->serializer->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2289,9 +2377,9 @@ struct Context
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 ());
}
}
@@ -2425,25 +2513,38 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
const LookupRecord lookupRecord[],
ChainContextApplyLookupContext &lookup_context)
{
- unsigned int start_index = 0, match_length = 0, end_index = 0;
- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
- return match_input (c,
- inputCount, input,
- lookup_context.funcs.match, lookup_context.match_data[1],
- &match_length, match_positions)
- && match_backtrack (c,
- backtrackCount, backtrack,
- lookup_context.funcs.match, lookup_context.match_data[0],
- &start_index)
- && match_lookahead (c,
- lookaheadCount, lookahead,
- lookup_context.funcs.match, lookup_context.match_data[2],
- match_length, &end_index)
- && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
- apply_lookup (c,
- inputCount, match_positions,
- lookupCount, lookupRecord,
- match_length));
+ unsigned end_index = c->buffer->idx;
+ 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[1],
+ &match_end, match_positions) && (end_index = match_end)
+ && match_lookahead (c,
+ lookaheadCount, lookahead,
+ lookup_context.funcs.match, lookup_context.match_data[2],
+ match_end, &end_index)))
+ {
+ c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
+ return false;
+ }
+
+ unsigned start_index = c->buffer->out_len;
+ if (!match_backtrack (c,
+ backtrackCount, backtrack,
+ lookup_context.funcs.match, lookup_context.match_data[0],
+ &start_index))
+ {
+ c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
+ return false;
+ }
+
+ c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
+ apply_lookup (c,
+ inputCount, match_positions,
+ lookupCount, lookupRecord,
+ match_end);
+ return true;
}
struct ChainRule
@@ -2539,15 +2640,15 @@ struct ChainRule
c->copy ((HBUINT16) g);
}
- ChainRule* copy (hb_serialize_context_t *c,
- const hb_map_t *lookup_map,
- const hb_map_t *backtrack_map,
- const hb_map_t *input_map = nullptr,
- const hb_map_t *lookahead_map = nullptr) const
+ bool serialize (hb_serialize_context_t *c,
+ const hb_map_t *lookup_map,
+ const hb_map_t *backtrack_map,
+ const hb_map_t *input_map = nullptr,
+ const hb_map_t *lookahead_map = nullptr) const
{
TRACE_SERIALIZE (this);
auto *out = c->start_embed (this);
- if (unlikely (!out)) return_trace (nullptr);
+ if (unlikely (!out)) return_trace (false);
const hb_map_t *mapping = backtrack_map;
serialize_array (c, backtrack.len, + backtrack.iter ()
@@ -2566,19 +2667,10 @@ struct ChainRule
const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
HBUINT16* lookupCount = c->embed (&(lookupRecord.len));
- if (!lookupCount) return_trace (nullptr);
+ if (!lookupCount) return_trace (false);
- for (unsigned i = 0; i < lookupRecord.len; i++)
- {
- if (!lookup_map->has (lookupRecord[i].lookupListIndex))
- {
- (*lookupCount)--;
- continue;
- }
- if (!c->copy (lookupRecord[i], lookup_map)) return_trace (nullptr);
- }
-
- return_trace (out);
+ unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (), lookup_map);
+ return_trace (c->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
bool subset (hb_subset_context_t *c,
@@ -2600,7 +2692,7 @@ struct ChainRule
!hb_all (lookahead, glyphset))
return_trace (false);
- copy (c->serializer, lookup_map, c->plan->glyph_map);
+ serialize (c->serializer, lookup_map, c->plan->glyph_map);
}
else
{
@@ -2609,7 +2701,7 @@ struct ChainRule
!hb_all (lookahead, lookahead_map))
return_trace (false);
- copy (c->serializer, lookup_map, backtrack_map, input_map, lookahead_map);
+ serialize (c->serializer, lookup_map, backtrack_map, input_map, lookahead_map);
}
return_trace (true);
@@ -2724,10 +2816,10 @@ struct ChainRuleSet
for (const Offset16To<ChainRule>& _ : 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,
backtrack_klass_map,
@@ -2784,8 +2876,9 @@ struct ChainContextFormat1
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 ChainContextClosureLookupContext lookup_context = {
{intersects_glyph, intersected_glyph},
@@ -2794,10 +2887,14 @@ struct ChainContextFormat1
};
+ 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 ChainRuleSet&> (_.first, this+ruleSet[_.second]); })
| hb_apply ([&] (const hb_pair_t<unsigned, const ChainRuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
;
+
+ c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@@ -2920,12 +3017,19 @@ struct ChainContextFormat2
&lookahead_class_def}
};
+ hb_set_t retained_coverage_glyphs;
+ (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
+
+ hb_set_t coverage_glyph_classes;
+ input_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 ChainRuleSet &> p)
{ return input_class_def.intersects_class (glyphs, p.first) &&
+ coverage_glyph_classes.has (p.first) &&
p.second.intersects (glyphs, lookup_context); })
| hb_any
;
@@ -2939,8 +3043,10 @@ struct ChainContextFormat2
if (!(this+coverage).intersects (c->glyphs))
return;
- c->cur_intersected_glyphs->clear ();
- get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
+ hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
+ get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ cur_active_glyphs);
+
const ClassDef &backtrack_class_def = this+backtrackClassDef;
const ClassDef &input_class_def = this+inputClassDef;
@@ -2954,10 +3060,9 @@ struct ChainContextFormat2
&lookahead_class_def}
};
- return
+ hb_enumerate (ruleSet)
| hb_filter ([&] (unsigned _)
- { return input_class_def.intersects_class (c->cur_intersected_glyphs, _); },
+ { return input_class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
| hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<ChainRuleSet>&> _)
{
@@ -2965,6 +3070,8 @@ struct ChainContextFormat2
chainrule_set.closure (c, _.first, lookup_context);
})
;
+
+ c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@@ -3080,13 +3187,19 @@ struct ChainContextFormat2
lookahead_klass_map)))
return_trace (false);
+ const hb_set_t* glyphset = c->plan->glyphset_gsub ();
+ hb_set_t retained_coverage_glyphs;
+ (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
+
+ hb_set_t coverage_glyph_classes;
+ (this+inputClassDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
+
int non_zero_index = -1, index = 0;
bool ret = true;
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
auto last_non_zero = c->serializer->snapshot ();
- for (const Offset16To<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
- | hb_filter (input_klass_map, hb_first)
- | hb_map (hb_second))
+ for (const auto& _ : + hb_enumerate (ruleSet)
+ | hb_filter (input_klass_map, hb_first))
{
auto *o = out->ruleSet.serialize_append (c->serializer);
if (unlikely (!o))
@@ -3094,7 +3207,8 @@ struct ChainContextFormat2
ret = false;
break;
}
- if (o->serialize_subset (c, _, this,
+ if (coverage_glyph_classes.has (_.first) &&
+ o->serialize_subset (c, _.second, this,
lookup_map,
&backtrack_klass_map,
&input_klass_map,
@@ -3107,7 +3221,7 @@ struct ChainContextFormat2
index++;
}
- if (!ret) return_trace (ret);
+ if (!ret || non_zero_index == -1) return_trace (false);
// prune empty trailing ruleSets
if (index > non_zero_index) {
@@ -3184,8 +3298,10 @@ struct ChainContextFormat3
if (!(this+input[0]).intersects (c->glyphs))
return;
- 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);
+
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
@@ -3200,6 +3316,8 @@ struct ChainContextFormat3
lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
lookup.len, lookup.arrayZ,
0, lookup_context);
+
+ c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@@ -3318,22 +3436,12 @@ struct ChainContextFormat3
const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
- hb_set_t lookup_indices;
- for (unsigned i = 0; i < (unsigned) lookupRecord.len; i++)
- if (lookup_map->has (lookupRecord[i].lookupListIndex))
- lookup_indices.add (i);
- HBUINT16 lookupCount;
- lookupCount = lookup_indices.get_population ();
- if (!c->serializer->copy (lookupCount)) return_trace (false);
+ HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookupRecord.len);
+ if (!lookupCount) return_trace (false);
- for (unsigned i : lookup_indices.iter ())
- {
- if (!c->serializer->copy (lookupRecord[i], lookup_map))
- return_trace (false);
- }
-
- return_trace (true);
+ unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (), lookup_map);
+ return_trace (c->serializer->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -3378,9 +3486,9 @@ struct ChainContext
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 ());
}
}
@@ -3409,7 +3517,7 @@ struct ExtensionFormat1
{
TRACE_DISPATCH (this, format);
if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
- return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), hb_forward<Ts> (ds)...));
+ return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), std::forward<Ts> (ds)...));
}
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
@@ -3489,7 +3597,7 @@ struct Extension
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 (u.format1.dispatch (c, hb_forward<Ts> (ds)...));
+ case 1: return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
}
}
@@ -3621,7 +3729,7 @@ struct GSUBGPOS
}
void prune_langsys (const hb_map_t *duplicate_feature_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_set_t *new_feature_indexes /* OUT */) const
{
hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
@@ -3678,57 +3786,72 @@ struct GSUBGPOS
const hb_set_t *feature_indices,
hb_map_t *duplicate_feature_map /* OUT */) const
{
+ if (feature_indices->is_empty ()) return;
+ hb_hashmap_t<hb_tag_t, hb_set_t *> unique_features;
//find out duplicate features after subset
- unsigned prev = 0xFFFFu;
for (unsigned i : feature_indices->iter ())
{
- if (prev == 0xFFFFu)
+ hb_tag_t t = get_feature_tag (i);
+ if (t == HB_MAP_VALUE_INVALID) continue;
+ if (!unique_features.has (t))
{
+ hb_set_t* indices = hb_set_create ();
+ if (unlikely (indices == hb_set_get_empty () ||
+ !unique_features.set (t, indices)))
+ {
+ hb_set_destroy (indices);
+ for (auto _ : unique_features.iter ())
+ hb_set_destroy (_.second);
+ return;
+ }
+ if (unique_features.get (t))
+ unique_features.get (t)->add (i);
duplicate_feature_map->set (i, i);
- prev = i;
continue;
}
- hb_tag_t t = get_feature_tag (i);
- hb_tag_t prev_t = get_feature_tag (prev);
- if (t != prev_t)
+ bool found = false;
+
+ hb_set_t* same_tag_features = unique_features.get (t);
+ for (unsigned other_f_index : same_tag_features->iter ())
{
- duplicate_feature_map->set (i, i);
- prev = i;
- continue;
- }
+ const Feature& f = get_feature (i);
+ const Feature& other_f = get_feature (other_f_index);
- const Feature& f = get_feature (i);
- const Feature& prev_f = get_feature (prev);
+ auto f_iter =
+ + hb_iter (f.lookupIndex)
+ | hb_filter (lookup_indices)
+ ;
- auto f_iter =
- + hb_iter (f.lookupIndex)
- | hb_filter (lookup_indices)
- ;
+ auto other_f_iter =
+ + hb_iter (other_f.lookupIndex)
+ | hb_filter (lookup_indices)
+ ;
- auto prev_iter =
- + hb_iter (prev_f.lookupIndex)
- | hb_filter (lookup_indices)
- ;
+ bool is_equal = true;
+ for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
+ {
+ unsigned a = *f_iter;
+ unsigned b = *other_f_iter;
+ if (a != b) { is_equal = false; break; }
+ }
- if (f_iter.len () != prev_iter.len ())
- {
- duplicate_feature_map->set (i, i);
- prev = i;
- continue;
- }
+ if (is_equal == false || f_iter || other_f_iter) continue;
- bool is_equal = true;
- for (auto _ : + hb_zip (f_iter, prev_iter))
- if (_.first != _.second) { is_equal = false; break; }
+ found = true;
+ duplicate_feature_map->set (i, other_f_index);
+ break;
+ }
- if (is_equal == true) duplicate_feature_map->set (i, prev);
- else
+ if (found == false)
{
+ same_tag_features->add (i);
duplicate_feature_map->set (i, i);
- prev = i;
}
}
+
+ for (auto _ : unique_features.iter ())
+ hb_set_destroy (_.second);
}
void prune_features (const hb_map_t *lookup_indices, /* IN */
@@ -3759,8 +3882,12 @@ struct GSUBGPOS
// http://lists.freedesktop.org/archives/harfbuzz/2012-November/002660.html
continue;
- if (f.featureParams.is_null ()
- && !f.intersects_lookup_indexes (lookup_indices)
+
+ if (!f.featureParams.is_null () &&
+ tag == HB_TAG ('s', 'i', 'z', 'e'))
+ continue;
+
+ if (!f.intersects_lookup_indexes (lookup_indices)
#ifndef HB_NO_VAR
&& !alternate_feature_indices.has (i)
#endif
@@ -3798,7 +3925,7 @@ struct GSUBGPOS
template <typename T>
struct accelerator_t
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{
this->table = hb_sanitize_context_t ().reference_table<T> (face);
if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
@@ -3820,8 +3947,7 @@ struct GSUBGPOS
for (unsigned int i = 0; i < this->lookup_count; i++)
this->accels[i].init (table->get_lookup (i));
}
-
- void fini ()
+ ~accelerator_t ()
{
for (unsigned int i = 0; i < this->lookup_count; i++)
this->accels[i].fini ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh
index 3b2293dff0..a1c125b11b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh
@@ -136,7 +136,7 @@ struct JstfLangSys : List16OfOffset16To<JstfPriority>
* ExtenderGlyphs -- Extender Glyph Table
*/
-typedef SortedArray16Of<HBGlyphID> ExtenderGlyphs;
+typedef SortedArray16Of<HBGlyphID16> ExtenderGlyphs;
/*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
index 0454af2063..f4ea21a4f9 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
@@ -54,6 +54,8 @@
#include "hb-aat-layout-morx-table.hh"
#include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise.
+using OT::Layout::GSUB::GSUB;
+
/**
* SECTION:hb-ot-layout
* @title: hb-ot-layout
@@ -361,6 +363,13 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
* Fetches a list of the caret positions defined for a ligature glyph in the GDEF
* table of the font. The list returned will begin at the offset provided.
*
+ * Note that a ligature that is formed from n characters will have n-1
+ * caret positions. The first character is not represented in the array,
+ * since its caret position is the glyph position.
+ *
+ * The positions returned by this function are 'unshaped', and will have to
+ * be fixed up for kerning that may be applied to the ligature glyph.
+ *
* Return value: Total number of ligature caret positions for @glyph.
*
**/
@@ -382,7 +391,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
*/
bool
-OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
+GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
hb_face_t *face) const
{
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
@@ -613,7 +622,7 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
* hb_ot_layout_table_find_feature:
* @face: #hb_face_t to work upon
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
- * @feature_tag: The #hb_tag_t og the requested feature tag
+ * @feature_tag: The #hb_tag_t of the requested feature tag
* @feature_index: (out): The index of the requested feature
*
* Fetches the index for a given feature tag in the specified face's GSUB table
@@ -688,8 +697,8 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
*
* Return value: %true if the language tag is found, %false otherwise
*
- * Since: ??
- * Deprecated: ??
+ * Since: 0.6.0
+ * Deprecated: 2.0.0
**/
hb_bool_t
hb_ot_layout_script_find_language (hb_face_t *face,
@@ -717,10 +726,14 @@ hb_ot_layout_script_find_language (hb_face_t *face,
* @language_tags: The array of language tags
* @language_index: (out): The index of the requested language
*
- * Fetches the index of a given language tag in the specified face's GSUB table
- * or GPOS table, underneath the specified script index.
+ * Fetches the index of the first language tag fom @language_tags that is present
+ * in the specified face's GSUB or GPOS table, underneath the specified script
+ * index.
*
- * Return value: %true if the language tag is found, %false otherwise
+ * If none of the given language tags is found, %false is returned and
+ * @language_index is set to the default language index.
+ *
+ * Return value: %true if one of the given language tags is found, %false otherwise
*
* Since: 2.0.0
**/
@@ -746,7 +759,8 @@ hb_ot_layout_script_select_language (hb_face_t *face,
if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
return false;
- if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
+ if (language_index)
+ *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
return false;
}
@@ -994,7 +1008,7 @@ struct hb_collect_features_context_t
hb_collect_features_context_t (hb_face_t *face,
hb_tag_t table_tag,
hb_set_t *feature_indices_,
- const hb_tag_t *features)
+ const hb_tag_t *features)
: g (get_gsubgpos_table (face, table_tag)),
feature_indices (feature_indices_),
@@ -1013,24 +1027,15 @@ struct hb_collect_features_context_t
}
has_feature_filter = true;
+ hb_set_t features_set;
for (; *features; features++)
- {
- hb_tag_t tag = *features;
- unsigned index;
- g.find_feature_index (tag, &index);
- if (index == OT::Index::NOT_FOUND_INDEX) continue;
+ features_set.add (*features);
- feature_indices_filter.add(index);
- for (int i = (int) index - 1; i >= 0; i--)
- {
- if (g.get_feature_tag (i) != tag) break;
- feature_indices_filter.add(i);
- }
- for (unsigned i = index + 1; i < g.get_feature_count (); i++)
- {
- if (g.get_feature_tag (i) != tag) break;
- feature_indices_filter.add(i);
- }
+ for (unsigned i = 0; i < g.get_feature_count (); i++)
+ {
+ hb_tag_t tag = g.get_feature_tag (i);
+ if (features_set.has (tag))
+ feature_indices_filter.add(i);
}
}
@@ -1495,10 +1500,9 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
unsigned int lookup_index,
hb_set_t *glyphs /* OUT */)
{
- hb_set_t cur_intersected_glyphs;
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
- OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
+ hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
@@ -1524,16 +1528,16 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
const hb_set_t *lookups,
hb_set_t *glyphs /* OUT */)
{
- hb_set_t cur_intersected_glyphs;
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
- OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
- const OT::GSUB& gsub = *face->table.GSUB->table;
+ hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
+ const GSUB& gsub = *face->table.GSUB->table;
unsigned int iteration_count = 0;
unsigned int glyphs_length;
do
{
+ c.reset_lookup_visit_count ();
glyphs_length = glyphs->get_population ();
if (lookups)
{
@@ -1806,7 +1810,7 @@ struct GSUBProxy
table (*face->table.GSUB->table),
accels (face->table.GSUB->accels) {}
- const OT::GSUB &table;
+ const GSUB &table;
const OT::hb_ot_layout_lookup_accelerator_t *accels;
};
@@ -1893,7 +1897,7 @@ apply_string (OT::hb_ot_apply_context_t *c,
apply_forward (c, accel);
if (!Proxy::inplace)
- buffer->swap_buffers ();
+ buffer->sync ();
}
else
{
@@ -1927,6 +1931,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
c.set_random (lookups[table_index][i].random);
+ c.set_per_syllable (lookups[table_index][i].per_syllable);
apply_string<Proxy> (&c,
proxy.table.get_lookup (lookup_index),
@@ -1965,13 +1970,84 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
#ifndef HB_NO_BASE
/**
+ * hb_ot_layout_get_horizontal_baseline_tag_for_script:
+ * @script: a script tag.
+ *
+ * Fetches the dominant horizontal baseline tag used by @script.
+ *
+ * Return value: dominant baseline tag for the @script.
+ *
+ * Since: 4.0.0
+ **/
+hb_ot_layout_baseline_tag_t
+hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script)
+{
+ /* Keep in sync with hb_ot_layout_get_baseline_with_fallback */
+ switch ((int) script)
+ {
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_BENGALI:
+ case HB_SCRIPT_DEVANAGARI:
+ case HB_SCRIPT_GUJARATI:
+ case HB_SCRIPT_GURMUKHI:
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN:
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU:
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_SYLOTI_NAGRI:
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHAGS_PA:
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_MEETEI_MAYEK:
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_SHARADA:
+ case HB_SCRIPT_TAKRI:
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MODI:
+ case HB_SCRIPT_SIDDHAM:
+ case HB_SCRIPT_TIRHUTA:
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_MARCHEN:
+ case HB_SCRIPT_NEWA:
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_SOYOMBO:
+ case HB_SCRIPT_ZANABAZAR_SQUARE:
+ /* Unicode-11.0 additions */
+ case HB_SCRIPT_DOGRA:
+ case HB_SCRIPT_GUNJALA_GONDI:
+ /* Unicode-12.0 additions */
+ case HB_SCRIPT_NANDINAGARI:
+ return HB_OT_LAYOUT_BASELINE_TAG_HANGING;
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_HANGUL:
+ case HB_SCRIPT_HAN:
+ case HB_SCRIPT_HIRAGANA:
+ case HB_SCRIPT_KATAKANA:
+ /* Unicode-3.0 additions */
+ case HB_SCRIPT_BOPOMOFO:
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_TANGUT:
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_NUSHU:
+ /* Unicode-13.0 additions */
+ case HB_SCRIPT_KHITAN_SMALL_SCRIPT:
+ return HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT;
+
+ default:
+ return HB_OT_LAYOUT_BASELINE_TAG_ROMAN;
+ }
+}
+
+/**
* hb_ot_layout_get_baseline:
* @font: a font
* @baseline_tag: a baseline tag
* @direction: text direction.
* @script_tag: script tag.
* @language_tag: language tag, currently unused.
- * @coord: (out): baseline value if found.
+ * @coord: (out) (nullable): baseline value if found.
*
* Fetches a baseline value from the face.
*
@@ -1987,13 +2063,231 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */)
{
- bool result = font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord);
+ return font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord);
+}
- if (result && coord)
- *coord = HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (*coord) : font->em_scale_x (*coord);
+/**
+ * hb_ot_layout_get_baseline_with_fallback:
+ * @font: a font
+ * @baseline_tag: a baseline tag
+ * @direction: text direction.
+ * @script_tag: script tag.
+ * @language_tag: language tag, currently unused.
+ * @coord: (out): baseline value if found.
+ *
+ * Fetches a baseline value from the face, and synthesizes
+ * it if the font does not have it.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_tag_t script_tag,
+ hb_tag_t language_tag,
+ hb_position_t *coord /* OUT */)
+{
+ if (hb_ot_layout_get_baseline (font,
+ baseline_tag,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ return;
- return result;
+ /* Synthesize missing baselines.
+ * See https://www.w3.org/TR/css-inline-3/#baseline-synthesis-fonts
+ */
+ switch (baseline_tag)
+ {
+ case HB_OT_LAYOUT_BASELINE_TAG_ROMAN:
+ *coord = 0; // FIXME origin ?
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_MATH:
+ {
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+ if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
+ (hb_font_get_nominal_glyph (font, 0x2212u, &glyph) ||
+ hb_font_get_nominal_glyph (font, '-', &glyph)) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ {
+ *coord = extents.y_bearing + extents.height / 2;
+ }
+ else
+ {
+ hb_position_t x_height = font->y_scale / 2;
+#ifndef HB_NO_METRICS
+ hb_ot_metrics_get_position_with_fallback (font, HB_OT_METRICS_TAG_X_HEIGHT, &x_height);
+#endif
+ *coord = x_height / 2;
+ }
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT:
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT:
+ {
+ hb_position_t embox_top, embox_bottom;
+
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_bottom);
+
+ if (baseline_tag == HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT)
+ *coord = embox_top + (embox_bottom - embox_top) / 10;
+ else
+ *coord = embox_bottom + (embox_top - embox_bottom) / 10;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT:
+ if (hb_ot_layout_get_baseline (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ *coord += HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
+ else
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, direction, &font_extents);
+ *coord = font_extents.ascender;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT:
+ if (hb_ot_layout_get_baseline (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ *coord -= HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
+ else
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, direction, &font_extents);
+ *coord = font_extents.descender;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_HANGING:
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ {
+ hb_codepoint_t ch;
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+
+ /* Keep in sync with hb_ot_layout_get_horizontal_baseline_for_script */
+ switch ((int) script_tag)
+ {
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_BENGALI: ch = 0x0995u; break;
+ case HB_SCRIPT_DEVANAGARI: ch = 0x0915u; break;
+ case HB_SCRIPT_GUJARATI: ch = 0x0a95u; break;
+ case HB_SCRIPT_GURMUKHI: ch = 0x0a15u; break;
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN: ch = 0x0f40u; break;
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU: ch = 0x1901u; break;
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_SYLOTI_NAGRI: ch = 0xa807u; break;
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHAGS_PA: ch = 0xa840u; break;
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_MEETEI_MAYEK: ch = 0xabc0u; break;
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_SHARADA: ch = 0x11191u; break;
+ case HB_SCRIPT_TAKRI: ch = 0x1168cu; break;
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MODI: ch = 0x1160eu;break;
+ case HB_SCRIPT_SIDDHAM: ch = 0x11590u; break;
+ case HB_SCRIPT_TIRHUTA: ch = 0x1148fu; break;
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_MARCHEN: ch = 0x11c72u; break;
+ case HB_SCRIPT_NEWA: ch = 0x1140eu; break;
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_SOYOMBO: ch = 0x11a5cu; break;
+ case HB_SCRIPT_ZANABAZAR_SQUARE: ch = 0x11a0bu; break;
+ /* Unicode-11.0 additions */
+ case HB_SCRIPT_DOGRA: ch = 0x1180au; break;
+ case HB_SCRIPT_GUNJALA_GONDI: ch = 0x11d6cu; break;
+ /* Unicode-12.0 additions */
+ case HB_SCRIPT_NANDINAGARI: ch = 0x119b0u; break;
+ default: ch = 0; break;
+ }
+
+ if (ch &&
+ hb_font_get_nominal_glyph (font, ch, &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *coord = extents.y_bearing;
+ else
+ *coord = font->y_scale * 6 / 10; // FIXME makes assumptions about origin
+ }
+ else
+ *coord = font->x_scale * 6 / 10; // FIXME makes assumptions about origin
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL:
+ {
+ hb_position_t top, bottom;
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
+ *coord = (top + bottom) / 2;
+
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL:
+ {
+ hb_position_t top, bottom;
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
+ *coord = (top + bottom) / 2;
+
+ }
+ break;
+
+ case _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE:
+ default:
+ *coord = 0;
+ break;
+ }
}
+
#endif
@@ -2011,14 +2305,14 @@ struct hb_get_glyph_alternates_dispatch_t :
private:
template <typename T, typename ...Ts> auto
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
- ( obj.get_glyph_alternates (hb_forward<Ts> (ds)...) )
+ ( obj.get_glyph_alternates (std::forward<Ts> (ds)...) )
template <typename T, typename ...Ts> auto
_dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
( default_return_value () )
public:
template <typename T, typename ...Ts> auto
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
- ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
+ ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
};
/**
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
index d47ba0fc92..4edddd9e0d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
@@ -332,31 +332,6 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
hb_set_t *glyphs_after, /* OUT. May be NULL */
hb_set_t *glyphs_output /* OUT. May be NULL */);
-#ifdef HB_NOT_IMPLEMENTED
-typedef struct
-{
- const hb_codepoint_t *before,
- unsigned int before_length,
- const hb_codepoint_t *input,
- unsigned int input_length,
- const hb_codepoint_t *after,
- unsigned int after_length,
-} hb_ot_layout_glyph_sequence_t;
-
-typedef hb_bool_t
-(*hb_ot_layout_glyph_sequence_func_t) (hb_font_t *font,
- hb_tag_t table_tag,
- unsigned int lookup_index,
- const hb_ot_layout_glyph_sequence_t *sequence,
- void *user_data);
-
-HB_EXTERN void
-Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face,
- hb_tag_t table_tag,
- unsigned int lookup_index,
- hb_ot_layout_glyph_sequence_func_t callback,
- void *user_data);
-#endif
/* Variations support */
@@ -411,19 +386,6 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs);
-#ifdef HB_NOT_IMPLEMENTED
-/* Note: You better have GDEF when using this API, or marks won't do much. */
-HB_EXTERN hb_bool_t
-Xhb_ot_layout_lookup_substitute (hb_font_t *font,
- unsigned int lookup_index,
- const hb_ot_layout_glyph_sequence_t *sequence,
- unsigned int out_size,
- hb_codepoint_t *glyphs_out, /* OUT */
- unsigned int *clusters_out, /* OUT */
- unsigned int *out_length /* OUT */);
-#endif
-
-
/*
* GPOS
*/
@@ -431,15 +393,6 @@ Xhb_ot_layout_lookup_substitute (hb_font_t *font,
HB_EXTERN hb_bool_t
hb_ot_layout_has_positioning (hb_face_t *face);
-#ifdef HB_NOT_IMPLEMENTED
-/* Note: You better have GDEF when using this API, or marks won't do much. */
-HB_EXTERN hb_bool_t
-Xhb_ot_layout_lookup_position (hb_font_t *font,
- unsigned int lookup_index,
- const hb_ot_layout_glyph_sequence_t *sequence,
- hb_glyph_position_t *positions /* IN / OUT */);
-#endif
-
/* Optical 'size' feature info. Returns true if found.
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
HB_EXTERN hb_bool_t
@@ -487,9 +440,11 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT: Ideographic character face top or right edge,
* if the direction is horizontal or vertical, respectively.
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL: The center of the ideographic character face. Since: 4.0.0
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT: Ideographic em-box bottom or left edge,
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT: Ideographic em-box top or right edge baseline,
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL: The center of the ideographic em-box. Since: 4.0.0
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered.
* In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered.
@@ -503,14 +458,19 @@ typedef enum {
HB_OT_LAYOUT_BASELINE_TAG_HANGING = HB_TAG ('h','a','n','g'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT = HB_TAG ('i','c','f','b'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT = HB_TAG ('i','c','f','t'),
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL = HB_TAG ('I','c','f','c'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT = HB_TAG ('i','d','e','o'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT = HB_TAG ('i','d','t','p'),
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL = HB_TAG ('I','d','c','e'),
HB_OT_LAYOUT_BASELINE_TAG_MATH = HB_TAG ('m','a','t','h'),
/*< private >*/
_HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_layout_baseline_tag_t;
+HB_EXTERN hb_ot_layout_baseline_tag_t
+hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script);
+
HB_EXTERN hb_bool_t
hb_ot_layout_get_baseline (hb_font_t *font,
hb_ot_layout_baseline_tag_t baseline_tag,
@@ -519,6 +479,14 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */);
+HB_EXTERN void
+hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_tag_t script_tag,
+ hb_tag_t language_tag,
+ hb_position_t *coord /* OUT */);
+
HB_END_DECLS
#endif /* HB_OT_LAYOUT_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
index bcc014ee98..75bba0bc50 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
@@ -108,13 +108,17 @@ hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
namespace OT {
struct hb_ot_apply_context_t;
- struct SubstLookup;
struct hb_ot_layout_lookup_accelerator_t;
+namespace Layout {
+namespace GSUB {
+ struct SubstLookup;
+}
+}
}
HB_INTERNAL void
hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
- const OT::SubstLookup &lookup,
+ const OT::Layout::GSUB::SubstLookup &lookup,
const OT::hb_ot_layout_lookup_accelerator_t &accel);
@@ -168,17 +172,6 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
return start;
}
-static inline void
-_hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- hb_glyph_info_t *info = buffer->info;
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- info[i].syllable() = 0;
-}
-
/* unicode_props */
@@ -187,7 +180,7 @@ _hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
* - General_Category: 5 bits.
* - A bit each for:
* * Is it Default_Ignorable(); we have a modified Default_Ignorable().
- * * Whether it's one of the three Mongolian Free Variation Selectors,
+ * * Whether it's one of the four Mongolian Free Variation Selectors,
* CGJ, or other characters that are hidden but should not be ignored
* like most other Default_Ignorable()s do during matching.
* * Whether it's a grapheme continuation.
@@ -202,7 +195,7 @@ _hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
enum hb_unicode_props_flags_t {
UPROPS_MASK_GEN_CAT = 0x001Fu,
UPROPS_MASK_IGNORABLE = 0x0020u,
- UPROPS_MASK_HIDDEN = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, or TAG characters */
+ UPROPS_MASK_HIDDEN = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters */
UPROPS_MASK_CONTINUATION=0x0080u,
/* If GEN_CAT=FORMAT, top byte masks: */
@@ -236,7 +229,7 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
* FVSes are GC=Mn, we have use a separate bit to remember them.
* Fixes:
* https://github.com/harfbuzz/harfbuzz/issues/234 */
- else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
+ else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x180Bu, 0x180Du, 0x180Fu, 0x180Fu))) props |= UPROPS_MASK_HIDDEN;
/* TAG characters need similar treatment. Fixes:
* https://github.com/harfbuzz/harfbuzz/issues/463 */
else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
@@ -350,24 +343,20 @@ _hb_glyph_info_is_continuation (const hb_glyph_info_t *info)
{
return info->unicode_props() & UPROPS_MASK_CONTINUATION;
}
-/* Loop over grapheme. Based on foreach_cluster(). */
-#define foreach_grapheme(buffer, start, end) \
- for (unsigned int \
- _count = buffer->len, \
- start = 0, end = _count ? _hb_next_grapheme (buffer, 0) : 0; \
- start < _count; \
- start = end, end = _hb_next_grapheme (buffer, start))
-static inline unsigned int
-_hb_next_grapheme (hb_buffer_t *buffer, unsigned int start)
-{
- hb_glyph_info_t *info = buffer->info;
- unsigned int count = buffer->len;
+static inline bool
+_hb_grapheme_group_func (const hb_glyph_info_t& a HB_UNUSED,
+ const hb_glyph_info_t& b)
+{ return _hb_glyph_info_is_continuation (&b); }
- while (++start < count && _hb_glyph_info_is_continuation (&info[start]))
- ;
+#define foreach_grapheme(buffer, start, end) \
+ foreach_group (buffer, start, end, _hb_grapheme_group_func)
- return start;
+static inline void
+_hb_ot_layout_reverse_graphemes (hb_buffer_t *buffer)
+{
+ buffer->reverse_groups (_hb_grapheme_group_func,
+ buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
}
static inline bool
@@ -486,7 +475,8 @@ _hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
}
static inline uint8_t
-_hb_allocate_lig_id (hb_buffer_t *buffer) {
+_hb_allocate_lig_id (hb_buffer_t *buffer)
+{
uint8_t lig_id = buffer->next_serial () & 0x07;
if (unlikely (!lig_id))
lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
index 12ceea5785..f085c78ff8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
@@ -117,7 +117,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
hb_mask_t mask,
bool auto_zwnj,
bool auto_zwj,
- bool random)
+ bool random,
+ bool per_syllable)
{
unsigned int lookup_indices[32];
unsigned int offset, len;
@@ -145,6 +146,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
lookup->auto_zwnj = auto_zwnj;
lookup->auto_zwj = auto_zwj;
lookup->random = random;
+ lookup->per_syllable = per_syllable;
}
offset += len;
@@ -277,6 +279,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ);
map->auto_zwj = !(info->flags & F_MANUAL_ZWJ);
map->random = !!(info->flags & F_RANDOM);
+ map->per_syllable = !!(info->flags & F_PER_SYLLABLE);
if ((info->flags & F_GLOBAL) && info->max_value == 1) {
/* Uses the global bit */
map->shift = global_bit_shift;
@@ -319,7 +322,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
m.features[i].mask,
m.features[i].auto_zwnj,
m.features[i].auto_zwj,
- m.features[i].random);
+ m.features[i].random,
+ m.features[i].per_syllable);
/* Sort lookups and merge duplicates */
if (last_num_lookups < m.lookups[table_index].length)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh
index 5f2afae281..f1cbf752fc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh
@@ -56,6 +56,7 @@ struct hb_ot_map_t
unsigned int auto_zwnj : 1;
unsigned int auto_zwj : 1;
unsigned int random : 1;
+ unsigned int per_syllable : 1;
int cmp (const hb_tag_t tag_) const
{ return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
@@ -66,6 +67,7 @@ struct hb_ot_map_t
unsigned short auto_zwnj : 1;
unsigned short auto_zwj : 1;
unsigned short random : 1;
+ unsigned short per_syllable : 1;
hb_mask_t mask;
HB_INTERNAL static int cmp (const void *pa, const void *pb)
@@ -183,7 +185,8 @@ enum hb_ot_map_feature_flags_t
F_GLOBAL_MANUAL_JOINERS= F_GLOBAL | F_MANUAL_JOINERS,
F_GLOBAL_HAS_FALLBACK = F_GLOBAL | F_HAS_FALLBACK,
F_GLOBAL_SEARCH = 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */
- F_RANDOM = 0x0020u /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
+ F_RANDOM = 0x0020u, /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
+ F_PER_SYLLABLE = 0x0040u /* Contain lookup application to within syllable. */
};
HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
@@ -237,7 +240,8 @@ struct hb_ot_map_builder_t
hb_mask_t mask,
bool auto_zwnj = true,
bool auto_zwj = true,
- bool random = false);
+ bool random = false,
+ bool per_syllable = false);
struct feature_info_t {
hb_tag_t tag;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
index 5916ad29f2..d834d94371 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
@@ -41,6 +41,16 @@ struct MathValueRecord
hb_position_t get_y_value (hb_font_t *font, const void *base) const
{ return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
+ MathValueRecord* copy (hb_serialize_context_t *c, const void *base) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+ out->deviceTable.serialize_copy (c, deviceTable, base, 0, hb_serialize_context_t::Head);
+
+ return_trace (out);
+ }
+
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -59,6 +69,29 @@ struct MathValueRecord
struct MathConstants
{
+ MathConstants* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->start_embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2);
+ if (unlikely (!p)) return_trace (nullptr);
+ memcpy (p, percentScaleDown, HBINT16::static_size * 2);
+
+ HBUINT16 *m = c->allocate_size<HBUINT16> (HBUINT16::static_size * 2);
+ if (unlikely (!m)) return_trace (nullptr);
+ memcpy (m, minHeight, HBUINT16::static_size * 2);
+
+ unsigned count = ARRAY_LENGTH (mathValueRecords);
+ for (unsigned i = 0; i < count; i++)
+ if (!c->copy (mathValueRecords[i], this))
+ return_trace (nullptr);
+
+ if (!c->embed (radicalDegreeBottomRaisePercent)) return_trace (nullptr);
+ return_trace (out);
+ }
+
bool sanitize_math_value_records (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -165,6 +198,28 @@ struct MathConstants
struct MathItalicsCorrectionInfo
{
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, italicsCorrection)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (serialize_math_record_array (c->serializer, out->italicsCorrection, 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 (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -196,6 +251,28 @@ struct MathItalicsCorrectionInfo
struct MathTopAccentAttachment
{
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+topAccentCoverage, topAccentAttachment)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (serialize_math_record_array (c->serializer, out->topAccentAttachment, this), hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ out->topAccentCoverage.serialize_serialize (c->serializer, new_coverage.iter ());
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -229,6 +306,22 @@ struct MathTopAccentAttachment
struct MathKern
{
+ MathKern* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->start_embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ if (unlikely (!c->embed (heightCount))) return_trace (nullptr);
+
+ unsigned count = 2 * heightCount + 1;
+ for (unsigned i = 0; i < count; i++)
+ if (!c->copy (mathValueRecordsZ.arrayZ[i], this))
+ return_trace (nullptr);
+
+ return_trace (out);
+ }
+
bool sanitize_math_value_records (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -276,6 +369,37 @@ struct MathKern
return kernValue[i].get_x_value (font, this);
}
+ unsigned int get_entries (unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font) const
+ {
+ const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ;
+ const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
+ const unsigned int entriesCount = heightCount + 1;
+
+ if (entries_count)
+ {
+ unsigned int start = hb_min (start_offset, entriesCount);
+ unsigned int end = hb_min (start + *entries_count, entriesCount);
+ *entries_count = end - start;
+
+ for (unsigned int i = 0; i < *entries_count; i++) {
+ unsigned int j = start + i;
+
+ hb_position_t max_height;
+ if (j == heightCount) {
+ max_height = INT32_MAX;
+ } else {
+ max_height = correctionHeight[j].get_y_value (font, this);
+ }
+
+ kern_entries[i] = {max_height, kernValue[j].get_x_value (font, this)};
+ }
+ }
+ return entriesCount;
+ }
+
protected:
HBUINT16 heightCount;
UnsizedArrayOf<MathValueRecord>
@@ -295,6 +419,19 @@ struct MathKern
struct MathKernInfoRecord
{
+ MathKernInfoRecord* copy (hb_serialize_context_t *c, const void *base) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ unsigned count = ARRAY_LENGTH (mathKern);
+ for (unsigned i = 0; i < count; i++)
+ out->mathKern[i].serialize_copy (c, mathKern[i], base, 0, hb_serialize_context_t::Head);
+
+ return_trace (out);
+ }
+
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -317,6 +454,24 @@ struct MathKernInfoRecord
return (base+mathKern[idx]).get_value (correction_height, font);
}
+ unsigned int get_kernings (hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font,
+ const void *base) const
+ {
+ unsigned int idx = kern;
+ if (unlikely (idx >= ARRAY_LENGTH (mathKern)) || !mathKern[idx]) {
+ if (entries_count) *entries_count = 0;
+ return 0;
+ }
+ return (base+mathKern[idx]).get_entries (start_offset,
+ entries_count,
+ kern_entries,
+ font);
+ }
+
protected:
/* Offset to MathKern table for each corner -
* from the beginning of MathKernInfo table. May be NULL. */
@@ -328,6 +483,28 @@ struct MathKernInfoRecord
struct MathKernInfo
{
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+mathKernCoverage, mathKernInfoRecords)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (serialize_math_record_array (c->serializer, out->mathKernInfoRecords, this), hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ out->mathKernCoverage.serialize_serialize (c->serializer, new_coverage.iter ());
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -345,6 +522,22 @@ struct MathKernInfo
return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
}
+ unsigned int get_kernings (hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font) const
+ {
+ unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
+ return mathKernInfoRecords[index].get_kernings (kern,
+ start_offset,
+ entries_count,
+ kern_entries,
+ font,
+ this);
+ }
+
protected:
Offset16To<Coverage>
mathKernCoverage;
@@ -365,6 +558,31 @@ struct MathKernInfo
struct MathGlyphInfo
{
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ out->mathItalicsCorrectionInfo.serialize_subset (c, mathItalicsCorrectionInfo, this);
+ out->mathTopAccentAttachment.serialize_subset (c, mathTopAccentAttachment, this);
+
+ const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (this+extendedShapeCoverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (it) out->extendedShapeCoverage.serialize_serialize (c->serializer, it);
+ else out->extendedShapeCoverage = 0;
+
+ out->mathKernInfo.serialize_subset (c, mathKernInfo, this);
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -392,6 +610,19 @@ struct MathGlyphInfo
hb_font_t *font) const
{ return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
+ hb_position_t get_kernings (hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font) const
+ { return (this+mathKernInfo).get_kernings (glyph,
+ kern,
+ start_offset,
+ entries_count,
+ kern_entries,
+ font); }
+
protected:
/* Offset to MathItalicsCorrectionInfo table -
* from the beginning of MathGlyphInfo table. */
@@ -420,14 +651,27 @@ struct MathGlyphVariantRecord
{
friend struct MathGlyphConstruction;
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ const hb_map_t& glyph_map = *c->plan->glyph_map;
+ return_trace (c->serializer->check_assign (out->variantGlyph, glyph_map.get (variantGlyph), HB_SERIALIZE_ERROR_INT_OVERFLOW));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
+ void closure_glyphs (hb_set_t *variant_glyphs) const
+ { variant_glyphs->add (variantGlyph); }
+
protected:
- HBGlyphID variantGlyph; /* Glyph ID for the variant. */
+ HBGlyphID16 variantGlyph; /* Glyph ID for the variant. */
HBUINT16 advanceMeasurement; /* Advance width/height, in design units, of the
* variant, in the direction of requested
* glyph extension. */
@@ -450,6 +694,16 @@ struct PartFlags : HBUINT16
struct MathGlyphPartRecord
{
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ const hb_map_t& glyph_map = *c->plan->glyph_map;
+ return_trace (c->serializer->check_assign (out->glyph, glyph_map.get (glyph), HB_SERIALIZE_ERROR_INT_OVERFLOW));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -474,8 +728,11 @@ struct MathGlyphPartRecord
(partFlags & PartFlags::Defined);
}
+ void closure_glyphs (hb_set_t *variant_glyphs) const
+ { variant_glyphs->add (glyph); }
+
protected:
- HBGlyphID glyph; /* Glyph ID for the part. */
+ HBGlyphID16 glyph; /* Glyph ID for the part. */
HBUINT16 startConnectorLength;
/* Advance width/ height of the straight bar
* connector material, in design units, is at
@@ -497,6 +754,20 @@ struct MathGlyphPartRecord
struct MathGlyphAssembly
{
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ if (!c->serializer->copy (italicsCorrection, this)) return_trace (false);
+ if (!c->serializer->copy<HBUINT16> (partRecords.len)) return_trace (false);
+
+ for (const auto& record : partRecords.iter ())
+ if (!record.subset (c)) return_trace (false);
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -526,6 +797,12 @@ struct MathGlyphAssembly
return partRecords.len;
}
+ void closure_glyphs (hb_set_t *variant_glyphs) const
+ {
+ for (const auto& _ : partRecords.iter ())
+ _.closure_glyphs (variant_glyphs);
+ }
+
protected:
MathValueRecord
italicsCorrection;
@@ -543,6 +820,22 @@ struct MathGlyphAssembly
struct MathGlyphConstruction
{
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ out->glyphAssembly.serialize_subset (c, glyphAssembly, this);
+
+ if (!c->serializer->check_assign (out->mathGlyphVariantRecord.len, mathGlyphVariantRecord.len, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+ for (const auto& record : mathGlyphVariantRecord.iter ())
+ if (!record.subset (c)) return_trace (false);
+
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -569,6 +862,14 @@ struct MathGlyphConstruction
return mathGlyphVariantRecord.len;
}
+ void closure_glyphs (hb_set_t *variant_glyphs) const
+ {
+ (this+glyphAssembly).closure_glyphs (variant_glyphs);
+
+ for (const auto& _ : mathGlyphVariantRecord.iter ())
+ _.closure_glyphs (variant_glyphs);
+ }
+
protected:
/* Offset to MathGlyphAssembly table for this shape - from the beginning of
MathGlyphConstruction table. May be NULL. */
@@ -583,6 +884,94 @@ struct MathGlyphConstruction
struct MathVariants
{
+ void closure_glyphs (const hb_set_t *glyph_set,
+ hb_set_t *variant_glyphs) const
+ {
+ const hb_array_t<const Offset16To<MathGlyphConstruction>> glyph_construction_offsets = glyphConstruction.as_array (vertGlyphCount + horizGlyphCount);
+
+ if (vertGlyphCoverage)
+ {
+ const auto vert_offsets = glyph_construction_offsets.sub_array (0, vertGlyphCount);
+ + hb_zip (this+vertGlyphCoverage, vert_offsets)
+ | hb_filter (glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([=] (const MathGlyphConstruction &_) { _.closure_glyphs (variant_glyphs); })
+ ;
+ }
+
+ if (horizGlyphCoverage)
+ {
+ const auto hori_offsets = glyph_construction_offsets.sub_array (vertGlyphCount, horizGlyphCount);
+ + hb_zip (this+horizGlyphCoverage, hori_offsets)
+ | hb_filter (glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([=] (const MathGlyphConstruction &_) { _.closure_glyphs (variant_glyphs); })
+ ;
+ }
+ }
+
+ void collect_coverage_and_indices (hb_sorted_vector_t<hb_codepoint_t>& new_coverage,
+ const Offset16To<Coverage>& coverage,
+ unsigned i,
+ unsigned end_index,
+ hb_set_t& indices,
+ const hb_set_t& glyphset,
+ const hb_map_t& glyph_map) const
+ {
+ if (!coverage) return;
+
+ for (const auto _ : (this+coverage).iter ())
+ {
+ if (i >= end_index) return;
+ if (glyphset.has (_))
+ {
+ unsigned new_gid = glyph_map.get (_);
+ new_coverage.push (new_gid);
+ indices.add (i);
+ }
+ i++;
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
+ 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);
+ if (!c->serializer->check_assign (out->minConnectorOverlap, minConnectorOverlap, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+
+ hb_sorted_vector_t<hb_codepoint_t> new_vert_coverage;
+ hb_sorted_vector_t<hb_codepoint_t> new_hori_coverage;
+ hb_set_t indices;
+ collect_coverage_and_indices (new_vert_coverage, vertGlyphCoverage, 0, vertGlyphCount, indices, glyphset, glyph_map);
+ collect_coverage_and_indices (new_hori_coverage, horizGlyphCoverage, vertGlyphCount, vertGlyphCount + horizGlyphCount, indices, glyphset, glyph_map);
+
+ if (!c->serializer->check_assign (out->vertGlyphCount, new_vert_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+ if (!c->serializer->check_assign (out->horizGlyphCount, new_hori_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+
+ for (unsigned i : indices.iter ())
+ {
+ auto *o = c->serializer->embed (glyphConstruction[i]);
+ if (!o) return_trace (false);
+ o->serialize_subset (c, glyphConstruction[i], this);
+ }
+
+ if (new_vert_coverage)
+ out->vertGlyphCoverage.serialize_serialize (c->serializer, new_vert_coverage.iter ());
+
+ if (new_hori_coverage)
+ out->horizGlyphCoverage.serialize_serialize (c->serializer, new_hori_coverage.iter ());
+ return_trace (true);
+ }
+
bool sanitize_offsets (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -690,6 +1079,28 @@ struct MATH
bool has_data () const { return version.to_int (); }
+ void closure_glyphs (hb_set_t *glyph_set) const
+ {
+ if (mathVariants)
+ {
+ hb_set_t variant_glyphs;
+ (this+mathVariants).closure_glyphs (glyph_set, &variant_glyphs);
+ hb_set_union (glyph_set, &variant_glyphs);
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ out->mathConstants.serialize_copy (c->serializer, mathConstants, this, 0, hb_serialize_context_t::Head);
+ out->mathGlyphInfo.serialize_subset (c, mathGlyphInfo, this);
+ out->mathVariants.serialize_subset (c, mathVariants, this);
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc
index 5781d25f2a..f44ac35849 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc
@@ -185,6 +185,51 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
}
/**
+ * hb_ot_math_get_glyph_kernings:
+ * @font: #hb_font_t to work upon
+ * @glyph: The glyph index from which to retrieve the kernings
+ * @kern: The #hb_ot_math_kern_t from which to retrieve the kernings
+ * @start_offset: offset of the first kern entry to retrieve
+ * @entries_count: (inout) (optional): Input = the maximum number of kern entries to return;
+ * Output = the actual number of kern entries returned
+ * @kern_entries: (out caller-allocates) (array length=entries_count): array of kern entries returned
+ *
+ * Fetches the raw MathKern (cut-in) data for the specified font, glyph index,
+ * and @kern. The corresponding list of kern values and correction heights is
+ * returned as a list of #hb_ot_math_kern_entry_t structs.
+ *
+ * See also #hb_ot_math_get_glyph_kerning, which handles selecting the
+ * appropriate kern value for a given correction height.
+ *
+ * <note>For a glyph with @n defined kern values (where @n > 0), there are only
+ * @n−1 defined correction heights, as each correction height defines a boundary
+ * past which the next kern value should be selected. Therefore, only the
+ * #hb_ot_math_kern_entry_t.kern_value of the uppermost #hb_ot_math_kern_entry_t
+ * actually comes from the font; its corresponding
+ * #hb_ot_math_kern_entry_t.max_correction_height is always set to
+ * <code>INT32_MAX</code>.</note>
+ *
+ * Return value: the total number of kern values available or zero
+ *
+ * Since: 3.4.0
+ **/
+unsigned int
+hb_ot_math_get_glyph_kernings (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries /* OUT */)
+{
+ return font->face->table.MATH->get_glyph_info().get_kernings (glyph,
+ kern,
+ start_offset,
+ entries_count,
+ kern_entries,
+ font);
+}
+
+/**
* hb_ot_math_get_glyph_variants:
* @font: #hb_font_t to work upon
* @glyph: The index of the glyph to stretch
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.h
index d3ffa19d85..1378a0639a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.h
@@ -50,14 +50,18 @@ HB_BEGIN_DECLS
#define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
/**
- * HB_OT_MATH_SCRIPT:
+ * HB_OT_TAG_MATH_SCRIPT:
*
- * OpenType script tag for math shaping, for use with
- * Use with hb_buffer_set_script().
+ * OpenType script tag, `math`, for features specific to math shaping.
*
- * Since: 1.3.3
+ * <note>#HB_OT_TAG_MATH_SCRIPT is not a valid #hb_script_t and should only be
+ * used with functions that accept raw OpenType script tags, such as
+ * #hb_ot_layout_collect_features. In other cases, #HB_SCRIPT_MATH should be
+ * used instead.</note>
+ *
+ * Since: 3.4.0
*/
-#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h')
+#define HB_OT_TAG_MATH_SCRIPT HB_TAG('m','a','t','h')
/* Types */
@@ -205,6 +209,20 @@ typedef enum {
} hb_ot_math_kern_t;
/**
+ * hb_ot_math_kern_entry_t:
+ * @max_correction_height: The maximum height at which this entry should be used
+ * @kern_value: The kern value of the entry
+ *
+ * Data type to hold math kerning (cut-in) information for a glyph.
+ *
+ * Since: 3.4.0
+ */
+typedef struct {
+ hb_position_t max_correction_height;
+ hb_position_t kern_value;
+} hb_ot_math_kern_entry_t;
+
+/**
* hb_ot_math_glyph_variant_t:
* @glyph: The glyph index of the variant
* @advance: The advance width of the variant
@@ -281,6 +299,14 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
hb_position_t correction_height);
HB_EXTERN unsigned int
+hb_ot_math_get_glyph_kernings (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries /* OUT */);
+
+HB_EXTERN unsigned int
hb_ot_math_get_glyph_variants (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-meta-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-meta-table.hh
index e31447f8fc..93e64c5327 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-meta-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-meta-table.hh
@@ -71,9 +71,9 @@ struct meta
struct accelerator_t
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{ table = hb_sanitize_context_t ().reference_table<meta> (face); }
- void fini () { table.destroy (); }
+ ~accelerator_t () { table.destroy (); }
hb_blob_t *reference_entry (hb_tag_t tag) const
{ return table->dataMaps.lsearch (tag).reference_entry (table.get_blob ()); }
@@ -119,7 +119,9 @@ struct meta
DEFINE_SIZE_ARRAY (16, dataMaps);
};
-struct meta_accelerator_t : meta::accelerator_t {};
+struct meta_accelerator_t : meta::accelerator_t {
+ meta_accelerator_t (hb_face_t *face) : meta::accelerator_t (face) {}
+};
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc
index 72aeff82d6..f9c4b96fff 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc
@@ -77,6 +77,7 @@ _hb_ot_metrics_get_position_common (hb_font_t *font,
(face->table.TABLE->has_data () && \
(position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
+
case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) ||
GET_METRIC_Y (hhea, ascender);
@@ -86,9 +87,13 @@ _hb_ot_metrics_get_position_common (hb_font_t *font,
case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP:
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoLineGap)) ||
GET_METRIC_Y (hhea, lineGap);
+
+#ifndef HB_NO_VERTICAL
case HB_OT_METRICS_TAG_VERTICAL_ASCENDER: return GET_METRIC_X (vhea, ascender);
case HB_OT_METRICS_TAG_VERTICAL_DESCENDER: return GET_METRIC_X (vhea, descender);
case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP: return GET_METRIC_X (vhea, lineGap);
+#endif
+
#undef GET_METRIC_Y
#undef GET_METRIC_X
#undef GET_VAR
@@ -155,12 +160,55 @@ hb_ot_metrics_get_position (hb_font_t *font,
(position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true))
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent);
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent);
- case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: return GET_METRIC_Y (hhea, caretSlopeRise);
- case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: return GET_METRIC_X (hhea, caretSlopeRun);
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE:
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN:
+ {
+ unsigned mult = 1u;
+
+ if (font->slant)
+ {
+ unsigned rise = face->table.hhea->caretSlopeRise;
+ unsigned upem = face->get_upem ();
+ mult = (rise && rise < upem) ? hb_min (upem / rise, 256u) : 1u;
+ }
+
+ if (metrics_tag == HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE)
+ {
+ bool ret = GET_METRIC_Y (hhea, caretSlopeRise);
+
+ if (position)
+ *position *= mult;
+
+ return ret;
+ }
+ else
+ {
+ hb_position_t rise = 0;
+
+ if (font->slant && position && GET_METRIC_Y (hhea, caretSlopeRise))
+ rise = *position;
+
+ bool ret = GET_METRIC_X (hhea, caretSlopeRun);
+
+ if (position)
+ {
+ *position *= mult;
+
+ if (font->slant)
+ *position += _hb_roundf (mult * font->slant_xy * rise);
+ }
+
+ return ret;
+ }
+ }
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET: return GET_METRIC_X (hhea, caretOffset);
+
+#ifndef HB_NO_VERTICAL
case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE: return GET_METRIC_X (vhea, caretSlopeRise);
case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN: return GET_METRIC_Y (vhea, caretSlopeRun);
case HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET: return GET_METRIC_Y (vhea, caretOffset);
+#endif
case HB_OT_METRICS_TAG_X_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sxHeight);
case HB_OT_METRICS_TAG_CAP_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sCapHeight);
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE: return GET_METRIC_X (OS2, ySubscriptXSize);
@@ -190,6 +238,145 @@ hb_ot_metrics_get_position (hb_font_t *font,
}
}
+/**
+ * hb_ot_metrics_get_position_with_fallback:
+ * @font: an #hb_font_t object.
+ * @metrics_tag: tag of metrics value you like to fetch.
+ * @position: (out) (optional): result of metrics value from the font.
+ *
+ * Fetches metrics value corresponding to @metrics_tag from @font,
+ * and synthesizes a value if it the value is missing in the font.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_ot_metrics_get_position_with_fallback (hb_font_t *font,
+ hb_ot_metrics_tag_t metrics_tag,
+ hb_position_t *position /* OUT */)
+{
+ hb_font_extents_t font_extents;
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+
+ if (hb_ot_metrics_get_position (font, metrics_tag, position))
+ {
+ if ((metrics_tag != HB_OT_METRICS_TAG_STRIKEOUT_SIZE &&
+ metrics_tag != HB_OT_METRICS_TAG_UNDERLINE_SIZE) ||
+ *position != 0)
+ return;
+ }
+
+ switch (metrics_tag)
+ {
+ case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
+ case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ *position = font_extents.ascender;
+ break;
+
+ case HB_OT_METRICS_TAG_VERTICAL_ASCENDER:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
+ *position = font_extents.ascender;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER:
+ case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ *position = font_extents.descender;
+ break;
+
+ case HB_OT_METRICS_TAG_VERTICAL_DESCENDER:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
+ *position = font_extents.ascender;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ *position = font_extents.line_gap;
+ break;
+
+ case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
+ *position = font_extents.line_gap;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE:
+ case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE:
+ *position = 1;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN:
+ case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN:
+ *position = 0;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET:
+ case HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET:
+ *position = 0;
+ break;
+
+ case HB_OT_METRICS_TAG_X_HEIGHT:
+ if (hb_font_get_nominal_glyph (font, 'x', &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *position = extents.y_bearing;
+ else
+ *position = font->y_scale / 2;
+ break;
+
+ case HB_OT_METRICS_TAG_CAP_HEIGHT:
+ if (hb_font_get_nominal_glyph (font, 'O', &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *position = extents.height + 2 * extents.y_bearing;
+ else
+ *position = font->y_scale * 2 / 3;
+ break;
+
+ case HB_OT_METRICS_TAG_STRIKEOUT_SIZE:
+ case HB_OT_METRICS_TAG_UNDERLINE_SIZE:
+ *position = font->y_scale / 18;
+ break;
+
+ case HB_OT_METRICS_TAG_STRIKEOUT_OFFSET:
+ {
+ hb_position_t ascender;
+ hb_ot_metrics_get_position_with_fallback (font,
+ HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER,
+ &ascender);
+ *position = ascender / 2;
+ }
+ break;
+
+ case HB_OT_METRICS_TAG_UNDERLINE_OFFSET:
+ *position = - font->y_scale / 18;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE:
+ *position = font->x_scale * 10 / 12;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE:
+ *position = font->y_scale * 10 / 12;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET:
+ *position = 0;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET:
+ *position = font->y_scale / 5;
+ break;
+
+ case _HB_OT_METRICS_TAG_MAX_VALUE:
+ default:
+ *position = 0;
+ break;
+ }
+}
+
#ifndef HB_NO_VAR
/**
* hb_ot_metrics_get_variation:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.h
index 5841fc8b0f..30de500088 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.h
@@ -110,6 +110,11 @@ hb_ot_metrics_get_position (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */);
+HB_EXTERN void
+hb_ot_metrics_get_position_with_fallback (hb_font_t *font,
+ hb_ot_metrics_tag_t metrics_tag,
+ hb_position_t *position /* OUT */);
+
HB_EXTERN float
hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh
index c17bb4abb8..d52367e9b1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh
@@ -256,7 +256,7 @@ struct name
})
;
- name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset));
+ name_prime->serialize (c->serializer, it, std::addressof (this + stringOffset));
return_trace (name_prime->count);
}
@@ -279,7 +279,7 @@ struct name
struct accelerator_t
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{
this->table = hb_sanitize_context_t ().reference_table<name> (face);
assert (this->table.get_length () >= this->table->stringOffset);
@@ -288,7 +288,6 @@ struct name
const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
this->table->count);
- this->names.init ();
this->names.alloc (all_names.length);
for (unsigned int i = 0; i < all_names.length; i++)
@@ -318,10 +317,8 @@ struct name
}
this->names.resize (j);
}
-
- void fini ()
+ ~accelerator_t ()
{
- this->names.fini ();
this->table.destroy ();
}
@@ -373,7 +370,9 @@ struct name
#undef entry_index
#undef entry_score
-struct name_accelerator_t : name::accelerator_t {};
+struct name_accelerator_t : name::accelerator_t {
+ name_accelerator_t (hb_face_t *face) : name::accelerator_t (face) {}
+};
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc
index eff46ef227..c35ac5b3dc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc
@@ -52,7 +52,7 @@
* array is owned by the @face and should not be modified. It can be
* used as long as @face is alive.
*
- * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries.
+ * Returns: (transfer none) (array length=num_entries): Array of available name entries.
* Since: 2.1.0
**/
const hb_ot_name_entry_t *
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-name.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-name.h
index 9359014c8a..1ea4b55e5c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name.h
@@ -36,12 +36,42 @@ HB_BEGIN_DECLS
/**
* hb_ot_name_id_t:
+ * @HB_OT_NAME_ID_COPYRIGHT: Copyright notice
+ * @HB_OT_NAME_ID_FONT_FAMILY: Font Family name
+ * @HB_OT_NAME_ID_FONT_SUBFAMILY: Font Subfamily name
+ * @HB_OT_NAME_ID_UNIQUE_ID: Unique font identifier
+ * @HB_OT_NAME_ID_FULL_NAME: Full font name that reflects
+ * all family and relevant subfamily descriptors
+ * @HB_OT_NAME_ID_VERSION_STRING: Version string
+ * @HB_OT_NAME_ID_POSTSCRIPT_NAME: PostScript name for the font
+ * @HB_OT_NAME_ID_TRADEMARK: Trademark
+ * @HB_OT_NAME_ID_MANUFACTURER: Manufacturer Name
+ * @HB_OT_NAME_ID_DESIGNER: Designer
+ * @HB_OT_NAME_ID_DESCRIPTION: Description
+ * @HB_OT_NAME_ID_VENDOR_URL: URL of font vendor
+ * @HB_OT_NAME_ID_DESIGNER_URL: URL of typeface designer
+ * @HB_OT_NAME_ID_LICENSE: License Description
+ * @HB_OT_NAME_ID_LICENSE_URL: URL where additional licensing
+ * information can be found
+ * @HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY: Typographic Family name
+ * @HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY: Typographic Subfamily name
+ * @HB_OT_NAME_ID_MAC_FULL_NAME: Compatible Full Name for MacOS
+ * @HB_OT_NAME_ID_SAMPLE_TEXT: Sample text
+ * @HB_OT_NAME_ID_CID_FINDFONT_NAME: PostScript CID findfont name
+ * @HB_OT_NAME_ID_WWS_FAMILY: WWS Family Name
+ * @HB_OT_NAME_ID_WWS_SUBFAMILY: WWS Subfamily Name
+ * @HB_OT_NAME_ID_LIGHT_BACKGROUND: Light Background Palette
+ * @HB_OT_NAME_ID_DARK_BACKGROUND: Dark Background Palette
+ * @HB_OT_NAME_ID_VARIATIONS_PS_PREFIX: Variations PostScript Name Prefix
* @HB_OT_NAME_ID_INVALID: Value to represent a nonexistent name ID.
*
* An integral type representing an OpenType 'name' table name identifier.
* There are predefined name IDs, as well as name IDs return from other
* API. These can be used to fetch name strings from a font face.
*
+ * For more information on these fields, see the
+ * [OpenType spec](https://docs.microsoft.com/en-us/typography/opentype/spec/name#name-ids).
+ *
* Since: 2.0.0
**/
enum
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh
index 94450eb53a..0f3cd8e24f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh
@@ -76,9 +76,9 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
hb_map_t old_new_index_map, old_gid_new_index_map;
unsigned i = 0;
- post::accelerator_t _post;
- _post.init (c->plan->source);
+ post::accelerator_t _post (c->plan->source);
+ hb_hashmap_t<hb_bytes_t, unsigned, std::nullptr_t, unsigned, nullptr, (unsigned)-1> glyph_name_to_new_index;
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
{
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
@@ -90,22 +90,28 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
else
{
hb_bytes_t s = _post.find_glyph_name (old_gid);
- int standard_glyph_index = -1;
- for (unsigned i = 0; i < format1_names_length; i++)
+ new_index = glyph_name_to_new_index.get (s);
+ if (new_index == (unsigned)-1)
{
- if (s == format1_names (i))
+ int standard_glyph_index = -1;
+ for (unsigned i = 0; i < format1_names_length; i++)
{
- standard_glyph_index = i;
- break;
+ if (s == format1_names (i))
+ {
+ standard_glyph_index = i;
+ break;
+ }
}
+
+ if (standard_glyph_index == -1)
+ {
+ new_index = 258 + i;
+ i++;
+ }
+ else
+ { new_index = standard_glyph_index; }
+ glyph_name_to_new_index.set (s, new_index);
}
- if (standard_glyph_index == -1)
- {
- new_index = 258 + i;
- i++;
- }
- else
- { new_index = standard_glyph_index; }
old_new_index_map.set (old_index, new_index);
}
old_gid_new_index_map.set (old_gid, new_index);
@@ -121,9 +127,7 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
})
;
- bool ret = serialize (c->serializer, index_iter, &_post);
- _post.fini ();
- return_trace (ret);
+ return_trace (serialize (c->serializer, index_iter, &_post));
}
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh
index 39de671707..a4844e94bc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh
@@ -111,10 +111,9 @@ struct post
struct accelerator_t
{
friend struct postV2Tail;
- void init (hb_face_t *face)
- {
- index_to_offset.init ();
+ accelerator_t (hb_face_t *face)
+ {
table = hb_sanitize_context_t ().reference_table<post> (face);
unsigned int table_length = table.get_length ();
@@ -132,9 +131,8 @@ struct post
data += 1 + *data)
index_to_offset.push (data - pool);
}
- void fini ()
+ ~accelerator_t ()
{
- index_to_offset.fini ();
hb_free (gids_sorted_by_name.get ());
table.destroy ();
}
@@ -254,9 +252,9 @@ struct post
private:
uint32_t version;
- const Array16Of<HBUINT16> *glyphNameIndex;
+ const Array16Of<HBUINT16> *glyphNameIndex = nullptr;
hb_vector_t<uint32_t> index_to_offset;
- const uint8_t *pool;
+ const uint8_t *pool = nullptr;
hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
};
@@ -307,7 +305,10 @@ struct post
DEFINE_SIZE_MIN (32);
};
-struct post_accelerator_t : post::accelerator_t {};
+struct post_accelerator_t : post::accelerator_t {
+ post_accelerator_t (hb_face_t *face) : post::accelerator_t (face) {}
+};
+
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
index 2b3b134ae3..78f46c1cac 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -49,8 +49,8 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
hb_font_t *font,
unsigned int feature_index)
{
- OT::HBGlyphID glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
- OT::HBGlyphID substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
+ OT::HBGlyphID16 glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
+ OT::HBGlyphID16 substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
unsigned int num_glyphs = 0;
/* Populate arrays */
@@ -78,7 +78,7 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
/* Bubble-sort or something equally good!
* May not be good-enough for presidential candidate interviews, but good-enough for us... */
hb_stable_sort (&glyphs[0], num_glyphs,
- (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID::cmp,
+ (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp,
&substitutes[0]);
@@ -99,15 +99,15 @@ static OT::SubstLookup *
arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font)
{
- OT::HBGlyphID first_glyphs[ARRAY_LENGTH_CONST (ligature_table)];
+ OT::HBGlyphID16 first_glyphs[ARRAY_LENGTH_CONST (ligature_table)];
unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)];
unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)];
unsigned int num_first_glyphs = 0;
/* We know that all our ligatures are 2-component */
- OT::HBGlyphID ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)];
+ OT::HBGlyphID16 ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)];
unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)];
- OT::HBGlyphID component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */];
+ OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */];
unsigned int num_ligatures = 0;
/* Populate arrays */
@@ -125,7 +125,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
num_first_glyphs++;
}
hb_stable_sort (&first_glyphs[0], num_first_glyphs,
- (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID::cmp,
+ (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp,
&first_glyphs_indirection[0]);
/* Now that the first-glyphs are sorted, walk again, populate ligatures. */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh
index 41e3dd38ab..429974d05b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh
@@ -87,6 +87,8 @@
#define OT_GLYPHID /* GlyphID */ \
OT_UINT16
+/* Shorthand. */
+#define G OT_GLYPHID
#define OT_UARRAY(Name, Items) \
OT_LABEL_START(Name) \
@@ -183,8 +185,6 @@
Tag \
OT_OFFSET(manifest, Name)
-/* Shorthand. */
-#define G OT_GLYPHID
/*
* Table Start
@@ -300,14 +300,40 @@ OT_TABLE_END
/*
* Clean up
*/
+
+#undef MANIFEST
+#undef MANIFEST_LOOKUP
+
#undef OT_TABLE_START
#undef OT_TABLE_END
#undef OT_LABEL_START
#undef OT_LABEL_END
#undef OT_UINT8
#undef OT_UINT16
-#undef OT_DISTANCE
#undef OT_COUNT
+#undef OT_DISTANCE
+
+#undef OT_LABEL
+#undef OT_LIST
+
+#undef OT_TAG
+#undef OT_OFFSET
+#undef OT_GLYPHID
+#undef G
+#undef OT_UARRAY
+#undef OT_UHEADLESSARRAY
+
+#undef OT_LOOKUP_FLAG_IGNORE_MARKS
+#undef OT_LOOKUP
+#undef OT_SUBLOOKUP
+#undef OT_COVERAGE1
+#undef OT_LOOKUP_TYPE_SUBST_SINGLE
+#undef OT_LOOKUP_TYPE_SUBST_LIGATURE
+#undef OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2
+#undef OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1
+#undef OT_LIGATURE_SET
+#undef OT_LIGATURE
+
/*
* Include a second time to get the table data...
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
index 1f8c1410fc..224f8b842e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
@@ -321,6 +321,20 @@ arabic_joining (hb_buffer_t *buffer)
info[prev].arabic_shaping_action() = entry->prev_action;
buffer->unsafe_to_break (prev, i + 1);
}
+ else
+ {
+ if (prev == UINT_MAX)
+ {
+ if (this_type >= JOINING_TYPE_R)
+ buffer->unsafe_to_concat_from_outbuffer (0, i + 1);
+ }
+ else
+ {
+ if (this_type >= JOINING_TYPE_R ||
+ (2 <= state && state <= 5) /* States that have a possible prev_action. */)
+ buffer->unsafe_to_concat (prev, i + 1);
+ }
+ }
info[i].arabic_shaping_action() = entry->curr_action;
@@ -337,7 +351,14 @@ arabic_joining (hb_buffer_t *buffer)
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
if (entry->prev_action != NONE && prev != UINT_MAX)
+ {
info[prev].arabic_shaping_action() = entry->prev_action;
+ buffer->unsafe_to_break (prev, buffer->len);
+ }
+ else if (2 <= state && state <= 5) /* States that have a possible prev_action. */
+ {
+ buffer->unsafe_to_concat (prev, buffer->len);
+ }
break;
}
}
@@ -349,7 +370,7 @@ mongolian_variation_selectors (hb_buffer_t *buffer)
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 1; i < count; i++)
- if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du)))
+ if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du, 0x180Fu, 0x180Fu)))
info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
}
@@ -614,6 +635,11 @@ modifier_combining_marks[] =
0x06E3u, /* ARABIC SMALL LOW SEEN */
0x06E7u, /* ARABIC SMALL HIGH YEH */
0x06E8u, /* ARABIC SMALL HIGH NOON */
+ 0x08CAu, /* ARABIC SMALL HIGH FARSI YEH */
+ 0x08CBu, /* ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW */
+ 0x08CDu, /* ARABIC SMALL HIGH ZAH */
+ 0x08CEu, /* ARABIC LARGE ROUND DOT ABOVE */
+ 0x08CFu, /* ARABIC LARGE ROUND DOT BELOW */
0x08D3u, /* ARABIC SMALL LOW WAW */
0x08F3u, /* ARABIC SMALL HIGH WAW */
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
index 0d84a76b85..3bc9e9b961 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
@@ -140,7 +140,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
*
* - LV can be precomposed, or decomposed. Lets call those
* <LV> and <L,V>,
- * - LVT can be fully precomposed, partically precomposed, or
+ * - LVT can be fully precomposed, partially precomposed, or
* fully decomposed. Ie. <LVT>, <LV,T>, or <L,V,T>.
*
* The composition / decomposition is mechanical. However, not
@@ -392,7 +392,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
*/
(void) buffer->next_glyph ();
}
- buffer->swap_buffers ();
+ buffer->sync ();
}
static void
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
index 0983a32848..c80f7df6a9 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
@@ -109,17 +109,17 @@ indic_features[] =
* These features are applied in order, one at a time, after initial_reordering,
* constrained to the syllable.
*/
- {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('r','p','h','f'), F_MANUAL_JOINERS},
- {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
- {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
- {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS},
- {HB_TAG('h','a','l','f'), F_MANUAL_JOINERS},
- {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS},
- {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
+ {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('r','p','h','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('h','a','l','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
/*
* Other features.
* These features are applied all at once, after final_reordering, constrained
@@ -127,12 +127,12 @@ indic_features[] =
* Default Bengali font in Windows for example has intermixed
* lookups for init,pres,abvs,blws features.
*/
- {HB_TAG('i','n','i','t'), F_MANUAL_JOINERS},
- {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS},
+ {HB_TAG('i','n','i','t'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
};
/*
@@ -183,10 +183,10 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables_indic);
- map->enable_feature (HB_TAG('l','o','c','l'));
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
/* The Indic specs do not require ccmp, but we apply it here since if
* there is a use of it, it's typically at the beginning. */
- map->enable_feature (HB_TAG('c','c','m','p'));
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
unsigned int i = 0;
@@ -201,11 +201,6 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
for (; i < INDIC_NUM_FEATURES; i++)
map->add_feature (indic_features[i]);
-
- map->enable_feature (HB_TAG('c','a','l','t'));
- map->enable_feature (HB_TAG('c','l','i','g'));
-
- map->add_gsub_pause (_hb_clear_syllables);
}
static void
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.hh
index dcb28a4e84..da77a2887c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.hh
@@ -368,6 +368,7 @@ set_indic_properties (hb_glyph_info_t &info)
else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */
else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
+ else if (unlikely (u == 0x0D04u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/3511 */
else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
cat = OT_PLACEHOLDER;
else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc
index 7787886857..a7d5bf574b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc
@@ -45,11 +45,11 @@ khmer_features[] =
* These features are applied all at once, before reordering, constrained
* to the syllable.
*/
- {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
- {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
- {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS},
- {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS},
- {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS},
+ {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
/*
* Other features.
* These features are applied all at once after clearing syllables.
@@ -107,14 +107,15 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
*
* https://github.com/harfbuzz/harfbuzz/issues/974
*/
- map->enable_feature (HB_TAG('l','o','c','l'));
- map->enable_feature (HB_TAG('c','c','m','p'));
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
unsigned int i = 0;
for (; i < KHMER_BASIC_FEATURES; i++)
map->add_feature (khmer_features[i]);
- map->add_gsub_pause (_hb_clear_syllables);
+ /* https://github.com/harfbuzz/harfbuzz/issues/3531 */
+ map->add_gsub_pause (nullptr);
for (; i < KHMER_NUM_FEATURES; i++)
map->add_feature (khmer_features[i]);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.hh
index e24d68a8b5..35bfbb64d5 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.hh
@@ -49,13 +49,15 @@ enum khmer_category_t
//OT_VPst = 29,
};
+using khmer_position_t = indic_position_t;
+
static inline void
set_khmer_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
khmer_category_t cat = (khmer_category_t) (type & 0xFFu);
- indic_position_t pos = (indic_position_t) (type >> 8);
+ khmer_position_t pos = (khmer_position_t) (type >> 8);
/*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
index c09497896d..f4ef33004d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -51,6 +51,7 @@ enum myanmar_syllable_type_t {
#define myanmar_syllable_machine_ex_H 4u
#define myanmar_syllable_machine_ex_IV 2u
#define myanmar_syllable_machine_ex_MH 21u
+#define myanmar_syllable_machine_ex_ML 33u
#define myanmar_syllable_machine_ex_MR 22u
#define myanmar_syllable_machine_ex_MW 23u
#define myanmar_syllable_machine_ex_MY 24u
@@ -67,35 +68,36 @@ enum myanmar_syllable_type_t {
#define myanmar_syllable_machine_ex_ZWNJ 5u
-#line 71 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 72 "hb-ot-shape-complex-myanmar-machine.hh"
static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
- 1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
- 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u,
- 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u,
- 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u,
- 3u, 29u, 3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u,
- 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u,
- 3u, 29u, 1u, 32u, 1u, 32u, 8u, 8u, 0
+ 1u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
+ 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
+ 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u, 3u, 33u,
+ 3u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
+ 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
+ 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u,
+ 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 1u, 33u, 1u, 32u, 8u, 8u,
+ 0
};
static const char _myanmar_syllable_machine_key_spans[] = {
- 32, 28, 25, 4, 25, 23, 21, 21,
- 27, 27, 27, 27, 16, 27, 27, 27,
- 27, 27, 28, 27, 27, 27, 27, 27,
- 25, 4, 25, 23, 21, 21, 27, 27,
- 27, 27, 16, 28, 27, 27, 27, 27,
- 27, 28, 27, 27, 27, 27, 27, 28,
- 27, 32, 32, 1
+ 33, 31, 25, 4, 25, 23, 21, 21,
+ 31, 27, 27, 27, 31, 16, 31, 31,
+ 27, 27, 27, 28, 27, 31, 31, 31,
+ 31, 31, 25, 4, 25, 23, 21, 21,
+ 31, 27, 27, 27, 31, 16, 31, 31,
+ 31, 27, 27, 27, 28, 27, 31, 31,
+ 31, 31, 31, 31, 31, 33, 32, 1
};
static const short _myanmar_syllable_machine_index_offsets[] = {
- 0, 33, 62, 88, 93, 119, 143, 165,
- 187, 215, 243, 271, 299, 316, 344, 372,
- 400, 428, 456, 485, 513, 541, 569, 597,
- 625, 651, 656, 682, 706, 728, 750, 778,
- 806, 834, 862, 879, 908, 936, 964, 992,
- 1020, 1048, 1077, 1105, 1133, 1161, 1189, 1217,
- 1246, 1274, 1307, 1340
+ 0, 34, 66, 92, 97, 123, 147, 169,
+ 191, 223, 251, 279, 307, 339, 356, 388,
+ 420, 448, 476, 504, 533, 561, 593, 625,
+ 657, 689, 721, 747, 752, 778, 802, 824,
+ 846, 878, 906, 934, 962, 994, 1011, 1043,
+ 1075, 1107, 1135, 1163, 1191, 1220, 1248, 1280,
+ 1312, 1344, 1376, 1408, 1440, 1472, 1506, 1539
};
static const char _myanmar_syllable_machine_indicies[] = {
@@ -103,192 +105,217 @@ static const char _myanmar_syllable_machine_indicies[] = {
0, 6, 1, 0, 0, 0, 0, 7,
0, 8, 9, 0, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 1,
- 0, 22, 23, 24, 24, 21, 25, 21,
- 26, 21, 21, 21, 21, 21, 21, 21,
- 27, 21, 21, 28, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 21, 24, 24,
- 21, 25, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 38, 21, 21, 21, 21,
- 21, 21, 32, 21, 21, 21, 36, 21,
- 24, 24, 21, 25, 21, 24, 24, 21,
- 25, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 32, 21, 21, 21, 36, 21, 39,
- 21, 24, 24, 21, 25, 21, 32, 21,
- 21, 21, 21, 21, 21, 21, 40, 21,
- 21, 21, 21, 21, 21, 32, 21, 24,
- 24, 21, 25, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 40, 21, 21, 21,
- 21, 21, 21, 32, 21, 24, 24, 21,
- 25, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 32, 21, 22, 21, 24, 24, 21,
- 25, 21, 26, 21, 21, 21, 21, 21,
- 21, 21, 41, 21, 21, 41, 21, 21,
- 21, 32, 42, 21, 21, 36, 21, 22,
- 21, 24, 24, 21, 25, 21, 26, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 32, 21, 21,
- 21, 36, 21, 22, 21, 24, 24, 21,
- 25, 21, 26, 21, 21, 21, 21, 21,
- 21, 21, 41, 21, 21, 21, 21, 21,
- 21, 32, 42, 21, 21, 36, 21, 22,
- 21, 24, 24, 21, 25, 21, 26, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 32, 42, 21,
- 21, 36, 21, 1, 1, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 1, 21, 22, 21, 24, 24,
- 21, 25, 21, 26, 21, 21, 21, 21,
- 21, 21, 21, 27, 21, 21, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 21,
- 22, 21, 24, 24, 21, 25, 21, 26,
- 21, 21, 21, 21, 21, 21, 21, 43,
- 21, 21, 21, 21, 21, 21, 32, 33,
- 34, 35, 36, 21, 22, 21, 24, 24,
- 21, 25, 21, 26, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 32, 33, 34, 35, 36, 21,
- 22, 21, 24, 24, 21, 25, 21, 26,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 32, 33,
- 34, 21, 36, 21, 22, 21, 24, 24,
- 21, 25, 21, 26, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 32, 21, 34, 21, 36, 21,
- 22, 21, 24, 24, 21, 25, 21, 26,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 32, 33,
- 34, 35, 36, 43, 21, 22, 21, 24,
- 24, 21, 25, 21, 26, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 28,
- 21, 30, 21, 32, 33, 34, 35, 36,
- 21, 22, 21, 24, 24, 21, 25, 21,
- 26, 21, 21, 21, 21, 21, 21, 21,
- 43, 21, 21, 28, 21, 21, 21, 32,
- 33, 34, 35, 36, 21, 22, 21, 24,
- 24, 21, 25, 21, 26, 21, 21, 21,
- 21, 21, 21, 21, 44, 21, 21, 28,
- 29, 30, 21, 32, 33, 34, 35, 36,
- 21, 22, 21, 24, 24, 21, 25, 21,
- 26, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 28, 29, 30, 21, 32,
- 33, 34, 35, 36, 21, 22, 23, 24,
- 24, 21, 25, 21, 26, 21, 21, 21,
- 21, 21, 21, 21, 27, 21, 21, 28,
- 29, 30, 31, 32, 33, 34, 35, 36,
- 21, 46, 46, 45, 5, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 47, 45,
- 45, 45, 45, 45, 45, 14, 45, 45,
- 45, 18, 45, 46, 46, 45, 5, 45,
- 46, 46, 45, 5, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 14, 45, 45, 45,
- 18, 45, 48, 45, 46, 46, 45, 5,
- 45, 14, 45, 45, 45, 45, 45, 45,
- 45, 49, 45, 45, 45, 45, 45, 45,
- 14, 45, 46, 46, 45, 5, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 49,
- 45, 45, 45, 45, 45, 45, 14, 45,
- 46, 46, 45, 5, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 14, 45, 2, 45,
- 46, 46, 45, 5, 45, 6, 45, 45,
- 45, 45, 45, 45, 45, 50, 45, 45,
- 50, 45, 45, 45, 14, 51, 45, 45,
- 18, 45, 2, 45, 46, 46, 45, 5,
- 45, 6, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45,
- 14, 45, 45, 45, 18, 45, 2, 45,
- 46, 46, 45, 5, 45, 6, 45, 45,
- 45, 45, 45, 45, 45, 50, 45, 45,
- 45, 45, 45, 45, 14, 51, 45, 45,
- 18, 45, 2, 45, 46, 46, 45, 5,
- 45, 6, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45,
- 14, 51, 45, 45, 18, 45, 52, 52,
- 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 52, 45, 2,
- 3, 46, 46, 45, 5, 45, 6, 45,
- 45, 45, 45, 45, 45, 45, 8, 45,
- 45, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 45, 2, 45, 46, 46,
- 45, 5, 45, 6, 45, 45, 45, 45,
- 45, 45, 45, 8, 45, 45, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 45,
- 2, 45, 46, 46, 45, 5, 45, 6,
- 45, 45, 45, 45, 45, 45, 45, 53,
- 45, 45, 45, 45, 45, 45, 14, 15,
- 16, 17, 18, 45, 2, 45, 46, 46,
- 45, 5, 45, 6, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 14, 15, 16, 17, 18, 45,
- 2, 45, 46, 46, 45, 5, 45, 6,
- 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 14, 15,
- 16, 45, 18, 45, 2, 45, 46, 46,
- 45, 5, 45, 6, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 14, 45, 16, 45, 18, 45,
- 2, 45, 46, 46, 45, 5, 45, 6,
- 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 14, 15,
- 16, 17, 18, 53, 45, 2, 45, 46,
- 46, 45, 5, 45, 6, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 10,
- 45, 12, 45, 14, 15, 16, 17, 18,
- 45, 2, 45, 46, 46, 45, 5, 45,
- 6, 45, 45, 45, 45, 45, 45, 45,
- 53, 45, 45, 10, 45, 45, 45, 14,
- 15, 16, 17, 18, 45, 2, 45, 46,
- 46, 45, 5, 45, 6, 45, 45, 45,
- 45, 45, 45, 45, 54, 45, 45, 10,
- 11, 12, 45, 14, 15, 16, 17, 18,
- 45, 2, 45, 46, 46, 45, 5, 45,
- 6, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 10, 11, 12, 45, 14,
- 15, 16, 17, 18, 45, 2, 3, 46,
- 46, 45, 5, 45, 6, 45, 45, 45,
- 45, 45, 45, 45, 8, 45, 45, 10,
- 11, 12, 13, 14, 15, 16, 17, 18,
- 45, 22, 23, 24, 24, 21, 25, 21,
- 26, 21, 21, 21, 21, 21, 21, 21,
- 55, 21, 21, 28, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 21, 22, 56,
- 24, 24, 21, 25, 21, 26, 21, 21,
- 21, 21, 21, 21, 21, 27, 21, 21,
- 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 21, 1, 1, 2, 3, 46, 46,
- 45, 5, 45, 6, 1, 45, 45, 45,
- 45, 1, 45, 8, 45, 45, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19,
- 45, 1, 45, 1, 1, 57, 57, 57,
- 57, 57, 57, 57, 57, 1, 57, 57,
- 57, 57, 1, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 1, 57, 58, 57, 0
+ 21, 0, 23, 24, 25, 25, 22, 26,
+ 22, 27, 22, 22, 22, 22, 22, 22,
+ 22, 28, 22, 22, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 22, 22,
+ 39, 22, 25, 25, 22, 26, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 40,
+ 22, 22, 22, 22, 22, 22, 33, 22,
+ 22, 22, 37, 22, 25, 25, 22, 26,
+ 22, 25, 25, 22, 26, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 33, 22, 22,
+ 22, 37, 22, 41, 22, 25, 25, 22,
+ 26, 22, 33, 22, 22, 22, 22, 22,
+ 22, 22, 42, 22, 22, 22, 22, 22,
+ 22, 33, 22, 25, 25, 22, 26, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 42, 22, 22, 22, 22, 22, 22, 33,
+ 22, 25, 25, 22, 26, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 33, 22, 23,
+ 22, 25, 25, 22, 26, 22, 27, 22,
+ 22, 22, 22, 22, 22, 22, 43, 22,
+ 22, 44, 22, 22, 22, 33, 45, 22,
+ 22, 37, 22, 22, 22, 43, 22, 23,
+ 22, 25, 25, 22, 26, 22, 27, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 33, 22, 22,
+ 22, 37, 22, 23, 22, 25, 25, 22,
+ 26, 22, 27, 22, 22, 22, 22, 22,
+ 22, 22, 43, 22, 22, 22, 22, 22,
+ 22, 33, 45, 22, 22, 37, 22, 23,
+ 22, 25, 25, 22, 26, 22, 27, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 33, 45, 22,
+ 22, 37, 22, 23, 22, 25, 25, 22,
+ 26, 22, 27, 22, 22, 22, 22, 22,
+ 22, 22, 43, 22, 22, 22, 22, 22,
+ 22, 33, 45, 22, 22, 37, 22, 22,
+ 22, 43, 22, 1, 1, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 1, 22, 23, 22, 25, 25,
+ 22, 26, 22, 27, 22, 22, 22, 22,
+ 22, 22, 22, 28, 22, 22, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 22,
+ 22, 22, 39, 22, 23, 22, 25, 25,
+ 22, 26, 22, 27, 22, 22, 22, 22,
+ 22, 22, 22, 46, 22, 22, 22, 22,
+ 22, 22, 33, 34, 35, 36, 37, 22,
+ 22, 22, 39, 22, 23, 22, 25, 25,
+ 22, 26, 22, 27, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 33, 34, 35, 36, 37, 22,
+ 23, 22, 25, 25, 22, 26, 22, 27,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 33, 34,
+ 35, 22, 37, 22, 23, 22, 25, 25,
+ 22, 26, 22, 27, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 33, 22, 35, 22, 37, 22,
+ 23, 22, 25, 25, 22, 26, 22, 27,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 33, 34,
+ 35, 36, 37, 46, 22, 23, 22, 25,
+ 25, 22, 26, 22, 27, 22, 22, 22,
+ 22, 22, 22, 22, 46, 22, 22, 22,
+ 22, 22, 22, 33, 34, 35, 36, 37,
+ 22, 23, 22, 25, 25, 22, 26, 22,
+ 27, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 29, 22, 31, 22, 33,
+ 34, 35, 36, 37, 22, 22, 22, 39,
+ 22, 23, 22, 25, 25, 22, 26, 22,
+ 27, 22, 22, 22, 22, 22, 22, 22,
+ 46, 22, 22, 29, 22, 22, 22, 33,
+ 34, 35, 36, 37, 22, 22, 22, 39,
+ 22, 23, 22, 25, 25, 22, 26, 22,
+ 27, 22, 22, 22, 22, 22, 22, 22,
+ 47, 22, 22, 29, 30, 31, 22, 33,
+ 34, 35, 36, 37, 22, 22, 22, 39,
+ 22, 23, 22, 25, 25, 22, 26, 22,
+ 27, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 29, 30, 31, 22, 33,
+ 34, 35, 36, 37, 22, 22, 22, 39,
+ 22, 23, 24, 25, 25, 22, 26, 22,
+ 27, 22, 22, 22, 22, 22, 22, 22,
+ 28, 22, 22, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 22, 22, 22, 39,
+ 22, 49, 49, 48, 5, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 50, 48,
+ 48, 48, 48, 48, 48, 14, 48, 48,
+ 48, 18, 48, 49, 49, 48, 5, 48,
+ 49, 49, 48, 5, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 14, 48, 48, 48,
+ 18, 48, 51, 48, 49, 49, 48, 5,
+ 48, 14, 48, 48, 48, 48, 48, 48,
+ 48, 52, 48, 48, 48, 48, 48, 48,
+ 14, 48, 49, 49, 48, 5, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 52,
+ 48, 48, 48, 48, 48, 48, 14, 48,
+ 49, 49, 48, 5, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 14, 48, 2, 48,
+ 49, 49, 48, 5, 48, 6, 48, 48,
+ 48, 48, 48, 48, 48, 53, 48, 48,
+ 54, 48, 48, 48, 14, 55, 48, 48,
+ 18, 48, 48, 48, 53, 48, 2, 48,
+ 49, 49, 48, 5, 48, 6, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 14, 48, 48, 48,
+ 18, 48, 2, 48, 49, 49, 48, 5,
+ 48, 6, 48, 48, 48, 48, 48, 48,
+ 48, 53, 48, 48, 48, 48, 48, 48,
+ 14, 55, 48, 48, 18, 48, 2, 48,
+ 49, 49, 48, 5, 48, 6, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 14, 55, 48, 48,
+ 18, 48, 2, 48, 49, 49, 48, 5,
+ 48, 6, 48, 48, 48, 48, 48, 48,
+ 48, 53, 48, 48, 48, 48, 48, 48,
+ 14, 55, 48, 48, 18, 48, 48, 48,
+ 53, 48, 56, 56, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 56, 48, 2, 3, 49, 49, 48,
+ 5, 48, 6, 48, 48, 48, 48, 48,
+ 48, 48, 8, 48, 48, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 48,
+ 48, 21, 48, 2, 48, 49, 49, 48,
+ 5, 48, 6, 48, 48, 48, 48, 48,
+ 48, 48, 8, 48, 48, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 48, 48,
+ 48, 21, 48, 2, 48, 49, 49, 48,
+ 5, 48, 6, 48, 48, 48, 48, 48,
+ 48, 48, 57, 48, 48, 48, 48, 48,
+ 48, 14, 15, 16, 17, 18, 48, 48,
+ 48, 21, 48, 2, 48, 49, 49, 48,
+ 5, 48, 6, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 14, 15, 16, 17, 18, 48, 2,
+ 48, 49, 49, 48, 5, 48, 6, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 14, 15, 16,
+ 48, 18, 48, 2, 48, 49, 49, 48,
+ 5, 48, 6, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 14, 48, 16, 48, 18, 48, 2,
+ 48, 49, 49, 48, 5, 48, 6, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 14, 15, 16,
+ 17, 18, 57, 48, 2, 48, 49, 49,
+ 48, 5, 48, 6, 48, 48, 48, 48,
+ 48, 48, 48, 57, 48, 48, 48, 48,
+ 48, 48, 14, 15, 16, 17, 18, 48,
+ 2, 48, 49, 49, 48, 5, 48, 6,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 10, 48, 12, 48, 14, 15,
+ 16, 17, 18, 48, 48, 48, 21, 48,
+ 2, 48, 49, 49, 48, 5, 48, 6,
+ 48, 48, 48, 48, 48, 48, 48, 57,
+ 48, 48, 10, 48, 48, 48, 14, 15,
+ 16, 17, 18, 48, 48, 48, 21, 48,
+ 2, 48, 49, 49, 48, 5, 48, 6,
+ 48, 48, 48, 48, 48, 48, 48, 58,
+ 48, 48, 10, 11, 12, 48, 14, 15,
+ 16, 17, 18, 48, 48, 48, 21, 48,
+ 2, 48, 49, 49, 48, 5, 48, 6,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 10, 11, 12, 48, 14, 15,
+ 16, 17, 18, 48, 48, 48, 21, 48,
+ 2, 3, 49, 49, 48, 5, 48, 6,
+ 48, 48, 48, 48, 48, 48, 48, 8,
+ 48, 48, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 48, 48, 48, 21, 48,
+ 23, 24, 25, 25, 22, 26, 22, 27,
+ 22, 22, 22, 22, 22, 22, 22, 59,
+ 22, 22, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 22, 22, 39, 22,
+ 23, 60, 25, 25, 22, 26, 22, 27,
+ 22, 22, 22, 22, 22, 22, 22, 28,
+ 22, 22, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 22, 22, 22, 39, 22,
+ 1, 1, 2, 3, 49, 49, 48, 5,
+ 48, 6, 1, 48, 48, 48, 48, 1,
+ 48, 8, 48, 48, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 48, 1,
+ 21, 48, 1, 1, 61, 61, 61, 61,
+ 61, 61, 61, 61, 1, 61, 61, 61,
+ 61, 1, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 1, 61, 62, 61, 0
};
static const char _myanmar_syllable_machine_trans_targs[] = {
- 0, 1, 24, 34, 0, 25, 31, 47,
- 36, 50, 37, 42, 43, 44, 27, 39,
- 40, 41, 30, 46, 51, 0, 2, 12,
- 0, 3, 9, 13, 14, 19, 20, 21,
- 5, 16, 17, 18, 8, 23, 4, 6,
- 7, 10, 11, 15, 22, 0, 0, 26,
- 28, 29, 32, 33, 35, 38, 45, 48,
- 49, 0, 0
+ 0, 1, 26, 37, 0, 27, 33, 51,
+ 39, 54, 40, 46, 47, 48, 29, 42,
+ 43, 44, 32, 50, 55, 45, 0, 2,
+ 13, 0, 3, 9, 14, 15, 21, 22,
+ 23, 5, 17, 18, 19, 8, 25, 20,
+ 4, 6, 7, 10, 12, 11, 16, 24,
+ 0, 0, 28, 30, 31, 34, 36, 35,
+ 38, 41, 49, 52, 53, 0, 0
};
static const char _myanmar_syllable_machine_trans_actions[] = {
3, 0, 0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 5, 0, 0,
- 6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 5, 0,
+ 0, 6, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 7, 8, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 9, 10
+ 7, 8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 9, 10
};
static const char _myanmar_syllable_machine_to_state_actions[] = {
@@ -298,7 +325,7 @@ static const char _myanmar_syllable_machine_to_state_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0
};
static const char _myanmar_syllable_machine_from_state_actions[] = {
@@ -308,17 +335,17 @@ static const char _myanmar_syllable_machine_from_state_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0
};
static const short _myanmar_syllable_machine_eof_trans[] = {
- 0, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 22,
- 22, 46, 58, 58
+ 0, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 23, 23, 49, 62, 62
};
static const int myanmar_syllable_machine_start = 0;
@@ -332,7 +359,7 @@ static const int myanmar_syllable_machine_en_main = 0;
-#line 101 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 102 "hb-ot-shape-complex-myanmar-machine.rl"
#define found_syllable(syllable_type) \
@@ -351,7 +378,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
-#line 355 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 382 "hb-ot-shape-complex-myanmar-machine.hh"
{
cs = myanmar_syllable_machine_start;
ts = 0;
@@ -359,7 +386,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
act = 0;
}
-#line 121 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
p = 0;
@@ -367,7 +394,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
unsigned int syllable_serial = 1;
-#line 371 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 398 "hb-ot-shape-complex-myanmar-machine.hh"
{
int _slen;
int _trans;
@@ -381,7 +408,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 385 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 412 "hb-ot-shape-complex-myanmar-machine.hh"
}
_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -400,38 +427,38 @@ _eof_trans:
switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
case 6:
-#line 93 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
break;
case 4:
-#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 95 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
break;
case 10:
-#line 95 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (myanmar_punctuation_cluster); }}
break;
case 8:
-#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (myanmar_broken_cluster); }}
break;
case 3:
-#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
break;
case 5:
-#line 93 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
break;
case 7:
-#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (myanmar_broken_cluster); }}
break;
case 9:
-#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
break;
-#line 435 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 462 "hb-ot-shape-complex-myanmar-machine.hh"
}
_again:
@@ -440,7 +467,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 444 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 471 "hb-ot-shape-complex-myanmar-machine.hh"
}
if ( ++p != pe )
@@ -456,7 +483,7 @@ _again:
}
-#line 129 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 130 "hb-ot-shape-complex-myanmar-machine.rl"
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
index 6e92a9b0ae..13beaf4d4c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
@@ -79,22 +79,20 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables_myanmar);
- map->enable_feature (HB_TAG('l','o','c','l'));
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
/* The Indic specs do not require ccmp, but we apply it here since if
* there is a use of it, it's typically at the beginning. */
- map->enable_feature (HB_TAG('c','c','m','p'));
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
map->add_gsub_pause (reorder_myanmar);
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_basic_features); i++)
{
- map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ);
+ map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (nullptr);
}
- map->add_gsub_pause (_hb_clear_syllables);
-
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
}
@@ -107,8 +105,7 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_category);
HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_position);
- /* We cannot setup masks here. We save information about characters
- * and setup masks later on in a pause-callback. */
+ /* No masks, we just save information about characters. */
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
@@ -185,7 +182,7 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
info[i].myanmar_position() = POS_BASE_C;
i++;
}
- indic_position_t pos = POS_AFTER_MAIN;
+ myanmar_position_t pos = POS_AFTER_MAIN;
/* The following loop may be ugly, but it implements all of
* Myanmar reordering! */
for (; i < end; i++)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.hh
index a6d68aae57..7fbca3878f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.hh
@@ -56,8 +56,10 @@ enum myanmar_category_t {
OT_VS = 30, /* Variation selectors */
OT_P = 31, /* Punctuation */
OT_D = 32, /* Digits except zero */
+ OT_ML = 33, /* Various consonant medial types */
};
+using myanmar_position_t = indic_position_t;
static inline void
set_myanmar_properties (hb_glyph_info_t &info)
@@ -65,7 +67,7 @@ set_myanmar_properties (hb_glyph_info_t &info)
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
unsigned int cat = type & 0xFFu;
- indic_position_t pos = (indic_position_t) (type >> 8);
+ myanmar_position_t pos = (myanmar_position_t) (type >> 8);
/* Myanmar
* https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
@@ -114,10 +116,14 @@ set_myanmar_properties (hb_glyph_info_t &info)
cat = OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
break;
- case 0x103Eu: case 0x1060u:
+ case 0x103Eu:
cat = OT_MH;
break;
+ case 0x1060u:
+ cat = OT_ML;
+ break;
+
case 0x103Cu:
cat = OT_MR;
break;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.cc
index 5a08f878dc..76092c7f38 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.cc
@@ -96,7 +96,7 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
else
(void) buffer->next_glyph ();
}
- buffer->swap_buffers ();
+ buffer->sync ();
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
index 4c3068173b..a1e27a83be 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
@@ -364,7 +364,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
buffer->merge_out_clusters (start - 1, end);
}
}
- buffer->swap_buffers ();
+ buffer->sync ();
/* If font has Thai GSUB, we are done. */
if (plan->props.script == HB_SCRIPT_THAI && !plan->map.found_script[0])
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh
index bb046a72ec..468bd95c3f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh
@@ -41,7 +41,6 @@
#define USE(Cat) use_syllable_machine_ex_##Cat
enum use_syllable_type_t {
- use_independent_cluster,
use_virama_terminated_cluster,
use_sakot_terminated_cluster,
use_standard_cluster,
@@ -54,8 +53,9 @@ enum use_syllable_type_t {
};
-#line 58 "hb-ot-shape-complex-use-machine.hh"
+#line 57 "hb-ot-shape-complex-use-machine.hh"
#define use_syllable_machine_ex_B 1u
+#define use_syllable_machine_ex_CGJ 6u
#define use_syllable_machine_ex_CMAbv 31u
#define use_syllable_machine_ex_CMBlw 32u
#define use_syllable_machine_ex_CS 43u
@@ -69,7 +69,7 @@ enum use_syllable_type_t {
#define use_syllable_machine_ex_GB 5u
#define use_syllable_machine_ex_H 12u
#define use_syllable_machine_ex_HN 13u
-#define use_syllable_machine_ex_HVM 44u
+#define use_syllable_machine_ex_IS 44u
#define use_syllable_machine_ex_J 50u
#define use_syllable_machine_ex_MAbv 27u
#define use_syllable_machine_ex_MBlw 28u
@@ -78,7 +78,6 @@ enum use_syllable_type_t {
#define use_syllable_machine_ex_N 4u
#define use_syllable_machine_ex_O 0u
#define use_syllable_machine_ex_R 18u
-#define use_syllable_machine_ex_S 19u
#define use_syllable_machine_ex_SB 51u
#define use_syllable_machine_ex_SE 52u
#define use_syllable_machine_ex_SMAbv 41u
@@ -93,283 +92,514 @@ enum use_syllable_type_t {
#define use_syllable_machine_ex_VMPst 39u
#define use_syllable_machine_ex_VPre 22u
#define use_syllable_machine_ex_VPst 35u
+#define use_syllable_machine_ex_WJ 16u
#define use_syllable_machine_ex_ZWNJ 14u
#line 100 "hb-ot-shape-complex-use-machine.hh"
static const unsigned char _use_syllable_machine_trans_keys[] = {
- 1u, 1u, 1u, 1u, 0u, 51u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u,
+ 0u, 51u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u,
+ 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u,
+ 23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u,
+ 1u, 1u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u,
24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
- 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u,
- 11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u,
- 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
- 24u, 48u, 24u, 48u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u,
- 22u, 48u, 11u, 48u, 1u, 48u, 1u, 1u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u,
- 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0
+ 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u,
+ 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u,
+ 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
+ 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
+ 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 11u, 48u, 11u, 48u,
+ 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
+ 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
+ 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 4u, 4u, 13u, 13u,
+ 1u, 48u, 11u, 48u, 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u,
+ 0
};
static const char _use_syllable_machine_key_spans[] = {
- 1, 1, 52, 38, 38, 1, 27, 26,
+ 52, 38, 38, 48, 26, 24, 23, 22,
+ 2, 1, 25, 25, 25, 1, 25, 27,
+ 26, 26, 26, 37, 37, 37, 37, 38,
+ 1, 38, 2, 1, 38, 38, 48, 26,
24, 23, 22, 2, 1, 25, 25, 25,
- 1, 25, 26, 26, 26, 27, 27, 27,
- 38, 48, 1, 1, 38, 2, 1, 38,
- 27, 26, 24, 23, 22, 2, 1, 25,
- 25, 25, 25, 26, 26, 26, 27, 27,
- 27, 38, 48, 1, 1, 1, 48, 38,
- 2, 1, 5, 3, 4, 3
+ 1, 25, 27, 26, 26, 26, 37, 37,
+ 37, 37, 38, 1, 1, 1, 38, 38,
+ 48, 26, 24, 23, 22, 2, 1, 25,
+ 25, 25, 1, 25, 27, 26, 26, 26,
+ 37, 37, 37, 37, 38, 1, 38, 38,
+ 48, 26, 24, 23, 22, 2, 1, 25,
+ 25, 25, 1, 25, 27, 26, 26, 26,
+ 37, 37, 37, 37, 38, 1, 1, 1,
+ 48, 38, 2, 1, 5, 3, 4, 3
};
static const short _use_syllable_machine_index_offsets[] = {
- 0, 2, 4, 57, 96, 135, 137, 165,
- 192, 217, 241, 264, 267, 269, 295, 321,
- 347, 349, 375, 402, 429, 456, 484, 512,
- 540, 579, 628, 630, 632, 671, 674, 676,
- 715, 743, 770, 795, 819, 842, 845, 847,
- 873, 899, 925, 951, 978, 1005, 1032, 1060,
- 1088, 1116, 1155, 1204, 1206, 1208, 1210, 1259,
- 1298, 1301, 1303, 1309, 1313, 1318
+ 0, 53, 92, 131, 180, 207, 232, 256,
+ 279, 282, 284, 310, 336, 362, 364, 390,
+ 418, 445, 472, 499, 537, 575, 613, 651,
+ 690, 692, 731, 734, 736, 775, 814, 863,
+ 890, 915, 939, 962, 965, 967, 993, 1019,
+ 1045, 1047, 1073, 1101, 1128, 1155, 1182, 1220,
+ 1258, 1296, 1334, 1373, 1375, 1377, 1379, 1418,
+ 1457, 1506, 1533, 1558, 1582, 1605, 1608, 1610,
+ 1636, 1662, 1688, 1690, 1716, 1744, 1771, 1798,
+ 1825, 1863, 1901, 1939, 1977, 2016, 2018, 2057,
+ 2096, 2145, 2172, 2197, 2221, 2244, 2247, 2249,
+ 2275, 2301, 2327, 2329, 2355, 2383, 2410, 2437,
+ 2464, 2502, 2540, 2578, 2616, 2655, 2657, 2659,
+ 2661, 2710, 2749, 2752, 2754, 2760, 2764, 2769
};
static const char _use_syllable_machine_indicies[] = {
- 1, 0, 2, 0, 3, 4, 5, 5,
- 6, 7, 5, 5, 5, 5, 5, 1,
- 8, 9, 5, 5, 5, 5, 10, 11,
- 5, 5, 12, 13, 14, 15, 16, 17,
- 18, 12, 19, 20, 21, 22, 23, 24,
- 5, 25, 26, 27, 5, 28, 29, 30,
- 31, 32, 33, 34, 8, 35, 5, 36,
- 5, 38, 39, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 40, 41, 42, 43,
- 44, 45, 46, 40, 47, 4, 48, 49,
- 50, 51, 37, 52, 53, 54, 37, 37,
- 37, 37, 55, 56, 57, 58, 39, 37,
- 38, 39, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 40, 41, 42, 43, 44,
- 45, 46, 40, 47, 48, 48, 49, 50,
- 51, 37, 52, 53, 54, 37, 37, 37,
- 37, 55, 56, 57, 58, 39, 37, 38,
- 59, 40, 41, 42, 43, 44, 37, 37,
- 37, 37, 37, 37, 49, 50, 51, 37,
- 52, 53, 54, 37, 37, 37, 37, 41,
- 56, 57, 58, 60, 37, 41, 42, 43,
- 44, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 52, 53, 54, 37, 37,
- 37, 37, 37, 56, 57, 58, 60, 37,
- 42, 43, 44, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 56, 57, 58,
- 37, 43, 44, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 56, 57, 58,
- 37, 44, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 56, 57, 58, 37,
- 56, 57, 37, 57, 37, 42, 43, 44,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 52, 53, 54, 37, 37, 37,
- 37, 37, 56, 57, 58, 60, 37, 42,
- 43, 44, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 53, 54, 37,
- 37, 37, 37, 37, 56, 57, 58, 60,
- 37, 42, 43, 44, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 54, 37, 37, 37, 37, 37, 56, 57,
- 58, 60, 37, 62, 61, 42, 43, 44,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 56, 57, 58, 60, 37, 41,
- 42, 43, 44, 37, 37, 37, 37, 37,
- 37, 49, 50, 51, 37, 52, 53, 54,
- 37, 37, 37, 37, 41, 56, 57, 58,
- 60, 37, 41, 42, 43, 44, 37, 37,
- 37, 37, 37, 37, 37, 50, 51, 37,
- 52, 53, 54, 37, 37, 37, 37, 41,
- 56, 57, 58, 60, 37, 41, 42, 43,
- 44, 37, 37, 37, 37, 37, 37, 37,
- 37, 51, 37, 52, 53, 54, 37, 37,
- 37, 37, 41, 56, 57, 58, 60, 37,
- 40, 41, 42, 43, 44, 37, 46, 40,
- 37, 37, 37, 49, 50, 51, 37, 52,
- 53, 54, 37, 37, 37, 37, 41, 56,
- 57, 58, 60, 37, 40, 41, 42, 43,
- 44, 37, 37, 40, 37, 37, 37, 49,
- 50, 51, 37, 52, 53, 54, 37, 37,
- 37, 37, 41, 56, 57, 58, 60, 37,
- 40, 41, 42, 43, 44, 45, 46, 40,
- 37, 37, 37, 49, 50, 51, 37, 52,
- 53, 54, 37, 37, 37, 37, 41, 56,
- 57, 58, 60, 37, 38, 39, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 40,
- 41, 42, 43, 44, 45, 46, 40, 47,
- 37, 48, 49, 50, 51, 37, 52, 53,
- 54, 37, 37, 37, 37, 55, 56, 57,
- 58, 39, 37, 38, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 41, 42, 43, 44, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 52,
- 53, 54, 59, 59, 59, 59, 59, 56,
- 57, 58, 60, 59, 64, 63, 6, 65,
- 38, 39, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 40, 41, 42, 43, 44,
- 45, 46, 40, 47, 4, 48, 49, 50,
- 51, 37, 52, 53, 54, 37, 11, 66,
- 37, 55, 56, 57, 58, 39, 37, 11,
- 66, 67, 66, 67, 1, 69, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 12,
- 13, 14, 15, 16, 17, 18, 12, 19,
- 21, 21, 22, 23, 24, 68, 25, 26,
- 27, 68, 68, 68, 68, 31, 32, 33,
- 34, 69, 68, 12, 13, 14, 15, 16,
- 68, 68, 68, 68, 68, 68, 22, 23,
- 24, 68, 25, 26, 27, 68, 68, 68,
- 68, 13, 32, 33, 34, 70, 68, 13,
- 14, 15, 16, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 25, 26, 27,
- 68, 68, 68, 68, 68, 32, 33, 34,
- 70, 68, 14, 15, 16, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 32,
- 33, 34, 68, 15, 16, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 32,
- 33, 34, 68, 16, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 32, 33,
- 34, 68, 32, 33, 68, 33, 68, 14,
- 15, 16, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 25, 26, 27, 68,
- 68, 68, 68, 68, 32, 33, 34, 70,
- 68, 14, 15, 16, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 26,
- 27, 68, 68, 68, 68, 68, 32, 33,
- 34, 70, 68, 14, 15, 16, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 27, 68, 68, 68, 68, 68,
- 32, 33, 34, 70, 68, 14, 15, 16,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 32, 33, 34, 70, 68, 13,
- 14, 15, 16, 68, 68, 68, 68, 68,
- 68, 22, 23, 24, 68, 25, 26, 27,
- 68, 68, 68, 68, 13, 32, 33, 34,
- 70, 68, 13, 14, 15, 16, 68, 68,
- 68, 68, 68, 68, 68, 23, 24, 68,
- 25, 26, 27, 68, 68, 68, 68, 13,
- 32, 33, 34, 70, 68, 13, 14, 15,
- 16, 68, 68, 68, 68, 68, 68, 68,
- 68, 24, 68, 25, 26, 27, 68, 68,
- 68, 68, 13, 32, 33, 34, 70, 68,
- 12, 13, 14, 15, 16, 68, 18, 12,
- 68, 68, 68, 22, 23, 24, 68, 25,
- 26, 27, 68, 68, 68, 68, 13, 32,
- 33, 34, 70, 68, 12, 13, 14, 15,
- 16, 68, 68, 12, 68, 68, 68, 22,
- 23, 24, 68, 25, 26, 27, 68, 68,
- 68, 68, 13, 32, 33, 34, 70, 68,
- 12, 13, 14, 15, 16, 17, 18, 12,
- 68, 68, 68, 22, 23, 24, 68, 25,
- 26, 27, 68, 68, 68, 68, 13, 32,
- 33, 34, 70, 68, 1, 69, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 12,
- 13, 14, 15, 16, 17, 18, 12, 19,
- 68, 21, 22, 23, 24, 68, 25, 26,
- 27, 68, 68, 68, 68, 31, 32, 33,
- 34, 69, 68, 1, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 13, 14, 15, 16, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 25,
- 26, 27, 68, 68, 68, 68, 68, 32,
- 33, 34, 70, 68, 1, 71, 72, 68,
- 9, 68, 4, 68, 68, 68, 4, 68,
- 68, 68, 68, 68, 1, 69, 9, 68,
- 68, 68, 68, 68, 68, 68, 68, 12,
- 13, 14, 15, 16, 17, 18, 12, 19,
- 20, 21, 22, 23, 24, 68, 25, 26,
- 27, 68, 28, 29, 68, 31, 32, 33,
- 34, 69, 68, 1, 69, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 12, 13,
- 14, 15, 16, 17, 18, 12, 19, 20,
- 21, 22, 23, 24, 68, 25, 26, 27,
- 68, 68, 68, 68, 31, 32, 33, 34,
- 69, 68, 28, 29, 68, 29, 68, 4,
- 71, 71, 71, 4, 71, 74, 73, 35,
- 73, 35, 74, 73, 74, 73, 35, 73,
- 36, 73, 0
+ 0, 1, 2, 2, 3, 4, 2, 2,
+ 2, 2, 2, 5, 6, 7, 2, 2,
+ 2, 2, 8, 2, 2, 2, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 2, 23, 24, 25,
+ 2, 26, 27, 28, 29, 30, 31, 32,
+ 29, 33, 2, 34, 2, 36, 37, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 35, 52,
+ 53, 54, 35, 55, 56, 35, 57, 58,
+ 59, 60, 57, 35, 36, 37, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46,
+ 48, 48, 49, 50, 51, 35, 52, 53,
+ 54, 35, 35, 35, 35, 57, 58, 59,
+ 60, 57, 35, 36, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 39, 40, 41, 42, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 52,
+ 53, 54, 35, 35, 35, 35, 35, 58,
+ 59, 60, 61, 35, 39, 40, 41, 42,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 52, 53, 54, 35, 35, 35,
+ 35, 35, 58, 59, 60, 61, 35, 40,
+ 41, 42, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 58, 59, 60, 35,
+ 41, 42, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 58, 59, 60, 35,
+ 42, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 58, 59, 60, 35, 58,
+ 59, 35, 59, 35, 40, 41, 42, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 52, 53, 54, 35, 35, 35, 35,
+ 35, 58, 59, 60, 61, 35, 40, 41,
+ 42, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 53, 54, 35, 35,
+ 35, 35, 35, 58, 59, 60, 61, 35,
+ 40, 41, 42, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 54,
+ 35, 35, 35, 35, 35, 58, 59, 60,
+ 61, 35, 62, 35, 40, 41, 42, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 58, 59, 60, 61, 35, 38, 39,
+ 40, 41, 42, 35, 35, 35, 35, 35,
+ 35, 49, 50, 51, 35, 52, 53, 54,
+ 35, 35, 35, 35, 35, 58, 59, 60,
+ 61, 35, 39, 40, 41, 42, 35, 35,
+ 35, 35, 35, 35, 49, 50, 51, 35,
+ 52, 53, 54, 35, 35, 35, 35, 35,
+ 58, 59, 60, 61, 35, 39, 40, 41,
+ 42, 35, 35, 35, 35, 35, 35, 35,
+ 50, 51, 35, 52, 53, 54, 35, 35,
+ 35, 35, 35, 58, 59, 60, 61, 35,
+ 39, 40, 41, 42, 35, 35, 35, 35,
+ 35, 35, 35, 35, 51, 35, 52, 53,
+ 54, 35, 35, 35, 35, 35, 58, 59,
+ 60, 61, 35, 39, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 38, 39, 40,
+ 41, 42, 35, 44, 45, 35, 35, 35,
+ 49, 50, 51, 35, 52, 53, 54, 35,
+ 35, 35, 35, 35, 58, 59, 60, 61,
+ 35, 39, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 38, 39, 40, 41, 42,
+ 35, 35, 45, 35, 35, 35, 49, 50,
+ 51, 35, 52, 53, 54, 35, 35, 35,
+ 35, 35, 58, 59, 60, 61, 35, 39,
+ 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 38, 39, 40, 41, 42, 35, 35,
+ 35, 35, 35, 35, 49, 50, 51, 35,
+ 52, 53, 54, 35, 35, 35, 35, 35,
+ 58, 59, 60, 61, 35, 39, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 38,
+ 39, 40, 41, 42, 43, 44, 45, 35,
+ 35, 35, 49, 50, 51, 35, 52, 53,
+ 54, 35, 35, 35, 35, 35, 58, 59,
+ 60, 61, 35, 36, 37, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 35,
+ 48, 49, 50, 51, 35, 52, 53, 54,
+ 35, 35, 35, 35, 57, 58, 59, 60,
+ 57, 35, 36, 35, 36, 37, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 35, 52, 53,
+ 54, 35, 35, 35, 35, 57, 58, 59,
+ 60, 57, 35, 55, 56, 35, 56, 35,
+ 64, 65, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 1, 75, 76, 77,
+ 78, 63, 79, 80, 81, 63, 63, 63,
+ 63, 82, 83, 84, 85, 86, 63, 64,
+ 65, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 75, 76, 77, 78,
+ 63, 79, 80, 81, 63, 63, 63, 63,
+ 82, 83, 84, 85, 86, 63, 64, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 67, 68, 69, 70,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 79, 80, 81, 63, 63, 63,
+ 63, 63, 83, 84, 85, 87, 63, 67,
+ 68, 69, 70, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 79, 80, 81,
+ 63, 63, 63, 63, 63, 83, 84, 85,
+ 87, 63, 68, 69, 70, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 83,
+ 84, 85, 63, 69, 70, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 83,
+ 84, 85, 63, 70, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 83, 84,
+ 85, 63, 83, 84, 63, 84, 63, 68,
+ 69, 70, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 79, 80, 81, 63,
+ 63, 63, 63, 63, 83, 84, 85, 87,
+ 63, 68, 69, 70, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 80,
+ 81, 63, 63, 63, 63, 63, 83, 84,
+ 85, 87, 63, 68, 69, 70, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 81, 63, 63, 63, 63, 63,
+ 83, 84, 85, 87, 63, 89, 88, 68,
+ 69, 70, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 83, 84, 85, 87,
+ 63, 66, 67, 68, 69, 70, 63, 63,
+ 63, 63, 63, 63, 76, 77, 78, 63,
+ 79, 80, 81, 63, 63, 63, 63, 63,
+ 83, 84, 85, 87, 63, 67, 68, 69,
+ 70, 63, 63, 63, 63, 63, 63, 76,
+ 77, 78, 63, 79, 80, 81, 63, 63,
+ 63, 63, 63, 83, 84, 85, 87, 63,
+ 67, 68, 69, 70, 63, 63, 63, 63,
+ 63, 63, 63, 77, 78, 63, 79, 80,
+ 81, 63, 63, 63, 63, 63, 83, 84,
+ 85, 87, 63, 67, 68, 69, 70, 63,
+ 63, 63, 63, 63, 63, 63, 63, 78,
+ 63, 79, 80, 81, 63, 63, 63, 63,
+ 63, 83, 84, 85, 87, 63, 67, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 66, 67, 68, 69, 70, 63, 72, 73,
+ 63, 63, 63, 76, 77, 78, 63, 79,
+ 80, 81, 63, 63, 63, 63, 63, 83,
+ 84, 85, 87, 63, 67, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 66, 67,
+ 68, 69, 70, 63, 63, 73, 63, 63,
+ 63, 76, 77, 78, 63, 79, 80, 81,
+ 63, 63, 63, 63, 63, 83, 84, 85,
+ 87, 63, 67, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 66, 67, 68, 69,
+ 70, 63, 63, 63, 63, 63, 63, 76,
+ 77, 78, 63, 79, 80, 81, 63, 63,
+ 63, 63, 63, 83, 84, 85, 87, 63,
+ 67, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 66, 67, 68, 69, 70, 71,
+ 72, 73, 63, 63, 63, 76, 77, 78,
+ 63, 79, 80, 81, 63, 63, 63, 63,
+ 63, 83, 84, 85, 87, 63, 64, 65,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 63, 75, 76, 77, 78, 63,
+ 79, 80, 81, 63, 63, 63, 63, 82,
+ 83, 84, 85, 86, 63, 64, 90, 92,
+ 91, 3, 93, 94, 95, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 63, 110, 111, 112,
+ 63, 55, 56, 63, 113, 114, 115, 85,
+ 116, 63, 94, 95, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 106, 106,
+ 107, 108, 109, 63, 110, 111, 112, 63,
+ 63, 63, 63, 113, 114, 115, 85, 116,
+ 63, 94, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 97,
+ 98, 99, 100, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 110, 111, 112,
+ 63, 63, 63, 63, 63, 114, 115, 85,
+ 117, 63, 97, 98, 99, 100, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 110, 111, 112, 63, 63, 63, 63, 63,
+ 114, 115, 85, 117, 63, 98, 99, 100,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 114, 115, 85, 63, 99, 100,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 114, 115, 85, 63, 100, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 114, 115, 85, 63, 114, 115, 63,
+ 115, 63, 98, 99, 100, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 110,
+ 111, 112, 63, 63, 63, 63, 63, 114,
+ 115, 85, 117, 63, 98, 99, 100, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 111, 112, 63, 63, 63, 63,
+ 63, 114, 115, 85, 117, 63, 98, 99,
+ 100, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 112, 63, 63,
+ 63, 63, 63, 114, 115, 85, 117, 63,
+ 118, 88, 98, 99, 100, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 114,
+ 115, 85, 117, 63, 96, 97, 98, 99,
+ 100, 63, 63, 63, 63, 63, 63, 107,
+ 108, 109, 63, 110, 111, 112, 63, 63,
+ 63, 63, 63, 114, 115, 85, 117, 63,
+ 97, 98, 99, 100, 63, 63, 63, 63,
+ 63, 63, 107, 108, 109, 63, 110, 111,
+ 112, 63, 63, 63, 63, 63, 114, 115,
+ 85, 117, 63, 97, 98, 99, 100, 63,
+ 63, 63, 63, 63, 63, 63, 108, 109,
+ 63, 110, 111, 112, 63, 63, 63, 63,
+ 63, 114, 115, 85, 117, 63, 97, 98,
+ 99, 100, 63, 63, 63, 63, 63, 63,
+ 63, 63, 109, 63, 110, 111, 112, 63,
+ 63, 63, 63, 63, 114, 115, 85, 117,
+ 63, 97, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 96, 97, 98, 99, 100,
+ 63, 102, 103, 63, 63, 63, 107, 108,
+ 109, 63, 110, 111, 112, 63, 63, 63,
+ 63, 63, 114, 115, 85, 117, 63, 97,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 96, 97, 98, 99, 100, 63, 63,
+ 103, 63, 63, 63, 107, 108, 109, 63,
+ 110, 111, 112, 63, 63, 63, 63, 63,
+ 114, 115, 85, 117, 63, 97, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 96,
+ 97, 98, 99, 100, 63, 63, 63, 63,
+ 63, 63, 107, 108, 109, 63, 110, 111,
+ 112, 63, 63, 63, 63, 63, 114, 115,
+ 85, 117, 63, 97, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 96, 97, 98,
+ 99, 100, 101, 102, 103, 63, 63, 63,
+ 107, 108, 109, 63, 110, 111, 112, 63,
+ 63, 63, 63, 63, 114, 115, 85, 117,
+ 63, 94, 95, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 63, 106, 107,
+ 108, 109, 63, 110, 111, 112, 63, 63,
+ 63, 63, 113, 114, 115, 85, 116, 63,
+ 94, 90, 94, 95, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 63, 110, 111, 112, 63,
+ 63, 63, 63, 113, 114, 115, 85, 116,
+ 63, 5, 6, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 19, 19, 20,
+ 21, 22, 119, 23, 24, 25, 119, 119,
+ 119, 119, 29, 30, 31, 32, 29, 119,
+ 5, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 10, 11,
+ 12, 13, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 23, 24, 25, 119,
+ 119, 119, 119, 119, 30, 31, 32, 120,
+ 119, 10, 11, 12, 13, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 23,
+ 24, 25, 119, 119, 119, 119, 119, 30,
+ 31, 32, 120, 119, 11, 12, 13, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 30, 31, 32, 119, 12, 13, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 30, 31, 32, 119, 13, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 30, 31, 32, 119, 30, 31, 119, 31,
+ 119, 11, 12, 13, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 23, 24,
+ 25, 119, 119, 119, 119, 119, 30, 31,
+ 32, 120, 119, 11, 12, 13, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 24, 25, 119, 119, 119, 119, 119,
+ 30, 31, 32, 120, 119, 11, 12, 13,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 25, 119, 119, 119,
+ 119, 119, 30, 31, 32, 120, 119, 121,
+ 119, 11, 12, 13, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 30, 31,
+ 32, 120, 119, 9, 10, 11, 12, 13,
+ 119, 119, 119, 119, 119, 119, 20, 21,
+ 22, 119, 23, 24, 25, 119, 119, 119,
+ 119, 119, 30, 31, 32, 120, 119, 10,
+ 11, 12, 13, 119, 119, 119, 119, 119,
+ 119, 20, 21, 22, 119, 23, 24, 25,
+ 119, 119, 119, 119, 119, 30, 31, 32,
+ 120, 119, 10, 11, 12, 13, 119, 119,
+ 119, 119, 119, 119, 119, 21, 22, 119,
+ 23, 24, 25, 119, 119, 119, 119, 119,
+ 30, 31, 32, 120, 119, 10, 11, 12,
+ 13, 119, 119, 119, 119, 119, 119, 119,
+ 119, 22, 119, 23, 24, 25, 119, 119,
+ 119, 119, 119, 30, 31, 32, 120, 119,
+ 10, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 9, 10, 11, 12, 13, 119,
+ 15, 16, 119, 119, 119, 20, 21, 22,
+ 119, 23, 24, 25, 119, 119, 119, 119,
+ 119, 30, 31, 32, 120, 119, 10, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 9, 10, 11, 12, 13, 119, 119, 16,
+ 119, 119, 119, 20, 21, 22, 119, 23,
+ 24, 25, 119, 119, 119, 119, 119, 30,
+ 31, 32, 120, 119, 10, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 9, 10,
+ 11, 12, 13, 119, 119, 119, 119, 119,
+ 119, 20, 21, 22, 119, 23, 24, 25,
+ 119, 119, 119, 119, 119, 30, 31, 32,
+ 120, 119, 10, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 9, 10, 11, 12,
+ 13, 14, 15, 16, 119, 119, 119, 20,
+ 21, 22, 119, 23, 24, 25, 119, 119,
+ 119, 119, 119, 30, 31, 32, 120, 119,
+ 5, 6, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 119, 19, 20, 21,
+ 22, 119, 23, 24, 25, 119, 119, 119,
+ 119, 29, 30, 31, 32, 29, 119, 5,
+ 119, 122, 119, 7, 119, 1, 119, 119,
+ 119, 1, 119, 119, 119, 119, 119, 5,
+ 6, 7, 119, 119, 119, 119, 119, 119,
+ 119, 119, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22,
+ 119, 23, 24, 25, 119, 26, 27, 119,
+ 29, 30, 31, 32, 29, 119, 5, 6,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 119,
+ 23, 24, 25, 119, 119, 119, 119, 29,
+ 30, 31, 32, 29, 119, 26, 27, 119,
+ 27, 119, 1, 123, 123, 123, 1, 123,
+ 125, 124, 33, 124, 33, 125, 124, 125,
+ 124, 33, 124, 34, 124, 0
};
static const char _use_syllable_machine_trans_targs[] = {
- 2, 31, 42, 2, 3, 2, 26, 28,
- 51, 52, 54, 29, 32, 33, 34, 35,
- 36, 46, 47, 48, 55, 49, 43, 44,
- 45, 39, 40, 41, 56, 57, 58, 50,
- 37, 38, 2, 59, 61, 2, 4, 5,
- 6, 7, 8, 9, 10, 21, 22, 23,
- 24, 18, 19, 20, 13, 14, 15, 25,
- 11, 12, 2, 2, 16, 2, 17, 2,
- 27, 2, 30, 2, 2, 0, 1, 2,
- 53, 2, 60
+ 1, 28, 0, 52, 54, 79, 80, 102,
+ 104, 92, 81, 82, 83, 84, 96, 97,
+ 98, 99, 105, 100, 93, 94, 95, 87,
+ 88, 89, 106, 107, 108, 101, 85, 86,
+ 0, 109, 111, 0, 2, 3, 15, 4,
+ 5, 6, 7, 19, 20, 21, 22, 25,
+ 23, 16, 17, 18, 10, 11, 12, 26,
+ 27, 24, 8, 9, 0, 13, 14, 0,
+ 29, 30, 42, 31, 32, 33, 34, 46,
+ 47, 48, 49, 50, 43, 44, 45, 37,
+ 38, 39, 51, 35, 36, 0, 51, 40,
+ 0, 41, 0, 0, 53, 0, 55, 56,
+ 68, 57, 58, 59, 60, 72, 73, 74,
+ 75, 78, 76, 69, 70, 71, 63, 64,
+ 65, 77, 61, 62, 77, 66, 67, 0,
+ 90, 91, 103, 0, 0, 110
};
static const char _use_syllable_machine_trans_actions[] = {
- 1, 2, 2, 5, 0, 6, 0, 0,
- 0, 0, 2, 0, 2, 2, 0, 0,
- 0, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 0, 0, 0, 2,
- 0, 0, 7, 0, 0, 8, 0, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 6, 0, 0, 7,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 9, 10, 0, 11, 0, 12,
- 0, 13, 0, 14, 15, 0, 0, 16,
- 0, 17, 0
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 8, 0, 0, 9, 10, 0,
+ 11, 0, 12, 13, 0, 14, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 0, 0, 10, 0, 0, 15,
+ 0, 0, 0, 16, 17, 0
};
static const char _use_syllable_machine_to_state_actions[] = {
- 0, 0, 3, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
};
static const char _use_syllable_machine_from_state_actions[] = {
- 0, 0, 4, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
};
static const short _use_syllable_machine_eof_trans[] = {
- 1, 1, 0, 38, 38, 60, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38,
- 62, 38, 38, 38, 38, 38, 38, 38,
- 38, 60, 64, 66, 38, 68, 68, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 72, 69, 69, 69, 69,
- 69, 69, 72, 74, 74, 74
+ 0, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64,
+ 89, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 91, 92, 94, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 89, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 91, 64, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 124, 125, 125, 125
};
-static const int use_syllable_machine_start = 2;
-static const int use_syllable_machine_first_final = 2;
+static const int use_syllable_machine_start = 0;
+static const int use_syllable_machine_first_final = 0;
static const int use_syllable_machine_error = -1;
-static const int use_syllable_machine_en_main = 2;
+static const int use_syllable_machine_en_main = 0;
-#line 59 "hb-ot-shape-complex-use-machine.rl"
+#line 58 "hb-ot-shape-complex-use-machine.rl"
-#line 176 "hb-ot-shape-complex-use-machine.rl"
+#line 181 "hb-ot-shape-complex-use-machine.rl"
#define found_syllable(syllable_type) \
@@ -388,7 +618,9 @@ struct machine_index_t :
typename Iter::item_t>
{
machine_index_t (const Iter& it) : it (it) {}
- machine_index_t (const machine_index_t& o) : it (o.it) {}
+ machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
+ typename Iter::item_t> (),
+ it (o.it), is_null (o.is_null) {}
static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
@@ -400,14 +632,28 @@ struct machine_index_t :
void __forward__ (unsigned n) { it += n; }
void __prev__ () { --it; }
void __rewind__ (unsigned n) { it -= n; }
+
void operator = (unsigned n)
- { unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; }
- void operator = (const machine_index_t& o) { *this = (*o.it).first; }
- bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; }
+ {
+ assert (n == 0);
+ is_null = true;
+ }
+ explicit operator bool () { return !is_null; }
+
+ void operator = (const machine_index_t& o)
+ {
+ is_null = o.is_null;
+ unsigned index = (*it).first;
+ unsigned n = (*o.it).first;
+ if (index < n) it += n - index; else if (index > n) it -= index - n;
+ }
+ bool operator == (const machine_index_t& o) const
+ { return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
bool operator != (const machine_index_t& o) const { return !(*this == o); }
private:
Iter it;
+ bool is_null = false;
};
struct
{
@@ -422,8 +668,8 @@ HB_FUNCOBJ (machine_index);
static bool
-not_standard_default_ignorable (const hb_glyph_info_t &i)
-{ return !(i.use_category() == USE(O) && _hb_glyph_info_is_default_ignorable (&i)); }
+not_ccs_default_ignorable (const hb_glyph_info_t &i)
+{ return i.use_category() != USE(CGJ); }
static inline void
find_syllables_use (hb_buffer_t *buffer)
@@ -432,13 +678,13 @@ find_syllables_use (hb_buffer_t *buffer)
auto p =
+ hb_iter (info, buffer->len)
| hb_enumerate
- | hb_filter ([] (const hb_glyph_info_t &i) { return not_standard_default_ignorable (i); },
+ | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
hb_second)
| hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
{
if (p.second.use_category() == USE(ZWNJ))
for (unsigned i = p.first + 1; i < buffer->len; ++i)
- if (not_standard_default_ignorable (info[i]))
+ if (not_ccs_default_ignorable (info[i]))
return !_hb_glyph_info_is_unicode_mark (&info[i]);
return true;
})
@@ -452,7 +698,7 @@ find_syllables_use (hb_buffer_t *buffer)
unsigned int act HB_UNUSED;
int cs;
-#line 456 "hb-ot-shape-complex-use-machine.hh"
+#line 702 "hb-ot-shape-complex-use-machine.hh"
{
cs = use_syllable_machine_start;
ts = 0;
@@ -460,12 +706,12 @@ find_syllables_use (hb_buffer_t *buffer)
act = 0;
}
-#line 260 "hb-ot-shape-complex-use-machine.rl"
+#line 281 "hb-ot-shape-complex-use-machine.rl"
unsigned int syllable_serial = 1;
-#line 469 "hb-ot-shape-complex-use-machine.hh"
+#line 715 "hb-ot-shape-complex-use-machine.hh"
{
int _slen;
int _trans;
@@ -475,11 +721,11 @@ find_syllables_use (hb_buffer_t *buffer)
goto _test_eof;
_resume:
switch ( _use_syllable_machine_from_state_actions[cs] ) {
- case 4:
+ case 2:
#line 1 "NONE"
{ts = p;}
break;
-#line 483 "hb-ot-shape-complex-use-machine.hh"
+#line 729 "hb-ot-shape-complex-use-machine.hh"
}
_keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -497,76 +743,88 @@ _eof_trans:
goto _again;
switch ( _use_syllable_machine_trans_actions[_trans] ) {
- case 2:
-#line 1 "NONE"
- {te = p+1;}
- break;
- case 5:
-#line 163 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_independent_cluster); }}
- break;
case 9:
-#line 166 "hb-ot-shape-complex-use-machine.rl"
+#line 171 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (use_standard_cluster); }}
break;
- case 7:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
+ case 6:
+#line 174 "hb-ot-shape-complex-use-machine.rl"
+ {te = p+1;{ found_syllable (use_symbol_cluster); }}
+ break;
+ case 4:
+#line 176 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (use_broken_cluster); }}
break;
- case 6:
-#line 172 "hb-ot-shape-complex-use-machine.rl"
+ case 3:
+#line 177 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (use_non_cluster); }}
break;
- case 10:
-#line 164 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_virama_terminated_cluster); }}
- break;
case 11:
-#line 165 "hb-ot-shape-complex-use-machine.rl"
+#line 170 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
break;
- case 8:
-#line 166 "hb-ot-shape-complex-use-machine.rl"
+ case 7:
+#line 171 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_standard_cluster); }}
break;
- case 13:
-#line 167 "hb-ot-shape-complex-use-machine.rl"
+ case 14:
+#line 172 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
break;
- case 12:
-#line 168 "hb-ot-shape-complex-use-machine.rl"
+ case 13:
+#line 173 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_numeral_cluster); }}
break;
- case 14:
-#line 169 "hb-ot-shape-complex-use-machine.rl"
+ case 5:
+#line 174 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_symbol_cluster); }}
break;
case 17:
-#line 170 "hb-ot-shape-complex-use-machine.rl"
+#line 175 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
break;
case 15:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
+#line 176 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_broken_cluster); }}
break;
case 16:
-#line 172 "hb-ot-shape-complex-use-machine.rl"
+#line 177 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_non_cluster); }}
break;
+ case 12:
+#line 1 "NONE"
+ { switch( act ) {
case 1:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
- {{p = ((te))-1;}{ found_syllable (use_broken_cluster); }}
+ {{p = ((te))-1;} found_syllable (use_virama_terminated_cluster); }
break;
-#line 561 "hb-ot-shape-complex-use-machine.hh"
+ case 2:
+ {{p = ((te))-1;} found_syllable (use_sakot_terminated_cluster); }
+ break;
+ }
+ }
+ break;
+ case 8:
+#line 1 "NONE"
+ {te = p+1;}
+#line 169 "hb-ot-shape-complex-use-machine.rl"
+ {act = 1;}
+ break;
+ case 10:
+#line 1 "NONE"
+ {te = p+1;}
+#line 170 "hb-ot-shape-complex-use-machine.rl"
+ {act = 2;}
+ break;
+#line 819 "hb-ot-shape-complex-use-machine.hh"
}
_again:
switch ( _use_syllable_machine_to_state_actions[cs] ) {
- case 3:
+ case 1:
#line 1 "NONE"
{ts = 0;}
break;
-#line 570 "hb-ot-shape-complex-use-machine.hh"
+#line 828 "hb-ot-shape-complex-use-machine.hh"
}
if ( ++p != pe )
@@ -582,7 +840,7 @@ _again:
}
-#line 265 "hb-ot-shape-complex-use-machine.rl"
+#line 286 "hb-ot-shape-complex-use-machine.rl"
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.hh
index 7903a0ef89..ea627cd27e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.hh
@@ -2,7 +2,7 @@
/*
* The following table is generated by running:
*
- * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt ArabicShaping.txt Blocks.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
+ * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
*
* on files with these headers:
*
@@ -12,22 +12,28 @@
* # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
* # ArabicShaping-14.0.0.txt
* # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
+ * # DerivedCoreProperties-14.0.0.txt
+ * # Date: 2021-08-12, 23:12:53 GMT
* # Blocks-14.0.0.txt
* # Date: 2021-01-22, 23:29:00 GMT [KW]
+ * # Scripts-14.0.0.txt
+ * # Date: 2021-07-10, 00:35:31 GMT
* # Override values For Indic_Syllabic_Category
* # Not derivable
* # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
- * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
- * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
* # Override values For Indic_Positional_Category
* # Not derivable
* # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
* # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
- * # Updated for L2/19-083 by Andrew Glass 2019-05-06
- * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
- * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for L2/19-083 by Andrew Glass 2019-05-06
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
* UnicodeData.txt does not have a header.
*/
@@ -41,21 +47,22 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"
#define B USE(B) /* BASE */
+#define CGJ USE(CGJ) /* CGJ */
#define CS USE(CS) /* CONS_WITH_STACKER */
#define G USE(G) /* HIEROGLYPH */
#define GB USE(GB) /* BASE_OTHER */
#define H USE(H) /* HALANT */
#define HN USE(HN) /* HALANT_NUM */
-#define HVM USE(HVM) /* HALANT_OR_VOWEL_MODIFIER */
+#define IS USE(IS) /* INVISIBLE_STACKER */
#define J USE(J) /* HIEROGLYPH_JOINER */
#define N USE(N) /* BASE_NUM */
#define O USE(O) /* OTHER */
#define R USE(R) /* REPHA */
-#define S USE(S) /* SYM */
#define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
#define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */
#define SUB USE(SUB) /* CONS_SUB */
#define Sk USE(Sk) /* SAKOT */
+#define WJ USE(WJ) /* Word_Joiner */
#define ZWNJ USE(ZWNJ) /* ZWNJ */
#define CMAbv USE(CMAbv)
#define CMBlw USE(CMBlw)
@@ -96,36 +103,42 @@ static const uint8_t use_table[] = {
/* Latin-1 Supplement */
- /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O, O,
/* 00B0 */ O, O, FMPst, FMPst, O, O, O, O, O, O, O, O, O, O, O, O,
/* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 00D0 */ O, O, O, O, O, O, O, GB,
-#define use_offset_0x0640u 80
+#define use_offset_0x0348u 80
+
+
+ /* Combining Diacritical Marks */
+ O, O, O, O, O, O, O, CGJ,
+
+#define use_offset_0x0640u 88
/* Arabic */
/* 0640 */ B, O, O, O, O, O, O, O,
-#define use_offset_0x07c8u 88
+#define use_offset_0x07c8u 96
/* NKo */
O, O, B, B, B, B, B, B,
/* 07D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 07E0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
- /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, O, O, O, B, O, O, VMAbv, O, O,
+ /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, O, O, O, B, WJ, WJ, VMAbv, O, O,
-#define use_offset_0x0840u 144
+#define use_offset_0x0840u 152
/* Mandaic */
/* 0840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0850 */ B, B, B, B, B, B, B, B, B, CMBlw, CMBlw, CMBlw, O, O, O, O,
+ /* 0850 */ B, B, B, B, B, B, B, B, B, CMBlw, CMBlw, CMBlw, WJ, WJ, O, WJ,
-#define use_offset_0x0900u 176
+#define use_offset_0x0900u 184
/* Devanagari */
@@ -141,104 +154,104 @@ static const uint8_t use_table[] = {
/* Bengali */
- /* 0980 */ GB, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
- /* 0990 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 09A0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 09B0 */ B, O, B, O, O, O, B, B, B, B, O, O, CMBlw, B, VPst, VPre,
- /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O,
- /* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B,
- /* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FMAbv, O,
+ /* 0980 */ GB, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B,
+ /* 0990 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 09A0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
+ /* 09B0 */ B, WJ, B, WJ, WJ, WJ, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre,
+ /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, O, WJ,
+ /* 09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, B, B, WJ, B,
+ /* 09E0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FMAbv, WJ,
/* Gurmukhi */
- /* 0A00 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, O, O, O, O, B,
- /* 0A10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0A20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0A30 */ B, O, B, B, O, B, B, O, B, B, O, O, CMBlw, O, VPst, VPre,
- /* 0A40 */ VPst, VBlw, VBlw, O, O, O, O, VAbv, VAbv, O, O, VAbv, VAbv, H, O, O,
- /* 0A50 */ O, VMBlw, O, O, O, O, O, O, O, B, B, B, B, O, B, O,
- /* 0A60 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, O, O, O, O, O, O, O, O, O,
+ /* 0A00 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B,
+ /* 0A10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 0A20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
+ /* 0A30 */ B, WJ, B, B, WJ, B, B, WJ, B, B, WJ, WJ, CMBlw, WJ, VPst, VPre,
+ /* 0A40 */ VPst, VBlw, VBlw, WJ, WJ, WJ, WJ, VAbv, VAbv, WJ, WJ, VAbv, VAbv, H, WJ, WJ,
+ /* 0A50 */ WJ, VMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, WJ, B, WJ,
+ /* 0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Gujarati */
- /* 0A80 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, B, B, B, O, B,
- /* 0A90 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0AA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0AB0 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPre,
- /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H, O, O,
- /* 0AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 0AE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0AF0 */ O, O, O, O, O, O, O, O, O, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv,
+ /* 0A80 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, B, B, B, WJ, B,
+ /* 0A90 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 0AA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
+ /* 0AB0 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre,
+ /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, WJ, VAbv, VAbv, VAbv, WJ, VPst, VPst, H, WJ, WJ,
+ /* 0AD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 0AE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 0AF0 */ O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv,
/* Oriya */
- /* 0B00 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
- /* 0B10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0B20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0B30 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv,
- /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O,
- /* 0B50 */ O, O, O, O, O, VAbv, VAbv, VAbv, O, O, O, O, B, B, O, B,
- /* 0B60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0B70 */ O, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 0B00 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B,
+ /* 0B10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 0B20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
+ /* 0B30 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv,
+ /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ,
+ /* 0B50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ, B, B, WJ, B,
+ /* 0B60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 0B70 */ O, B, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Tamil */
- /* 0B80 */ O, O, VMAbv, O, O, B, B, B, B, B, B, O, O, O, B, B,
- /* 0B90 */ B, O, B, B, B, B, O, O, O, B, B, O, B, O, B, B,
- /* 0BA0 */ O, O, O, B, B, O, O, O, B, B, B, O, O, O, B, B,
- /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, VPst, VPst,
- /* 0BC0 */ VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, O, O,
- /* 0BD0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O,
- /* 0BE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 0B80 */ WJ, WJ, VMAbv, O, WJ, B, B, B, B, B, B, WJ, WJ, WJ, B, B,
+ /* 0B90 */ B, WJ, B, B, B, B, WJ, WJ, WJ, B, B, WJ, B, WJ, B, B,
+ /* 0BA0 */ WJ, WJ, WJ, B, B, WJ, WJ, WJ, B, B, B, WJ, WJ, WJ, B, B,
+ /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, VPst, VPst,
+ /* 0BC0 */ VAbv, VPst, VPst, WJ, WJ, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, WJ, WJ,
+ /* 0BD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ,
/* Telugu */
- /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, O, B, B,
- /* 0C10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0C20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, CMBlw, B, VAbv, VAbv,
- /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O,
- /* 0C50 */ O, O, O, O, O, VAbv, VBlw, O, B, B, B, O, O, O, O, O,
- /* 0C60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0C70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, WJ, B, B,
+ /* 0C10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 0C20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
+ /* 0C30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, CMBlw, B, VAbv, VAbv,
+ /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ,
+ /* 0C50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VBlw, WJ, B, B, B, WJ, WJ, O, WJ, WJ,
+ /* 0C60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, O, O, O, O,
/* Kannada */
- /* 0C80 */ B, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B,
- /* 0C90 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0CA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0CB0 */ B, B, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv,
- /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O,
- /* 0CD0 */ O, O, O, O, O, VPst, VPst, O, O, O, O, O, O, O, B, O,
- /* 0CE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0CF0 */ O, CS, CS, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 0C80 */ B, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, WJ, B, B,
+ /* 0C90 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 0CA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
+ /* 0CB0 */ B, B, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv,
+ /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ,
+ /* 0CD0 */ WJ, WJ, WJ, WJ, WJ, VPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, O, B, WJ,
+ /* 0CE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 0CF0 */ WJ, CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Malayalam */
- /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, B, B, B, B, B, B, B, B, B, O, B, B,
- /* 0D10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, B, B, B, B, B, B, B, B, B, WJ, B, B,
+ /* 0D10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, VAbv, VAbv, B, VPst, VPst,
- /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O,
- /* 0D50 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, B,
- /* 0D60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
+ /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, R, O,
+ /* 0D50 */ WJ, WJ, WJ, WJ, O, O, O, VPst, O, O, O, O, O, O, O, B,
+ /* 0D60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
/* 0D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Sinhala */
- /* 0D80 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, B, B, B,
- /* 0D90 */ B, B, B, B, B, B, B, O, O, O, B, B, B, B, B, B,
+ /* 0D80 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, B, B, B,
+ /* 0D90 */ B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B, B, B, B,
/* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0DB0 */ B, B, O, B, B, B, B, B, B, B, B, B, O, B, O, O,
- /* 0DC0 */ B, B, B, B, B, B, B, O, O, O, H, O, O, O, O, VPst,
- /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, O, VBlw, O, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst,
- /* 0DE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0DF0 */ O, O, VPst, VPst, O, O, O, O,
+ /* 0DB0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, WJ, B, WJ, WJ,
+ /* 0DC0 */ B, B, B, B, B, B, B, WJ, WJ, WJ, H, WJ, WJ, WJ, WJ, VPst,
+ /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, WJ, VBlw, WJ, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst,
+ /* 0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 0DF0 */ WJ, WJ, VPst, VPst, O, WJ, WJ, WJ,
-#define use_offset_0x0f00u 1448
+#define use_offset_0x0f00u 1456
/* Tibetan */
@@ -247,17 +260,17 @@ static const uint8_t use_table[] = {
/* 0F10 */ O, O, O, O, O, O, O, O, VBlw, VBlw, O, O, O, O, O, O,
/* 0F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0F30 */ B, B, B, B, O, FBlw, O, FBlw, O, CMAbv, O, O, O, O, VPst, VPre,
- /* 0F40 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B,
+ /* 0F40 */ B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, B,
/* 0F50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O,
- /* 0F70 */ O, CMBlw, VBlw, VAbv, VAbv, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VMAbv, O,
+ /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
+ /* 0F70 */ WJ, CMBlw, VBlw, VAbv, VAbv, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VMAbv, O,
/* 0F80 */ VBlw, VAbv, VMAbv, VMAbv, VBlw, O, VMAbv, VMAbv, B, B, B, B, B, SUB, SUB, SUB,
- /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
+ /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
/* 0FA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, O, O,
+ /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, O, O,
/* 0FC0 */ O, O, O, O, O, O, FBlw, O,
-#define use_offset_0x1000u 1648
+#define use_offset_0x1000u 1656
/* Myanmar */
@@ -265,7 +278,7 @@ static const uint8_t use_table[] = {
/* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1020 */ B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VAbv, VAbv, VBlw,
- /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, H, VAbv, MPst, MPre, MBlw, MBlw, B,
+ /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B,
/* 1040 */ B, B, B, B, B, B, B, B, B, B, O, GB, O, O, GB, O,
/* 1050 */ B, B, B, B, B, B, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw,
/* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B,
@@ -273,99 +286,99 @@ static const uint8_t use_table[] = {
/* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst,
/* 1090 */ B, B, B, B, B, B, B, B, B, B, VMPst, VMPst, VPst, VAbv, O, O,
-#define use_offset_0x1700u 1808
+#define use_offset_0x1700u 1816
/* Tagalog */
/* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1710 */ B, B, VAbv, VBlw, VBlw, VPst, O, O, O, O, O, O, O, O, O, B,
+ /* 1710 */ B, B, VAbv, VBlw, VBlw, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B,
/* Hanunoo */
/* 1720 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1730 */ B, B, VAbv, VBlw, VPst, O, O, O, O, O, O, O, O, O, O, O,
+ /* 1730 */ B, B, VAbv, VBlw, VPst, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Buhid */
/* 1740 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1750 */ B, B, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 1750 */ B, B, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Tagbanwa */
- /* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, B,
- /* 1770 */ B, O, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B, B,
+ /* 1770 */ B, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Khmer */
/* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 17B0 */ B, B, B, B, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre,
+ /* 17B0 */ B, B, B, B, CGJ, CGJ, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre,
/* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FMAbv, FAbv, CMAbv, FMAbv, VMAbv,
- /* 17D0 */ FMAbv, VAbv, H, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, O, O,
- /* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 17F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 17D0 */ FMAbv, VAbv, IS, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, WJ, WJ,
+ /* 17E0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 17F0 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
/* Mongolian */
- /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, O, O, O, O, O,
- /* 1810 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, CGJ, CGJ, CGJ, WJ, CGJ,
+ /* 1810 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
/* 1820 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1830 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1870 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
+ /* 1870 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* 1880 */ GB, GB, GB, GB, GB, CMAbv, CMAbv, B, B, B, B, B, B, B, B, B,
/* 1890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18A0 */ B, B, B, B, B, B, B, B, B, CMBlw, B, O, O, O, O, O,
+ /* 18A0 */ B, B, B, B, B, B, B, B, B, CMBlw, B, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x1900u 2240
+#define use_offset_0x1900u 2248
/* Limbu */
/* 1900 */ GB, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O,
- /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, O, O, O, O,
- /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VMAbv, FMBlw, O, O, O, O,
- /* 1940 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
+ /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ,
+ /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, WJ, WJ, WJ, WJ,
+ /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VMAbv, FMBlw, WJ, WJ, WJ, WJ,
+ /* 1940 */ O, WJ, WJ, WJ, O, O, B, B, B, B, B, B, B, B, B, B,
/* Tai Le */
/* 1950 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, O,
- /* 1970 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O,
+ /* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ,
+ /* 1970 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* New Tai Lue */
/* 1980 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
+ /* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ,
/* 19B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, O, O, O, O, O, O,
- /* 19D0 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O,
+ /* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 19D0 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, O, O,
/* 19E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 19F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Buginese */
/* 1A00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A10 */ B, B, B, B, B, B, B, VAbv, VAbv, VPre, VPst, VAbv, O, O, O, O,
+ /* 1A10 */ B, B, B, B, B, B, B, VAbv, VAbv, VPre, VPst, VAbv, WJ, WJ, O, O,
/* Tai Tham */
/* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, O,
+ /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, WJ,
/* 1A60 */ Sk, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre,
- /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, VMAbv, VMAbv, O, O, VMBlw,
- /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, VMAbv, VMAbv, WJ, WJ, VMBlw,
+ /* 1A80 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 1A90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x1b00u 2656
+#define use_offset_0x1b00u 2664
/* Balinese */
@@ -374,16 +387,16 @@ static const uint8_t use_table[] = {
/* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre,
- /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, O, O, O,
- /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, GB, GB, O, O, GB,
- /* 1B60 */ O, S, GB, S, S, S, S, S, GB, S, S, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
- /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
+ /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* 1B60 */ O, O, O, O, O, O, O, O, O, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
+ /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, WJ,
/* Sundanese */
/* 1B80 */ VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, H, SUB, SUB, B, B,
+ /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, IS, SUB, SUB, B, B,
/* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* Batak */
@@ -391,60 +404,62 @@ static const uint8_t use_table[] = {
/* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BE0 */ B, B, B, B, B, B, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv,
- /* 1BF0 */ FAbv, FAbv, CMBlw, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 1BF0 */ FAbv, FAbv, CMBlw, CMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O,
/* Lepcha */
/* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv,
- /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, O, O, O, O, O, O, O, O,
- /* 1C40 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, B, B,
+ /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, WJ, WJ, WJ, O, O, O, O, O,
+ /* 1C40 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B,
-#define use_offset_0x1cd0u 2992
+#define use_offset_0x1cd0u 3000
/* Vedic Extensions */
/* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw,
/* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O,
- /* 1CF0 */ O, O, O, O, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, GB, O, O, O, O, O,
+ /* 1CF0 */ O, O, O, O, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, GB, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x1df8u 3040
+#define use_offset_0x1df8u 3048
/* Combining Diacritical Marks Supplement */
O, O, O, FMAbv, O, O, O, O,
-#define use_offset_0x2008u 3048
+#define use_offset_0x2008u 3056
/* General Punctuation */
- O, O, O, O, ZWNJ, O, O, O,
- /* 2010 */ GB, GB, GB, GB, GB, O, O, O,
-
-#define use_offset_0x2070u 3064
-
+ O, O, O, WJ, ZWNJ, CGJ, WJ, WJ,
+ /* 2010 */ GB, GB, GB, GB, GB, O, O, O, O, O, O, O, O, O, O, O,
+ /* 2020 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, O,
+ /* 2030 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 2040 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 2050 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 2060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Superscripts and Subscripts */
- /* 2070 */ O, O, O, O, FMPst, O, O, O, O, O, O, O, O, O, O, O,
+ /* 2070 */ O, O, WJ, WJ, FMPst, O, O, O, O, O, O, O, O, O, O, O,
/* 2080 */ O, O, FMPst, FMPst, FMPst, O, O, O,
-#define use_offset_0x20f0u 3088
+#define use_offset_0x20f0u 3184
/* Combining Diacritical Marks for Symbols */
- /* 20F0 */ VMAbv, O, O, O, O, O, O, O,
+ /* 20F0 */ VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x25c8u 3096
+#define use_offset_0x25c8u 3192
/* Geometric Shapes */
O, O, O, O, B, O, O, O,
-#define use_offset_0x2d30u 3104
+#define use_offset_0x2d30u 3200
/* Tifinagh */
@@ -452,25 +467,25 @@ static const uint8_t use_table[] = {
/* 2D30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 2D40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 2D50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D60 */ B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, B,
- /* 2D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, H,
+ /* 2D60 */ B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B,
+ /* 2D70 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, H,
-#define use_offset_0xa800u 3184
+#define use_offset_0xa800u 3280
/* Syloti Nagri */
/* A800 */ B, B, VAbv, B, B, B, H, B, B, B, B, VMAbv, B, B, B, B,
/* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, VBlw, O, O, O,
- /* A830 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, VBlw, WJ, WJ, WJ,
+ /* A830 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
/* Phags-pa */
/* A840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A870 */ B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* A870 */ B, B, B, B, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Saurashtra */
@@ -478,8 +493,8 @@ static const uint8_t use_table[] = {
/* A890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A8B0 */ B, B, B, B, MPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst,
- /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, O, O, O, O, O, O, O, O, O, O,
- /* A8D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O,
+ /* A8D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
/* Devanagari Extended */
@@ -496,9 +511,9 @@ static const uint8_t use_table[] = {
/* A930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A940 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VBlw, VBlw, VBlw, VBlw, FAbv,
- /* A950 */ FAbv, FAbv, FPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* A950 */ FAbv, FAbv, FPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O,
/* A960 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ,
/* Javanese */
@@ -506,22 +521,22 @@ static const uint8_t use_table[] = {
/* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, MBlw, MPst, MBlw,
- /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* A9D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O,
+ /* A9D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O,
/* Myanmar Extended-B */
/* A9E0 */ B, B, B, B, B, VAbv, O, B, B, B, B, B, B, B, B, B,
- /* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O,
+ /* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ,
/* Cham */
/* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AA20 */ B, B, B, B, B, B, B, B, B, VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre,
- /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MAbv, MBlw, O, O, O, O, O, O, O, O, O,
- /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, O, O,
- /* AA50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MAbv, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, WJ, WJ,
+ /* AA50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, O, O, O,
/* Myanmar Extended-A */
@@ -534,92 +549,128 @@ static const uint8_t use_table[] = {
/* AA90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AAA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AAB0 */ VAbv, B, VAbv, VAbv, VBlw, B, B, VAbv, VAbv, B, B, B, B, B, VAbv, VMAbv,
- /* AAC0 */ B, VMAbv, B, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* AAD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* AAC0 */ B, VMAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* AAD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O,
/* Meetei Mayek Extensions */
/* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst,
- /* AAF0 */ O, O, O, O, O, VMPst, H, O,
+ /* AAF0 */ O, O, O, O, O, VMPst, IS, WJ,
-#define use_offset_0xabc0u 3944
+#define use_offset_0xabc0u 4040
/* Meetei Mayek */
/* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* ABD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O,
- /* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, WJ, WJ,
+ /* ABF0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
+
+#define use_offset_0xfe00u 4104
+
+
+ /* Variation Selectors */
+
+ /* FE00 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+
+#define use_offset_0xfef8u 4120
+
+
+ /* Arabic Presentation Forms-B */
+ O, O, O, O, O, WJ, WJ, WJ,
+
+#define use_offset_0xfff0u 4128
+
+
+ /* Specials */
+
+ /* FFF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, WJ, WJ,
+
+#define use_offset_0x10570u 4144
+
+
+ /* Vithkuqi */
-#define use_offset_0x10a00u 4008
+ /* 10570 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B,
+ /* 10580 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B,
+ /* 10590 */ B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B, B,
+ /* 105A0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 105B0 */ B, B, WJ, B, B, B, B, B, B, B, WJ, B, B, WJ, WJ, WJ,
+
+#define use_offset_0x10a00u 4224
/* Kharoshthi */
- /* 10A00 */ B, VBlw, VBlw, VBlw, O, VAbv, VBlw, O, O, O, O, O, VPst, VMBlw, VMBlw, VMAbv,
- /* 10A10 */ B, B, B, B, O, B, B, B, O, B, B, B, B, B, B, B,
+ /* 10A00 */ B, VBlw, VBlw, VBlw, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, VPst, VMBlw, VMBlw, VMAbv,
+ /* 10A10 */ B, B, B, B, WJ, B, B, B, WJ, B, B, B, B, B, B, B,
/* 10A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10A30 */ B, B, B, B, B, B, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H,
- /* 10A40 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
+ /* 10A30 */ B, B, B, B, B, B, WJ, WJ, CMAbv, CMBlw, CMBlw, WJ, WJ, WJ, WJ, IS,
+ /* 10A40 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x10ac0u 4088
+#define use_offset_0x10ac0u 4304
/* Manichaean */
/* 10AC0 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B,
/* 10AD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, O,
+ /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, WJ, WJ, WJ, WJ, B, B, B, B, B,
-#define use_offset_0x10b80u 4128
+#define use_offset_0x10b80u 4352
/* Psalter Pahlavi */
/* 10B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10B90 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 10BA0 */ O, O, O, O, O, O, O, O, O, B, B, B, B, B, B, O,
+ /* 10B90 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, WJ, WJ, WJ,
+ /* 10BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, O,
-#define use_offset_0x10d00u 4176
+#define use_offset_0x10d00u 4400
/* Hanifi Rohingya */
/* 10D00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 10D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10D20 */ B, B, B, B, VMAbv, VMAbv, VMAbv, CMAbv, O, O, O, O, O, O, O, O,
- /* 10D30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* 10D20 */ B, B, B, B, VMAbv, VMAbv, VMAbv, CMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 10D30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x10e80u 4240
+#define use_offset_0x10e80u 4464
/* Yezidi */
/* 10E80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 10E90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10EA0 */ B, B, B, B, B, B, B, B, B, B, O, VAbv, VAbv, O, O, O,
- /* 10EB0 */ B, B, O, O, O, O, O, O,
+ /* 10EA0 */ B, B, B, B, B, B, B, B, B, B, WJ, VAbv, VAbv, O, WJ, WJ,
+ /* 10EB0 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x10f30u 4296
+#define use_offset_0x10f30u 4520
/* Sogdian */
/* 10F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 10F40 */ B, B, B, B, B, B, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,
- /* 10F50 */ VMBlw, B, B, B, B, O, O, O,
+ /* 10F50 */ VMBlw, B, B, B, B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 10F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x10fb0u 4336
+ /* Old Uyghur */
+ /* 10F70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 10F80 */ B, B, CMBlw, CMBlw, CMBlw, CMBlw, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 10F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 10FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Chorasmian */
/* 10FB0 */ B, O, B, B, B, B, B, O, B, B, B, B, B, B, B, B,
- /* 10FC0 */ O, B, B, B, B, O, O, O, O, B, B, B, O, O, O, O,
- /* 10FD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 10FC0 */ O, B, B, B, B, O, O, O, O, B, B, B, WJ, WJ, WJ, WJ,
+ /* 10FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* 10FE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 10FF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 10FF0 */ O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Brahmi */
@@ -627,10 +678,10 @@ static const uint8_t use_table[] = {
/* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw,
- /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, HVM, O, O, O, O, O, O, O, O, O,
- /* 11050 */ O, O, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
+ /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, WJ, WJ,
+ /* 11050 */ WJ, WJ, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
/* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B,
- /* 11070 */ VAbv, B, B, VAbv, VAbv, B, O, O, O, O, O, O, O, O, O, HN,
+ /* 11070 */ VAbv, B, B, VAbv, VAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, HN,
/* Kaithi */
@@ -638,9 +689,9 @@ static const uint8_t use_table[] = {
/* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O,
- /* 110C0 */ O, O, VBlw, O, O, O, O, O,
+ /* 110C0 */ O, O, VBlw, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x11100u 4616
+#define use_offset_0x11100u 4928
/* Chakma */
@@ -648,14 +699,14 @@ static const uint8_t use_table[] = {
/* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11120 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VBlw, VAbv, VAbv,
- /* 11130 */ VBlw, VAbv, VAbv, H, CMAbv, O, B, B, B, B, B, B, B, B, B, B,
- /* 11140 */ O, O, O, O, B, VPst, VPst, B, O, O, O, O, O, O, O, O,
+ /* 11130 */ VBlw, VAbv, VAbv, IS, CMAbv, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 11140 */ O, O, O, O, B, VPst, VPst, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Mahajani */
/* 11150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11170 */ B, B, B, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 11170 */ B, B, B, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Sharada */
@@ -663,50 +714,50 @@ static const uint8_t use_table[] = {
/* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,
- /* 111C0 */ H, B, R, R, O, O, O, O, GB, FMBlw, CMBlw, VAbv, VBlw, O, VPre, VMAbv,
+ /* 111C0 */ H, B, R, R, O, O, O, O, O, FMBlw, CMBlw, VAbv, VBlw, O, VPre, VMAbv,
/* 111D0 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O,
/* Sinhala Archaic Numbers */
- /* 111E0 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111F0 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O,
+ /* 111E0 */ WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 111F0 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Khojki */
/* 11200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11210 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 11210 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw,
- /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O,
+ /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, WJ,
-#define use_offset_0x11280u 4936
+#define use_offset_0x11280u 5248
/* Multani */
- /* 11280 */ B, B, B, B, B, B, B, O, B, O, B, B, B, B, O, B,
- /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, B,
- /* 112A0 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
+ /* 11280 */ B, B, B, B, B, B, B, WJ, B, WJ, B, B, B, B, WJ, B,
+ /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B,
+ /* 112A0 */ B, B, B, B, B, B, B, B, B, O, WJ, WJ, WJ, WJ, WJ, WJ,
/* Khudawadi */
/* 112B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv,
- /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, O, O, O, O, O,
- /* 112F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, WJ, WJ, WJ, WJ, WJ,
+ /* 112F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
/* Grantha */
- /* 11300 */ VMAbv, VMAbv, VMAbv, VMAbv, O, B, B, B, B, B, B, B, B, O, O, B,
- /* 11310 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 11330 */ B, O, B, B, O, B, B, B, B, B, O, CMBlw, CMBlw, B, VPst, VPst,
- /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, HVM, O, O,
- /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, B, B,
- /* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
- /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
+ /* 11300 */ VMAbv, VMAbv, VMAbv, VMAbv, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B,
+ /* 11310 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 11320 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
+ /* 11330 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, CMBlw, CMBlw, B, VPst, VPst,
+ /* 11340 */ VAbv, VPst, VPst, VPst, VPst, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ,
+ /* 11350 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, O, B, B,
+ /* 11360 */ B, B, VPst, VPst, WJ, WJ, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ,
+ /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ,
-#define use_offset_0x11400u 5184
+#define use_offset_0x11400u 5496
/* Newa */
@@ -716,9 +767,9 @@ static const uint8_t use_table[] = {
/* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv,
/* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O,
- /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, FMAbv, B,
- /* 11460 */ CS, CS, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 11470 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, WJ, O, FMAbv, B,
+ /* 11460 */ CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 11470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Tirhuta */
@@ -726,10 +777,10 @@ static const uint8_t use_table[] = {
/* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv,
- /* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O,
- /* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 114D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x11580u 5408
+#define use_offset_0x11580u 5720
/* Siddham */
@@ -737,11 +788,11 @@ static const uint8_t use_table[] = {
/* 11580 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
- /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H,
+ /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H,
/* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, O, O,
- /* 115E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 115F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, WJ, WJ,
+ /* 115E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 115F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Modi */
@@ -749,31 +800,31 @@ static const uint8_t use_table[] = {
/* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H,
- /* 11640 */ VAbv, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 11650 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 11670 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 11640 */ VAbv, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 11650 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ,
+ /* 11670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Takri */
/* 11680 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst,
- /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, B, O, O, O, O, O, O, O,
- /* 116C0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 116D0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 116E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 116F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, B, O, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 116C0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 116D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 116E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 116F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Ahom */
/* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, O, O, MBlw, MPre, MAbv,
- /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O,
+ /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, MBlw, MPre, MAbv,
+ /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ,
/* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
- /* 11740 */ B, B, B, B, B, B, B, O,
+ /* 11740 */ B, B, B, B, B, B, B, WJ,
-#define use_offset_0x11800u 5864
+#define use_offset_0x11800u 6176
/* Dogra */
@@ -781,31 +832,31 @@ static const uint8_t use_table[] = {
/* 11800 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw,
- /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, O, O, O, O,
+ /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, WJ, WJ, WJ, WJ,
-#define use_offset_0x11900u 5928
+#define use_offset_0x11900u 6240
/* Dives Akuru */
- /* 11900 */ B, B, B, B, B, B, B, O, O, B, O, O, B, B, B, B,
- /* 11910 */ B, B, B, B, O, B, B, O, B, B, B, B, B, B, B, B,
+ /* 11900 */ B, B, B, B, B, B, B, WJ, WJ, B, WJ, WJ, B, B, B, B,
+ /* 11910 */ B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B,
/* 11920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11930 */ VPst, VPst, VPst, VPst, VPst, VPre, O, VPre, VPre, O, O, VMAbv, VMAbv, VPst, H, R,
- /* 11940 */ MPst, R, MPst, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 11950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* 11930 */ VPst, VPst, VPst, VPst, VPst, VPre, WJ, VPre, VPre, WJ, WJ, VMAbv, VMAbv, VPst, IS, R,
+ /* 11940 */ MPst, R, MPst, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 11950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x119a0u 6024
+#define use_offset_0x119a0u 6336
/* Nandinagari */
- /* 119A0 */ B, B, B, B, B, B, B, B, O, O, B, B, B, B, B, B,
+ /* 119A0 */ B, B, B, B, B, B, B, B, WJ, WJ, B, B, B, B, B, B,
/* 119B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 119C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 119D0 */ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VAbv, VAbv, VPst, VPst, VMPst, VMPst,
- /* 119E0 */ H, B, O, O, VPre, O, O, O, O, O, O, O, O, O, O, O,
- /* 119F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 119D0 */ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VAbv, VAbv, VPst, VPst, VMPst, VMPst,
+ /* 119E0 */ H, B, O, O, VPre, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 119F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Zanabazar Square */
@@ -813,7 +864,7 @@ static const uint8_t use_table[] = {
/* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A30 */ B, B, B, FMBlw, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB,
- /* 11A40 */ O, O, O, O, O, GB, O, H, O, O, O, O, O, O, O, O,
+ /* 11A40 */ O, O, O, O, O, GB, O, IS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Soyombo */
@@ -821,50 +872,50 @@ static const uint8_t use_table[] = {
/* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A80 */ B, B, B, B, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw,
- /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, B, O, O,
+ /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, IS, O, O, O, B, O, O,
-#define use_offset_0x11c00u 6280
+#define use_offset_0x11c00u 6592
/* Bhaiksuki */
- /* 11C00 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
+ /* 11C00 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
/* 11C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
- /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, O, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H,
- /* 11C40 */ B, O, O, O, GB, GB, O, O, O, O, O, O, O, O, O, O,
+ /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H,
+ /* 11C40 */ B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* 11C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O,
+ /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
/* Marchen */
/* 11C70 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C90 */ O, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O,
+ /* 11C90 */ WJ, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
+ /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
+ /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, WJ,
-#define use_offset_0x11d00u 6464
+#define use_offset_0x11d00u 6776
/* Masaram Gondi */
- /* 11D00 */ B, B, B, B, B, B, B, O, B, B, O, B, B, B, B, B,
+ /* 11D00 */ B, B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B,
/* 11D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, O, O, O, VAbv, O, VAbv, VAbv, O, VAbv,
- /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, H, R, MBlw, O, O, O, O, O, O, O, O,
- /* 11D50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, WJ, WJ, WJ, VAbv, WJ, VAbv, VAbv, WJ, VAbv,
+ /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, IS, R, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 11D50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
/* Gunjala Gondi */
- /* 11D60 */ B, B, B, B, B, B, O, B, B, O, B, B, B, B, B, B,
+ /* 11D60 */ B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B,
/* 11D70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D80 */ B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VPst, VPst, O,
- /* 11D90 */ VAbv, VAbv, O, VPst, VPst, VMAbv, VMPst, H, O, O, O, O, O, O, O, O,
- /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* 11D80 */ B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VPst, VPst, WJ,
+ /* 11D90 */ VAbv, VAbv, WJ, VPst, VPst, VMAbv, VMPst, IS, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-#define use_offset_0x11ee0u 6640
+#define use_offset_0x11ee0u 6952
/* Makasar */
@@ -872,85 +923,92 @@ static const uint8_t use_table[] = {
/* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O,
-#define use_offset_0x13000u 6664
+#define use_offset_0x13000u 6976
/* Egyptian Hieroglyphs */
- /* 13000 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13010 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13020 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13030 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13040 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13050 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13060 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13070 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13080 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13090 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 130A0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 130B0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 130C0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 130D0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 130E0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 130F0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13100 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13110 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13120 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13130 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13140 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13150 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13160 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13170 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13180 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13190 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 131A0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 131B0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 131C0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 131D0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 131E0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 131F0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13200 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13210 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13220 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13230 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13240 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13250 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13260 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13270 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13280 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13290 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 132A0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 132B0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 132C0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 132D0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 132E0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 132F0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13300 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13310 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13320 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13330 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13340 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13350 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13360 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13370 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13380 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13390 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 133A0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 133B0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 133C0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 133D0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 133E0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 133F0 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13400 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13410 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G,
- /* 13420 */ G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, O,
+ /* 13000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13030 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13040 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13050 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13060 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13070 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13080 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 130A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 130B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 130C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 130D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 130E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 130F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13130 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13140 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13170 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13180 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 131A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 131B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 131C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 131D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 131E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 131F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13210 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13220 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13230 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13240 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13250 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13260 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13270 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13280 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 132A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 132B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 132C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 132D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 132E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 132F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13300 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13310 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13320 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13330 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13340 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13350 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13360 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13370 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13380 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13390 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 133A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 133B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 133C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 133D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 133E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 133F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 13420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ,
/* Egyptian Hieroglyph Format Controls */
- /* 13430 */ J, J, J, J, J, J, J, SB, SE, O, O, O, O, O, O, O,
+ /* 13430 */ H, H, H, H, H, H, H, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+
+#define use_offset_0x16ac0u 8064
+
-#define use_offset_0x16b00u 7752
+ /* Tangsa */
+ /* 16AC0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 16AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
+ /* 16AE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ,
+ /* 16AF0 */ O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Pahawh Hmong */
@@ -959,7 +1017,7 @@ static const uint8_t use_table[] = {
/* 16B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 16B30 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O,
-#define use_offset_0x16f00u 7808
+#define use_offset_0x16f00u 8184
/* Miao */
@@ -968,21 +1026,21 @@ static const uint8_t use_table[] = {
/* 16F10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 16F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 16F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F40 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, CMBlw,
+ /* 16F40 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, CMBlw,
/* 16F50 */ O, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
/* 16F60 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
/* 16F70 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, O, O, O, O, O, O, O, VMBlw,
+ /* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, VMBlw,
/* 16F90 */ VMBlw, VMBlw, VMBlw, O, O, O, O, O,
-#define use_offset_0x16fe0u 7960
+#define use_offset_0x16fe0u 8336
/* Ideographic Symbols and Punctuation */
- /* 16FE0 */ O, O, O, O, B, O, O, O,
+ /* 16FE0 */ O, O, O, O, B, WJ, WJ, WJ,
-#define use_offset_0x18b00u 7968
+#define use_offset_0x18b00u 8344
/* Khitan Small Script */
@@ -1016,9 +1074,9 @@ static const uint8_t use_table[] = {
/* 18CA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 18CB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 18CC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CD0 */ B, B, B, B, B, B, O, O,
+ /* 18CD0 */ B, B, B, B, B, B, WJ, WJ,
-#define use_offset_0x1bc00u 8440
+#define use_offset_0x1bc00u 8816
/* Duployan */
@@ -1029,33 +1087,46 @@ static const uint8_t use_table[] = {
/* 1BC30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BC40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BC50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC60 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O,
- /* 1BC70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O,
- /* 1BC80 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
- /* 1BC90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, CMBlw, CMBlw, O,
+ /* 1BC60 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ,
+ /* 1BC70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
+ /* 1BC80 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 1BC90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, CMBlw, CMBlw, O,
+
+#define use_offset_0x1d170u 8976
+
-#define use_offset_0x1e100u 8600
+ /* Musical Symbols */
+
+ /* 1D170 */ O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O,
+
+#define use_offset_0x1e100u 8992
/* Nyiakeng Puachue Hmong */
/* 1E100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1E110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O,
- /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, O, O,
- /* 1E140 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, B, B,
+ /* 1E120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
+ /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, WJ, WJ,
+ /* 1E140 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B, B,
+
+#define use_offset_0x1e290u 9072
+
-#define use_offset_0x1e2c0u 8680
+ /* Toto */
+ /* 1E290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
+ /* 1E2A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, WJ,
+ /* 1E2B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Wancho */
/* 1E2C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1E2D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1E2E0 */ B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv,
- /* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
+ /* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, O,
-#define use_offset_0x1e900u 8744
+#define use_offset_0x1e900u 9184
/* Adlam */
@@ -1064,19 +1135,292 @@ static const uint8_t use_table[] = {
/* 1E910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1E920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1E930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, O, O, O, O,
- /* 1E950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-}; /* Table items: 8840; occupancy: 79% */
+ /* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, WJ, WJ, WJ, WJ,
+ /* 1E950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O,
+
+#define use_offset_0xe0000u 9280
+
+
+ /* Tags */
+
+ /* E0000 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0010 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0020 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0030 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0040 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0050 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0070 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+
+ /* No_Block */
+
+ /* E0080 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0090 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E00A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E00B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E00C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E00D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E00E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E00F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+
+ /* Variation Selectors Supplement */
+
+ /* E0100 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E0110 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E0120 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E0130 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E0140 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E0150 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E0160 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E0170 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E0180 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E0190 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E01A0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E01B0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E01C0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E01D0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+ /* E01E0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
+
+ /* No_Block */
+
+ /* E01F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0200 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0210 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0220 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0230 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0240 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0250 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0260 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0270 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0280 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0290 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E02A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E02B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E02C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E02D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E02E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E02F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0300 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0310 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0320 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0330 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0340 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0350 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0360 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0370 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0380 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0390 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E03A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E03B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E03C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E03D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E03E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E03F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0400 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0410 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0420 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0430 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0440 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0450 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0460 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0480 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0490 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E04A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E04B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E04C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E04D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E04E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E04F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0500 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0510 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0520 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0530 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0540 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0550 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0560 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0570 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0580 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0590 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E05A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E05B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E05C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E05D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E05E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E05F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0600 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0610 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0620 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0630 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0640 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0650 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0660 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0680 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0690 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E06A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E06B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E06C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E06D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E06E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E06F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0700 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0710 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0720 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0730 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0740 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0750 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0760 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0770 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0780 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0790 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E07A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E07B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E07C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E07D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E07E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E07F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0800 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0810 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0820 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0830 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0840 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0850 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0860 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0870 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0880 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0890 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E08A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E08B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E08C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E08D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E08E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E08F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0900 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0910 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0920 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0930 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0940 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0950 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0960 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0970 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0980 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0990 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E09A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E09B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E09C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E09E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E09F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0A90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0AA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0AB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0AC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0AD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0AE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0AF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0B90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0BB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0BC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0BD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0BF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0C90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0CA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0CB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0CC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0CD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0CE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0CF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0D90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0DA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0DB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0DC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0DD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0DF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0E90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0EA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0EB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0EC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0ED0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0EE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0EF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0FB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0FC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0FE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* E0FF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+
+}; /* Table items: 13376; occupancy: 84% */
static inline uint8_t
-hb_use_get_category (hb_codepoint_t u)
+hb_use_get_category (hb_glyph_info_t info)
{
+ hb_codepoint_t u = info.codepoint;
switch (u >> 12)
{
case 0x0u:
if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
if (hb_in_range<hb_codepoint_t> (u, 0x0640u, 0x0647u)) return use_table[u - 0x0640u + use_offset_0x0640u];
if (hb_in_range<hb_codepoint_t> (u, 0x07C8u, 0x07FFu)) return use_table[u - 0x07C8u + use_offset_0x07c8u];
if (hb_in_range<hb_codepoint_t> (u, 0x0840u, 0x085Fu)) return use_table[u - 0x0840u + use_offset_0x0840u];
@@ -1094,8 +1438,7 @@ hb_use_get_category (hb_codepoint_t u)
break;
case 0x2u:
- if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u];
- if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return use_table[u - 0x2070u + use_offset_0x2070u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2087u)) return use_table[u - 0x2008u + use_offset_0x2008u];
if (hb_in_range<hb_codepoint_t> (u, 0x20F0u, 0x20F7u)) return use_table[u - 0x20F0u + use_offset_0x20f0u];
if (hb_in_range<hb_codepoint_t> (u, 0x25C8u, 0x25CFu)) return use_table[u - 0x25C8u + use_offset_0x25c8u];
if (hb_in_range<hb_codepoint_t> (u, 0x2D30u, 0x2D7Fu)) return use_table[u - 0x2D30u + use_offset_0x2d30u];
@@ -1106,18 +1449,25 @@ hb_use_get_category (hb_codepoint_t u)
if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
break;
+ case 0xFu:
+ if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u];
+ if (hb_in_range<hb_codepoint_t> (u, 0xFEF8u, 0xFEFFu)) return use_table[u - 0xFEF8u + use_offset_0xfef8u];
+ if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u];
+ break;
+
case 0x10u:
+ if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x10570u, 0x105BFu)) return use_table[u - 0x10570u + use_offset_0x10570u];
if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A4Fu)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AE7u)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u];
if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return use_table[u - 0x10B80u + use_offset_0x10b80u];
if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D3Fu)) return use_table[u - 0x10D00u + use_offset_0x10d00u];
if (hb_in_range<hb_codepoint_t> (u, 0x10E80u, 0x10EB7u)) return use_table[u - 0x10E80u + use_offset_0x10e80u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10F57u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110C7u)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
break;
case 0x11u:
- if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110C7u)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
@@ -1135,7 +1485,7 @@ hb_use_get_category (hb_codepoint_t u)
break;
case 0x16u:
- if (hb_in_range<hb_codepoint_t> (u, 0x16B00u, 0x16B37u)) return use_table[u - 0x16B00u + use_offset_0x16b00u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x16AC0u, 0x16B37u)) return use_table[u - 0x16AC0u + use_offset_0x16ac0u];
if (hb_in_range<hb_codepoint_t> (u, 0x16F00u, 0x16F97u)) return use_table[u - 0x16F00u + use_offset_0x16f00u];
if (hb_in_range<hb_codepoint_t> (u, 0x16FE0u, 0x16FE7u)) return use_table[u - 0x16FE0u + use_offset_0x16fe0u];
break;
@@ -1148,34 +1498,49 @@ hb_use_get_category (hb_codepoint_t u)
if (hb_in_range<hb_codepoint_t> (u, 0x1BC00u, 0x1BC9Fu)) return use_table[u - 0x1BC00u + use_offset_0x1bc00u];
break;
+ case 0x1Du:
+ if (hb_in_range<hb_codepoint_t> (u, 0x1D170u, 0x1D17Fu)) return use_table[u - 0x1D170u + use_offset_0x1d170u];
+ break;
+
case 0x1Eu:
if (hb_in_range<hb_codepoint_t> (u, 0x1E100u, 0x1E14Fu)) return use_table[u - 0x1E100u + use_offset_0x1e100u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1E2C0u, 0x1E2FFu)) return use_table[u - 0x1E2C0u + use_offset_0x1e2c0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x1E290u, 0x1E2FFu)) return use_table[u - 0x1E290u + use_offset_0x1e290u];
if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E95Fu)) return use_table[u - 0x1E900u + use_offset_0x1e900u];
break;
+ case 0xE0u:
+ if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u];
+ break;
+
+ case 0xE1u:
+ if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u];
+ break;
+
default:
break;
}
- return USE(O);
+ if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED)
+ return WJ;
+ return O;
}
#undef B
+#undef CGJ
#undef CS
#undef G
#undef GB
#undef H
#undef HN
-#undef HVM
+#undef IS
#undef J
#undef N
#undef O
#undef R
-#undef S
#undef SB
#undef SE
#undef SUB
#undef Sk
+#undef WJ
#undef ZWNJ
#undef CMAbv
#undef CMBlw
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc
index 1e4804c4a2..1d13c8a126 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc
@@ -115,25 +115,24 @@ collect_features_use (hb_ot_shape_planner_t *plan)
map->add_gsub_pause (setup_syllables_use);
/* "Default glyph pre-processing group" */
- map->enable_feature (HB_TAG('l','o','c','l'));
- map->enable_feature (HB_TAG('c','c','m','p'));
- map->enable_feature (HB_TAG('n','u','k','t'));
- map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('n','u','k','t'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ | F_PER_SYLLABLE);
/* "Reordering group" */
map->add_gsub_pause (_hb_clear_substitution_flags);
- map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ);
+ map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (record_rphf_use);
map->add_gsub_pause (_hb_clear_substitution_flags);
- map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (record_pref_use);
/* "Orthographic unit shaping group" */
for (unsigned int i = 0; i < ARRAY_LENGTH (use_basic_features); i++)
- map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ);
+ map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (reorder_use);
- map->add_gsub_pause (_hb_clear_syllables);
/* "Topographical features" */
for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)
@@ -206,7 +205,7 @@ setup_masks_use (const hb_ot_shape_plan_t *plan,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- info[i].use_category() = hb_use_get_category (info[i].codepoint);
+ info[i].use_category() = hb_use_get_category (info[i]);
}
static void
@@ -257,8 +256,6 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F);
switch (syllable_type)
{
- case use_independent_cluster:
- case use_symbol_cluster:
case use_hieroglyph_cluster:
case use_non_cluster:
/* These don't join. Nothing to do. */
@@ -270,6 +267,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
case use_standard_cluster:
case use_number_joiner_terminated_cluster:
case use_numeral_cluster:
+ case use_symbol_cluster:
case use_broken_cluster:
bool join = last_form == JOINING_FORM_FINA || last_form == JOINING_FORM_ISOL;
@@ -351,7 +349,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
static inline bool
is_halant_use (const hb_glyph_info_t &info)
{
- return (info.use_category() == USE(H) || info.use_category() == USE(HVM)) &&
+ return (info.use_category() == USE(H) || info.use_category() == USE(IS)) &&
!_hb_glyph_info_ligated (&info);
}
@@ -364,6 +362,7 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
(FLAG (use_virama_terminated_cluster) |
FLAG (use_sakot_terminated_cluster) |
FLAG (use_standard_cluster) |
+ FLAG (use_symbol_cluster) |
FLAG (use_broken_cluster) |
0))))
return;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.cc
index 045731dfb4..d2cca105a4 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.cc
@@ -435,7 +435,7 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
default:
break;
}
- buffer->swap_buffers ();
+ buffer->sync ();
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc
index eb1bc79768..b2eedb027b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc
@@ -446,6 +446,9 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
return;
#endif
+ if (!buffer->message (font, "start fallback mark"))
+ return;
+
_hb_buffer_assert_gsubgpos_vars (buffer);
unsigned int start = 0;
@@ -457,6 +460,8 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
start = i;
}
position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing);
+
+ (void) buffer->message (font, "end fallback mark");
}
@@ -497,6 +502,9 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
!font->has_glyph_v_kerning_func ())
return;
+ if (!buffer->message (font, "start fallback kern"))
+ return;
+
bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
if (reverse)
@@ -508,6 +516,8 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
if (reverse)
buffer->reverse ();
+
+ (void) buffer->message (font, "end fallback kern");
#endif
}
@@ -525,6 +535,15 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
for (unsigned int i = 0; i < count; i++)
if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
{
+ /* If font had no ASCII space and we used the invisible glyph, give it a 1/4 EM default advance. */
+ if (buffer->invisible && info[i].codepoint == buffer->invisible)
+ {
+ if (horizontal)
+ pos[i].x_advance = +font->x_scale / 4;
+ else
+ pos[i].y_advance = -font->y_scale / 4;
+ }
+
hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
hb_codepoint_t glyph;
typedef hb_unicode_funcs_t t;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc
index 778b5b8bd8..aa5a8eeaa3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc
@@ -171,7 +171,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
hb_codepoint_t u = buffer->cur().codepoint;
hb_codepoint_t glyph = 0;
- if (shortest && c->font->get_nominal_glyph (u, &glyph))
+ if (shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found))
{
next_char (buffer, glyph);
return;
@@ -183,7 +183,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
return;
}
- if (!shortest && c->font->get_nominal_glyph (u, &glyph))
+ if (!shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found))
{
next_char (buffer, glyph);
return;
@@ -193,7 +193,8 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
{
hb_codepoint_t space_glyph;
hb_unicode_funcs_t::space_t space_type = buffer->unicode->space_fallback_type (u);
- if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_nominal_glyph (0x0020u, &space_glyph))
+ if (space_type != hb_unicode_funcs_t::NOT_SPACE &&
+ (c->font->get_nominal_glyph (0x0020, &space_glyph) || (space_glyph = buffer->invisible)))
{
_hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type);
next_char (buffer, space_glyph);
@@ -312,6 +313,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
buffer,
font,
buffer->unicode,
+ buffer->not_found,
plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode,
plan->shaper->compose ? plan->shaper->compose : compose_unicode
};
@@ -373,7 +375,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
decompose_multi_char_cluster (&c, end, always_short_circuit);
}
while (buffer->idx < count && buffer->successful);
- buffer->swap_buffers ();
+ buffer->sync ();
}
@@ -476,7 +478,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
if (info_cc (buffer->prev()) == 0)
starter = buffer->out_len - 1;
}
- buffer->swap_buffers ();
+ buffer->sync ();
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.hh
index 04f1a80091..12c78a2352 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.hh
@@ -56,6 +56,7 @@ struct hb_ot_shape_normalize_context_t
hb_buffer_t *buffer;
hb_font_t *font;
hb_unicode_funcs_t *unicode;
+ const hb_codepoint_t not_found;
bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
hb_codepoint_t ab,
hb_codepoint_t *a,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
index 0e215c24f7..99aadab3f0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
@@ -47,6 +47,9 @@
#include "hb-aat-layout.hh"
+static inline bool
+_hb_codepoint_is_regional_indicator (hb_codepoint_t u)
+{ return hb_in_range<hb_codepoint_t> (u, 0x1F1E6u, 0x1F1FFu); }
#ifndef HB_NO_AAT_SHAPE
static inline bool
@@ -150,23 +153,25 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
*/
#ifndef HB_NO_AAT_SHAPE
- bool has_gsub = hb_ot_layout_has_substitution (face);
+ bool has_kerx = hb_aat_layout_has_positioning (face);
+ bool has_gsub = !apply_morx && hb_ot_layout_has_substitution (face);
#endif
bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
if (false)
;
#ifndef HB_NO_AAT_SHAPE
- else if (hb_aat_layout_has_positioning (face) && !(has_gsub && has_gpos))
+ /* Prefer GPOS over kerx if GSUB is present;
+ * https://github.com/harfbuzz/harfbuzz/issues/3008 */
+ else if (has_kerx && !(has_gsub && has_gpos))
plan.apply_kerx = true;
#endif
- else if (!apply_morx && has_gpos)
+ else if (has_gpos)
plan.apply_gpos = true;
if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos))
{
- /* Apparently Apple applies kerx if GPOS kern was not applied. */
#ifndef HB_NO_AAT_SHAPE
- if (hb_aat_layout_has_positioning (face))
+ if (has_kerx)
plan.apply_kerx = true;
else
#endif
@@ -502,9 +507,9 @@ hb_set_unicode_props (hb_buffer_t *buffer)
}
/* Regional_Indicators are hairy as hell...
* https://github.com/harfbuzz/harfbuzz/issues/2265 */
- else if (unlikely (i && hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F1E6u, 0x1F1FFu)))
+ else if (unlikely (i && _hb_codepoint_is_regional_indicator (info[i].codepoint)))
{
- if (hb_in_range<hb_codepoint_t> (info[i - 1].codepoint, 0x1F1E6u, 0x1F1FFu) &&
+ if (_hb_codepoint_is_regional_indicator (info[i - 1].codepoint) &&
!_hb_glyph_info_is_continuation (&info[i - 1]))
_hb_glyph_info_set_continuation (&info[i]);
}
@@ -564,7 +569,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
info.mask = buffer->cur().mask;
(void) buffer->output_info (info);
- buffer->swap_buffers ();
+ buffer->sync ();
}
static void
@@ -596,24 +601,33 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
* direction, so that features like ligatures will work as intended.
*
* https://github.com/harfbuzz/harfbuzz/issues/501
+ *
+ * Similar thing about Regional_Indicators; They are bidi=L, but Script=Common.
+ * If they are present in a run of natively-RTL text, they get assigned a script
+ * with natively RTL direction, which would result in wrong shaping if we
+ * assign such native RTL direction to them then. Detect that as well.
+ *
+ * https://github.com/harfbuzz/harfbuzz/issues/3314
*/
if (unlikely (horiz_dir == HB_DIRECTION_RTL && direction == HB_DIRECTION_LTR))
{
- bool found_number = false, found_letter = false;
+ bool found_number = false, found_letter = false, found_ri = false;
const auto* info = buffer->info;
const auto count = buffer->len;
for (unsigned i = 0; i < count; i++)
{
auto gc = _hb_glyph_info_get_general_category (&info[i]);
if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
- found_number = true;
+ found_number = true;
else if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc))
{
- found_letter = true;
- break;
+ found_letter = true;
+ break;
}
+ else if (_hb_codepoint_is_regional_indicator (info[i].codepoint))
+ found_ri = true;
}
- if (found_number && !found_letter)
+ if ((found_number || found_ri) && !found_letter)
horiz_dir = HB_DIRECTION_LTR;
}
@@ -626,20 +640,7 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
(HB_DIRECTION_IS_VERTICAL (direction) &&
direction != HB_DIRECTION_TTB))
{
-
- if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
- foreach_grapheme (buffer, start, end)
- {
- buffer->merge_clusters (start, end);
- buffer->reverse_range (start, end);
- }
- else
- foreach_grapheme (buffer, start, end)
- /* form_clusters() merged clusters already, we don't merge. */
- buffer->reverse_range (start, end);
-
- buffer->reverse ();
-
+ _hb_ot_layout_reverse_graphemes (buffer);
buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
}
}
@@ -649,6 +650,7 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
* Substitute
*/
+#ifndef HB_NO_VERTICAL
static hb_codepoint_t
hb_vert_char_for (hb_codepoint_t u)
{
@@ -699,6 +701,7 @@ hb_vert_char_for (hb_codepoint_t u)
return u;
}
+#endif
static inline void
hb_ot_rotate_chars (const hb_ot_shape_context_t *c)
@@ -721,6 +724,7 @@ hb_ot_rotate_chars (const hb_ot_shape_context_t *c)
}
}
+#ifndef HB_NO_VERTICAL
if (HB_DIRECTION_IS_VERTICAL (c->target_direction) && !c->plan->has_vert)
{
for (unsigned int i = 0; i < count; i++) {
@@ -729,6 +733,7 @@ hb_ot_rotate_chars (const hb_ot_shape_context_t *c)
info[i].codepoint = codepoint;
}
}
+#endif
}
static inline void
@@ -942,17 +947,23 @@ hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
_hb_buffer_allocate_gsubgpos_vars (c->buffer);
hb_ot_substitute_complex (c);
+
+#ifndef HB_NO_AAT_SHAPE
+ if (c->plan->apply_morx && c->plan->apply_gpos)
+ hb_aat_layout_remove_deleted_glyphs (c->buffer);
+#endif
}
static inline void
hb_ot_substitute_post (const hb_ot_shape_context_t *c)
{
- hb_ot_hide_default_ignorables (c->buffer, c->font);
#ifndef HB_NO_AAT_SHAPE
- if (c->plan->apply_morx)
+ if (c->plan->apply_morx && !c->plan->apply_gpos)
hb_aat_layout_remove_deleted_glyphs (c->buffer);
#endif
+ hb_ot_hide_default_ignorables (c->buffer, c->font);
+
if (c->plan->shaper->postprocess_glyphs &&
c->buffer->message(c->font, "start postprocess-glyphs")) {
c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
@@ -1041,7 +1052,7 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
* hanging over the next glyph after the final reordering.
*
* Note: If fallback positinoing happens, we don't care about
- * this as it will be overriden.
+ * this as it will be overridden.
*/
bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
@@ -1127,7 +1138,7 @@ hb_propagate_flags (hb_buffer_t *buffer)
/* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
* Simplifies using them. */
- if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK))
+ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS))
return;
hb_glyph_info_t *info = buffer->info;
@@ -1136,11 +1147,7 @@ hb_propagate_flags (hb_buffer_t *buffer)
{
unsigned int mask = 0;
for (unsigned int i = start; i < end; i++)
- if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
- {
- mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
- break;
- }
+ mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED;
if (mask)
for (unsigned int i = start; i < end; i++)
info[i].mask |= mask;
@@ -1152,18 +1159,7 @@ hb_propagate_flags (hb_buffer_t *buffer)
static void
hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
- c->buffer->deallocate_var_all ();
- c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
- if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
- {
- c->buffer->max_len = hb_max (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
- (unsigned) HB_BUFFER_MAX_LEN_MIN);
- }
- if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
- {
- c->buffer->max_ops = hb_max (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
- (unsigned) HB_BUFFER_MAX_OPS_MIN);
- }
+ c->buffer->enter ();
/* Save the original direction, we use it later. */
c->target_direction = c->buffer->props.direction;
@@ -1195,9 +1191,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
c->buffer->props.direction = c->target_direction;
- c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
- c->buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
- c->buffer->deallocate_var_all ();
+ c->buffer->leave ();
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh
index fc9bffc23f..5261783277 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh
@@ -6,8 +6,8 @@
*
* on files with these headers:
*
- * <meta name="updated_at" content="2021-09-02 09:40 PM" />
- * File-Date: 2021-08-06
+ * <meta name="updated_at" content="2022-01-28 10:00 PM" />
+ * File-Date: 2022-03-02
*/
#ifndef HB_OT_TAG_TABLE_HH
@@ -54,6 +54,7 @@ static const LangTag ot_languages[] = {
/*{"aio", HB_TAG('A','I','O',' ')},*/ /* Aiton */
{"aiw", HB_TAG('A','R','I',' ')}, /* Aari */
{"ajp", HB_TAG('A','R','A',' ')}, /* South Levantine Arabic -> Arabic */
+ {"ajt", HB_TAG('A','R','A',' ')}, /* Judeo-Tunisian Arabic (retired code) -> Arabic */
{"ak", HB_TAG('A','K','A',' ')}, /* Akan [macrolanguage] */
{"akb", HB_TAG('A','K','B',' ')}, /* Batak Angkola */
{"akb", HB_TAG('B','T','K',' ')}, /* Batak Angkola -> Batak */
@@ -66,7 +67,7 @@ static const LangTag ot_languages[] = {
{"an", HB_TAG('A','R','G',' ')}, /* Aragonese */
/*{"ang", HB_TAG('A','N','G',' ')},*/ /* Old English (ca. 450-1100) -> Anglo-Saxon */
{"aoa", HB_TAG('C','P','P',' ')}, /* Angolar -> Creoles */
- {"apa", HB_TAG('A','T','H',' ')}, /* Apache [family] -> Athapaskan */
+ {"apa", HB_TAG('A','T','H',' ')}, /* Apache [collection] -> Athapaskan */
{"apc", HB_TAG('A','R','A',' ')}, /* North Levantine Arabic -> Arabic */
{"apd", HB_TAG('A','R','A',' ')}, /* Sudanese Arabic -> Arabic */
{"apj", HB_TAG('A','T','H',' ')}, /* Jicarilla Apache -> Athapaskan */
@@ -86,7 +87,7 @@ static const LangTag ot_languages[] = {
{"arz", HB_TAG('A','R','A',' ')}, /* Egyptian Arabic -> Arabic */
{"as", HB_TAG('A','S','M',' ')}, /* Assamese */
/*{"ast", HB_TAG('A','S','T',' ')},*/ /* Asturian */
-/*{"ath", HB_TAG('A','T','H',' ')},*/ /* Athapascan [family] -> Athapaskan */
+/*{"ath", HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */
{"atj", HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */
{"atv", HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */
{"auj", HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */
@@ -110,10 +111,10 @@ static const LangTag ot_languages[] = {
{"azn", HB_TAG('N','A','H',' ')}, /* Western Durango Nahuatl -> Nahuatl */
{"azz", HB_TAG('N','A','H',' ')}, /* Highland Puebla Nahuatl -> Nahuatl */
{"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */
- {"bad", HB_TAG('B','A','D','0')}, /* Banda [family] */
+ {"bad", HB_TAG('B','A','D','0')}, /* Banda [collection] */
{"bag", HB_TAG_NONE }, /* Tuki != Baghelkhandi */
{"bah", HB_TAG('C','P','P',' ')}, /* Bahamas Creole English -> Creoles */
- {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [family] */
+ {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [collection] */
{"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolanguage] */
/*{"ban", HB_TAG('B','A','N',' ')},*/ /* Balinese */
/*{"bar", HB_TAG('B','A','R',' ')},*/ /* Bavarian */
@@ -135,7 +136,7 @@ static const LangTag ot_languages[] = {
{"bea", HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */
{"beb", HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */
/*{"bem", HB_TAG('B','E','M',' ')},*/ /* Bemba (Zambia) */
- {"ber", HB_TAG('B','B','R',' ')}, /* Berber [family] */
+ {"ber", HB_TAG('B','B','R',' ')}, /* Berber [collection] */
{"bew", HB_TAG('C','P','P',' ')}, /* Betawi -> Creoles */
{"bfl", HB_TAG('B','A','D','0')}, /* Banda-Ndélé -> Banda */
{"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */
@@ -203,7 +204,7 @@ static const LangTag ot_languages[] = {
{"btd", HB_TAG('B','T','K',' ')}, /* Batak Dairi -> Batak */
{"bti", HB_TAG_NONE }, /* Burate != Beti */
{"btj", HB_TAG('M','L','Y',' ')}, /* Bacanese Malay -> Malay */
-/*{"btk", HB_TAG('B','T','K',' ')},*/ /* Batak [family] */
+/*{"btk", HB_TAG('B','T','K',' ')},*/ /* Batak [collection] */
{"btm", HB_TAG('B','T','M',' ')}, /* Batak Mandailing */
{"btm", HB_TAG('B','T','K',' ')}, /* Batak Mandailing -> Batak */
{"bto", HB_TAG('B','I','K',' ')}, /* Rinconada Bikol -> Bikol */
@@ -256,6 +257,8 @@ static const LangTag ot_languages[] = {
{"chh", HB_TAG_NONE }, /* Chinook != Chattisgarhi */
{"chj", HB_TAG('C','C','H','N')}, /* Ojitlán Chinantec -> Chinantec */
{"chk", HB_TAG('C','H','K','0')}, /* Chuukese */
+ {"chm", HB_TAG('H','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> High Mari */
+ {"chm", HB_TAG('L','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> Low Mari */
{"chn", HB_TAG('C','P','P',' ')}, /* Chinook jargon -> Creoles */
/*{"cho", HB_TAG('C','H','O',' ')},*/ /* Choctaw */
{"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */
@@ -297,10 +300,10 @@ static const LangTag ot_languages[] = {
/*{"cop", HB_TAG('C','O','P',' ')},*/ /* Coptic */
{"coq", HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */
{"cpa", HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */
- {"cpe", HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [family] -> Creoles */
- {"cpf", HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [family] -> Creoles */
+ {"cpe", HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [collection] -> Creoles */
+ {"cpf", HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [collection] -> Creoles */
{"cpi", HB_TAG('C','P','P',' ')}, /* Chinese Pidgin English -> Creoles */
-/*{"cpp", HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [family] -> Creoles */
+/*{"cpp", HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [collection] -> Creoles */
{"cpx", HB_TAG('Z','H','S',' ')}, /* Pu-Xian Chinese -> Chinese, Simplified */
{"cqd", HB_TAG('H','M','N',' ')}, /* Chuanqiandian Cluster Miao -> Hmong */
{"cqu", HB_TAG('Q','U','H',' ')}, /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
@@ -320,7 +323,7 @@ static const LangTag ot_languages[] = {
{"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */
{"crm", HB_TAG('L','C','R',' ')}, /* Moose Cree -> L-Cree */
{"crm", HB_TAG('C','R','E',' ')}, /* Moose Cree -> Cree */
- {"crp", HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [family] -> Creoles */
+ {"crp", HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [collection] -> Creoles */
{"crr", HB_TAG_NONE }, /* Carolina Algonquian != Carrier */
{"crs", HB_TAG('C','P','P',' ')}, /* Seselwa Creole French -> Creoles */
{"crt", HB_TAG_NONE }, /* Iyojwa'ja Chorote != Crimean Tatar */
@@ -431,7 +434,7 @@ static const LangTag ot_languages[] = {
{"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */
{"eto", HB_TAG('B','T','I',' ')}, /* Eton (Cameroon) -> Beti */
{"eu", HB_TAG('E','U','Q',' ')}, /* Basque */
- {"euq", HB_TAG_NONE }, /* Basque [family] != Basque */
+ {"euq", HB_TAG_NONE }, /* Basque [collection] != Basque */
{"eve", HB_TAG('E','V','N',' ')}, /* Even */
{"evn", HB_TAG('E','V','K',' ')}, /* Evenki */
{"ewo", HB_TAG('B','T','I',' ')}, /* Ewondo -> Beti */
@@ -620,10 +623,11 @@ static const LangTag ot_languages[] = {
{"ijc", HB_TAG('I','J','O',' ')}, /* Izon -> Ijo */
{"ije", HB_TAG('I','J','O',' ')}, /* Biseni -> Ijo */
{"ijn", HB_TAG('I','J','O',' ')}, /* Kalabari -> Ijo */
-/*{"ijo", HB_TAG('I','J','O',' ')},*/ /* Ijo [family] */
+/*{"ijo", HB_TAG('I','J','O',' ')},*/ /* Ijo [collection] */
{"ijs", HB_TAG('I','J','O',' ')}, /* Southeast Ijo -> Ijo */
{"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] -> Inupiat */
{"ike", HB_TAG('I','N','U',' ')}, /* Eastern Canadian Inuktitut -> Inuktitut */
+ {"ike", HB_TAG('I','N','U','K')}, /* Eastern Canadian Inuktitut -> Nunavik Inuktitut */
{"ikt", HB_TAG('I','N','U',' ')}, /* Inuinnaqtun -> Inuktitut */
/*{"ilo", HB_TAG('I','L','O',' ')},*/ /* Iloko -> Ilokano */
{"in", HB_TAG('I','N','D',' ')}, /* Indonesian (retired code) */
@@ -638,6 +642,7 @@ static const LangTag ot_languages[] = {
{"it", HB_TAG('I','T','A',' ')}, /* Italian */
{"itz", HB_TAG('M','Y','N',' ')}, /* Itzá -> Mayan */
{"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */
+ {"iu", HB_TAG('I','N','U','K')}, /* Inuktitut [macrolanguage] -> Nunavik Inuktitut */
{"iw", HB_TAG('I','W','R',' ')}, /* Hebrew (retired code) */
{"ixl", HB_TAG('M','Y','N',' ')}, /* Ixil -> Mayan */
{"ja", HB_TAG('J','A','N',' ')}, /* Japanese */
@@ -667,7 +672,7 @@ static const LangTag ot_languages[] = {
{"kab", HB_TAG('B','B','R',' ')}, /* Kabyle -> Berber */
{"kac", HB_TAG_NONE }, /* Kachin != Kachchi */
{"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
- {"kar", HB_TAG('K','R','N',' ')}, /* Karen [family] */
+ {"kar", HB_TAG('K','R','N',' ')}, /* Karen [collection] */
/*{"kaw", HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */
{"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */
{"kby", HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */
@@ -805,7 +810,7 @@ static const LangTag ot_languages[] = {
{"lac", HB_TAG('M','Y','N',' ')}, /* Lacandon -> Mayan */
{"lad", HB_TAG('J','U','D',' ')}, /* Ladino */
{"lah", HB_TAG_NONE }, /* Lahnda [macrolanguage] != Lahuli */
- {"lak", HB_TAG_NONE }, /* Laka (Nigeria) != Lak */
+ {"lak", HB_TAG_NONE }, /* Laka (Nigeria) (retired code) != Lak */
{"lam", HB_TAG_NONE }, /* Lamba != Lambani */
{"laz", HB_TAG_NONE }, /* Aribwatsa != Laz */
{"lb", HB_TAG('L','T','Z',' ')}, /* Luxembourgish */
@@ -876,7 +881,7 @@ static const LangTag ot_languages[] = {
{"mam", HB_TAG('M','A','M',' ')}, /* Mam */
{"mam", HB_TAG('M','Y','N',' ')}, /* Mam -> Mayan */
{"man", HB_TAG('M','N','K',' ')}, /* Mandingo [macrolanguage] -> Maninka */
- {"map", HB_TAG_NONE }, /* Austronesian [family] != Mapudungun */
+ {"map", HB_TAG_NONE }, /* Austronesian [collection] != Mapudungun */
{"maw", HB_TAG_NONE }, /* Mampruli != Marwari */
{"max", HB_TAG('M','L','Y',' ')}, /* North Moluccan Malay -> Malay */
{"max", HB_TAG('C','P','P',' ')}, /* North Moluccan Malay -> Creoles */
@@ -933,8 +938,10 @@ static const LangTag ot_languages[] = {
{"mnp", HB_TAG('Z','H','S',' ')}, /* Min Bei Chinese -> Chinese, Simplified */
{"mns", HB_TAG('M','A','N',' ')}, /* Mansi */
{"mnw", HB_TAG('M','O','N',' ')}, /* Mon */
+ {"mnw", HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */
{"mnx", HB_TAG_NONE }, /* Manikion != Manx */
{"mo", HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */
+ {"mo", HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */
{"mod", HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */
/*{"moh", HB_TAG('M','O','H',' ')},*/ /* Mohawk */
{"mok", HB_TAG_NONE }, /* Morori != Moksha */
@@ -957,7 +964,7 @@ static const LangTag ot_languages[] = {
{"mts", HB_TAG_NONE }, /* Yora != Maltese */
{"mud", HB_TAG('C','P','P',' ')}, /* Mednyj Aleut -> Creoles */
{"mui", HB_TAG('M','L','Y',' ')}, /* Musi -> Malay */
- {"mun", HB_TAG_NONE }, /* Munda [family] != Mundari */
+ {"mun", HB_TAG_NONE }, /* Munda [collection] != Mundari */
{"mup", HB_TAG('R','A','J',' ')}, /* Malvi -> Rajasthani */
{"muq", HB_TAG('H','M','N',' ')}, /* Eastern Xiangxi Miao -> Hmong */
/*{"mus", HB_TAG('M','U','S',' ')},*/ /* Creek -> Muscogee */
@@ -972,7 +979,7 @@ static const LangTag ot_languages[] = {
{"mww", HB_TAG('H','M','N',' ')}, /* Hmong Daw -> Hmong */
{"my", HB_TAG('B','R','M',' ')}, /* Burmese */
{"mym", HB_TAG('M','E','N',' ')}, /* Me’en */
-/*{"myn", HB_TAG('M','Y','N',' ')},*/ /* Mayan [family] */
+/*{"myn", HB_TAG('M','Y','N',' ')},*/ /* Mayan [collection] */
{"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) -> Maninka */
{"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */
{"mzb", HB_TAG('B','B','R',' ')}, /* Tumzabt -> Berber */
@@ -981,7 +988,7 @@ static const LangTag ot_languages[] = {
{"na", HB_TAG('N','A','U',' ')}, /* Nauru -> Nauruan */
{"nag", HB_TAG('N','A','G',' ')}, /* Naga Pidgin -> Naga-Assamese */
{"nag", HB_TAG('C','P','P',' ')}, /* Naga Pidgin -> Creoles */
-/*{"nah", HB_TAG('N','A','H',' ')},*/ /* Nahuatl [family] */
+/*{"nah", HB_TAG('N','A','H',' ')},*/ /* Nahuatl [collection] */
{"nan", HB_TAG('Z','H','S',' ')}, /* Min Nan Chinese -> Chinese, Simplified */
/*{"nap", HB_TAG('N','A','P',' ')},*/ /* Neapolitan */
{"nas", HB_TAG_NONE }, /* Naasioi != Naskapi */
@@ -1038,7 +1045,6 @@ static const LangTag ot_languages[] = {
{"nln", HB_TAG('N','A','H',' ')}, /* Durango Nahuatl (retired code) -> Nahuatl */
{"nlv", HB_TAG('N','A','H',' ')}, /* Orizaba Nahuatl -> Nahuatl */
{"nn", HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk (Nynorsk, Norwegian) */
- {"nn", HB_TAG('N','O','R',' ')}, /* Norwegian Nynorsk -> Norwegian */
{"nnh", HB_TAG('B','M','L',' ')}, /* Ngiemboon -> Bamileke */
{"nnz", HB_TAG('B','M','L',' ')}, /* Nda'nda' -> Bamileke */
{"no", HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */
@@ -1092,7 +1098,7 @@ static const LangTag ot_languages[] = {
{"otw", HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */
{"oua", HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */
{"pa", HB_TAG('P','A','N',' ')}, /* Punjabi */
- {"paa", HB_TAG_NONE }, /* Papuan [family] != Palestinian Aramaic */
+ {"paa", HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */
/*{"pag", HB_TAG('P','A','G',' ')},*/ /* Pangasinan */
{"pal", HB_TAG_NONE }, /* Pahlavi != Pali */
/*{"pam", HB_TAG('P','A','M',' ')},*/ /* Pampanga -> Pampangan */
@@ -1307,6 +1313,9 @@ static const LangTag ot_languages[] = {
{"sgo", HB_TAG_NONE }, /* Songa (retired code) != Sango */
/*{"sgs", HB_TAG('S','G','S',' ')},*/ /* Samogitian */
{"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage -> Chaha Gurage */
+ {"sh", HB_TAG('B','O','S',' ')}, /* Serbo-Croatian [macrolanguage] -> Bosnian */
+ {"sh", HB_TAG('H','R','V',' ')}, /* Serbo-Croatian [macrolanguage] -> Croatian */
+ {"sh", HB_TAG('S','R','B',' ')}, /* Serbo-Croatian [macrolanguage] -> Serbian */
{"shi", HB_TAG('S','H','I',' ')}, /* Tachelhit */
{"shi", HB_TAG('B','B','R',' ')}, /* Tachelhit -> Berber */
{"shl", HB_TAG('Q','I','N',' ')}, /* Shendu -> Chin */
@@ -1328,15 +1337,17 @@ static const LangTag ot_languages[] = {
{"skw", HB_TAG('C','P','P',' ')}, /* Skepi Creole Dutch -> Creoles */
{"sky", HB_TAG_NONE }, /* Sikaiana != Slovak */
{"sl", HB_TAG('S','L','V',' ')}, /* Slovenian */
- {"sla", HB_TAG_NONE }, /* Slavic [family] != Slavey */
+ {"sla", HB_TAG_NONE }, /* Slavic [collection] != Slavey */
{"sm", HB_TAG('S','M','O',' ')}, /* Samoan */
{"sma", HB_TAG('S','S','M',' ')}, /* Southern Sami */
+ {"smd", HB_TAG('M','B','N',' ')}, /* Sama (retired code) -> Mbundu */
{"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */
{"sml", HB_TAG_NONE }, /* Central Sama != Somali */
{"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */
{"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */
{"smt", HB_TAG('Q','I','N',' ')}, /* Simte -> Chin */
{"sn", HB_TAG('S','N','A','0')}, /* Shona */
+ {"snb", HB_TAG('I','B','A',' ')}, /* Sebuyau (retired code) -> Iban */
{"snh", HB_TAG_NONE }, /* Shinabo (retired code) != Sinhala (Sinhalese) */
/*{"snk", HB_TAG('S','N','K',' ')},*/ /* Soninke */
{"so", HB_TAG('S','M','L',' ')}, /* Somali */
@@ -1422,6 +1433,7 @@ static const LangTag ot_languages[] = {
{"tia", HB_TAG('B','B','R',' ')}, /* Tidikelt Tamazight -> Berber */
{"tig", HB_TAG('T','G','R',' ')}, /* Tigre */
/*{"tiv", HB_TAG('T','I','V',' ')},*/ /* Tiv */
+/*{"tjl", HB_TAG('T','J','L',' ')},*/ /* Tai Laing */
{"tjo", HB_TAG('B','B','R',' ')}, /* Temacine Tamazight -> Berber */
{"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */
{"tkg", HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */
@@ -1449,7 +1461,7 @@ static const LangTag ot_languages[] = {
{"tpi", HB_TAG('C','P','P',' ')}, /* Tok Pisin -> Creoles */
{"tr", HB_TAG('T','R','K',' ')}, /* Turkish */
{"trf", HB_TAG('C','P','P',' ')}, /* Trinidadian Creole English -> Creoles */
- {"trk", HB_TAG_NONE }, /* Turkic [family] != Turkish */
+ {"trk", HB_TAG_NONE }, /* Turkic [collection] != Turkish */
{"tru", HB_TAG('T','U','A',' ')}, /* Turoyo -> Turoyo Aramaic */
{"tru", HB_TAG('S','Y','R',' ')}, /* Turoyo -> Syriac */
{"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */
@@ -1591,7 +1603,7 @@ static const LangTag ot_languages[] = {
{"zlq", HB_TAG('Z','H','A',' ')}, /* Liuqian Zhuang -> Zhuang */
{"zmi", HB_TAG('M','L','Y',' ')}, /* Negeri Sembilan Malay -> Malay */
{"zmz", HB_TAG('B','A','D','0')}, /* Mbandja -> Banda */
- {"znd", HB_TAG_NONE }, /* Zande [family] != Zande */
+ {"znd", HB_TAG_NONE }, /* Zande [collection] != Zande */
{"zne", HB_TAG('Z','N','D',' ')}, /* Zande */
{"zom", HB_TAG('Q','I','N',' ')}, /* Zou -> Chin */
{"zqe", HB_TAG('Z','H','A',' ')}, /* Qiubei Zhuang -> Zhuang */
@@ -2521,6 +2533,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = 1;
return true;
}
+ if (0 == strncmp (&lang_str[1], "nw-", 3)
+ && subtag_matches (lang_str, limit, "-th"))
+ {
+ /* Mon; Thailand */
+ tags[0] = HB_TAG('M','O','N','T'); /* Thailand Mon */
+ *count = 1;
+ return true;
+ }
break;
case 'n':
if (lang_matches (&lang_str[1], "an-hant-hk"))
@@ -2597,14 +2617,8 @@ hb_ot_tags_from_complex_language (const char *lang_str,
if (0 == strcmp (&lang_str[1], "o-nyn"))
{
/* Norwegian Nynorsk (retired code) */
- unsigned int i;
- hb_tag_t possible_tags[] = {
- HB_TAG('N','Y','N',' '), /* Norwegian Nynorsk (Nynorsk, Norwegian) */
- HB_TAG('N','O','R',' '), /* Norwegian */
- };
- for (i = 0; i < 2 && i < *count; i++)
- tags[i] = possible_tags[i];
- *count = i;
+ tags[0] = HB_TAG('N','Y','N',' '); /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+ *count = 1;
return true;
}
break;
@@ -2613,8 +2627,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
&& subtag_matches (lang_str, limit, "-md"))
{
/* Romanian; Moldova */
- tags[0] = HB_TAG('M','O','L',' '); /* Moldavian */
- *count = 1;
+ unsigned int i;
+ hb_tag_t possible_tags[] = {
+ HB_TAG('M','O','L',' '), /* Moldavian */
+ HB_TAG('R','O','M',' '), /* Romanian */
+ };
+ for (i = 0; i < 2 && i < *count; i++)
+ tags[i] = possible_tags[i];
+ *count = i;
return true;
}
break;
@@ -2803,15 +2823,15 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
case HB_TAG('A','R','K',' '): /* Rakhine */
return hb_language_from_string ("rki", -1); /* Rakhine */
case HB_TAG('A','T','H',' '): /* Athapaskan */
- return hb_language_from_string ("ath", -1); /* Athapascan [family] */
+ return hb_language_from_string ("ath", -1); /* Athapascan [collection] */
case HB_TAG('B','B','R',' '): /* Berber */
- return hb_language_from_string ("ber", -1); /* Berber [family] */
+ return hb_language_from_string ("ber", -1); /* Berber [collection] */
case HB_TAG('B','I','K',' '): /* Bikol */
return hb_language_from_string ("bik", -1); /* Bikol [macrolanguage] */
case HB_TAG('B','T','K',' '): /* Batak */
- return hb_language_from_string ("btk", -1); /* Batak [family] */
+ return hb_language_from_string ("btk", -1); /* Batak [collection] */
case HB_TAG('C','P','P',' '): /* Creoles */
- return hb_language_from_string ("crp", -1); /* Creoles and pidgins [family] */
+ return hb_language_from_string ("crp", -1); /* Creoles and pidgins [collection] */
case HB_TAG('C','R','R',' '): /* Carrier */
return hb_language_from_string ("crx", -1); /* Carrier */
case HB_TAG('D','G','R',' '): /* Dogri (macrolanguage) */
@@ -2828,6 +2848,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("fa", -1); /* Persian [macrolanguage] */
case HB_TAG('G','O','N',' '): /* Gondi */
return hb_language_from_string ("gon", -1); /* Gondi [macrolanguage] */
+ case HB_TAG('H','M','A',' '): /* High Mari */
+ return hb_language_from_string ("mrj", -1); /* Western Mari */
case HB_TAG('H','M','N',' '): /* Hmong */
return hb_language_from_string ("hmn", -1); /* Hmong [macrolanguage] */
case HB_TAG('H','N','D',' '): /* Hindko */
@@ -2837,7 +2859,7 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
case HB_TAG('I','B','A',' '): /* Iban */
return hb_language_from_string ("iba", -1); /* Iban */
case HB_TAG('I','J','O',' '): /* Ijo */
- return hb_language_from_string ("ijo", -1); /* Ijo [family] */
+ return hb_language_from_string ("ijo", -1); /* Ijo [collection] */
case HB_TAG('I','N','U',' '): /* Inuktitut */
return hb_language_from_string ("iu", -1); /* Inuktitut [macrolanguage] */
case HB_TAG('I','P','K',' '): /* Inupiat */
@@ -2863,11 +2885,13 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
case HB_TAG('K','P','L',' '): /* Kpelle */
return hb_language_from_string ("kpe", -1); /* Kpelle [macrolanguage] */
case HB_TAG('K','R','N',' '): /* Karen */
- return hb_language_from_string ("kar", -1); /* Karen [family] */
+ return hb_language_from_string ("kar", -1); /* Karen [collection] */
case HB_TAG('K','U','I',' '): /* Kui */
return hb_language_from_string ("uki", -1); /* Kui (India) */
case HB_TAG('K','U','R',' '): /* Kurdish */
return hb_language_from_string ("ku", -1); /* Kurdish [macrolanguage] */
+ case HB_TAG('L','M','A',' '): /* Low Mari */
+ return hb_language_from_string ("mhr", -1); /* Eastern Mari */
case HB_TAG('L','U','H',' '): /* Luyia */
return hb_language_from_string ("luy", -1); /* Luyia [macrolanguage] */
case HB_TAG('L','V','I',' '): /* Latvian */
@@ -2884,10 +2908,12 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("man", -1); /* Mandingo [macrolanguage] */
case HB_TAG('M','O','L',' '): /* Moldavian */
return hb_language_from_string ("ro-MD", -1); /* Romanian; Moldova */
+ case HB_TAG('M','O','N','T'): /* Thailand Mon */
+ return hb_language_from_string ("mnw-TH", -1); /* Mon; Thailand */
case HB_TAG('M','Y','N',' '): /* Mayan */
- return hb_language_from_string ("myn", -1); /* Mayan [family] */
+ return hb_language_from_string ("myn", -1); /* Mayan [collection] */
case HB_TAG('N','A','H',' '): /* Nahuatl */
- return hb_language_from_string ("nah", -1); /* Nahuatl [family] */
+ return hb_language_from_string ("nah", -1); /* Nahuatl [collection] */
case HB_TAG('N','E','P',' '): /* Nepali */
return hb_language_from_string ("ne", -1); /* Nepali [macrolanguage] */
case HB_TAG('N','I','S',' '): /* Nisi */
@@ -2914,6 +2940,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("qwh", -1); /* Huaylas Ancash Quechua */
case HB_TAG('R','A','J',' '): /* Rajasthani */
return hb_language_from_string ("raj", -1); /* Rajasthani [macrolanguage] */
+ case HB_TAG('R','O','M',' '): /* Romanian */
+ return hb_language_from_string ("ro", -1); /* Romanian */
case HB_TAG('R','O','Y',' '): /* Romany */
return hb_language_from_string ("rom", -1); /* Romany [macrolanguage] */
case HB_TAG('S','Q','I',' '): /* Albanian */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
index 1837063af8..f50be97ad3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
@@ -41,6 +41,7 @@ hb_ot_old_tag_from_script (hb_script_t script)
switch ((hb_tag_t) script)
{
case HB_SCRIPT_INVALID: return HB_OT_TAG_DEFAULT_SCRIPT;
+ case HB_SCRIPT_MATH: return HB_OT_TAG_MATH_SCRIPT;
/* KATAKANA and HIRAGANA both map to 'kana' */
case HB_SCRIPT_HIRAGANA: return HB_TAG('k','a','n','a');
@@ -63,6 +64,8 @@ hb_ot_old_tag_to_script (hb_tag_t tag)
{
if (unlikely (tag == HB_OT_TAG_DEFAULT_SCRIPT))
return HB_SCRIPT_INVALID;
+ if (unlikely (tag == HB_OT_TAG_MATH_SCRIPT))
+ return HB_SCRIPT_MATH;
/* This side of the conversion is fully algorithmic. */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
new file mode 100644
index 0000000000..0eafb949d5
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
@@ -0,0 +1,264 @@
+/*
+ * Copyright © 2021 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#ifndef HB_OT_VAR_COMMON_HH
+#define HB_OT_VAR_COMMON_HH
+
+#include "hb-ot-layout-common.hh"
+
+
+namespace OT {
+
+struct DeltaSetIndexMapFormat0
+{
+ friend struct DeltaSetIndexMap;
+
+ private:
+ DeltaSetIndexMapFormat0* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->start_embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ unsigned total_size = min_size + mapCount * get_width ();
+ HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
+ if (unlikely (!p)) return_trace (nullptr);
+
+ memcpy (p, this, HBUINT8::static_size * total_size);
+ return_trace (out);
+ }
+
+ template <typename T>
+ bool serialize (hb_serialize_context_t *c, const T &plan)
+ {
+ unsigned int width = plan.get_width ();
+ unsigned int inner_bit_count = plan.get_inner_bit_count ();
+ const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
+
+ TRACE_SERIALIZE (this);
+ if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
+ return_trace (false);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+
+ entryFormat = ((width-1)<<4)|(inner_bit_count-1);
+ mapCount = output_map.length;
+ HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
+ if (unlikely (!p)) return_trace (false);
+ for (unsigned int i = 0; i < output_map.length; i++)
+ {
+ unsigned int v = output_map[i];
+ unsigned int outer = v >> 16;
+ unsigned int inner = v & 0xFFFF;
+ unsigned int u = (outer << inner_bit_count) | inner;
+ for (unsigned int w = width; w > 0;)
+ {
+ p[--w] = u;
+ u >>= 8;
+ }
+ p += width;
+ }
+ return_trace (true);
+ }
+
+ uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
+ {
+ /* If count is zero, pass value unchanged. This takes
+ * care of direct mapping for advance map. */
+ if (!mapCount)
+ return v;
+
+ if (v >= mapCount)
+ v = mapCount - 1;
+
+ unsigned int u = 0;
+ { /* Fetch it. */
+ unsigned int w = get_width ();
+ const HBUINT8 *p = mapDataZ.arrayZ + w * v;
+ for (; w; w--)
+ u = (u << 8) + *p++;
+ }
+
+ { /* Repack it. */
+ unsigned int n = get_inner_bit_count ();
+ unsigned int outer = u >> n;
+ unsigned int inner = u & ((1 << n) - 1);
+ u = (outer<<16) | inner;
+ }
+
+ return u;
+ }
+
+ unsigned get_map_count () const { return mapCount; }
+ unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; }
+ unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
+
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ c->check_range (mapDataZ.arrayZ,
+ mapCount,
+ get_width ()));
+ }
+
+ protected:
+ HBUINT8 format; /* Format identifier--format = 0 */
+ HBUINT8 entryFormat; /* A packed field that describes the compressed
+ * representation of delta-set indices. */
+ HBUINT16 mapCount; /* The number of mapping entries. */
+ UnsizedArrayOf<HBUINT8>
+ mapDataZ; /* The delta-set index mapping data. */
+
+ public:
+ DEFINE_SIZE_ARRAY (4, mapDataZ);
+};
+
+struct DeltaSetIndexMapFormat1
+{
+ friend struct DeltaSetIndexMap;
+
+ private:
+ DeltaSetIndexMapFormat1* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->start_embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ unsigned total_size = min_size + mapCount * get_width ();
+ HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
+ if (unlikely (!p)) return_trace (nullptr);
+
+ memcpy (p, this, HBUINT8::static_size * total_size);
+ return_trace (out);
+ }
+
+ unsigned get_map_count () const { return mapCount; }
+ unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; }
+ unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ c->check_range (mapDataZ.arrayZ,
+ mapCount,
+ get_width ()));
+ }
+
+ protected:
+ HBUINT8 format; /* Format identifier--format = 1 */
+ HBUINT8 entryFormat; /* A packed field that describes the compressed
+ * representation of delta-set indices. */
+ HBUINT32 mapCount; /* The number of mapping entries. */
+ UnsizedArrayOf<HBUINT8>
+ mapDataZ; /* The delta-set index mapping data. */
+
+ public:
+ DEFINE_SIZE_ARRAY (6, mapDataZ);
+};
+
+struct DeltaSetIndexMap
+{
+ template <typename T>
+ bool serialize (hb_serialize_context_t *c, const T &plan)
+ {
+ TRACE_SERIALIZE (this);
+ switch (u.format) {
+ case 0: return_trace (u.format0.serialize (c, plan));
+ default:return_trace (false);
+ }
+ }
+
+ uint32_t map (unsigned v) const
+ {
+ switch (u.format) {
+ case 0: return (u.format0.map (v));
+ default:return v;
+ }
+ }
+
+ unsigned get_map_count () const
+ {
+ switch (u.format) {
+ case 0: return u.format0.get_map_count ();
+ case 1: return u.format1.get_map_count ();
+ default:return 0;
+ }
+ }
+
+ unsigned get_width () const
+ {
+ switch (u.format) {
+ case 0: return u.format0.get_width ();
+ case 1: return u.format1.get_width ();
+ default:return 0;
+ }
+ }
+
+ unsigned get_inner_bit_count () const
+ {
+ switch (u.format) {
+ case 0: return u.format0.get_inner_bit_count ();
+ case 1: return u.format1.get_inner_bit_count ();
+ default:return 0;
+ }
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.format.sanitize (c)) return_trace (false);
+ switch (u.format) {
+ case 0: return_trace (u.format0.sanitize (c));
+ case 1: return_trace (u.format1.sanitize (c));
+ default:return_trace (true);
+ }
+ }
+
+ DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ switch (u.format) {
+ case 0: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c)));
+ case 1: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c)));
+ default:return_trace (nullptr);
+ }
+ }
+
+ protected:
+ union {
+ HBUINT8 format; /* Format identifier */
+ DeltaSetIndexMapFormat0 format0;
+ DeltaSetIndexMapFormat1 format1;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (1, format);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_VAR_COMMON_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
index 05f289db26..e066558683 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh
@@ -263,7 +263,7 @@ struct fvar
if (coords_length && *coords_length)
{
hb_array_t<const HBFixed> instanceCoords = instance->get_coordinates (axisCount)
- .sub_array (0, *coords_length);
+ .sub_array (0, coords_length);
for (unsigned int i = 0; i < instanceCoords.length; i++)
coords[i] = instanceCoords.arrayZ[i].to_float ();
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh
index 49b5532d40..618cec08fb 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh
@@ -399,7 +399,7 @@ struct gvar
get_offset (glyphCount) - get_offset (0)));
}
- /* GlyphVariationData not sanitized here; must be checked while accessing each glyph varation data */
+ /* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */
bool sanitize (hb_sanitize_context_t *c) const
{ return sanitize_shallow (c); }
@@ -498,9 +498,9 @@ struct gvar
public:
struct accelerator_t
{
- void init (hb_face_t *face)
+ accelerator_t (hb_face_t *face)
{ table = hb_sanitize_context_t ().reference_table<gvar> (face); }
- void fini () { table.destroy (); }
+ ~accelerator_t () { table.destroy (); }
private:
struct x_getter { static float get (const contour_point_t &p) { return p.x; } };
@@ -577,10 +577,11 @@ struct gvar
hb_bytes_t bytes ((const char *) p, length);
hb_vector_t<unsigned int> private_indices;
- if (iterator.current_tuple->has_private_points () &&
+ bool has_private_points = iterator.current_tuple->has_private_points ();
+ if (has_private_points &&
!GlyphVariationData::unpack_points (p, private_indices, bytes))
return false;
- const hb_array_t<unsigned int> &indices = private_indices.length ? private_indices : shared_indices;
+ const hb_array_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
bool apply_to_all = (indices.length == 0);
unsigned int num_deltas = apply_to_all ? points.length : indices.length;
@@ -698,7 +699,9 @@ no_more_gaps:
DEFINE_SIZE_MIN (20);
};
-struct gvar_accelerator_t : gvar::accelerator_t {};
+struct gvar_accelerator_t : gvar::accelerator_t {
+ gvar_accelerator_t (hb_face_t *face) : gvar::accelerator_t (face) {}
+};
} /* namespace OT */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
index 72217e7f29..e9d90352f0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
@@ -28,97 +28,11 @@
#define HB_OT_VAR_HVAR_TABLE_HH
#include "hb-ot-layout-common.hh"
-
+#include "hb-ot-var-common.hh"
namespace OT {
-struct DeltaSetIndexMap
-{
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- c->check_range (mapDataZ.arrayZ,
- mapCount,
- get_width ()));
- }
-
- template <typename T>
- bool serialize (hb_serialize_context_t *c, const T &plan)
- {
- unsigned int width = plan.get_width ();
- unsigned int inner_bit_count = plan.get_inner_bit_count ();
- const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
-
- TRACE_SERIALIZE (this);
- if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
- return_trace (false);
- if (unlikely (!c->extend_min (this))) return_trace (false);
-
- format = ((width-1)<<4)|(inner_bit_count-1);
- mapCount = output_map.length;
- HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
- if (unlikely (!p)) return_trace (false);
- for (unsigned int i = 0; i < output_map.length; i++)
- {
- unsigned int v = output_map[i];
- unsigned int outer = v >> 16;
- unsigned int inner = v & 0xFFFF;
- unsigned int u = (outer << inner_bit_count) | inner;
- for (unsigned int w = width; w > 0;)
- {
- p[--w] = u;
- u >>= 8;
- }
- p += width;
- }
- return_trace (true);
- }
-
- uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
- {
- /* If count is zero, pass value unchanged. This takes
- * care of direct mapping for advance map. */
- if (!mapCount)
- return v;
-
- if (v >= mapCount)
- v = mapCount - 1;
-
- unsigned int u = 0;
- { /* Fetch it. */
- unsigned int w = get_width ();
- const HBUINT8 *p = mapDataZ.arrayZ + w * v;
- for (; w; w--)
- u = (u << 8) + *p++;
- }
-
- { /* Repack it. */
- unsigned int n = get_inner_bit_count ();
- unsigned int outer = u >> n;
- unsigned int inner = u & ((1 << n) - 1);
- u = (outer<<16) | inner;
- }
-
- return u;
- }
-
- unsigned int get_map_count () const { return mapCount; }
- unsigned int get_width () const { return ((format >> 4) & 3) + 1; }
- unsigned int get_inner_bit_count () const { return (format & 0xF) + 1; }
-
- protected:
- HBUINT16 format; /* A packed field that describes the compressed
- * representation of delta-set indices. */
- HBUINT16 mapCount; /* The number of mapping entries. */
- UnsizedArrayOf<HBUINT8>
- mapDataZ; /* The delta-set index mapping data. */
-
- public:
- DEFINE_SIZE_ARRAY (4, mapDataZ);
-};
-
struct index_map_subset_plan_t
{
enum index_map_index_t {
@@ -263,9 +177,6 @@ struct hvarvvar_subset_plan_t
inner_maps.resize (var_store->get_sub_table_count ());
- for (unsigned int i = 0; i < inner_maps.length; i++)
- inner_maps[i].init ();
-
if (unlikely (!index_map_plans.length || !inner_sets.length || !inner_maps.length)) return;
bool retain_adv_map = false;
@@ -315,8 +226,8 @@ struct hvarvvar_subset_plan_t
for (unsigned int i = 0; i < inner_sets.length; i++)
hb_set_destroy (inner_sets[i]);
hb_set_destroy (adv_set);
- inner_maps.fini_deep ();
- index_map_plans.fini_deep ();
+ inner_maps.fini ();
+ index_map_plans.fini ();
}
hb_inc_bimap_t outer_map;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc
index 6b42b45cd9..0376e26b4a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc
@@ -303,6 +303,9 @@ hb_ot_var_normalize_variations (hb_face_t *face,
* values for the axis are mapped to the interval [-1,1], with the default
* axis value mapped to 0.
*
+ * The normalized values have 14 bits of fixed-point sub-integer precision as per
+ * OpenType specification.
+ *
* Any additional scaling defined in the face's `avar` table is also
* applied, as described at https://docs.microsoft.com/en-us/typography/opentype/spec/avar
*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.h
index ce201d3b4f..05147cc25e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.h
@@ -109,7 +109,7 @@ typedef enum { /*< flags >*/
* @tag: The #hb_tag_t tag identifying the design variation of the axis
* @name_id: The `name` table Name ID that provides display names for the axis
* @flags: The #hb_ot_var_axis_flags_t flags for the axis
- * @min_value: The mininum value on the variation axis that the font covers
+ * @min_value: The minimum value on the variation axis that the font covers
* @default_value: The position on the variation axis corresponding to the font's defaults
* @max_value: The maximum value on the variation axis that the font covers
*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh
index efa7737d6f..811e13919e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-vorg-table.hh
@@ -48,7 +48,7 @@ struct VertOriginMetric
}
public:
- HBGlyphID glyph;
+ HBGlyphID16 glyph;
FWORD vertOriginY;
public:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh b/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
index b02128b5c4..2a9e75c45b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
@@ -33,40 +33,71 @@
#include "hb-serialize.hh"
#include "hb-vector.hh"
-
+/*
+ * For a detailed writeup on the overflow resolution algorithm see:
+ * docs/repacker.md
+ */
struct graph_t
{
struct vertex_t
{
- vertex_t () :
- distance (0),
- incoming_edges (0),
- start (0),
- end (0),
- priority(0) {}
-
- void fini () { obj.fini (); }
-
hb_serialize_context_t::object_t obj;
- int64_t distance;
- unsigned incoming_edges;
- unsigned start;
- unsigned end;
- unsigned priority;
+ int64_t distance = 0 ;
+ int64_t space = 0 ;
+ hb_vector_t<unsigned> parents;
+ unsigned start = 0;
+ unsigned end = 0;
+ unsigned priority = 0;
bool is_shared () const
{
- return incoming_edges > 1;
+ return parents.length > 1;
+ }
+
+ unsigned incoming_edges () const
+ {
+ return parents.length;
+ }
+
+ void remove_parent (unsigned parent_index)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ {
+ if (parents[i] != parent_index) continue;
+ parents.remove (i);
+ break;
+ }
+ }
+
+ void remap_parents (const hb_vector_t<unsigned>& id_map)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ parents[i] = id_map[parents[i]];
+ }
+
+ void remap_parent (unsigned old_index, unsigned new_index)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ {
+ if (parents[i] == old_index)
+ parents[i] = new_index;
+ }
}
bool is_leaf () const
{
- return !obj.links.length;
+ return !obj.real_links.length && !obj.virtual_links.length;
}
- void raise_priority ()
+ bool raise_priority ()
{
+ if (has_max_priority ()) return false;
priority++;
+ return true;
+ }
+
+ bool has_max_priority () const {
+ return priority >= 3;
}
int64_t modified_distance (unsigned order) const
@@ -76,49 +107,29 @@ struct graph_t
// it's parent where possible.
int64_t modified_distance =
- hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFF);
- return (modified_distance << 24) | (0x00FFFFFF & order);
+ hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF);
+ if (has_max_priority ()) {
+ modified_distance = 0;
+ }
+ return (modified_distance << 18) | (0x003FFFF & order);
}
int64_t distance_modifier () const
{
if (!priority) return 0;
int64_t table_size = obj.tail - obj.head;
- return -(table_size - table_size / (1 << hb_min(priority, 16u)));
+
+ if (priority == 1)
+ return -table_size / 2;
+
+ return -table_size;
}
};
struct overflow_record_t
{
unsigned parent;
- const hb_serialize_context_t::object_t::link_t* link;
- };
-
- struct clone_buffer_t
- {
- clone_buffer_t () : head (nullptr), tail (nullptr) {}
-
- bool copy (const hb_serialize_context_t::object_t& object)
- {
- fini ();
- unsigned size = object.tail - object.head;
- head = (char*) hb_malloc (size);
- if (!head) return false;
-
- memcpy (head, object.head, size);
- tail = head + size;
- return true;
- }
-
- char* head;
- char* tail;
-
- void fini ()
- {
- if (!head) return;
- hb_free (head);
- head = nullptr;
- }
+ unsigned child;
};
/*
@@ -128,12 +139,14 @@ struct graph_t
* the 'packed' object stack used internally in the
* serializer
*/
- graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects)
- : edge_count_invalid (true),
+ template<typename T>
+ graph_t (const T& objects)
+ : parents_invalid (true),
distance_invalid (true),
positions_invalid (true),
successful (true)
{
+ num_roots_for_space_.push (1);
bool removed_nil = false;
for (unsigned i = 0; i < objects.length; i++)
{
@@ -151,21 +164,23 @@ struct graph_t
if (check_success (!vertices_.in_error ()))
v->obj = *objects[i];
if (!removed_nil) continue;
- for (unsigned i = 0; i < v->obj.links.length; i++)
- // Fix indices to account for removed nil object.
- v->obj.links[i].objidx--;
+ // Fix indices to account for removed nil object.
+ for (auto& l : v->obj.all_links_writer ()) {
+ l.objidx--;
+ }
}
}
~graph_t ()
{
- vertices_.fini_deep ();
- clone_buffers_.fini_deep ();
+ vertices_.fini ();
}
bool in_error () const
{
- return !successful || vertices_.in_error () || clone_buffers_.in_error ();
+ return !successful ||
+ vertices_.in_error () ||
+ num_roots_for_space_.in_error ();
}
const vertex_t& root () const
@@ -189,26 +204,46 @@ struct graph_t
/*
* serialize graph into the provided serialization buffer.
*/
- void serialize (hb_serialize_context_t* c) const
+ hb_blob_t* serialize () const
{
- c->start_serialize<void> ();
+ hb_vector_t<char> buffer;
+ size_t size = serialized_length ();
+ if (!buffer.alloc (size)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
+ return nullptr;
+ }
+ hb_serialize_context_t c((void *) buffer, size);
+
+ c.start_serialize<void> ();
for (unsigned i = 0; i < vertices_.length; i++) {
- c->push ();
+ c.push ();
size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
- char* start = c->allocate_size <char> (size);
- if (!start) return;
+ char* start = c.allocate_size <char> (size);
+ if (!start) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space.");
+ return nullptr;
+ }
memcpy (start, vertices_[i].obj.head, size);
- for (const auto& link : vertices_[i].obj.links)
- serialize_link (link, start, c);
+ // Only real links needs to be serialized.
+ for (const auto& link : vertices_[i].obj.real_links)
+ serialize_link (link, start, &c);
// All duplications are already encoded in the graph, so don't
// enable sharing during packing.
- c->pop_pack (false);
+ c.pop_pack (false);
+ }
+ c.end_serialize ();
+
+ if (c.in_error ()) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d",
+ c.errors);
+ return nullptr;
}
- c->end_serialize ();
+
+ return c.copy_blob ();
}
/*
@@ -226,12 +261,13 @@ struct graph_t
hb_vector_t<unsigned> queue;
hb_vector_t<vertex_t> sorted_graph;
+ if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
hb_vector_t<unsigned> id_map;
if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
hb_vector_t<unsigned> removed_edges;
if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
- update_incoming_edge_count ();
+ update_parents ();
queue.push (root_idx ());
int new_id = vertices_.length - 1;
@@ -242,12 +278,12 @@ struct graph_t
queue.remove (0);
vertex_t& next = vertices_[next_id];
- sorted_graph.push (next);
+ sorted_graph[new_id] = next;
id_map[next_id] = new_id--;
- for (const auto& link : next.obj.links) {
+ for (const auto& link : next.obj.all_links ()) {
removed_edges[link.objidx]++;
- if (!(vertices_[link.objidx].incoming_edges - removed_edges[link.objidx]))
+ if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
queue.push (link.objidx);
}
}
@@ -255,15 +291,12 @@ struct graph_t
check_success (!queue.in_error ());
check_success (!sorted_graph.in_error ());
if (!check_success (new_id == -1))
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
-
- remap_obj_indices (id_map, &sorted_graph);
+ print_orphaned_nodes ();
- sorted_graph.as_array ().reverse ();
+ remap_all_obj_indices (id_map, &sorted_graph);
- vertices_.fini_deep ();
- vertices_ = sorted_graph;
- sorted_graph.fini_deep ();
+ hb_swap (vertices_, sorted_graph);
+ sorted_graph.fini ();
}
/*
@@ -283,12 +316,13 @@ struct graph_t
hb_priority_queue_t queue;
hb_vector_t<vertex_t> sorted_graph;
+ if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
hb_vector_t<unsigned> id_map;
if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
hb_vector_t<unsigned> removed_edges;
if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
- update_incoming_edge_count ();
+ update_parents ();
queue.insert (root ().modified_distance (0), root_idx ());
int new_id = root_idx ();
@@ -298,12 +332,12 @@ struct graph_t
unsigned next_id = queue.pop_minimum().second;
vertex_t& next = vertices_[next_id];
- sorted_graph.push (next);
+ sorted_graph[new_id] = next;
id_map[next_id] = new_id--;
- for (const auto& link : next.obj.links) {
+ for (const auto& link : next.obj.all_links ()) {
removed_edges[link.objidx]++;
- if (!(vertices_[link.objidx].incoming_edges - removed_edges[link.objidx]))
+ if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
// Add the order that the links were encountered to the priority.
// This ensures that ties between priorities objects are broken in a consistent
// way. More specifically this is set up so that if a set of objects have the same
@@ -317,72 +351,282 @@ struct graph_t
check_success (!queue.in_error ());
check_success (!sorted_graph.in_error ());
if (!check_success (new_id == -1))
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
+ print_orphaned_nodes ();
+
+ remap_all_obj_indices (id_map, &sorted_graph);
+
+ hb_swap (vertices_, sorted_graph);
+ sorted_graph.fini ();
+ }
+
+ /*
+ * Assign unique space numbers to each connected subgraph of 32 bit offset(s).
+ */
+ bool assign_32bit_spaces ()
+ {
+ unsigned root_index = root_idx ();
+ hb_set_t visited;
+ hb_set_t roots;
+ for (unsigned i = 0; i <= root_index; i++)
+ {
+ // Only real links can form 32 bit spaces
+ for (auto& l : vertices_[i].obj.real_links)
+ {
+ if (l.width == 4 && !l.is_signed)
+ {
+ roots.add (l.objidx);
+ find_subgraph (l.objidx, visited);
+ }
+ }
+ }
+
+ // Mark everything not in the subgraphs of 32 bit roots as visited.
+ // This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs.
+ visited.invert ();
+
+ if (!roots) return false;
+
+ while (roots)
+ {
+ unsigned next = HB_SET_VALUE_INVALID;
+ if (unlikely (!check_success (!roots.in_error ()))) break;
+ if (!roots.next (&next)) break;
+
+ hb_set_t connected_roots;
+ find_connected_nodes (next, roots, visited, connected_roots);
+ if (unlikely (!check_success (!connected_roots.in_error ()))) break;
+
+ isolate_subgraph (connected_roots);
+ if (unlikely (!check_success (!connected_roots.in_error ()))) break;
+
+ unsigned next_space = this->next_space ();
+ num_roots_for_space_.push (0);
+ for (unsigned root : connected_roots)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space);
+ vertices_[root].space = next_space;
+ num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1;
+ distance_invalid = true;
+ positions_invalid = true;
+ }
+
+ // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space
+ // into the 32 bit space as needed, instead of using isolation.
+ }
- remap_obj_indices (id_map, &sorted_graph);
- sorted_graph.as_array ().reverse ();
- vertices_.fini_deep ();
- vertices_ = sorted_graph;
- sorted_graph.fini_deep ();
+ return true;
}
/*
- * Creates a copy of child and re-assigns the link from
- * parent to the clone. The copy is a shallow copy, objects
- * linked from child are not duplicated.
+ * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph
+ * that originate from outside of the subgraph will be removed by duplicating the linked to
+ * object.
+ *
+ * Indices stored in roots will be updated if any of the roots are duplicated to new indices.
*/
- void duplicate (unsigned parent_idx, unsigned child_idx)
+ bool isolate_subgraph (hb_set_t& roots)
{
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
- parent_idx, child_idx);
+ update_parents ();
+ hb_hashmap_t<unsigned, unsigned> subgraph;
- positions_invalid = true;
+ // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these
+ // set the subgraph incoming edge count to match all of root_idx's incoming edges
+ hb_set_t parents;
+ for (unsigned root_idx : roots)
+ {
+ subgraph.set (root_idx, wide_parents (root_idx, parents));
+ find_subgraph (root_idx, subgraph);
+ }
- auto* clone = vertices_.push ();
- auto& child = vertices_[child_idx];
- clone_buffer_t* buffer = clone_buffers_.push ();
- if (vertices_.in_error ()
- || clone_buffers_.in_error ()
- || !check_success (buffer->copy (child.obj))) {
- return;
+ unsigned original_root_idx = root_idx ();
+ hb_hashmap_t<unsigned, unsigned> index_map;
+ bool made_changes = false;
+ for (auto entry : subgraph.iter ())
+ {
+ const auto& node = vertices_[entry.first];
+ unsigned subgraph_incoming_edges = entry.second;
+
+ if (subgraph_incoming_edges < node.incoming_edges ())
+ {
+ // Only de-dup objects with incoming links from outside the subgraph.
+ made_changes = true;
+ duplicate_subgraph (entry.first, index_map);
+ }
}
- clone->obj.head = buffer->head;
- clone->obj.tail = buffer->tail;
- clone->distance = child.distance;
+ if (!made_changes)
+ return false;
- for (const auto& l : child.obj.links)
- clone->obj.links.push (l);
+ if (original_root_idx != root_idx ()
+ && parents.has (original_root_idx))
+ {
+ // If the root idx has changed since parents was determined, update root idx in parents
+ parents.add (root_idx ());
+ parents.del (original_root_idx);
+ }
- check_success (!clone->obj.links.in_error ());
+ auto new_subgraph =
+ + subgraph.keys ()
+ | hb_map([&] (unsigned node_idx) {
+ if (index_map.has (node_idx)) return index_map[node_idx];
+ return node_idx;
+ })
+ ;
- auto& parent = vertices_[parent_idx];
- unsigned clone_idx = vertices_.length - 2;
- for (unsigned i = 0; i < parent.obj.links.length; i++)
+ remap_obj_indices (index_map, new_subgraph);
+ remap_obj_indices (index_map, parents.iter (), true);
+
+ // Update roots set with new indices as needed.
+ unsigned next = HB_SET_VALUE_INVALID;
+ while (roots.next (&next))
+ {
+ if (index_map.has (next))
+ {
+ roots.del (next);
+ roots.add (index_map[next]);
+ }
+ }
+
+ return true;
+ }
+
+ void find_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& subgraph)
+ {
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
{
- auto& l = parent.obj.links[i];
- if (l.objidx == child_idx)
+ if (subgraph.has (link.objidx))
{
- l.objidx = clone_idx;
- clone->incoming_edges++;
- child.incoming_edges--;
+ subgraph.set (link.objidx, subgraph[link.objidx] + 1);
+ continue;
}
+ subgraph.set (link.objidx, 1);
+ find_subgraph (link.objidx, subgraph);
}
+ }
+
+ void find_subgraph (unsigned node_idx, hb_set_t& subgraph)
+ {
+ if (subgraph.has (node_idx)) return;
+ subgraph.add (node_idx);
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ find_subgraph (link.objidx, subgraph);
+ }
+
+ /*
+ * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
+ * links. index_map is updated with mappings from old id to new id. If a duplication has already
+ * been performed for a given index, then it will be skipped.
+ */
+ void duplicate_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& index_map)
+ {
+ if (index_map.has (node_idx))
+ return;
+
+ index_map.set (node_idx, duplicate (node_idx));
+ for (const auto& l : object (node_idx).all_links ()) {
+ duplicate_subgraph (l.objidx, index_map);
+ }
+ }
+
+ /*
+ * Creates a copy of node_idx and returns it's new index.
+ */
+ unsigned duplicate (unsigned node_idx)
+ {
+ positions_invalid = true;
+ distance_invalid = true;
+
+ auto* clone = vertices_.push ();
+ auto& child = vertices_[node_idx];
+ if (vertices_.in_error ()) {
+ return -1;
+ }
+
+ clone->obj.head = child.obj.head;
+ clone->obj.tail = child.obj.tail;
+ clone->distance = child.distance;
+ clone->space = child.space;
+ clone->parents.reset ();
+
+ unsigned clone_idx = vertices_.length - 2;
+ for (const auto& l : child.obj.real_links)
+ {
+ clone->obj.real_links.push (l);
+ vertices_[l.objidx].parents.push (clone_idx);
+ }
+ for (const auto& l : child.obj.virtual_links)
+ {
+ clone->obj.virtual_links.push (l);
+ vertices_[l.objidx].parents.push (clone_idx);
+ }
+
+ check_success (!clone->obj.real_links.in_error ());
+ check_success (!clone->obj.virtual_links.in_error ());
// The last object is the root of the graph, so swap back the root to the end.
// The root's obj idx does change, however since it's root nothing else refers to it.
// all other obj idx's will be unaffected.
vertex_t root = vertices_[vertices_.length - 2];
- vertices_[vertices_.length - 2] = *clone;
+ vertices_[clone_idx] = *clone;
vertices_[vertices_.length - 1] = root;
+
+ // Since the root moved, update the parents arrays of all children on the root.
+ for (const auto& l : root.obj.all_links ())
+ vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
+
+ return clone_idx;
+ }
+
+ /*
+ * Creates a copy of child and re-assigns the link from
+ * parent to the clone. The copy is a shallow copy, objects
+ * linked from child are not duplicated.
+ */
+ bool duplicate (unsigned parent_idx, unsigned child_idx)
+ {
+ update_parents ();
+
+ unsigned links_to_child = 0;
+ for (const auto& l : vertices_[parent_idx].obj.all_links ())
+ {
+ if (l.objidx == child_idx) links_to_child++;
+ }
+
+ if (vertices_[child_idx].incoming_edges () <= links_to_child)
+ {
+ // Can't duplicate this node, doing so would orphan the original one as all remaining links
+ // to child are from parent.
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
+ parent_idx, child_idx);
+ return false;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
+ parent_idx, child_idx);
+
+ unsigned clone_idx = duplicate (child_idx);
+ if (clone_idx == (unsigned) -1) return false;
+ // duplicate shifts the root node idx, so if parent_idx was root update it.
+ if (parent_idx == clone_idx) parent_idx++;
+
+ auto& parent = vertices_[parent_idx];
+ for (auto& l : parent.obj.all_links_writer ())
+ {
+ if (l.objidx != child_idx)
+ continue;
+
+ reassign_link (l, parent_idx, clone_idx);
+ }
+
+ return true;
}
/*
* Raises the sorting priority of all children.
*/
- void raise_childrens_priority (unsigned parent_idx)
+ bool raise_childrens_priority (unsigned parent_idx)
{
DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d",
parent_idx);
@@ -390,8 +634,10 @@ struct graph_t
// to invalidate positions. It does not change graph structure so no need
// to update distances or edge counts.
auto& parent = vertices_[parent_idx].obj;
- for (unsigned i = 0; i < parent.links.length; i++)
- vertices_[parent.links[i].objidx].raise_priority ();
+ bool made_change = false;
+ for (auto& l : parent.all_links_writer ())
+ made_change |= vertices_[l.objidx].raise_priority ();
+ return made_change;
}
/*
@@ -404,7 +650,8 @@ struct graph_t
for (int parent_idx = vertices_.length - 1; parent_idx >= 0; parent_idx--)
{
- for (const auto& link : vertices_[parent_idx].obj.links)
+ // Don't need to check virtual links for overflow
+ for (const auto& link : vertices_[parent_idx].obj.real_links)
{
int64_t offset = compute_offset (parent_idx, link);
if (is_valid_offset (offset, link))
@@ -414,7 +661,7 @@ struct graph_t
overflow_record_t r;
r.parent = parent_idx;
- r.link = &link;
+ r.child = link.objidx;
overflows->push (r);
}
}
@@ -423,48 +670,156 @@ struct graph_t
return overflows->length;
}
+ void print_orphaned_nodes ()
+ {
+ if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
+ parents_invalid = true;
+ update_parents();
+
+ for (unsigned i = 0; i < root_idx (); i++)
+ {
+ const auto& v = vertices_[i];
+ if (!v.parents)
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i);
+ }
+ }
+
void print_overflows (const hb_vector_t<overflow_record_t>& overflows)
{
if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
- update_incoming_edge_count ();
+ update_parents ();
+ int limit = 10;
for (const auto& o : overflows)
{
- const auto& child = vertices_[o.link->objidx];
- DEBUG_MSG (SUBSET_REPACK, nullptr, " overflow from %d => %d (%d incoming , %d outgoing)",
+ if (!limit--) break;
+ const auto& parent = vertices_[o.parent];
+ const auto& child = vertices_[o.child];
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " overflow from "
+ "%4d (%4d in, %4d out, space %2d) => "
+ "%4d (%4d in, %4d out, space %2d)",
o.parent,
- o.link->objidx,
- child.incoming_edges,
- child.obj.links.length);
+ parent.incoming_edges (),
+ parent.obj.real_links.length + parent.obj.virtual_links.length,
+ space_for (o.parent),
+ o.child,
+ child.incoming_edges (),
+ child.obj.real_links.length + child.obj.virtual_links.length,
+ space_for (o.child));
+ }
+ if (overflows.length > 10) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10);
+ }
+ }
+
+ unsigned num_roots_for_space (unsigned space) const
+ {
+ return num_roots_for_space_[space];
+ }
+
+ unsigned next_space () const
+ {
+ return num_roots_for_space_.length;
+ }
+
+ void move_to_new_space (const hb_set_t& indices)
+ {
+ num_roots_for_space_.push (0);
+ unsigned new_space = num_roots_for_space_.length - 1;
+
+ for (unsigned index : indices) {
+ auto& node = vertices_[index];
+ num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1;
+ num_roots_for_space_[new_space] = num_roots_for_space_[new_space] + 1;
+ node.space = new_space;
+ distance_invalid = true;
+ positions_invalid = true;
}
}
+ unsigned space_for (unsigned index, unsigned* root = nullptr) const
+ {
+ const auto& node = vertices_[index];
+ if (node.space)
+ {
+ if (root != nullptr)
+ *root = index;
+ return node.space;
+ }
+
+ if (!node.parents)
+ {
+ if (root)
+ *root = index;
+ return 0;
+ }
+
+ return space_for (node.parents[0], root);
+ }
+
void err_other_error () { this->successful = false; }
private:
+ size_t serialized_length () const {
+ size_t total_size = 0;
+ for (unsigned i = 0; i < vertices_.length; i++) {
+ size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
+ total_size += size;
+ }
+ return total_size;
+ }
+
+ /*
+ * Returns the numbers of incoming edges that are 32bits wide.
+ */
+ unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
+ {
+ unsigned count = 0;
+ hb_set_t visited;
+ for (unsigned p : vertices_[node_idx].parents)
+ {
+ if (visited.has (p)) continue;
+ visited.add (p);
+
+ // Only real links can be wide
+ for (const auto& l : vertices_[p].obj.real_links)
+ {
+ if (l.objidx == node_idx && l.width == 4 && !l.is_signed)
+ {
+ count++;
+ parents.add (p);
+ }
+ }
+ }
+ return count;
+ }
+
bool check_success (bool success)
{ return this->successful && (success || (err_other_error (), false)); }
/*
* Creates a map from objid to # of incoming edges.
*/
- void update_incoming_edge_count ()
+ void update_parents ()
{
- if (!edge_count_invalid) return;
+ if (!parents_invalid) return;
for (unsigned i = 0; i < vertices_.length; i++)
- vertices_[i].incoming_edges = 0;
+ vertices_[i].parents.reset ();
- for (const vertex_t& v : vertices_)
+ for (unsigned p = 0; p < vertices_.length; p++)
{
- for (auto& l : v.obj.links)
+ for (auto& l : vertices_[p].obj.all_links ())
{
- vertices_[l.objidx].incoming_edges++;
+ vertices_[l.objidx].parents.push (p);
}
}
- edge_count_invalid = false;
+ parents_invalid = false;
}
/*
@@ -503,7 +858,7 @@ struct graph_t
// Redundant ones are filtered out later on by the visited set.
// According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
// for practical performance this is faster then using a more advanced queue
- // (such as a fibonaacci queue) with a fast decrease priority.
+ // (such as a fibonacci queue) with a fast decrease priority.
for (unsigned i = 0; i < vertices_.length; i++)
{
if (i == vertices_.length - 1)
@@ -515,23 +870,25 @@ struct graph_t
hb_priority_queue_t queue;
queue.insert (0, vertices_.length - 1);
- hb_set_t visited;
+ hb_vector_t<bool> visited;
+ visited.resize (vertices_.length);
while (!queue.in_error () && !queue.is_empty ())
{
unsigned next_idx = queue.pop_minimum ().second;
- if (visited.has (next_idx)) continue;
+ if (visited[next_idx]) continue;
const auto& next = vertices_[next_idx];
int64_t next_distance = vertices_[next_idx].distance;
- visited.add (next_idx);
+ visited[next_idx] = true;
- for (const auto& link : next.obj.links)
+ for (const auto& link : next.obj.all_links ())
{
- if (visited.has (link.objidx)) continue;
+ if (visited[link.objidx]) continue;
const auto& child = vertices_[link.objidx].obj;
- int64_t child_weight = child.tail - child.head +
- ((int64_t) 1 << (link.width * 8));
+ unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
+ int64_t child_weight = (child.tail - child.head) +
+ ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
int64_t child_distance = next_distance + child_weight;
if (child_distance < vertices_[link.objidx].distance)
@@ -545,7 +902,7 @@ struct graph_t
check_success (!queue.in_error ());
if (!check_success (queue.is_empty ()))
{
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
+ print_orphaned_nodes ();
return;
}
@@ -576,6 +933,10 @@ struct graph_t
bool is_valid_offset (int64_t offset,
const hb_serialize_context_t::object_t::link_t& link) const
{
+ if (unlikely (!link.width))
+ // Virtual links can't overflow.
+ return link.is_signed || offset >= 0;
+
if (link.is_signed)
{
if (link.width == 4)
@@ -595,16 +956,51 @@ struct graph_t
}
/*
+ * Updates a link in the graph to point to a different object. Corrects the
+ * parents vector on the previous and new child nodes.
+ */
+ void reassign_link (hb_serialize_context_t::object_t::link_t& link,
+ unsigned parent_idx,
+ unsigned new_idx)
+ {
+ unsigned old_idx = link.objidx;
+ link.objidx = new_idx;
+ vertices_[old_idx].remove_parent (parent_idx);
+ vertices_[new_idx].parents.push (parent_idx);
+ }
+
+ /*
+ * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts.
+ */
+ template<typename Iterator, hb_requires (hb_is_iterator (Iterator))>
+ void remap_obj_indices (const hb_hashmap_t<unsigned, unsigned>& id_map,
+ Iterator subgraph,
+ bool only_wide = false)
+ {
+ if (!id_map) return;
+ for (unsigned i : subgraph)
+ {
+ for (auto& link : vertices_[i].obj.all_links_writer ())
+ {
+ if (!id_map.has (link.objidx)) continue;
+ if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
+
+ reassign_link (link, i, id_map[link.objidx]);
+ }
+ }
+ }
+
+ /*
* Updates all objidx's in all links using the provided mapping.
*/
- void remap_obj_indices (const hb_vector_t<unsigned>& id_map,
- hb_vector_t<vertex_t>* sorted_graph) const
+ void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
+ hb_vector_t<vertex_t>* sorted_graph) const
{
for (unsigned i = 0; i < sorted_graph->length; i++)
{
- for (unsigned j = 0; j < (*sorted_graph)[i].obj.links.length; j++)
+ (*sorted_graph)[i].remap_parents (id_map);
+ for (auto& link : (*sorted_graph)[i].obj.all_links_writer ())
{
- auto& link = (*sorted_graph)[i].obj.links[j];
link.objidx = id_map[link.objidx];
}
}
@@ -631,6 +1027,9 @@ struct graph_t
{
switch (link.width)
{
+ case 0:
+ // Virtual links aren't serialized.
+ return;
case 4:
if (link.is_signed)
{
@@ -656,17 +1055,146 @@ struct graph_t
}
}
+ /*
+ * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped.
+ * For this search the graph is treated as being undirected.
+ *
+ * Connected targets will be added to connected and removed from targets. All visited nodes
+ * will be added to visited.
+ */
+ void find_connected_nodes (unsigned start_idx,
+ hb_set_t& targets,
+ hb_set_t& visited,
+ hb_set_t& connected)
+ {
+ if (unlikely (!check_success (!visited.in_error ()))) return;
+ if (visited.has (start_idx)) return;
+ visited.add (start_idx);
+
+ if (targets.has (start_idx))
+ {
+ targets.del (start_idx);
+ connected.add (start_idx);
+ }
+
+ const auto& v = vertices_[start_idx];
+
+ // Graph is treated as undirected so search children and parents of start_idx
+ for (const auto& l : v.obj.all_links ())
+ find_connected_nodes (l.objidx, targets, visited, connected);
+
+ for (unsigned p : v.parents)
+ find_connected_nodes (p, targets, visited, connected);
+ }
+
public:
// TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
hb_vector_t<vertex_t> vertices_;
private:
- hb_vector_t<clone_buffer_t> clone_buffers_;
- bool edge_count_invalid;
+ bool parents_invalid;
bool distance_invalid;
bool positions_invalid;
bool successful;
+ hb_vector_t<unsigned> num_roots_for_space_;
};
+static inline
+bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+ graph_t& sorted_graph)
+{
+ unsigned space = 0;
+ hb_set_t roots_to_isolate;
+
+ for (int i = overflows.length - 1; i >= 0; i--)
+ {
+ const graph_t::overflow_record_t& r = overflows[i];
+
+ unsigned root;
+ unsigned overflow_space = sorted_graph.space_for (r.parent, &root);
+ if (!overflow_space) continue;
+ if (sorted_graph.num_roots_for_space (overflow_space) <= 1) continue;
+
+ if (!space) {
+ space = overflow_space;
+ }
+
+ if (space == overflow_space)
+ roots_to_isolate.add(root);
+ }
+
+ if (!roots_to_isolate) return false;
+
+ unsigned maximum_to_move = hb_max ((sorted_graph.num_roots_for_space (space) / 2u), 1u);
+ if (roots_to_isolate.get_population () > maximum_to_move) {
+ // Only move at most half of the roots in a space at a time.
+ unsigned extra = roots_to_isolate.get_population () - maximum_to_move;
+ while (extra--) {
+ unsigned root = HB_SET_VALUE_INVALID;
+ roots_to_isolate.previous (&root);
+ roots_to_isolate.del (root);
+ }
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Overflow in space %d (%d roots). Moving %d roots to space %d.",
+ space,
+ sorted_graph.num_roots_for_space (space),
+ roots_to_isolate.get_population (),
+ sorted_graph.next_space ());
+
+ sorted_graph.isolate_subgraph (roots_to_isolate);
+ sorted_graph.move_to_new_space (roots_to_isolate);
+
+ return true;
+}
+
+static inline
+bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+ hb_set_t& priority_bumped_parents,
+ graph_t& sorted_graph)
+{
+ bool resolution_attempted = false;
+
+ // Try resolving the furthest overflows first.
+ for (int i = overflows.length - 1; i >= 0; i--)
+ {
+ const graph_t::overflow_record_t& r = overflows[i];
+ const auto& child = sorted_graph.vertices_[r.child];
+ if (child.is_shared ())
+ {
+ // The child object is shared, we may be able to eliminate the overflow
+ // by duplicating it.
+ if (!sorted_graph.duplicate (r.parent, r.child)) continue;
+ return true;
+ }
+
+ if (child.is_leaf () && !priority_bumped_parents.has (r.parent))
+ {
+ // This object is too far from it's parent, attempt to move it closer.
+ //
+ // TODO(garretrieger): initially limiting this to leaf's since they can be
+ // moved closer with fewer consequences. However, this can
+ // likely can be used for non-leafs as well.
+ // TODO(garretrieger): also try lowering priority of the parent. Make it
+ // get placed further up in the ordering, closer to it's children.
+ // this is probably preferable if the total size of the parent object
+ // is < then the total size of the children (and the parent can be moved).
+ // Since in that case moving the parent will cause a smaller increase in
+ // the length of other offsets.
+ if (sorted_graph.raise_childrens_priority (r.parent)) {
+ priority_bumped_parents.add (r.parent);
+ resolution_attempted = true;
+ }
+ continue;
+ }
+
+ // TODO(garretrieger): add additional offset resolution strategies
+ // - Promotion to extension lookups.
+ // - Table splitting.
+ }
+
+ return resolution_attempted;
+}
/*
* Attempts to modify the topological sorting of the provided object graph to
@@ -677,93 +1205,71 @@ struct graph_t
* If necessary the structure of the graph may be modified in ways that do not
* affect the functionality of the graph. For example shared objects may be
* duplicated.
+ *
+ * For a detailed writeup describing how the algorithm operates see:
+ * docs/repacker.md
*/
-inline void
-hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed,
- hb_serialize_context_t* c) {
+template<typename T>
+inline hb_blob_t*
+hb_resolve_overflows (const T& packed,
+ hb_tag_t table_tag,
+ unsigned max_rounds = 20) {
// Kahn sort is ~twice as fast as shortest distance sort and works for many fonts
// so try it first to save time.
graph_t sorted_graph (packed);
sorted_graph.sort_kahn ();
if (!sorted_graph.will_overflow ())
{
- sorted_graph.serialize (c);
- return;
+ return sorted_graph.serialize ();
}
sorted_graph.sort_shortest_distance ();
+ if ((table_tag == HB_OT_TAG_GPOS
+ || table_tag == HB_OT_TAG_GSUB)
+ && sorted_graph.will_overflow ())
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs.");
+ if (sorted_graph.assign_32bit_spaces ())
+ sorted_graph.sort_shortest_distance ();
+ }
+
unsigned round = 0;
hb_vector_t<graph_t::overflow_record_t> overflows;
// TODO(garretrieger): select a good limit for max rounds.
while (!sorted_graph.in_error ()
&& sorted_graph.will_overflow (&overflows)
- && round++ < 10) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Over flow resolution round %d ===", round);
+ && round++ < max_rounds) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %d ===", round);
sorted_graph.print_overflows (overflows);
- bool resolution_attempted = false;
hb_set_t priority_bumped_parents;
- // Try resolving the furthest overflows first.
- for (int i = overflows.length - 1; i >= 0; i--)
+
+ if (!_try_isolating_subgraphs (overflows, sorted_graph))
{
- const graph_t::overflow_record_t& r = overflows[i];
- const auto& child = sorted_graph.vertices_[r.link->objidx];
- if (child.is_shared ())
+ if (!_process_overflows (overflows, priority_bumped_parents, sorted_graph))
{
- // The child object is shared, we may be able to eliminate the overflow
- // by duplicating it.
- sorted_graph.duplicate (r.parent, r.link->objidx);
- resolution_attempted = true;
-
- // Stop processing overflows for this round so that object order can be
- // updated to account for the newly added object.
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :(");
break;
}
-
- if (child.is_leaf () && !priority_bumped_parents.has (r.parent))
- {
- // This object is too far from it's parent, attempt to move it closer.
- //
- // TODO(garretrieger): initially limiting this to leaf's since they can be
- // moved closer with fewer consequences. However, this can
- // likely can be used for non-leafs as well.
- // TODO(garretrieger): add a maximum priority, don't try to raise past this.
- // TODO(garretrieger): also try lowering priority of the parent. Make it
- // get placed further up in the ordering, closer to it's children.
- // this is probably preferable if the total size of the parent object
- // is < then the total size of the children (and the parent can be moved).
- // Since in that case moving the parent will cause a smaller increase in
- // the length of other offsets.
- sorted_graph.raise_childrens_priority (r.parent);
- priority_bumped_parents.add (r.parent);
- resolution_attempted = true;
- continue;
- }
-
- // TODO(garretrieger): add additional offset resolution strategies
- // - Promotion to extension lookups.
- // - Table splitting.
- }
-
- if (resolution_attempted)
- {
- sorted_graph.sort_shortest_distance ();
- continue;
}
- DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :(");
- c->err (HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
- return;
+ sorted_graph.sort_shortest_distance ();
}
if (sorted_graph.in_error ())
{
- c->err (HB_SERIALIZE_ERROR_OTHER);
- return;
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state.");
+ return nullptr;
}
- sorted_graph.serialize (c);
-}
+ if (sorted_graph.will_overflow ())
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
+ return nullptr;
+ }
+
+ return sorted_graph.serialize ();
+}
#endif /* HB_REPACKER_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
index 56c46015a6..65c2772201 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
@@ -123,6 +123,7 @@ struct hb_sanitize_context_t :
hb_sanitize_context_t () :
start (nullptr), end (nullptr),
max_ops (0), max_subtables (0),
+ recursion_depth (0),
writable (false), edit_count (0),
blob (nullptr),
num_glyphs (65536),
@@ -145,14 +146,14 @@ struct hb_sanitize_context_t :
private:
template <typename T, typename ...Ts> auto
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
- ( obj.sanitize (this, hb_forward<Ts> (ds)...) )
+ ( obj.sanitize (this, std::forward<Ts> (ds)...) )
template <typename T, typename ...Ts> auto
_dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
- ( obj.dispatch (this, hb_forward<Ts> (ds)...) )
+ ( obj.dispatch (this, std::forward<Ts> (ds)...) )
public:
template <typename T, typename ...Ts> auto
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
- ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
+ ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
void init (hb_blob_t *b)
@@ -205,6 +206,7 @@ struct hb_sanitize_context_t :
(unsigned) HB_SANITIZE_MAX_OPS_MAX);
this->edit_count = 0;
this->debug_depth = 0;
+ this->recursion_depth = 0;
DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
"start [%p..%p] (%lu bytes)",
@@ -278,6 +280,18 @@ struct hb_sanitize_context_t :
return this->check_range (base, a, b, hb_static_size (T));
}
+ bool check_start_recursion (int max_depth)
+ {
+ if (unlikely (recursion_depth >= max_depth)) return false;
+ return ++recursion_depth;
+ }
+
+ bool end_recursion (bool result)
+ {
+ recursion_depth--;
+ return result;
+ }
+
template <typename Type>
bool check_struct (const Type *obj) const
{ return likely (this->check_range (obj, obj->min_size)); }
@@ -389,6 +403,7 @@ struct hb_sanitize_context_t :
const char *start, *end;
mutable int max_ops, max_subtables;
private:
+ int recursion_depth;
bool writable;
unsigned int edit_count;
hb_blob_t *blob;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh b/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
index 7212d9872a..40895a4548 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
@@ -36,6 +36,9 @@
#include "hb-map.hh"
#include "hb-pool.hh"
+#ifdef HB_EXPERIMENTAL_API
+#include "hb-subset-repacker.h"
+#endif
/*
* Serialize
@@ -65,19 +68,44 @@ struct hb_serialize_context_t
struct object_t
{
- void fini () { links.fini (); }
+ void fini () {
+ real_links.fini ();
+ virtual_links.fini ();
+ }
+
+ object_t () = default;
+
+#ifdef HB_EXPERIMENTAL_API
+ object_t (const hb_object_t &o)
+ {
+ head = o.head;
+ tail = o.tail;
+ next = nullptr;
+ real_links.alloc (o.num_real_links);
+ for (unsigned i = 0 ; i < o.num_real_links; i++)
+ real_links.push (o.real_links[i]);
+
+ virtual_links.alloc (o.num_virtual_links);
+ for (unsigned i = 0; i < o.num_virtual_links; i++)
+ virtual_links.push (o.virtual_links[i]);
+ }
+#endif
bool operator == (const object_t &o) const
{
+ // Virtual links aren't considered for equality since they don't affect the functionality
+ // of the object.
return (tail - head == o.tail - o.head)
- && (links.length == o.links.length)
+ && (real_links.length == o.real_links.length)
&& 0 == hb_memcmp (head, o.head, tail - head)
- && links.as_bytes () == o.links.as_bytes ();
+ && real_links.as_bytes () == o.real_links.as_bytes ();
}
uint32_t hash () const
{
+ // Virtual links aren't considered for equality since they don't affect the functionality
+ // of the object.
return hb_bytes_t (head, tail - head).hash () ^
- links.as_bytes ().hash ();
+ real_links.as_bytes ().hash ();
}
struct link_t
@@ -88,12 +116,32 @@ struct hb_serialize_context_t
unsigned position: 28;
unsigned bias;
objidx_t objidx;
+
+ link_t () = default;
+
+#ifdef HB_EXPERIMENTAL_API
+ link_t (const hb_link_t &o)
+ {
+ width = o.width;
+ is_signed = 0;
+ whence = 0;
+ position = o.position;
+ bias = 0;
+ objidx = o.objidx;
+ }
+#endif
};
char *head;
char *tail;
- hb_vector_t<link_t> links;
+ hb_vector_t<link_t> real_links;
+ hb_vector_t<link_t> virtual_links;
object_t *next;
+
+ auto all_links () const HB_AUTO_RETURN
+ (( hb_concat (this->real_links, this->virtual_links) ));
+ auto all_links_writer () HB_AUTO_RETURN
+ (( hb_concat (this->real_links.writer (), this->virtual_links.writer ()) ));
};
struct snapshot_t
@@ -101,12 +149,14 @@ struct hb_serialize_context_t
char *head;
char *tail;
object_t *current; // Just for sanity check
- unsigned num_links;
+ unsigned num_real_links;
+ unsigned num_virtual_links;
hb_serialize_error_t errors;
};
snapshot_t snapshot ()
- { return snapshot_t { head, tail, current, current->links.length, errors }; }
+ { return snapshot_t {
+ head, tail, current, current->real_links.length, current->virtual_links.length, errors }; }
hb_serialize_context_t (void *start_, unsigned int size) :
start ((char *) start_),
@@ -189,8 +239,8 @@ struct hb_serialize_context_t
{ return check_success (!hb_deref (obj).in_error ()); }
template <typename T1, typename... Ts> bool propagate_error (T1 &&o1, Ts&&... os)
- { return propagate_error (hb_forward<T1> (o1)) &&
- propagate_error (hb_forward<Ts> (os)...); }
+ { return propagate_error (std::forward<T1> (o1)) &&
+ propagate_error (std::forward<Ts> (os)...); }
/* To be called around main operation. */
template <typename Type>
@@ -264,7 +314,7 @@ struct hb_serialize_context_t
object_pool.release (obj);
}
- /* Set share to false when an object is unlikely sharable with others
+ /* Set share to false when an object is unlikely shareable with others
* so not worth an attempt, or a contiguous table is serialized as
* multiple consecutive objects in the reverse order so can't be shared.
*/
@@ -282,7 +332,8 @@ struct hb_serialize_context_t
if (!len)
{
- assert (!obj->links.length);
+ assert (!obj->real_links.length);
+ assert (!obj->virtual_links.length);
return 0;
}
@@ -292,6 +343,7 @@ struct hb_serialize_context_t
objidx = packed_map.get (obj);
if (objidx)
{
+ merge_virtual_links (obj, objidx);
obj->fini ();
return objidx;
}
@@ -327,7 +379,8 @@ struct hb_serialize_context_t
// Overflows that happened after the snapshot will be erased by the revert.
if (unlikely (in_error () && !only_overflow ())) return;
assert (snap.current == current);
- current->links.shrink (snap.num_links);
+ current->real_links.shrink (snap.num_real_links);
+ current->virtual_links.shrink (snap.num_virtual_links);
errors = snap.errors;
revert (snap.head, snap.tail);
}
@@ -358,6 +411,35 @@ struct hb_serialize_context_t
assert (packed.tail ()->head == tail);
}
+ // Adds a virtual link from the current object to objidx. A virtual link is not associated with
+ // an actual offset field. They are solely used to enforce ordering constraints between objects.
+ // Adding a virtual link from object a to object b will ensure that object b is always packed after
+ // object a in the final serialized order.
+ //
+ // This is useful in certain situations where there needs to be a specific ordering in the
+ // final serialization. Such as when platform bugs require certain orderings, or to provide
+ // guidance to the repacker for better offset overflow resolution.
+ void add_virtual_link (objidx_t objidx)
+ {
+ if (unlikely (in_error ())) return;
+
+ if (!objidx)
+ return;
+
+ assert (current);
+
+ auto& link = *current->virtual_links.push ();
+ if (current->virtual_links.in_error ())
+ err (HB_SERIALIZE_ERROR_OTHER);
+
+ link.width = 0;
+ link.objidx = objidx;
+ link.is_signed = 0;
+ link.whence = 0;
+ link.position = 0;
+ link.bias = 0;
+ }
+
template <typename T>
void add_link (T &ofs, objidx_t objidx,
whence_t whence = Head,
@@ -371,16 +453,27 @@ struct hb_serialize_context_t
assert (current);
assert (current->head <= (const char *) &ofs);
- auto& link = *current->links.push ();
- if (current->links.in_error ())
+ auto& link = *current->real_links.push ();
+ if (current->real_links.in_error ())
err (HB_SERIALIZE_ERROR_OTHER);
link.width = sizeof (T);
- link.is_signed = hb_is_signed (hb_unwrap_type (T));
+ link.objidx = objidx;
+ if (unlikely (!sizeof (T)))
+ {
+ // This link is not associated with an actual offset and exists merely to enforce
+ // an ordering constraint.
+ link.is_signed = 0;
+ link.whence = 0;
+ link.position = 0;
+ link.bias = 0;
+ return;
+ }
+
+ link.is_signed = std::is_signed<hb_unwrap_type (T)>::value;
link.whence = (unsigned) whence;
link.position = (const char *) &ofs - current->head;
link.bias = bias;
- link.objidx = objidx;
}
unsigned to_bias (const void *base) const
@@ -400,7 +493,7 @@ struct hb_serialize_context_t
assert (packed.length > 1);
for (const object_t* parent : ++hb_iter (packed))
- for (const object_t::link_t &link : parent->links)
+ for (const object_t::link_t &link : parent->real_links)
{
const object_t* child = packed[link.objidx];
if (unlikely (!child)) { err (HB_SERIALIZE_ERROR_OTHER); return; }
@@ -452,7 +545,7 @@ struct hb_serialize_context_t
{ return reinterpret_cast<Type *> (this->head); }
template <typename Type>
Type *start_embed (const Type &obj) const
- { return start_embed (hb_addressof (obj)); }
+ { return start_embed (std::addressof (obj)); }
bool err (hb_serialize_error_t err_type)
{
@@ -490,11 +583,11 @@ struct hb_serialize_context_t
}
template <typename Type>
Type *embed (const Type &obj)
- { return embed (hb_addressof (obj)); }
+ { return embed (std::addressof (obj)); }
template <typename Type, typename ...Ts> auto
_copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN
- (Type *, src.copy (this, hb_forward<Ts> (ds)...))
+ (Type *, src.copy (this, std::forward<Ts> (ds)...))
template <typename Type> auto
_copy (const Type &src, hb_priority<0>) -> decltype (&(hb_declval<Type> () = src))
@@ -509,16 +602,16 @@ struct hb_serialize_context_t
* instead of memcpy(). */
template <typename Type, typename ...Ts>
Type *copy (const Type &src, Ts&&... ds)
- { return _copy (src, hb_prioritize, hb_forward<Ts> (ds)...); }
+ { return _copy (src, hb_prioritize, std::forward<Ts> (ds)...); }
template <typename Type, typename ...Ts>
Type *copy (const Type *src, Ts&&... ds)
- { return copy (*src, hb_forward<Ts> (ds)...); }
+ { return copy (*src, std::forward<Ts> (ds)...); }
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator)),
typename ...Ts>
void copy_all (Iterator it, Ts&&... ds)
- { for (decltype (*it) _ : it) copy (_, hb_forward<Ts> (ds)...); }
+ { for (decltype (*it) _ : it) copy (_, std::forward<Ts> (ds)...); }
template <typename Type>
hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; }
@@ -537,19 +630,19 @@ struct hb_serialize_context_t
}
template <typename Type>
Type *extend_size (Type &obj, size_t size)
- { return extend_size (hb_addressof (obj), size); }
+ { return extend_size (std::addressof (obj), size); }
template <typename Type>
Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); }
template <typename Type>
- Type *extend_min (Type &obj) { return extend_min (hb_addressof (obj)); }
+ Type *extend_min (Type &obj) { return extend_min (std::addressof (obj)); }
template <typename Type, typename ...Ts>
Type *extend (Type *obj, Ts&&... ds)
- { return extend_size (obj, obj->get_size (hb_forward<Ts> (ds)...)); }
+ { return extend_size (obj, obj->get_size (std::forward<Ts> (ds)...)); }
template <typename Type, typename ...Ts>
Type *extend (Type &obj, Ts&&... ds)
- { return extend (hb_addressof (obj), hb_forward<Ts> (ds)...); }
+ { return extend (std::addressof (obj), std::forward<Ts> (ds)...); }
/* Output routines. */
hb_bytes_t copy_bytes () const
@@ -600,6 +693,13 @@ struct hb_serialize_context_t
private:
+ void merge_virtual_links (const object_t* from, objidx_t to_idx) {
+ object_t* to = packed[to_idx];
+ for (const auto& l : from->virtual_links) {
+ to->virtual_links.push (l);
+ }
+ }
+
/* Object memory pool. */
hb_pool_t<object_t> object_pool;
@@ -610,7 +710,9 @@ struct hb_serialize_context_t
hb_vector_t<object_t *> packed;
/* Map view of packed objects. */
- hb_hashmap_t<const object_t *, objidx_t, nullptr, 0> packed_map;
+ hb_hashmap_t<const object_t *, objidx_t,
+ const object_t *, objidx_t,
+ nullptr, 0> packed_map;
};
#endif /* HB_SERIALIZE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh
index 1ef1ba5fb2..7d4979b73b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh
@@ -168,15 +168,17 @@ struct hb_set_digest_combiner_t
* There is not much science to this: it's a result of intuition
* and testing.
*/
-typedef hb_set_digest_combiner_t
-<
- hb_set_digest_lowest_bits_t<unsigned long, 4>,
+using hb_set_digest_t =
hb_set_digest_combiner_t
<
- hb_set_digest_lowest_bits_t<unsigned long, 0>,
- hb_set_digest_lowest_bits_t<unsigned long, 9>
+ hb_set_digest_lowest_bits_t<unsigned long, 4>,
+ hb_set_digest_combiner_t
+ <
+ hb_set_digest_lowest_bits_t<unsigned long, 0>,
+ hb_set_digest_lowest_bits_t<unsigned long, 9>
+ >
>
-> hb_set_digest_t;
+;
#endif /* HB_SET_DIGEST_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.cc b/src/3rdparty/harfbuzz-ng/src/hb-set.cc
index 204dbb5645..0e2c1f77ef 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.cc
@@ -257,6 +257,29 @@ hb_set_add (hb_set_t *set,
}
/**
+ * hb_set_add_sorted_array:
+ * @set: A set
+ * @sorted_codepoints: (array length=num_codepoints): Array of codepoints to add
+ * @num_codepoints: Length of @sorted_codepoints
+ *
+ * Adds @num_codepoints codepoints to a set at once.
+ * The codepoints array must be in increasing order,
+ * with size at least @num_codepoints.
+ *
+ * Since: 4.1.0
+ */
+HB_EXTERN void
+hb_set_add_sorted_array (hb_set_t *set,
+ const hb_codepoint_t *sorted_codepoints,
+ unsigned int num_codepoints)
+{
+ /* Immutible-safe. */
+ set->add_sorted_array (sorted_codepoints,
+ num_codepoints,
+ sizeof(hb_codepoint_t));
+}
+
+/**
* hb_set_add_range:
* @set: A set
* @first: The first element to add to @set
@@ -591,3 +614,28 @@ hb_set_previous_range (const hb_set_t *set,
{
return set->previous_range (first, last);
}
+
+/**
+ * hb_set_next_many:
+ * @set: A set
+ * @codepoint: Outputting codepoints starting after this one.
+ * Use #HB_SET_VALUE_INVALID to get started.
+ * @out: (array length=size): An array of codepoints to write to.
+ * @size: The maximum number of codepoints to write out.
+ *
+ * Finds the next element in @set that is greater than @codepoint. Writes out
+ * codepoints to @out, until either the set runs out of elements, or @size
+ * codepoints are written, whichever comes first.
+ *
+ * Return value: the number of values written.
+ *
+ * Since: 4.2.0
+ **/
+unsigned int
+hb_set_next_many (const hb_set_t *set,
+ hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size)
+{
+ return set->next_many (codepoint, out, size);
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.h b/src/3rdparty/harfbuzz-ng/src/hb-set.h
index 423225bf96..10ce7c10d4 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.h
@@ -111,6 +111,11 @@ hb_set_add_range (hb_set_t *set,
hb_codepoint_t last);
HB_EXTERN void
+hb_set_add_sorted_array (hb_set_t *set,
+ const hb_codepoint_t *sorted_codepoints,
+ unsigned int num_codepoints);
+
+HB_EXTERN void
hb_set_del (hb_set_t *set,
hb_codepoint_t codepoint);
@@ -180,6 +185,12 @@ hb_set_previous_range (const hb_set_t *set,
hb_codepoint_t *first,
hb_codepoint_t *last);
+/* Pass HB_SET_VALUE_INVALID in to get started. */
+HB_EXTERN unsigned int
+hb_set_next_many (const hb_set_t *set,
+ hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size);
HB_END_DECLS
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-set.hh
index 437e234361..1f05407869 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.hh
@@ -42,9 +42,22 @@ struct hb_sparseset_t
~hb_sparseset_t () { fini (); }
hb_sparseset_t (const hb_sparseset_t& other) : hb_sparseset_t () { set (other); }
- void operator= (const hb_sparseset_t& other) { set (other); }
- // TODO Add move construtor/assign
- // TODO Add constructor for Iterator
+ hb_sparseset_t (hb_sparseset_t&& other) : hb_sparseset_t () { s = std::move (other.s); }
+ hb_sparseset_t& operator= (const hb_sparseset_t& other) { set (other); return *this; }
+ hb_sparseset_t& operator= (hb_sparseset_t&& other) { hb_swap (*this, other); return *this; }
+ friend void swap (hb_sparseset_t& a, hb_sparseset_t& b) { hb_swap (a.s, b.s); }
+
+ hb_sparseset_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t ()
+ {
+ for (auto&& item : lst)
+ add (item);
+ }
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
+ hb_sparseset_t (const Iterable &o) : hb_sparseset_t ()
+ {
+ hb_copy (o, *this);
+ }
void init_shallow () { s.init (); }
void init ()
@@ -96,6 +109,7 @@ struct hb_sparseset_t
typedef bool value_t;
value_t operator [] (hb_codepoint_t k) const { return get (k); }
bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
@@ -125,6 +139,8 @@ struct hb_sparseset_t
{ return s.next_range (first, last); }
bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
{ return s.previous_range (first, last); }
+ unsigned int next_many (hb_codepoint_t codepoint, hb_codepoint_t *out, unsigned int size) const
+ { return s.next_many (codepoint, out, size); }
unsigned int get_population () const { return s.get_population (); }
hb_codepoint_t get_min () const { return s.get_min (); }
@@ -140,7 +156,18 @@ struct hb_sparseset_t
operator iter_t () const { return iter (); }
};
-struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t> {};
+struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t>
+{
+ hb_set_t () = default;
+ ~hb_set_t () = default;
+ hb_set_t (hb_set_t&) = default;
+ hb_set_t& operator= (const hb_set_t&) = default;
+ hb_set_t& operator= (hb_set_t&&) = default;
+ hb_set_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t<hb_bit_set_invertible_t> (lst) {}
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
+ hb_set_t (const Iterable &o) : hb_sparseset_t<hb_bit_set_invertible_t> (o) {}
+};
static_assert (hb_set_t::INVALID == HB_SET_VALUE_INVALID, "");
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
index c1f619c81c..3407e1af42 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
@@ -126,6 +126,13 @@ hb_shape_full (hb_font_t *font,
unsigned int num_features,
const char * const *shaper_list)
{
+ hb_buffer_t *text_buffer = nullptr;
+ if (buffer->flags & HB_BUFFER_FLAG_VERIFY)
+ {
+ text_buffer = hb_buffer_create ();
+ hb_buffer_append (text_buffer, buffer, 0, -1);
+ }
+
hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props,
features, num_features,
font->coords, font->num_coords,
@@ -133,6 +140,17 @@ hb_shape_full (hb_font_t *font,
hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
hb_shape_plan_destroy (shape_plan);
+ if (text_buffer)
+ {
+ if (res && !buffer->verify (text_buffer,
+ font,
+ features,
+ num_features,
+ shaper_list))
+ res = false;
+ hb_buffer_destroy (text_buffer);
+ }
+
return res;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-static.cc b/src/3rdparty/harfbuzz-ng/src/hb-static.cc
index ec4b241470..7cc51be611 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-static.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-static.cc
@@ -33,6 +33,7 @@
#include "hb-aat-layout-feat-table.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
@@ -55,17 +56,43 @@ const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
/* hb_face_t */
+#ifndef HB_NO_BORING_EXPANSION
+static inline unsigned
+load_num_glyphs_from_loca (const hb_face_t *face)
+{
+ unsigned ret = 0;
+
+ unsigned indexToLocFormat = face->table.head->indexToLocFormat;
+
+ if (indexToLocFormat <= 1)
+ {
+ bool short_offset = 0 == indexToLocFormat;
+ hb_blob_t *loca_blob = face->table.loca.get_blob ();
+ ret = hb_max (1u, loca_blob->length / (short_offset ? 2 : 4)) - 1;
+ }
+
+ return ret;
+}
+#endif
+
+static inline unsigned
+load_num_glyphs_from_maxp (const hb_face_t *face)
+{
+ return face->table.maxp->get_num_glyphs ();
+}
+
unsigned int
hb_face_t::load_num_glyphs () const
{
- hb_sanitize_context_t c = hb_sanitize_context_t ();
- c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */
- hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this);
- const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
+ unsigned ret = 0;
+
+#ifndef HB_NO_BORING_EXPANSION
+ ret = hb_max (ret, load_num_glyphs_from_loca (this));
+#endif
+
+ ret = hb_max (ret, load_num_glyphs_from_maxp (this));
- unsigned int ret = maxp_table->get_num_glyphs ();
num_glyphs.set_relaxed (ret);
- hb_blob_destroy (maxp_blob);
return ret;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-style.cc b/src/3rdparty/harfbuzz-ng/src/hb-style.cc
index dfb1017c88..c7d7d713c2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-style.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-style.cc
@@ -46,15 +46,14 @@
static inline float
_hb_angle_to_ratio (float a)
{
- return tanf (a * float (M_PI / 180.));
+ return tanf (a * float (-M_PI / 180.));
}
-#if 0
+
static inline float
_hb_ratio_to_angle (float r)
{
- return atanf (r) * float (180. / M_PI);
+ return atanf (r) * float (-180. / M_PI);
}
-#endif
/**
* hb_style_get_value:
@@ -109,11 +108,20 @@ hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag)
: 12.f;
}
case HB_STYLE_TAG_SLANT_ANGLE:
- return face->table.post->table->italicAngle.to_float ();
+ {
+ float angle = face->table.post->table->italicAngle.to_float ();
+
+ if (font->slant)
+ angle = _hb_ratio_to_angle (font->slant + _hb_angle_to_ratio (angle));
+
+ return angle;
+ }
case HB_STYLE_TAG_WIDTH:
return face->table.OS2->has_data ()
? face->table.OS2->get_width ()
- : (face->table.head->is_condensed () ? 75 : 100);
+ : (face->table.head->is_condensed () ? 75 :
+ face->table.head->is_expanded () ? 125 :
+ 100);
case HB_STYLE_TAG_WEIGHT:
return face->table.OS2->has_data ()
? face->table.OS2->usWeightClass
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-style.h b/src/3rdparty/harfbuzz-ng/src/hb-style.h
index 30a6f2b878..d17d2daa5f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-style.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-style.h
@@ -43,8 +43,10 @@ HB_BEGIN_DECLS
* @HB_STYLE_TAG_SLANT_ANGLE: Used to vary between upright and slanted text. Values
* must be greater than -90 and less than +90. Values can be interpreted as
* the angle, in counter-clockwise degrees, of oblique slant from whatever the
- * designer considers to be upright for that font design.
+ * designer considers to be upright for that font design. Typical right-leaning
+ * Italic fonts have a negative slant angle (typically around -12)
* @HB_STYLE_TAG_SLANT_RATIO: same as @HB_STYLE_TAG_SLANT_ANGLE expression as ratio.
+ * Typical right-leaning Italic fonts have a positive slant ratio (typically around 0.2)
* @HB_STYLE_TAG_WIDTH: Used to vary width of text from narrower to wider.
* Non-zero. Values can be interpreted as a percentage of whatever the font
* designer considers “normal width” for that font design.
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
index 7fd96ca86d..18657705fa 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
@@ -275,60 +275,36 @@ struct subr_flattener_t
struct subr_closures_t
{
- subr_closures_t () : valid (false), global_closure (nullptr)
- { local_closures.init (); }
-
- void init (unsigned int fd_count)
+ subr_closures_t (unsigned int fd_count) : valid (false), global_closure (), local_closures ()
{
valid = true;
- global_closure = hb_set_create ();
- if (global_closure == hb_set_get_empty ())
- valid = false;
if (!local_closures.resize (fd_count))
valid = false;
-
- for (unsigned int i = 0; i < local_closures.length; i++)
- {
- local_closures[i] = hb_set_create ();
- if (local_closures[i] == hb_set_get_empty ())
- valid = false;
- }
- }
-
- void fini ()
- {
- hb_set_destroy (global_closure);
- for (unsigned int i = 0; i < local_closures.length; i++)
- hb_set_destroy (local_closures[i]);
- local_closures.fini ();
}
void reset ()
{
- hb_set_clear (global_closure);
+ global_closure.clear();
for (unsigned int i = 0; i < local_closures.length; i++)
- hb_set_clear (local_closures[i]);
+ local_closures[i].clear();
}
bool is_valid () const { return valid; }
bool valid;
- hb_set_t *global_closure;
- hb_vector_t<hb_set_t *> local_closures;
+ hb_set_t global_closure;
+ hb_vector_t<hb_set_t> local_closures;
};
struct parsed_cs_op_t : op_str_t
{
void init (unsigned int subr_num_ = 0)
{
- op_str_t::init ();
subr_num = subr_num_;
drop_flag = false;
keep_flag = false;
skip_flag = false;
}
- void fini () { op_str_t::fini (); }
-
bool for_drop () const { return drop_flag; }
void set_drop () { if (!for_keep ()) drop_flag = true; }
@@ -416,16 +392,6 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
{
- void init (unsigned int len_ = 0)
- {
- SUPER::init ();
- if (unlikely (!resize (len_)))
- return;
- for (unsigned int i = 0; i < length; i++)
- (*this)[i].init ();
- }
- void fini () { SUPER::fini_deep (); }
-
private:
typedef hb_vector_t<parsed_cs_str_t> SUPER;
};
@@ -496,7 +462,7 @@ struct subr_subset_param_t
struct subr_remap_t : hb_inc_bimap_t
{
- void create (hb_set_t *closure)
+ void create (const hb_set_t *closure)
{
/* create a remapping of subroutine numbers from old to new.
* no optimization based on usage counts. fonttools doesn't appear doing that either.
@@ -526,19 +492,9 @@ struct subr_remap_t : hb_inc_bimap_t
struct subr_remaps_t
{
- subr_remaps_t ()
+ subr_remaps_t (unsigned int fdCount)
{
- global_remap.init ();
- local_remaps.init ();
- }
-
- ~subr_remaps_t () { fini (); }
-
- void init (unsigned int fdCount)
- {
- if (unlikely (!local_remaps.resize (fdCount))) return;
- for (unsigned int i = 0; i < fdCount; i++)
- local_remaps[i].init ();
+ local_remaps.resize (fdCount);
}
bool in_error()
@@ -548,15 +504,9 @@ struct subr_remaps_t
void create (subr_closures_t& closures)
{
- global_remap.create (closures.global_closure);
+ global_remap.create (&closures.global_closure);
for (unsigned int i = 0; i < local_remaps.length; i++)
- local_remaps[i].create (closures.local_closures[i]);
- }
-
- void fini ()
- {
- global_remap.fini ();
- local_remaps.fini_deep ();
+ local_remaps[i].create (&closures.local_closures[i]);
}
subr_remap_t global_remap;
@@ -567,21 +517,8 @@ template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typena
struct subr_subsetter_t
{
subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_)
- : acc (acc_), plan (plan_)
- {
- parsed_charstrings.init ();
- parsed_global_subrs.init ();
- parsed_local_subrs.init ();
- }
-
- ~subr_subsetter_t ()
- {
- closures.fini ();
- remaps.fini ();
- parsed_charstrings.fini_deep ();
- parsed_global_subrs.fini_deep ();
- parsed_local_subrs.fini_deep ();
- }
+ : acc (acc_), plan (plan_), closures(acc_.fdCount), remaps(acc_.fdCount)
+ {}
/* Subroutine subsetting with --no-desubroutinize runs in phases:
*
@@ -599,11 +536,8 @@ struct subr_subsetter_t
*/
bool subset (void)
{
- closures.init (acc.fdCount);
- remaps.init (acc.fdCount);
-
- parsed_charstrings.init (plan->num_output_glyphs ());
- parsed_global_subrs.init (acc.globalSubrs->count);
+ parsed_charstrings.resize (plan->num_output_glyphs ());
+ parsed_global_subrs.resize (acc.globalSubrs->count);
if (unlikely (remaps.in_error()
|| parsed_charstrings.in_error ()
@@ -615,7 +549,7 @@ struct subr_subsetter_t
for (unsigned int i = 0; i < acc.fdCount; i++)
{
- parsed_local_subrs[i].init (acc.privateDicts[i].localSubrs->count);
+ parsed_local_subrs[i].resize (acc.privateDicts[i].localSubrs->count);
if (unlikely (parsed_local_subrs[i].in_error ())) return false;
}
if (unlikely (!closures.valid))
@@ -638,7 +572,7 @@ struct subr_subsetter_t
subr_subset_param_t param;
param.init (&parsed_charstrings[i],
&parsed_global_subrs, &parsed_local_subrs[fd],
- closures.global_closure, closures.local_closures[fd],
+ &closures.global_closure, &closures.local_closures[fd],
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
if (unlikely (!interp.interpret (param)))
@@ -662,7 +596,7 @@ struct subr_subsetter_t
subr_subset_param_t param;
param.init (&parsed_charstrings[i],
&parsed_global_subrs, &parsed_local_subrs[fd],
- closures.global_closure, closures.local_closures[fd],
+ &closures.global_closure, &closures.local_closures[fd],
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
drop_hints_param_t drop;
@@ -687,7 +621,7 @@ struct subr_subsetter_t
subr_subset_param_t param;
param.init (&parsed_charstrings[i],
&parsed_global_subrs, &parsed_local_subrs[fd],
- closures.global_closure, closures.local_closures[fd],
+ &closures.global_closure, &closures.local_closures[fd],
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
collect_subr_refs_in_str (parsed_charstrings[i], param);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
index b4e24122c9..35fecd67bc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
@@ -362,43 +362,11 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs
struct cff_subset_plan {
cff_subset_plan ()
- : info (),
- orig_fdcount (0),
- subset_fdcount (1),
- subset_fdselect_format (0),
- drop_hints (false),
- desubroutinize(false)
{
- topdict_mod.init ();
- subset_fdselect_ranges.init ();
- fdmap.init ();
- subset_charstrings.init ();
- subset_globalsubrs.init ();
- subset_localsubrs.init ();
- fontdicts_mod.init ();
- subset_enc_code_ranges.init ();
- subset_enc_supp_codes.init ();
- subset_charset_ranges.init ();
- sidmap.init ();
for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
topDictModSIDs[i] = CFF_UNDEF_SID;
}
- ~cff_subset_plan ()
- {
- topdict_mod.fini ();
- subset_fdselect_ranges.fini ();
- fdmap.fini ();
- subset_charstrings.fini_deep ();
- subset_globalsubrs.fini_deep ();
- subset_localsubrs.fini_deep ();
- fontdicts_mod.fini ();
- subset_enc_code_ranges.fini ();
- subset_enc_supp_codes.fini ();
- subset_charset_ranges.fini ();
- sidmap.fini ();
- }
-
void plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
{
const Encoding *encoding = acc.encoding;
@@ -672,9 +640,9 @@ struct cff_subset_plan {
cff1_sub_table_info_t info;
unsigned int num_glyphs;
- unsigned int orig_fdcount;
- unsigned int subset_fdcount;
- unsigned int subset_fdselect_format;
+ unsigned int orig_fdcount = 0;
+ unsigned int subset_fdcount = 1;
+ unsigned int subset_fdselect_format = 0;
hb_vector_t<code_pair_t> subset_fdselect_ranges;
/* font dict index remap table from fullset FDArray to subset FDArray.
@@ -686,7 +654,7 @@ struct cff_subset_plan {
hb_vector_t<str_buff_vec_t> subset_localsubrs;
hb_vector_t<cff1_font_dict_values_mod_t> fontdicts_mod;
- bool drop_hints;
+ bool drop_hints = false;
bool gid_renum;
bool subset_encoding;
@@ -702,7 +670,7 @@ struct cff_subset_plan {
remap_sid_t sidmap;
unsigned int topDictModSIDs[name_dict_values_t::ValCount];
- bool desubroutinize;
+ bool desubroutinize = false;
};
static bool _serialize_cff1 (hb_serialize_context_t *c,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
index 896ae64016..92dd6b1d2c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
@@ -233,29 +233,6 @@ struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs
};
struct cff2_subset_plan {
- cff2_subset_plan ()
- : orig_fdcount (0),
- subset_fdcount(1),
- subset_fdselect_size (0),
- subset_fdselect_format (0),
- drop_hints (false),
- desubroutinize (false)
- {
- subset_fdselect_ranges.init ();
- fdmap.init ();
- subset_charstrings.init ();
- subset_globalsubrs.init ();
- subset_localsubrs.init ();
- }
-
- ~cff2_subset_plan ()
- {
- subset_fdselect_ranges.fini ();
- fdmap.fini ();
- subset_charstrings.fini_deep ();
- subset_globalsubrs.fini_deep ();
- subset_localsubrs.fini_deep ();
- }
bool create (const OT::cff2::accelerator_subset_t &acc,
hb_subset_plan_t *plan)
@@ -320,10 +297,10 @@ struct cff2_subset_plan {
cff2_sub_table_info_t info;
- unsigned int orig_fdcount;
- unsigned int subset_fdcount;
- unsigned int subset_fdselect_size;
- unsigned int subset_fdselect_format;
+ unsigned int orig_fdcount = 0;
+ unsigned int subset_fdcount = 1;
+ unsigned int subset_fdselect_size = 0;
+ unsigned int subset_fdselect_format = 0;
hb_vector_t<code_pair_t> subset_fdselect_ranges;
hb_inc_bimap_t fdmap;
@@ -332,8 +309,8 @@ struct cff2_subset_plan {
str_buff_vec_t subset_globalsubrs;
hb_vector_t<str_buff_vec_t> subset_localsubrs;
- bool drop_hints;
- bool desubroutinize;
+ bool drop_hints = false;
+ bool desubroutinize = false;
};
static bool _serialize_cff2 (hb_serialize_context_t *c,
@@ -473,12 +450,8 @@ _hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc,
bool
hb_subset_cff2 (hb_subset_context_t *c)
{
- OT::cff2::accelerator_subset_t acc;
- acc.init (c->plan->source);
- bool result = likely (acc.is_valid ()) && _hb_subset_cff2 (acc, c);
- acc.fini ();
-
- return result;
+ OT::cff2::accelerator_subset_t acc (c->plan->source);
+ return acc.is_valid () && _hb_subset_cff2 (acc, c);
}
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
index a3e28b0562..07c0e22676 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
@@ -42,17 +42,19 @@ struct hb_subset_input_t
{
hb_object_header_t header;
+ struct sets_t {
+ hb_set_t *glyphs;
+ hb_set_t *unicodes;
+ hb_set_t *no_subset_tables;
+ hb_set_t *drop_tables;
+ hb_set_t *name_ids;
+ hb_set_t *name_languages;
+ hb_set_t *layout_features;
+ };
+
union {
- struct {
- hb_set_t *glyphs;
- hb_set_t *unicodes;
- hb_set_t *no_subset_tables;
- hb_set_t *drop_tables;
- hb_set_t *name_ids;
- hb_set_t *name_languages;
- hb_set_t *layout_features;
- } sets;
- hb_set_t* set_ptrs[sizeof (sets) / sizeof (hb_set_t*)];
+ sets_t sets;
+ hb_set_t* set_ptrs[sizeof (sets_t) / sizeof (hb_set_t*)];
};
unsigned flags;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
index 677df35fad..74b7e3977c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
@@ -38,9 +38,12 @@
#include "hb-ot-color-colrv1-closure.hh"
#include "hb-ot-var-fvar-table.hh"
#include "hb-ot-stat-table.hh"
+#include "hb-ot-math-table.hh"
+using OT::Layout::GSUB::GSUB;
-typedef hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> script_langsys_map;
+
+typedef hb_hashmap_t<unsigned, hb_set_t *> script_langsys_map;
#ifndef HB_NO_SUBSET_CFF
static inline void
_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
@@ -99,11 +102,23 @@ static void _collect_layout_indices (hb_face_t *face,
if (!features.alloc (table.get_feature_count () + 1))
return;
+ hb_set_t visited_features;
+ bool retain_all_features = true;
for (unsigned i = 0; i < table.get_feature_count (); i++)
{
hb_tag_t tag = table.get_feature_tag (i);
- if (tag && layout_features_to_retain->has (tag))
- features.push (tag);
+ if (!tag) continue;
+ if (!layout_features_to_retain->has (tag))
+ {
+ retain_all_features = false;
+ continue;
+ }
+
+ if (visited_features.has (tag))
+ continue;
+
+ features.push (tag);
+ visited_features.add (tag);
}
if (!features)
@@ -112,7 +127,7 @@ static void _collect_layout_indices (hb_face_t *face,
// The collect function needs a null element to signal end of the array.
features.push (0);
- if (features.get_size () == table.get_feature_count () + 1)
+ if (retain_all_features)
{
// Looking for all features, trigger the faster collection method.
layout_collect_func (face,
@@ -215,12 +230,51 @@ _cmap_closure (hb_face_t *face,
const hb_set_t *unicodes,
hb_set_t *glyphset)
{
- OT::cmap::accelerator_t cmap;
- cmap.init (face);
+ OT::cmap::accelerator_t cmap (face);
cmap.table->closure_glyphs (unicodes, glyphset);
- cmap.fini ();
}
+static void _colr_closure (hb_face_t *face,
+ hb_map_t *layers_map,
+ hb_map_t *palettes_map,
+ hb_set_t *glyphs_colred)
+{
+ OT::COLR::accelerator_t colr (face);
+ if (!colr.is_valid ()) return;
+
+ unsigned iteration_count = 0;
+ hb_set_t palette_indices, layer_indices;
+ unsigned glyphs_num;
+ {
+ glyphs_num = glyphs_colred->get_population ();
+ // Collect all glyphs referenced by COLRv0
+ hb_set_t glyphset_colrv0;
+ for (hb_codepoint_t gid : glyphs_colred->iter ())
+ colr.closure_glyphs (gid, &glyphset_colrv0);
+
+ glyphs_colred->union_ (glyphset_colrv0);
+
+ //closure for COLRv1
+ colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
+ } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
+ glyphs_num != glyphs_colred->get_population ());
+
+ colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
+ _remap_indexes (&layer_indices, layers_map);
+ _remap_palette_indexes (&palette_indices, palettes_map);
+}
+
+static inline void
+_math_closure (hb_face_t *face,
+ hb_set_t *glyphset)
+{
+ hb_blob_ptr_t<OT::MATH> math = hb_sanitize_context_t ().reference_table<OT::MATH> (face);
+ if (math->has_data ())
+ math->closure_glyphs (glyphset);
+ math.destroy ();
+}
+
+
static inline void
_remove_invalid_gids (hb_set_t *glyphs,
unsigned int num_glyphs)
@@ -238,8 +292,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
const hb_set_t *glyphs,
hb_subset_plan_t *plan)
{
- OT::cmap::accelerator_t cmap;
- cmap.init (plan->source);
+ OT::cmap::accelerator_t cmap (plan->source);
constexpr static const int size_threshold = 4096;
@@ -287,8 +340,6 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
+ plan->codepoint_to_glyph->keys () | hb_sink (plan->unicodes);
+ plan->codepoint_to_glyph->values () | hb_sink (plan->_glyphset_gsub);
-
- cmap.fini ();
}
static void
@@ -297,16 +348,10 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
bool close_over_gpos,
bool close_over_gdef)
{
- OT::glyf::accelerator_t glyf;
-#ifndef HB_NO_SUBSET_CFF
- OT::cff1::accelerator_t cff;
-#endif
- OT::COLR::accelerator_t colr;
- glyf.init (plan->source);
+ OT::glyf::accelerator_t glyf (plan->source);
#ifndef HB_NO_SUBSET_CFF
- cff.init (plan->source);
+ OT::cff1::accelerator_t cff (plan->source);
#endif
- colr.init (plan->source);
plan->_glyphset_gsub->add (0); // Not-def
@@ -315,7 +360,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
#ifndef HB_NO_SUBSET_LAYOUT
if (close_over_gsub)
// closure all glyphs/lookups/features needed for GSUB substitutions.
- _closure_glyphs_lookups_features<OT::GSUB> (
+ _closure_glyphs_lookups_features<GSUB> (
plan->source,
plan->_glyphset_gsub,
plan->layout_features,
@@ -334,30 +379,18 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
#endif
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
- // Collect all glyphs referenced by COLRv0
- hb_set_t* cur_glyphset = plan->_glyphset_gsub;
- hb_set_t glyphset_colrv0;
- if (colr.is_valid ())
- {
- glyphset_colrv0.union_ (*cur_glyphset);
- for (hb_codepoint_t gid : cur_glyphset->iter ())
- colr.closure_glyphs (gid, &glyphset_colrv0);
- cur_glyphset = &glyphset_colrv0;
- }
-
- hb_set_t palette_indices;
- colr.closure_V0palette_indices (cur_glyphset, &palette_indices);
+ hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
+ _math_closure (plan->source, plan->_glyphset_mathed);
+ _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
- hb_set_t layer_indices;
- colr.closure_forV1 (cur_glyphset, &layer_indices, &palette_indices);
- _remap_indexes (&layer_indices, plan->colrv1_layers);
- _remap_palette_indexes (&palette_indices, plan->colr_palettes);
- colr.fini ();
- _remove_invalid_gids (cur_glyphset, plan->source->get_num_glyphs ());
+ hb_set_t cur_glyphset = *plan->_glyphset_mathed;
+ _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
+ _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
+ hb_set_set (plan->_glyphset_colred, &cur_glyphset);
// Populate a full set of glyphs to retain by adding all referenced
// composite glyphs.
- for (hb_codepoint_t gid : cur_glyphset->iter ())
+ for (hb_codepoint_t gid : cur_glyphset.iter ())
{
glyf.add_gid_and_children (gid, plan->_glyphset);
#ifndef HB_NO_SUBSET_CFF
@@ -377,11 +410,6 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
plan->layout_variation_indices,
plan->layout_variation_idx_map);
#endif
-
-#ifndef HB_NO_SUBSET_CFF
- cff.fini ();
-#endif
- glyf.fini ();
}
static void
@@ -432,7 +460,7 @@ _nameid_closure (hb_face_t *face,
}
/**
- * hb_subset_plan_create:
+ * hb_subset_plan_create_or_fail:
* @face: font face to create the plan for.
* @input: a #hb_subset_input_t input.
*
@@ -441,17 +469,18 @@ _nameid_closure (hb_face_t *face,
* which tables and glyphs should be retained.
*
* Return value: (transfer full): New subset plan. Destroy with
- * hb_subset_plan_destroy().
+ * hb_subset_plan_destroy(). If there is a failure creating the plan
+ * nullptr will be returned.
*
- * Since: 1.7.5
+ * Since: 4.0.0
**/
hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t *face,
- const hb_subset_input_t *input)
+hb_subset_plan_create_or_fail (hb_face_t *face,
+ const hb_subset_input_t *input)
{
hb_subset_plan_t *plan;
if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> ())))
- return const_cast<hb_subset_plan_t *> (&Null (hb_subset_plan_t));
+ return nullptr;
plan->successful = true;
plan->flags = input->flags;
@@ -468,6 +497,8 @@ hb_subset_plan_create (hb_face_t *face,
plan->_glyphset = hb_set_create ();
plan->_glyphset_gsub = hb_set_create ();
+ plan->_glyphset_mathed = hb_set_create ();
+ plan->_glyphset_colred = hb_set_create ();
plan->codepoint_to_glyph = hb_map_create ();
plan->glyph_map = hb_map_create ();
plan->reverse_glyph_map = hb_map_create ();
@@ -486,8 +517,9 @@ hb_subset_plan_create (hb_face_t *face,
plan->layout_variation_indices = hb_set_create ();
plan->layout_variation_idx_map = hb_map_create ();
- if (plan->in_error ()) {
- return plan;
+ if (unlikely (plan->in_error ())) {
+ hb_subset_plan_destroy (plan);
+ return nullptr;
}
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
@@ -504,6 +536,10 @@ hb_subset_plan_create (hb_face_t *face,
plan->reverse_glyph_map,
&plan->_num_output_glyphs);
+ if (unlikely (plan->in_error ())) {
+ hb_subset_plan_destroy (plan);
+ return nullptr;
+ }
return plan;
}
@@ -514,7 +550,7 @@ hb_subset_plan_create (hb_face_t *face,
* Decreases the reference count on @plan, and if it reaches zero, destroys
* @plan, freeing all memory.
*
- * Since: 1.7.5
+ * Since: 4.0.0
**/
void
hb_subset_plan_destroy (hb_subset_plan_t *plan)
@@ -535,6 +571,8 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_map_destroy (plan->reverse_glyph_map);
hb_set_destroy (plan->_glyphset);
hb_set_destroy (plan->_glyphset_gsub);
+ hb_set_destroy (plan->_glyphset_mathed);
+ hb_set_destroy (plan->_glyphset_colred);
hb_map_destroy (plan->gsub_lookups);
hb_map_destroy (plan->gpos_lookups);
hb_map_destroy (plan->gsub_features);
@@ -566,3 +604,116 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_free (plan);
}
+
+/**
+ * hb_subset_plan_old_to_new_glyph_mapping:
+ * @plan: a subsetting plan.
+ *
+ * Returns the mapping between glyphs in the original font to glyphs in the
+ * subset that will be produced by @plan
+ *
+ * Return value: (transfer none):
+ * A pointer to the #hb_map_t of the mapping.
+ *
+ * Since: 4.0.0
+ **/
+const hb_map_t*
+hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan)
+{
+ return plan->glyph_map;
+}
+
+/**
+ * hb_subset_plan_new_to_old_glyph_mapping:
+ * @plan: a subsetting plan.
+ *
+ * Returns the mapping between glyphs in the subset that will be produced by
+ * @plan and the glyph in the original font.
+ *
+ * Return value: (transfer none):
+ * A pointer to the #hb_map_t of the mapping.
+ *
+ * Since: 4.0.0
+ **/
+const hb_map_t*
+hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan)
+{
+ return plan->reverse_glyph_map;
+}
+
+/**
+ * hb_subset_plan_unicode_to_old_glyph_mapping:
+ * @plan: a subsetting plan.
+ *
+ * Returns the mapping between codepoints in the original font and the
+ * associated glyph id in the original font.
+ *
+ * Return value: (transfer none):
+ * A pointer to the #hb_map_t of the mapping.
+ *
+ * Since: 4.0.0
+ **/
+const hb_map_t*
+hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan)
+{
+ return plan->codepoint_to_glyph;
+}
+
+/**
+ * hb_subset_plan_reference: (skip)
+ * @plan: a #hb_subset_plan_t object.
+ *
+ * Increases the reference count on @plan.
+ *
+ * Return value: @plan.
+ *
+ * Since: 4.0.0
+ **/
+hb_subset_plan_t *
+hb_subset_plan_reference (hb_subset_plan_t *plan)
+{
+ return hb_object_reference (plan);
+}
+
+/**
+ * hb_subset_plan_set_user_data: (skip)
+ * @plan: a #hb_subset_plan_t object.
+ * @key: The user-data key to set
+ * @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 given subset plan object.
+ *
+ * Return value: %true if success, %false otherwise
+ *
+ * Since: 4.0.0
+ **/
+hb_bool_t
+hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
+ hb_user_data_key_t *key,
+ void *data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (plan, key, data, destroy, replace);
+}
+
+/**
+ * hb_subset_plan_get_user_data: (skip)
+ * @plan: a #hb_subset_plan_t object.
+ * @key: The user-data key to query
+ *
+ * Fetches the user data associated with the specified key,
+ * attached to the specified subset plan object.
+ *
+ * Return value: (transfer none): A pointer to the user data
+ *
+ * Since: 4.0.0
+ **/
+void *
+hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (plan, key);
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
index 92a4e27ccc..ab2c4c302c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
@@ -77,14 +77,16 @@ struct hb_subset_plan_t
unsigned int _num_output_glyphs;
hb_set_t *_glyphset;
hb_set_t *_glyphset_gsub;
+ hb_set_t *_glyphset_mathed;
+ hb_set_t *_glyphset_colred;
//active lookups we'd like to retain
hb_map_t *gsub_lookups;
hb_map_t *gpos_lookups;
//active langsys we'd like to retain
- hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *gsub_langsys;
- hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *gpos_langsys;
+ hb_hashmap_t<unsigned, hb_set_t *> *gsub_langsys;
+ hb_hashmap_t<unsigned, hb_set_t *> *gpos_langsys;
//active features after removing redundant langsys and prune_features
hb_map_t *gsub_features;
@@ -196,13 +198,4 @@ struct hb_subset_plan_t
}
};
-typedef struct hb_subset_plan_t hb_subset_plan_t;
-
-HB_INTERNAL hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t *face,
- const hb_subset_input_t *input);
-
-HB_INTERNAL void
-hb_subset_plan_destroy (hb_subset_plan_t *plan);
-
#endif /* HB_SUBSET_PLAN_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc
new file mode 100644
index 0000000000..2447d296b8
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+#include "hb-repacker.hh"
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_subset_repack_or_fail:
+ * @hb_objects: raw array of struct hb_object_t, which provides
+ * object graph info
+ * @num_hb_objs: number of hb_object_t in the hb_objects array.
+ *
+ * Given the input object graph info, repack a table to eliminate
+ * offset overflows. A nullptr is returned if the repacking attempt fails.
+ *
+ * Since: EXPERIMENTAL
+ **/
+hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_objs)
+{
+ hb_vector_t<const hb_object_t *> packed;
+ packed.alloc (num_hb_objs + 1);
+ packed.push (nullptr);
+ for (unsigned i = 0 ; i < num_hb_objs ; i++)
+ packed.push (&(hb_objects[i]));
+ return hb_resolve_overflows (packed, HB_OT_TAG_GSUB);
+}
+#endif
+
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.h b/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.h
new file mode 100644
index 0000000000..f9a2383698
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#ifndef HB_SUBSET_REPACKER_H
+#define HB_SUBSET_REPACKER_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * struct hb_link_t
+ * width: offsetSize in bytes
+ * position: position of the offset field in bytes
+ * from beginning of subtable
+ * objidx: index of subtable
+ **/
+struct hb_link_t
+{
+ unsigned width;
+ unsigned position;
+ unsigned objidx;
+};
+
+typedef struct hb_link_t hb_link_t;
+
+/**
+ * struct hb_object_t
+ * head: start of object data
+ * tail: end of object data
+ * num_real_links: num of offset field in the object
+ * real_links: pointer to array of offset info
+ * num_virtual_links: num of objects that must be packed
+ * after current object in the final serialized order
+ * virtual_links: array of virtual link info
+ **/
+struct hb_object_t
+{
+ char *head;
+ char *tail;
+ unsigned num_real_links;
+ hb_link_t *real_links;
+ unsigned num_virtual_links;
+ hb_link_t *virtual_links;
+};
+
+typedef struct hb_object_t hb_object_t;
+
+HB_EXTERN hb_blob_t*
+hb_subset_repack_or_fail (hb_object_t* hb_objects,
+ unsigned num_hb_objs);
+
+#endif
+
+HB_END_DECLS
+
+#endif /* HB_SUBSET_REPACKER_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
index 34f92e0d81..4588268b76 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
@@ -52,8 +52,11 @@
#include "hb-ot-layout-gpos-table.hh"
#include "hb-ot-var-gvar-table.hh"
#include "hb-ot-var-hvar-table.hh"
+#include "hb-ot-math-table.hh"
#include "hb-repacker.hh"
+using OT::Layout::GSUB::GSUB;
+
/**
* SECTION:hb-subset
* @title: hb-subset
@@ -103,20 +106,16 @@ _repack (hb_tag_t tag, const hb_serialize_context_t& c)
if (!c.offset_overflow ())
return c.copy_blob ();
- hb_vector_t<char> buf;
- int buf_size = c.end - c.start;
- if (unlikely (!buf.alloc (buf_size)))
- return nullptr;
+ hb_blob_t* result = hb_resolve_overflows (c.object_graph (), tag);
- hb_serialize_context_t repacked ((void *) buf, buf_size);
- hb_resolve_overflows (c.object_graph (), &repacked);
-
- if (unlikely (repacked.in_error ()))
- // TODO(garretrieger): refactor so we can share the resize/retry logic with the subset
- // portion.
+ if (unlikely (!result))
+ {
+ DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c offset overflow resolution failed.",
+ HB_UNTAG (tag));
return nullptr;
+ }
- return repacked.copy_blob ();
+ return result;
}
template<typename TableType>
@@ -305,6 +304,7 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan);
case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan);
case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
+ case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan);
#ifndef HB_NO_SUBSET_CFF
case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan);
@@ -314,7 +314,7 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
#ifndef HB_NO_SUBSET_LAYOUT
case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan);
- case HB_OT_TAG_GSUB: return _subset<const OT::GSUB> (plan);
+ case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan);
case HB_OT_TAG_GPOS: return _subset<const OT::GPOS> (plan);
case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan);
case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan);
@@ -345,9 +345,33 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
{
if (unlikely (!input || !source)) return hb_face_get_empty ();
- hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
- if (unlikely (plan->in_error ())) {
- hb_subset_plan_destroy (plan);
+ hb_subset_plan_t *plan = hb_subset_plan_create_or_fail (source, input);
+ if (unlikely (!plan)) {
+ return nullptr;
+ }
+
+ hb_face_t * result = hb_subset_plan_execute_or_fail (plan);
+ hb_subset_plan_destroy (plan);
+ return result;
+}
+
+
+/**
+ * hb_subset_plan_execute_or_fail:
+ * @plan: a subsetting plan.
+ *
+ * Executes the provided subsetting @plan.
+ *
+ * Return value:
+ * on success returns a reference to generated font subset. If the subsetting operation fails
+ * returns nullptr.
+ *
+ * Since: 4.0.0
+ **/
+hb_face_t *
+hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
+{
+ if (unlikely (!plan || plan->in_error ())) {
return nullptr;
}
@@ -355,7 +379,7 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
bool success = true;
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
- while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
+ while ((hb_face_get_table_tags (plan->source, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
{
@@ -369,8 +393,5 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
}
end:
- hb_face_t *result = success ? hb_face_reference (plan->dest) : nullptr;
-
- hb_subset_plan_destroy (plan);
- return result;
+ return success ? hb_face_reference (plan->dest) : nullptr;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.h b/src/3rdparty/harfbuzz-ng/src/hb-subset.h
index 1c65a4da1c..a2799d91e8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.h
@@ -40,6 +40,15 @@ HB_BEGIN_DECLS
typedef struct hb_subset_input_t hb_subset_input_t;
/**
+ * hb_subset_plan_t:
+ *
+ * Contains information about how the subset operation will be executed.
+ * Such as mappings from the old glyph ids to the new ones in the subset.
+ */
+
+typedef struct hb_subset_plan_t hb_subset_plan_t;
+
+/**
* hb_subset_flags_t:
* @HB_SUBSET_FLAGS_DEFAULT: all flags at their default value of false.
* @HB_SUBSET_FLAGS_NO_HINTING: If set hinting instructions will be dropped in
@@ -124,7 +133,7 @@ hb_subset_input_set_user_data (hb_subset_input_t *input,
HB_EXTERN void *
hb_subset_input_get_user_data (const hb_subset_input_t *input,
- hb_user_data_key_t *key);
+ hb_user_data_key_t *key);
HB_EXTERN hb_set_t *
hb_subset_input_unicode_set (hb_subset_input_t *input);
@@ -145,6 +154,41 @@ hb_subset_input_set_flags (hb_subset_input_t *input,
HB_EXTERN hb_face_t *
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
+HB_EXTERN hb_face_t *
+hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan);
+
+HB_EXTERN hb_subset_plan_t *
+hb_subset_plan_create_or_fail (hb_face_t *face,
+ const hb_subset_input_t *input);
+
+HB_EXTERN void
+hb_subset_plan_destroy (hb_subset_plan_t *plan);
+
+HB_EXTERN const hb_map_t*
+hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan);
+
+HB_EXTERN const hb_map_t*
+hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan);
+
+HB_EXTERN const hb_map_t*
+hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan);
+
+
+HB_EXTERN hb_subset_plan_t *
+hb_subset_plan_reference (hb_subset_plan_t *plan);
+
+HB_EXTERN hb_bool_t
+hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
+ hb_user_data_key_t *key,
+ void *data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+HB_EXTERN void *
+hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
+ hb_user_data_key_t *key);
+
+
HB_END_DECLS
#endif /* HB_SUBSET_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset.hh
index c9b01c67f3..98c5f06fbf 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.hh
@@ -45,14 +45,14 @@ struct hb_subset_context_t :
private:
template <typename T, typename ...Ts> auto
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
- ( obj.subset (this, hb_forward<Ts> (ds)...) )
+ ( obj.subset (this, std::forward<Ts> (ds)...) )
template <typename T, typename ...Ts> auto
_dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
- ( obj.dispatch (this, hb_forward<Ts> (ds)...) )
+ ( obj.dispatch (this, std::forward<Ts> (ds)...) )
public:
template <typename T, typename ...Ts> auto
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
- ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
+ ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
hb_blob_t *source_blob;
hb_subset_plan_t *plan;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode.hh b/src/3rdparty/harfbuzz-ng/src/hb-unicode.hh
index 0a79944107..4c28bb0cdf 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-unicode.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode.hh
@@ -121,7 +121,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
static hb_bool_t
is_variation_selector (hb_codepoint_t unicode)
{
- /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
+ /* U+180B..180D, U+180F MONGOLIAN FREE VARIATION SELECTORs are handled in the
* Arabic shaper. No need to match them here. */
return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
@@ -136,7 +136,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
* As such, we make exceptions for those four.
* Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
*
- * Unicode 7.0:
+ * Unicode 14.0:
* $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
* 00AD # Cf SOFT HYPHEN
* 034F # Mn COMBINING GRAPHEME JOINER
@@ -145,6 +145,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
* 17B4..17B5 # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
* 180B..180D # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
* 180E # Cf MONGOLIAN VOWEL SEPARATOR
+ * 180F # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
* 200B..200F # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
* 202A..202E # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
* 2060..2064 # Cf [5] WORD JOINER..INVISIBLE PLUS
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc b/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc
index 3dc4c0937d..50f71ce9ce 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc
@@ -878,7 +878,8 @@ retry:
if (backward)
hb_buffer_reverse (buffer);
- buffer->unsafe_to_break_all ();
+ buffer->clear_glyph_flags ();
+ buffer->unsafe_to_break ();
/* Wow, done! */
return true;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
index 110d457caf..6c7d32e49d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
@@ -32,16 +32,32 @@
#include "hb-null.hh"
-template <typename Type>
-struct hb_vector_t
+template <typename Type,
+ bool sorted=false>
+struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty_t>::type
{
typedef Type item_t;
static constexpr unsigned item_size = hb_static_size (Type);
+ using array_t = typename std::conditional<sorted, hb_sorted_array_t<Type>, hb_array_t<Type>>::type;
+ using c_array_t = typename std::conditional<sorted, hb_sorted_array_t<const Type>, hb_array_t<const Type>>::type;
- hb_vector_t () { init (); }
- hb_vector_t (const hb_vector_t &o)
+ hb_vector_t () = default;
+ hb_vector_t (std::initializer_list<Type> lst) : hb_vector_t ()
+ {
+ alloc (lst.size ());
+ for (auto&& item : lst)
+ push (item);
+ }
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
+ hb_vector_t (const Iterable &o) : hb_vector_t ()
+ {
+ if (hb_iter (o).is_random_access_iterator)
+ alloc (hb_len (hb_iter (o)));
+ hb_copy (o, *this);
+ }
+ hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
{
- init ();
alloc (o.length);
hb_copy (o, *this);
}
@@ -55,11 +71,11 @@ struct hb_vector_t
~hb_vector_t () { fini (); }
private:
- int allocated; /* == -1 means allocation failed. */
+ int allocated = 0; /* == -1 means allocation failed. */
public:
- unsigned int length;
+ unsigned int length = 0;
public:
- Type *arrayZ;
+ Type *arrayZ = nullptr;
void init ()
{
@@ -69,16 +85,10 @@ struct hb_vector_t
void fini ()
{
+ shrink_vector (0);
hb_free (arrayZ);
init ();
}
- void fini_deep ()
- {
- unsigned int count = length;
- for (unsigned int i = 0; i < count; i++)
- arrayZ[i].fini ();
- fini ();
- }
void reset ()
{
@@ -87,6 +97,13 @@ struct hb_vector_t
resize (0);
}
+ friend void swap (hb_vector_t& a, hb_vector_t& b)
+ {
+ hb_swap (a.allocated, b.allocated);
+ hb_swap (a.length, b.length);
+ hb_swap (a.arrayZ, b.arrayZ);
+ }
+
hb_vector_t& operator = (const hb_vector_t &o)
{
reset ();
@@ -96,11 +113,7 @@ struct hb_vector_t
}
hb_vector_t& operator = (hb_vector_t &&o)
{
- fini ();
- allocated = o.allocated;
- length = o.length;
- arrayZ = o.arrayZ;
- o.init ();
+ hb_swap (*this, o);
return *this;
}
@@ -134,26 +147,26 @@ struct hb_vector_t
/* Sink interface. */
template <typename T>
- hb_vector_t& operator << (T&& v) { push (hb_forward<T> (v)); return *this; }
+ hb_vector_t& operator << (T&& v) { push (std::forward<T> (v)); return *this; }
- hb_array_t< Type> as_array () { return hb_array (arrayZ, length); }
- hb_array_t<const Type> as_array () const { return hb_array (arrayZ, length); }
+ array_t as_array () { return hb_array (arrayZ, length); }
+ c_array_t as_array () const { return hb_array (arrayZ, length); }
/* Iterator. */
- typedef hb_array_t<const Type> iter_t;
- typedef hb_array_t< Type> writer_t;
+ typedef c_array_t iter_t;
+ typedef array_t writer_t;
iter_t iter () const { return as_array (); }
writer_t writer () { return as_array (); }
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
- hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+ c_array_t sub_array (unsigned int start_offset, unsigned int count) const
{ return as_array ().sub_array (start_offset, count); }
- hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+ c_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
{ return as_array ().sub_array (start_offset, count); }
- hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+ array_t sub_array (unsigned int start_offset, unsigned int count)
{ return as_array ().sub_array (start_offset, count); }
- hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+ array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
{ return as_array ().sub_array (start_offset, count); }
hb_sorted_array_t<Type> as_sorted_array ()
@@ -176,18 +189,105 @@ struct hb_vector_t
template <typename T>
Type *push (T&& v)
{
+ /* TODO Emplace? */
Type *p = push ();
if (p == &Crap (Type))
// If push failed to allocate then don't copy v, since this may cause
// the created copy to leak memory since we won't have stored a
// reference to it.
return p;
- *p = hb_forward<T> (v);
+ *p = std::forward<T> (v);
return p;
}
bool in_error () const { return allocated < 0; }
+ template <typename T = Type,
+ hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
+ Type *
+ realloc_vector (unsigned new_allocated)
+ {
+ return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
+ }
+ template <typename T = Type,
+ hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
+ Type *
+ realloc_vector (unsigned new_allocated)
+ {
+ Type *new_array = (Type *) hb_malloc (new_allocated * sizeof (Type));
+ if (likely (new_array))
+ {
+ for (unsigned i = 0; i < length; i++)
+ new (std::addressof (new_array[i])) Type ();
+ for (unsigned i = 0; i < (unsigned) length; i++)
+ new_array[i] = std::move (arrayZ[i]);
+ unsigned old_length = length;
+ shrink_vector (0);
+ length = old_length;
+ hb_free (arrayZ);
+ }
+ return new_array;
+ }
+
+ template <typename T = Type,
+ hb_enable_if (std::is_trivially_constructible<T>::value ||
+ !std::is_default_constructible<T>::value)>
+ void
+ grow_vector (unsigned size)
+ {
+ memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
+ length = size;
+ }
+ template <typename T = Type,
+ hb_enable_if (!std::is_trivially_constructible<T>::value &&
+ std::is_default_constructible<T>::value)>
+ void
+ grow_vector (unsigned size)
+ {
+ while (length < size)
+ {
+ length++;
+ new (std::addressof (arrayZ[length - 1])) Type ();
+ }
+ }
+
+ template <typename T = Type,
+ hb_enable_if (std::is_trivially_destructible<T>::value)>
+ void
+ shrink_vector (unsigned size)
+ {
+ length = size;
+ }
+ template <typename T = Type,
+ hb_enable_if (!std::is_trivially_destructible<T>::value)>
+ void
+ shrink_vector (unsigned size)
+ {
+ while ((unsigned) length > size)
+ {
+ arrayZ[(unsigned) length - 1].~Type ();
+ length--;
+ }
+ }
+
+ template <typename T = Type,
+ hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
+ void
+ shift_down_vector (unsigned i)
+ {
+ memmove (static_cast<void *> (&arrayZ[i - 1]),
+ static_cast<void *> (&arrayZ[i]),
+ (length - i) * sizeof (Type));
+ }
+ template <typename T = Type,
+ hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
+ void
+ shift_down_vector (unsigned i)
+ {
+ for (; i < length; i++)
+ arrayZ[i - 1] = std::move (arrayZ[i]);
+ }
+
/* Allocate for size but don't adjust length. */
bool alloc (unsigned int size)
{
@@ -209,7 +309,7 @@ struct hb_vector_t
(new_allocated < (unsigned) allocated) ||
hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
if (likely (!overflows))
- new_array = (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
+ new_array = realloc_vector (new_allocated);
if (unlikely (!new_array))
{
@@ -230,7 +330,9 @@ struct hb_vector_t
return false;
if (size > length)
- memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
+ grow_vector (size);
+ else if (size < length)
+ shrink_vector (size);
length = size;
return true;
@@ -239,48 +341,38 @@ struct hb_vector_t
Type pop ()
{
if (!length) return Null (Type);
- return hb_move (arrayZ[--length]); /* Does this move actually work? */
+ Type v = std::move (arrayZ[length - 1]);
+ arrayZ[length - 1].~Type ();
+ length--;
+ return v;
}
void remove (unsigned int i)
{
if (unlikely (i >= length))
return;
- memmove (static_cast<void *> (&arrayZ[i]),
- static_cast<void *> (&arrayZ[i + 1]),
- (length - i - 1) * sizeof (Type));
+ arrayZ[i].~Type ();
+ shift_down_vector (i + 1);
length--;
}
void shrink (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
- if (size < length)
- length = size;
- }
+ if (size >= length)
+ return;
- template <typename T>
- Type *find (T v)
- {
- for (unsigned int i = 0; i < length; i++)
- if (arrayZ[i] == v)
- return &arrayZ[i];
- return nullptr;
- }
- template <typename T>
- const Type *find (T v) const
- {
- for (unsigned int i = 0; i < length; i++)
- if (arrayZ[i] == v)
- return &arrayZ[i];
- return nullptr;
+ shrink_vector (size);
}
+
+ /* Sorting API. */
void qsort (int (*cmp)(const void*, const void*))
{ as_array ().qsort (cmp); }
void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
{ as_array ().qsort (start, end); }
+ /* Unsorted search API. */
template <typename T>
Type *lsearch (const T &x, Type *not_found = nullptr)
{ return as_array ().lsearch (x, not_found); }
@@ -290,34 +382,25 @@ struct hb_vector_t
template <typename T>
bool lfind (const T &x, unsigned *pos = nullptr) const
{ return as_array ().lfind (x, pos); }
-};
-
-template <typename Type>
-struct hb_sorted_vector_t : hb_vector_t<Type>
-{
- hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->length); }
- hb_sorted_array_t<const Type> as_array () const { return hb_sorted_array (this->arrayZ, this->length); }
-
- /* Iterator. */
- typedef hb_sorted_array_t<const Type> const_iter_t;
- typedef hb_sorted_array_t< Type> iter_t;
- const_iter_t iter () const { return as_array (); }
- const_iter_t citer () const { return as_array (); }
- iter_t iter () { return as_array (); }
- operator iter_t () { return iter (); }
- operator const_iter_t () const { return iter (); }
- template <typename T>
+ /* Sorted search API. */
+ template <typename T,
+ bool Sorted=sorted, hb_enable_if (Sorted)>
Type *bsearch (const T &x, Type *not_found = nullptr)
{ return as_array ().bsearch (x, not_found); }
- template <typename T>
+ template <typename T,
+ bool Sorted=sorted, hb_enable_if (Sorted)>
const Type *bsearch (const T &x, const Type *not_found = nullptr) const
{ return as_array ().bsearch (x, not_found); }
- template <typename T>
+ template <typename T,
+ bool Sorted=sorted, hb_enable_if (Sorted)>
bool bfind (const T &x, unsigned int *i = nullptr,
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
unsigned int to_store = (unsigned int) -1) const
{ return as_array ().bfind (x, i, not_found, to_store); }
};
+template <typename Type>
+using hb_sorted_vector_t = hb_vector_t<Type, true>;
+
#endif /* HB_VECTOR_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-version.h b/src/3rdparty/harfbuzz-ng/src/hb-version.h
index 70325f88eb..94c73e15bf 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-version.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-version.h
@@ -41,26 +41,26 @@ HB_BEGIN_DECLS
*
* The major component of the library version available at compile-time.
*/
-#define HB_VERSION_MAJOR 3
+#define HB_VERSION_MAJOR 4
/**
* HB_VERSION_MINOR:
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 0
+#define HB_VERSION_MINOR 2
/**
* HB_VERSION_MICRO:
*
* The micro component of the library version available at compile-time.
*/
-#define HB_VERSION_MICRO 0
+#define HB_VERSION_MICRO 1
/**
* HB_VERSION_STRING:
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "3.0.0"
+#define HB_VERSION_STRING "4.2.1"
/**
* HB_VERSION_ATLEAST:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb.hh b/src/3rdparty/harfbuzz-ng/src/hb.hh
index 829b5a1ab7..b9f5f71415 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb.hh
@@ -62,6 +62,7 @@
/* Error. Should never happen. */
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
+#pragma GCC diagnostic error "-Wbitwise-instead-of-logical"
#pragma GCC diagnostic error "-Wcast-align"
#pragma GCC diagnostic error "-Wcast-function-type"
#pragma GCC diagnostic error "-Wdelete-non-virtual-dtor"
@@ -446,6 +447,7 @@ static int HB_UNUSED _hb_errno = 0;
#ifndef HB_USE_ATEXIT
# define HB_USE_ATEXIT 0
#endif
+#ifndef hb_atexit
#if !HB_USE_ATEXIT
# define hb_atexit(_) HB_STMT_START { if (0) (_) (); } HB_STMT_END
#else /* HB_USE_ATEXIT */
@@ -456,6 +458,7 @@ static int HB_UNUSED _hb_errno = 0;
# define hb_atexit(f) static hb_atexit_t<f> _hb_atexit_##__LINE__;
# endif
#endif
+#endif
/* Lets assert int types. Saves trouble down the road. */
static_assert ((sizeof (hb_codepoint_t) == 4), "");
diff --git a/src/3rdparty/harfbuzz-ng/src/main.cc b/src/3rdparty/harfbuzz-ng/src/main.cc
index 1ab013cd3a..7a7614f7b6 100644
--- a/src/3rdparty/harfbuzz-ng/src/main.cc
+++ b/src/3rdparty/harfbuzz-ng/src/main.cc
@@ -42,7 +42,7 @@
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
#endif
-#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API)
+#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW)
static void
svg_dump (hb_face_t *face, unsigned face_index)
{
@@ -129,48 +129,60 @@ png_dump (hb_face_t *face, unsigned face_index)
hb_font_destroy (font);
}
-struct user_data_t
+struct draw_data_t
{
FILE *f;
hb_position_t ascender;
};
static void
-move_to (hb_position_t to_x, hb_position_t to_y, user_data_t &user_data)
+move_to (hb_draw_funcs_t *, draw_data_t *draw_data,
+ hb_draw_state_t *,
+ float to_x, float to_y,
+ void *)
{
- fprintf (user_data.f, "M%d,%d", to_x, user_data.ascender - to_y);
+ fprintf (draw_data->f, "M%g,%g", to_x, draw_data->ascender - to_y);
}
static void
-line_to (hb_position_t to_x, hb_position_t to_y, user_data_t &user_data)
+line_to (hb_draw_funcs_t *, draw_data_t *draw_data,
+ hb_draw_state_t *,
+ float to_x, float to_y,
+ void *)
{
- fprintf (user_data.f, "L%d,%d", to_x, user_data.ascender - to_y);
+ fprintf (draw_data->f, "L%g,%g", to_x, draw_data->ascender - to_y);
}
static void
-quadratic_to (hb_position_t control_x, hb_position_t control_y,
- hb_position_t to_x, hb_position_t to_y,
- user_data_t &user_data)
+quadratic_to (hb_draw_funcs_t *, draw_data_t *draw_data,
+ hb_draw_state_t *,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *)
{
- fprintf (user_data.f, "Q%d,%d %d,%d", control_x, user_data.ascender - control_y,
- to_x, user_data.ascender - to_y);
+ fprintf (draw_data->f, "Q%g,%g %g,%g", control_x, draw_data->ascender - control_y,
+ to_x, draw_data->ascender - to_y);
}
static void
-cubic_to (hb_position_t control1_x, hb_position_t control1_y,
- hb_position_t control2_x, hb_position_t control2_y,
- hb_position_t to_x, hb_position_t to_y,
- user_data_t &user_data)
+cubic_to (hb_draw_funcs_t *, draw_data_t *draw_data,
+ hb_draw_state_t *,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y,
+ void *)
{
- fprintf (user_data.f, "C%d,%d %d,%d %d,%d", control1_x, user_data.ascender - control1_y,
- control2_x, user_data.ascender - control2_y,
- to_x, user_data.ascender - to_y);
+ fprintf (draw_data->f, "C%g,%g %g,%g %g,%g", control1_x, draw_data->ascender - control1_y,
+ control2_x, draw_data->ascender - control2_y,
+ to_x, draw_data->ascender - to_y);
}
static void
-close_path (user_data_t &user_data)
+close_path (hb_draw_funcs_t *, draw_data_t *draw_data,
+ hb_draw_state_t *,
+ void *)
{
- fprintf (user_data.f, "Z");
+ fprintf (draw_data->f, "Z");
}
static void
@@ -218,9 +230,9 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index
" viewBox=\"%d %d %d %d\">\n",
extents.x_bearing, 0,
extents.x_bearing + extents.width, -extents.height);
- user_data_t user_data;
- user_data.ascender = extents.y_bearing;
- user_data.f = f;
+ draw_data_t draw_data;
+ draw_data.ascender = extents.y_bearing;
+ draw_data.f = f;
for (unsigned layer = 0; layer < num_layers; ++layer)
{
@@ -232,8 +244,7 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index
if (hb_color_get_alpha (color) != 255)
fprintf (f, "fill-opacity=\"%.3f\"", (double) hb_color_get_alpha (color) / 255.);
fprintf (f, "d=\"");
- if (!hb_font_draw_glyph (font, layers[layer].glyph, funcs, &user_data))
- printf ("Failed to decompose layer %d while %d\n", layers[layer].glyph, gid);
+ hb_font_get_glyph_shape (font, layers[layer].glyph, funcs, &draw_data);
fprintf (f, "\"/>\n");
}
@@ -269,11 +280,10 @@ dump_glyphs (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index)
" viewBox=\"%d %d %d %d\"><path d=\"",
extents.x_bearing, 0,
extents.x_bearing + extents.width, font_extents.ascender - font_extents.descender);
- user_data_t user_data;
- user_data.ascender = font_extents.ascender;
- user_data.f = f;
- if (!hb_font_draw_glyph (font, gid, funcs, &user_data))
- printf ("Failed to decompose gid: %d\n", gid);
+ draw_data_t draw_data;
+ draw_data.ascender = font_extents.ascender;
+ draw_data.f = f;
+ hb_font_get_glyph_shape (font, gid, funcs, &draw_data);
fprintf (f, "\"/></svg>");
fclose (f);
}
@@ -300,11 +310,11 @@ dump_glyphs (hb_blob_t *blob, const char *font_name)
fclose (font_name_file);
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
- hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to);
- hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to);
- hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to);
- hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to);
- hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path);
+ hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, nullptr, nullptr);
+ hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, nullptr, nullptr);
+ hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, nullptr, nullptr);
+ hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, nullptr, nullptr);
+ hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, nullptr, nullptr);
unsigned num_faces = hb_face_count (blob);
for (unsigned face_index = 0; face_index < num_faces; ++face_index)
@@ -512,7 +522,7 @@ main (int argc, char **argv)
#ifndef MAIN_CC_NO_PRIVATE_API
print_layout_info_using_private_api (blob);
#endif
-#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API)
+#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW)
dump_glyphs (blob, argv[1]);
#endif
hb_blob_destroy (blob);
diff --git a/src/3rdparty/harfbuzz-ng/src/test-iter.cc b/src/3rdparty/harfbuzz-ng/src/test-iter.cc
index fd201c85e8..dc85b72147 100644
--- a/src/3rdparty/harfbuzz-ng/src/test-iter.cc
+++ b/src/3rdparty/harfbuzz-ng/src/test-iter.cc
@@ -114,6 +114,78 @@ test_iterable (const Iterable &lst = Null (Iterable))
test_iterator (lst.iter ());
}
+template <typename It>
+static void check_sequential (It it)
+{
+ int i = 1;
+ for (int v : +it) {
+ assert (v == i++);
+ }
+}
+
+static void test_concat ()
+{
+ hb_vector_t<int> a = {1, 2, 3};
+ hb_vector_t<int> b = {4, 5};
+
+ hb_vector_t<int> c = {};
+ hb_vector_t<int> d = {1, 2, 3, 4, 5};
+
+ auto it1 = hb_concat (a, b);
+ assert (it1.len () == 5);
+ assert (it1.is_random_access_iterator);
+ auto it2 = hb_concat (c, d);
+ assert (it2.len () == 5);
+ auto it3 = hb_concat (d, c);
+ assert (it3.len () == 5);
+ for (int i = 0; i < 5; i++) {
+ assert(it1[i] == i + 1);
+ assert(it2[i] == i + 1);
+ assert(it3[i] == i + 1);
+ }
+
+ check_sequential (it1);
+ check_sequential (it2);
+ check_sequential (it3);
+
+ auto it4 = +it1;
+ it4 += 0;
+ assert (*it4 == 1);
+
+ it4 += 2;
+ assert (*it4 == 3);
+ assert (it4);
+ assert (it4.len () == 3);
+
+ it4 += 2;
+ assert (*it4 == 5);
+ assert (it4);
+ assert (it4.len () == 1);
+
+ it4++;
+ assert (!it4);
+ assert (it4.len () == 0);
+
+ auto it5 = +it1;
+ it5 += 3;
+ assert (*it5 == 4);
+
+ hb_set_t s_a = {1, 2, 3};
+ hb_set_t s_b = {4, 5};
+ auto it6 = hb_concat (s_a, s_b);
+ assert (!it6.is_random_access_iterator);
+ check_sequential (it6);
+ assert (it6.len () == 5);
+
+ it6 += 0;
+ assert (*it6 == 1);
+
+ it6 += 3;
+ assert (*it6 == 4);
+ assert (it6);
+ assert (it6.len () == 2);
+}
+
int
main (int argc, char **argv)
{
@@ -282,5 +354,7 @@ main (int argc, char **argv)
assert (hb_range (-2, -8, -3).len () == 2);
assert (hb_range (-2, -7, -3).len () == 2);
+ test_concat ();
+
return 0;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-machinery.cc b/src/3rdparty/harfbuzz-ng/src/test-machinery.cc
new file mode 100644
index 0000000000..7fc9c24b59
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/test-machinery.cc
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#include "hb.hh"
+#include "hb-machinery.hh"
+
+struct hb_intp_lazy_loader_t : hb_lazy_loader_t<int, hb_intp_lazy_loader_t>
+{
+ static int* create () { return nullptr; }
+ static void destroy (int* l) {}
+ static int* get_null () { return nullptr; }
+};
+
+struct hb_void_lazy_loader_t : hb_lazy_loader_t<void, hb_void_lazy_loader_t>
+{
+ static void* create () { return nullptr; }
+ static void destroy (void* l) {}
+ static void* get_null () { return nullptr; }
+};
+
+int
+main (int argc, char **argv)
+{
+ return 0;
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-map.cc b/src/3rdparty/harfbuzz-ng/src/test-map.cc
new file mode 100644
index 0000000000..fd2b2f0e64
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/test-map.cc
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2021 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.
+ *
+ */
+
+#include "hb.hh"
+#include "hb-map.hh"
+#include <string>
+
+static const std::string invalid{"invalid"};
+
+int
+main (int argc, char **argv)
+{
+
+ /* Test copy constructor. */
+ {
+ hb_map_t v1;
+ v1.set (1, 2);
+ hb_map_t v2 {v1};
+ assert (v1.get_population () == 1);
+ assert (v2.get_population () == 1);
+ assert (v1[1] == 2);
+ assert (v2[1] == 2);
+ }
+
+ /* Test copy assignment. */
+ {
+ hb_map_t v1;
+ v1.set (1, 2);
+ hb_map_t v2 = v1;
+ assert (v1.get_population () == 1);
+ assert (v2.get_population () == 1);
+ assert (v1[1] == 2);
+ assert (v2[1] == 2);
+ }
+
+ /* Test move constructor. */
+ {
+ hb_map_t v {hb_map_t {}};
+ }
+
+ /* Test move assignment. */
+ {
+ hb_map_t v;
+ v = hb_map_t {};
+ }
+
+ /* Test initializing from iterable. */
+ {
+ hb_map_t s;
+
+ s.set (1, 2);
+ s.set (3, 4);
+
+ hb_map_t v (s);
+
+ assert (v.get_population () == 2);
+ }
+
+ /* Test call fini() twice. */
+ {
+ hb_map_t s;
+ for (int i = 0; i < 16; i++)
+ s.set(i, i+1);
+ s.fini();
+ }
+
+ /* Test initializing from iterator. */
+ {
+ hb_map_t s;
+
+ s.set (1, 2);
+ s.set (3, 4);
+
+ hb_map_t v (hb_iter (s));
+
+ assert (v.get_population () == 2);
+ }
+
+ /* Test initializing from initializer list and swapping. */
+ {
+ using pair_t = hb_pair_t<hb_codepoint_t, hb_codepoint_t>;
+ hb_map_t v1 {pair_t{1,2}, pair_t{4,5}};
+ hb_map_t v2 {pair_t{3,4}};
+ hb_swap (v1, v2);
+ assert (v1.get_population () == 1);
+ assert (v2.get_population () == 2);
+ }
+
+ /* Test class key / value types. */
+ {
+ hb_hashmap_t<hb_bytes_t, int, std::nullptr_t, int, nullptr, 0> m1;
+ hb_hashmap_t<int, hb_bytes_t, int, std::nullptr_t, 0, nullptr> m2;
+ hb_hashmap_t<hb_bytes_t, hb_bytes_t, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m3;
+ assert (m1.get_population () == 0);
+ assert (m2.get_population () == 0);
+ assert (m3.get_population () == 0);
+ }
+
+ {
+ hb_hashmap_t<int, int, int, int, 0, 0> m0;
+ hb_hashmap_t<std::string, int, const std::string*, int, &invalid, 0> m1;
+ hb_hashmap_t<int, std::string, int, const std::string*, 0, &invalid> m2;
+ hb_hashmap_t<std::string, std::string, const std::string*, const std::string*, &invalid, &invalid> m3;
+
+ std::string s;
+ for (unsigned i = 1; i < 1000; i++)
+ {
+ s += "x";
+ m0.set (i, i);
+ m1.set (s, i);
+ m2.set (i, s);
+ m3.set (s, s);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-meta.cc b/src/3rdparty/harfbuzz-ng/src/test-meta.cc
deleted file mode 100644
index 9436b9038e..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-meta.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright © 2019 Facebook, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Facebook Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-#include "hb-meta.hh"
-
-#include <type_traits>
-
-template <typename T> struct U { typedef T type; };
-
-int
-main (int argc, char **argv)
-{
- static_assert (hb_is_convertible (void, void), "");
- static_assert (hb_is_convertible (void, const void), "");
- static_assert (hb_is_convertible (const void, void), "");
-
- static_assert (hb_is_convertible (int, int), "");
- static_assert (hb_is_convertible (char, int), "");
- static_assert (hb_is_convertible (long, int), "");
-
- static_assert (hb_is_convertible (int, int), "");
-
- static_assert (hb_is_convertible (const int, int), "");
- static_assert (hb_is_convertible (int, const int), "");
- static_assert (hb_is_convertible (const int, const int), "");
-
- static_assert (hb_is_convertible (int&, int), "");
- static_assert (!hb_is_convertible (int, int&), "");
-
- static_assert (hb_is_convertible (int, const int&), "");
- static_assert (!hb_is_convertible (const int, int&), "");
- static_assert (hb_is_convertible (const int, const int&), "");
- static_assert (hb_is_convertible (int&, const int), "");
- static_assert (hb_is_convertible (const int&, int), "");
- static_assert (hb_is_convertible (const int&, const int), "");
- static_assert (hb_is_convertible (const int&, const int), "");
-
- struct X {};
- struct Y : X {};
-
- static_assert (hb_is_convertible (const X &, const X), "");
- static_assert (hb_is_convertible (X &, const X), "");
- static_assert (hb_is_convertible (X &, const X &), "");
- static_assert (hb_is_convertible (X, const X &), "");
- static_assert (hb_is_convertible (const X, const X &), "");
- static_assert (!hb_is_convertible (const X, X &), "");
- static_assert (!hb_is_convertible (X, X &), "");
- static_assert (hb_is_convertible (X &, X &), "");
-
- static_assert (hb_is_convertible (int&, long), "");
- static_assert (!hb_is_convertible (int&, long&), "");
-
- static_assert (hb_is_convertible (int *, int *), "");
- static_assert (hb_is_convertible (int *, const int *), "");
- static_assert (!hb_is_convertible (const int *, int *), "");
- static_assert (!hb_is_convertible (int *, long *), "");
- static_assert (hb_is_convertible (int *, void *), "");
- static_assert (!hb_is_convertible (void *, int *), "");
-
- static_assert (hb_is_base_of (void, void), "");
- static_assert (hb_is_base_of (void, int), "");
- static_assert (!hb_is_base_of (int, void), "");
-
- static_assert (hb_is_base_of (int, int), "");
- static_assert (hb_is_base_of (const int, int), "");
- static_assert (hb_is_base_of (int, const int), "");
-
- static_assert (hb_is_base_of (X, X), "");
- static_assert (hb_is_base_of (X, Y), "");
- static_assert (hb_is_base_of (const X, Y), "");
- static_assert (hb_is_base_of (X, const Y), "");
- static_assert (!hb_is_base_of (Y, X), "");
-
- static_assert (hb_is_constructible (int), "");
- static_assert (hb_is_constructible (int, int), "");
- static_assert (hb_is_constructible (int, char), "");
- static_assert (hb_is_constructible (int, long), "");
- static_assert (!hb_is_constructible (int, X), "");
- static_assert (!hb_is_constructible (int, int, int), "");
- static_assert (hb_is_constructible (X), "");
- static_assert (!hb_is_constructible (X, int), "");
- static_assert (hb_is_constructible (X, X), "");
- static_assert (!hb_is_constructible (X, X, X), "");
- static_assert (hb_is_constructible (X, Y), "");
- static_assert (!hb_is_constructible (Y, X), "");
-
- static_assert (hb_is_trivially_default_constructible (X), "");
- static_assert (hb_is_trivially_default_constructible (Y), "");
- static_assert (hb_is_trivially_copy_constructible (X), "");
- static_assert (hb_is_trivially_copy_constructible (Y), "");
- static_assert (hb_is_trivially_move_constructible (X), "");
- static_assert (hb_is_trivially_move_constructible (Y), "");
- static_assert (hb_is_trivially_destructible (Y), "");
-
- static_assert (hb_is_trivially_copyable (int), "");
- static_assert (hb_is_trivially_copyable (X), "");
- static_assert (hb_is_trivially_copyable (Y), "");
-
- static_assert (hb_is_trivial (int), "");
- static_assert (hb_is_trivial (X), "");
- static_assert (hb_is_trivial (Y), "");
-
- static_assert (hb_is_signed (hb_unwrap_type (U<U<U<int>>>)), "");
- static_assert (hb_is_unsigned (hb_unwrap_type (U<U<U<U<unsigned>>>>)), "");
-
- /* TODO Add more meaningful tests. */
-
- return 0;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-repacker.cc b/src/3rdparty/harfbuzz-ng/src/test-repacker.cc
index 6f46b04287..3a2536a29a 100644
--- a/src/3rdparty/harfbuzz-ng/src/test-repacker.cc
+++ b/src/3rdparty/harfbuzz-ng/src/test-repacker.cc
@@ -56,6 +56,51 @@ static void add_offset (unsigned id,
c->add_link (*offset, id);
}
+static void add_wide_offset (unsigned id,
+ hb_serialize_context_t* c)
+{
+ OT::Offset32* offset = c->start_embed<OT::Offset32> ();
+ c->extend_min (offset);
+ c->add_link (*offset, id);
+}
+
+static void run_resolve_overflow_test (const char* name,
+ hb_serialize_context_t& overflowing,
+ hb_serialize_context_t& expected,
+ unsigned num_iterations = 0)
+{
+ printf (">>> Testing overflowing resolution for %s\n",
+ name);
+
+ graph_t graph (overflowing.object_graph ());
+
+
+ assert (overflowing.offset_overflow ());
+ hb_blob_t* out = hb_resolve_overflows (overflowing.object_graph (),
+ HB_TAG ('G', 'S', 'U', 'B'), num_iterations);
+ assert (out);
+
+ hb_bytes_t result = out->as_bytes ();
+
+ assert (!expected.offset_overflow ());
+ hb_bytes_t expected_result = expected.copy_bytes ();
+
+ assert (result.length == expected_result.length);
+ for (unsigned i = 0; i < expected_result.length; i++)
+ {
+ assert (result[i] == expected_result[i]);
+ }
+
+ expected_result.fini ();
+ hb_blob_destroy (out);
+}
+
+static void add_virtual_offset (unsigned id,
+ hb_serialize_context_t* c)
+{
+ c->add_virtual_link (id);
+}
+
static void
populate_serializer_simple (hb_serialize_context_t* c)
{
@@ -67,7 +112,7 @@ populate_serializer_simple (hb_serialize_context_t* c)
start_object ("abc", 3, c);
add_offset (obj_2, c);
add_offset (obj_1, c);
- c->pop_pack ();
+ c->pop_pack (false);
c->end_serialize();
}
@@ -86,12 +131,64 @@ populate_serializer_with_overflow (hb_serialize_context_t* c)
add_offset (obj_3, c);
add_offset (obj_2, c);
add_offset (obj_1, c);
- c->pop_pack ();
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_with_priority_overflow (hb_serialize_context_t* c)
+{
+ std::string large_string(50000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_e = add_object ("e", 1, c);
+ unsigned obj_d = add_object ("d", 1, c);
+
+ start_object (large_string.c_str (), 50000, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object (large_string.c_str (), 20000, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_offset (obj_c, c);
+ c->pop_pack (false);
c->end_serialize();
}
static void
+populate_serializer_with_priority_overflow_expected (hb_serialize_context_t* c)
+{
+ std::string large_string(50000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_e = add_object ("e", 1, c);
+
+ start_object (large_string.c_str (), 50000, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ unsigned obj_d = add_object ("d", 1, c);
+
+ start_object (large_string.c_str (), 20000, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_offset (obj_c, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+
+static void
populate_serializer_with_dedup_overflow (hb_serialize_context_t* c)
{
std::string large_string(70000, 'a');
@@ -112,6 +209,526 @@ populate_serializer_with_dedup_overflow (hb_serialize_context_t* c)
}
static void
+populate_serializer_with_isolation_overflow (hb_serialize_context_t* c)
+{
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_4 = add_object ("4", 1, c);
+
+ start_object (large_string.c_str(), 60000, c);
+ add_offset (obj_4, c);
+ unsigned obj_3 = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 10000, c);
+ add_offset (obj_4, c);
+ unsigned obj_2 = c->pop_pack (false);
+
+ start_object ("1", 1, c);
+ add_wide_offset (obj_3, c);
+ add_offset (obj_2, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_with_isolation_overflow_complex (hb_serialize_context_t* c)
+{
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_f = add_object ("f", 1, c);
+
+ start_object ("e", 1, c);
+ add_offset (obj_f, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object ("d", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 60000, c);
+ add_offset (obj_d, c);
+ unsigned obj_h = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 60000, c);
+ add_offset (obj_c, c);
+ add_offset (obj_h, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 10000, c);
+ add_offset (obj_d, c);
+ unsigned obj_g = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 11000, c);
+ add_offset (obj_d, c);
+ unsigned obj_i = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_wide_offset (obj_b, c);
+ add_offset (obj_g, c);
+ add_offset (obj_i, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_with_isolation_overflow_complex_expected (hb_serialize_context_t* c)
+{
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+
+ // space 1
+
+ unsigned obj_f_prime = add_object ("f", 1, c);
+
+ start_object ("e", 1, c);
+ add_offset (obj_f_prime, c);
+ unsigned obj_e_prime = c->pop_pack (false);
+
+ start_object ("d", 1, c);
+ add_offset (obj_e_prime, c);
+ unsigned obj_d_prime = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 60000, c);
+ add_offset (obj_d_prime, c);
+ unsigned obj_h = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e_prime, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 60000, c);
+ add_offset (obj_c, c);
+ add_offset (obj_h, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ // space 0
+
+ unsigned obj_f = add_object ("f", 1, c);
+
+ start_object ("e", 1, c);
+ add_offset (obj_f, c);
+ unsigned obj_e = c->pop_pack (false);
+
+
+ start_object ("d", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 11000, c);
+ add_offset (obj_d, c);
+ unsigned obj_i = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 10000, c);
+ add_offset (obj_d, c);
+ unsigned obj_g = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_wide_offset (obj_b, c);
+ add_offset (obj_g, c);
+ add_offset (obj_i, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_with_isolation_overflow_spaces (hb_serialize_context_t* c)
+{
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_d = add_object ("f", 1, c);
+ unsigned obj_e = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 60000, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack ();
+
+ start_object (large_string.c_str(), 60000, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack ();
+
+
+ start_object ("a", 1, c);
+ add_wide_offset (obj_b, c);
+ add_wide_offset (obj_c, c);
+ c->pop_pack ();
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_spaces (hb_serialize_context_t* c, bool with_overflow)
+{
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_i;
+
+ if (with_overflow)
+ obj_i = add_object ("i", 1, c);
+
+ // Space 2
+ unsigned obj_h = add_object ("h", 1, c);
+
+ start_object (large_string.c_str(), 30000, c);
+ add_offset (obj_h, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ // Space 1
+ if (!with_overflow)
+ obj_i = add_object ("i", 1, c);
+
+ start_object (large_string.c_str(), 30000, c);
+ add_offset (obj_i, c);
+ unsigned obj_g = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 30000, c);
+ add_offset (obj_i, c);
+ unsigned obj_f = c->pop_pack (false);
+
+ start_object ("d", 1, c);
+ add_offset (obj_g, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_f, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_wide_offset (obj_b, c);
+ add_wide_offset (obj_c, c);
+ add_wide_offset (obj_d, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_spaces_16bit_connection (hb_serialize_context_t* c)
+{
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_g = add_object ("g", 1, c);
+ unsigned obj_h = add_object ("h", 1, c);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_g, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_h, c);
+ unsigned obj_f = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object ("d", 1, c);
+ add_offset (obj_f, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_e, c);
+ add_offset (obj_h, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_wide_offset (obj_c, c);
+ add_wide_offset (obj_d, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_spaces_16bit_connection_expected (hb_serialize_context_t* c)
+{
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_g_prime = add_object ("g", 1, c);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_g_prime, c);
+ unsigned obj_e_prime = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e_prime, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ unsigned obj_h_prime = add_object ("h", 1, c);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_h_prime, c);
+ unsigned obj_f = c->pop_pack (false);
+
+ start_object ("d", 1, c);
+ add_offset (obj_f, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ unsigned obj_g = add_object ("g", 1, c);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_g, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ unsigned obj_h = add_object ("h", 1, c);
+
+ start_object ("b", 1, c);
+ add_offset (obj_e, c);
+ add_offset (obj_h, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_wide_offset (obj_c, c);
+ add_wide_offset (obj_d, c);
+ c->pop_pack (false);
+
+ c->end_serialize ();
+}
+
+static void
+populate_serializer_short_and_wide_subgraph_root (hb_serialize_context_t* c)
+{
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_e = add_object ("e", 1, c);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_c, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_c, c);
+ add_offset (obj_e, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_wide_offset (obj_c, c);
+ add_wide_offset (obj_d, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_short_and_wide_subgraph_root_expected (hb_serialize_context_t* c)
+{
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_e_prime = add_object ("e", 1, c);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_e_prime, c);
+ unsigned obj_c_prime = c->pop_pack (false);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_c_prime, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ unsigned obj_e = add_object ("e", 1, c);
+
+ start_object (large_string.c_str (), 40000, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+
+ start_object ("b", 1, c);
+ add_offset (obj_c, c);
+ add_offset (obj_e, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_wide_offset (obj_c_prime, c);
+ add_wide_offset (obj_d, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_with_split_spaces (hb_serialize_context_t* c)
+{
+ // Overflow needs to be resolved by splitting the single space
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_f = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_wide_offset (obj_b, c);
+ add_wide_offset (obj_c, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_with_split_spaces_2 (hb_serialize_context_t* c)
+{
+ // Overflow needs to be resolved by splitting the single space
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_f = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_wide_offset (obj_b, c);
+ add_wide_offset (obj_c, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_with_split_spaces_expected (hb_serialize_context_t* c)
+{
+ // Overflow needs to be resolved by splitting the single space
+
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ unsigned obj_f_prime = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f_prime, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ unsigned obj_f = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_wide_offset (obj_b, c);
+ add_wide_offset (obj_c, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_with_split_spaces_expected_2 (hb_serialize_context_t* c)
+{
+ // Overflow needs to be resolved by splitting the single space
+
+ std::string large_string(70000, 'a');
+ c->start_serialize<char> ();
+
+ // Space 2
+
+ unsigned obj_f_double_prime = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f_double_prime, c);
+ unsigned obj_d_prime = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_d_prime, c);
+ unsigned obj_b_prime = c->pop_pack (false);
+
+ // Space 1
+
+ unsigned obj_f_prime = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f_prime, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ // Space 0
+
+ unsigned obj_f = add_object ("f", 1, c);
+
+ start_object (large_string.c_str(), 40000, c);
+ add_offset (obj_f, c);
+ unsigned obj_d = c->pop_pack (false);
+
+ start_object ("b", 1, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ // Root
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_wide_offset (obj_b_prime, c);
+ add_wide_offset (obj_c, c);
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
populate_serializer_complex_1 (hb_serialize_context_t* c)
{
c->start_serialize<char> ();
@@ -126,7 +743,7 @@ populate_serializer_complex_1 (hb_serialize_context_t* c)
start_object ("abc", 3, c);
add_offset (obj_2, c);
add_offset (obj_4, c);
- c->pop_pack ();
+ c->pop_pack (false);
c->end_serialize();
}
@@ -152,7 +769,7 @@ populate_serializer_complex_2 (hb_serialize_context_t* c)
add_offset (obj_2, c);
add_offset (obj_4, c);
add_offset (obj_5, c);
- c->pop_pack ();
+ c->pop_pack (false);
c->end_serialize();
}
@@ -182,7 +799,34 @@ populate_serializer_complex_3 (hb_serialize_context_t* c)
add_offset (obj_2, c);
add_offset (obj_4, c);
add_offset (obj_5, c);
- c->pop_pack ();
+ c->pop_pack (false);
+
+ c->end_serialize();
+}
+
+static void
+populate_serializer_virtual_link (hb_serialize_context_t* c)
+{
+ c->start_serialize<char> ();
+
+ unsigned obj_d = add_object ("d", 1, c);
+
+ start_object ("b", 1, c);
+ add_offset (obj_d, c);
+ unsigned obj_b = c->pop_pack (false);
+
+ start_object ("e", 1, c);
+ add_virtual_offset (obj_b, c);
+ unsigned obj_e = c->pop_pack (false);
+
+ start_object ("c", 1, c);
+ add_offset (obj_e, c);
+ unsigned obj_c = c->pop_pack (false);
+
+ start_object ("a", 1, c);
+ add_offset (obj_b, c);
+ add_offset (obj_c, c);
+ c->pop_pack (false);
c->end_serialize();
}
@@ -198,19 +842,19 @@ static void test_sort_kahn_1 ()
graph.sort_kahn ();
assert(strncmp (graph.object (3).head, "abc", 3) == 0);
- assert(graph.object (3).links.length == 2);
- assert(graph.object (3).links[0].objidx == 2);
- assert(graph.object (3).links[1].objidx == 1);
+ assert(graph.object (3).real_links.length == 2);
+ assert(graph.object (3).real_links[0].objidx == 2);
+ assert(graph.object (3).real_links[1].objidx == 1);
assert(strncmp (graph.object (2).head, "def", 3) == 0);
- assert(graph.object (2).links.length == 1);
- assert(graph.object (2).links[0].objidx == 0);
+ assert(graph.object (2).real_links.length == 1);
+ assert(graph.object (2).real_links[0].objidx == 0);
assert(strncmp (graph.object (1).head, "jkl", 3) == 0);
- assert(graph.object (1).links.length == 0);
+ assert(graph.object (1).real_links.length == 0);
assert(strncmp (graph.object (0).head, "ghi", 3) == 0);
- assert(graph.object (0).links.length == 0);
+ assert(graph.object (0).real_links.length == 0);
free (buffer);
}
@@ -227,24 +871,24 @@ static void test_sort_kahn_2 ()
assert(strncmp (graph.object (4).head, "abc", 3) == 0);
- assert(graph.object (4).links.length == 3);
- assert(graph.object (4).links[0].objidx == 3);
- assert(graph.object (4).links[1].objidx == 0);
- assert(graph.object (4).links[2].objidx == 2);
+ assert(graph.object (4).real_links.length == 3);
+ assert(graph.object (4).real_links[0].objidx == 3);
+ assert(graph.object (4).real_links[1].objidx == 0);
+ assert(graph.object (4).real_links[2].objidx == 2);
assert(strncmp (graph.object (3).head, "def", 3) == 0);
- assert(graph.object (3).links.length == 1);
- assert(graph.object (3).links[0].objidx == 1);
+ assert(graph.object (3).real_links.length == 1);
+ assert(graph.object (3).real_links[0].objidx == 1);
assert(strncmp (graph.object (2).head, "mn", 2) == 0);
- assert(graph.object (2).links.length == 0);
+ assert(graph.object (2).real_links.length == 0);
assert(strncmp (graph.object (1).head, "ghi", 3) == 0);
- assert(graph.object (1).links.length == 1);
- assert(graph.object (1).links[0].objidx == 0);
+ assert(graph.object (1).real_links.length == 1);
+ assert(graph.object (1).real_links[0].objidx == 0);
assert(strncmp (graph.object (0).head, "jkl", 3) == 0);
- assert(graph.object (0).links.length == 0);
+ assert(graph.object (0).real_links.length == 0);
free (buffer);
}
@@ -260,24 +904,24 @@ static void test_sort_shortest ()
graph.sort_shortest_distance ();
assert(strncmp (graph.object (4).head, "abc", 3) == 0);
- assert(graph.object (4).links.length == 3);
- assert(graph.object (4).links[0].objidx == 2);
- assert(graph.object (4).links[1].objidx == 0);
- assert(graph.object (4).links[2].objidx == 3);
+ assert(graph.object (4).real_links.length == 3);
+ assert(graph.object (4).real_links[0].objidx == 2);
+ assert(graph.object (4).real_links[1].objidx == 0);
+ assert(graph.object (4).real_links[2].objidx == 3);
assert(strncmp (graph.object (3).head, "mn", 2) == 0);
- assert(graph.object (3).links.length == 0);
+ assert(graph.object (3).real_links.length == 0);
assert(strncmp (graph.object (2).head, "def", 3) == 0);
- assert(graph.object (2).links.length == 1);
- assert(graph.object (2).links[0].objidx == 1);
+ assert(graph.object (2).real_links.length == 1);
+ assert(graph.object (2).real_links[0].objidx == 1);
assert(strncmp (graph.object (1).head, "ghi", 3) == 0);
- assert(graph.object (1).links.length == 1);
- assert(graph.object (1).links[0].objidx == 0);
+ assert(graph.object (1).real_links.length == 1);
+ assert(graph.object (1).real_links[0].objidx == 0);
assert(strncmp (graph.object (0).head, "jkl", 3) == 0);
- assert(graph.object (0).links.length == 0);
+ assert(graph.object (0).real_links.length == 0);
free (buffer);
}
@@ -293,27 +937,27 @@ static void test_duplicate_leaf ()
graph.duplicate (4, 1);
assert(strncmp (graph.object (5).head, "abc", 3) == 0);
- assert(graph.object (5).links.length == 3);
- assert(graph.object (5).links[0].objidx == 3);
- assert(graph.object (5).links[1].objidx == 4);
- assert(graph.object (5).links[2].objidx == 0);
+ assert(graph.object (5).real_links.length == 3);
+ assert(graph.object (5).real_links[0].objidx == 3);
+ assert(graph.object (5).real_links[1].objidx == 4);
+ assert(graph.object (5).real_links[2].objidx == 0);
assert(strncmp (graph.object (4).head, "jkl", 3) == 0);
- assert(graph.object (4).links.length == 0);
+ assert(graph.object (4).real_links.length == 0);
assert(strncmp (graph.object (3).head, "def", 3) == 0);
- assert(graph.object (3).links.length == 1);
- assert(graph.object (3).links[0].objidx == 2);
+ assert(graph.object (3).real_links.length == 1);
+ assert(graph.object (3).real_links[0].objidx == 2);
assert(strncmp (graph.object (2).head, "ghi", 3) == 0);
- assert(graph.object (2).links.length == 1);
- assert(graph.object (2).links[0].objidx == 1);
+ assert(graph.object (2).real_links.length == 1);
+ assert(graph.object (2).real_links[0].objidx == 1);
assert(strncmp (graph.object (1).head, "jkl", 3) == 0);
- assert(graph.object (1).links.length == 0);
+ assert(graph.object (1).real_links.length == 0);
assert(strncmp (graph.object (0).head, "mn", 2) == 0);
- assert(graph.object (0).links.length == 0);
+ assert(graph.object (0).real_links.length == 0);
free (buffer);
}
@@ -329,32 +973,32 @@ static void test_duplicate_interior ()
graph.duplicate (3, 2);
assert(strncmp (graph.object (6).head, "abc", 3) == 0);
- assert(graph.object (6).links.length == 3);
- assert(graph.object (6).links[0].objidx == 4);
- assert(graph.object (6).links[1].objidx == 2);
- assert(graph.object (6).links[2].objidx == 1);
+ assert(graph.object (6).real_links.length == 3);
+ assert(graph.object (6).real_links[0].objidx == 4);
+ assert(graph.object (6).real_links[1].objidx == 2);
+ assert(graph.object (6).real_links[2].objidx == 1);
assert(strncmp (graph.object (5).head, "jkl", 3) == 0);
- assert(graph.object (5).links.length == 1);
- assert(graph.object (5).links[0].objidx == 0);
+ assert(graph.object (5).real_links.length == 1);
+ assert(graph.object (5).real_links[0].objidx == 0);
assert(strncmp (graph.object (4).head, "def", 3) == 0);
- assert(graph.object (4).links.length == 1);
- assert(graph.object (4).links[0].objidx == 3);
+ assert(graph.object (4).real_links.length == 1);
+ assert(graph.object (4).real_links[0].objidx == 3);
assert(strncmp (graph.object (3).head, "ghi", 3) == 0);
- assert(graph.object (3).links.length == 1);
- assert(graph.object (3).links[0].objidx == 5);
+ assert(graph.object (3).real_links.length == 1);
+ assert(graph.object (3).real_links[0].objidx == 5);
assert(strncmp (graph.object (2).head, "jkl", 3) == 0);
- assert(graph.object (2).links.length == 1);
- assert(graph.object (2).links[0].objidx == 0);
+ assert(graph.object (2).real_links.length == 1);
+ assert(graph.object (2).real_links[0].objidx == 0);
assert(strncmp (graph.object (1).head, "mn", 2) == 0);
- assert(graph.object (1).links.length == 0);
+ assert(graph.object (1).real_links.length == 0);
assert(strncmp (graph.object (0).head, "opqrst", 6) == 0);
- assert(graph.object (0).links.length == 0);
+ assert(graph.object (0).real_links.length == 0);
free (buffer);
}
@@ -368,19 +1012,14 @@ test_serialize ()
populate_serializer_simple (&c1);
hb_bytes_t expected = c1.copy_bytes ();
- void* buffer_2 = malloc (buffer_size);
- hb_serialize_context_t c2 (buffer_2, buffer_size);
-
graph_t graph (c1.object_graph ());
- graph.serialize (&c2);
- hb_bytes_t actual = c2.copy_bytes ();
+ hb_blob_t* out = graph.serialize ();
+ free (buffer_1);
+ hb_bytes_t actual = out->as_bytes ();
assert (actual == expected);
-
- actual.fini ();
expected.fini ();
- free (buffer_1);
- free (buffer_2);
+ hb_blob_destroy (out);
}
static void test_will_overflow_1 ()
@@ -430,17 +1069,13 @@ static void test_resolve_overflows_via_sort ()
populate_serializer_with_overflow (&c);
graph_t graph (c.object_graph ());
- void* out_buffer = malloc (buffer_size);
- hb_serialize_context_t out (out_buffer, buffer_size);
-
- hb_resolve_overflows (c.object_graph (), &out);
- assert (!out.offset_overflow ());
- hb_bytes_t result = out.copy_bytes ();
+ hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE);
+ assert (out);
+ hb_bytes_t result = out->as_bytes ();
assert (result.length == (80000 + 3 + 3 * 2));
- result.fini ();
free (buffer);
- free (out_buffer);
+ hb_blob_destroy (out);
}
static void test_resolve_overflows_via_duplication ()
@@ -451,21 +1086,250 @@ static void test_resolve_overflows_via_duplication ()
populate_serializer_with_dedup_overflow (&c);
graph_t graph (c.object_graph ());
- void* out_buffer = malloc (buffer_size);
- hb_serialize_context_t out (out_buffer, buffer_size);
-
- hb_resolve_overflows (c.object_graph (), &out);
- assert (!out.offset_overflow ());
- hb_bytes_t result = out.copy_bytes ();
+ hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE);
+ assert (out);
+ hb_bytes_t result = out->as_bytes ();
assert (result.length == (10000 + 2 * 2 + 60000 + 2 + 3 * 2));
- result.fini ();
free (buffer);
- free (out_buffer);
+ hb_blob_destroy (out);
}
+static void test_resolve_overflows_via_space_assignment ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_spaces (&c, true);
+
+ void* expected_buffer = malloc (buffer_size);
+ hb_serialize_context_t e (expected_buffer, buffer_size);
+ populate_serializer_spaces (&e, false);
+
+ run_resolve_overflow_test ("test_resolve_overflows_via_space_assignment",
+ c,
+ e);
+
+ free (buffer);
+ free (expected_buffer);
+}
+
+static void test_resolve_overflows_via_isolation ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_with_isolation_overflow (&c);
+ graph_t graph (c.object_graph ());
+
+ assert (c.offset_overflow ());
+ hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0);
+ assert (out);
+ hb_bytes_t result = out->as_bytes ();
+ assert (result.length == (1 + 10000 + 60000 + 1 + 1
+ + 4 + 3 * 2));
+
+ free (buffer);
+ hb_blob_destroy (out);
+}
+
+static void test_resolve_overflows_via_isolation_with_recursive_duplication ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_with_isolation_overflow_complex (&c);
+
+ void* expected_buffer = malloc (buffer_size);
+ hb_serialize_context_t e (expected_buffer, buffer_size);
+ populate_serializer_with_isolation_overflow_complex_expected (&e);
+
+ run_resolve_overflow_test ("test_resolve_overflows_via_isolation_with_recursive_duplication",
+ c,
+ e);
+ free (buffer);
+ free (expected_buffer);
+}
+
+static void test_resolve_overflows_via_isolating_16bit_space ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_spaces_16bit_connection (&c);
+
+ void* expected_buffer = malloc (buffer_size);
+ hb_serialize_context_t e (expected_buffer, buffer_size);
+ populate_serializer_spaces_16bit_connection_expected (&e);
+
+ run_resolve_overflow_test ("test_resolve_overflows_via_isolating_16bit_space",
+ c,
+ e);
+
+ free (buffer);
+ free (expected_buffer);
+}
+
+static void test_resolve_overflows_via_isolating_16bit_space_2 ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_short_and_wide_subgraph_root (&c);
+
+ void* expected_buffer = malloc (buffer_size);
+ hb_serialize_context_t e (expected_buffer, buffer_size);
+ populate_serializer_short_and_wide_subgraph_root_expected (&e);
+
+ run_resolve_overflow_test ("test_resolve_overflows_via_isolating_16bit_space_2",
+ c,
+ e);
+
+ free (buffer);
+ free (expected_buffer);
+}
+
+static void test_resolve_overflows_via_isolation_spaces ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_with_isolation_overflow_spaces (&c);
+ graph_t graph (c.object_graph ());
+
+ assert (c.offset_overflow ());
+ hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0);
+ assert (out);
+ hb_bytes_t result = out->as_bytes ();
+
+ unsigned expected_length = 3 + 2 * 60000; // objects
+ expected_length += 2 * 4 + 2 * 2; // links
+ assert (result.length == expected_length);
+
+ free (buffer);
+ hb_blob_destroy (out);
+}
+
+static void test_resolve_overflows_via_splitting_spaces ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_with_split_spaces (&c);
+
+ void* expected_buffer = malloc (buffer_size);
+ hb_serialize_context_t e (expected_buffer, buffer_size);
+ populate_serializer_with_split_spaces_expected (&e);
+
+ run_resolve_overflow_test ("test_resolve_overflows_via_splitting_spaces",
+ c,
+ e,
+ 1);
+
+ free (buffer);
+ free (expected_buffer);
+
+}
+
+static void test_resolve_overflows_via_splitting_spaces_2 ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_with_split_spaces_2 (&c);
+
+ void* expected_buffer = malloc (buffer_size);
+ hb_serialize_context_t e (expected_buffer, buffer_size);
+ populate_serializer_with_split_spaces_expected_2 (&e);
+
+ run_resolve_overflow_test ("test_resolve_overflows_via_splitting_spaces_2",
+ c,
+ e,
+ 1);
+ free (buffer);
+ free (expected_buffer);
+}
+
+static void test_resolve_overflows_via_priority ()
+{
+ size_t buffer_size = 160000;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_with_priority_overflow (&c);
+
+ void* expected_buffer = malloc (buffer_size);
+ hb_serialize_context_t e (expected_buffer, buffer_size);
+ populate_serializer_with_priority_overflow_expected (&e);
+
+ run_resolve_overflow_test ("test_resolve_overflows_via_priority",
+ c,
+ e,
+ 3);
+ free (buffer);
+ free (expected_buffer);
+}
+
+
+static void test_virtual_link ()
+{
+ size_t buffer_size = 100;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+ populate_serializer_virtual_link (&c);
+
+ hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE);
+ assert (out);
+
+ hb_bytes_t result = out->as_bytes ();
+ assert (result.length == 5 + 4 * 2);
+ assert (result[0] == 'a');
+ assert (result[5] == 'c');
+ assert (result[8] == 'e');
+ assert (result[9] == 'b');
+ assert (result[12] == 'd');
+
+ free (buffer);
+ hb_blob_destroy (out);
+}
+
+static void
+test_shared_node_with_virtual_links ()
+{
+ size_t buffer_size = 100;
+ void* buffer = malloc (buffer_size);
+ hb_serialize_context_t c (buffer, buffer_size);
+
+ c.start_serialize<char> ();
+
+ unsigned obj_b = add_object ("b", 1, &c);
+ unsigned obj_c = add_object ("c", 1, &c);
+
+ start_object ("d", 1, &c);
+ add_virtual_offset (obj_b, &c);
+ unsigned obj_d_1 = c.pop_pack ();
+
+ start_object ("d", 1, &c);
+ add_virtual_offset (obj_c, &c);
+ unsigned obj_d_2 = c.pop_pack ();
+
+ assert (obj_d_1 == obj_d_2);
+
+ start_object ("a", 1, &c);
+ add_offset (obj_b, &c);
+ add_offset (obj_c, &c);
+ add_offset (obj_d_1, &c);
+ add_offset (obj_d_2, &c);
+ c.pop_pack ();
+ c.end_serialize ();
+
+ assert(c.object_graph() [obj_d_1]->virtual_links.length == 2);
+ assert(c.object_graph() [obj_d_1]->virtual_links[0].objidx == obj_b);
+ assert(c.object_graph() [obj_d_1]->virtual_links[1].objidx == obj_c);
+ free(buffer);
+}
+
+
// TODO(garretrieger): update will_overflow tests to check the overflows array.
-// TODO(garretrieger): add a test(s) using a real font.
// TODO(garretrieger): add tests for priority raising.
int
@@ -480,6 +1344,17 @@ main (int argc, char **argv)
test_will_overflow_3 ();
test_resolve_overflows_via_sort ();
test_resolve_overflows_via_duplication ();
+ test_resolve_overflows_via_priority ();
+ test_resolve_overflows_via_space_assignment ();
+ test_resolve_overflows_via_isolation ();
+ test_resolve_overflows_via_isolation_with_recursive_duplication ();
+ test_resolve_overflows_via_isolation_spaces ();
+ test_resolve_overflows_via_isolating_16bit_space ();
+ test_resolve_overflows_via_isolating_16bit_space_2 ();
+ test_resolve_overflows_via_splitting_spaces ();
+ test_resolve_overflows_via_splitting_spaces_2 ();
test_duplicate_leaf ();
test_duplicate_interior ();
+ test_virtual_link ();
+ test_shared_node_with_virtual_links ();
}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-serialize.cc b/src/3rdparty/harfbuzz-ng/src/test-serialize.cc
new file mode 100644
index 0000000000..44a2e0fe1d
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/test-serialize.cc
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ *
+ */
+
+#include "hb.hh"
+#include "hb-serialize.hh"
+#include "hb-ot-layout-common.hh"
+
+
+int
+main (int argc, char **argv)
+{
+ char buf[16384];
+
+ hb_serialize_context_t s (buf, sizeof (buf));
+
+ hb_sorted_vector_t<hb_codepoint_t> v{1, 2, 5};
+
+ auto c = s.start_serialize<OT::Coverage> ();
+
+ c->serialize (&s, hb_iter (v));
+
+ s.end_serialize ();
+
+ hb_bytes_t bytes = s.copy_bytes ();
+ assert (bytes.length == 10);
+ bytes.fini ();
+
+ return 0;
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-set.cc b/src/3rdparty/harfbuzz-ng/src/test-set.cc
new file mode 100644
index 0000000000..286f1a9976
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/test-set.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2021 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.
+ *
+ */
+
+#include "hb.hh"
+#include "hb-set.hh"
+
+
+int
+main (int argc, char **argv)
+{
+
+ /* Test copy constructor. */
+ {
+ hb_set_t v1 {1, 2};
+ hb_set_t v2 {v1};
+ assert (v1.get_population () == 2);
+ assert (v2.get_population () == 2);
+ }
+
+ /* Test copy assignment. */
+ {
+ hb_set_t v1 {1, 2};
+ hb_set_t v2 = v1;
+ assert (v1.get_population () == 2);
+ assert (v2.get_population () == 2);
+ }
+
+ /* Test move constructor. */
+ {
+ hb_set_t v {hb_set_t {1, 2}};
+ assert (v.get_population () == 2);
+ }
+
+ /* Test move assignment. */
+ {
+ hb_set_t v;
+ v = hb_set_t {1, 2};
+ assert (v.get_population () == 2);
+ }
+
+ /* Test initializing from iterable. */
+ {
+ hb_set_t s;
+
+ s.add (18);
+ s.add (12);
+
+ hb_set_t v (s);
+
+ assert (v.get_population () == 2);
+ }
+
+ /* Test initializing from iterator. */
+ {
+ hb_set_t s;
+
+ s.add (18);
+ s.add (12);
+
+ hb_set_t v (hb_iter (s));
+
+ assert (v.get_population () == 2);
+ }
+
+ /* Test initializing from initializer list and swapping. */
+ {
+ hb_set_t v1 {1, 2, 3};
+ hb_set_t v2 {4, 5};
+ hb_swap (v1, v2);
+ assert (v1.get_population () == 2);
+ assert (v2.get_population () == 3);
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-vector.cc b/src/3rdparty/harfbuzz-ng/src/test-vector.cc
new file mode 100644
index 0000000000..521f2a171d
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/test-vector.cc
@@ -0,0 +1,154 @@
+/*
+ * Copyright © 2021 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.
+ *
+ */
+
+#include "hb.hh"
+#include "hb-vector.hh"
+#include "hb-set.hh"
+#include <string>
+
+
+int
+main (int argc, char **argv)
+{
+
+ /* Test copy constructor. */
+ {
+ hb_vector_t<int> v1 {1, 2};
+ hb_vector_t<int> v2 {v1};
+ hb_vector_t<int> V2 {v1};
+ assert (v1.length == 2);
+ assert (v1[0] == 1);
+ assert (v1[1] == 2);
+ assert (v2.length == 2);
+ assert (v2[0] == 1);
+ assert (v2[1] == 2);
+ }
+
+ /* Test copy assignment. */
+ {
+ hb_vector_t<int> v1 {1, 2};
+ hb_vector_t<int> v2 = v1;
+ hb_vector_t<int> V2 = v1;
+ assert (v1.length == 2);
+ assert (v1[0] == 1);
+ assert (v1[1] == 2);
+ assert (v2.length == 2);
+ assert (v2[0] == 1);
+ assert (v2[1] == 2);
+ }
+
+ /* Test move constructor. */
+ {
+ hb_vector_t<int> v {hb_vector_t<int> {1, 2}};
+ hb_vector_t<int> V {hb_vector_t<int> {1, 2}};
+ assert (v.length == 2);
+ assert (v[0] == 1);
+ assert (v[1] == 2);
+ }
+
+ /* Test move assignment. */
+ {
+ hb_vector_t<int> v;
+ hb_sorted_vector_t<int> V;
+ v = hb_vector_t<int> {1, 2};
+ V = hb_sorted_vector_t<int> {1, 2};
+ assert (v.length == 2);
+ assert (v[0] == 1);
+ assert (v[1] == 2);
+ }
+
+ /* Test initializing from iterable. */
+ {
+ hb_set_t s;
+
+ s.add (18);
+ s.add (12);
+
+ hb_vector_t<int> v (s);
+ hb_sorted_vector_t<int> V (s);
+
+ assert (v.length == 2);
+ assert (V.length == 2);
+ assert (v[0] == 12);
+ assert (V[0] == 12);
+ assert (v[1] == 18);
+ assert (V[1] == 18);
+ }
+
+ /* Test initializing from iterator. */
+ {
+ hb_set_t s;
+
+ s.add (18);
+ s.add (12);
+
+ hb_vector_t<int> v (hb_iter (s));
+ hb_vector_t<int> V (hb_iter (s));
+
+ assert (v.length == 2);
+ assert (V.length == 2);
+ assert (v[0] == 12);
+ assert (V[0] == 12);
+ assert (v[1] == 18);
+ assert (V[1] == 18);
+ }
+
+ /* Test initializing from initializer list and swapping. */
+ {
+ hb_vector_t<int> v1 {1, 2, 3};
+ hb_vector_t<int> v2 {4, 5};
+ hb_swap (v1, v2);
+ assert (v1.length == 2);
+ assert (v1[0] == 4);
+ assert (v2.length == 3);
+ assert (v2[2] == 3);
+ }
+
+ /* Test initializing sorted-vector from initializer list and swapping. */
+ {
+ hb_sorted_vector_t<int> v1 {1, 2, 3};
+ hb_sorted_vector_t<int> v2 {4, 5};
+ hb_swap (v1, v2);
+ assert (v1.length == 2);
+ assert (v1[0] == 4);
+ assert (v2.length == 3);
+ assert (v2[2] == 3);
+ }
+
+#if 0
+ {
+ hb_vector_t<std::string> v;
+
+ std::string s;
+ for (unsigned i = 1; i < 100; i++)
+ {
+ s += "x";
+ v.push (s);
+ }
+ }
+#endif
+
+ return 0;
+}