summaryrefslogtreecommitdiffstats
path: root/src/3rdparty
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2023-02-27 09:53:00 +0100
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2023-03-01 06:37:29 +0100
commita6edf9cbe5bd1d1c6bc08733f97fc07812126bde (patch)
tree7013520fe3cf1828c75c3eee562c90c41465b567 /src/3rdparty
parent5f32c9edce208125f642c86a4bc9e73564386243 (diff)
Update Harfbuzz to 7.0.1
Note: 6.4.x update has to be done in a separate commit because it did not get the update to 6.0.0, so the cherry-pick will not apply. Pick-to: 6.2 6.5 Task-number: QTBUG-111535 Change-Id: I9d4aae98f8267827ec983ca89b1310006c6aee78 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/3rdparty')
-rw-r--r--src/3rdparty/harfbuzz-ng/CMakeLists.txt20
-rw-r--r--src/3rdparty/harfbuzz-ng/COPYING20
-rw-r--r--src/3rdparty/harfbuzz-ng/NEWS136
-rw-r--r--src/3rdparty/harfbuzz-ng/qt_attribution.json33
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh)77
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-color-colr-table.hh)652
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/colrv1-closure.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-color-colrv1-closure.hh)11
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Color/CPAL/CPAL.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-color-cpal-table.hh)14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-color-sbix-table.hh)69
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Color/svg/svg.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-color-svg-table.hh)33
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh918
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh83
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh29
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh38
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh158
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/GlyphHeader.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh31
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh114
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh63
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/name/name.hh589
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/graph.hh17
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/serialize.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/harfbuzz.cc4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh105
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-kerx-table.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh57
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-map.cc130
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-map.hh45
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-algs.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-array.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-atomic.hh41
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh26
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-blob.cc6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh372
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-glyphs.hh692
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-unicode.hh332
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh917
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc21
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.cc38
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.h2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.hh70
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cache.hh7
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc869
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.hh107
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cairo.cc1010
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cairo.h99
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh16
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff-interp-dict-common.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff1-interp-cs.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh13
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-common.cc26
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-common.h26
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-config.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-coretext.cc1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cplusplus.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-debug.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-deprecated.h3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-draw.cc65
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-draw.h35
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-face-builder.cc246
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-face.cc248
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-face.h6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.cc326
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.h145
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.hh120
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh567
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ft.cc261
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h20
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-graphite2.h3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-iter.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-limits.hh109
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-machinery.hh33
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-map.cc86
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-map.h19
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-map.hh75
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-multimap.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-mutex.hh5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-number.cc1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-object.hh34
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-open-type.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc19
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc19
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh43
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc55
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color.h9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-face.cc6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc166
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh1
-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.hh81
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh104
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh886
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh262
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc140
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh13
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh565
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name.h22
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh69
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-os2-unicode-ranges.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh17
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc43
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh29
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.cc16
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.cc4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh16
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc24
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-mvar-table.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-outline.cc322
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-outline.hh (renamed from src/3rdparty/harfbuzz-ng/src/test-unicode-ranges.cc)81
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-paint-extents.cc330
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-paint-extents.hh293
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-paint.cc703
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-paint.h987
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-paint.hh228
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-pool.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-repacker.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-serialize.hh11
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.cc22
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.h3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-static.cc35
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh47
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh267
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc221
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc184
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh44
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc464
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc341
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh170
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.cc35
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.h19
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.hh1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-unicode.cc2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-utf.hh30
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-vector.hh78
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-version.h6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb.h1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb.hh37
-rw-r--r--src/3rdparty/harfbuzz-ng/src/main.cc36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-algs.cc110
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-array.cc79
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-bimap.cc76
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-buffer-serialize.cc95
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-gpos-size-params.cc62
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-gsub-would-substitute.cc67
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-iter.cc382
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-machinery.cc46
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-map.cc306
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-number.cc224
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-ot-glyphname.cc89
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-ot-meta.cc68
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-ot-name.cc74
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-priority-queue.cc81
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-repacker.cc2138
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-serialize.cc52
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-set.cc111
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-vector.cc186
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test.cc2
218 files changed, 13973 insertions, 8939 deletions
diff --git a/src/3rdparty/harfbuzz-ng/CMakeLists.txt b/src/3rdparty/harfbuzz-ng/CMakeLists.txt
index b18179e6d0..1940da9b2b 100644
--- a/src/3rdparty/harfbuzz-ng/CMakeLists.txt
+++ b/src/3rdparty/harfbuzz-ng/CMakeLists.txt
@@ -16,7 +16,8 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
src/hb-blob.cc src/hb-blob.h
src/hb-buffer.cc src/hb-buffer.h src/hb-buffer.hh
src/hb-buffer-deserialize-json.hh
- src/hb-buffer-deserialize-text.hh
+ src/hb-buffer-deserialize-text-glyphs.hh
+ src/hb-buffer-deserialize-text-unicode.hh
src/hb-buffer-serialize.cc
src/hb-buffer-verify.cc
src/hb-cache.hh
@@ -25,14 +26,20 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
src/hb-deprecated.h
src/hb-draw.cc src/hb-draw.h src/hb-draw.hh
src/hb-face.cc src/hb-face.h src/hb-face.hh
+ src/hb-face-builder.cc
src/hb-fallback-shape.cc
src/hb-font.cc src/hb-font.h src/hb-font.hh
+ src/hb-ft-colr.hh
+ src/hb-limits.hh
src/hb-map.cc
src/hb-mutex.hh
src/hb-number.cc
src/hb-object.hh
src/hb-open-file.hh
src/hb-open-type.hh
+ src/hb-outline.cc src/hb-outline.hh
+ src/hb-paint.cc src/hb-paint.h src/hb-paint.hh
+ src/hb-paint-extents.cc src/hb-paint-extents.hh
src/hb-priority-queue.hh
src/hb-repacker.hh
src/hb-set.cc src/hb-set.h src/hb-set.hh
@@ -49,6 +56,7 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
src/hb-subset-cff1.cc
src/hb-subset-cff2.cc
src/hb-subset-input.cc
+ src/hb-subset-instancer-solver.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
@@ -103,8 +111,6 @@ qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE
src/hb-ot-cff2-table.cc
src/hb-ot-cmap-table.hh
src/hb-ot-color.cc
- src/hb-ot-color-cbdt-table.hh
- src/hb-ot-color-colrv1-closure.hh
src/hb-ot-face.cc
src/hb-ot-font.cc src/hb-ot-font.h
src/hb-ot-glyf-table.hh
@@ -163,6 +169,14 @@ qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE
src/hb-ot-var-fvar-table.hh
src/hb-ot-var-hvar-table.hh
src/hb-ot-var-mvar-table.hh
+ src/OT/Color/CBDT/CBDT.hh
+ src/OT/Color/COLR/COLR.hh
+ src/OT/Color/COLR/colrv1-closure.hh
+ src/OT/Color/CPAL/CPAL.hh
+ src/OT/Color/sbix/sbix.hh
+ src/OT/Color/svg/svg.hh
+ src/OT/Layout/GDEF/GDEF.hh
+ src/OT/name/name.hh
DEFINES
HAVE_OT
)
diff --git a/src/3rdparty/harfbuzz-ng/COPYING b/src/3rdparty/harfbuzz-ng/COPYING
index 48d1b30f90..1dd917e9f2 100644
--- a/src/3rdparty/harfbuzz-ng/COPYING
+++ b/src/3rdparty/harfbuzz-ng/COPYING
@@ -2,19 +2,23 @@ HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
For parts of HarfBuzz that are licensed under different licenses see individual
files names COPYING in subdirectories where applicable.
-Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc.
-Copyright © 2018,2019,2020 Ebrahim Byagowi
+Copyright © 2010-2022 Google, Inc.
+Copyright © 2015-2020 Ebrahim Byagowi
Copyright © 2019,2020 Facebook, Inc.
-Copyright © 2012 Mozilla Foundation
+Copyright © 2012,2015 Mozilla Foundation
Copyright © 2011 Codethink Limited
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
Copyright © 2009 Keith Stribley
-Copyright © 2009 Martin Hosken and SIL International
+Copyright © 2011 Martin Hosken and SIL International
Copyright © 2007 Chris Wilson
-Copyright © 2005,2006,2020,2021 Behdad Esfahbod
-Copyright © 2005 David Turner
-Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
-Copyright © 1998-2004 David Turner and Werner Lemberg
+Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
+Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
+Copyright © 1998-2005 David Turner and Werner Lemberg
+Copyright © 2016 Igalia S.L.
+Copyright © 2022 Matthias Clasen
+Copyright © 2018,2021 Khaled Hosny
+Copyright © 2018,2019,2020 Adobe, Inc
+Copyright © 2013-2015 Alexei Podtelezhnikov
For full copyright notices consult the individual files in the package.
diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS
index 73dcef083a..9a5914525c 100644
--- a/src/3rdparty/harfbuzz-ng/NEWS
+++ b/src/3rdparty/harfbuzz-ng/NEWS
@@ -1,3 +1,139 @@
+Overview of changes leading to 7.0.1
+Monday, February 20, 2023
+====================================
+- Various build and bug fixes.
+
+
+Overview of changes leading to 7.0.0
+Saturday, February 11, 2023
+====================================
+- New hb-paint API that is designed mainly to paint “COLRv1” glyphs, but can be
+ also used as a unified API to paint any of the glyph representations
+ supported by HarfBuzz (B/W outlines, color layers, or color bitmaps).
+ (Behdad Esfahbod, Matthias Clasen)
+- New hb-cairo API for integrating with cairo graphics library. This is provided
+ as a separate harfbuzz-cairo library. (Behdad Esfahbod, Matthias Clasen)
+- Support for instancing “CFF2” table. (Behdad Esfahbod)
+- Support font emboldening. (Behdad Esfahbod)
+- Support feature ranges with AAT shaping. (Behdad Esfahbod)
+- Experimental support to cubic curves in “glyf” table, see
+ https://github.com/harfbuzz/boring-expansion-spec/blob/main/glyf1-cubicOutlines.md
+ for spec. (Behdad Esfahbod)
+- Various subsetter improvements. (Garret Rieger, Qunxin Liu, Behdad Esfahbod)
+- Various documentation improvements.
+ (Behdad Esfahbod, Matthias Clasen, Khaled Hosny)
+- Significantly reduced memory use during shaping. (Behdad Esfahbod)
+- Greatly reduced memory use during subsetting “CFF” table. (Behdad Esfahbod)
+- New command line utility, hb-info, for querying various font information.
+ (Behdad Esfahbod, Matthias Clasen)
+- New hb-shape/hb-view options: --glyphs, --color-palette, --font-bold,
+ --font-grade, and --named-instance. (Behdad Esfahbod)
+- Miscellaneous fixes and improvements.
+ (Amir Masoud Abdol, Andres Salomon, Behdad Esfahbod, Chun-wei Fan,
+ Garret Rieger, Jens Kutilek, Khaled Hosny, Konstantin Käfer, Matthias Clasen,
+ Nirbheek Chauhan, Pedro J. Estébanez, Qunxin Liu, Sergei Trofimovich)
+
+- New API:
++HB_FONT_NO_VAR_NAMED_INSTANCE
++HB_PAINT_IMAGE_FORMAT_BGRA
++HB_PAINT_IMAGE_FORMAT_PNG
++HB_PAINT_IMAGE_FORMAT_SVG
++hb_cairo_font_face_create_for_face
++hb_cairo_font_face_create_for_font
++hb_cairo_font_face_get_face
++hb_cairo_font_face_get_font
++hb_cairo_font_face_get_scale_factor
++hb_cairo_font_face_set_font_init_func
++hb_cairo_font_face_set_scale_factor
++hb_cairo_font_init_func_t
++hb_cairo_glyphs_from_buffer
++hb_cairo_scaled_font_get_font
++hb_color_line_get_color_stops
++hb_color_line_get_color_stops_func_t
++hb_color_line_get_extend
++hb_color_line_get_extend_func_t
++hb_color_line_t
++hb_color_stop_t
++hb_draw_funcs_get_empty
++hb_draw_funcs_get_user_data
++hb_draw_funcs_set_user_data
++hb_face_collect_nominal_glyph_mapping
++hb_font_draw_glyph
++hb_font_draw_glyph_func_t
++hb_font_funcs_set_draw_glyph_func
++hb_font_funcs_set_paint_glyph_func
++hb_font_get_synthetic_bold
++hb_font_get_var_named_instance
++hb_font_paint_glyph
++hb_font_paint_glyph_func_t
++hb_font_set_synthetic_bold
++hb_map_keys
++hb_map_next
++hb_map_update
++hb_map_values
++hb_ot_color_glyph_has_paint
++hb_ot_color_has_paint
++hb_ot_layout_script_select_language2
++hb_ot_name_id_predefined_t
++hb_paint_color
++hb_paint_color_func_t
++hb_paint_composite_mode_t
++hb_paint_custom_palette_color
++hb_paint_custom_palette_color_func_t
++hb_paint_extend_t
++hb_paint_funcs_create
++hb_paint_funcs_destroy
++hb_paint_funcs_get_empty
++hb_paint_funcs_get_user_data
++hb_paint_funcs_is_immutable
++hb_paint_funcs_make_immutable
++hb_paint_funcs_reference
++hb_paint_funcs_set_color_func
++hb_paint_funcs_set_custom_palette_color_func
++hb_paint_funcs_set_image_func
++hb_paint_funcs_set_linear_gradient_func
++hb_paint_funcs_set_pop_clip_func
++hb_paint_funcs_set_pop_group_func
++hb_paint_funcs_set_pop_transform_func
++hb_paint_funcs_set_push_clip_glyph_func
++hb_paint_funcs_set_push_clip_rectangle_func
++hb_paint_funcs_set_push_group_func
++hb_paint_funcs_set_push_transform_func
++hb_paint_funcs_set_radial_gradient_func
++hb_paint_funcs_set_sweep_gradient_func
++hb_paint_funcs_set_user_data
++hb_paint_funcs_t
++hb_paint_image
++hb_paint_image_func_t
++hb_paint_linear_gradient
++hb_paint_linear_gradient_func_t
++hb_paint_pop_clip
++hb_paint_pop_clip_func_t
++hb_paint_pop_group
++hb_paint_pop_group_func_t
++hb_paint_pop_transform
++hb_paint_pop_transform_func_t
++hb_paint_push_clip_glyph
++hb_paint_push_clip_glyph_func_t
++hb_paint_push_clip_rectangle
++hb_paint_push_clip_rectangle_func_t
++hb_paint_push_group
++hb_paint_push_group_func_t
++hb_paint_push_transform
++hb_paint_push_transform_func_t
++hb_paint_radial_gradient
++hb_paint_radial_gradient_func_t
++hb_paint_sweep_gradient
++hb_paint_sweep_gradient_func_t
++hb_set_is_inverted
++hb_subset_input_keep_everything
+
+- Deprecated API:
++hb_font_funcs_set_glyph_shape_func
++hb_font_get_glyph_shape_func_t
++hb_font_get_glyph_shape
+
+
Overview of changes leading to 6.0.0
Friday, December 16, 2022
====================================
diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json
index 4aefc44203..1779409e3b 100644
--- a/src/3rdparty/harfbuzz-ng/qt_attribution.json
+++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json
@@ -6,23 +6,26 @@
"Description": "HarfBuzz is an OpenType text shaping engine.",
"Homepage": "http://harfbuzz.org",
- "Version": "6.0.0",
+ "Version": "7.0.1",
"License": "MIT License",
"LicenseId": "MIT",
"LicenseFile": "COPYING",
- "Copyright": "Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc.
-Copyright © 2018,2019,2020 Ebrahim Byagowi
-Copyright © 2019,2020 Facebook, Inc.
-Copyright © 2012 Mozilla Foundation
-Copyright © 2011 Codethink Limited
-Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
-Copyright © 2009 Keith Stribley
-Copyright © 2009 Martin Hosken and SIL International
-Copyright © 2007 Chris Wilson
-Copyright © 2005,2006,2020,2021 Behdad Esfahbod
-Copyright © 2005 David Turner
-Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
-Copyright © 1998-2004 David Turner and Werner Lemberg
-"
+ "Copyright": "Copyright © 2010-2022 Google, Inc.
+ Copyright © 2015-2020 Ebrahim Byagowi
+ Copyright © 2019,2020 Facebook, Inc.
+ Copyright © 2012,2015 Mozilla Foundation
+ Copyright © 2011 Codethink Limited
+ Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright © 2009 Keith Stribley
+ Copyright © 2011 Martin Hosken and SIL International
+ Copyright © 2007 Chris Wilson
+ Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
+ Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
+ Copyright © 1998-2005 David Turner and Werner Lemberg
+ Copyright © 2016 Igalia S.L.
+ Copyright © 2022 Matthias Clasen
+ Copyright © 2018,2021 Khaled Hosny
+ Copyright © 2018,2019,2020 Adobe, Inc
+ Copyright © 2013-2015 Alexei Podtelezhnikov"
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh
index 3246894d39..b125052344 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-cbdt-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh
@@ -24,10 +24,11 @@
* Google Author(s): Seigo Nonaka, Calder Kitagawa
*/
-#ifndef HB_OT_COLOR_CBDT_TABLE_HH
-#define HB_OT_COLOR_CBDT_TABLE_HH
+#ifndef OT_COLOR_CBDT_CBDT_HH
+#define OT_COLOR_CBDT_CBDT_HH
-#include "hb-open-type.hh"
+#include "../../../hb-open-type.hh"
+#include "../../../hb-paint.hh"
/*
* CBLC -- Color Bitmap Location
@@ -80,12 +81,15 @@ struct SmallGlyphMetrics
return_trace (c->check_struct (this));
}
- void get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const
+ void get_extents (hb_font_t *font, hb_glyph_extents_t *extents, bool scale) const
{
- extents->x_bearing = font->em_scale_x (bearingX);
- extents->y_bearing = font->em_scale_y (bearingY);
- extents->width = font->em_scale_x (width);
- extents->height = font->em_scale_y (-static_cast<int>(height));
+ extents->x_bearing = bearingX;
+ extents->y_bearing = bearingY;
+ extents->width = width;
+ extents->height = -static_cast<int> (height);
+
+ if (scale)
+ font->scale_glyph_extents (extents);
}
HBUINT8 height;
@@ -307,7 +311,7 @@ struct IndexSubtable
}
}
- bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const
+ bool get_extents (hb_glyph_extents_t *extents HB_UNUSED, bool scale HB_UNUSED) const
{
switch (u.header.indexFormat)
{
@@ -504,8 +508,8 @@ struct IndexSubtableRecord
return num_missing;
}
- bool get_extents (hb_glyph_extents_t *extents, const void *base) const
- { return (base+offsetToSubtable).get_extents (extents); }
+ bool get_extents (hb_glyph_extents_t *extents, const void *base, bool scale) const
+ { return (base+offsetToSubtable).get_extents (extents, scale); }
bool get_image_data (unsigned int gid,
const void *base,
@@ -833,7 +837,7 @@ struct CBDT
}
bool
- get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+ get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents, bool scale = true) const
{
const void *base;
const BitmapSizeTable &strike = this->cblc->choose_strike (font);
@@ -841,7 +845,7 @@ struct CBDT
if (!subtable_record || !strike.ppemX || !strike.ppemY)
return false;
- if (subtable_record->get_extents (extents, base))
+ if (subtable_record->get_extents (extents, base, scale))
return true;
unsigned int image_offset = 0, image_length = 0, image_format = 0;
@@ -858,26 +862,29 @@ struct CBDT
if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
return false;
auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
- glyphFormat17.glyphMetrics.get_extents (font, extents);
+ glyphFormat17.glyphMetrics.get_extents (font, extents, scale);
break;
}
case 18: {
if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
return false;
auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
- glyphFormat18.glyphMetrics.get_extents (font, extents);
+ glyphFormat18.glyphMetrics.get_extents (font, extents, scale);
break;
}
default: return false; /* TODO: Support other image formats. */
}
/* Convert to font units. */
- float x_scale = upem / (float) strike.ppemX;
- float y_scale = upem / (float) strike.ppemY;
- extents->x_bearing = roundf (extents->x_bearing * x_scale);
- extents->y_bearing = roundf (extents->y_bearing * y_scale);
- extents->width = roundf (extents->width * x_scale);
- extents->height = roundf (extents->height * y_scale);
+ if (scale)
+ {
+ float x_scale = upem / (float) strike.ppemX;
+ float y_scale = upem / (float) strike.ppemY;
+ extents->x_bearing = roundf (extents->x_bearing * x_scale);
+ extents->y_bearing = roundf (extents->y_bearing * y_scale);
+ extents->width = roundf (extents->width * x_scale);
+ extents->height = roundf (extents->height * y_scale);
+ }
return true;
}
@@ -934,6 +941,32 @@ struct CBDT
bool has_data () const { return cbdt.get_length (); }
+ bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
+ {
+ hb_glyph_extents_t extents;
+ hb_glyph_extents_t pixel_extents;
+ hb_blob_t *blob = reference_png (font, glyph);
+
+ if (unlikely (blob == hb_blob_get_empty ()))
+ return false;
+
+ if (unlikely (!hb_font_get_glyph_extents (font, glyph, &extents)))
+ return false;
+
+ if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
+ return false;
+
+ bool ret = funcs->image (data,
+ blob,
+ pixel_extents.width, -pixel_extents.height,
+ HB_PAINT_IMAGE_FORMAT_PNG,
+ font->slant_xy,
+ &extents);
+
+ hb_blob_destroy (blob);
+ return ret;
+ }
+
private:
hb_blob_ptr_t<CBLC> cblc;
hb_blob_ptr_t<CBDT> cbdt;
@@ -994,4 +1027,4 @@ struct CBDT_accelerator_t : CBDT::accelerator_t {
} /* namespace OT */
-#endif /* HB_OT_COLOR_CBDT_TABLE_HH */
+#endif /* OT_COLOR_CBDT_CBDT_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colr-table.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh
index 1af9d30937..31be6585dd 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colr-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh
@@ -25,12 +25,14 @@
* Google Author(s): Calder Kitagawa
*/
-#ifndef HB_OT_COLOR_COLR_TABLE_HH
-#define HB_OT_COLOR_COLR_TABLE_HH
+#ifndef OT_COLOR_COLR_COLR_HH
+#define OT_COLOR_COLR_COLR_HH
-#include "hb-open-type.hh"
-#include "hb-ot-layout-common.hh"
-#include "hb-ot-var-common.hh"
+#include "../../../hb.hh"
+#include "../../../hb-open-type.hh"
+#include "../../../hb-ot-var-common.hh"
+#include "../../../hb-paint.hh"
+#include "../../../hb-paint-extents.hh"
/*
* COLR -- Color
@@ -38,13 +40,82 @@
*/
#define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
-#ifndef HB_COLRV1_MAX_NESTING_LEVEL
-#define HB_COLRV1_MAX_NESTING_LEVEL 16
-#endif
+
+namespace OT {
+struct hb_paint_context_t;
+}
namespace OT {
struct COLR;
+
+struct Paint;
+
+struct hb_paint_context_t :
+ hb_dispatch_context_t<hb_paint_context_t>
+{
+ template <typename T>
+ return_t dispatch (const T &obj) { obj.paint_glyph (this); return hb_empty_t (); }
+ static return_t default_return_value () { return hb_empty_t (); }
+
+ const COLR* get_colr_table () const
+ { return reinterpret_cast<const COLR *> (base); }
+
+public:
+ const void *base;
+ hb_paint_funcs_t *funcs;
+ void *data;
+ hb_font_t *font;
+ unsigned int palette_index;
+ hb_color_t foreground;
+ VarStoreInstancer &instancer;
+ int depth_left = HB_MAX_NESTING_LEVEL;
+ int edge_count = HB_COLRV1_MAX_EDGE_COUNT;
+
+ hb_paint_context_t (const void *base_,
+ hb_paint_funcs_t *funcs_,
+ void *data_,
+ hb_font_t *font_,
+ unsigned int palette_,
+ hb_color_t foreground_,
+ VarStoreInstancer &instancer_) :
+ base (base_),
+ funcs (funcs_),
+ data (data_),
+ font (font_),
+ palette_index (palette_),
+ foreground (foreground_),
+ instancer (instancer_)
+ { }
+
+ hb_color_t get_color (unsigned int color_index, float alpha, hb_bool_t *is_foreground)
+ {
+ hb_color_t color = foreground;
+
+ *is_foreground = true;
+
+ if (color_index != 0xffff)
+ {
+ if (!funcs->custom_palette_color (data, color_index, &color))
+ {
+ unsigned int clen = 1;
+ hb_face_t *face = hb_font_get_face (font);
+
+ hb_ot_color_palette_get_colors (face, palette_index, color_index, &clen, &color);
+ }
+
+ *is_foreground = false;
+ }
+
+ return HB_COLOR (hb_color_get_blue (color),
+ hb_color_get_green (color),
+ hb_color_get_red (color),
+ hb_color_get_alpha (color) * alpha);
+ }
+
+ inline void recurse (const Paint &paint);
+};
+
struct hb_colrv1_closure_context_t :
hb_dispatch_context_t<hb_colrv1_closure_context_t>
{
@@ -98,7 +169,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_ = HB_COLRV1_MAX_NESTING_LEVEL) :
+ unsigned nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
base (base_),
glyphs (glyphs_),
layer_indices (layer_indices_),
@@ -160,6 +231,8 @@ struct BaseGlyphRecord
template <typename T>
struct Variable
{
+ static constexpr bool is_variable = true;
+
Variable<T>* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
@@ -182,6 +255,23 @@ struct Variable
return_trace (c->check_struct (this) && value.sanitize (c));
}
+ void paint_glyph (hb_paint_context_t *c) const
+ {
+ value.paint_glyph (c, varIdxBase);
+ }
+
+ void get_color_stop (hb_paint_context_t *c,
+ hb_color_stop_t *stop,
+ const VarStoreInstancer &instancer) const
+ {
+ value.get_color_stop (c, stop, varIdxBase, instancer);
+ }
+
+ hb_paint_extend_t get_extend () const
+ {
+ return value.get_extend ();
+ }
+
protected:
T value;
public:
@@ -193,6 +283,8 @@ struct Variable
template <typename T>
struct NoVariable
{
+ static constexpr bool is_variable = false;
+
static constexpr uint32_t varIdxBase = VarIdx::NO_VARIATION;
NoVariable<T>* copy (hb_serialize_context_t *c) const
@@ -216,6 +308,23 @@ struct NoVariable
return_trace (c->check_struct (this) && value.sanitize (c));
}
+ void paint_glyph (hb_paint_context_t *c) const
+ {
+ value.paint_glyph (c, varIdxBase);
+ }
+
+ void get_color_stop (hb_paint_context_t *c,
+ hb_color_stop_t *stop,
+ const VarStoreInstancer &instancer) const
+ {
+ value.get_color_stop (c, stop, VarIdx::NO_VARIATION, instancer);
+ }
+
+ hb_paint_extend_t get_extend () const
+ {
+ return value.get_extend ();
+ }
+
T value;
public:
DEFINE_SIZE_STATIC (T::static_size);
@@ -233,7 +342,7 @@ struct ColorStop
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),
+ return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes.get (paletteIndex),
HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
@@ -243,6 +352,17 @@ struct ColorStop
return_trace (c->check_struct (this));
}
+ void get_color_stop (hb_paint_context_t *c,
+ hb_color_stop_t *out,
+ uint32_t varIdx,
+ const VarStoreInstancer &instancer) const
+ {
+ out->offset = stopOffset.to_float(instancer (varIdx, 0));
+ out->color = c->get_color (paletteIndex,
+ alpha.to_float (instancer (varIdx, 1)),
+ &out->is_foreground);
+ }
+
F2DOT14 stopOffset;
HBUINT16 paletteIndex;
F2DOT14 alpha;
@@ -294,6 +414,52 @@ struct ColorLine
stops.sanitize (c));
}
+ /* get up to count stops from start */
+ unsigned int
+ get_color_stops (hb_paint_context_t *c,
+ unsigned int start,
+ unsigned int *count,
+ hb_color_stop_t *color_stops,
+ const VarStoreInstancer &instancer) const
+ {
+ unsigned int len = stops.len;
+
+ if (count && color_stops)
+ {
+ unsigned int i;
+ for (i = 0; i < *count && start + i < len; i++)
+ stops[start + i].get_color_stop (c, &color_stops[i], instancer);
+ *count = i;
+ }
+
+ return len;
+ }
+
+ HB_INTERNAL static unsigned int static_get_color_stops (hb_color_line_t *color_line,
+ void *color_line_data,
+ unsigned int start,
+ unsigned int *count,
+ hb_color_stop_t *color_stops,
+ void *user_data)
+ {
+ const ColorLine *thiz = (const ColorLine *) color_line_data;
+ hb_paint_context_t *c = (hb_paint_context_t *) user_data;
+ return thiz->get_color_stops (c, start, count, color_stops, c->instancer);
+ }
+
+ hb_paint_extend_t get_extend () const
+ {
+ return (hb_paint_extend_t) (unsigned int) extend;
+ }
+
+ HB_INTERNAL static hb_paint_extend_t static_get_extend (hb_color_line_t *color_line,
+ void *color_line_data,
+ void *user_data)
+ {
+ const ColorLine *thiz = (const ColorLine *) color_line_data;
+ return thiz->get_extend ();
+ }
+
Extend extend;
Array16Of<Var<ColorStop>> stops;
public:
@@ -357,6 +523,17 @@ struct Affine2x3
return_trace (c->check_struct (this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ c->funcs->push_transform (c->data,
+ xx.to_float (c->instancer (varIdxBase, 0)),
+ yx.to_float (c->instancer (varIdxBase, 1)),
+ xy.to_float (c->instancer (varIdxBase, 2)),
+ yy.to_float (c->instancer (varIdxBase, 3)),
+ dx.to_float (c->instancer (varIdxBase, 4)),
+ dy.to_float (c->instancer (varIdxBase, 5)));
+ }
+
F16DOT16 xx;
F16DOT16 yx;
F16DOT16 xy;
@@ -376,7 +553,7 @@ struct PaintColrLayers
TRACE_SUBSET (this);
auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (false);
- return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers->get (firstLayerIndex),
+ return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers.get (firstLayerIndex),
HB_SERIALIZE_ERROR_INT_OVERFLOW));
return_trace (true);
@@ -388,6 +565,8 @@ struct PaintColrLayers
return_trace (c->check_struct (this));
}
+ inline void paint_glyph (hb_paint_context_t *c) const;
+
HBUINT8 format; /* format = 1 */
HBUINT8 numLayers;
HBUINT32 firstLayerIndex; /* index into COLRv1::layerList */
@@ -405,7 +584,7 @@ struct PaintSolid
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),
+ return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes.get (paletteIndex),
HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
@@ -415,6 +594,17 @@ struct PaintSolid
return_trace (c->check_struct (this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ hb_bool_t is_foreground;
+ hb_color_t color;
+
+ color = c->get_color (paletteIndex,
+ alpha.to_float (c->instancer (varIdxBase, 0)),
+ &is_foreground);
+ c->funcs->color (c->data, is_foreground, color);
+ }
+
HBUINT8 format; /* format = 2(noVar) or 3(Var)*/
HBUINT16 paletteIndex;
F2DOT14 alpha;
@@ -443,6 +633,23 @@ struct PaintLinearGradient
return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ hb_color_line_t cl = {
+ (void *) &(this+colorLine),
+ (this+colorLine).static_get_color_stops, c,
+ (this+colorLine).static_get_extend, nullptr
+ };
+
+ c->funcs->linear_gradient (c->data, &cl,
+ x0 + c->instancer (varIdxBase, 0),
+ y0 + c->instancer (varIdxBase, 1),
+ x1 + c->instancer (varIdxBase, 2),
+ y1 + c->instancer (varIdxBase, 3),
+ x2 + c->instancer (varIdxBase, 4),
+ y2 + c->instancer (varIdxBase, 5));
+ }
+
HBUINT8 format; /* format = 4(noVar) or 5 (Var) */
Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintLinearGradient
* table) to ColorLine subtable. */
@@ -477,6 +684,23 @@ struct PaintRadialGradient
return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ hb_color_line_t cl = {
+ (void *) &(this+colorLine),
+ (this+colorLine).static_get_color_stops, c,
+ (this+colorLine).static_get_extend, nullptr
+ };
+
+ c->funcs->radial_gradient (c->data, &cl,
+ x0 + c->instancer (varIdxBase, 0),
+ y0 + c->instancer (varIdxBase, 1),
+ radius0 + c->instancer (varIdxBase, 2),
+ x1 + c->instancer (varIdxBase, 3),
+ y1 + c->instancer (varIdxBase, 4),
+ radius1 + c->instancer (varIdxBase, 5));
+ }
+
HBUINT8 format; /* format = 6(noVar) or 7 (Var) */
Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintRadialGradient
* table) to ColorLine subtable. */
@@ -511,6 +735,21 @@ struct PaintSweepGradient
return_trace (c->check_struct (this) && colorLine.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ hb_color_line_t cl = {
+ (void *) &(this+colorLine),
+ (this+colorLine).static_get_color_stops, c,
+ (this+colorLine).static_get_extend, nullptr
+ };
+
+ c->funcs->sweep_gradient (c->data, &cl,
+ centerX + c->instancer (varIdxBase, 0),
+ centerY + c->instancer (varIdxBase, 1),
+ (startAngle.to_float (c->instancer (varIdxBase, 2)) + 1) * (float) M_PI,
+ (endAngle.to_float (c->instancer (varIdxBase, 3)) + 1) * (float) M_PI);
+ }
+
HBUINT8 format; /* format = 8(noVar) or 9 (Var) */
Offset24To<ColorLine<Var>> colorLine; /* Offset (from beginning of PaintSweepGradient
* table) to ColorLine subtable. */
@@ -522,8 +761,6 @@ struct PaintSweepGradient
DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size + 2 * F2DOT14::static_size);
};
-struct Paint;
-
// Paint a non-COLR glyph, filled as indicated by paint.
struct PaintGlyph
{
@@ -548,6 +785,17 @@ struct PaintGlyph
return_trace (c->check_struct (this) && paint.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c) const
+ {
+ c->funcs->push_inverse_root_transform (c->data, c->font);
+ c->funcs->push_clip_glyph (c->data, gid, c->font);
+ c->funcs->push_root_transform (c->data, c->font);
+ c->recurse (this+paint);
+ c->funcs->pop_transform (c->data);
+ c->funcs->pop_clip (c->data);
+ c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 10 */
Offset24To<Paint> paint; /* Offset (from beginning of PaintGlyph table) to Paint subtable. */
HBUINT16 gid;
@@ -575,6 +823,8 @@ struct PaintColrGlyph
return_trace (c->check_struct (this));
}
+ inline void paint_glyph (hb_paint_context_t *c) const;
+
HBUINT8 format; /* format = 11 */
HBUINT16 gid;
public:
@@ -603,6 +853,13 @@ struct PaintTransform
transform.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c) const
+ {
+ (this+transform).paint_glyph (c);
+ c->recurse (this+src);
+ c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 12(noVar) or 13 (Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */
Offset24To<Var<Affine2x3>> transform;
@@ -629,6 +886,16 @@ struct PaintTranslate
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ float ddx = dx + c->instancer (varIdxBase, 0);
+ float ddy = dy + c->instancer (varIdxBase, 1);
+
+ bool p1 = c->funcs->push_translate (c->data, ddx, ddy);
+ c->recurse (this+src);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 14(noVar) or 15 (Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */
FWORD dx;
@@ -656,6 +923,16 @@ struct PaintScale
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ float sx = scaleX.to_float (c->instancer (varIdxBase, 0));
+ float sy = scaleY.to_float (c->instancer (varIdxBase, 1));
+
+ bool p1 = c->funcs->push_scale (c->data, sx, sy);
+ c->recurse (this+src);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 16 (noVar) or 17(Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintScale table) to Paint subtable. */
F2DOT14 scaleX;
@@ -683,6 +960,22 @@ struct PaintScaleAroundCenter
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ float sx = scaleX.to_float (c->instancer (varIdxBase, 0));
+ float sy = scaleY.to_float (c->instancer (varIdxBase, 1));
+ float tCenterX = centerX + c->instancer (varIdxBase, 2);
+ float tCenterY = centerY + c->instancer (varIdxBase, 3);
+
+ bool p1 = c->funcs->push_translate (c->data, +tCenterX, +tCenterY);
+ bool p2 = c->funcs->push_scale (c->data, sx, sy);
+ bool p3 = c->funcs->push_translate (c->data, -tCenterX, -tCenterY);
+ c->recurse (this+src);
+ if (p3) c->funcs->pop_transform (c->data);
+ if (p2) c->funcs->pop_transform (c->data);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 18 (noVar) or 19(Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintScaleAroundCenter table) to Paint subtable. */
F2DOT14 scaleX;
@@ -712,6 +1005,15 @@ struct PaintScaleUniform
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ float s = scale.to_float (c->instancer (varIdxBase, 0));
+
+ bool p1 = c->funcs->push_scale (c->data, s, s);
+ c->recurse (this+src);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 20 (noVar) or 21(Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintScaleUniform table) to Paint subtable. */
F2DOT14 scale;
@@ -738,6 +1040,21 @@ struct PaintScaleUniformAroundCenter
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ float s = scale.to_float (c->instancer (varIdxBase, 0));
+ float tCenterX = centerX + c->instancer (varIdxBase, 1);
+ float tCenterY = centerY + c->instancer (varIdxBase, 2);
+
+ bool p1 = c->funcs->push_translate (c->data, +tCenterX, +tCenterY);
+ bool p2 = c->funcs->push_scale (c->data, s, s);
+ bool p3 = c->funcs->push_translate (c->data, -tCenterX, -tCenterY);
+ c->recurse (this+src);
+ if (p3) c->funcs->pop_transform (c->data);
+ if (p2) c->funcs->pop_transform (c->data);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 22 (noVar) or 23(Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintScaleUniformAroundCenter table) to Paint subtable. */
F2DOT14 scale;
@@ -766,6 +1083,15 @@ struct PaintRotate
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ float a = angle.to_float (c->instancer (varIdxBase, 0));
+
+ bool p1 = c->funcs->push_rotate (c->data, a);
+ c->recurse (this+src);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 24 (noVar) or 25(Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */
F2DOT14 angle;
@@ -792,6 +1118,21 @@ struct PaintRotateAroundCenter
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ float a = angle.to_float (c->instancer (varIdxBase, 0));
+ float tCenterX = centerX + c->instancer (varIdxBase, 1);
+ float tCenterY = centerY + c->instancer (varIdxBase, 2);
+
+ bool p1 = c->funcs->push_translate (c->data, +tCenterX, +tCenterY);
+ bool p2 = c->funcs->push_rotate (c->data, a);
+ bool p3 = c->funcs->push_translate (c->data, -tCenterX, -tCenterY);
+ c->recurse (this+src);
+ if (p3) c->funcs->pop_transform (c->data);
+ if (p2) c->funcs->pop_transform (c->data);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 26 (noVar) or 27(Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintRotateAroundCenter table) to Paint subtable. */
F2DOT14 angle;
@@ -820,6 +1161,16 @@ struct PaintSkew
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ float sx = xSkewAngle.to_float(c->instancer (varIdxBase, 0));
+ float sy = ySkewAngle.to_float(c->instancer (varIdxBase, 1));
+
+ bool p1 = c->funcs->push_skew (c->data, sx, sy);
+ c->recurse (this+src);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 28(noVar) or 29 (Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */
F2DOT14 xSkewAngle;
@@ -847,6 +1198,22 @@ struct PaintSkewAroundCenter
return_trace (c->check_struct (this) && src.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
+ {
+ float sx = xSkewAngle.to_float(c->instancer (varIdxBase, 0));
+ float sy = ySkewAngle.to_float(c->instancer (varIdxBase, 1));
+ float tCenterX = centerX + c->instancer (varIdxBase, 2);
+ float tCenterY = centerY + c->instancer (varIdxBase, 3);
+
+ bool p1 = c->funcs->push_translate (c->data, +tCenterX, +tCenterY);
+ bool p2 = c->funcs->push_skew (c->data, sx, sy);
+ bool p3 = c->funcs->push_translate (c->data, -tCenterX, -tCenterY);
+ c->recurse (this+src);
+ if (p3) c->funcs->pop_transform (c->data);
+ if (p2) c->funcs->pop_transform (c->data);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+
HBUINT8 format; /* format = 30(noVar) or 31 (Var) */
Offset24To<Paint> src; /* Offset (from beginning of PaintSkewAroundCenter table) to Paint subtable. */
F2DOT14 xSkewAngle;
@@ -879,6 +1246,14 @@ struct PaintComposite
backdrop.sanitize (c, this));
}
+ void paint_glyph (hb_paint_context_t *c) const
+ {
+ c->recurse (this+backdrop);
+ c->funcs->push_group (c->data);
+ c->recurse (this+src);
+ c->funcs->pop_group (c->data, (hb_paint_composite_mode_t) (int) mode);
+ }
+
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 */
@@ -948,8 +1323,8 @@ struct ClipBox
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
@@ -1084,7 +1459,7 @@ struct ClipList
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_set_t& glyphset = c->plan->_glyphset_colred;
const hb_map_t &glyph_map = *c->plan->glyph_map;
hb_map_t new_gid_offset_map;
@@ -1142,7 +1517,7 @@ struct Paint
{
TRACE_SANITIZE (this);
- if (unlikely (!c->check_start_recursion (HB_COLRV1_MAX_NESTING_LEVEL)))
+ if (unlikely (!c->check_start_recursion (HB_MAX_NESTING_LEVEL)))
return_trace (c->no_dispatch_return_value ());
return_trace (c->end_recursion (this->dispatch (c, std::forward<Ts> (ds)...)));
@@ -1151,8 +1526,8 @@ struct Paint
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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, std::forward<Ts> (ds)...));
case 2: return_trace (c->dispatch (u.paintformat2, std::forward<Ts> (ds)...));
@@ -1194,35 +1569,35 @@ struct Paint
union {
HBUINT8 format;
PaintColrLayers paintformat1;
- PaintSolid paintformat2;
+ NoVariable<PaintSolid> paintformat2;
Variable<PaintSolid> paintformat3;
- PaintLinearGradient<NoVariable> paintformat4;
+ NoVariable<PaintLinearGradient<NoVariable>> paintformat4;
Variable<PaintLinearGradient<Variable>> paintformat5;
- PaintRadialGradient<NoVariable> paintformat6;
+ NoVariable<PaintRadialGradient<NoVariable>> paintformat6;
Variable<PaintRadialGradient<Variable>> paintformat7;
- PaintSweepGradient<NoVariable> paintformat8;
+ NoVariable<PaintSweepGradient<NoVariable>> paintformat8;
Variable<PaintSweepGradient<Variable>> paintformat9;
PaintGlyph paintformat10;
PaintColrGlyph paintformat11;
PaintTransform<NoVariable> paintformat12;
PaintTransform<Variable> paintformat13;
- PaintTranslate paintformat14;
+ NoVariable<PaintTranslate> paintformat14;
Variable<PaintTranslate> paintformat15;
- PaintScale paintformat16;
+ NoVariable<PaintScale> paintformat16;
Variable<PaintScale> paintformat17;
- PaintScaleAroundCenter paintformat18;
+ NoVariable<PaintScaleAroundCenter> paintformat18;
Variable<PaintScaleAroundCenter> paintformat19;
- PaintScaleUniform paintformat20;
+ NoVariable<PaintScaleUniform> paintformat20;
Variable<PaintScaleUniform> paintformat21;
- PaintScaleUniformAroundCenter paintformat22;
+ NoVariable<PaintScaleUniformAroundCenter> paintformat22;
Variable<PaintScaleUniformAroundCenter> paintformat23;
- PaintRotate paintformat24;
+ NoVariable<PaintRotate> paintformat24;
Variable<PaintRotate> paintformat25;
- PaintRotateAroundCenter paintformat26;
+ NoVariable<PaintRotateAroundCenter> paintformat26;
Variable<PaintRotateAroundCenter> paintformat27;
- PaintSkew paintformat28;
+ NoVariable<PaintSkew> paintformat28;
Variable<PaintSkew> paintformat29;
- PaintSkewAroundCenter paintformat30;
+ NoVariable<PaintSkewAroundCenter> paintformat30;
Variable<PaintSkewAroundCenter> paintformat31;
PaintComposite paintformat32;
} u;
@@ -1269,7 +1644,7 @@ struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
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_colred;
+ const hb_set_t* glyphset = &c->plan->_glyphset_colred;
for (const auto& _ : as_array ())
{
@@ -1323,7 +1698,14 @@ struct COLR
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
- bool has_data () const { return numBaseGlyphs; }
+ bool has_v0_data () const { return numBaseGlyphs; }
+ bool has_v1_data () const
+ {
+ if (version == 1)
+ return (this+baseGlyphList).len > 0;
+
+ return false;
+ }
unsigned int get_glyph_layers (hb_codepoint_t glyph,
unsigned int start_offset,
@@ -1503,7 +1885,7 @@ 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;
+ const hb_set_t& glyphset = c->plan->_glyphset_colred;
auto base_it =
+ hb_range (c->plan->num_output_glyphs ())
@@ -1552,7 +1934,7 @@ struct COLR
if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid)))
return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
out_layers[i].glyphId = new_gid;
- out_layers[i].colorIdx = c->plan->colr_palettes->get (layers[i].colorIdx);
+ out_layers[i].colorIdx = c->plan->colr_palettes.get (layers[i].colorIdx);
}
return hb_pair_t<bool, hb_vector_t<LayerRecord>> (true, out_layers);
@@ -1585,10 +1967,23 @@ struct COLR
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
+ colr_prime->varStore.serialize_copy (c->serializer, varStore, this);
return_trace (true);
}
+ const Paint *get_base_glyph_paint (hb_codepoint_t glyph) const
+ {
+ const BaseGlyphList &baseglyph_paintrecords = this+baseGlyphList;
+ const BaseGlyphPaintRecord* record = get_base_glyph_paintrecord (glyph);
+ if (record)
+ {
+ const Paint &paint = &baseglyph_paintrecords+record->paint;
+ return &paint;
+ }
+ else
+ return nullptr;
+ }
+
bool
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
{
@@ -1599,14 +1994,138 @@ struct COLR
this+varIdxMap,
hb_array (font->coords, font->num_coords));
- if ((this+clipList).get_extents (glyph,
- extents,
- instancer))
+ if (get_clip (glyph, extents, instancer))
{
- extents->x_bearing = font->em_scale_x (extents->x_bearing);
- extents->y_bearing = font->em_scale_x (extents->y_bearing);
- extents->width = font->em_scale_x (extents->width);
- extents->height = font->em_scale_x (extents->height);
+ font->scale_glyph_extents (extents);
+ return true;
+ }
+
+ auto *extents_funcs = hb_paint_extents_get_funcs ();
+ hb_paint_extents_context_t extents_data;
+ bool ret = paint_glyph (font, glyph, extents_funcs, &extents_data, 0, HB_COLOR(0,0,0,0));
+
+ hb_extents_t e = extents_data.get_extents ();
+ if (e.is_void ())
+ {
+ extents->x_bearing = 0;
+ extents->y_bearing = 0;
+ extents->width = 0;
+ extents->height = 0;
+ }
+ else
+ {
+ extents->x_bearing = e.xmin;
+ extents->y_bearing = e.ymax;
+ extents->width = e.xmax - e.xmin;
+ extents->height = e.ymin - e.ymax;
+ }
+
+ return ret;
+ }
+
+ bool
+ has_paint_for_glyph (hb_codepoint_t glyph) const
+ {
+ if (version == 1)
+ {
+ const Paint *paint = get_base_glyph_paint (glyph);
+
+ return paint != nullptr;
+ }
+
+ return false;
+ }
+
+ bool get_clip (hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ const VarStoreInstancer instancer) const
+ {
+ return (this+clipList).get_extents (glyph,
+ extents,
+ instancer);
+ }
+
+ bool
+ paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const
+ {
+ VarStoreInstancer instancer (this+varStore,
+ this+varIdxMap,
+ hb_array (font->coords, font->num_coords));
+ hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
+
+ if (version == 1)
+ {
+ const Paint *paint = get_base_glyph_paint (glyph);
+ if (paint)
+ {
+ // COLRv1 glyph
+
+ VarStoreInstancer instancer (this+varStore,
+ this+varIdxMap,
+ hb_array (font->coords, font->num_coords));
+
+ bool is_bounded = true;
+ if (clip)
+ {
+ hb_glyph_extents_t extents;
+ if (get_clip (glyph, &extents, instancer))
+ {
+ font->scale_glyph_extents (&extents);
+ c.funcs->push_clip_rectangle (c.data,
+ extents.x_bearing,
+ extents.y_bearing + extents.height,
+ extents.x_bearing + extents.width,
+ extents.y_bearing);
+ }
+ else
+ {
+ auto *extents_funcs = hb_paint_extents_get_funcs ();
+ hb_paint_extents_context_t extents_data;
+
+ paint_glyph (font, glyph,
+ extents_funcs, &extents_data,
+ palette_index, foreground,
+ false);
+
+ hb_extents_t extents = extents_data.get_extents ();
+ is_bounded = extents_data.is_bounded ();
+
+ c.funcs->push_clip_rectangle (c.data,
+ extents.xmin,
+ extents.ymin,
+ extents.xmax,
+ extents.ymax);
+ }
+ }
+
+ c.funcs->push_root_transform (c.data, font);
+
+ if (is_bounded)
+ c.recurse (*paint);
+
+ c.funcs->pop_transform (c.data);
+
+ if (clip)
+ c.funcs->pop_clip (c.data);
+
+ return true;
+ }
+ }
+
+ const BaseGlyphRecord *record = get_base_glyph_record (glyph);
+ if (record && ((hb_codepoint_t) record->glyphId == glyph))
+ {
+ // COLRv0 glyph
+ for (const auto &r : (this+layersZ).as_array (numLayers)
+ .sub_array (record->firstLayerIdx, record->numLayers))
+ {
+ hb_bool_t is_foreground;
+ hb_color_t color = c.get_color (r.colorIdx, 1., &is_foreground);
+ c.funcs->push_clip_glyph (c.data, r.glyphId, c.font);
+ c.funcs->color (c.data, is_foreground, color);
+ c.funcs->pop_clip (c.data);
+ }
+
return true;
}
@@ -1635,7 +2154,50 @@ struct COLR_accelerator_t : COLR::accelerator_t {
COLR_accelerator_t (hb_face_t *face) : COLR::accelerator_t (face) {}
};
-} /* namespace OT */
+void
+hb_paint_context_t::recurse (const Paint &paint)
+{
+ if (unlikely (depth_left <= 0 || edge_count <= 0)) return;
+ depth_left--;
+ edge_count--;
+ paint.dispatch (this);
+ depth_left++;
+}
+
+void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const
+{
+ const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
+ for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
+ {
+ const Paint &paint = paint_offset_lists.get_paint (i);
+ c->funcs->push_group (c->data);
+ c->recurse (paint);
+ c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
+ }
+}
+
+void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
+{
+ const COLR *colr_table = c->get_colr_table ();
+ const Paint *paint = colr_table->get_base_glyph_paint (gid);
+ hb_glyph_extents_t extents = {0};
+ bool has_clip_box = colr_table->get_clip (gid, &extents, c->instancer);
+
+ if (has_clip_box)
+ c->funcs->push_clip_rectangle (c->data,
+ extents.x_bearing,
+ extents.y_bearing + extents.height,
+ extents.x_bearing + extents.width,
+ extents.y_bearing);
+
+ if (paint)
+ c->recurse (*paint);
+
+ if (has_clip_box)
+ c->funcs->pop_clip (c->data);
+}
+
+} /* namespace OT */
-#endif /* HB_OT_COLOR_COLR_TABLE_HH */
+#endif /* OT_COLOR_COLR_COLR_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colrv1-closure.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/colrv1-closure.hh
index fbaf2ec26b..705863d4ad 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-colrv1-closure.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/colrv1-closure.hh
@@ -24,12 +24,11 @@
*
*/
-#ifndef HB_OT_COLR_COLRV1_CLOSURE_HH
-#define HB_OT_COLR_COLRV1_CLOSURE_HH
+#ifndef OT_COLOR_COLR_COLRV1_CLOSURE_HH
+#define OT_COLOR_COLR_COLRV1_CLOSURE_HH
-#include "hb-open-type.hh"
-#include "hb-ot-layout-common.hh"
-#include "hb-ot-color-colr-table.hh"
+#include "../../../hb-open-type.hh"
+#include "COLR.hh"
/*
* COLR -- Color
@@ -105,4 +104,4 @@ HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) cons
} /* namespace OT */
-#endif /* HB_OT_COLR_COLRV1_CLOSURE_HH */
+#endif /* OT_COLOR_COLR_COLRV1_CLOSURE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-cpal-table.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/CPAL/CPAL.hh
index bcab77f79d..4914a0ed57 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-cpal-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/CPAL/CPAL.hh
@@ -25,12 +25,12 @@
* Google Author(s): Sascha Brawer
*/
-#ifndef HB_OT_COLOR_CPAL_TABLE_HH
-#define HB_OT_COLOR_CPAL_TABLE_HH
+#ifndef OT_COLOR_CPAL_CPAL_HH
+#define OT_COLOR_CPAL_CPAL_HH
-#include "hb-open-type.hh"
-#include "hb-ot-color.h"
-#include "hb-ot-name.h"
+#include "../../../hb-open-type.hh"
+#include "../../../hb-ot-color.h"
+#include "../../../hb-ot-name.h"
/*
@@ -239,7 +239,7 @@ struct CPAL
TRACE_SUBSET (this);
if (!numPalettes) return_trace (false);
- const hb_map_t *color_index_map = c->plan->colr_palettes;
+ const hb_map_t *color_index_map = &c->plan->colr_palettes;
if (color_index_map->is_empty ()) return_trace (false);
hb_set_t retained_color_indices;
@@ -319,4 +319,4 @@ struct CPAL
} /* namespace OT */
-#endif /* HB_OT_COLOR_CPAL_TABLE_HH */
+#endif /* OT_COLOR_CPAL_CPAL_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-sbix-table.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh
index d0e2235fb2..46ad3fd58e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-sbix-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh
@@ -25,11 +25,11 @@
* Google Author(s): Calder Kitagawa
*/
-#ifndef HB_OT_COLOR_SBIX_TABLE_HH
-#define HB_OT_COLOR_SBIX_TABLE_HH
+#ifndef OT_COLOR_SBIX_SBIX_HH
+#define OT_COLOR_SBIX_SBIX_HH
-#include "hb-open-type.hh"
-#include "hb-ot-layout-common.hh"
+#include "../../../hb-open-type.hh"
+#include "../../../hb-paint.hh"
/*
* sbix -- Standard Bitmap Graphics
@@ -213,10 +213,11 @@ struct sbix
bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
- hb_glyph_extents_t *extents) const
+ hb_glyph_extents_t *extents,
+ bool scale = true) const
{
/* We only support PNG right now, and following function checks type. */
- return get_png_extents (font, glyph, extents);
+ return get_png_extents (font, glyph, extents, scale);
}
hb_blob_t *reference_png (hb_font_t *font,
@@ -231,6 +232,37 @@ struct sbix
num_glyphs, available_ppem);
}
+ bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
+ {
+ if (!has_data ())
+ return false;
+
+ int x_offset = 0, y_offset = 0;
+ unsigned int strike_ppem = 0;
+ hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
+ hb_glyph_extents_t extents;
+ hb_glyph_extents_t pixel_extents;
+
+ if (blob == hb_blob_get_empty ())
+ return false;
+
+ if (!hb_font_get_glyph_extents (font, glyph, &extents))
+ return false;
+
+ if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
+ return false;
+
+ bool ret = funcs->image (data,
+ blob,
+ pixel_extents.width, -pixel_extents.height,
+ HB_PAINT_IMAGE_FORMAT_PNG,
+ font->slant_xy,
+ &extents);
+
+ hb_blob_destroy (blob);
+ return ret;
+ }
+
private:
const SBIXStrike &choose_strike (hb_font_t *font) const
@@ -285,7 +317,8 @@ struct sbix
bool get_png_extents (hb_font_t *font,
hb_codepoint_t glyph,
- hb_glyph_extents_t *extents) const
+ hb_glyph_extents_t *extents,
+ bool scale = true) const
{
/* Following code is safe to call even without data.
* But faster to short-circuit. */
@@ -310,22 +343,18 @@ struct sbix
extents->height = -1 * png.IHDR.height;
/* Convert to font units. */
- if (strike_ppem)
+ if (strike_ppem && scale)
{
float scale = font->face->get_upem () / (float) strike_ppem;
- extents->x_bearing = font->em_scalef_x (extents->x_bearing * scale);
- extents->y_bearing = font->em_scalef_y (extents->y_bearing * scale);
- extents->width = font->em_scalef_x (extents->width * scale);
- extents->height = font->em_scalef_y (extents->height * scale);
- }
- else
- {
- extents->x_bearing = font->em_scale_x (extents->x_bearing);
- extents->y_bearing = font->em_scale_y (extents->y_bearing);
- extents->width = font->em_scale_x (extents->width);
- extents->height = font->em_scale_y (extents->height);
+ extents->x_bearing = roundf (extents->x_bearing * scale);
+ extents->y_bearing = roundf (extents->y_bearing * scale);
+ extents->width = roundf (extents->width * scale);
+ extents->height = roundf (extents->height * scale);
}
+ if (scale)
+ font->scale_glyph_extents (extents);
+
hb_blob_destroy (blob);
return strike_ppem;
@@ -420,4 +449,4 @@ struct sbix_accelerator_t : sbix::accelerator_t {
} /* namespace OT */
-#endif /* HB_OT_COLOR_SBIX_TABLE_HH */
+#endif /* OT_COLOR_SBIX_SBIX_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-svg-table.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/svg/svg.hh
index fc649f1006..c7d91b88ee 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color-svg-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/svg/svg.hh
@@ -22,10 +22,12 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#ifndef HB_OT_COLOR_SVG_TABLE_HH
-#define HB_OT_COLOR_SVG_TABLE_HH
+#ifndef OT_COLOR_SVG_SVG_HH
+#define OT_COLOR_SVG_SVG_HH
-#include "hb-open-type.hh"
+#include "../../../hb-open-type.hh"
+#include "../../../hb-blob.hh"
+#include "../../../hb-paint.hh"
/*
* SVG -- SVG (Scalable Vector Graphics)
@@ -91,8 +93,31 @@ struct SVG
bool has_data () const { return table->has_data (); }
+ bool paint_glyph (hb_font_t *font HB_UNUSED, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
+ {
+ if (!has_data ())
+ return false;
+
+ hb_blob_t *blob = reference_blob_for_glyph (glyph);
+
+ if (blob == hb_blob_get_empty ())
+ return false;
+
+ funcs->image (data,
+ blob,
+ 0, 0,
+ HB_PAINT_IMAGE_FORMAT_SVG,
+ font->slant_xy,
+ nullptr);
+
+ hb_blob_destroy (blob);
+ return true;
+ }
+
private:
hb_blob_ptr_t<SVG> table;
+ public:
+ DEFINE_SIZE_STATIC (sizeof (hb_blob_ptr_t<SVG>));
};
const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
@@ -123,4 +148,4 @@ struct SVG_accelerator_t : SVG::accelerator_t {
} /* namespace OT */
-#endif /* HB_OT_COLOR_SVG_TABLE_HH */
+#endif /* OT_COLOR_SVG_SVG_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh
index fbd7c642ab..d35654e245 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh
@@ -147,6 +147,7 @@ struct Coverage
TRACE_SUBSET (this);
auto it =
+ iter ()
+ | hb_take (c->plan->source->get_num_glyphs ())
| hb_filter (c->plan->glyph_map_gsub)
| hb_map_retains_sorting (c->plan->glyph_map_gsub)
;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh
new file mode 100644
index 0000000000..0551fcf812
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh
@@ -0,0 +1,918 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef OT_LAYOUT_GDEF_GDEF_HH
+#define OT_LAYOUT_GDEF_GDEF_HH
+
+#include "../../../hb-ot-layout-common.hh"
+
+#include "../../../hb-font.hh"
+
+
+namespace OT {
+
+
+/*
+ * Attachment List Table
+ */
+
+/* Array of contour point indices--in increasing numerical order */
+struct AttachPoint : Array16Of<HBUINT16>
+{
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ return_trace (out->serialize (c->serializer, + iter ()));
+ }
+};
+
+struct AttachList
+{
+ unsigned int get_attach_points (hb_codepoint_t glyph_id,
+ unsigned int start_offset,
+ unsigned int *point_count /* IN/OUT */,
+ unsigned int *point_array /* OUT */) const
+ {
+ unsigned int index = (this+coverage).get_coverage (glyph_id);
+ if (index == NOT_COVERED)
+ {
+ if (point_count)
+ *point_count = 0;
+ return 0;
+ }
+
+ const AttachPoint &points = this+attachPoint[index];
+
+ if (point_count)
+ {
+ + points.as_array ().sub_array (start_offset, point_count)
+ | hb_sink (hb_array (point_array, *point_count))
+ ;
+ }
+
+ return points.len;
+ }
+
+ 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);
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, attachPoint)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (subset_offset_array (c, out->attachPoint, 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) && attachPoint.sanitize (c, this));
+ }
+
+ protected:
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table -- from
+ * beginning of AttachList table */
+ Array16OfOffset16To<AttachPoint>
+ attachPoint; /* Array of AttachPoint tables
+ * in Coverage Index order */
+ public:
+ DEFINE_SIZE_ARRAY (4, attachPoint);
+};
+
+/*
+ * Ligature Caret Table
+ */
+
+struct CaretValueFormat1
+{
+ friend struct CaretValue;
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+ return_trace (true);
+ }
+
+ private:
+ hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
+ {
+ return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ protected:
+ HBUINT16 caretValueFormat; /* Format identifier--format = 1 */
+ FWORD coordinate; /* X or Y value, in design units */
+ public:
+ DEFINE_SIZE_STATIC (4);
+};
+
+struct CaretValueFormat2
+{
+ friend struct CaretValue;
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+ return_trace (true);
+ }
+
+ private:
+ hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
+ {
+ hb_position_t x, y;
+ font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y);
+ return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ protected:
+ HBUINT16 caretValueFormat; /* Format identifier--format = 2 */
+ HBUINT16 caretValuePoint; /* Contour point index on glyph */
+ public:
+ DEFINE_SIZE_STATIC (4);
+};
+
+struct CaretValueFormat3
+{
+ friend struct CaretValue;
+
+ hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,
+ const VariationStore &var_store) const
+ {
+ return HB_DIRECTION_IS_HORIZONTAL (direction) ?
+ font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
+ font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out)) return_trace (false);
+ if (!c->serializer->embed (caretValueFormat)) return_trace (false);
+ if (!c->serializer->embed (coordinate)) return_trace (false);
+
+ unsigned varidx = (this+deviceTable).get_variation_index ();
+ if (c->plan->layout_variation_idx_delta_map.has (varidx))
+ {
+ int delta = hb_second (c->plan->layout_variation_idx_delta_map.get (varidx));
+ if (delta != 0)
+ {
+ if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+ }
+ }
+
+ if (c->plan->all_axes_pinned)
+ return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
+
+ if (!c->serializer->embed (deviceTable))
+ return_trace (false);
+
+ return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out),
+ hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map));
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ { (this+deviceTable).collect_variation_indices (c); }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
+ }
+
+ protected:
+ HBUINT16 caretValueFormat; /* Format identifier--format = 3 */
+ FWORD coordinate; /* X or Y value, in design units */
+ Offset16To<Device>
+ deviceTable; /* Offset to Device table for X or Y
+ * value--from beginning of CaretValue
+ * table */
+ public:
+ DEFINE_SIZE_STATIC (6);
+};
+
+struct CaretValue
+{
+ hb_position_t get_caret_value (hb_font_t *font,
+ hb_direction_t direction,
+ hb_codepoint_t glyph_id,
+ const VariationStore &var_store) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.get_caret_value (font, direction);
+ case 2: return u.format2.get_caret_value (font, direction, glyph_id);
+ case 3: return u.format3.get_caret_value (font, direction, var_store);
+ default:return 0;
+ }
+ }
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
+ TRACE_DISPATCH (this, u.format);
+ 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)...));
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ switch (u.format) {
+ case 1:
+ case 2:
+ return;
+ case 3:
+ u.format3.collect_variation_indices (c);
+ return;
+ default: return;
+ }
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.format.sanitize (c)) return_trace (false);
+ switch (u.format) {
+ case 1: return_trace (u.format1.sanitize (c));
+ case 2: return_trace (u.format2.sanitize (c));
+ case 3: return_trace (u.format3.sanitize (c));
+ default:return_trace (true);
+ }
+ }
+
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ CaretValueFormat1 format1;
+ CaretValueFormat2 format2;
+ CaretValueFormat3 format3;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (2, format);
+};
+
+struct LigGlyph
+{
+ unsigned get_lig_carets (hb_font_t *font,
+ hb_direction_t direction,
+ hb_codepoint_t glyph_id,
+ const VariationStore &var_store,
+ unsigned start_offset,
+ unsigned *caret_count /* IN/OUT */,
+ hb_position_t *caret_array /* OUT */) const
+ {
+ if (caret_count)
+ {
+ + carets.as_array ().sub_array (start_offset, caret_count)
+ | hb_map (hb_add (this))
+ | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); })
+ | hb_sink (hb_array (caret_array, *caret_count))
+ ;
+ }
+
+ return carets.len;
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ + hb_iter (carets)
+ | hb_apply (subset_offset_array (c, out->carets, this))
+ ;
+
+ return_trace (bool (out->carets));
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ for (const Offset16To<CaretValue>& offset : carets.iter ())
+ (this+offset).collect_variation_indices (c);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (carets.sanitize (c, this));
+ }
+
+ protected:
+ Array16OfOffset16To<CaretValue>
+ carets; /* Offset array of CaretValue tables
+ * --from beginning of LigGlyph table
+ * --in increasing coordinate order */
+ public:
+ DEFINE_SIZE_ARRAY (2, carets);
+};
+
+struct LigCaretList
+{
+ unsigned int get_lig_carets (hb_font_t *font,
+ hb_direction_t direction,
+ hb_codepoint_t glyph_id,
+ const VariationStore &var_store,
+ unsigned int start_offset,
+ unsigned int *caret_count /* IN/OUT */,
+ hb_position_t *caret_array /* OUT */) const
+ {
+ unsigned int index = (this+coverage).get_coverage (glyph_id);
+ if (index == NOT_COVERED)
+ {
+ if (caret_count)
+ *caret_count = 0;
+ return 0;
+ }
+ const LigGlyph &lig_glyph = this+ligGlyph[index];
+ return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_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);
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, ligGlyph)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (subset_offset_array (c, out->ligGlyph, this), hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
+ return_trace (bool (new_coverage));
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+coverage, ligGlyph)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); })
+ ;
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
+ }
+
+ protected:
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of LigCaretList table */
+ Array16OfOffset16To<LigGlyph>
+ ligGlyph; /* Array of LigGlyph tables
+ * in Coverage Index order */
+ public:
+ DEFINE_SIZE_ARRAY (4, ligGlyph);
+};
+
+
+struct MarkGlyphSetsFormat1
+{
+ bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+ { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ bool ret = true;
+ for (const Offset32To<Coverage>& offset : coverage.iter ())
+ {
+ auto *o = out->coverage.serialize_append (c->serializer);
+ if (unlikely (!o))
+ {
+ ret = false;
+ break;
+ }
+
+ //not using o->serialize_subset (c, offset, this, out) here because
+ //OTS doesn't allow null offset.
+ //See issue: https://github.com/khaledhosny/ots/issues/172
+ c->serializer->push ();
+ c->dispatch (this+offset);
+ c->serializer->add_link (*o, c->serializer->pop_pack ());
+ }
+
+ return_trace (ret && out->coverage.len);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this));
+ }
+
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Array16Of<Offset32To<Coverage>>
+ coverage; /* Array of long offsets to mark set
+ * coverage tables */
+ public:
+ DEFINE_SIZE_ARRAY (4, coverage);
+};
+
+struct MarkGlyphSets
+{
+ bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.covers (set_index, glyph_id);
+ default:return false;
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ switch (u.format) {
+ case 1: return_trace (u.format1.subset (c));
+ default:return_trace (false);
+ }
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.format.sanitize (c)) return_trace (false);
+ switch (u.format) {
+ case 1: return_trace (u.format1.sanitize (c));
+ default:return_trace (true);
+ }
+ }
+
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkGlyphSetsFormat1 format1;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (2, format);
+};
+
+
+/*
+ * GDEF -- Glyph Definition
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef
+ */
+
+
+template <typename Types>
+struct GDEFVersion1_2
+{
+ friend struct GDEF;
+
+ protected:
+ FixedVersion<>version; /* Version of the GDEF table--currently
+ * 0x00010003u */
+ typename Types::template OffsetTo<ClassDef>
+ glyphClassDef; /* Offset to class definition table
+ * for glyph type--from beginning of
+ * GDEF header (may be Null) */
+ typename Types::template OffsetTo<AttachList>
+ attachList; /* Offset to list of glyphs with
+ * attachment points--from beginning
+ * of GDEF header (may be Null) */
+ typename Types::template OffsetTo<LigCaretList>
+ ligCaretList; /* Offset to list of positioning points
+ * for ligature carets--from beginning
+ * of GDEF header (may be Null) */
+ typename Types::template OffsetTo<ClassDef>
+ markAttachClassDef; /* Offset to class definition table for
+ * mark attachment type--from beginning
+ * of GDEF header (may be Null) */
+ typename Types::template OffsetTo<MarkGlyphSets>
+ markGlyphSetsDef; /* Offset to the table of mark set
+ * definitions--from beginning of GDEF
+ * header (may be NULL). Introduced
+ * in version 0x00010002. */
+ Offset32To<VariationStore>
+ varStore; /* Offset to the table of Item Variation
+ * Store--from beginning of GDEF
+ * header (may be NULL). Introduced
+ * in version 0x00010003. */
+ public:
+ DEFINE_SIZE_MIN (4 + 4 * Types::size);
+
+ unsigned int get_size () const
+ {
+ return min_size +
+ (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
+ (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (version.sanitize (c) &&
+ glyphClassDef.sanitize (c, this) &&
+ attachList.sanitize (c, this) &&
+ ligCaretList.sanitize (c, this) &&
+ markAttachClassDef.sanitize (c, this) &&
+ (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
+ (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
+ bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
+ bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
+ bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
+
+ bool subset_markglyphsetsdef = false;
+ if (version.to_int () >= 0x00010002u)
+ {
+ subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
+ }
+
+ bool subset_varstore = false;
+ if (version.to_int () >= 0x00010003u)
+ {
+ if (c->plan->all_axes_pinned)
+ out->varStore = 0;
+ else
+ subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ());
+ }
+
+ if (subset_varstore)
+ {
+ out->version.minor = 3;
+ } else if (subset_markglyphsetsdef) {
+ out->version.minor = 2;
+ } else {
+ out->version.minor = 0;
+ }
+
+ return_trace (subset_glyphclassdef || subset_attachlist ||
+ subset_ligcaretlist || subset_markattachclassdef ||
+ (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||
+ (out->version.to_int () >= 0x00010003u && subset_varstore));
+ }
+};
+
+struct GDEF
+{
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
+
+ enum GlyphClasses {
+ UnclassifiedGlyph = 0,
+ BaseGlyph = 1,
+ LigatureGlyph = 2,
+ MarkGlyph = 3,
+ ComponentGlyph = 4
+ };
+
+ unsigned int get_size () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.get_size ();
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.get_size ();
+#endif
+ default: return u.version.static_size;
+ }
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!u.version.sanitize (c))) return_trace (false);
+ switch (u.version.major) {
+ case 1: return_trace (u.version1.sanitize (c));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return_trace (u.version2.sanitize (c));
+#endif
+ default: return_trace (true);
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.subset (c);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.subset (c);
+#endif
+ default: return false;
+ }
+ }
+
+ bool has_glyph_classes () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.glyphClassDef != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.glyphClassDef != 0;
+#endif
+ default: return false;
+ }
+ }
+ const ClassDef &get_glyph_class_def () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.glyphClassDef;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.glyphClassDef;
+#endif
+ default: return Null(ClassDef);
+ }
+ }
+ bool has_attach_list () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.attachList != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.attachList != 0;
+#endif
+ default: return false;
+ }
+ }
+ const AttachList &get_attach_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.attachList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.attachList;
+#endif
+ default: return Null(AttachList);
+ }
+ }
+ bool has_lig_carets () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.ligCaretList != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.ligCaretList != 0;
+#endif
+ default: return false;
+ }
+ }
+ const LigCaretList &get_lig_caret_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.ligCaretList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.ligCaretList;
+#endif
+ default: return Null(LigCaretList);
+ }
+ }
+ bool has_mark_attachment_types () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.markAttachClassDef != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.markAttachClassDef != 0;
+#endif
+ default: return false;
+ }
+ }
+ const ClassDef &get_mark_attach_class_def () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.markAttachClassDef;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.markAttachClassDef;
+#endif
+ default: return Null(ClassDef);
+ }
+ }
+ bool has_mark_glyph_sets () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.markGlyphSetsDef != 0;
+#endif
+ default: return false;
+ }
+ }
+ const MarkGlyphSets &get_mark_glyph_sets () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.markGlyphSetsDef;
+#endif
+ default: return Null(MarkGlyphSets);
+ }
+ }
+ bool has_var_store () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.varStore != 0;
+#endif
+ default: return false;
+ }
+ }
+ const VariationStore &get_var_store () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.varStore;
+#endif
+ default: return Null(VariationStore);
+ }
+ }
+
+
+ bool has_data () const { return u.version.to_int (); }
+ unsigned int get_glyph_class (hb_codepoint_t glyph) const
+ { return get_glyph_class_def ().get_class (glyph); }
+ void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
+ { get_glyph_class_def ().collect_class (glyphs, klass); }
+
+ unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
+ { return get_mark_attach_class_def ().get_class (glyph); }
+
+ unsigned int get_attach_points (hb_codepoint_t glyph_id,
+ unsigned int start_offset,
+ unsigned int *point_count /* IN/OUT */,
+ unsigned int *point_array /* OUT */) const
+ { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); }
+
+ unsigned int get_lig_carets (hb_font_t *font,
+ hb_direction_t direction,
+ hb_codepoint_t glyph_id,
+ unsigned int start_offset,
+ unsigned int *caret_count /* IN/OUT */,
+ hb_position_t *caret_array /* OUT */) const
+ { return get_lig_caret_list ().get_lig_carets (font,
+ direction, glyph_id, get_var_store(),
+ start_offset, caret_count, caret_array); }
+
+ bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+ { return get_mark_glyph_sets ().covers (set_index, glyph_id); }
+
+ /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
+ * glyph class and other bits, and high 8-bit the mark attachment type (if any).
+ * Not to be confused with lookup_props which is very similar. */
+ unsigned int get_glyph_props (hb_codepoint_t glyph) const
+ {
+ unsigned int klass = get_glyph_class (glyph);
+
+ static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), "");
+ static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), "");
+ static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), "");
+
+ switch (klass) {
+ default: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
+ case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
+ case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
+ case MarkGlyph:
+ klass = get_mark_attachment_type (glyph);
+ return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8);
+ }
+ }
+
+ HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
+ struct accelerator_t
+ {
+ accelerator_t (hb_face_t *face)
+ {
+ table = hb_sanitize_context_t ().reference_table<GDEF> (face);
+ if (unlikely (table->is_blocklisted (table.get_blob (), face)))
+ {
+ hb_blob_destroy (table.get_blob ());
+ table = hb_blob_get_empty ();
+ }
+ }
+ ~accelerator_t () { table.destroy (); }
+
+ hb_blob_ptr_t<GDEF> table;
+ };
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ { get_lig_caret_list ().collect_variation_indices (c); }
+
+ void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
+ hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const
+ {
+ if (!has_var_store ()) return;
+ if (layout_variation_indices->is_empty ()) return;
+
+ unsigned new_major = 0, new_minor = 0;
+ unsigned last_major = (layout_variation_indices->get_min ()) >> 16;
+ for (unsigned idx : layout_variation_indices->iter ())
+ {
+ uint16_t major = idx >> 16;
+ if (major >= get_var_store ().get_sub_table_count ()) break;
+ if (major != last_major)
+ {
+ new_minor = 0;
+ ++new_major;
+ }
+
+ unsigned new_idx = (new_major << 16) + new_minor;
+ if (!layout_variation_idx_delta_map->has (idx))
+ continue;
+ int delta = hb_second (layout_variation_idx_delta_map->get (idx));
+
+ layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
+ ++new_minor;
+ last_major = major;
+ }
+ }
+
+ protected:
+ union {
+ FixedVersion<> version; /* Version identifier */
+ GDEFVersion1_2<SmallTypes> version1;
+#ifndef HB_NO_BEYOND_64K
+ GDEFVersion1_2<MediumTypes> version2;
+#endif
+ } u;
+ public:
+ DEFINE_SIZE_MIN (4);
+};
+
+struct GDEF_accelerator_t : GDEF::accelerator_t {
+ GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {}
+};
+
+} /* namespace OT */
+
+
+#endif /* OT_LAYOUT_GDEF_GDEF_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh
index 2e30ab33c3..e7e3c5c6d1 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh
@@ -51,9 +51,9 @@ struct AnchorFormat3
if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
- if (c->plan->layout_variation_idx_delta_map->has (x_varidx))
+ if (c->plan->layout_variation_idx_delta_map.has (x_varidx))
{
- int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (x_varidx));
+ int delta = hb_second (c->plan->layout_variation_idx_delta_map.get (x_varidx));
if (delta != 0)
{
if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
@@ -63,9 +63,9 @@ struct AnchorFormat3
}
unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
- if (c->plan->layout_variation_idx_delta_map->has (y_varidx))
+ if (c->plan->layout_variation_idx_delta_map.has (y_varidx))
{
- int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (y_varidx));
+ int delta = hb_second (c->plan->layout_variation_idx_delta_map.get (y_varidx));
if (delta != 0)
{
if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
@@ -80,8 +80,8 @@ struct AnchorFormat3
if (!c->serializer->embed (xDeviceTable)) return_trace (false);
if (!c->serializer->embed (yDeviceTable)) return_trace (false);
- out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map);
- out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map);
+ out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
+ out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
return_trace (out);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh
index c105cfb091..0105a9b854 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh
@@ -19,8 +19,8 @@ struct CursivePos
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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 ());
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
index 7f58fac8b8..ff255e090a 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
@@ -143,7 +143,7 @@ struct CursivePosFormat1
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "cursive attaching glyph at %d to glyph at %d",
+ "cursive attaching glyph at %u to glyph at %u",
i, j);
}
@@ -241,7 +241,7 @@ struct CursivePosFormat1
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "cursive attached glyph at %d to glyph at %d",
+ "cursive attached glyph at %u to glyph at %u",
i, j);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
index cb5e8b2689..ff43ffb8c5 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
@@ -42,7 +42,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "attaching mark glyph at %d to glyph at %d",
+ "attaching mark glyph at %u to glyph at %u",
c->buffer->idx, glyph_pos);
}
@@ -56,7 +56,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "attached mark glyph at %d to glyph at %d",
+ "attached mark glyph at %u to glyph at %u",
c->buffer->idx, glyph_pos);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh
index edf7099c07..cd2fc7ccfd 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh
@@ -22,8 +22,8 @@ struct MarkBasePos
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
#ifndef HB_NO_BEYOND_64K
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
index ebb8c31c67..eb4712049b 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
@@ -90,6 +90,25 @@ struct MarkBasePosFormat1_2
const Coverage &get_coverage () const { return this+markCoverage; }
+ static inline bool accept (hb_buffer_t *buffer, unsigned idx)
+ {
+ /* We only want to attach to the first of a MultipleSubst sequence.
+ * https://github.com/harfbuzz/harfbuzz/issues/740
+ * Reject others...
+ * ...but stop if we find a mark in the MultipleSubst sequence:
+ * https://github.com/harfbuzz/harfbuzz/issues/1020 */
+ return !_hb_glyph_info_multiplied (&buffer->info[idx]) ||
+ 0 == _hb_glyph_info_get_lig_comp (&buffer->info[idx]) ||
+ (idx == 0 ||
+ _hb_glyph_info_is_mark (&buffer->info[idx - 1]) ||
+ !_hb_glyph_info_multiplied (&buffer->info[idx - 1]) ||
+ _hb_glyph_info_get_lig_id (&buffer->info[idx]) !=
+ _hb_glyph_info_get_lig_id (&buffer->info[idx - 1]) ||
+ _hb_glyph_info_get_lig_comp (&buffer->info[idx]) !=
+ _hb_glyph_info_get_lig_comp (&buffer->info[idx - 1]) + 1
+ );
+ }
+
bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
@@ -97,48 +116,54 @@ struct MarkBasePosFormat1_2
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
if (likely (mark_index == NOT_COVERED)) return_trace (false);
- /* Now we search backwards for a non-mark glyph */
+ /* Now we search backwards for a non-mark glyph.
+ * We don't use skippy_iter.prev() to avoid O(n^2) behavior. */
+
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);
- do {
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
+
+ if (c->last_base_until > buffer->idx)
+ {
+ c->last_base_until = 0;
+ c->last_base = -1;
+ }
+ unsigned j;
+ for (j = buffer->idx; j > c->last_base_until; j--)
+ {
+ auto match = skippy_iter.match (buffer->info[j - 1]);
+ if (match == skippy_iter.MATCH)
+ {
+ // https://github.com/harfbuzz/harfbuzz/issues/4124
+ if (!accept (buffer, j - 1) &&
+ NOT_COVERED == (this+baseCoverage).get_coverage (buffer->info[j - 1].codepoint))
+ match = skippy_iter.SKIP;
+ }
+ if (match == skippy_iter.MATCH)
{
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
+ c->last_base = (signed) j - 1;
+ break;
}
+ }
+ c->last_base_until = buffer->idx;
+ if (c->last_base == -1)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (0, 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...
- * ...but stop if we find a mark in the MultipleSubst sequence:
- * https://github.com/harfbuzz/harfbuzz/issues/1020 */
- if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
- 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
- (skippy_iter.idx == 0 ||
- _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
- !_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx - 1]) ||
- _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
- _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
- _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
- _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
- ))
- break;
- skippy_iter.reject ();
- } while (true);
+ unsigned idx = (unsigned) c->last_base;
/* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
- //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
+ //if (!_hb_glyph_info_is_base_glyph (&buffer->info[idx])) { return_trace (false); }
- unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
+ unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[idx].codepoint);
if (base_index == NOT_COVERED)
{
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
return_trace (false);
}
- return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
+ return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, idx));
}
bool subset (hb_subset_context_t *c) const
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh
index 09152fd876..739c325411 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh
@@ -22,8 +22,8 @@ struct MarkLigPos
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
#ifndef HB_NO_BEYOND_64K
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
index 1a8021237e..7e7b438aa7 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
@@ -100,20 +100,37 @@ struct MarkLigPosFormat1_2
if (likely (mark_index == NOT_COVERED)) return_trace (false);
/* Now we search backwards for a non-mark glyph */
+
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);
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
+
+ if (c->last_base_until > buffer->idx)
{
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ c->last_base_until = 0;
+ c->last_base = -1;
+ }
+ unsigned j;
+ for (j = buffer->idx; j > c->last_base_until; j--)
+ {
+ auto match = skippy_iter.match (buffer->info[j - 1]);
+ if (match == skippy_iter.MATCH)
+ {
+ c->last_base = (signed) j - 1;
+ break;
+ }
+ }
+ c->last_base_until = buffer->idx;
+ if (c->last_base == -1)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
return_trace (false);
}
+ j = (unsigned) c->last_base;
+
/* 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); }
+ //if (!_hb_glyph_info_is_ligature (&buffer->info[j])) { 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)
{
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh
index 4118fc304f..cddd2a3d50 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh
@@ -22,8 +22,8 @@ struct MarkMarkPos
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
#ifndef HB_NO_BEYOND_64K
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh
index 9823768cbc..c13d4f4894 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh
@@ -25,8 +25,8 @@ struct PairPos
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
index 9c9b268889..b4a9a9ad53 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
@@ -43,7 +43,7 @@ struct PairPosFormat1_3
{
valueFormat,
len1,
- 1 + len1 + len2
+ PairSet::get_size (len1, len2)
};
return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
@@ -177,9 +177,7 @@ struct PairPosFormat1_3
hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
{
- unsigned len1 = valueFormat[0].get_len ();
- unsigned len2 = valueFormat[1].get_len ();
- unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+ unsigned record_size = PairSet::get_size (valueFormat);
unsigned format1 = 0;
unsigned format2 = 0;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
index 9c87ac2b03..de15a29e3c 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
@@ -49,7 +49,7 @@ struct PairPosFormat2_4
unsigned int len1 = valueFormat1.get_len ();
unsigned int len2 = valueFormat2.get_len ();
- unsigned int stride = len1 + len2;
+ unsigned int stride = HBUINT16::static_size * (len1 + len2);
unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
return_trace (c->check_range ((const void *) values,
@@ -220,7 +220,7 @@ struct PairPosFormat2_4
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "try kerning glyphs at %d,%d",
+ "try kerning glyphs at %u,%u",
c->buffer->idx, skippy_iter.idx);
}
@@ -231,14 +231,14 @@ struct PairPosFormat2_4
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "kerned glyphs at %d,%d",
+ "kerned glyphs at %u,%u",
c->buffer->idx, skippy_iter.idx);
}
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "tried kerning glyphs at %d,%d",
+ "tried kerning glyphs at %u,%u",
c->buffer->idx, skippy_iter.idx);
}
@@ -298,8 +298,8 @@ struct PairPosFormat2_4
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
{
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
- valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], c->plan->layout_variation_idx_delta_map);
- valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], c->plan->layout_variation_idx_delta_map);
+ valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], &c->plan->layout_variation_idx_delta_map);
+ valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &c->plan->layout_variation_idx_delta_map);
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
index a318f39913..147b8e00ea 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
@@ -24,11 +24,22 @@ struct PairSet
public:
DEFINE_SIZE_MIN (2);
+ static unsigned get_size (unsigned len1, unsigned len2)
+ {
+ return Types::HBGlyphID::static_size + Value::static_size * (len1 + len2);
+ }
+ static unsigned get_size (const ValueFormat valueFormats[2])
+ {
+ unsigned len1 = valueFormats[0].get_len ();
+ unsigned len2 = valueFormats[1].get_len ();
+ return get_size (len1, len2);
+ }
+
struct sanitize_closure_t
{
const ValueFormat *valueFormats;
unsigned int len1; /* valueFormats[0].get_len() */
- unsigned int stride; /* 1 + len1 + len2 */
+ unsigned int stride; /* bytes */
};
bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
@@ -37,7 +48,6 @@ struct PairSet
if (!(c->check_struct (this)
&& c->check_range (&firstPairValueRecord,
len,
- HBUINT16::static_size,
closure->stride))) return_trace (false);
unsigned int count = len;
@@ -49,9 +59,7 @@ struct PairSet
bool intersects (const hb_set_t *glyphs,
const ValueFormat *valueFormats) const
{
- unsigned int len1 = valueFormats[0].get_len ();
- unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+ unsigned record_size = get_size (valueFormats);
const PairValueRecord *record = &firstPairValueRecord;
unsigned int count = len;
@@ -67,9 +75,7 @@ struct PairSet
void collect_glyphs (hb_collect_glyphs_context_t *c,
const ValueFormat *valueFormats) const
{
- unsigned int len1 = valueFormats[0].get_len ();
- unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+ unsigned record_size = get_size (valueFormats);
const PairValueRecord *record = &firstPairValueRecord;
c->input->add_array (&record->secondGlyph, len, record_size);
@@ -78,9 +84,7 @@ struct PairSet
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
const ValueFormat *valueFormats) const
{
- unsigned len1 = valueFormats[0].get_len ();
- unsigned len2 = valueFormats[1].get_len ();
- unsigned record_size = HBUINT16::static_size * (1 + len1 + len2);
+ unsigned record_size = get_size (valueFormats);
const PairValueRecord *record = &firstPairValueRecord;
unsigned count = len;
@@ -101,7 +105,7 @@ struct PairSet
hb_buffer_t *buffer = c->buffer;
unsigned int len1 = valueFormats[0].get_len ();
unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+ unsigned record_size = get_size (len1, len2);
const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
&firstPairValueRecord,
@@ -112,7 +116,7 @@ struct PairSet
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "try kerning glyphs at %d,%d",
+ "try kerning glyphs at %u,%u",
c->buffer->idx, pos);
}
@@ -123,14 +127,14 @@ struct PairSet
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "kerned glyphs at %d,%d",
+ "kerned glyphs at %u,%u",
c->buffer->idx, pos);
}
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "tried kerning glyphs at %d,%d",
+ "tried kerning glyphs at %u,%u",
c->buffer->idx, pos);
}
@@ -168,7 +172,7 @@ struct PairSet
unsigned len1 = valueFormats[0].get_len ();
unsigned len2 = valueFormats[1].get_len ();
- unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+ unsigned record_size = get_size (len1, len2);
typename PairValueRecord::context_t context =
{
@@ -177,7 +181,7 @@ struct PairSet
newFormats,
len1,
&glyph_map,
- c->plan->layout_variation_idx_delta_map
+ &c->plan->layout_variation_idx_delta_map
};
const PairValueRecord *record = &firstPairValueRecord;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh
index 6dce3e6343..3af6c49965 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh
@@ -72,8 +72,8 @@ struct SinglePos
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
index b4c9fc3db0..f7a170f34e 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
@@ -63,7 +63,7 @@ struct SinglePosFormat1
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "positioning glyph at %d",
+ "positioning glyph at %u",
c->buffer->idx);
}
@@ -72,7 +72,7 @@ struct SinglePosFormat1
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "positioned glyph at %d",
+ "positioned glyph at %u",
c->buffer->idx);
}
@@ -144,7 +144,7 @@ struct SinglePosFormat1
;
bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
+ SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
return_trace (ret);
}
};
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
index c77951156b..e8f2d7c2c6 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
@@ -73,7 +73,7 @@ struct SinglePosFormat2
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "positioning glyph at %d",
+ "positioning glyph at %u",
c->buffer->idx);
}
@@ -84,7 +84,7 @@ struct SinglePosFormat2
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "positioned glyph at %d",
+ "positioned glyph at %u",
c->buffer->idx);
}
@@ -163,7 +163,7 @@ struct SinglePosFormat2
;
bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
+ SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
return_trace (ret);
}
};
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
index 26a40f01a3..1aa451abcc 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
@@ -371,7 +371,7 @@ struct ValueFormat : HBUINT16
for (unsigned int i = 0; i < count; i++) {
if (!sanitize_value_devices (c, base, values))
return_trace (false);
- values += stride;
+ values = &StructAtOffset<const Value> (values, stride);
}
return_trace (true);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh
index 6c50c9717a..b4466119be 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh
@@ -61,7 +61,7 @@ struct AlternateSet
{
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "replacing glyph at %d (alternate substitution)",
+ "replacing glyph at %u (alternate substitution)",
c->buffer->idx);
}
@@ -70,8 +70,8 @@ struct AlternateSet
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "replaced glyph at %d (alternate substitution)",
- c->buffer->idx - 1);
+ "replaced glyph at %u (alternate substitution)",
+ c->buffer->idx - 1u);
}
return_trace (true);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh
index 9d7cd6fddf..04a052a783 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh
@@ -23,8 +23,8 @@ struct AlternateSubst
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
#ifndef HB_NO_BEYOND_64K
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
index cdb35f525b..ffe39d52ab 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
@@ -69,7 +69,7 @@ struct Ligature
{
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "replacing glyph at %d (ligature substitution)",
+ "replacing glyph at %u (ligature substitution)",
c->buffer->idx);
}
@@ -78,8 +78,8 @@ struct Ligature
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "replaced glyph at %d (ligature substitution)",
- c->buffer->idx - 1);
+ "replaced glyph at %u (ligature substitution)",
+ c->buffer->idx - 1u);
}
return_trace (true);
@@ -138,7 +138,7 @@ struct Ligature
{
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "ligated glyph at %d",
+ "ligated glyph at %u",
pos);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh
index 7ba19e844c..18f6e35581 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh
@@ -23,8 +23,8 @@ struct LigatureSubst
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
#ifndef HB_NO_BEYOND_64K
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh
index 95710ed2be..742c8587ee 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh
@@ -24,8 +24,8 @@ struct MultipleSubst
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
#ifndef HB_NO_BEYOND_64K
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
index 48e208efb9..5ad463fea7 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
@@ -20,8 +20,8 @@ struct ReverseChainSingleSubst
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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 ());
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
index a23e92028e..2c2e1aa44f 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
@@ -135,7 +135,7 @@ struct ReverseChainSingleSubstFormat1
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "replacing glyph at %d (reverse chaining substitution)",
+ "replacing glyph at %u (reverse chaining substitution)",
c->buffer->idx);
}
@@ -144,7 +144,7 @@ struct ReverseChainSingleSubstFormat1
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "replaced glyph at %d (reverse chaining substitution)",
+ "replaced glyph at %u (reverse chaining substitution)",
c->buffer->idx);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
index e2190078b8..ae3292f329 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
@@ -44,7 +44,7 @@ struct Sequence
{
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "replacing glyph at %d (multiple substitution)",
+ "replacing glyph at %u (multiple substitution)",
c->buffer->idx);
}
@@ -53,8 +53,8 @@ struct Sequence
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "replaced glyph at %d (multiple subtitution)",
- c->buffer->idx - 1);
+ "replaced glyph at %u (multiple subtitution)",
+ c->buffer->idx - 1u);
}
return_trace (true);
@@ -67,7 +67,7 @@ struct Sequence
{
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "deleting glyph at %d (multiple substitution)",
+ "deleting glyph at %u (multiple substitution)",
c->buffer->idx);
}
@@ -77,7 +77,7 @@ struct Sequence
{
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "deleted glyph at %d (multiple substitution)",
+ "deleted glyph at %u (multiple substitution)",
c->buffer->idx);
}
@@ -88,7 +88,7 @@ struct Sequence
{
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "multiplying glyph at %d",
+ "multiplying glyph at %u",
c->buffer->idx);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh
index 7da8103168..4529927ba6 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh
@@ -27,8 +27,8 @@ struct SingleSubst
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh
index 1be21b98bc..78725352c2 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh
@@ -103,7 +103,7 @@ struct SingleSubstFormat1_3
{
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "replacing glyph at %d (single substitution)",
+ "replacing glyph at %u (single substitution)",
c->buffer->idx);
}
@@ -112,8 +112,8 @@ struct SingleSubstFormat1_3
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "replaced glyph at %d (single substitution)",
- c->buffer->idx - 1);
+ "replaced glyph at %u (single substitution)",
+ c->buffer->idx - 1u);
}
return_trace (true);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh
index 01df714525..17aa087363 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh
@@ -87,7 +87,7 @@ struct SingleSubstFormat2_4
{
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "replacing glyph at %d (single substitution)",
+ "replacing glyph at %u (single substitution)",
c->buffer->idx);
}
@@ -96,8 +96,8 @@ struct SingleSubstFormat2_4
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
{
c->buffer->message (c->font,
- "replaced glyph at %d (single substitution)",
- c->buffer->idx - 1);
+ "replaced glyph at %u (single substitution)",
+ c->buffer->idx - 1u);
}
return_trace (true);
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
index b7215b0170..5574ae0722 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
@@ -18,11 +18,6 @@ struct glyf_accelerator_t;
namespace glyf_impl {
-#ifndef HB_GLYF_MAX_POINTS
-#define HB_GLYF_MAX_POINTS 10000
-#endif
-
-
enum phantom_point_index_t
{
PHANTOM_LEFT = 0,
@@ -85,28 +80,38 @@ struct Glyph
}
void update_mtx (const hb_subset_plan_t *plan,
- int xMin, int yMax,
+ int xMin, int xMax,
+ int yMin, int yMax,
const contour_point_vector_t &all_points) const
{
hb_codepoint_t new_gid = 0;
if (!plan->new_gid_for_old_gid (gid, &new_gid))
return;
+ if (type != EMPTY)
+ {
+ plan->bounds_width_map.set (new_gid, xMax - xMin);
+ plan->bounds_height_map.set (new_gid, yMax - yMin);
+ }
+
unsigned len = all_points.length;
float leftSideX = all_points[len - 4].x;
float rightSideX = all_points[len - 3].x;
float topSideY = all_points[len - 2].y;
float bottomSideY = all_points[len - 1].y;
- int hori_aw = roundf (rightSideX - leftSideX);
+ signed hori_aw = roundf (rightSideX - leftSideX);
if (hori_aw < 0) hori_aw = 0;
int lsb = roundf (xMin - leftSideX);
- plan->hmtx_map->set (new_gid, hb_pair (hori_aw, lsb));
+ plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
+ //flag value should be computed using non-empty glyphs
+ if (type != EMPTY && lsb != xMin)
+ plan->head_maxp_info.allXMinIsLsb = false;
- int vert_aw = roundf (topSideY - bottomSideY);
+ signed vert_aw = roundf (topSideY - bottomSideY);
if (vert_aw < 0) vert_aw = 0;
int tsb = roundf (topSideY - yMax);
- plan->vmtx_map->set (new_gid, hb_pair (vert_aw, tsb));
+ plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
}
bool compile_header_bytes (const hb_subset_plan_t *plan,
@@ -114,7 +119,7 @@ struct Glyph
hb_bytes_t &dest_bytes /* OUT */) const
{
GlyphHeader *glyph_header = nullptr;
- if (type != EMPTY && all_points.length > 4)
+ if (!plan->pinned_at_default && type != EMPTY && all_points.length >= 4)
{
glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
if (unlikely (!glyph_header)) return false;
@@ -138,18 +143,33 @@ struct Glyph
yMax = hb_max (yMax, y);
}
- update_mtx (plan, roundf (xMin), roundf (yMax), all_points);
+ update_mtx (plan, roundf (xMin), roundf (xMax), roundf (yMin), roundf (yMax), all_points);
+
+ int rounded_xMin = roundf (xMin);
+ int rounded_xMax = roundf (xMax);
+ int rounded_yMin = roundf (yMin);
+ int rounded_yMax = roundf (yMax);
+
+ if (type != EMPTY)
+ {
+ plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, rounded_xMin);
+ plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, rounded_yMin);
+ plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, rounded_xMax);
+ plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, rounded_yMax);
+ }
- /*for empty glyphs: all_points only include phantom points.
- *just update metrics and then return */
+ /* when pinned at default, no need to compile glyph header
+ * and for empty glyphs: all_points only include phantom points.
+ * just update metrics and then return */
if (!glyph_header)
return true;
glyph_header->numberOfContours = header->numberOfContours;
- glyph_header->xMin = roundf (xMin);
- glyph_header->yMin = roundf (yMin);
- glyph_header->xMax = roundf (xMax);
- glyph_header->yMax = roundf (yMax);
+
+ glyph_header->xMin = rounded_xMin;
+ glyph_header->yMin = rounded_yMin;
+ glyph_header->xMax = rounded_xMax;
+ glyph_header->yMax = rounded_yMax;
dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size);
return true;
@@ -162,34 +182,54 @@ struct Glyph
hb_bytes_t &dest_end /* OUT */)
{
contour_point_vector_t all_points, deltas;
- if (!get_points (font, glyf, all_points, &deltas, false, false))
+ unsigned composite_contours = 0;
+ head_maxp_info_t *head_maxp_info_p = &plan->head_maxp_info;
+ unsigned *composite_contours_p = &composite_contours;
+
+ // don't compute head/maxp values when glyph has no contours(type is EMPTY)
+ // also ignore .notdef glyph when --notdef-outline is not enabled
+ if (type == EMPTY ||
+ (gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)))
+ {
+ head_maxp_info_p = nullptr;
+ composite_contours_p = nullptr;
+ }
+
+ if (!get_points (font, glyf, all_points, &deltas, head_maxp_info_p, composite_contours_p, false, false))
return false;
// .notdef, set type to empty so we only update metrics and don't compile bytes for
// it
if (gid == 0 &&
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+ {
type = EMPTY;
-
- switch (type) {
- case COMPOSITE:
- if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
- deltas,
- dest_end))
- return false;
- break;
- case SIMPLE:
- if (!SimpleGlyph (*header, bytes).compile_bytes_with_deltas (all_points,
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING,
- dest_end))
- return false;
- break;
- default:
- /* set empty bytes for empty glyph
- * do not use source glyph's pointers */
dest_start = hb_bytes_t ();
dest_end = hb_bytes_t ();
- break;
+ }
+
+ //dont compile bytes when pinned at default, just recalculate bounds
+ if (!plan->pinned_at_default) {
+ switch (type) {
+ case COMPOSITE:
+ if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
+ deltas,
+ dest_end))
+ return false;
+ break;
+ case SIMPLE:
+ if (!SimpleGlyph (*header, bytes).compile_bytes_with_deltas (all_points,
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING,
+ dest_end))
+ return false;
+ break;
+ default:
+ /* set empty bytes for empty glyph
+ * do not use source glyph's pointers */
+ dest_start = hb_bytes_t ();
+ dest_end = hb_bytes_t ();
+ break;
+ }
}
if (!compile_header_bytes (plan, all_points, dest_start))
@@ -208,13 +248,25 @@ struct Glyph
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
contour_point_vector_t &all_points /* OUT */,
contour_point_vector_t *deltas = nullptr, /* OUT */
+ head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
+ unsigned *composite_contours = nullptr, /* OUT */
bool shift_points_hori = true,
bool use_my_metrics = true,
bool phantom_only = false,
hb_array_t<int> coords = hb_array_t<int> (),
- unsigned int depth = 0) const
+ unsigned int depth = 0,
+ unsigned *edge_count = nullptr) const
{
if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
+ unsigned stack_edge_count = 0;
+ if (!edge_count) edge_count = &stack_edge_count;
+ if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false;
+ (*edge_count)++;
+
+ if (head_maxp_info)
+ {
+ head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
+ }
if (!coords)
coords = hb_array (font->coords, font->num_coords);
@@ -226,6 +278,10 @@ struct Glyph
switch (type) {
case SIMPLE:
+ if (depth == 0 && head_maxp_info)
+ head_maxp_info->maxContours = hb_max (head_maxp_info->maxContours, (unsigned) header->numberOfContours);
+ if (depth > 0 && composite_contours)
+ *composite_contours += (unsigned) header->numberOfContours;
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
return false;
break;
@@ -301,6 +357,8 @@ struct Glyph
switch (type) {
case SIMPLE:
+ if (depth == 0 && head_maxp_info)
+ head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, points.length - 4);
if (!inplace)
all_points.extend (points.as_array ());
break;
@@ -311,17 +369,19 @@ struct Glyph
for (auto &item : get_composite_iterator ())
{
comp_points.reset ();
-
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
.get_points (font,
glyf_accelerator,
comp_points,
deltas,
+ head_maxp_info,
+ composite_contours,
shift_points_hori,
use_my_metrics,
phantom_only,
coords,
- depth + 1)))
+ depth + 1,
+ edge_count)))
return false;
/* Copy phantom points from component if USE_MY_METRICS flag set */
@@ -357,6 +417,13 @@ struct Glyph
comp_index++;
}
+ if (head_maxp_info && depth == 0)
+ {
+ if (composite_contours)
+ head_maxp_info->maxCompositeContours = hb_max (head_maxp_info->maxCompositeContours, *composite_contours);
+ head_maxp_info->maxCompositePoints = hb_max (head_maxp_info->maxCompositePoints, all_points.length);
+ head_maxp_info->maxComponentElements = hb_max (head_maxp_info->maxComponentElements, comp_index);
+ }
all_points.extend (phantoms);
} break;
#ifndef HB_NO_VAR_COMPOSITES
@@ -370,7 +437,11 @@ struct Glyph
comp_points.reset ();
- coord_setter_t coord_setter (coords);
+ auto component_coords = coords;
+ if (item.is_reset_unspecified_axes ())
+ component_coords = hb_array<int> ();
+
+ coord_setter_t coord_setter (component_coords);
item.set_variations (coord_setter, record_points);
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
@@ -378,11 +449,14 @@ struct Glyph
glyf_accelerator,
comp_points,
deltas,
+ head_maxp_info,
+ nullptr,
shift_points_hori,
use_my_metrics,
phantom_only,
coord_setter.get_coords (),
- depth + 1)))
+ depth + 1,
+ edge_count)))
return false;
/* Apply component transformation */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/GlyphHeader.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/GlyphHeader.hh
index e4a9168b79..a43b6691ab 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/GlyphHeader.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/GlyphHeader.hh
@@ -21,10 +21,12 @@ struct GlyphHeader
/* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
int lsb = hb_min (xMin, xMax);
(void) glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb);
- extents->x_bearing = font->em_scale_x (lsb);
- extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
- extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
- extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
+ extents->x_bearing = lsb;
+ extents->y_bearing = hb_max (yMin, yMax);
+ extents->width = hb_max (xMin, xMax) - hb_min (xMin, xMax);
+ extents->height = hb_min (yMin, yMax) - hb_max (yMin, yMax);
+
+ font->scale_glyph_extents (extents);
return true;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh
index 2b4aa99d25..b6fefce1ac 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh
@@ -20,7 +20,7 @@ struct SimpleGlyph
FLAG_X_SAME = 0x10,
FLAG_Y_SAME = 0x20,
FLAG_OVERLAP_SIMPLE = 0x40,
- FLAG_RESERVED2 = 0x80
+ FLAG_CUBIC = 0x80
};
const GlyphHeader &header;
@@ -184,7 +184,7 @@ struct SimpleGlyph
if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false;
unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
- points_.alloc (num_points + 4); // Allocate for phantom points, to avoid a possible copy
+ points_.alloc (num_points + 4, true); // Allocate for phantom points, to avoid a possible copy
if (!points_.resize (num_points)) return false;
if (phantom_only) return true;
@@ -272,9 +272,9 @@ struct SimpleGlyph
unsigned num_points = all_points.length - 4;
hb_vector_t<uint8_t> flags, x_coords, y_coords;
- if (unlikely (!flags.alloc (num_points))) return false;
- if (unlikely (!x_coords.alloc (2*num_points))) return false;
- if (unlikely (!y_coords.alloc (2*num_points))) return false;
+ if (unlikely (!flags.alloc (num_points, true))) return false;
+ if (unlikely (!x_coords.alloc (2*num_points, true))) return false;
+ if (unlikely (!y_coords.alloc (2*num_points, true))) return false;
uint8_t lastflag = 255, repeat = 0;
int prev_x = 0, prev_y = 0;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh
index 1a0370c757..795925bba5 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh
@@ -21,22 +21,14 @@ struct SubsetGlyph
bool serialize (hb_serialize_context_t *c,
bool use_short_loca,
- const hb_subset_plan_t *plan,
- hb_font_t *font)
+ const hb_subset_plan_t *plan)
{
TRACE_SERIALIZE (this);
- if (font)
- {
- const OT::glyf_accelerator_t &glyf = *font->face->table.glyf;
- if (!this->compile_bytes_with_deltas (plan, font, glyf))
- return_trace (false);
- }
-
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 = 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);
+ DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
HBUINT8 pad;
pad = 0;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh
index 0f4c71c83d..3685da7913 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh
@@ -29,6 +29,7 @@ struct VarCompositeGlyphRecord
HAVE_TCENTER_Y = 0x0800,
GID_IS_24 = 0x1000,
AXES_HAVE_VARIATION = 0x2000,
+ RESET_UNSPECIFIED_AXES = 0x4000,
};
public:
@@ -60,6 +61,7 @@ struct VarCompositeGlyphRecord
bool has_more () const { return true; }
bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
+ bool is_reset_unspecified_axes () const { return flags & RESET_UNSPECIFIED_AXES; }
hb_codepoint_t get_gid () const
{
@@ -165,8 +167,8 @@ struct VarCompositeGlyphRecord
float translateX = 0.f;
float translateY = 0.f;
float rotation = 0.f;
- float scaleX = 1.f * (1 << 12);
- float scaleY = 1.f * (1 << 12);
+ float scaleX = 1.f * (1 << 10);
+ float scaleY = 1.f * (1 << 10);
float skewX = 0.f;
float skewY = 0.f;
float tCenterX = 0.f;
@@ -187,7 +189,7 @@ struct VarCompositeGlyphRecord
if (flags & AXES_HAVE_VARIATION)
{
for (unsigned i = 0; i < count; i++)
- rec_points[i].x = *q++;
+ rec_points[i].x = q++->to_int ();
rec_points += count;
}
else
@@ -197,11 +199,11 @@ struct VarCompositeGlyphRecord
if (flags & HAVE_TRANSLATE_X) translateX = * (const FWORD *) p++;
if (flags & HAVE_TRANSLATE_Y) translateY = * (const FWORD *) p++;
- if (flags & HAVE_ROTATION) rotation = * (const F2DOT14 *) p++;
- if (flags & HAVE_SCALE_X) scaleX = * (const F4DOT12 *) p++;
- if (flags & HAVE_SCALE_Y) scaleY = * (const F4DOT12 *) p++;
- if (flags & HAVE_SKEW_X) skewX = * (const F2DOT14 *) p++;
- if (flags & HAVE_SKEW_Y) skewY = * (const F2DOT14 *) p++;
+ if (flags & HAVE_ROTATION) rotation = ((const F4DOT12 *) p++)->to_int ();
+ if (flags & HAVE_SCALE_X) scaleX = ((const F6DOT10 *) p++)->to_int ();
+ if (flags & HAVE_SCALE_Y) scaleY = ((const F6DOT10 *) p++)->to_int ();
+ if (flags & HAVE_SKEW_X) skewX = ((const F4DOT12 *) p++)->to_int ();
+ if (flags & HAVE_SKEW_Y) skewY = ((const F4DOT12 *) p++)->to_int ();
if (flags & HAVE_TCENTER_X) tCenterX = * (const FWORD *) p++;
if (flags & HAVE_TCENTER_Y) tCenterY = * (const FWORD *) p++;
@@ -270,19 +272,19 @@ struct VarCompositeGlyphRecord
}
if (flags & HAVE_ROTATION)
{
- rotation = rec_points[0].x / (1 << 14);
+ rotation = rec_points[0].x / (1 << 12);
rec_points++;
}
if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))
{
- scaleX = rec_points[0].x / (1 << 12);
- scaleY = rec_points[0].y / (1 << 12);
+ scaleX = rec_points[0].x / (1 << 10);
+ scaleY = rec_points[0].y / (1 << 10);
rec_points++;
}
if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y))
{
- skewX = rec_points[0].x / (1 << 14);
- skewY = rec_points[0].y / (1 << 14);
+ skewX = rec_points[0].x / (1 << 12);
+ skewY = rec_points[0].y / (1 << 12);
rec_points++;
}
if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
@@ -316,9 +318,8 @@ struct VarCompositeGlyphRecord
{
unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++;
- signed v = have_variations ? rec_points[i].x : *a++;
+ signed v = have_variations ? rec_points[i].x : a++->to_int ();
- v += setter[axis_index];
v = hb_clamp (v, -(1<<14), (1<<14));
setter[axis_index] = v;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh
index 181c33d06d..30106b2b98 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh
@@ -25,7 +25,7 @@ _write_loca (IteratorIn&& it, bool short_offsets, IteratorOut&& dest)
| hb_map ([=, &offset] (unsigned int padded_size)
{
offset += padded_size;
- DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
+ DEBUG_MSG (SUBSET, nullptr, "loca entry offset %u", offset);
return offset >> right_shift;
})
| hb_sink (dest)
@@ -44,6 +44,20 @@ _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
+ if (plan->normalized_coords)
+ {
+ head_prime->xMin = plan->head_maxp_info.xMin;
+ head_prime->xMax = plan->head_maxp_info.xMax;
+ head_prime->yMin = plan->head_maxp_info.yMin;
+ head_prime->yMax = plan->head_maxp_info.yMax;
+
+ unsigned orig_flag = head_prime->flags;
+ if (plan->head_maxp_info.allXMinIsLsb)
+ orig_flag |= 1 << 1;
+ else
+ orig_flag &= ~(1 << 1);
+ head_prime->flags = orig_flag;
+ }
bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
hb_blob_destroy (head_prime_blob);
@@ -61,7 +75,7 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s
if (unlikely (!loca_prime_data)) return false;
- DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
+ DEBUG_MSG (SUBSET, nullptr, "loca entry_size %u num_offsets %u size %u",
entry_size, num_offsets, entry_size * num_offsets);
if (use_short_loca)
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
index e6e985c38c..29328c7627 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
@@ -7,6 +7,7 @@
#include "../../hb-ot-hmtx-table.hh"
#include "../../hb-ot-var-gvar-table.hh"
#include "../../hb-draw.hh"
+#include "../../hb-paint.hh"
#include "glyf-helpers.hh"
#include "Glyph.hh"
@@ -42,14 +43,13 @@ struct glyf
bool serialize (hb_serialize_context_t *c,
Iterator it,
bool use_short_loca,
- const hb_subset_plan_t *plan,
- hb_font_t *font)
+ const hb_subset_plan_t *plan)
{
TRACE_SERIALIZE (this);
unsigned init_len = c->length ();
for (auto &_ : it)
- if (unlikely (!_.serialize (c, use_short_loca, plan, font)))
+ if (unlikely (!_.serialize (c, use_short_loca, plan)))
return false;
/* As a special case when all glyph in the font are empty, add a zero byte
@@ -75,59 +75,66 @@ struct glyf
glyf *glyf_prime = c->serializer->start_embed <glyf> ();
if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
- hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
- _populate_subset_glyphs (c->plan, glyphs);
-
hb_font_t *font = nullptr;
- if (!c->plan->pinned_at_default)
+ if (c->plan->normalized_coords)
{
font = _create_font_for_instancing (c->plan);
if (unlikely (!font)) return false;
}
- auto padded_offsets =
- + hb_iter (glyphs)
- | hb_map (&glyf_impl::SubsetGlyph::padded_size)
- ;
+ hb_vector_t<unsigned> padded_offsets;
+ unsigned num_glyphs = c->plan->num_output_glyphs ();
+ if (unlikely (!padded_offsets.resize (num_glyphs)))
+ return false;
+
+ hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
+ if (!_populate_subset_glyphs (c->plan, font, glyphs))
+ return false;
+
+ if (font)
+ hb_font_destroy (font);
+
+ unsigned max_offset = 0;
+ for (unsigned i = 0; i < num_glyphs; i++)
+ {
+ padded_offsets[i] = glyphs[i].padded_size ();
+ max_offset += padded_offsets[i];
+ }
bool use_short_loca = false;
if (likely (!c->plan->force_long_loca))
- {
- unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
use_short_loca = max_offset < 0x1FFFF;
- }
- glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan, font);
if (!use_short_loca) {
- padded_offsets =
- + hb_iter (glyphs)
- | hb_map (&glyf_impl::SubsetGlyph::length)
- ;
+ for (unsigned i = 0; i < num_glyphs; i++)
+ padded_offsets[i] = glyphs[i].length ();
}
- if (font)
- {
- _free_compiled_subset_glyphs (&glyphs);
- hb_font_destroy (font);
- }
+ bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan);
+ if (c->plan->normalized_coords && !c->plan->pinned_at_default)
+ _free_compiled_subset_glyphs (glyphs, glyphs.length - 1);
+
+ if (!result) return false;
if (unlikely (c->serializer->in_error ())) return_trace (false);
+
return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
- padded_offsets,
+ padded_offsets.iter (),
use_short_loca)));
}
- void
+ bool
_populate_subset_glyphs (const hb_subset_plan_t *plan,
+ hb_font_t *font,
hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
hb_font_t *
_create_font_for_instancing (const hb_subset_plan_t *plan) const;
- void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> *glyphs) const
+ void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs, unsigned index) const
{
- for (auto _ : *glyphs)
- _.free_compiled_bytes ();
+ for (unsigned i = 0; i <= index && i < glyphs.length; i++)
+ glyphs[i].free_compiled_bytes ();
}
protected:
@@ -193,7 +200,7 @@ struct glyf_accelerator_t
contour_point_vector_t all_points;
bool phantom_only = !consumer.is_consuming_contour_points ();
- if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, true, phantom_only)))
+ if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only)))
return false;
if (consumer.is_consuming_contour_points ())
@@ -247,19 +254,14 @@ struct glyf_accelerator_t
extents->y_bearing = 0;
return;
}
- if (scaled)
- {
- extents->x_bearing = font->em_scalef_x (min_x);
- extents->width = font->em_scalef_x (max_x) - extents->x_bearing;
- extents->y_bearing = font->em_scalef_y (max_y);
- extents->height = font->em_scalef_y (min_y) - extents->y_bearing;
- }
- else
{
extents->x_bearing = roundf (min_x);
extents->width = roundf (max_x - extents->x_bearing);
extents->y_bearing = roundf (max_y);
extents->height = roundf (min_y - extents->y_bearing);
+
+ if (scaled)
+ font->scale_glyph_extents (extents);
}
}
@@ -337,6 +339,15 @@ struct glyf_accelerator_t
return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
}
+ bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
+ {
+ funcs->push_clip_glyph (data, gid, font);
+ funcs->color (data, true, foreground);
+ funcs->pop_clip (data);
+
+ return true;
+ }
+
const glyf_impl::Glyph
glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
{
@@ -385,14 +396,16 @@ struct glyf_accelerator_t
};
-inline void
+inline bool
glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
+ hb_font_t *font,
hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
{
OT::glyf_accelerator_t glyf (plan->source);
unsigned num_glyphs = plan->num_output_glyphs ();
- if (!glyphs.resize (num_glyphs)) return;
+ if (!glyphs.resize (num_glyphs)) return false;
+ unsigned idx = 0;
for (auto p : plan->glyph_map->iter ())
{
unsigned new_gid = p.second;
@@ -401,7 +414,7 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
if (unlikely (new_gid == 0 &&
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
- plan->pinned_at_default)
+ !plan->normalized_coords)
subset_glyph.source_glyph = glyf_impl::Glyph ();
else
{
@@ -414,7 +427,20 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
subset_glyph.drop_hints_bytes ();
else
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
+
+ if (font)
+ {
+ if (unlikely (!subset_glyph.compile_bytes_with_deltas (plan, font, glyf)))
+ {
+ // when pinned at default, only bounds are updated, thus no need to free
+ if (!plan->pinned_at_default && idx > 0)
+ _free_compiled_subset_glyphs (glyphs, idx - 1);
+ return false;
+ }
+ idx++;
+ }
}
+ return true;
}
inline hb_font_t *
@@ -424,10 +450,10 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
if (unlikely (font == hb_font_get_empty ())) return nullptr;
hb_vector_t<hb_variation_t> vars;
- if (unlikely (!vars.alloc (plan->user_axes_location->get_population ())))
+ if (unlikely (!vars.alloc (plan->user_axes_location.get_population (), true)))
return nullptr;
- for (auto _ : *plan->user_axes_location)
+ for (auto _ : plan->user_axes_location)
{
hb_variation_t var;
var.tag = _.first;
@@ -436,7 +462,7 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
}
#ifndef HB_NO_VAR
- hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
+ hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
#endif
return font;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh
index 9bfc45a1a6..e35a4dafde 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh
@@ -26,22 +26,29 @@ struct path_builder_t
optional_point_t lerp (optional_point_t p, float t)
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
- } first_oncurve, first_offcurve, last_offcurve;
+ } first_oncurve, first_offcurve, last_offcurve, last_offcurve2;
path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
{
font = font_;
draw_session = &draw_session_;
- first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
+ first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
}
/* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
See also:
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
- * https://stackoverflow.com/a/20772557 */
+ * https://stackoverflow.com/a/20772557
+ *
+ * Cubic support added (incomplete). */
void consume_point (const contour_point_t &point)
{
bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
+#ifdef HB_NO_CUBIC_GLYF
+ bool is_cubic = false;
+#else
+ bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
+#endif
optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
if (!first_oncurve)
{
@@ -69,16 +76,41 @@ struct path_builder_t
{
if (is_on_curve)
{
- draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
- p.x, p.y);
+ if (last_offcurve2)
+ {
+ draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+ last_offcurve.x, last_offcurve.y,
+ p.x, p.y);
+ last_offcurve2 = optional_point_t ();
+ }
+ else
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ p.x, p.y);
last_offcurve = optional_point_t ();
}
else
{
- optional_point_t mid = last_offcurve.lerp (p, .5f);
- draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
- mid.x, mid.y);
- last_offcurve = p;
+ if (is_cubic && !last_offcurve2)
+ {
+ last_offcurve2 = last_offcurve;
+ last_offcurve = p;
+ }
+ else
+ {
+ optional_point_t mid = last_offcurve.lerp (p, .5f);
+
+ if (is_cubic)
+ {
+ draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+ last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve2 = optional_point_t ();
+ }
+ else
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve = p;
+ }
}
}
else
@@ -105,8 +137,15 @@ struct path_builder_t
draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
first_oncurve.x, first_oncurve.y);
else if (last_offcurve && first_oncurve)
- draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
- first_oncurve.x, first_oncurve.y);
+ {
+ if (last_offcurve2)
+ draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+ last_offcurve.x, last_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ }
else if (first_oncurve)
draw_session->line_to (first_oncurve.x, first_oncurve.y);
else if (first_offcurve)
@@ -117,7 +156,7 @@ struct path_builder_t
}
/* Getting ready for the next contour */
- first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
+ first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
draw_session->close_path ();
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh b/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh
new file mode 100644
index 0000000000..c1839f3b68
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh
@@ -0,0 +1,589 @@
+/*
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef OT_NAME_NAME_HH
+#define OT_NAME_NAME_HH
+
+#include "../../hb-open-type.hh"
+#include "../../hb-ot-name-language.hh"
+#include "../../hb-aat-layout.hh"
+#include "../../hb-utf.hh"
+
+
+namespace OT {
+
+template <typename in_utf_t, typename out_utf_t>
+inline unsigned int
+hb_ot_name_convert_utf (hb_bytes_t bytes,
+ unsigned int *text_size /* IN/OUT */,
+ typename out_utf_t::codepoint_t *text /* OUT */)
+{
+ unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
+ const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
+ const typename in_utf_t::codepoint_t *src_end = src + src_len;
+
+ typename out_utf_t::codepoint_t *dst = text;
+
+ hb_codepoint_t unicode;
+ const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+
+ if (text_size && *text_size)
+ {
+ (*text_size)--; /* Save room for NUL-termination. */
+ const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
+
+ while (src < src_end && dst < dst_end)
+ {
+ const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
+ typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
+ if (dst_next == dst)
+ break; /* Out-of-room. */
+
+ dst = dst_next;
+ src = src_next;
+ }
+
+ *text_size = dst - text;
+ *dst = 0; /* NUL-terminate. */
+ }
+
+ /* Accumulate length of rest. */
+ unsigned int dst_len = dst - text;
+ while (src < src_end)
+ {
+ src = in_utf_t::next (src, src_end, &unicode, replacement);
+ dst_len += out_utf_t::encode_len (unicode);
+ }
+ return dst_len;
+}
+
+#define entry_score var.u16[0]
+#define entry_index var.u16[1]
+
+
+/*
+ * name -- Naming
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/name
+ */
+#define HB_OT_TAG_name HB_TAG('n','a','m','e')
+
+#define UNSUPPORTED 42
+
+struct NameRecord
+{
+ hb_language_t language (hb_face_t *face) const
+ {
+#ifndef HB_NO_OT_NAME_LANGUAGE
+ unsigned int p = platformID;
+ unsigned int l = languageID;
+
+ if (p == 3)
+ return _hb_ot_name_language_for_ms_code (l);
+
+ if (p == 1)
+ return _hb_ot_name_language_for_mac_code (l);
+
+#ifndef HB_NO_OT_NAME_LANGUAGE_AAT
+ if (p == 0)
+ return face->table.ltag->get_language (l);
+#endif
+
+#endif
+ return HB_LANGUAGE_INVALID;
+ }
+
+ uint16_t score () const
+ {
+ /* Same order as in cmap::find_best_subtable(). */
+ unsigned int p = platformID;
+ unsigned int e = encodingID;
+
+ /* 32-bit. */
+ if (p == 3 && e == 10) return 0;
+ if (p == 0 && e == 6) return 1;
+ if (p == 0 && e == 4) return 2;
+
+ /* 16-bit. */
+ if (p == 3 && e == 1) return 3;
+ if (p == 0 && e == 3) return 4;
+ if (p == 0 && e == 2) return 5;
+ if (p == 0 && e == 1) return 6;
+ if (p == 0 && e == 0) return 7;
+
+ /* Symbol. */
+ if (p == 3 && e == 0) return 8;
+
+ /* We treat all Mac Latin names as ASCII only. */
+ if (p == 1 && e == 0) return 10; /* 10 is magic number :| */
+
+ return UNSUPPORTED;
+ }
+
+ NameRecord* copy (hb_serialize_context_t *c, const void *base
+#ifdef HB_EXPERIMENTAL_API
+ , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
+#endif
+ ) const
+ {
+ TRACE_SERIALIZE (this);
+ HB_UNUSED auto snap = c->snapshot ();
+ auto *out = c->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+#ifdef HB_EXPERIMENTAL_API
+ hb_ot_name_record_ids_t record_ids (platformID, encodingID, languageID, nameID);
+ hb_bytes_t* name_bytes;
+
+ if (name_table_overrides->has (record_ids, &name_bytes)) {
+ hb_bytes_t encoded_bytes = *name_bytes;
+ char *name_str_utf16_be = nullptr;
+
+ if (platformID != 1)
+ {
+ unsigned text_size = hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, nullptr, nullptr);
+
+ text_size++; // needs to consider NULL terminator for use in hb_ot_name_convert_utf()
+ unsigned byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
+ name_str_utf16_be = (char *) hb_calloc (byte_len, 1);
+ if (!name_str_utf16_be)
+ {
+ c->revert (snap);
+ return_trace (nullptr);
+ }
+ hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, &text_size,
+ (hb_utf16_be_t::codepoint_t *) name_str_utf16_be);
+
+ unsigned encoded_byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
+ if (!encoded_byte_len || !c->check_assign (out->length, encoded_byte_len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
+ c->revert (snap);
+ hb_free (name_str_utf16_be);
+ return_trace (nullptr);
+ }
+
+ encoded_bytes = hb_bytes_t (name_str_utf16_be, encoded_byte_len);
+ }
+ else
+ {
+ // mac platform, copy the UTF-8 string(all ascii characters) as is
+ if (!c->check_assign (out->length, encoded_bytes.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
+ c->revert (snap);
+ return_trace (nullptr);
+ }
+ }
+
+ out->offset = 0;
+ c->push ();
+ encoded_bytes.copy (c);
+ c->add_link (out->offset, c->pop_pack (), hb_serialize_context_t::Tail, 0);
+ hb_free (name_str_utf16_be);
+ }
+ else
+#endif
+ {
+ out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length);
+ }
+ return_trace (out);
+ }
+
+ bool isUnicode () const
+ {
+ unsigned int p = platformID;
+ unsigned int e = encodingID;
+
+ return (p == 0 ||
+ (p == 3 && (e == 0 || e == 1 || e == 10)));
+ }
+
+ static int cmp (const void *pa, const void *pb)
+ {
+ const NameRecord *a = (const NameRecord *)pa;
+ const NameRecord *b = (const NameRecord *)pb;
+
+ if (a->platformID != b->platformID)
+ return a->platformID - b->platformID;
+
+ if (a->encodingID != b->encodingID)
+ return a->encodingID - b->encodingID;
+
+ if (a->languageID != b->languageID)
+ return a->languageID - b->languageID;
+
+ if (a->nameID != b->nameID)
+ return a->nameID - b->nameID;
+
+ if (a->length != b->length)
+ return a->length - b->length;
+
+ return 0;
+ }
+
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && offset.sanitize (c, base, length));
+ }
+
+ HBUINT16 platformID; /* Platform ID. */
+ HBUINT16 encodingID; /* Platform-specific encoding ID. */
+ HBUINT16 languageID; /* Language ID. */
+ HBUINT16 nameID; /* Name ID. */
+ HBUINT16 length; /* String length (in bytes). */
+ NNOffset16To<UnsizedArrayOf<HBUINT8>>
+ offset; /* String offset from start of storage area (in bytes). */
+ public:
+ DEFINE_SIZE_STATIC (12);
+};
+
+static int
+_hb_ot_name_entry_cmp_key (const void *pa, const void *pb, bool exact)
+{
+ const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
+ const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
+
+ /* Compare by name_id, then language. */
+
+ if (a->name_id != b->name_id)
+ return a->name_id - b->name_id;
+
+ if (a->language == b->language) return 0;
+ if (!a->language) return -1;
+ if (!b->language) return +1;
+
+ const char *astr = hb_language_to_string (a->language);
+ const char *bstr = hb_language_to_string (b->language);
+
+ signed c = strcmp (astr, bstr);
+
+ // 'a' is the user request, and 'b' is string in the font.
+ // If eg. user asks for "en-us" and font has "en", approve.
+ if (!exact && c &&
+ hb_language_matches (b->language, a->language))
+ return 0;
+
+ return c;
+}
+
+static int
+_hb_ot_name_entry_cmp (const void *pa, const void *pb)
+{
+ /* Compare by name_id, then language, then score, then index. */
+
+ int v = _hb_ot_name_entry_cmp_key (pa, pb, true);
+ if (v)
+ return v;
+
+ const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
+ const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
+
+ if (a->entry_score != b->entry_score)
+ return a->entry_score - b->entry_score;
+
+ if (a->entry_index != b->entry_index)
+ return a->entry_index - b->entry_index;
+
+ return 0;
+}
+
+struct name
+{
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_name;
+
+ unsigned int get_size () const
+ { return min_size + count * nameRecordZ.item_size; }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, const NameRecord &))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator it,
+ const void *src_string_pool
+#ifdef HB_EXPERIMENTAL_API
+ , const hb_vector_t<hb_ot_name_record_ids_t>& insert_name_records
+ , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
+#endif
+ )
+ {
+ TRACE_SERIALIZE (this);
+
+ if (unlikely (!c->extend_min ((*this)))) return_trace (false);
+
+ unsigned total_count = it.len ()
+#ifdef HB_EXPERIMENTAL_API
+ + insert_name_records.length
+#endif
+ ;
+ this->format = 0;
+ if (!c->check_assign (this->count, total_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return false;
+
+ NameRecord *name_records = (NameRecord *) hb_calloc (total_count, NameRecord::static_size);
+ if (unlikely (!name_records)) return_trace (false);
+
+ hb_array_t<NameRecord> records (name_records, total_count);
+
+ for (const NameRecord& record : it)
+ {
+ hb_memcpy (name_records, &record, NameRecord::static_size);
+ name_records++;
+ }
+
+#ifdef HB_EXPERIMENTAL_API
+ for (unsigned i = 0; i < insert_name_records.length; i++)
+ {
+ const hb_ot_name_record_ids_t& ids = insert_name_records[i];
+ NameRecord record;
+ record.platformID = ids.platform_id;
+ record.encodingID = ids.encoding_id;
+ record.languageID = ids.language_id;
+ record.nameID = ids.name_id;
+ record.length = 0; // handled in NameRecord copy()
+ record.offset = 0;
+ memcpy (name_records, &record, NameRecord::static_size);
+ name_records++;
+ }
+#endif
+
+ records.qsort ();
+
+ c->copy_all (records,
+ src_string_pool
+#ifdef HB_EXPERIMENTAL_API
+ , name_table_overrides
+#endif
+ );
+ hb_free (records.arrayZ);
+
+
+ if (unlikely (c->ran_out_of_room ())) return_trace (false);
+
+ this->stringOffset = c->length ();
+
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ name *name_prime = c->serializer->start_embed<name> ();
+ if (unlikely (!name_prime)) return_trace (false);
+
+#ifdef HB_EXPERIMENTAL_API
+ const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides =
+ &c->plan->name_table_overrides;
+#endif
+
+ auto it =
+ + nameRecordZ.as_array (count)
+ | hb_filter (c->plan->name_ids, &NameRecord::nameID)
+ | hb_filter (c->plan->name_languages, &NameRecord::languageID)
+ | hb_filter ([&] (const NameRecord& namerecord) {
+ return
+ (c->plan->flags & HB_SUBSET_FLAGS_NAME_LEGACY)
+ || namerecord.isUnicode ();
+ })
+#ifdef HB_EXPERIMENTAL_API
+ | hb_filter ([&] (const NameRecord& namerecord) {
+ if (name_table_overrides->is_empty ())
+ return true;
+ hb_ot_name_record_ids_t rec_ids (namerecord.platformID,
+ namerecord.encodingID,
+ namerecord.languageID,
+ namerecord.nameID);
+
+ hb_bytes_t *p;
+ if (name_table_overrides->has (rec_ids, &p) &&
+ (*p).length == 0)
+ return false;
+ return true;
+ })
+#endif
+ ;
+
+#ifdef HB_EXPERIMENTAL_API
+ hb_hashmap_t<hb_ot_name_record_ids_t, unsigned> retained_name_record_ids;
+ for (const NameRecord& rec : it)
+ {
+ hb_ot_name_record_ids_t rec_ids (rec.platformID,
+ rec.encodingID,
+ rec.languageID,
+ rec.nameID);
+ retained_name_record_ids.set (rec_ids, 1);
+ }
+
+ hb_vector_t<hb_ot_name_record_ids_t> insert_name_records;
+ if (!name_table_overrides->is_empty ())
+ {
+ if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population (), true)))
+ return_trace (false);
+ for (const auto& record_ids : name_table_overrides->keys ())
+ {
+ if (name_table_overrides->get (record_ids).length == 0)
+ continue;
+ if (retained_name_record_ids.has (record_ids))
+ continue;
+ insert_name_records.push (record_ids);
+ }
+ }
+#endif
+
+ return (name_prime->serialize (c->serializer, it,
+ std::addressof (this + stringOffset)
+#ifdef HB_EXPERIMENTAL_API
+ , insert_name_records
+ , name_table_overrides
+#endif
+ ));
+ }
+
+ bool sanitize_records (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ const void *string_pool = (this+stringOffset).arrayZ;
+ return_trace (nameRecordZ.sanitize (c, count, string_pool));
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ likely (format == 0 || format == 1) &&
+ c->check_array (nameRecordZ.arrayZ, count) &&
+ c->check_range (this, stringOffset) &&
+ sanitize_records (c));
+ }
+
+ struct accelerator_t
+ {
+ accelerator_t (hb_face_t *face)
+ {
+ this->table = hb_sanitize_context_t ().reference_table<name> (face);
+ assert (this->table.get_length () >= this->table->stringOffset);
+ this->pool = (const char *) (const void *) (this->table+this->table->stringOffset);
+ this->pool_len = this->table.get_length () - this->table->stringOffset;
+ const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
+ this->table->count);
+
+ this->names.alloc (all_names.length, true);
+
+ for (unsigned int i = 0; i < all_names.length; i++)
+ {
+ hb_ot_name_entry_t *entry = this->names.push ();
+
+ entry->name_id = all_names[i].nameID;
+ entry->language = all_names[i].language (face);
+ entry->entry_score = all_names[i].score ();
+ entry->entry_index = i;
+ }
+
+ this->names.qsort (_hb_ot_name_entry_cmp);
+ /* Walk and pick best only for each name_id,language pair,
+ * while dropping unsupported encodings. */
+ unsigned int j = 0;
+ for (unsigned int i = 0; i < this->names.length; i++)
+ {
+ if (this->names[i].entry_score == UNSUPPORTED ||
+ this->names[i].language == HB_LANGUAGE_INVALID)
+ continue;
+ if (i &&
+ this->names[i - 1].name_id == this->names[i].name_id &&
+ this->names[i - 1].language == this->names[i].language)
+ continue;
+ this->names[j++] = this->names[i];
+ }
+ this->names.resize (j);
+ }
+ ~accelerator_t ()
+ {
+ this->table.destroy ();
+ }
+
+ int get_index (hb_ot_name_id_t name_id,
+ hb_language_t language,
+ unsigned int *width=nullptr) const
+ {
+ const hb_ot_name_entry_t key = {name_id, {0}, language};
+ const hb_ot_name_entry_t *entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
+ this->names.length,
+ sizeof (hb_ot_name_entry_t),
+ _hb_ot_name_entry_cmp_key,
+ true);
+
+ if (!entry)
+ {
+ entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
+ this->names.length,
+ sizeof (hb_ot_name_entry_t),
+ _hb_ot_name_entry_cmp_key,
+ false);
+ }
+
+ if (!entry)
+ return -1;
+
+ if (width)
+ *width = entry->entry_score < 10 ? 2 : 1;
+
+ return entry->entry_index;
+ }
+
+ hb_bytes_t get_name (unsigned int idx) const
+ {
+ const hb_array_t<const NameRecord> all_names (table->nameRecordZ.arrayZ, table->count);
+ const NameRecord &record = all_names[idx];
+ const hb_bytes_t string_pool (pool, pool_len);
+ return string_pool.sub_array (record.offset, record.length);
+ }
+
+ private:
+ const char *pool;
+ unsigned int pool_len;
+ public:
+ hb_blob_ptr_t<name> table;
+ hb_vector_t<hb_ot_name_entry_t> names;
+ };
+
+ public:
+ /* We only implement format 0 for now. */
+ HBUINT16 format; /* Format selector (=0/1). */
+ HBUINT16 count; /* Number of name records. */
+ NNOffset16To<UnsizedArrayOf<HBUINT8>>
+ stringOffset; /* Offset to start of string storage (from start of table). */
+ UnsizedArrayOf<NameRecord>
+ nameRecordZ; /* The name records where count is the number of records. */
+ public:
+ DEFINE_SIZE_ARRAY (6, nameRecordZ);
+};
+
+#undef entry_index
+#undef entry_score
+
+struct name_accelerator_t : name::accelerator_t {
+ name_accelerator_t (hb_face_t *face) : name::accelerator_t (face) {}
+};
+
+} /* namespace OT */
+
+
+#endif /* OT_NAME_NAME_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh
index dc5b6a36fe..38ca5db096 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh
+++ b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh
@@ -123,7 +123,7 @@ struct graph_t
while (a || b)
{
DEBUG_MSG (SUBSET_REPACK, nullptr,
- " 0x%x %s 0x%x", *a, (*a == *b) ? "==" : "!=", *b);
+ " 0x%x %s 0x%x", (unsigned) *a, (*a == *b) ? "==" : "!=", (unsigned) *b);
a++;
b++;
}
@@ -700,6 +700,9 @@ struct graph_t
}
}
+ if (in_error ())
+ return false;
+
if (!made_changes)
return false;
@@ -833,7 +836,11 @@ struct graph_t
if (index_map.has (node_idx))
return;
- index_map.set (node_idx, duplicate (node_idx));
+ unsigned clone_idx = duplicate (node_idx);
+ if (!check_success (clone_idx != (unsigned) -1))
+ return;
+
+ index_map.set (node_idx, clone_idx);
for (const auto& l : object (node_idx).all_links ()) {
duplicate_subgraph (l.objidx, index_map);
}
@@ -918,12 +925,12 @@ struct graph_t
{
// 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",
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %u => %u",
parent_idx, child_idx);
return -1;
}
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %u => %u",
parent_idx, child_idx);
unsigned clone_idx = duplicate (child_idx);
@@ -981,7 +988,7 @@ struct graph_t
*/
bool raise_childrens_priority (unsigned parent_idx)
{
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d",
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %u",
parent_idx);
// This operation doesn't change ordering until a sort is run, so no need
// to invalidate positions. It does not change graph structure so no need
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh
index d03a61bd19..040fd1de5f 100644
--- a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh
@@ -153,8 +153,8 @@ void print_overflows (graph_t& graph,
const auto& child = graph.vertices_[o.child];
DEBUG_MSG (SUBSET_REPACK, nullptr,
" overflow from "
- "%4d (%4d in, %4d out, space %2d) => "
- "%4d (%4d in, %4d out, space %2d)",
+ "%4u (%4u in, %4u out, space %2u) => "
+ "%4u (%4u in, %4u out, space %2u)",
o.parent,
parent.incoming_edges (),
parent.obj.real_links.length + parent.obj.virtual_links.length,
@@ -165,7 +165,7 @@ void print_overflows (graph_t& graph,
graph.space_for (o.child));
}
if (overflows.length > 10) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10);
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %u more overflows.", overflows.length - 10);
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc b/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc
index a43485e6fb..c0e23b3eb8 100644
--- a/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc
+++ b/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc
@@ -7,6 +7,7 @@
#include "hb-buffer.cc"
#include "hb-common.cc"
#include "hb-draw.cc"
+#include "hb-face-builder.cc"
#include "hb-face.cc"
#include "hb-fallback-shape.cc"
#include "hb-font.cc"
@@ -40,6 +41,9 @@
#include "hb-ot-shaper-vowel-constraints.cc"
#include "hb-ot-tag.cc"
#include "hb-ot-var.cc"
+#include "hb-outline.cc"
+#include "hb-paint-extents.cc"
+#include "hb-paint.cc"
#include "hb-set.cc"
#include "hb-shape-plan.cc"
#include "hb-shape.cc"
@@ -50,6 +54,7 @@
#include "hb-subset-cff1.cc"
#include "hb-subset-cff2.cc"
#include "hb-subset-input.cc"
+#include "hb-subset-instancer-solver.cc"
#include "hb-subset-plan.cc"
#include "hb-subset-repacker.cc"
#include "hb-subset.cc"
diff --git a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
index fe4e21db07..d7e8a93f39 100644
--- a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
+++ b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
@@ -8,6 +8,7 @@
#include "hb-coretext.cc"
#include "hb-directwrite.cc"
#include "hb-draw.cc"
+#include "hb-face-builder.cc"
#include "hb-face.cc"
#include "hb-fallback-shape.cc"
#include "hb-font.cc"
@@ -45,6 +46,9 @@
#include "hb-ot-shaper-vowel-constraints.cc"
#include "hb-ot-tag.cc"
#include "hb-ot-var.cc"
+#include "hb-outline.cc"
+#include "hb-paint-extents.cc"
+#include "hb-paint.cc"
#include "hb-set.cc"
#include "hb-shape-plan.cc"
#include "hb-shape.cc"
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 6cbed82692..efbb623efc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
@@ -28,6 +28,7 @@
#define HB_AAT_LAYOUT_COMMON_HH
#include "hb-aat-layout.hh"
+#include "hb-aat-map.hh"
#include "hb-open-type.hh"
namespace OT {
@@ -39,6 +40,43 @@ namespace AAT {
using namespace OT;
+struct ankr;
+
+struct hb_aat_apply_context_t :
+ hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
+{
+ const char *get_name () { return "APPLY"; }
+ template <typename T>
+ return_t dispatch (const T &obj) { return obj.apply (this); }
+ static return_t default_return_value () { return false; }
+ bool stop_sublookup_iteration (return_t r) const { return r; }
+
+ const hb_ot_shape_plan_t *plan;
+ hb_font_t *font;
+ hb_face_t *face;
+ hb_buffer_t *buffer;
+ hb_sanitize_context_t sanitizer;
+ const ankr *ankr_table;
+ const OT::GDEF *gdef_table;
+ const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
+ hb_mask_t subtable_flags = 0;
+
+ /* Unused. For debug tracing only. */
+ unsigned int lookup_index;
+
+ HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
+ hb_font_t *font_,
+ hb_buffer_t *buffer_,
+ hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
+
+ HB_INTERNAL ~hb_aat_apply_context_t ();
+
+ HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
+
+ void set_lookup_index (unsigned int i) { lookup_index = i; }
+};
+
+
/*
* Lookup Table
*/
@@ -740,16 +778,44 @@ struct StateTableDriver
num_glyphs (face_->get_num_glyphs ()) {}
template <typename context_t>
- void drive (context_t *c)
+ void drive (context_t *c, hb_aat_apply_context_t *ac)
{
if (!c->in_place)
buffer->clear_output ();
int state = StateTableT::STATE_START_OF_TEXT;
+ // If there's only one range, we already checked the flag.
+ auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
for (buffer->idx = 0; buffer->successful;)
{
+ /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
+ if (last_range)
+ {
+ auto *range = last_range;
+ if (buffer->idx < buffer->len)
+ {
+ unsigned cluster = buffer->cur().cluster;
+ while (cluster < range->cluster_first)
+ range--;
+ while (cluster > range->cluster_last)
+ range++;
+
+
+ last_range = range;
+ }
+ if (!(range->flags & ac->subtable_flags))
+ {
+ if (buffer->idx == buffer->len || unlikely (!buffer->successful))
+ break;
+
+ state = StateTableT::STATE_START_OF_TEXT;
+ (void) buffer->next_glyph ();
+ continue;
+ }
+ }
+
unsigned int klass = buffer->idx < buffer->len ?
- machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
+ machine.get_class (buffer->cur().codepoint, num_glyphs) :
(unsigned) StateTableT::CLASS_END_OF_TEXT;
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
const EntryT &entry = machine.get_entry (state, klass);
@@ -845,41 +911,6 @@ struct StateTableDriver
};
-struct ankr;
-
-struct hb_aat_apply_context_t :
- hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
-{
- const char *get_name () { return "APPLY"; }
- template <typename T>
- return_t dispatch (const T &obj) { return obj.apply (this); }
- static return_t default_return_value () { return false; }
- bool stop_sublookup_iteration (return_t r) const { return r; }
-
- const hb_ot_shape_plan_t *plan;
- hb_font_t *font;
- hb_face_t *face;
- hb_buffer_t *buffer;
- hb_sanitize_context_t sanitizer;
- const ankr *ankr_table;
- const OT::GDEF *gdef_table;
-
- /* Unused. For debug tracing only. */
- unsigned int lookup_index;
-
- HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
- hb_font_t *font_,
- hb_buffer_t *buffer_,
- hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
-
- HB_INTERNAL ~hb_aat_apply_context_t ();
-
- HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
-
- void set_lookup_index (unsigned int i) { lookup_index = i; }
-};
-
-
} /* namespace AAT */
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 995492cd5a..35d7c84c2b 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
@@ -350,7 +350,7 @@ struct KerxSubTableFormat1
driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (true);
}
@@ -594,7 +594,7 @@ struct KerxSubTableFormat4
driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (true);
}
@@ -869,6 +869,8 @@ struct KerxTable
bool apply (AAT::hb_aat_apply_context_t *c) const
{
+ c->buffer->unsafe_to_concat ();
+
typedef typename T::SubTable SubTable;
bool ret = false;
@@ -889,7 +891,7 @@ struct KerxTable
reverse = bool (st->u.header.coverage & st->u.header.Backwards) !=
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
- if (!c->buffer->message (c->font, "start subtable %d", c->lookup_index))
+ if (!c->buffer->message (c->font, "start subtable %u", c->lookup_index))
goto skip;
if (!seenCrossStream &&
@@ -921,7 +923,7 @@ struct KerxTable
if (reverse)
c->buffer->reverse ();
- (void) c->buffer->message (c->font, "end subtable %d", c->lookup_index);
+ (void) c->buffer->message (c->font, "end subtable %u", c->lookup_index);
skip:
st = &StructAfter<SubTable> (*st);
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 8b9190d0be..f41ecc197f 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
@@ -169,7 +169,7 @@ struct RearrangementSubtable
driver_context_t dc (this);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (dc.ret);
}
@@ -325,7 +325,7 @@ struct ContextualSubtable
driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (dc.ret);
}
@@ -525,7 +525,7 @@ struct LigatureSubtable
if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
ligature_idx += componentData;
- DEBUG_MSG (APPLY, nullptr, "Action store %u last %u",
+ DEBUG_MSG (APPLY, nullptr, "Action store %d last %d",
bool (action & LigActionStore),
bool (action & LigActionLast));
if (action & (LigActionStore | LigActionLast))
@@ -577,7 +577,7 @@ struct LigatureSubtable
driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (dc.ret);
}
@@ -618,8 +618,27 @@ struct NoncontextualSubtable
hb_glyph_info_t *info = c->buffer->info;
unsigned int count = c->buffer->len;
+ // If there's only one range, we already checked the flag.
+ auto *last_range = c->range_flags && (c->range_flags->length > 1) ? &(*c->range_flags)[0] : nullptr;
for (unsigned int i = 0; i < count; i++)
{
+ /* This block copied from StateTableDriver::drive. Keep in sync. */
+ if (last_range)
+ {
+ auto *range = last_range;
+ {
+ unsigned cluster = info[i].cluster;
+ while (cluster < range->cluster_first)
+ range--;
+ while (cluster > range->cluster_last)
+ range++;
+
+ last_range = range;
+ }
+ if (!(range->flags & c->subtable_flags))
+ continue;
+ }
+
const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
if (replacement)
{
@@ -820,7 +839,7 @@ struct InsertionSubtable
driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
- driver.drive (&dc);
+ driver.drive (&dc, c);
return_trace (dc.ret);
}
@@ -968,7 +987,7 @@ struct Chain
// Check whether this type/setting pair was requested in the map, and if so, apply its flags.
// (The search here only looks at the type and setting fields of feature_info_t.)
hb_aat_map_builder_t::feature_info_t info = { type, setting, false, 0 };
- if (map->features.bsearch (info))
+ if (map->current_features.bsearch (info))
{
flags &= feature.disableFlags;
flags |= feature.enableFlags;
@@ -994,8 +1013,7 @@ struct Chain
return flags;
}
- void apply (hb_aat_apply_context_t *c,
- hb_mask_t flags) const
+ void apply (hb_aat_apply_context_t *c) const
{
const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
unsigned int count = subtableCount;
@@ -1003,8 +1021,10 @@ struct Chain
{
bool reverse;
- if (!(subtable->subFeatureFlags & flags))
+ if (hb_none (hb_iter (c->range_flags) |
+ hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); })))
goto skip;
+ c->subtable_flags = subtable->subFeatureFlags;
if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
@@ -1043,7 +1063,7 @@ struct Chain
bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) !=
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
- if (!c->buffer->message (c->font, "start chainsubtable %d", c->lookup_index))
+ if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index))
goto skip;
if (reverse)
@@ -1054,7 +1074,7 @@ struct Chain
if (reverse)
c->buffer->reverse ();
- (void) c->buffer->message (c->font, "end chainsubtable %d", c->lookup_index);
+ (void) c->buffer->message (c->font, "end chainsubtable %u", c->lookup_index);
if (unlikely (!c->buffer->successful)) return;
@@ -1120,22 +1140,31 @@ struct mortmorx
{
const Chain<Types> *chain = &firstChain;
unsigned int count = chainCount;
+ if (unlikely (!map->chain_flags.resize (count)))
+ return;
for (unsigned int i = 0; i < count; i++)
{
- map->chain_flags.push (chain->compile_flags (mapper));
+ map->chain_flags[i].push (hb_aat_map_t::range_flags_t {chain->compile_flags (mapper),
+ mapper->range_first,
+ mapper->range_last});
chain = &StructAfter<Chain<Types>> (*chain);
}
}
- void apply (hb_aat_apply_context_t *c) const
+ void apply (hb_aat_apply_context_t *c,
+ const hb_aat_map_t &map) const
{
if (unlikely (!c->buffer->successful)) return;
+
+ c->buffer->unsafe_to_concat ();
+
c->set_lookup_index (0);
const Chain<Types> *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
- chain->apply (c, c->plan->aat_map.chain_flags[i]);
+ c->range_flags = &map.chain_flags[i];
+ chain->apply (c);
if (unlikely (!c->buffer->successful)) return;
chain = &StructAfter<Chain<Types>> (*chain);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
index 78427b0d5a..c9147ff73b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
@@ -244,15 +244,23 @@ hb_aat_layout_has_substitution (hb_face_t *face)
void
hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
- hb_buffer_t *buffer)
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned num_features)
{
+ hb_aat_map_builder_t builder (font->face, plan->props);
+ for (unsigned i = 0; i < num_features; i++)
+ builder.add_feature (features[i]);
+ hb_aat_map_t map;
+ builder.compile (map);
+
hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
if (morx.has_data ())
{
AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
if (!buffer->message (font, "start table morx")) return;
- morx.apply (&c);
+ morx.apply (&c, map);
(void) buffer->message (font, "end table morx");
return;
}
@@ -263,7 +271,7 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
{
AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
if (!buffer->message (font, "start table mort")) return;
- mort.apply (&c);
+ mort.apply (&c, map);
(void) buffer->message (font, "end table mort");
return;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.hh
index 5e4e3bda15..15c382aa92 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.hh
@@ -53,7 +53,9 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
HB_INTERNAL void
hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
- hb_buffer_t *buffer);
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned num_features);
HB_INTERNAL void
hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-map.cc b/src/3rdparty/harfbuzz-ng/src/hb-aat-map.cc
index 2c38c35029..5bdb8004f2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-map.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-map.cc
@@ -36,27 +36,29 @@
#include "hb-aat-layout-feat-table.hh"
-void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned value)
+void hb_aat_map_builder_t::add_feature (const hb_feature_t &feature)
{
if (!face->table.feat->has_data ()) return;
- if (tag == HB_TAG ('a','a','l','t'))
+ if (feature.tag == HB_TAG ('a','a','l','t'))
{
if (!face->table.feat->exposes_feature (HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES))
return;
- feature_info_t *info = features.push();
- info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
- info->setting = (hb_aat_layout_feature_selector_t) value;
- info->seq = features.length;
- info->is_exclusive = true;
+ feature_range_t *range = features.push();
+ range->start = feature.start;
+ range->end = feature.end;
+ range->info.type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
+ range->info.setting = (hb_aat_layout_feature_selector_t) feature.value;
+ range->info.seq = features.length;
+ range->info.is_exclusive = true;
return;
}
- const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
+ const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (feature.tag);
if (!mapping) return;
- const AAT::FeatureName* feature = &face->table.feat->get_feature (mapping->aatFeatureType);
- if (!feature->has_data ())
+ const AAT::FeatureName* feature_name = &face->table.feat->get_feature (mapping->aatFeatureType);
+ if (!feature_name->has_data ())
{
/* Special case: Chain::compile_flags will fall back to the deprecated version of
* small-caps if necessary, so we need to check for that possibility.
@@ -64,38 +66,106 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned value)
if (mapping->aatFeatureType == HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE &&
mapping->selectorToEnable == HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS)
{
- feature = &face->table.feat->get_feature (HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE);
- if (!feature->has_data ()) return;
+ feature_name = &face->table.feat->get_feature (HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE);
+ if (!feature_name->has_data ()) return;
}
else return;
}
- feature_info_t *info = features.push();
- info->type = mapping->aatFeatureType;
- info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
- info->seq = features.length;
- info->is_exclusive = feature->is_exclusive ();
+ feature_range_t *range = features.push();
+ range->start = feature.start;
+ range->end = feature.end;
+ range->info.type = mapping->aatFeatureType;
+ range->info.setting = feature.value ? mapping->selectorToEnable : mapping->selectorToDisable;
+ range->info.seq = features.length;
+ range->info.is_exclusive = feature_name->is_exclusive ();
}
void
hb_aat_map_builder_t::compile (hb_aat_map_t &m)
{
- /* Sort features and merge duplicates */
- if (features.length)
+ /* Compute active features per range, and compile each. */
+
+ /* Sort features by start/end events. */
+ hb_vector_t<feature_event_t> feature_events;
+ for (unsigned int i = 0; i < features.length; i++)
+ {
+ auto &feature = features[i];
+
+ if (features[i].start == features[i].end)
+ continue;
+
+ feature_event_t *event;
+
+ event = feature_events.push ();
+ event->index = features[i].start;
+ event->start = true;
+ event->feature = feature.info;
+
+ event = feature_events.push ();
+ event->index = features[i].end;
+ event->start = false;
+ event->feature = feature.info;
+ }
+ feature_events.qsort ();
+ /* Add a strategic final event. */
+ {
+ feature_info_t feature;
+ feature.seq = features.length + 1;
+
+ feature_event_t *event = feature_events.push ();
+ event->index = -1; /* This value does magic. */
+ event->start = false;
+ event->feature = feature;
+ }
+
+ /* Scan events and save features for each range. */
+ hb_sorted_vector_t<feature_info_t> active_features;
+ unsigned int last_index = 0;
+ for (unsigned int i = 0; i < feature_events.length; i++)
{
- features.qsort ();
- unsigned int j = 0;
- for (unsigned int i = 1; i < features.length; i++)
- if (features[i].type != features[j].type ||
- /* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
- * respectively, so we mask out the low-order bit when checking for "duplicates"
- * (selectors referring to the same feature setting) here. */
- (!features[i].is_exclusive && ((features[i].setting & ~1) != (features[j].setting & ~1))))
- features[++j] = features[i];
- features.shrink (j + 1);
+ feature_event_t *event = &feature_events[i];
+
+ if (event->index != last_index)
+ {
+ /* Save a snapshot of active features and the range. */
+
+ /* Sort features and merge duplicates */
+ current_features = active_features;
+ range_first = last_index;
+ range_last = event->index - 1;
+ if (current_features.length)
+ {
+ current_features.qsort ();
+ unsigned int j = 0;
+ for (unsigned int i = 1; i < current_features.length; i++)
+ if (current_features[i].type != current_features[j].type ||
+ /* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
+ * respectively, so we mask out the low-order bit when checking for "duplicates"
+ * (selectors referring to the same feature setting) here. */
+ (!current_features[i].is_exclusive && ((current_features[i].setting & ~1) != (current_features[j].setting & ~1))))
+ current_features[++j] = current_features[i];
+ current_features.shrink (j + 1);
+ }
+
+ hb_aat_layout_compile_map (this, &m);
+
+ last_index = event->index;
+ }
+
+ if (event->start)
+ {
+ active_features.push (event->feature);
+ } else {
+ feature_info_t *feature = active_features.lsearch (event->feature);
+ if (feature)
+ active_features.remove_ordered (feature - active_features.arrayZ);
+ }
}
- hb_aat_layout_compile_map (this, &m);
+ for (auto &chain_flags : m.chain_flags)
+ // With our above setup this value is one less than desired; adjust it.
+ chain_flags.tail().cluster_last = HB_FEATURE_GLOBAL_END;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-map.hh
index d0ee7d672c..cb22ffee42 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-map.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-map.hh
@@ -35,16 +35,15 @@ struct hb_aat_map_t
friend struct hb_aat_map_builder_t;
public:
-
- void init ()
+ struct range_flags_t
{
- hb_memset (this, 0, sizeof (*this));
- chain_flags.init ();
- }
- void fini () { chain_flags.fini (); }
+ hb_mask_t flags;
+ unsigned cluster_first;
+ unsigned cluster_last; // end - 1
+ };
public:
- hb_vector_t<hb_mask_t> chain_flags;
+ hb_vector_t<hb_sorted_vector_t<range_flags_t>> chain_flags;
};
struct hb_aat_map_builder_t
@@ -56,7 +55,7 @@ struct hb_aat_map_builder_t
face (face_),
props (props_) {}
- HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1);
+ HB_INTERNAL void add_feature (const hb_feature_t &feature);
HB_INTERNAL void compile (hb_aat_map_t &m);
@@ -78,7 +77,7 @@ struct hb_aat_map_builder_t
return (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
}
- /* compares type & setting only, not is_exclusive flag or seq number */
+ /* compares type & setting only */
int cmp (const feature_info_t& f) const
{
return (f.type != type) ? (f.type < type ? -1 : 1) :
@@ -86,12 +85,38 @@ struct hb_aat_map_builder_t
}
};
+ struct feature_range_t
+ {
+ feature_info_t info;
+ unsigned start;
+ unsigned end;
+ };
+
+ private:
+ struct feature_event_t
+ {
+ unsigned int index;
+ bool start;
+ feature_info_t feature;
+
+ HB_INTERNAL static int cmp (const void *pa, const void *pb) {
+ const feature_event_t *a = (const feature_event_t *) pa;
+ const feature_event_t *b = (const feature_event_t *) pb;
+ return a->index < b->index ? -1 : a->index > b->index ? 1 :
+ a->start < b->start ? -1 : a->start > b->start ? 1 :
+ feature_info_t::cmp (&a->feature, &b->feature);
+ }
+ };
+
public:
hb_face_t *face;
hb_segment_properties_t props;
public:
- hb_sorted_vector_t<feature_info_t> features;
+ hb_sorted_vector_t<feature_range_t> features;
+ hb_sorted_vector_t<feature_info_t> current_features;
+ unsigned range_first = HB_FEATURE_GLOBAL_START;
+ unsigned range_last = HB_FEATURE_GLOBAL_END;
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
index d85a4afe10..e98645e3e3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
@@ -875,7 +875,7 @@ hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
static inline bool
hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
{
-#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || (defined(__clang__) && (__clang_major__ >= 8))
unsigned stack_result;
if (!result)
result = &stack_result;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-array.hh
index 17562bc336..e82c081535 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-array.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-array.hh
@@ -304,6 +304,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
unsigned int backwards_length = 0;
};
template <typename T> inline hb_array_t<T>
+hb_array ()
+{ return hb_array_t<T> (); }
+template <typename T> inline hb_array_t<T>
hb_array (T *array, unsigned int length)
{ return hb_array_t<T> (array, length); }
template <typename T, unsigned int length_> inline hb_array_t<T>
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
index 14c6fb3264..a6283de140 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
@@ -84,11 +84,11 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#define _hb_memory_r_barrier() std::atomic_thread_fence(std::memory_order_acquire)
#define _hb_memory_w_barrier() std::atomic_thread_fence(std::memory_order_release)
-#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
-#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_relaxed))
-#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_release))
-#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<int> const *> (AI)->load (std::memory_order_relaxed))
-#define hb_atomic_int_impl_get(AI) (reinterpret_cast<std::atomic<int> const *> (AI)->load (std::memory_order_acquire))
+#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
+#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_release))
+#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_relaxed))
+#define hb_atomic_int_impl_get(AI) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_acquire))
#define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast<std::atomic<void*> *> (P)->store ((V), std::memory_order_relaxed))
#define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast<std::atomic<void*> const *> (P)->load (std::memory_order_relaxed))
@@ -111,10 +111,15 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#endif
+/* This should never be disabled, even under HB_NO_MT.
+ * except that MSVC gives me an internal compiler error, so disabled there.
+ *
+ * https://github.com/harfbuzz/harfbuzz/pull/4119
+ */
#ifndef _hb_compiler_memory_r_barrier
-/* This we always use std::atomic for; and should never be disabled...
- * except that MSVC gives me an internal compiler error on it. */
-#if !defined(_MSC_VER)
+#if defined(__ATOMIC_ACQUIRE) // gcc-like
+#define _hb_compiler_memory_r_barrier() asm volatile("": : :"memory")
+#elif !defined(_MSC_VER)
#include <atomic>
#define _hb_compiler_memory_r_barrier() std::atomic_signal_fence (std::memory_order_acquire)
#else
@@ -145,15 +150,35 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#endif
#ifndef hb_atomic_int_impl_set
inline void hb_atomic_int_impl_set (int *AI, int v) { _hb_memory_w_barrier (); *AI = v; }
+inline void hb_atomic_int_impl_set (short *AI, short v) { _hb_memory_w_barrier (); *AI = v; }
#endif
#ifndef hb_atomic_int_impl_get
inline int hb_atomic_int_impl_get (const int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; }
+inline short hb_atomic_int_impl_get (const short *AI) { short v = *AI; _hb_memory_r_barrier (); return v; }
#endif
#ifndef hb_atomic_ptr_impl_get
inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; }
#endif
+struct hb_atomic_short_t
+{
+ hb_atomic_short_t () = default;
+ constexpr hb_atomic_short_t (short v) : v (v) {}
+
+ hb_atomic_short_t& operator = (short v_) { set_relaxed (v_); return *this; }
+ operator short () const { return get_relaxed (); }
+
+ void set_relaxed (short v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
+ void set_release (short v_) { hb_atomic_int_impl_set (&v, v_); }
+ short get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
+ short get_acquire () const { return hb_atomic_int_impl_get (&v); }
+ short inc () { return hb_atomic_int_impl_add (&v, 1); }
+ short dec () { return hb_atomic_int_impl_add (&v, -1); }
+
+ short v = 0;
+};
+
struct hb_atomic_int_t
{
hb_atomic_int_t () = default;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
index 11987054f8..9b027ac590 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
@@ -34,14 +34,24 @@
/* Compiler-assisted vectorization. */
/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
- * basically a fixed-size bitset. */
+ * basically a fixed-size bitset. We can't use the compiler type because hb_vector_t cannot
+ * guarantee alignment requirements. */
template <typename elt_t, unsigned int byte_size>
struct hb_vector_size_t
{
elt_t& operator [] (unsigned int i) { return v[i]; }
const elt_t& operator [] (unsigned int i) const { return v[i]; }
- void clear (unsigned char v = 0) { hb_memset (this, v, sizeof (*this)); }
+ void init0 ()
+ {
+ for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+ v[i] = 0;
+ }
+ void init1 ()
+ {
+ for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+ v[i] = (elt_t) -1;
+ }
template <typename Op>
hb_vector_size_t process (const Op& op) const
@@ -79,10 +89,10 @@ struct hb_vector_size_t
struct hb_bit_page_t
{
- void init0 () { v.clear (); }
- void init1 () { v.clear (0xFF); }
+ void init0 () { v.init0 (); }
+ void init1 () { v.init1 (); }
- constexpr unsigned len () const
+ static inline constexpr unsigned len ()
{ return ARRAY_LENGTH_CONST (v); }
bool is_empty () const
@@ -300,10 +310,10 @@ struct hb_bit_page_t
static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
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 constexpr unsigned PAGE_BITS_LOG_2 = 9; // 512 bits
+ static constexpr unsigned PAGE_BITS = 1 << PAGE_BITS_LOG_2;
static_assert (1 << PAGE_BITS_LOG_2 == PAGE_BITS, "");
+ static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
static constexpr unsigned PAGE_BITMASK = PAGE_BITS - 1;
static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
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 ff8aecc60c..1eb1b1c209 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh
@@ -74,6 +74,11 @@ struct hb_bit_set_invertible_t
inverted = !inverted;
}
+ bool is_inverted () const
+ {
+ return inverted;
+ }
+
bool is_empty () const
{
hb_codepoint_t v = INVALID;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
index 8de6e037fb..475b07b810 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
@@ -38,7 +38,7 @@ struct hb_bit_set_t
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); }
+ hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other, true); }
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; }
@@ -85,12 +85,16 @@ struct hb_bit_set_t
void err () { if (successful) successful = false; } /* TODO Remove */
bool in_error () const { return !successful; }
- bool resize (unsigned int count, bool clear = true)
+ bool resize (unsigned int count, bool clear = true, bool exact_size = false)
{
if (unlikely (!successful)) return false;
- if (unlikely (!pages.resize (count, clear) || !page_map.resize (count, clear)))
+
+ if (pages.length == 0 && count == 1)
+ exact_size = true; // Most sets are small and local
+
+ if (unlikely (!pages.resize (count, clear, exact_size) || !page_map.resize (count, clear, exact_size)))
{
- pages.resize (page_map.length);
+ pages.resize (page_map.length, clear, exact_size);
successful = false;
return false;
}
@@ -346,11 +350,11 @@ struct hb_bit_set_t
hb_codepoint_t c = first - 1;
return next (&c) && c <= last;
}
- void set (const hb_bit_set_t &other)
+ void set (const hb_bit_set_t &other, bool exact_size = false)
{
if (unlikely (!successful)) return;
unsigned int count = other.pages.length;
- if (unlikely (!resize (count, false)))
+ if (unlikely (!resize (count, false, exact_size)))
return;
population = other.population;
@@ -422,7 +426,7 @@ struct hb_bit_set_t
private:
bool allocate_compact_workspace (hb_vector_t<unsigned>& workspace)
{
- if (unlikely (!workspace.resize (pages.length)))
+ if (unlikely (!workspace.resize_exact (pages.length)))
{
successful = false;
return false;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
index f0fda1fa4d..265effba03 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
@@ -676,7 +676,7 @@ fail_without_close:
wchar_t * wchar_file_name = (wchar_t *) hb_malloc (sizeof (wchar_t) * size);
if (unlikely (!wchar_file_name)) goto fail_without_close;
mbstowcs (wchar_file_name, file_name, size);
-#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
{
CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 };
ceparams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
@@ -697,7 +697,7 @@ fail_without_close:
if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
-#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
{
LARGE_INTEGER length;
GetFileSizeEx (fd, &length);
@@ -710,7 +710,7 @@ fail_without_close:
#endif
if (unlikely (!file->mapping)) goto fail;
-#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0);
#else
file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh
index 993bb1f698..004a9fb8b7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh
@@ -35,34 +35,34 @@
#line 33 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = {
0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
- 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
- 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u,
- 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u,
- 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u,
- 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u, 9u, 125u,
- 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 93u,
+ 48u, 57u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
+ 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u,
+ 9u, 125u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u,
+ 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u,
+ 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u,
+ 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u,
9u, 123u, 0u, 0u, 0
};
static const char _deserialize_json_key_spans[] = {
0, 115, 26, 21, 2, 1, 50, 49,
- 10, 117, 117, 117, 1, 50, 49, 10,
- 117, 117, 1, 1, 50, 49, 117, 117,
- 2, 1, 50, 49, 10, 117, 117, 1,
- 50, 49, 10, 117, 117, 1, 1, 50,
- 49, 117, 117, 1, 50, 49, 59, 117,
- 59, 117, 117, 1, 50, 49, 117, 85,
+ 10, 117, 117, 85, 117, 1, 50, 49,
+ 10, 117, 117, 1, 1, 50, 49, 117,
+ 117, 2, 1, 50, 49, 10, 117, 117,
+ 1, 50, 49, 10, 117, 117, 1, 1,
+ 50, 49, 117, 117, 1, 50, 49, 59,
+ 117, 59, 117, 117, 1, 50, 49, 117,
115, 0
};
static const short _deserialize_json_index_offsets[] = {
0, 0, 116, 143, 165, 168, 170, 221,
- 271, 282, 400, 518, 636, 638, 689, 739,
- 750, 868, 986, 988, 990, 1041, 1091, 1209,
- 1327, 1330, 1332, 1383, 1433, 1444, 1562, 1680,
- 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2034,
- 2085, 2135, 2253, 2371, 2373, 2424, 2474, 2534,
- 2652, 2712, 2830, 2948, 2950, 3001, 3051, 3169,
+ 271, 282, 400, 518, 604, 722, 724, 775,
+ 825, 836, 954, 1072, 1074, 1076, 1127, 1177,
+ 1295, 1413, 1416, 1418, 1469, 1519, 1530, 1648,
+ 1766, 1768, 1819, 1869, 1880, 1998, 2116, 2118,
+ 2120, 2171, 2221, 2339, 2457, 2459, 2510, 2560,
+ 2620, 2738, 2798, 2916, 3034, 3036, 3087, 3137,
3255, 3371
};
@@ -131,57 +131,54 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 24, 1, 20,
- 20, 20, 20, 20, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 20, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 21, 1, 1, 1, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,
- 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 24, 1, 25,
+ 25, 25, 25, 25, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 25, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 26, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 22, 1, 25, 1, 25,
- 25, 25, 25, 25, 1, 1, 1, 1,
+ 1, 1, 1, 27, 1, 20, 20, 20,
+ 20, 20, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 25, 1,
+ 1, 1, 1, 1, 20, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 21, 1, 1, 1, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 26, 1, 26, 26, 26, 26, 26, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 26, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 27, 1,
- 1, 28, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 1, 30, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 1, 32,
- 32, 32, 32, 32, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 32, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 33, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 22, 1, 28, 1, 28, 28, 28,
+ 28, 28, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 28, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 29, 1,
+ 29, 29, 29, 29, 29, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 29,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 30, 1, 1, 31,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 1, 33, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 1, 35, 35, 35,
+ 35, 35, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 35, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 34, 1, 32, 32, 32,
- 32, 32, 1, 1, 1, 1, 1, 1,
+ 36, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 32, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 33, 1, 1, 1, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -189,291 +186,294 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 37, 1, 35, 35, 35, 35, 35,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 34, 1, 35, 1, 36, 1, 36,
- 36, 36, 36, 36, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 35, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 36, 1,
+ 1, 1, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 37, 1, 37, 37, 37, 37, 37, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 37, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 38, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 1, 40, 40, 40, 40,
- 40, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 40, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 41,
+ 1, 1, 1, 1, 1, 1, 1, 37,
+ 1, 38, 1, 39, 1, 39, 39, 39,
+ 39, 39, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 39, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 40, 1,
+ 40, 40, 40, 40, 40, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 40,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 41,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 1, 43, 43, 43, 43, 43, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 43, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 44, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 42, 1, 40, 40, 40, 40, 40, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 40, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 41, 1, 1,
- 1, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 45, 1,
+ 43, 43, 43, 43, 43, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 43,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 44, 1, 1, 1, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46,
+ 46, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 42, 1,
- 44, 45, 1, 46, 1, 46, 46, 46,
- 46, 46, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 46, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 47, 1,
- 47, 47, 47, 47, 47, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 47,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 48, 1, 1, 49,
- 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 1, 51, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 1, 53, 53, 53,
- 53, 53, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 53, 1, 1, 1,
+ 1, 1, 1, 1, 45, 1, 47, 48,
+ 1, 49, 1, 49, 49, 49, 49, 49,
1, 1, 1, 1, 1, 1, 1, 1,
- 54, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 49, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 50, 1, 50, 50,
+ 50, 50, 50, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 50, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 51, 1, 1, 52, 53, 53,
+ 53, 53, 53, 53, 53, 53, 53, 1,
+ 54, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 1, 56, 56, 56, 56, 56,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 56, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 57, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 55, 1, 53, 53, 53, 53, 53,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 53, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 54, 1,
- 1, 1, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 58,
+ 1, 56, 56, 56, 56, 56, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 55,
- 1, 56, 1, 56, 56, 56, 56, 56,
+ 56, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 57, 1, 1, 1,
+ 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 56, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 57, 1, 57, 57,
- 57, 57, 57, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 57, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 58, 1, 1, 59, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 1,
- 61, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 1, 63, 63, 63, 63, 63,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 58, 1, 59,
+ 1, 59, 59, 59, 59, 59, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 63, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 64, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 59, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 60, 1, 60, 60, 60, 60,
+ 60, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 60, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 61, 1, 1, 62, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 1, 64, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65,
+ 1, 66, 66, 66, 66, 66, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 66, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 67, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 65,
- 1, 63, 63, 63, 63, 63, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 63, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 64, 1, 1, 1,
- 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 68, 1, 66,
+ 66, 66, 66, 66, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 66, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 65, 1, 66,
- 1, 67, 1, 67, 67, 67, 67, 67,
+ 1, 1, 67, 1, 1, 1, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 67, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 68, 1, 68, 68,
- 68, 68, 68, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 68, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 69, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 1,
- 71, 71, 71, 71, 71, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 71,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 72, 1, 1, 1, 1,
+ 1, 1, 1, 68, 1, 69, 1, 70,
+ 1, 70, 70, 70, 70, 70, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 70, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 71, 1, 71, 71, 71, 71,
+ 71, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 71, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 72, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 1, 74, 74,
+ 74, 74, 74, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 74, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 75, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 73, 1, 71, 71,
- 71, 71, 71, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 71, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 72, 1, 1, 1, 74, 74, 74,
- 74, 74, 74, 74, 74, 74, 74, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 76, 1, 74, 74, 74, 74,
+ 74, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 74, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 75,
+ 1, 1, 1, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 73, 1, 75, 1, 75, 75,
- 75, 75, 75, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 75, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 76,
- 1, 76, 76, 76, 76, 76, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 76, 1, 77, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 78, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 1, 81, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 82, 80, 83,
- 83, 83, 83, 83, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 83, 1,
+ 76, 1, 78, 1, 78, 78, 78, 78,
+ 78, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 84, 1, 1, 1, 1, 1,
+ 1, 1, 1, 78, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 79, 1, 79,
+ 79, 79, 79, 79, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 79, 1,
+ 80, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 81, 82,
+ 82, 82, 82, 82, 82, 82, 82, 82,
+ 1, 84, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 85, 83, 86, 86, 86,
+ 86, 86, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 86, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 87, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 85, 1, 80, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 88, 1, 83, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 80,
- 1, 86, 86, 86, 86, 86, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 86, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 87, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 83, 1, 89,
+ 89, 89, 89, 89, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 89, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 90, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 88, 1, 86,
- 86, 86, 86, 86, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 86, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 87, 1, 1, 1, 89, 89,
- 89, 89, 89, 89, 89, 89, 89, 89,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 91, 1, 89, 89, 89,
+ 89, 89, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 89, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 90, 1, 1, 1, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 88, 1, 90, 1, 90,
- 90, 90, 90, 90, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 90, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 91, 1, 91, 91, 91, 91, 91, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 91, 1, 93, 1, 93, 93, 93,
+ 93, 93, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 91, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 93, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 92, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 1, 86, 86, 86, 86,
- 86, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 86, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 87,
- 1, 1, 1, 94, 94, 94, 94, 94,
+ 1, 1, 1, 1, 1, 1, 94, 1,
94, 94, 94, 94, 94, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 94,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 95,
+ 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 1, 89, 89, 89, 89, 89, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 89, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 90, 1, 1,
+ 1, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 88, 1, 95, 95, 95, 95, 95, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 95, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 96, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 97, 1,
+ 1, 1, 1, 1, 1, 1, 91, 1,
0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 0,
@@ -492,39 +492,39 @@ static const char _deserialize_json_indicies[] = {
};
static const char _deserialize_json_trans_targs[] = {
- 1, 0, 2, 2, 3, 4, 18, 24,
- 37, 43, 51, 5, 12, 6, 7, 8,
- 9, 11, 9, 11, 10, 2, 55, 10,
- 55, 13, 14, 15, 16, 17, 16, 17,
- 10, 2, 55, 19, 20, 21, 22, 23,
- 10, 2, 55, 23, 25, 31, 26, 27,
- 28, 29, 30, 29, 30, 10, 2, 55,
- 32, 33, 34, 35, 36, 35, 36, 10,
- 2, 55, 38, 39, 40, 41, 42, 10,
- 2, 55, 42, 44, 45, 46, 49, 50,
- 46, 47, 48, 10, 2, 55, 10, 2,
- 55, 50, 52, 53, 49, 54, 54, 55,
- 56, 57
+ 1, 0, 2, 2, 3, 4, 19, 25,
+ 38, 44, 52, 5, 13, 6, 7, 8,
+ 9, 12, 9, 12, 10, 2, 11, 10,
+ 11, 11, 56, 57, 14, 15, 16, 17,
+ 18, 17, 18, 10, 2, 11, 20, 21,
+ 22, 23, 24, 10, 2, 11, 24, 26,
+ 32, 27, 28, 29, 30, 31, 30, 31,
+ 10, 2, 11, 33, 34, 35, 36, 37,
+ 36, 37, 10, 2, 11, 39, 40, 41,
+ 42, 43, 10, 2, 11, 43, 45, 46,
+ 47, 50, 51, 47, 48, 49, 10, 2,
+ 11, 10, 2, 11, 51, 53, 54, 50,
+ 55, 55
};
static const char _deserialize_json_trans_actions[] = {
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 2,
2, 2, 0, 0, 3, 3, 4, 0,
- 5, 0, 0, 2, 2, 2, 0, 0,
- 6, 6, 7, 0, 0, 0, 2, 2,
- 8, 8, 9, 0, 0, 0, 0, 0,
- 2, 2, 2, 0, 0, 10, 10, 11,
- 0, 0, 2, 2, 2, 0, 0, 12,
- 12, 13, 0, 0, 0, 2, 2, 14,
- 14, 15, 0, 0, 0, 2, 16, 16,
- 0, 17, 0, 18, 18, 19, 20, 20,
- 21, 17, 0, 0, 22, 22, 23, 0,
- 0, 0
+ 5, 0, 0, 0, 0, 0, 2, 2,
+ 2, 0, 0, 6, 6, 7, 0, 0,
+ 0, 2, 2, 8, 8, 9, 0, 0,
+ 0, 0, 0, 2, 2, 2, 0, 0,
+ 10, 10, 11, 0, 0, 2, 2, 2,
+ 0, 0, 12, 12, 13, 0, 0, 0,
+ 2, 2, 14, 14, 15, 0, 0, 0,
+ 2, 16, 16, 0, 17, 0, 18, 18,
+ 19, 20, 20, 21, 17, 0, 0, 22,
+ 22, 23
};
static const int deserialize_json_start = 1;
-static const int deserialize_json_first_final = 55;
+static const int deserialize_json_first_final = 56;
static const int deserialize_json_error = 0;
static const int deserialize_json_en_main = 1;
@@ -548,21 +548,19 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer,
while (p < pe && ISSPACE (*p))
p++;
if (p < pe && *p == (buffer->len ? ',' : '['))
- {
*end_ptr = ++p;
- }
const char *tok = nullptr;
int cs;
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 554 "hb-buffer-deserialize-json.hh"
+#line 552 "hb-buffer-deserialize-json.hh"
{
cs = deserialize_json_start;
}
-#line 557 "hb-buffer-deserialize-json.hh"
+#line 555 "hb-buffer-deserialize-json.hh"
{
int _slen;
int _trans;
@@ -774,7 +772,7 @@ _resume:
*end_ptr = p;
}
break;
-#line 735 "hb-buffer-deserialize-json.hh"
+#line 733 "hb-buffer-deserialize-json.hh"
}
_again:
@@ -786,7 +784,7 @@ _again:
_out: {}
}
-#line 139 "hb-buffer-deserialize-json.rl"
+#line 137 "hb-buffer-deserialize-json.rl"
*end_ptr = p;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-glyphs.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-glyphs.hh
new file mode 100644
index 0000000000..ea81273b31
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-glyphs.hh
@@ -0,0 +1,692 @@
+
+#line 1 "hb-buffer-deserialize-text-glyphs.rl"
+/*
+ * Copyright © 2013 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BUFFER_DESERIALIZE_TEXT_GLYPHS_HH
+#define HB_BUFFER_DESERIALIZE_TEXT_GLYPHS_HH
+
+#include "hb.hh"
+
+
+#line 36 "hb-buffer-deserialize-text-glyphs.hh"
+static const unsigned char _deserialize_text_glyphs_trans_keys[] = {
+ 0u, 0u, 48u, 57u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u,
+ 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 9u, 124u, 9u, 124u,
+ 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
+ 9u, 124u, 9u, 124u, 9u, 124u, 0
+};
+
+static const char _deserialize_text_glyphs_key_spans[] = {
+ 0, 10, 13, 10, 13, 10, 10, 13,
+ 10, 1, 13, 10, 14, 82, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116
+};
+
+static const short _deserialize_text_glyphs_index_offsets[] = {
+ 0, 0, 11, 25, 36, 50, 61, 72,
+ 86, 97, 99, 113, 124, 139, 222, 339,
+ 456, 573, 690, 807, 924, 1041, 1158, 1275,
+ 1392, 1509, 1626
+};
+
+static const char _deserialize_text_glyphs_indicies[] = {
+ 0, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 3, 1, 1, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 1, 6, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 1, 8, 1, 1,
+ 9, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 1, 11, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 1, 13, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 1, 15, 1, 1, 16, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 1, 18,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 1, 20, 1, 21, 1, 1, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 1, 24, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 1, 20, 1, 1,
+ 1, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 1, 26, 26, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 26, 1,
+ 1, 26, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 26, 26, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 26, 1, 28,
+ 28, 28, 28, 28, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 28, 27,
+ 27, 29, 27, 27, 27, 27, 27, 27,
+ 27, 30, 1, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 31, 27, 27, 32, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 33, 1, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 28, 27, 34, 34, 34, 34,
+ 34, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 34, 26, 26, 35, 26,
+ 26, 26, 26, 26, 26, 26, 36, 1,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 37, 26, 26, 38, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 39,
+ 1, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 40,
+ 26, 41, 41, 41, 41, 41, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 41, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 42, 1, 43, 43,
+ 43, 43, 43, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 43, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 44, 1, 41, 41, 41, 41, 41,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 41, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 42, 1,
+ 46, 46, 46, 46, 46, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 46,
+ 1, 1, 47, 1, 1, 1, 1, 1,
+ 1, 1, 1, 48, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 49, 1, 50, 50, 50,
+ 50, 50, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 50, 1, 1, 51,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 52, 1, 50, 50, 50, 50, 50, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 50, 1, 1, 51, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 52, 1, 46,
+ 46, 46, 46, 46, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 46, 1,
+ 1, 47, 1, 1, 1, 1, 1, 1,
+ 1, 1, 48, 1, 1, 1, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 49, 1, 53, 53, 53, 53,
+ 53, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 53, 1, 1, 54, 1,
+ 1, 1, 1, 1, 1, 1, 55, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 56, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 57,
+ 1, 58, 58, 58, 58, 58, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 58, 1, 1, 59, 1, 1, 1, 1,
+ 1, 1, 1, 60, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 61, 1, 58, 58,
+ 58, 58, 58, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 58, 1, 1,
+ 59, 1, 1, 1, 1, 1, 1, 1,
+ 60, 1, 1, 1, 1, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 61, 1, 53, 53, 53, 53, 53,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 53, 1, 1, 54, 1, 1,
+ 1, 1, 1, 1, 1, 55, 1, 1,
+ 1, 1, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 1, 1, 1, 1,
+ 1, 1, 56, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 57, 1,
+ 0
+};
+
+static const char _deserialize_text_glyphs_trans_targs[] = {
+ 16, 0, 18, 3, 19, 22, 19, 22,
+ 5, 20, 21, 20, 21, 23, 26, 8,
+ 9, 12, 9, 12, 10, 11, 24, 25,
+ 24, 25, 15, 15, 14, 1, 2, 6,
+ 7, 13, 15, 1, 2, 6, 7, 13,
+ 14, 17, 14, 17, 14, 18, 17, 1,
+ 4, 14, 17, 1, 14, 17, 1, 2,
+ 7, 14, 17, 1, 2, 14, 26
+};
+
+static const char _deserialize_text_glyphs_trans_actions[] = {
+ 1, 0, 1, 1, 1, 1, 0, 0,
+ 1, 1, 1, 0, 0, 1, 1, 1,
+ 1, 1, 0, 0, 2, 1, 1, 1,
+ 0, 0, 0, 4, 3, 5, 5, 5,
+ 5, 4, 6, 7, 7, 7, 7, 0,
+ 6, 8, 8, 0, 0, 0, 9, 10,
+ 10, 9, 11, 12, 11, 13, 14, 14,
+ 14, 13, 15, 16, 16, 15, 0
+};
+
+static const char _deserialize_text_glyphs_eof_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3, 6,
+ 8, 0, 8, 9, 11, 11, 9, 13,
+ 15, 15, 13
+};
+
+static const int deserialize_text_glyphs_start = 14;
+static const int deserialize_text_glyphs_first_final = 14;
+static const int deserialize_text_glyphs_error = 0;
+
+static const int deserialize_text_glyphs_en_main = 14;
+
+
+#line 98 "hb-buffer-deserialize-text-glyphs.rl"
+
+
+static hb_bool_t
+_hb_buffer_deserialize_text_glyphs (hb_buffer_t *buffer,
+ const char *buf,
+ unsigned int buf_len,
+ const char **end_ptr,
+ hb_font_t *font)
+{
+ const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
+
+ /* Ensure we have positions. */
+ (void) hb_buffer_get_glyph_positions (buffer, nullptr);
+
+ while (p < pe && ISSPACE (*p))
+ p++;
+ if (p < pe && *p == (buffer->len ? '|' : '['))
+ *end_ptr = ++p;
+
+ const char *end = strchr ((char *) p, ']');
+ if (end)
+ pe = eof = end;
+ else
+ {
+ end = strrchr ((char *) p, '|');
+ if (end)
+ pe = eof = end;
+ else
+ pe = eof = p;
+ }
+
+ const char *tok = nullptr;
+ int cs;
+ hb_glyph_info_t info = {0};
+ hb_glyph_position_t pos = {0};
+
+#line 353 "hb-buffer-deserialize-text-glyphs.hh"
+ {
+ cs = deserialize_text_glyphs_start;
+ }
+
+#line 358 "hb-buffer-deserialize-text-glyphs.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _keys = _deserialize_text_glyphs_trans_keys + (cs<<1);
+ _inds = _deserialize_text_glyphs_indicies + _deserialize_text_glyphs_index_offsets[cs];
+
+ _slen = _deserialize_text_glyphs_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
+ (*p) <= _keys[1] ?
+ (*p) - _keys[0] : _slen ];
+
+ cs = _deserialize_text_glyphs_trans_targs[_trans];
+
+ if ( _deserialize_text_glyphs_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _deserialize_text_glyphs_trans_actions[_trans] ) {
+ case 1:
+#line 51 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
+}
+ break;
+ case 7:
+#line 55 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+ break;
+ case 14:
+#line 63 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_uint (tok, p, &info.cluster )) return false; }
+ break;
+ case 2:
+#line 64 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.x_offset )) return false; }
+ break;
+ case 16:
+#line 65 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.y_offset )) return false; }
+ break;
+ case 10:
+#line 66 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.x_advance)) return false; }
+ break;
+ case 12:
+#line 67 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.y_advance)) return false; }
+ break;
+ case 4:
+#line 38 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
+}
+#line 51 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
+}
+ break;
+ case 6:
+#line 55 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 13:
+#line 63 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_uint (tok, p, &info.cluster )) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 15:
+#line 65 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.y_offset )) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 9:
+#line 66 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.x_advance)) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 11:
+#line 67 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.y_advance)) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 8:
+#line 68 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 5:
+#line 38 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
+}
+#line 51 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
+}
+#line 55 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+ break;
+ case 3:
+#line 38 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
+}
+#line 51 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
+}
+#line 55 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+#line 554 "hb-buffer-deserialize-text-glyphs.hh"
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ switch ( _deserialize_text_glyphs_eof_actions[cs] ) {
+ case 6:
+#line 55 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 13:
+#line 63 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_uint (tok, p, &info.cluster )) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 15:
+#line 65 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.y_offset )) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 9:
+#line 66 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.x_advance)) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 11:
+#line 67 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_int (tok, p, &pos.y_advance)) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 8:
+#line 68 "hb-buffer-deserialize-text-glyphs.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 3:
+#line 38 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
+}
+#line 51 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ tok = p;
+}
+#line 55 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 43 "hb-buffer-deserialize-text-glyphs.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+#line 671 "hb-buffer-deserialize-text-glyphs.hh"
+ }
+ }
+
+ _out: {}
+ }
+
+#line 136 "hb-buffer-deserialize-text-glyphs.rl"
+
+
+ if (pe < orig_pe && *pe == ']')
+ {
+ pe++;
+ if (p == pe)
+ p++;
+ }
+
+ *end_ptr = p;
+
+ return p == pe;
+}
+
+#endif /* HB_BUFFER_DESERIALIZE_TEXT_GLYPHS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-unicode.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-unicode.hh
new file mode 100644
index 0000000000..8ca73bf25f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-unicode.hh
@@ -0,0 +1,332 @@
+
+#line 1 "hb-buffer-deserialize-text-unicode.rl"
+/*
+ * Copyright © 2013 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BUFFER_DESERIALIZE_TEXT_UNICODE_HH
+#define HB_BUFFER_DESERIALIZE_TEXT_UNICODE_HH
+
+#include "hb.hh"
+
+
+#line 33 "hb-buffer-deserialize-text-unicode.hh"
+static const unsigned char _deserialize_text_unicode_trans_keys[] = {
+ 0u, 0u, 9u, 117u, 43u, 102u, 48u, 102u, 48u, 57u, 9u, 124u, 9u, 124u, 9u, 124u,
+ 9u, 124u, 0
+};
+
+static const char _deserialize_text_unicode_key_spans[] = {
+ 0, 109, 60, 55, 10, 116, 116, 116,
+ 116
+};
+
+static const short _deserialize_text_unicode_index_offsets[] = {
+ 0, 0, 110, 171, 227, 238, 355, 472,
+ 589
+};
+
+static const char _deserialize_text_unicode_indicies[] = {
+ 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 1, 3,
+ 1, 1, 1, 1, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 1, 1,
+ 1, 1, 1, 1, 1, 4, 4, 4,
+ 4, 4, 4, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 4, 4, 4,
+ 4, 4, 4, 1, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 1, 1,
+ 1, 1, 1, 1, 1, 4, 4, 4,
+ 4, 4, 4, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 4, 4, 4,
+ 4, 4, 4, 1, 5, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 1, 7,
+ 7, 7, 7, 7, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 7, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 1, 1, 1, 9, 1, 1, 1, 8,
+ 8, 8, 8, 8, 8, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 8,
+ 8, 8, 8, 8, 8, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 10, 1, 11, 11, 11, 11,
+ 11, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 11, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0,
+ 1, 12, 12, 12, 12, 12, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 12, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 13, 1, 12, 12,
+ 12, 12, 12, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 12, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 13, 1, 0
+};
+
+static const char _deserialize_text_unicode_trans_targs[] = {
+ 1, 0, 2, 3, 5, 7, 8, 6,
+ 5, 4, 1, 6, 6, 1, 8
+};
+
+static const char _deserialize_text_unicode_trans_actions[] = {
+ 0, 0, 1, 0, 2, 2, 2, 3,
+ 0, 4, 3, 0, 5, 5, 0
+};
+
+static const char _deserialize_text_unicode_eof_actions[] = {
+ 0, 0, 0, 0, 0, 3, 0, 5,
+ 5
+};
+
+static const int deserialize_text_unicode_start = 1;
+static const int deserialize_text_unicode_first_final = 5;
+static const int deserialize_text_unicode_error = 0;
+
+static const int deserialize_text_unicode_en_main = 1;
+
+
+#line 79 "hb-buffer-deserialize-text-unicode.rl"
+
+
+static hb_bool_t
+_hb_buffer_deserialize_text_unicode (hb_buffer_t *buffer,
+ const char *buf,
+ unsigned int buf_len,
+ const char **end_ptr,
+ hb_font_t *font)
+{
+ const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
+
+ while (p < pe && ISSPACE (*p))
+ p++;
+ if (p < pe && *p == (buffer->len ? '|' : '<'))
+ *end_ptr = ++p;
+
+ const char *end = strchr ((char *) p, '>');
+ if (end)
+ pe = eof = end;
+ else
+ {
+ end = strrchr ((char *) p, '|');
+ if (end)
+ pe = eof = end;
+ else
+ pe = eof = p;
+ }
+
+
+ const char *tok = nullptr;
+ int cs;
+ hb_glyph_info_t info = {0};
+ const hb_glyph_position_t pos = {0};
+
+#line 194 "hb-buffer-deserialize-text-unicode.hh"
+ {
+ cs = deserialize_text_unicode_start;
+ }
+
+#line 197 "hb-buffer-deserialize-text-unicode.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _keys = _deserialize_text_unicode_trans_keys + (cs<<1);
+ _inds = _deserialize_text_unicode_indicies + _deserialize_text_unicode_index_offsets[cs];
+
+ _slen = _deserialize_text_unicode_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
+ (*p) <= _keys[1] ?
+ (*p) - _keys[0] : _slen ];
+
+ cs = _deserialize_text_unicode_trans_targs[_trans];
+
+ if ( _deserialize_text_unicode_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _deserialize_text_unicode_trans_actions[_trans] ) {
+ case 1:
+#line 38 "hb-buffer-deserialize-text-unicode.rl"
+ {
+ hb_memset (&info, 0, sizeof (info));
+}
+ break;
+ case 2:
+#line 51 "hb-buffer-deserialize-text-unicode.rl"
+ {
+ tok = p;
+}
+ break;
+ case 4:
+#line 55 "hb-buffer-deserialize-text-unicode.rl"
+ {if (!parse_hex (tok, p, &info.codepoint )) return false; }
+ break;
+ case 3:
+#line 55 "hb-buffer-deserialize-text-unicode.rl"
+ {if (!parse_hex (tok, p, &info.codepoint )) return false; }
+#line 42 "hb-buffer-deserialize-text-unicode.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ if (buffer->have_positions)
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 5:
+#line 57 "hb-buffer-deserialize-text-unicode.rl"
+ { if (!parse_uint (tok, p, &info.cluster )) return false; }
+#line 42 "hb-buffer-deserialize-text-unicode.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ if (buffer->have_positions)
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+#line 256 "hb-buffer-deserialize-text-unicode.hh"
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ switch ( _deserialize_text_unicode_eof_actions[cs] ) {
+ case 3:
+#line 55 "hb-buffer-deserialize-text-unicode.rl"
+ {if (!parse_hex (tok, p, &info.codepoint )) return false; }
+#line 42 "hb-buffer-deserialize-text-unicode.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ if (buffer->have_positions)
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 5:
+#line 57 "hb-buffer-deserialize-text-unicode.rl"
+ { if (!parse_uint (tok, p, &info.cluster )) return false; }
+#line 42 "hb-buffer-deserialize-text-unicode.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ if (buffer->have_positions)
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+#line 289 "hb-buffer-deserialize-text-unicode.hh"
+ }
+ }
+
+ _out: {}
+ }
+
+#line 115 "hb-buffer-deserialize-text-unicode.rl"
+
+
+ if (pe < orig_pe && *pe == '>')
+ {
+ pe++;
+ if (p == pe)
+ p++;
+ }
+
+ *end_ptr = p;
+
+ return p == pe;
+}
+
+#endif /* HB_BUFFER_DESERIALIZE_TEXT_UNICODE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh
deleted file mode 100644
index 6b9b4282fc..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh
+++ /dev/null
@@ -1,917 +0,0 @@
-
-#line 1 "hb-buffer-deserialize-text.rl"
-/*
- * Copyright © 2013 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
-#define HB_BUFFER_DESERIALIZE_TEXT_HH
-
-#include "hb.hh"
-
-
-#line 33 "hb-buffer-deserialize-text.hh"
-static const unsigned char _deserialize_text_trans_keys[] = {
- 0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 48u, 57u,
- 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u,
- 45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u,
- 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
- 0
-};
-
-static const char _deserialize_text_key_spans[] = {
- 0, 83, 1, 1, 55, 77, 10, 10,
- 13, 10, 13, 10, 10, 13, 10, 1,
- 13, 10, 14, 82, 116, 116, 0, 77,
- 116, 116, 116, 116, 116, 116, 116, 116,
- 116, 116, 116, 116, 116, 116, 116, 116
-};
-
-static const short _deserialize_text_index_offsets[] = {
- 0, 0, 84, 86, 88, 144, 222, 233,
- 244, 258, 269, 283, 294, 305, 319, 330,
- 332, 346, 357, 372, 455, 572, 689, 690,
- 768, 885, 1002, 1119, 1236, 1353, 1470, 1587,
- 1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523
-};
-
-static const char _deserialize_text_indicies[] = {
- 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 3, 1, 4, 1, 5,
- 1, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 1, 1, 1, 1, 1,
- 1, 1, 6, 6, 6, 6, 6, 6,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 6, 6, 6, 6, 6, 6,
- 1, 7, 7, 7, 7, 7, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 7, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 4, 1, 8,
- 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 1, 10, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 1, 12, 1, 1,
- 13, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 1, 15, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 1, 17, 1,
- 1, 18, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 1, 20, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 1, 22,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 1, 24, 1, 1, 25, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 1,
- 27, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 1, 29, 1, 30, 1, 1,
- 31, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 1, 33, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 1, 29, 1,
- 1, 1, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 1, 35, 35, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 35,
- 1, 1, 35, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 35, 35,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 35, 1,
- 36, 36, 36, 36, 36, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 36,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 1, 1, 1, 38, 39, 1, 1,
- 37, 37, 37, 37, 37, 37, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 37, 37, 37, 37, 37, 37, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 40, 1, 41, 41, 41,
- 41, 41, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 41, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 42, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 43, 1, 1, 7, 7, 7, 7, 7,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 7, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 4,
- 1, 44, 44, 44, 44, 44, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 44, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 45, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 46, 1, 44, 44,
- 44, 44, 44, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 44, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 1,
- 1, 1, 1, 45, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 46, 1, 49, 49, 49, 49, 49,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 49, 48, 48, 50, 48, 48,
- 48, 48, 48, 48, 48, 51, 1, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 52,
- 48, 48, 53, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 54, 55,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 56, 48,
- 57, 57, 57, 57, 57, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 57,
- 35, 35, 58, 35, 35, 35, 35, 35,
- 35, 35, 59, 1, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 60, 35, 35, 61,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 62, 63, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 64, 35, 65, 65, 65,
- 65, 65, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 65, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 66, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 67, 1, 68, 68, 68, 68, 68, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 68, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 42, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 69, 1, 70,
- 70, 70, 70, 70, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 70, 48,
- 48, 50, 48, 48, 48, 48, 48, 48,
- 48, 51, 1, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 52, 48, 48, 53, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 54, 55, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 56, 48, 71, 71, 71, 71,
- 71, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 71, 1, 1, 72, 1,
- 1, 1, 1, 1, 1, 1, 1, 73,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 74, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 75,
- 1, 76, 76, 76, 76, 76, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 76, 1, 1, 77, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 78, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 79, 1, 76, 76,
- 76, 76, 76, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 76, 1, 1,
- 77, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 78, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 79, 1, 71, 71, 71, 71, 71,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 71, 1, 1, 72, 1, 1,
- 1, 1, 1, 1, 1, 1, 73, 1,
- 1, 1, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 74,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 75, 1,
- 80, 80, 80, 80, 80, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 80,
- 1, 1, 81, 1, 1, 1, 1, 1,
- 1, 1, 82, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 83,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 45, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 84, 1, 85, 85, 85,
- 85, 85, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 85, 1, 1, 86,
- 1, 1, 1, 1, 1, 1, 1, 87,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 88, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 89, 1, 85, 85, 85, 85, 85, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 85, 1, 1, 86, 1, 1, 1,
- 1, 1, 1, 1, 87, 1, 1, 1,
- 1, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 88, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 89, 1, 80,
- 80, 80, 80, 80, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 80, 1,
- 1, 81, 1, 1, 1, 1, 1, 1,
- 1, 82, 1, 1, 1, 1, 90, 90,
- 90, 90, 90, 90, 90, 90, 90, 90,
- 1, 1, 1, 1, 1, 1, 83, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 45, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 84, 1, 65, 65, 65, 65,
- 65, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 65, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 66, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 67,
- 1, 0
-};
-
-static const char _deserialize_text_trans_targs[] = {
- 1, 0, 2, 26, 3, 4, 20, 5,
- 24, 25, 28, 39, 9, 31, 34, 31,
- 34, 11, 32, 33, 32, 33, 35, 38,
- 14, 15, 18, 15, 18, 16, 17, 36,
- 37, 36, 37, 27, 21, 20, 6, 22,
- 23, 21, 22, 23, 21, 22, 23, 25,
- 27, 27, 7, 8, 12, 13, 19, 22,
- 30, 27, 7, 8, 12, 13, 19, 22,
- 30, 29, 22, 30, 29, 30, 30, 29,
- 7, 10, 22, 30, 29, 7, 22, 30,
- 29, 7, 8, 13, 30, 29, 7, 8,
- 22, 30, 38, 39
-};
-
-static const char _deserialize_text_trans_actions[] = {
- 0, 0, 0, 0, 1, 0, 2, 0,
- 2, 2, 3, 3, 4, 3, 3, 5,
- 5, 4, 3, 3, 5, 5, 3, 3,
- 4, 4, 4, 0, 0, 6, 4, 3,
- 3, 5, 5, 5, 7, 8, 9, 7,
- 7, 0, 0, 0, 10, 10, 10, 8,
- 12, 13, 14, 14, 14, 14, 15, 11,
- 11, 17, 18, 18, 18, 18, 0, 16,
- 16, 19, 19, 19, 0, 0, 13, 20,
- 21, 21, 20, 20, 22, 23, 22, 22,
- 10, 24, 24, 24, 10, 25, 26, 26,
- 25, 25, 5, 5
-};
-
-static const char _deserialize_text_eof_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 7, 0, 0, 0,
- 10, 10, 11, 16, 19, 0, 11, 20,
- 22, 22, 20, 10, 25, 25, 10, 19
-};
-
-static const int deserialize_text_start = 1;
-static const int deserialize_text_first_final = 20;
-static const int deserialize_text_error = 0;
-
-static const int deserialize_text_en_main = 1;
-
-
-#line 117 "hb-buffer-deserialize-text.rl"
-
-
-static hb_bool_t
-_hb_buffer_deserialize_text (hb_buffer_t *buffer,
- const char *buf,
- unsigned int buf_len,
- const char **end_ptr,
- hb_font_t *font)
-{
- const char *p = buf, *pe = buf + buf_len;
-
- /* Ensure we have positions. */
- (void) hb_buffer_get_glyph_positions (buffer, nullptr);
-
- while (p < pe && ISSPACE (*p))
- p++;
-
- const char *eof = pe, *tok = nullptr;
- int cs;
- hb_glyph_info_t info = {0};
- hb_glyph_position_t pos = {0};
-
-#line 457 "hb-buffer-deserialize-text.hh"
- {
- cs = deserialize_text_start;
- }
-
-#line 460 "hb-buffer-deserialize-text.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
- if ( cs == 0 )
- goto _out;
-_resume:
- _keys = _deserialize_text_trans_keys + (cs<<1);
- _inds = _deserialize_text_indicies + _deserialize_text_index_offsets[cs];
-
- _slen = _deserialize_text_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
- (*p) <= _keys[1] ?
- (*p) - _keys[0] : _slen ];
-
- cs = _deserialize_text_trans_targs[_trans];
-
- if ( _deserialize_text_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _deserialize_text_trans_actions[_trans] ) {
- case 1:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
- break;
- case 4:
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
- break;
- case 5:
-#line 55 "hb-buffer-deserialize-text.rl"
- { if (unlikely (!buffer->ensure_glyphs ())) return false; }
- break;
- case 8:
-#line 56 "hb-buffer-deserialize-text.rl"
- { if (unlikely (!buffer->ensure_unicode ())) return false; }
- break;
- case 18:
-#line 58 "hb-buffer-deserialize-text.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
- break;
- case 9:
-#line 66 "hb-buffer-deserialize-text.rl"
- {if (!parse_hex (tok, p, &info.codepoint )) return false; }
- break;
- case 24:
-#line 68 "hb-buffer-deserialize-text.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
- break;
- case 6:
-#line 69 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.x_offset )) return false; }
- break;
- case 26:
-#line 70 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
- break;
- case 21:
-#line 71 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
- break;
- case 23:
-#line 72 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
- break;
- case 15:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
- break;
- case 3:
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
-#line 55 "hb-buffer-deserialize-text.rl"
- { if (unlikely (!buffer->ensure_glyphs ())) return false; }
- break;
- case 2:
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
-#line 56 "hb-buffer-deserialize-text.rl"
- { if (unlikely (!buffer->ensure_unicode ())) return false; }
- break;
- case 16:
-#line 58 "hb-buffer-deserialize-text.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 7:
-#line 66 "hb-buffer-deserialize-text.rl"
- {if (!parse_hex (tok, p, &info.codepoint )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 10:
-#line 68 "hb-buffer-deserialize-text.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 25:
-#line 70 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 20:
-#line 71 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 22:
-#line 72 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 19:
-#line 73 "hb-buffer-deserialize-text.rl"
- { if (!parse_uint (tok, p, &info.mask )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 12:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
-#line 55 "hb-buffer-deserialize-text.rl"
- { if (unlikely (!buffer->ensure_glyphs ())) return false; }
- break;
- case 14:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
-#line 58 "hb-buffer-deserialize-text.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
- break;
- case 17:
-#line 58 "hb-buffer-deserialize-text.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 55 "hb-buffer-deserialize-text.rl"
- { if (unlikely (!buffer->ensure_glyphs ())) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 11:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
-#line 58 "hb-buffer-deserialize-text.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 13:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
-#line 58 "hb-buffer-deserialize-text.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 55 "hb-buffer-deserialize-text.rl"
- { if (unlikely (!buffer->ensure_glyphs ())) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
-#line 715 "hb-buffer-deserialize-text.hh"
- }
-
-_again:
- if ( cs == 0 )
- goto _out;
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- switch ( _deserialize_text_eof_actions[cs] ) {
- case 16:
-#line 58 "hb-buffer-deserialize-text.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 7:
-#line 66 "hb-buffer-deserialize-text.rl"
- {if (!parse_hex (tok, p, &info.codepoint )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 10:
-#line 68 "hb-buffer-deserialize-text.rl"
- { if (!parse_uint (tok, p, &info.cluster )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 25:
-#line 70 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 20:
-#line 71 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 22:
-#line 72 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.y_advance)) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 19:
-#line 73 "hb-buffer-deserialize-text.rl"
- { if (!parse_uint (tok, p, &info.mask )) return false; }
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
- case 11:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- hb_memset (&info, 0, sizeof (info));
- hb_memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
-#line 58 "hb-buffer-deserialize-text.rl"
- {
- /* TODO Unescape delimiters. */
- if (!hb_font_glyph_from_string (font,
- tok, p - tok,
- &info.codepoint))
- return false;
-}
-#line 43 "hb-buffer-deserialize-text.rl"
- {
- buffer->add_info (info);
- if (unlikely (!buffer->successful))
- return false;
- buffer->pos[buffer->len - 1] = pos;
- *end_ptr = p;
-}
- break;
-#line 825 "hb-buffer-deserialize-text.hh"
- }
- }
-
- _out: {}
- }
-
-#line 141 "hb-buffer-deserialize-text.rl"
-
-
- *end_ptr = p;
-
- return p == pe && *(p-1) != ']';
-}
-
-#endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc
index a458f2318f..16f189519b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc
@@ -721,7 +721,8 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
}
#include "hb-buffer-deserialize-json.hh"
-#include "hb-buffer-deserialize-text.hh"
+#include "hb-buffer-deserialize-text-glyphs.hh"
+#include "hb-buffer-deserialize-text-unicode.hh"
/**
* hb_buffer_deserialize_glyphs:
@@ -736,7 +737,8 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
* Deserializes glyphs @buffer from textual representation in the format
* produced by hb_buffer_serialize_glyphs().
*
- * Return value: `true` if @buf is not fully consumed, `false` otherwise.
+ * Return value: `true` if parse was successful, `false` if an error
+ * occurred.
*
* Since: 0.9.7
**/
@@ -779,9 +781,9 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
switch (format)
{
case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
- return _hb_buffer_deserialize_text (buffer,
- buf, buf_len, end_ptr,
- font);
+ return _hb_buffer_deserialize_text_glyphs (buffer,
+ buf, buf_len, end_ptr,
+ font);
case HB_BUFFER_SERIALIZE_FORMAT_JSON:
return _hb_buffer_deserialize_json (buffer,
@@ -808,7 +810,8 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
* Deserializes Unicode @buffer from textual representation in the format
* produced by hb_buffer_serialize_unicode().
*
- * Return value: `true` if @buf is not fully consumed, `false` otherwise.
+ * Return value: `true` if parse was successful, `false` if an error
+ * occurred.
*
* Since: 2.7.3
**/
@@ -849,9 +852,9 @@ hb_buffer_deserialize_unicode (hb_buffer_t *buffer,
switch (format)
{
case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
- return _hb_buffer_deserialize_text (buffer,
- buf, buf_len, end_ptr,
- font);
+ return _hb_buffer_deserialize_text_unicode (buffer,
+ buf, buf_len, end_ptr,
+ font);
case HB_BUFFER_SERIALIZE_FORMAT_JSON:
return _hb_buffer_deserialize_json (buffer,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
index 1cd52b39b1..f111b2d8dc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
@@ -150,7 +150,7 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
assert (text_start < text_end);
if (0)
- printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
+ printf("start %u end %u text start %u end %u\n", start, end, text_start, text_end);
hb_buffer_clear_contents (fragment);
@@ -292,7 +292,7 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
assert (text_start < text_end);
if (0)
- printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
+ printf("start %u end %u text start %u end %u\n", start, end, text_start, text_end);
#if 0
hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
index 4b6c2d9eaa..f557ceee56 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
@@ -522,15 +522,17 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
cluster = hb_min (cluster, info[i].cluster);
/* Extend end */
- while (end < len && info[end - 1].cluster == info[end].cluster)
- end++;
+ if (cluster != info[end - 1].cluster)
+ while (end < len && info[end - 1].cluster == info[end].cluster)
+ end++;
/* Extend start */
- while (idx < start && info[start - 1].cluster == info[start].cluster)
- start--;
+ if (cluster != info[start].cluster)
+ while (idx < start && info[start - 1].cluster == info[start].cluster)
+ start--;
/* If we hit the start of buffer, continue in out-buffer. */
- if (idx == start)
+ if (idx == start && info[start].cluster != cluster)
for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
set_cluster (out_info[i - 1], cluster);
@@ -893,6 +895,32 @@ hb_buffer_get_user_data (const hb_buffer_t *buffer,
* Sets the type of @buffer contents. Buffers are either empty, contain
* characters (before shaping), or contain glyphs (the result of shaping).
*
+ * You rarely need to call this function, since a number of other
+ * functions transition the content type for you. Namely:
+ *
+ * - A newly created buffer starts with content type
+ * %HB_BUFFER_CONTENT_TYPE_INVALID. Calling hb_buffer_reset(),
+ * hb_buffer_clear_contents(), as well as calling hb_buffer_set_length()
+ * with an argument of zero all set the buffer content type to invalid
+ * as well.
+ *
+ * - Calling hb_buffer_add_utf8(), hb_buffer_add_utf16(),
+ * hb_buffer_add_utf32(), hb_buffer_add_codepoints() and
+ * hb_buffer_add_latin1() expect that buffer is either empty and
+ * have a content type of invalid, or that buffer content type is
+ * %HB_BUFFER_CONTENT_TYPE_UNICODE, and they also set the content
+ * type to Unicode if they added anything to an empty buffer.
+ *
+ * - Finally hb_shape() and hb_shape_full() expect that the buffer
+ * is either empty and have content type of invalid, or that buffer
+ * content type is %HB_BUFFER_CONTENT_TYPE_UNICODE, and upon
+ * success they set the buffer content type to
+ * %HB_BUFFER_CONTENT_TYPE_GLYPHS.
+ *
+ * The above transitions are designed such that one can use a buffer
+ * in a loop of "reset : add-text : shape" without needing to ever
+ * modify the content type manually.
+ *
* Since: 0.9.5
**/
void
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
index 8c17489835..bff78543c8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
@@ -763,7 +763,7 @@ hb_buffer_diff (hb_buffer_t *buffer,
/*
- * Debugging.
+ * Tracing.
*/
/**
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
index bb1efe9dd3..5a43cabcb7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
@@ -35,26 +35,6 @@
#include "hb-set-digest.hh"
-#ifndef HB_BUFFER_MAX_LEN_FACTOR
-#define HB_BUFFER_MAX_LEN_FACTOR 64
-#endif
-#ifndef HB_BUFFER_MAX_LEN_MIN
-#define HB_BUFFER_MAX_LEN_MIN 16384
-#endif
-#ifndef HB_BUFFER_MAX_LEN_DEFAULT
-#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
-#endif
-
-#ifndef HB_BUFFER_MAX_OPS_FACTOR
-#define HB_BUFFER_MAX_OPS_FACTOR 1024
-#endif
-#ifndef HB_BUFFER_MAX_OPS_MIN
-#define HB_BUFFER_MAX_OPS_MIN 16384
-#endif
-#ifndef HB_BUFFER_MAX_OPS_DEFAULT
-#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
-#endif
-
static_assert ((sizeof (hb_glyph_info_t) == 20), "");
static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
@@ -601,21 +581,59 @@ struct hb_buffer_t
unsigned int cluster,
hb_mask_t mask)
{
- for (unsigned int i = start; i < end; i++)
- if (cluster != infos[i].cluster)
+ if (unlikely (start == end))
+ return;
+
+ unsigned cluster_first = infos[start].cluster;
+ unsigned cluster_last = infos[end - 1].cluster;
+
+ if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS ||
+ (cluster != cluster_first && cluster != cluster_last))
+ {
+ for (unsigned int i = start; i < end; i++)
+ if (cluster != infos[i].cluster)
+ {
+ scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
+ infos[i].mask |= mask;
+ }
+ return;
+ }
+
+ /* Monotone clusters */
+
+ if (cluster == cluster_first)
+ {
+ for (unsigned int i = end; start < i && infos[i - 1].cluster != cluster_first; i--)
+ {
+ scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
+ infos[i - 1].mask |= mask;
+ }
+ }
+ else /* cluster == cluster_last */
+ {
+ for (unsigned int i = start; i < end && infos[i].cluster != cluster_last; i++)
{
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
infos[i].mask |= mask;
}
+ }
}
- static unsigned
+ 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;
+ if (unlikely (start == end))
+ return cluster;
+
+ if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
+ {
+ for (unsigned int i = start; i < end; i++)
+ cluster = hb_min (cluster, infos[i].cluster);
+ return cluster;
+ }
+
+ return hb_min (cluster, hb_min (infos[start].cluster, infos[end - 1].cluster));
}
void clear_glyph_flags (hb_mask_t mask = 0)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh
index f8c8108f1f..2e98187b50 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh
@@ -39,7 +39,9 @@ template <unsigned int key_bits=16,
struct hb_cache_t
{
using item_t = typename std::conditional<thread_safe,
- hb_atomic_int_t,
+ typename std::conditional<key_bits + value_bits - cache_bits <= 16,
+ hb_atomic_short_t,
+ hb_atomic_int_t>::type,
typename std::conditional<key_bits + value_bits - cache_bits <= 16,
short,
int>::type
@@ -48,8 +50,9 @@ struct hb_cache_t
static_assert ((key_bits >= cache_bits), "");
static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), "");
+ hb_cache_t () { init (); }
+
void init () { clear (); }
- void fini () {}
void clear ()
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc
new file mode 100644
index 0000000000..3e5118f213
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc
@@ -0,0 +1,869 @@
+/*
+ * Copyright © 2022 Red Hat, Inc
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Matthias Clasen
+ */
+
+#include "hb.hh"
+
+#ifdef HAVE_CAIRO
+
+#include "hb-cairo-utils.hh"
+
+#include <cairo.h>
+
+#define PREALLOCATED_COLOR_STOPS 16
+
+#define _2_M_PIf (2.f * float (M_PI))
+
+typedef struct {
+ float r, g, b, a;
+} hb_cairo_color_t;
+
+static inline cairo_extend_t
+hb_cairo_extend (hb_paint_extend_t extend)
+{
+ switch (extend)
+ {
+ case HB_PAINT_EXTEND_PAD: return CAIRO_EXTEND_PAD;
+ case HB_PAINT_EXTEND_REPEAT: return CAIRO_EXTEND_REPEAT;
+ case HB_PAINT_EXTEND_REFLECT: return CAIRO_EXTEND_REFLECT;
+ default: break;
+ }
+
+ return CAIRO_EXTEND_PAD;
+}
+
+#ifdef CAIRO_HAS_PNG_FUNCTIONS
+typedef struct
+{
+ hb_blob_t *blob;
+ unsigned int offset;
+} hb_cairo_read_blob_data_t;
+
+static cairo_status_t
+hb_cairo_read_blob (void *closure,
+ unsigned char *data,
+ unsigned int length)
+{
+ hb_cairo_read_blob_data_t *r = (hb_cairo_read_blob_data_t *) closure;
+ const char *d;
+ unsigned int size;
+
+ d = hb_blob_get_data (r->blob, &size);
+
+ if (r->offset + length > size)
+ return CAIRO_STATUS_READ_ERROR;
+
+ memcpy (data, d + r->offset, length);
+ r->offset += length;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+#endif
+
+static const cairo_user_data_key_t *_hb_cairo_surface_blob_user_data_key = {0};
+
+static void
+_hb_cairo_destroy_blob (void *p)
+{
+ hb_blob_destroy ((hb_blob_t *) p);
+}
+
+hb_bool_t
+_hb_cairo_paint_glyph_image (hb_cairo_context_t *c,
+ hb_blob_t *blob,
+ unsigned width,
+ unsigned height,
+ hb_tag_t format,
+ float slant,
+ hb_glyph_extents_t *extents)
+{
+ cairo_t *cr = c->cr;
+
+ if (!extents) /* SVG currently. */
+ return false;
+
+ cairo_surface_t *surface = nullptr;
+
+#ifdef CAIRO_HAS_PNG_FUNCTIONS
+ if (format == HB_PAINT_IMAGE_FORMAT_PNG)
+ {
+ hb_cairo_read_blob_data_t r;
+ r.blob = blob;
+ r.offset = 0;
+ surface = cairo_image_surface_create_from_png_stream (hb_cairo_read_blob, &r);
+
+ /* For PNG, width,height can be unreliable, as is the case for NotoColorEmoji :(.
+ * Just pull them out of the surface. */
+ width = cairo_image_surface_get_width (surface);
+ height = cairo_image_surface_get_width (surface);
+ }
+ else
+#endif
+ if (format == HB_PAINT_IMAGE_FORMAT_BGRA)
+ {
+ /* Byte-endian conversion. */
+ unsigned data_size = hb_blob_get_length (blob);
+ if (data_size < width * height * 4)
+ return false;
+
+ unsigned char *data;
+#ifdef __BYTE_ORDER
+ if (__BYTE_ORDER == __BIG_ENDIAN)
+ {
+ data = (unsigned char *) hb_blob_get_data_writable (blob, nullptr);
+ if (!data)
+ return false;
+
+ unsigned count = width * height * 4;
+ for (unsigned i = 0; i < count; i += 4)
+ {
+ unsigned char b;
+ b = data[i];
+ data[i] = data[i+3];
+ data[i+3] = b;
+ b = data[i+1];
+ data[i+1] = data[i+2];
+ data[i+2] = b;
+ }
+ }
+ else
+#endif
+ data = (unsigned char *) hb_blob_get_data (blob, nullptr);
+
+ surface = cairo_image_surface_create_for_data (data,
+ CAIRO_FORMAT_ARGB32,
+ width, height,
+ width * 4);
+
+ cairo_surface_set_user_data (surface,
+ _hb_cairo_surface_blob_user_data_key,
+ hb_blob_reference (blob),
+ _hb_cairo_destroy_blob);
+ }
+
+ if (!surface)
+ return false;
+
+ cairo_save (cr);
+ /* this clip is here to work around recording surface limitations */
+ cairo_rectangle (cr,
+ extents->x_bearing,
+ extents->y_bearing,
+ extents->width,
+ extents->height);
+ cairo_clip (cr);
+
+ cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
+
+ cairo_matrix_t matrix = {(double) width, 0, 0, (double) height, 0, 0};
+ cairo_pattern_set_matrix (pattern, &matrix);
+
+ /* Undo slant in the extents and apply it in the context. */
+ extents->width -= extents->height * slant;
+ extents->x_bearing -= extents->y_bearing * slant;
+ cairo_matrix_t cairo_matrix = {1., 0., (double) slant, 1., 0., 0.};
+ cairo_transform (cr, &cairo_matrix);
+
+ cairo_translate (cr, extents->x_bearing, extents->y_bearing);
+ cairo_scale (cr, extents->width, extents->height);
+ cairo_set_source (cr, pattern);
+
+ cairo_paint (cr);
+
+ cairo_pattern_destroy (pattern);
+ cairo_surface_destroy (surface);
+
+ cairo_restore (cr);
+
+ return true;
+}
+
+static void
+_hb_cairo_reduce_anchors (float x0, float y0,
+ float x1, float y1,
+ float x2, float y2,
+ float *xx0, float *yy0,
+ float *xx1, float *yy1)
+{
+ float q1x, q1y, q2x, q2y;
+ float s;
+ float k;
+
+ q2x = x2 - x0;
+ q2y = y2 - y0;
+ q1x = x1 - x0;
+ q1y = y1 - y0;
+
+ s = q2x * q2x + q2y * q2y;
+ if (s < 0.000001f)
+ {
+ *xx0 = x0; *yy0 = y0;
+ *xx1 = x1; *yy1 = y1;
+ return;
+ }
+
+ k = (q2x * q1x + q2y * q1y) / s;
+ *xx0 = x0;
+ *yy0 = y0;
+ *xx1 = x1 - k * q2x;
+ *yy1 = y1 - k * q2y;
+}
+
+static int
+_hb_cairo_cmp_color_stop (const void *p1,
+ const void *p2)
+{
+ const hb_color_stop_t *c1 = (const hb_color_stop_t *) p1;
+ const hb_color_stop_t *c2 = (const hb_color_stop_t *) p2;
+
+ if (c1->offset < c2->offset)
+ return -1;
+ else if (c1->offset > c2->offset)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+_hb_cairo_normalize_color_line (hb_color_stop_t *stops,
+ unsigned int len,
+ float *omin,
+ float *omax)
+{
+ float min, max;
+
+ hb_qsort (stops, len, sizeof (hb_color_stop_t), _hb_cairo_cmp_color_stop);
+
+ min = max = stops[0].offset;
+ for (unsigned int i = 0; i < len; i++)
+ {
+ min = hb_min (min, stops[i].offset);
+ max = hb_max (max, stops[i].offset);
+ }
+
+ if (min != max)
+ {
+ for (unsigned int i = 0; i < len; i++)
+ stops[i].offset = (stops[i].offset - min) / (max - min);
+ }
+
+ *omin = min;
+ *omax = max;
+}
+
+static bool
+_hb_cairo_get_color_stops (hb_cairo_context_t *c,
+ hb_color_line_t *color_line,
+ unsigned *count,
+ hb_color_stop_t **stops)
+{
+ unsigned len = hb_color_line_get_color_stops (color_line, 0, nullptr, nullptr);
+ if (len > *count)
+ {
+ *stops = (hb_color_stop_t *) hb_malloc (len * sizeof (hb_color_stop_t));
+ if (unlikely (!stops))
+ return false;
+ }
+ hb_color_line_get_color_stops (color_line, 0, &len, *stops);
+ for (unsigned i = 0; i < len; i++)
+ if ((*stops)[i].is_foreground)
+ {
+#ifdef HAVE_CAIRO_USER_SCALED_FONT_GET_FOREGROUND_SOURCE
+ double r, g, b, a;
+ cairo_pattern_t *foreground = cairo_user_scaled_font_get_foreground_source (c->scaled_font);
+ if (cairo_pattern_get_rgba (foreground, &r, &g, &b, &a) == CAIRO_STATUS_SUCCESS)
+ (*stops)[i].color = HB_COLOR (round (b * 255.), round (g * 255.), round (r * 255.),
+ round (a * hb_color_get_alpha ((*stops)[i].color)));
+ else
+#endif
+ (*stops)[i].color = HB_COLOR (0, 0, 0, hb_color_get_alpha ((*stops)[i].color));
+ }
+
+ *count = len;
+ return true;
+}
+
+void
+_hb_cairo_paint_linear_gradient (hb_cairo_context_t *c,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float x1, float y1,
+ float x2, float y2)
+{
+ cairo_t *cr = c->cr;
+
+ unsigned int len = PREALLOCATED_COLOR_STOPS;
+ hb_color_stop_t stops_[PREALLOCATED_COLOR_STOPS];
+ hb_color_stop_t *stops = stops_;
+ float xx0, yy0, xx1, yy1;
+ float xxx0, yyy0, xxx1, yyy1;
+ float min, max;
+ cairo_pattern_t *pattern;
+
+ if (unlikely (!_hb_cairo_get_color_stops (c, color_line, &len, &stops)))
+ return;
+ _hb_cairo_normalize_color_line (stops, len, &min, &max);
+
+ _hb_cairo_reduce_anchors (x0, y0, x1, y1, x2, y2, &xx0, &yy0, &xx1, &yy1);
+
+ xxx0 = xx0 + min * (xx1 - xx0);
+ yyy0 = yy0 + min * (yy1 - yy0);
+ xxx1 = xx0 + max * (xx1 - xx0);
+ yyy1 = yy0 + max * (yy1 - yy0);
+
+ pattern = cairo_pattern_create_linear ((double) xxx0, (double) yyy0, (double) xxx1, (double) yyy1);
+ cairo_pattern_set_extend (pattern, hb_cairo_extend (hb_color_line_get_extend (color_line)));
+ for (unsigned int i = 0; i < len; i++)
+ {
+ double r, g, b, a;
+ r = hb_color_get_red (stops[i].color) / 255.;
+ g = hb_color_get_green (stops[i].color) / 255.;
+ b = hb_color_get_blue (stops[i].color) / 255.;
+ a = hb_color_get_alpha (stops[i].color) / 255.;
+ cairo_pattern_add_color_stop_rgba (pattern, (double) stops[i].offset, r, g, b, a);
+ }
+
+ cairo_set_source (cr, pattern);
+ cairo_paint (cr);
+
+ cairo_pattern_destroy (pattern);
+
+ if (stops != stops_)
+ hb_free (stops);
+}
+
+void
+_hb_cairo_paint_radial_gradient (hb_cairo_context_t *c,
+ hb_color_line_t *color_line,
+ float x0, float y0, float r0,
+ float x1, float y1, float r1)
+{
+ cairo_t *cr = c->cr;
+
+ unsigned int len = PREALLOCATED_COLOR_STOPS;
+ hb_color_stop_t stops_[PREALLOCATED_COLOR_STOPS];
+ hb_color_stop_t *stops = stops_;
+ float min, max;
+ float xx0, yy0, xx1, yy1;
+ float rr0, rr1;
+ cairo_pattern_t *pattern;
+
+ if (unlikely (!_hb_cairo_get_color_stops (c, color_line, &len, &stops)))
+ return;
+ _hb_cairo_normalize_color_line (stops, len, &min, &max);
+
+ xx0 = x0 + min * (x1 - x0);
+ yy0 = y0 + min * (y1 - y0);
+ xx1 = x0 + max * (x1 - x0);
+ yy1 = y0 + max * (y1 - y0);
+ rr0 = r0 + min * (r1 - r0);
+ rr1 = r0 + max * (r1 - r0);
+
+ pattern = cairo_pattern_create_radial ((double) xx0, (double) yy0, (double) rr0, (double) xx1, (double) yy1, (double) rr1);
+ cairo_pattern_set_extend (pattern, hb_cairo_extend (hb_color_line_get_extend (color_line)));
+
+ for (unsigned int i = 0; i < len; i++)
+ {
+ double r, g, b, a;
+ r = hb_color_get_red (stops[i].color) / 255.;
+ g = hb_color_get_green (stops[i].color) / 255.;
+ b = hb_color_get_blue (stops[i].color) / 255.;
+ a = hb_color_get_alpha (stops[i].color) / 255.;
+ cairo_pattern_add_color_stop_rgba (pattern, (double) stops[i].offset, r, g, b, a);
+ }
+
+ cairo_set_source (cr, pattern);
+ cairo_paint (cr);
+
+ cairo_pattern_destroy (pattern);
+
+ if (stops != stops_)
+ hb_free (stops);
+}
+
+typedef struct {
+ float x, y;
+} hb_cairo_point_t;
+
+static inline float
+_hb_cairo_interpolate (float f0, float f1, float f)
+{
+ return f0 + f * (f1 - f0);
+}
+
+static inline void
+_hb_cairo_premultiply (hb_cairo_color_t *c)
+{
+ c->r *= c->a;
+ c->g *= c->a;
+ c->b *= c->a;
+}
+
+static inline void
+_hb_cairo_unpremultiply (hb_cairo_color_t *c)
+{
+ if (c->a != 0.f)
+ {
+ c->r /= c->a;
+ c->g /= c->a;
+ c->b /= c->a;
+ }
+}
+
+static void
+_hb_cairo_interpolate_colors (hb_cairo_color_t *c0, hb_cairo_color_t *c1, float k, hb_cairo_color_t *c)
+{
+ // According to the COLR specification, gradients
+ // should be interpolated in premultiplied form
+ _hb_cairo_premultiply (c0);
+ _hb_cairo_premultiply (c1);
+ c->r = c0->r + k * (c1->r - c0->r);
+ c->g = c0->g + k * (c1->g - c0->g);
+ c->b = c0->b + k * (c1->b - c0->b);
+ c->a = c0->a + k * (c1->a - c0->a);
+ _hb_cairo_unpremultiply (c);
+}
+
+static inline float
+_hb_cairo_dot (hb_cairo_point_t p, hb_cairo_point_t q)
+{
+ return p.x * q.x + p.y * q.y;
+}
+
+static inline hb_cairo_point_t
+_hb_cairo_normalize (hb_cairo_point_t p)
+{
+ float len = sqrtf (_hb_cairo_dot (p, p));
+
+ return hb_cairo_point_t { p.x / len, p.y / len };
+}
+
+static inline hb_cairo_point_t
+_hb_cairo_sum (hb_cairo_point_t p, hb_cairo_point_t q)
+{
+ return hb_cairo_point_t { p.x + q.x, p.y + q.y };
+}
+
+static inline hb_cairo_point_t
+_hb_cairo_difference (hb_cairo_point_t p, hb_cairo_point_t q)
+{
+ return hb_cairo_point_t { p.x - q.x, p.y - q.y };
+}
+
+static inline hb_cairo_point_t
+_hb_cairo_scale (hb_cairo_point_t p, float f)
+{
+ return hb_cairo_point_t { p.x * f, p.y * f };
+}
+
+typedef struct {
+ hb_cairo_point_t center, p0, c0, c1, p1;
+ hb_cairo_color_t color0, color1;
+} hb_cairo_patch_t;
+
+static void
+_hb_cairo_add_patch (cairo_pattern_t *pattern, hb_cairo_point_t *center, hb_cairo_patch_t *p)
+{
+ cairo_mesh_pattern_begin_patch (pattern);
+ cairo_mesh_pattern_move_to (pattern, (double) center->x, (double) center->y);
+ cairo_mesh_pattern_line_to (pattern, (double) p->p0.x, (double) p->p0.y);
+ cairo_mesh_pattern_curve_to (pattern,
+ (double) p->c0.x, (double) p->c0.y,
+ (double) p->c1.x, (double) p->c1.y,
+ (double) p->p1.x, (double) p->p1.y);
+ cairo_mesh_pattern_line_to (pattern, (double) center->x, (double) center->y);
+ cairo_mesh_pattern_set_corner_color_rgba (pattern, 0,
+ (double) p->color0.r,
+ (double) p->color0.g,
+ (double) p->color0.b,
+ (double) p->color0.a);
+ cairo_mesh_pattern_set_corner_color_rgba (pattern, 1,
+ (double) p->color0.r,
+ (double) p->color0.g,
+ (double) p->color0.b,
+ (double) p->color0.a);
+ cairo_mesh_pattern_set_corner_color_rgba (pattern, 2,
+ (double) p->color1.r,
+ (double) p->color1.g,
+ (double) p->color1.b,
+ (double) p->color1.a);
+ cairo_mesh_pattern_set_corner_color_rgba (pattern, 3,
+ (double) p->color1.r,
+ (double) p->color1.g,
+ (double) p->color1.b,
+ (double) p->color1.a);
+ cairo_mesh_pattern_end_patch (pattern);
+}
+
+#define MAX_ANGLE ((float) M_PI / 8.f)
+
+static void
+_hb_cairo_add_sweep_gradient_patches1 (float cx, float cy, float radius,
+ float a0, hb_cairo_color_t *c0,
+ float a1, hb_cairo_color_t *c1,
+ cairo_pattern_t *pattern)
+{
+ hb_cairo_point_t center = hb_cairo_point_t { cx, cy };
+ int num_splits;
+ hb_cairo_point_t p0;
+ hb_cairo_color_t color0, color1;
+
+ num_splits = ceilf (fabsf (a1 - a0) / MAX_ANGLE);
+ p0 = hb_cairo_point_t { cosf (a0), sinf (a0) };
+ color0 = *c0;
+
+ for (int a = 0; a < num_splits; a++)
+ {
+ float k = (a + 1.) / num_splits;
+ float angle1;
+ hb_cairo_point_t p1;
+ hb_cairo_point_t A, U;
+ hb_cairo_point_t C0, C1;
+ hb_cairo_patch_t patch;
+
+ angle1 = _hb_cairo_interpolate (a0, a1, k);
+ _hb_cairo_interpolate_colors (c0, c1, k, &color1);
+
+ patch.color0 = color0;
+ patch.color1 = color1;
+
+ p1 = hb_cairo_point_t { cosf (angle1), sinf (angle1) };
+ patch.p0 = _hb_cairo_sum (center, _hb_cairo_scale (p0, radius));
+ patch.p1 = _hb_cairo_sum (center, _hb_cairo_scale (p1, radius));
+
+ A = _hb_cairo_normalize (_hb_cairo_sum (p0, p1));
+ U = hb_cairo_point_t { -A.y, A.x };
+ C0 = _hb_cairo_sum (A, _hb_cairo_scale (U, _hb_cairo_dot (_hb_cairo_difference (p0, A), p0) / _hb_cairo_dot (U, p0)));
+ C1 = _hb_cairo_sum (A, _hb_cairo_scale (U, _hb_cairo_dot (_hb_cairo_difference (p1, A), p1) / _hb_cairo_dot (U, p1)));
+
+ patch.c0 = _hb_cairo_sum (center, _hb_cairo_scale (_hb_cairo_sum (C0, _hb_cairo_scale (_hb_cairo_difference (C0, p0), 0.33333f)), radius));
+ patch.c1 = _hb_cairo_sum (center, _hb_cairo_scale (_hb_cairo_sum (C1, _hb_cairo_scale (_hb_cairo_difference (C1, p1), 0.33333f)), radius));
+
+ _hb_cairo_add_patch (pattern, &center, &patch);
+
+ p0 = p1;
+ color0 = color1;
+ }
+}
+
+static void
+_hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
+ unsigned int n_stops,
+ cairo_extend_t extend,
+ float cx, float cy,
+ float radius,
+ float start_angle,
+ float end_angle,
+ cairo_pattern_t *pattern)
+{
+ float angles_[PREALLOCATED_COLOR_STOPS];
+ float *angles = angles_;
+ hb_cairo_color_t colors_[PREALLOCATED_COLOR_STOPS];
+ hb_cairo_color_t *colors = colors_;
+ hb_cairo_color_t color0, color1;
+
+ if (start_angle == end_angle)
+ {
+ if (extend == CAIRO_EXTEND_PAD)
+ {
+ hb_cairo_color_t c;
+ if (start_angle > 0)
+ {
+ c.r = hb_color_get_red (stops[0].color) / 255.;
+ c.g = hb_color_get_green (stops[0].color) / 255.;
+ c.b = hb_color_get_blue (stops[0].color) / 255.;
+ c.a = hb_color_get_alpha (stops[0].color) / 255.;
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ 0., &c,
+ start_angle, &c,
+ pattern);
+ }
+ if (end_angle < _2_M_PIf)
+ {
+ c.r = hb_color_get_red (stops[n_stops - 1].color) / 255.;
+ c.g = hb_color_get_green (stops[n_stops - 1].color) / 255.;
+ c.b = hb_color_get_blue (stops[n_stops - 1].color) / 255.;
+ c.a = hb_color_get_alpha (stops[n_stops - 1].color) / 255.;
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ end_angle, &c,
+ _2_M_PIf, &c,
+ pattern);
+ }
+ }
+ return;
+ }
+
+ assert (start_angle != end_angle);
+
+ /* handle directions */
+ if (end_angle < start_angle)
+ {
+ hb_swap (start_angle, end_angle);
+
+ for (unsigned i = 0; i < n_stops - 1 - i; i++)
+ hb_swap (stops[i], stops[n_stops - 1 - i]);
+ for (unsigned i = 0; i < n_stops; i++)
+ stops[i].offset = 1 - stops[i].offset;
+ }
+
+ if (n_stops > PREALLOCATED_COLOR_STOPS)
+ {
+ angles = (float *) hb_malloc (sizeof (float) * n_stops);
+ colors = (hb_cairo_color_t *) hb_malloc (sizeof (hb_cairo_color_t) * n_stops);
+ if (unlikely (!angles || !colors))
+ {
+ hb_free (angles);
+ hb_free (colors);
+ return;
+ }
+ }
+
+ for (unsigned i = 0; i < n_stops; i++)
+ {
+ angles[i] = start_angle + stops[i].offset * (end_angle - start_angle);
+ colors[i].r = hb_color_get_red (stops[i].color) / 255.;
+ colors[i].g = hb_color_get_green (stops[i].color) / 255.;
+ colors[i].b = hb_color_get_blue (stops[i].color) / 255.;
+ colors[i].a = hb_color_get_alpha (stops[i].color) / 255.;
+ }
+
+ if (extend == CAIRO_EXTEND_PAD)
+ {
+ unsigned pos;
+
+ color0 = colors[0];
+ for (pos = 0; pos < n_stops; pos++)
+ {
+ if (angles[pos] >= 0)
+ {
+ if (pos > 0)
+ {
+ float k = (0 - angles[pos - 1]) / (angles[pos] - angles[pos - 1]);
+ _hb_cairo_interpolate_colors (&colors[pos-1], &colors[pos], k, &color0);
+ }
+ break;
+ }
+ }
+ if (pos == n_stops)
+ {
+ /* everything is below 0 */
+ color0 = colors[n_stops-1];
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ 0., &color0,
+ _2_M_PIf, &color0,
+ pattern);
+ goto done;
+ }
+
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ 0., &color0,
+ angles[pos], &colors[pos],
+ pattern);
+
+ for (pos++; pos < n_stops; pos++)
+ {
+ if (angles[pos] <= _2_M_PIf)
+ {
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ angles[pos - 1], &colors[pos-1],
+ angles[pos], &colors[pos],
+ pattern);
+ }
+ else
+ {
+ float k = (_2_M_PIf - angles[pos - 1]) / (angles[pos] - angles[pos - 1]);
+ _hb_cairo_interpolate_colors (&colors[pos - 1], &colors[pos], k, &color1);
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ angles[pos - 1], &colors[pos - 1],
+ _2_M_PIf, &color1,
+ pattern);
+ break;
+ }
+ }
+
+ if (pos == n_stops)
+ {
+ /* everything is below 2*M_PI */
+ color0 = colors[n_stops - 1];
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ angles[n_stops - 1], &color0,
+ _2_M_PIf, &color0,
+ pattern);
+ goto done;
+ }
+ }
+ else
+ {
+ int k;
+ float span;
+
+ span = angles[n_stops - 1] - angles[0];
+ k = 0;
+ if (angles[0] >= 0)
+ {
+ float ss = angles[0];
+ while (ss > 0)
+ {
+ if (span > 0)
+ {
+ ss -= span;
+ k--;
+ }
+ else
+ {
+ ss += span;
+ k++;
+ }
+ }
+ }
+ else if (angles[0] < 0)
+ {
+ float ee = angles[n_stops - 1];
+ while (ee < 0)
+ {
+ if (span > 0)
+ {
+ ee += span;
+ k++;
+ }
+ else
+ {
+ ee -= span;
+ k--;
+ }
+ }
+ }
+
+ //assert (angles[0] + k * span <= 0 && 0 < angles[n_stops - 1] + k * span);
+ span = fabs (span);
+
+ for (signed l = k; l < 1000; l++)
+ {
+ for (unsigned i = 1; i < n_stops; i++)
+ {
+ float a0, a1;
+ hb_cairo_color_t *c0, *c1;
+
+ if ((l % 2 != 0) && (extend == CAIRO_EXTEND_REFLECT))
+ {
+ a0 = angles[0] + angles[n_stops - 1] - angles[n_stops - 1 - (i-1)] + l * span;
+ a1 = angles[0] + angles[n_stops - 1] - angles[n_stops - 1 - i] + l * span;
+ c0 = &colors[n_stops - 1 - (i - 1)];
+ c1 = &colors[n_stops - 1 - i];
+ }
+ else
+ {
+ a0 = angles[i-1] + l * span;
+ a1 = angles[i] + l * span;
+ c0 = &colors[i-1];
+ c1 = &colors[i];
+ }
+
+ if (a1 < 0)
+ continue;
+ if (a0 < 0)
+ {
+ hb_cairo_color_t color;
+ float f = (0 - a0)/(a1 - a0);
+ _hb_cairo_interpolate_colors (c0, c1, f, &color);
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ 0, &color,
+ a1, c1,
+ pattern);
+ }
+ else if (a1 >= _2_M_PIf)
+ {
+ hb_cairo_color_t color;
+ float f = (_2_M_PIf - a0)/(a1 - a0);
+ _hb_cairo_interpolate_colors (c0, c1, f, &color);
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ a0, c0,
+ _2_M_PIf, &color,
+ pattern);
+ goto done;
+ }
+ else
+ {
+ _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
+ a0, c0,
+ a1, c1,
+ pattern);
+ }
+ }
+ }
+ }
+
+done:
+
+ if (angles != angles_)
+ hb_free (angles);
+ if (colors != colors_)
+ hb_free (colors);
+}
+
+void
+_hb_cairo_paint_sweep_gradient (hb_cairo_context_t *c,
+ hb_color_line_t *color_line,
+ float cx, float cy,
+ float start_angle,
+ float end_angle)
+{
+ cairo_t *cr = c->cr;
+
+ unsigned int len = PREALLOCATED_COLOR_STOPS;
+ hb_color_stop_t stops_[PREALLOCATED_COLOR_STOPS];
+ hb_color_stop_t *stops = stops_;
+ cairo_extend_t extend;
+ double x1, y1, x2, y2;
+ float max_x, max_y, radius;
+ cairo_pattern_t *pattern;
+
+ if (unlikely (!_hb_cairo_get_color_stops (c, color_line, &len, &stops)))
+ return;
+
+ hb_qsort (stops, len, sizeof (hb_color_stop_t), _hb_cairo_cmp_color_stop);
+
+ cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
+ max_x = (float) hb_max ((x1 - (double) cx) * (x1 - (double) cx), (x2 - (double) cx) * (x2 - (double) cx));
+ max_y = (float) hb_max ((y1 - (double) cy) * (y1 - (double) cy), (y2 - (double) cy) * (y2 - (double) cy));
+ radius = sqrtf (max_x + max_y);
+
+ extend = hb_cairo_extend (hb_color_line_get_extend (color_line));
+ pattern = cairo_pattern_create_mesh ();
+
+ _hb_cairo_add_sweep_gradient_patches (stops, len, extend, cx, cy,
+ radius, start_angle, end_angle, pattern);
+
+ cairo_set_source (cr, pattern);
+ cairo_paint (cr);
+
+ cairo_pattern_destroy (pattern);
+
+ if (stops != stops_)
+ hb_free (stops);
+}
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.hh b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.hh
new file mode 100644
index 0000000000..a26bf59d91
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.hh
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2022 Red Hat, Inc
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Matthias Clasen
+ */
+
+#ifndef HB_CAIRO_UTILS_H
+#define HB_CAIRO_UTILS_H
+
+#include "hb.hh"
+#include "hb-cairo.h"
+
+
+typedef struct
+{
+ cairo_scaled_font_t *scaled_font;
+ cairo_t *cr;
+ hb_map_t *color_cache;
+} hb_cairo_context_t;
+
+static inline cairo_operator_t
+_hb_paint_composite_mode_to_cairo (hb_paint_composite_mode_t mode)
+{
+ switch (mode)
+ {
+ case HB_PAINT_COMPOSITE_MODE_CLEAR: return CAIRO_OPERATOR_CLEAR;
+ case HB_PAINT_COMPOSITE_MODE_SRC: return CAIRO_OPERATOR_SOURCE;
+ case HB_PAINT_COMPOSITE_MODE_DEST: return CAIRO_OPERATOR_DEST;
+ case HB_PAINT_COMPOSITE_MODE_SRC_OVER: return CAIRO_OPERATOR_OVER;
+ case HB_PAINT_COMPOSITE_MODE_DEST_OVER: return CAIRO_OPERATOR_DEST_OVER;
+ case HB_PAINT_COMPOSITE_MODE_SRC_IN: return CAIRO_OPERATOR_IN;
+ case HB_PAINT_COMPOSITE_MODE_DEST_IN: return CAIRO_OPERATOR_DEST_IN;
+ case HB_PAINT_COMPOSITE_MODE_SRC_OUT: return CAIRO_OPERATOR_OUT;
+ case HB_PAINT_COMPOSITE_MODE_DEST_OUT: return CAIRO_OPERATOR_DEST_OUT;
+ case HB_PAINT_COMPOSITE_MODE_SRC_ATOP: return CAIRO_OPERATOR_ATOP;
+ case HB_PAINT_COMPOSITE_MODE_DEST_ATOP: return CAIRO_OPERATOR_DEST_ATOP;
+ case HB_PAINT_COMPOSITE_MODE_XOR: return CAIRO_OPERATOR_XOR;
+ case HB_PAINT_COMPOSITE_MODE_PLUS: return CAIRO_OPERATOR_ADD;
+ case HB_PAINT_COMPOSITE_MODE_SCREEN: return CAIRO_OPERATOR_SCREEN;
+ case HB_PAINT_COMPOSITE_MODE_OVERLAY: return CAIRO_OPERATOR_OVERLAY;
+ case HB_PAINT_COMPOSITE_MODE_DARKEN: return CAIRO_OPERATOR_DARKEN;
+ case HB_PAINT_COMPOSITE_MODE_LIGHTEN: return CAIRO_OPERATOR_LIGHTEN;
+ case HB_PAINT_COMPOSITE_MODE_COLOR_DODGE: return CAIRO_OPERATOR_COLOR_DODGE;
+ case HB_PAINT_COMPOSITE_MODE_COLOR_BURN: return CAIRO_OPERATOR_COLOR_BURN;
+ case HB_PAINT_COMPOSITE_MODE_HARD_LIGHT: return CAIRO_OPERATOR_HARD_LIGHT;
+ case HB_PAINT_COMPOSITE_MODE_SOFT_LIGHT: return CAIRO_OPERATOR_SOFT_LIGHT;
+ case HB_PAINT_COMPOSITE_MODE_DIFFERENCE: return CAIRO_OPERATOR_DIFFERENCE;
+ case HB_PAINT_COMPOSITE_MODE_EXCLUSION: return CAIRO_OPERATOR_EXCLUSION;
+ case HB_PAINT_COMPOSITE_MODE_MULTIPLY: return CAIRO_OPERATOR_MULTIPLY;
+ case HB_PAINT_COMPOSITE_MODE_HSL_HUE: return CAIRO_OPERATOR_HSL_HUE;
+ case HB_PAINT_COMPOSITE_MODE_HSL_SATURATION: return CAIRO_OPERATOR_HSL_SATURATION;
+ case HB_PAINT_COMPOSITE_MODE_HSL_COLOR: return CAIRO_OPERATOR_HSL_COLOR;
+ case HB_PAINT_COMPOSITE_MODE_HSL_LUMINOSITY: return CAIRO_OPERATOR_HSL_LUMINOSITY;
+ default: return CAIRO_OPERATOR_CLEAR;
+ }
+}
+
+HB_INTERNAL hb_bool_t
+_hb_cairo_paint_glyph_image (hb_cairo_context_t *c,
+ hb_blob_t *blob,
+ unsigned width,
+ unsigned height,
+ hb_tag_t format,
+ float slant,
+ hb_glyph_extents_t *extents);
+
+HB_INTERNAL void
+_hb_cairo_paint_linear_gradient (hb_cairo_context_t *c,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float x1, float y1,
+ float x2, float y2);
+
+HB_INTERNAL void
+_hb_cairo_paint_radial_gradient (hb_cairo_context_t *c,
+ hb_color_line_t *color_line,
+ float x0, float y0, float r0,
+ float x1, float y1, float r1);
+
+HB_INTERNAL void
+_hb_cairo_paint_sweep_gradient (hb_cairo_context_t *c,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float start_angle, float end_angle);
+
+
+#endif /* HB_CAIRO_UTILS_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc b/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc
new file mode 100644
index 0000000000..f005afd17e
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc
@@ -0,0 +1,1010 @@
+/*
+ * Copyright © 2022 Red Hat, 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.
+ *
+ * Red Hat Author(s): Matthias Clasen
+ */
+
+#include "hb.hh"
+
+#ifdef HAVE_CAIRO
+
+#include "hb-cairo.h"
+
+#include "hb-cairo-utils.hh"
+
+#include "hb-machinery.hh"
+#include "hb-utf.hh"
+
+
+/**
+ * SECTION:hb-cairo
+ * @title: hb-cairo
+ * @short_description: Cairo integration
+ * @include: hb-cairo.h
+ *
+ * Functions for using HarfBuzz with the cairo library.
+ *
+ * HarfBuzz supports using cairo for rendering.
+ **/
+
+static void
+hb_cairo_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *draw_data,
+ hb_draw_state_t *st HB_UNUSED,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ cairo_t *cr = (cairo_t *) draw_data;
+
+ cairo_move_to (cr, (double) to_x, (double) to_y);
+}
+
+static void
+hb_cairo_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *draw_data,
+ hb_draw_state_t *st HB_UNUSED,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ cairo_t *cr = (cairo_t *) draw_data;
+
+ cairo_line_to (cr, (double) to_x, (double) to_y);
+}
+
+static void
+hb_cairo_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *draw_data,
+ hb_draw_state_t *st HB_UNUSED,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ cairo_t *cr = (cairo_t *) draw_data;
+
+ cairo_curve_to (cr,
+ (double) control1_x, (double) control1_y,
+ (double) control2_x, (double) control2_y,
+ (double) to_x, (double) to_y);
+}
+
+static void
+hb_cairo_close_path (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *draw_data,
+ hb_draw_state_t *st HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ cairo_t *cr = (cairo_t *) draw_data;
+
+ cairo_close_path (cr);
+}
+
+static inline void free_static_cairo_draw_funcs ();
+
+static struct hb_cairo_draw_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_cairo_draw_funcs_lazy_loader_t>
+{
+ static hb_draw_funcs_t *create ()
+ {
+ hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
+
+ hb_draw_funcs_set_move_to_func (funcs, hb_cairo_move_to, nullptr, nullptr);
+ hb_draw_funcs_set_line_to_func (funcs, hb_cairo_line_to, nullptr, nullptr);
+ hb_draw_funcs_set_cubic_to_func (funcs, hb_cairo_cubic_to, nullptr, nullptr);
+ hb_draw_funcs_set_close_path_func (funcs, hb_cairo_close_path, nullptr, nullptr);
+
+ hb_draw_funcs_make_immutable (funcs);
+
+ hb_atexit (free_static_cairo_draw_funcs);
+
+ return funcs;
+ }
+} static_cairo_draw_funcs;
+
+static inline
+void free_static_cairo_draw_funcs ()
+{
+ static_cairo_draw_funcs.free_instance ();
+}
+
+static hb_draw_funcs_t *
+hb_cairo_draw_get_funcs ()
+{
+ return static_cairo_draw_funcs.get_unconst ();
+}
+
+
+#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
+
+static void
+hb_cairo_push_transform (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ float xx, float yx,
+ float xy, float yy,
+ float dx, float dy,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+ cairo_t *cr = c->cr;
+
+ cairo_matrix_t m;
+
+ cairo_save (cr);
+ cairo_matrix_init (&m, (double) xx, (double) yx,
+ (double) xy, (double) yy,
+ (double) dx, (double) dy);
+ cairo_transform (cr, &m);
+}
+
+static void
+hb_cairo_pop_transform (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+ cairo_t *cr = c->cr;
+
+ cairo_restore (cr);
+}
+
+static void
+hb_cairo_push_clip_glyph (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ hb_codepoint_t glyph,
+ hb_font_t *font,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+ cairo_t *cr = c->cr;
+
+ cairo_save (cr);
+ cairo_new_path (cr);
+ hb_font_draw_glyph (font, glyph, hb_cairo_draw_get_funcs (), cr);
+ cairo_close_path (cr);
+ cairo_clip (cr);
+}
+
+static void
+hb_cairo_push_clip_rectangle (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ float xmin, float ymin, float xmax, float ymax,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+ cairo_t *cr = c->cr;
+
+ cairo_save (cr);
+ cairo_rectangle (cr,
+ (double) xmin, (double) ymin,
+ (double) (xmax - xmin), (double) (ymax - ymin));
+ cairo_clip (cr);
+}
+
+static void
+hb_cairo_pop_clip (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+ cairo_t *cr = c->cr;
+
+ cairo_restore (cr);
+}
+
+static void
+hb_cairo_push_group (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+ cairo_t *cr = c->cr;
+
+ cairo_save (cr);
+ cairo_push_group (cr);
+}
+
+static void
+hb_cairo_pop_group (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ hb_paint_composite_mode_t mode,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+ cairo_t *cr = c->cr;
+
+ cairo_pop_group_to_source (cr);
+ cairo_set_operator (cr, _hb_paint_composite_mode_to_cairo (mode));
+ cairo_paint (cr);
+
+ cairo_restore (cr);
+}
+
+static void
+hb_cairo_paint_color (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ hb_bool_t use_foreground,
+ hb_color_t color,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+ cairo_t *cr = c->cr;
+
+ if (use_foreground)
+ {
+#ifdef HAVE_CAIRO_USER_SCALED_FONT_GET_FOREGROUND_SOURCE
+ double r, g, b, a;
+ cairo_pattern_t *foreground = cairo_user_scaled_font_get_foreground_source (c->scaled_font);
+ if (cairo_pattern_get_rgba (foreground, &r, &g, &b, &a) == CAIRO_STATUS_SUCCESS)
+ cairo_set_source_rgba (cr, r, g, b, a * hb_color_get_alpha (color) / 255.);
+ else
+#endif
+ cairo_set_source_rgba (cr, 0, 0, 0, hb_color_get_alpha (color) / 255.);
+ }
+ else
+ cairo_set_source_rgba (cr,
+ hb_color_get_red (color) / 255.,
+ hb_color_get_green (color) / 255.,
+ hb_color_get_blue (color) / 255.,
+ hb_color_get_alpha (color) / 255.);
+ cairo_paint (cr);
+}
+
+static hb_bool_t
+hb_cairo_paint_image (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ hb_blob_t *blob,
+ unsigned width,
+ unsigned height,
+ hb_tag_t format,
+ float slant,
+ hb_glyph_extents_t *extents,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+
+ return _hb_cairo_paint_glyph_image (c, blob, width, height, format, slant, extents);
+}
+
+static void
+hb_cairo_paint_linear_gradient (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float x1, float y1,
+ float x2, float y2,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+
+ _hb_cairo_paint_linear_gradient (c, color_line, x0, y0, x1, y1, x2, y2);
+}
+
+static void
+hb_cairo_paint_radial_gradient (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0, float r0,
+ float x1, float y1, float r1,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+
+ _hb_cairo_paint_radial_gradient (c, color_line, x0, y0, r0, x1, y1, r1);
+}
+
+static void
+hb_cairo_paint_sweep_gradient (hb_paint_funcs_t *pfuncs HB_UNUSED,
+ void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float start_angle, float end_angle,
+ void *user_data HB_UNUSED)
+{
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+
+ _hb_cairo_paint_sweep_gradient (c, color_line, x0, y0, start_angle, end_angle);
+}
+
+static const cairo_user_data_key_t color_cache_key = {0};
+
+static void
+_hb_cairo_destroy_map (void *p)
+{
+ hb_map_destroy ((hb_map_t *) p);
+}
+
+static hb_bool_t
+hb_cairo_paint_custom_palette_color (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ unsigned int color_index,
+ hb_color_t *color,
+ void *user_data HB_UNUSED)
+{
+#ifdef HAVE_CAIRO_FONT_OPTIONS_GET_CUSTOM_PALETTE_COLOR
+ hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
+ cairo_t *cr = c->cr;
+
+#define HB_DEADBEEF HB_TAG(0xDE,0xAD,0xBE,0xEF)
+
+ hb_map_t *color_cache = c->color_cache;
+ hb_codepoint_t *v;
+ if (likely (color_cache && color_cache->has (color_index, &v)))
+ {
+ if (*v == HB_DEADBEEF)
+ return false;
+ *color = *v;
+ return true;
+ }
+
+ cairo_font_options_t *options;
+ double red, green, blue, alpha;
+
+ options = cairo_font_options_create ();
+ cairo_get_font_options (cr, options);
+ if (CAIRO_STATUS_SUCCESS ==
+ cairo_font_options_get_custom_palette_color (options, color_index,
+ &red, &green, &blue, &alpha))
+ {
+ cairo_font_options_destroy (options);
+ *color = HB_COLOR (round (255 * blue),
+ round (255 * green),
+ round (255 * red),
+ round (255 * alpha));
+
+ if (likely (color_cache && *color != HB_DEADBEEF))
+ color_cache->set (color_index, *color);
+
+ return true;
+ }
+ cairo_font_options_destroy (options);
+
+ if (likely (color_cache))
+ color_cache->set (color_index, HB_DEADBEEF);
+
+#undef HB_DEADBEEF
+
+#endif
+
+ return false;
+}
+
+static inline void free_static_cairo_paint_funcs ();
+
+static struct hb_cairo_paint_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t<hb_cairo_paint_funcs_lazy_loader_t>
+{
+ static hb_paint_funcs_t *create ()
+ {
+ hb_paint_funcs_t *funcs = hb_paint_funcs_create ();
+
+ hb_paint_funcs_set_push_transform_func (funcs, hb_cairo_push_transform, nullptr, nullptr);
+ hb_paint_funcs_set_pop_transform_func (funcs, hb_cairo_pop_transform, nullptr, nullptr);
+ hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_cairo_push_clip_glyph, nullptr, nullptr);
+ hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_cairo_push_clip_rectangle, nullptr, nullptr);
+ hb_paint_funcs_set_pop_clip_func (funcs, hb_cairo_pop_clip, nullptr, nullptr);
+ hb_paint_funcs_set_push_group_func (funcs, hb_cairo_push_group, nullptr, nullptr);
+ hb_paint_funcs_set_pop_group_func (funcs, hb_cairo_pop_group, nullptr, nullptr);
+ hb_paint_funcs_set_color_func (funcs, hb_cairo_paint_color, nullptr, nullptr);
+ hb_paint_funcs_set_image_func (funcs, hb_cairo_paint_image, nullptr, nullptr);
+ hb_paint_funcs_set_linear_gradient_func (funcs, hb_cairo_paint_linear_gradient, nullptr, nullptr);
+ hb_paint_funcs_set_radial_gradient_func (funcs, hb_cairo_paint_radial_gradient, nullptr, nullptr);
+ hb_paint_funcs_set_sweep_gradient_func (funcs, hb_cairo_paint_sweep_gradient, nullptr, nullptr);
+ hb_paint_funcs_set_custom_palette_color_func (funcs, hb_cairo_paint_custom_palette_color, nullptr, nullptr);
+
+ hb_paint_funcs_make_immutable (funcs);
+
+ hb_atexit (free_static_cairo_paint_funcs);
+
+ return funcs;
+ }
+} static_cairo_paint_funcs;
+
+static inline
+void free_static_cairo_paint_funcs ()
+{
+ static_cairo_paint_funcs.free_instance ();
+}
+
+static hb_paint_funcs_t *
+hb_cairo_paint_get_funcs ()
+{
+ return static_cairo_paint_funcs.get_unconst ();
+}
+#endif
+
+static const cairo_user_data_key_t hb_cairo_face_user_data_key = {0};
+static const cairo_user_data_key_t hb_cairo_font_user_data_key = {0};
+static const cairo_user_data_key_t hb_cairo_font_init_func_user_data_key = {0};
+static const cairo_user_data_key_t hb_cairo_font_init_user_data_user_data_key = {0};
+static const cairo_user_data_key_t hb_cairo_scale_factor_user_data_key = {0};
+
+static void hb_cairo_face_destroy (void *p) { hb_face_destroy ((hb_face_t *) p); }
+static void hb_cairo_font_destroy (void *p) { hb_font_destroy ((hb_font_t *) p); }
+
+static cairo_status_t
+hb_cairo_init_scaled_font (cairo_scaled_font_t *scaled_font,
+ cairo_t *cr HB_UNUSED,
+ cairo_font_extents_t *extents)
+{
+ cairo_font_face_t *font_face = cairo_scaled_font_get_font_face (scaled_font);
+
+ hb_font_t *font = (hb_font_t *) cairo_font_face_get_user_data (font_face,
+ &hb_cairo_font_user_data_key);
+
+ if (!font)
+ {
+ hb_face_t *face = (hb_face_t *) cairo_font_face_get_user_data (font_face,
+ &hb_cairo_face_user_data_key);
+ font = hb_font_create (face);
+
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,16,0)
+ cairo_font_options_t *font_options = cairo_font_options_create ();
+
+ // Set variations
+ cairo_scaled_font_get_font_options (scaled_font, font_options);
+ const char *variations = cairo_font_options_get_variations (font_options);
+ hb_vector_t<hb_variation_t> vars;
+ const char *p = variations;
+ while (p && *p)
+ {
+ const char *end = strpbrk ((char *) p, ", ");
+ hb_variation_t var;
+ if (hb_variation_from_string (p, end ? end - p : -1, &var))
+ vars.push (var);
+ p = end ? end + 1 : nullptr;
+ }
+ hb_font_set_variations (font, &vars[0], vars.length);
+
+ cairo_font_options_destroy (font_options);
+#endif
+
+ // Set scale; Note: should NOT set slant, or we'll double-slant.
+ unsigned scale_factor = hb_cairo_font_face_get_scale_factor (font_face);
+ if (scale_factor)
+ {
+ cairo_matrix_t font_matrix;
+ cairo_scaled_font_get_scale_matrix (scaled_font, &font_matrix);
+ hb_font_set_scale (font,
+ round (font_matrix.xx * scale_factor),
+ round (font_matrix.yy * scale_factor));
+ }
+
+ auto *init_func = (hb_cairo_font_init_func_t)
+ cairo_font_face_get_user_data (font_face,
+ &hb_cairo_font_init_func_user_data_key);
+ if (init_func)
+ {
+ void *user_data = cairo_font_face_get_user_data (font_face,
+ &hb_cairo_font_init_user_data_user_data_key);
+ font = init_func (font, scaled_font, user_data);
+ }
+
+ hb_font_make_immutable (font);
+ }
+
+ cairo_scaled_font_set_user_data (scaled_font,
+ &hb_cairo_font_user_data_key,
+ (void *) hb_font_reference (font),
+ hb_cairo_font_destroy);
+
+ hb_position_t x_scale, y_scale;
+ hb_font_get_scale (font, &x_scale, &y_scale);
+
+ hb_font_extents_t hb_extents;
+ hb_font_get_h_extents (font, &hb_extents);
+
+ extents->ascent = (double) hb_extents.ascender / y_scale;
+ extents->descent = (double) -hb_extents.descender / y_scale;
+ extents->height = extents->ascent + extents->descent;
+
+#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
+ hb_map_t *color_cache = hb_map_create ();
+ if (unlikely (CAIRO_STATUS_SUCCESS != cairo_scaled_font_set_user_data (scaled_font,
+ &color_cache_key,
+ color_cache,
+ _hb_cairo_destroy_map)))
+ hb_map_destroy (color_cache);
+#endif
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+hb_cairo_text_to_glyphs (cairo_scaled_font_t *scaled_font,
+ const char *utf8,
+ int utf8_len,
+ cairo_glyph_t **glyphs,
+ int *num_glyphs,
+ cairo_text_cluster_t **clusters,
+ int *num_clusters,
+ cairo_text_cluster_flags_t *cluster_flags)
+{
+ hb_font_t *font = (hb_font_t *) cairo_scaled_font_get_user_data (scaled_font,
+ &hb_cairo_font_user_data_key);
+
+ hb_buffer_t *buffer = hb_buffer_create ();
+ hb_buffer_add_utf8 (buffer, utf8, utf8_len, 0, utf8_len);
+ hb_buffer_guess_segment_properties (buffer);
+ hb_shape (font, buffer, nullptr, 0);
+
+ hb_cairo_glyphs_from_buffer (buffer,
+ true,
+ font->x_scale, font->y_scale,
+ 0., 0.,
+ utf8, utf8_len,
+ glyphs, (unsigned *) num_glyphs,
+ clusters, (unsigned *) num_clusters,
+ cluster_flags);
+
+ hb_buffer_destroy (buffer);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+hb_cairo_render_glyph (cairo_scaled_font_t *scaled_font,
+ unsigned long glyph,
+ cairo_t *cr,
+ cairo_text_extents_t *extents)
+{
+ hb_font_t *font = (hb_font_t *) cairo_scaled_font_get_user_data (scaled_font,
+ &hb_cairo_font_user_data_key);
+
+ hb_position_t x_scale, y_scale;
+ hb_font_get_scale (font, &x_scale, &y_scale);
+ cairo_scale (cr, +1./x_scale, -1./y_scale);
+
+ hb_font_draw_glyph (font, glyph, hb_cairo_draw_get_funcs (), cr);
+
+ cairo_fill (cr);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
+
+static cairo_status_t
+hb_cairo_render_color_glyph (cairo_scaled_font_t *scaled_font,
+ unsigned long glyph,
+ cairo_t *cr,
+ cairo_text_extents_t *extents)
+{
+ hb_font_t *font = (hb_font_t *) cairo_scaled_font_get_user_data (scaled_font,
+ &hb_cairo_font_user_data_key);
+
+ unsigned int palette = 0;
+#ifdef CAIRO_COLOR_PALETTE_DEFAULT
+ cairo_font_options_t *options = cairo_font_options_create ();
+ cairo_scaled_font_get_font_options (scaled_font, options);
+ palette = cairo_font_options_get_color_palette (options);
+ cairo_font_options_destroy (options);
+#endif
+
+ hb_color_t color = HB_COLOR (0, 0, 0, 255);
+ hb_position_t x_scale, y_scale;
+ hb_font_get_scale (font, &x_scale, &y_scale);
+ cairo_scale (cr, +1./x_scale, -1./y_scale);
+
+ hb_cairo_context_t c;
+ c.scaled_font = scaled_font;
+ c.cr = cr;
+ c.color_cache = (hb_map_t *) cairo_scaled_font_get_user_data (scaled_font, &color_cache_key);
+
+ hb_font_paint_glyph (font, glyph, hb_cairo_paint_get_funcs (), &c, palette, color);
+
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+#endif
+
+static cairo_font_face_t *
+user_font_face_create (hb_face_t *face)
+{
+ cairo_font_face_t *cairo_face;
+
+ cairo_face = cairo_user_font_face_create ();
+ cairo_user_font_face_set_init_func (cairo_face, hb_cairo_init_scaled_font);
+ cairo_user_font_face_set_text_to_glyphs_func (cairo_face, hb_cairo_text_to_glyphs);
+ cairo_user_font_face_set_render_glyph_func (cairo_face, hb_cairo_render_glyph);
+#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
+ if (hb_ot_color_has_png (face) || hb_ot_color_has_layers (face) || hb_ot_color_has_paint (face))
+ cairo_user_font_face_set_render_color_glyph_func (cairo_face, hb_cairo_render_color_glyph);
+#endif
+
+ if (unlikely (CAIRO_STATUS_SUCCESS != cairo_font_face_set_user_data (cairo_face,
+ &hb_cairo_face_user_data_key,
+ (void *) hb_face_reference (face),
+ hb_cairo_face_destroy)))
+ hb_face_destroy (face);
+
+ return cairo_face;
+}
+
+/**
+ * hb_cairo_font_face_create_for_font:
+ * @font: a #hb_font_t
+ *
+ * Creates a #cairo_font_face_t for rendering text according
+ * to @font.
+ *
+ * Note that the scale of @font does not affect the rendering,
+ * but the variations and slant that are set on @font do.
+ *
+ * Returns: (transfer full): a newly created #cairo_font_face_t
+ *
+ * Since: 7.0.0
+ */
+cairo_font_face_t *
+hb_cairo_font_face_create_for_font (hb_font_t *font)
+{
+ hb_font_make_immutable (font);
+
+ auto *cairo_face = user_font_face_create (font->face);
+
+ if (unlikely (CAIRO_STATUS_SUCCESS != cairo_font_face_set_user_data (cairo_face,
+ &hb_cairo_font_user_data_key,
+ (void *) hb_font_reference (font),
+ hb_cairo_font_destroy)))
+ hb_font_destroy (font);
+
+ return cairo_face;
+}
+
+/**
+ * hb_cairo_font_face_get_font:
+ * @font_face: a #cairo_font_face_t
+ *
+ * Gets the #hb_font_t that @font_face was created from.
+ *
+ * Returns: (nullable) (transfer none): the #hb_font_t that @font_face was created from
+ *
+ * Since: 7.0.0
+ */
+hb_font_t *
+hb_cairo_font_face_get_font (cairo_font_face_t *font_face)
+{
+ return (hb_font_t *) cairo_font_face_get_user_data (font_face,
+ &hb_cairo_font_user_data_key);
+}
+
+/**
+ * hb_cairo_font_face_create_for_face:
+ * @face: a #hb_face_t
+ *
+ * Creates a #cairo_font_face_t for rendering text according
+ * to @face.
+ *
+ * Returns: (transfer full): a newly created #cairo_font_face_t
+ *
+ * Since: 7.0.0
+ */
+cairo_font_face_t *
+hb_cairo_font_face_create_for_face (hb_face_t *face)
+{
+ hb_face_make_immutable (face);
+
+ return user_font_face_create (face);
+}
+
+/**
+ * hb_cairo_font_face_get_face:
+ * @font_face: a #cairo_font_face_t
+ *
+ * Gets the #hb_face_t associated with @font_face.
+ *
+ * Returns: (nullable) (transfer none): the #hb_face_t associated with @font_face
+ *
+ * Since: 7.0.0
+ */
+hb_face_t *
+hb_cairo_font_face_get_face (cairo_font_face_t *font_face)
+{
+ return (hb_face_t *) cairo_font_face_get_user_data (font_face,
+ &hb_cairo_face_user_data_key);
+}
+
+/**
+ * hb_cairo_font_face_set_font_init_func:
+ * @font_face: a #cairo_font_face_t
+ * @func: The virtual method to use
+ * @user_data: user data accompanying the method
+ * @destroy: function to call when @user_data is not needed anymore
+ *
+ * Set the virtual method to be called when a cairo
+ * face created using hb_cairo_font_face_create_for_face()
+ * creates an #hb_font_t for a #cairo_scaled_font_t.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_cairo_font_face_set_font_init_func (cairo_font_face_t *font_face,
+ hb_cairo_font_init_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy)
+{
+ cairo_font_face_set_user_data (font_face,
+ &hb_cairo_font_init_func_user_data_key,
+ (void *) func,
+ nullptr);
+ if (unlikely (CAIRO_STATUS_SUCCESS != cairo_font_face_set_user_data (font_face,
+ &hb_cairo_font_init_user_data_user_data_key,
+ (void *) user_data,
+ destroy)) && destroy)
+ {
+ destroy (user_data);
+ cairo_font_face_set_user_data (font_face,
+ &hb_cairo_font_init_func_user_data_key,
+ nullptr,
+ nullptr);
+ }
+}
+
+/**
+ * hb_cairo_scaled_font_get_font:
+ * @scaled_font: a #cairo_scaled_font_t
+ *
+ * Gets the #hb_font_t associated with @scaled_font.
+ *
+ * Returns: (nullable) (transfer none): the #hb_font_t associated with @scaled_font
+ *
+ * Since: 7.0.0
+ */
+hb_font_t *
+hb_cairo_scaled_font_get_font (cairo_scaled_font_t *scaled_font)
+{
+ return (hb_font_t *) cairo_scaled_font_get_user_data (scaled_font, &hb_cairo_font_user_data_key);
+}
+
+
+/**
+ * hb_cairo_font_face_set_scale_factor:
+ * @scale_factor: The scale factor to use. See below
+ * @font_face: a #cairo_font_face_t
+ *
+ * Sets the scale factor of the @font_face. Default scale
+ * factor is zero.
+ *
+ * When a #cairo_font_face_t is created from a #hb_face_t using
+ * hb_cairo_font_face_create_for_face(), such face will create
+ * #hb_font_t objects during scaled-font creation. The scale
+ * factor defines how the scale set on such #hb_font_t objects
+ * relates to the font-matrix (as such font size) of the cairo
+ * scaled-font.
+ *
+ * If the scale-factor is zero (default), then the scale of the
+ * #hb_font_t object will be left at default, which is the UPEM
+ * value of the respective #hb_face_t.
+ *
+ * If the scale-factor is set to non-zero, then the X and Y scale
+ * of the #hb_font_t object will be respectively set to the
+ * @scale_factor times the xx and yy elements of the scale-matrix
+ * of the cairo scaled-font being created.
+ *
+ * When using the hb_cairo_glyphs_from_buffer() API to convert the
+ * HarfBuzz glyph buffer that resulted from shaping with such a #hb_font_t,
+ * if the scale-factor was non-zero, you can pass it directly to
+ * that API as both X and Y scale factors.
+ *
+ * If the scale-factor was zero however, or the cairo face was
+ * created using the alternative constructor
+ * hb_cairo_font_face_create_for_font(), you need to calculate the
+ * correct X/Y scale-factors to pass to hb_cairo_glyphs_from_buffer()
+ * by dividing the #hb_font_t X/Y scale-factors by the
+ * cairo scaled-font's scale-matrix XX/YY components respectively
+ * and use those values. Or if you know that relationship offhand
+ * (because you set the scale of the #hb_font_t yourself), use
+ * the conversion rate involved.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_cairo_font_face_set_scale_factor (cairo_font_face_t *font_face,
+ unsigned int scale_factor)
+{
+ cairo_font_face_set_user_data (font_face,
+ &hb_cairo_scale_factor_user_data_key,
+ (void *) (uintptr_t) scale_factor,
+ nullptr);
+}
+
+/**
+ * hb_cairo_font_face_get_scale_factor:
+ * @font_face: a #cairo_font_face_t
+ *
+ * Gets the scale factor set on the @font_face. Defaults to zero.
+ * See hb_cairo_font_face_set_scale_factor() for details.
+ *
+ * Returns: the scale factor of @font_face
+ *
+ * Since: 7.0.0
+ */
+unsigned int
+hb_cairo_font_face_get_scale_factor (cairo_font_face_t *font_face)
+{
+ return (unsigned int) (uintptr_t)
+ cairo_font_face_get_user_data (font_face,
+ &hb_cairo_scale_factor_user_data_key);
+}
+
+
+/**
+ * hb_cairo_glyphs_from_buffer:
+ * @buffer: a #hb_buffer_t containing glyphs
+ * @utf8_clusters: `true` if @buffer clusters are in bytes, instead of characters
+ * @x_scale_factor: scale factor to divide #hb_position_t Y values by
+ * @y_scale_factor: scale factor to divide #hb_position_t X values by
+ * @x: X position to place first glyph
+ * @y: Y position to place first glyph
+ * @utf8: (nullable): the text that was shaped in @buffer
+ * @utf8_len: the length of @utf8 in bytes
+ * @glyphs: (out): return location for an array of #cairo_glyph_t
+ * @num_glyphs: (inout): return location for the length of @glyphs
+ * @clusters: (out) (nullable): return location for an array of cluster positions
+ * @num_clusters: (inout) (nullable): return location for the length of @clusters
+ * @cluster_flags: (out) (nullable): return location for cluster flags
+ *
+ * Extracts information from @buffer in a form that can be
+ * passed to cairo_show_text_glyphs() or cairo_show_glyphs().
+ * This API is modeled after cairo_scaled_font_text_to_glyphs() and
+ * cairo_user_scaled_font_text_to_glyphs_func_t.
+ *
+ * The @num_glyphs argument should be preset to the number of glyph entries available
+ * in the @glyphs buffer. If the @glyphs buffer is `NULL`, the value of
+ * @num_glyphs must be zero. If the provided glyph array is too short for
+ * the conversion (or for convenience), a new glyph array may be allocated
+ * using cairo_glyph_allocate() and placed in @glyphs. Upon return,
+ * @num_glyphs should contain the number of generated glyphs. If the value
+ * @glyphs points at has changed after the call, the caller will free the
+ * allocated glyph array using cairo_glyph_free(). The caller will also free
+ * the original value of @glyphs, so this function shouldn't do so.
+ *
+ * If @clusters is not `NULL`, then @num_clusters and @cluster_flags
+ * should not be either, and @utf8 must be provided, and cluster
+ * mapping will be computed. The semantics of how
+ * cluster array allocation works is similar to the glyph array. That is,
+ * if @clusters initially points to a non-`NULL` value, that array may be used
+ * as a cluster buffer, and @num_clusters points to the number of cluster
+ * entries available there. If the provided cluster array is too short for
+ * the conversion (or for convenience), a new cluster array may be allocated
+ * using cairo_text_cluster_allocate() and placed in @clusters. In this case,
+ * the original value of @clusters will still be freed by the caller. Upon
+ * return, @num_clusters will contain the number of generated clusters.
+ * If the value @clusters points at has changed after the call, the caller
+ * will free the allocated cluster array using cairo_text_cluster_free().
+ *
+ * See hb_cairo_font_face_set_scale_factor() for the details of
+ * the @scale_factor argument.
+ *
+ * The returned @glyphs vector actually has `@num_glyphs + 1` entries in
+ * it and the x,y values of the extra entry at the end add up the advance
+ * x,y of all the glyphs in the @buffer.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_cairo_glyphs_from_buffer (hb_buffer_t *buffer,
+ hb_bool_t utf8_clusters,
+ double x_scale_factor,
+ double y_scale_factor,
+ double x,
+ double y,
+ const char *utf8,
+ int utf8_len,
+ cairo_glyph_t **glyphs,
+ unsigned int *num_glyphs,
+ cairo_text_cluster_t **clusters,
+ unsigned int *num_clusters,
+ cairo_text_cluster_flags_t *cluster_flags)
+{
+ if (utf8 && utf8_len < 0)
+ utf8_len = strlen (utf8);
+
+ unsigned orig_num_glyphs = *num_glyphs;
+ *num_glyphs = hb_buffer_get_length (buffer);
+ hb_glyph_info_t *hb_glyph = hb_buffer_get_glyph_infos (buffer, nullptr);
+ hb_glyph_position_t *hb_position = hb_buffer_get_glyph_positions (buffer, nullptr);
+ if (orig_num_glyphs < *num_glyphs + 1)
+ *glyphs = cairo_glyph_allocate (*num_glyphs + 1);
+
+ if (clusters && utf8)
+ {
+ unsigned orig_num_clusters = *num_clusters;
+ *num_clusters = *num_glyphs ? 1 : 0;
+ for (unsigned int i = 1; i < *num_glyphs; i++)
+ if (hb_glyph[i].cluster != hb_glyph[i-1].cluster)
+ (*num_clusters)++;
+ if (orig_num_clusters < *num_clusters)
+ *clusters = cairo_text_cluster_allocate (*num_clusters);
+ }
+
+ double x_scale = x_scale_factor ? 1. / x_scale_factor : 0.;
+ double y_scale = y_scale_factor ? 1. / y_scale_factor : 0.;
+ hb_position_t hx = 0, hy = 0;
+ int i;
+ for (i = 0; i < (int) *num_glyphs; i++)
+ {
+ (*glyphs)[i].index = hb_glyph[i].codepoint;
+ (*glyphs)[i].x = x + (+hb_position->x_offset + hx) * x_scale;
+ (*glyphs)[i].y = y + (-hb_position->y_offset + hy) * y_scale;
+ hx += hb_position->x_advance;
+ hy += -hb_position->y_advance;
+
+ hb_position++;
+ }
+ (*glyphs)[i].index = -1;
+ (*glyphs)[i].x = round (hx * x_scale);
+ (*glyphs)[i].y = round (hy * y_scale);
+
+ if (clusters && *num_clusters && utf8)
+ {
+ memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0]));
+ hb_bool_t backward = HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (buffer));
+ *cluster_flags = backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : (cairo_text_cluster_flags_t) 0;
+ unsigned int cluster = 0;
+ const char *start = utf8, *end;
+ (*clusters)[cluster].num_glyphs++;
+ if (backward)
+ {
+ for (i = *num_glyphs - 2; i >= 0; i--)
+ {
+ if (hb_glyph[i].cluster != hb_glyph[i+1].cluster)
+ {
+ assert (hb_glyph[i].cluster > hb_glyph[i+1].cluster);
+ if (utf8_clusters)
+ end = start + hb_glyph[i].cluster - hb_glyph[i+1].cluster;
+ else
+ end = (const char *) hb_utf_offset_to_pointer<hb_utf8_t> ((const uint8_t *) start,
+ (signed) (hb_glyph[i].cluster - hb_glyph[i+1].cluster));
+ (*clusters)[cluster].num_bytes = end - start;
+ start = end;
+ cluster++;
+ }
+ (*clusters)[cluster].num_glyphs++;
+ }
+ (*clusters)[cluster].num_bytes = utf8 + utf8_len - start;
+ }
+ else
+ {
+ for (i = 1; i < (int) *num_glyphs; i++)
+ {
+ if (hb_glyph[i].cluster != hb_glyph[i-1].cluster)
+ {
+ assert (hb_glyph[i].cluster > hb_glyph[i-1].cluster);
+ if (utf8_clusters)
+ end = start + hb_glyph[i].cluster - hb_glyph[i-1].cluster;
+ else
+ end = (const char *) hb_utf_offset_to_pointer<hb_utf8_t> ((const uint8_t *) start,
+ (signed) (hb_glyph[i].cluster - hb_glyph[i-1].cluster));
+ (*clusters)[cluster].num_bytes = end - start;
+ start = end;
+ cluster++;
+ }
+ (*clusters)[cluster].num_glyphs++;
+ }
+ (*clusters)[cluster].num_bytes = utf8 + utf8_len - start;
+ }
+ }
+ else if (num_clusters)
+ *num_clusters = 0;
+}
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo.h b/src/3rdparty/harfbuzz-ng/src/hb-cairo.h
new file mode 100644
index 0000000000..21e284c8f9
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2022 Red Hat, 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.
+ *
+ * Red Hat Author(s): Matthias Clasen
+ */
+
+#ifndef HB_CAIRO_H
+#define HB_CAIRO_H
+
+#include "hb.h"
+
+#include <cairo.h>
+
+HB_BEGIN_DECLS
+
+HB_EXTERN cairo_font_face_t *
+hb_cairo_font_face_create_for_font (hb_font_t *font);
+
+HB_EXTERN hb_font_t *
+hb_cairo_font_face_get_font (cairo_font_face_t *font_face);
+
+HB_EXTERN cairo_font_face_t *
+hb_cairo_font_face_create_for_face (hb_face_t *face);
+
+HB_EXTERN hb_face_t *
+hb_cairo_font_face_get_face (cairo_font_face_t *font_face);
+
+/**
+ * hb_cairo_font_init_func_t:
+ * @font: The #hb_font_t being created
+ * @scaled_font: The respective #cairo_scaled_font_t
+ * @user_data: User data accompanying this method
+ *
+ * The type of a virtual method to be called when a cairo
+ * face created using hb_cairo_font_face_create_for_face()
+ * creates an #hb_font_t for a #cairo_scaled_font_t.
+ *
+ * Return value: the #hb_font_t value to use; in most cases same as @font
+ *
+ * Since: 7.0.0
+ */
+typedef hb_font_t * (*hb_cairo_font_init_func_t) (hb_font_t *font,
+ cairo_scaled_font_t *scaled_font,
+ void *user_data);
+
+HB_EXTERN void
+hb_cairo_font_face_set_font_init_func (cairo_font_face_t *font_face,
+ hb_cairo_font_init_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+HB_EXTERN hb_font_t *
+hb_cairo_scaled_font_get_font (cairo_scaled_font_t *scaled_font);
+
+HB_EXTERN void
+hb_cairo_font_face_set_scale_factor (cairo_font_face_t *font_face,
+ unsigned int scale_factor);
+
+HB_EXTERN unsigned int
+hb_cairo_font_face_get_scale_factor (cairo_font_face_t *font_face);
+
+HB_EXTERN void
+hb_cairo_glyphs_from_buffer (hb_buffer_t *buffer,
+ hb_bool_t utf8_clusters,
+ double x_scale_factor,
+ double y_scale_factor,
+ double x,
+ double y,
+ const char *utf8,
+ int utf8_len,
+ cairo_glyph_t **glyphs,
+ unsigned int *num_glyphs,
+ cairo_text_cluster_t **clusters,
+ unsigned int *num_clusters,
+ cairo_text_cluster_flags_t *cluster_flags);
+
+HB_END_DECLS
+
+#endif /* HB_CAIRO_H */
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 49805a89c5..949bfebf9b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
@@ -488,7 +488,7 @@ struct op_str_t
const unsigned char *ptr = nullptr;
- op_code_t op;
+ op_code_t op = OpCode_Invalid;
uint8_t length = 0;
};
@@ -522,20 +522,10 @@ struct parsed_values_t
void alloc (unsigned n)
{
- values.alloc (n);
+ values.alloc (n, true);
}
- void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ())
- {
- VAL *val = values.push ();
- val->op = op;
- auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
- val->ptr = arr.arrayZ;
- val->length = arr.length;
- opStart = str_ref.get_offset ();
- }
-
- void add_op (op_code_t op, const byte_str_ref_t& str_ref, const VAL &v)
+ void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t (), const VAL &v = VAL ())
{
VAL *val = values.push (v);
val->op = op;
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 f93c83ab45..f40be51f0d 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
@@ -57,7 +57,6 @@ struct call_context_t
/* call stack */
const unsigned int kMaxCallLimit = 10;
-const unsigned int kMaxOps = 10000;
struct call_stack_t : cff_stack_t<call_context_t, kMaxCallLimit> {};
template <typename SUBRS>
@@ -882,7 +881,7 @@ struct cs_interpreter_t : interpreter_t<ENV>
{
SUPER::env.set_endchar (false);
- unsigned max_ops = kMaxOps;
+ unsigned max_ops = HB_CFF_MAX_OPS;
for (;;) {
if (unlikely (!--max_ops))
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-dict-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-dict-common.hh
index 79fe9b42c5..53226b227e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-dict-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-dict-common.hh
@@ -35,10 +35,8 @@ using namespace OT;
/* an opstr and the parsed out dict value(s) */
struct dict_val_t : op_str_t
{
- void init () { single_val.set_int (0); }
+ void init () {}
void fini () {}
-
- number_t single_val;
};
typedef dict_val_t num_dict_val_t;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff1-interp-cs.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff1-interp-cs.hh
index b306c2ecc9..d8868efa53 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff1-interp-cs.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff1-interp-cs.hh
@@ -38,7 +38,8 @@ typedef biased_subrs_t<CFF1Subrs> cff1_biased_subrs_t;
struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
{
template <typename ACC>
- cff1_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd)
+ cff1_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
+ const int *coords_=nullptr, unsigned int num_coords_=0)
: SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
{
processed_width = false;
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 00c25800e6..915b10cf39 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh
@@ -45,7 +45,7 @@ struct blend_arg_t : number_t
numValues = numValues_;
valueIndex = valueIndex_;
unsigned numBlends = blends_.length;
- if (unlikely (!deltas.resize (numBlends)))
+ if (unlikely (!deltas.resize_exact (numBlends)))
return;
for (unsigned int i = 0; i < numBlends; i++)
deltas.arrayZ[i] = blends_.arrayZ[i];
@@ -55,7 +55,7 @@ struct blend_arg_t : number_t
void reset_blends ()
{
numValues = valueIndex = 0;
- deltas.resize (0);
+ deltas.shrink (0);
}
unsigned int numValues;
@@ -118,7 +118,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
region_count = varStore->varStore.get_region_index_count (get_ivs ());
if (do_blend)
{
- if (unlikely (!scalars.resize (region_count)))
+ if (unlikely (!scalars.resize_exact (region_count)))
SUPER::set_error ();
else
varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
@@ -163,6 +163,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
return v;
}
+ bool have_coords () const { return num_coords; }
+
protected:
const int *coords;
unsigned int num_coords;
@@ -222,7 +224,10 @@ struct cff2_cs_opset_t : cs_opset_t<ELEM, OPSET, cff2_cs_interp_env_t<ELEM>, PAR
const hb_array_t<const ELEM> blends,
unsigned n, unsigned i)
{
- arg.set_blends (n, i, blends);
+ if (env.have_coords ())
+ arg.set_int (round (arg.to_real () + env.blend_deltas (blends)));
+ else
+ arg.set_blends (n, i, blends);
}
template <typename T = ELEM,
hb_enable_if (!hb_is_same (T, blend_arg_t))>
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-common.cc
index e9f9cfeb5f..c9a40295a3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-common.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-common.cc
@@ -29,32 +29,6 @@
#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)
-
-#endif
/**
* SECTION:hb-common
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h
index e92feb9898..a5da4e76a3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-common.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h
@@ -897,6 +897,32 @@ HB_EXTERN uint8_t
hb_color_get_blue (hb_color_t color);
#define hb_color_get_blue(color) (((color) >> 24) & 0xFF)
+/**
+ * hb_glyph_extents_t:
+ * @x_bearing: Distance from the x-origin to the left extremum of the glyph.
+ * @y_bearing: Distance from the top extremum of the glyph to the y-origin.
+ * @width: Distance from the left extremum of the glyph to the right extremum.
+ * @height: Distance from the top extremum of the glyph to the bottom extremum.
+ *
+ * Glyph extent values, measured in font units.
+ *
+ * Note that @height is negative, in coordinate systems that grow up.
+ **/
+typedef struct hb_glyph_extents_t {
+ hb_position_t x_bearing;
+ hb_position_t y_bearing;
+ hb_position_t width;
+ hb_position_t height;
+} hb_glyph_extents_t;
+
+/**
+ * hb_font_t:
+ *
+ * Data type for holding fonts.
+ *
+ */
+typedef struct hb_font_t hb_font_t;
+
HB_END_DECLS
#endif /* HB_COMMON_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-config.hh b/src/3rdparty/harfbuzz-ng/src/hb-config.hh
index 98b1e9d0cf..047518b87d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-config.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-config.hh
@@ -37,6 +37,7 @@
#ifndef HB_EXPERIMENTAL_API
#define HB_NO_BEYOND_64K
+#define HB_NO_CUBIC_GLYF
#define HB_NO_VAR_COMPOSITES
#endif
@@ -80,9 +81,10 @@
#define HB_NO_MMAP
#define HB_NO_NAME
#define HB_NO_OPEN
-#define HB_NO_SETLOCALE
#define HB_NO_OT_FONT_GLYPH_NAMES
#define HB_NO_OT_SHAPE_FRACTIONS
+#define HB_NO_PAINT
+#define HB_NO_SETLOCALE
#define HB_NO_STYLE
#define HB_NO_SUBSET_LAYOUT
#define HB_NO_VERTICAL
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
index 4267e0e13e..a87cb5cd02 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
@@ -511,7 +511,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
buffer->merge_clusters (i - 1, i + 1);
}
- hb_vector_t<feature_record_t> feature_records;
hb_vector_t<range_record_t> range_records;
/*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cplusplus.hh b/src/3rdparty/harfbuzz-ng/src/hb-cplusplus.hh
index a210ab7960..531ef1b7c8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cplusplus.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cplusplus.hh
@@ -160,6 +160,8 @@ HB_DEFINE_VTABLE (map);
HB_DEFINE_VTABLE (set);
HB_DEFINE_VTABLE (shape_plan);
HB_DEFINE_VTABLE (unicode_funcs);
+HB_DEFINE_VTABLE (draw_funcs);
+HB_DEFINE_VTABLE (paint_funcs);
#undef HB_DEFINE_VTABLE
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
index cbe13e5214..efab374646 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
@@ -113,7 +113,7 @@ _hb_print_func (const char *func)
const char *paren = strchr (func, '(');
if (paren)
func_len = paren - func;
- fprintf (stderr, "%.*s", func_len, func);
+ fprintf (stderr, "%.*s", (int) func_len, func);
}
}
@@ -142,9 +142,9 @@ _hb_debug_msg_va (const char *what,
fprintf (stderr, "%-10s", what ? what : "");
if (obj)
- fprintf (stderr, "(%*p) ", (unsigned int) (2 * sizeof (void *)), obj);
+ fprintf (stderr, "(%*p) ", (int) (2 * sizeof (void *)), obj);
else
- fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), "");
+ fprintf (stderr, " %*s ", (int) (2 * sizeof (void *)), "");
if (indented) {
#define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
@@ -306,7 +306,7 @@ struct hb_auto_trace_t
}
_hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
- "return %s (line %d)",
+ "return %s (line %u)",
hb_printer_t<hb_decay<decltype (v)>>().print (v), line);
if (plevel) --*plevel;
plevel = nullptr;
@@ -396,7 +396,7 @@ struct hb_no_trace_t {
#define TRACE_APPLY(this) \
hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
- "idx %d gid %u lookup %d", \
+ "idx %u gid %u lookup %d", \
c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index)
#else
#define TRACE_APPLY(this) hb_no_trace_t<bool> trace
@@ -454,7 +454,7 @@ struct hb_no_trace_t {
#define TRACE_DISPATCH(this, format) \
hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
- "format %d", (int) format)
+ "format %u", (unsigned) format)
#else
#define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h
index 333dc3cd4c..edacfd064c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h
@@ -102,7 +102,8 @@ typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t *glyph,
void *user_data);
-HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func and hb_font_funcs_set_variation_glyph_func) void
+HB_DEPRECATED_FOR (hb_font_funcs_set_nominal_glyph_func and hb_font_funcs_set_variation_glyph_func)
+HB_EXTERN void
hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_func_t func,
void *user_data, hb_destroy_func_t destroy);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc b/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
index de05b7d871..42764a244b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
@@ -251,16 +251,12 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader);
data->dwriteFactory->Release ();
}
- if (data->fontFileLoader)
- delete data->fontFileLoader;
- if (data->fontFileStream)
- delete data->fontFileStream;
- if (data->faceBlob)
- hb_blob_destroy (data->faceBlob);
+ delete data->fontFileLoader;
+ delete data->fontFileStream;
+ hb_blob_destroy (data->faceBlob);
if (data->dwrite_dll)
FreeLibrary (data->dwrite_dll);
- if (data)
- delete data;
+ delete data;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-draw.cc b/src/3rdparty/harfbuzz-ng/src/hb-draw.cc
index 72c203f24f..f204f56bc7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-draw.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-draw.cc
@@ -35,6 +35,8 @@
* @include: hb.h
*
* Functions for drawing (extracting) glyph shapes.
+ *
+ * The #hb_draw_funcs_t struct can be used with hb_font_draw_glyph().
**/
static void
@@ -198,13 +200,29 @@ DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
}
};
+/**
+ * hb_draw_funcs_get_empty:
+ *
+ * Fetches the singleton empty draw-functions structure.
+ *
+ * Return value: (transfer full): The empty draw-functions structure
+ *
+ * Since: 7.0.0
+ **/
+hb_draw_funcs_t *
+hb_draw_funcs_get_empty ()
+{
+ return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
+}
/**
* 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.
+ * Increases the reference count on @dfuncs by one.
+ *
+ * This prevents @dfuncs from being destroyed until a matching
+ * call to hb_draw_funcs_destroy() is made.
*
* Return value: (transfer full):
* The referenced #hb_draw_funcs_t.
@@ -247,6 +265,49 @@ hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
}
/**
+ * hb_draw_funcs_set_user_data: (skip)
+ * @dfuncs: The draw-functions structure
+ * @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 draw-functions structure.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: 7.0.0
+ **/
+hb_bool_t
+hb_draw_funcs_set_user_data (hb_draw_funcs_t *dfuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (dfuncs, key, data, destroy, replace);
+}
+
+/**
+ * hb_draw_funcs_get_user_data: (skip)
+ * @dfuncs: The draw-functions structure
+ * @key: The user-data key to query
+ *
+ * Fetches the user-data associated with the specified key,
+ * attached to the specified draw-functions structure.
+ *
+ * Return value: (transfer none): A pointer to the user data
+ *
+ * Since: 7.0.0
+ **/
+void *
+hb_draw_funcs_get_user_data (const hb_draw_funcs_t *dfuncs,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (dfuncs, key);
+}
+
+/**
* hb_draw_funcs_make_immutable:
* @dfuncs: draw functions
*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-draw.h b/src/3rdparty/harfbuzz-ng/src/hb-draw.h
index c45a53212a..9ca0b4006e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-draw.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-draw.h
@@ -92,11 +92,11 @@ 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
+ * @draw_data: The data accompanying the draw functions in hb_font_draw_glyph()
* @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
+ * @user_data: User data pointer passed to hb_draw_funcs_set_move_to_func()
*
* A virtual method for the #hb_draw_funcs_t to perform a "move-to" draw
* operation.
@@ -112,11 +112,11 @@ typedef void (*hb_draw_move_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data
/**
* hb_draw_line_to_func_t:
* @dfuncs: draw functions object
- * @draw_data: The data accompanying the draw functions
+ * @draw_data: The data accompanying the draw functions in hb_font_draw_glyph()
* @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
+ * @user_data: User data pointer passed to hb_draw_funcs_set_line_to_func()
*
* A virtual method for the #hb_draw_funcs_t to perform a "line-to" draw
* operation.
@@ -132,13 +132,13 @@ typedef void (*hb_draw_line_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data
/**
* hb_draw_quadratic_to_func_t:
* @dfuncs: draw functions object
- * @draw_data: The data accompanying the draw functions
+ * @draw_data: The data accompanying the draw functions in hb_font_draw_glyph()
* @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
+ * @user_data: User data pointer passed to hb_draw_funcs_set_quadratic_to_func()
*
* A virtual method for the #hb_draw_funcs_t to perform a "quadratic-to" draw
* operation.
@@ -155,7 +155,7 @@ typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw
/**
* hb_draw_cubic_to_func_t:
* @dfuncs: draw functions object
- * @draw_data: The data accompanying the draw functions
+ * @draw_data: The data accompanying the draw functions in hb_font_draw_glyph()
* @st: current draw state
* @control1_x: X component of first control point
* @control1_y: Y component of first control point
@@ -163,7 +163,7 @@ typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw
* @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
+ * @user_data: User data pointer passed to hb_draw_funcs_set_cubic_to_func()
*
* A virtual method for the #hb_draw_funcs_t to perform a "cubic-to" draw
* operation.
@@ -181,9 +181,9 @@ typedef void (*hb_draw_cubic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_dat
/**
* hb_draw_close_path_func_t:
* @dfuncs: draw functions object
- * @draw_data: The data accompanying the draw functions
+ * @draw_data: The data accompanying the draw functions in hb_font_draw_glyph()
* @st: current draw state
- * @user_data: User data pointer passed by the caller
+ * @user_data: User data pointer passed to hb_draw_funcs_set_close_path_func()
*
* A virtual method for the #hb_draw_funcs_t to perform a "close-path" draw
* operation.
@@ -280,11 +280,26 @@ HB_EXTERN hb_draw_funcs_t *
hb_draw_funcs_create (void);
HB_EXTERN hb_draw_funcs_t *
+hb_draw_funcs_get_empty (void);
+
+HB_EXTERN hb_draw_funcs_t *
hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs);
+HB_EXTERN hb_bool_t
+hb_draw_funcs_set_user_data (hb_draw_funcs_t *dfuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+
+HB_EXTERN void *
+hb_draw_funcs_get_user_data (const hb_draw_funcs_t *dfuncs,
+ hb_user_data_key_t *key);
+
HB_EXTERN void
hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face-builder.cc b/src/3rdparty/harfbuzz-ng/src/hb-face-builder.cc
new file mode 100644
index 0000000000..84b14d28d6
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-face-builder.cc
@@ -0,0 +1,246 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#include "hb-face.hh"
+
+#include "hb-map.hh"
+#include "hb-open-file.hh"
+#include "hb-serialize.hh"
+
+
+/*
+ * face-builder: A face that has add_table().
+ */
+
+struct face_table_info_t
+{
+ hb_blob_t* data;
+ signed order;
+};
+
+struct hb_face_builder_data_t
+{
+ hb_hashmap_t<hb_tag_t, face_table_info_t> tables;
+};
+
+static int compare_entries (const void* pa, const void* pb)
+{
+ const auto& a = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pa;
+ const auto& b = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pb;
+
+ /* Order by blob size first (smallest to largest) and then table tag */
+
+ if (a.second.order != b.second.order)
+ return a.second.order < b.second.order ? -1 : +1;
+
+ if (a.second.data->length != b.second.data->length)
+ return a.second.data->length < b.second.data->length ? -1 : +1;
+
+ return a.first < b.first ? -1 : a.first == b.first ? 0 : +1;
+}
+
+static hb_face_builder_data_t *
+_hb_face_builder_data_create ()
+{
+ hb_face_builder_data_t *data = (hb_face_builder_data_t *) hb_calloc (1, sizeof (hb_face_builder_data_t));
+ if (unlikely (!data))
+ return nullptr;
+
+ data->tables.init ();
+
+ return data;
+}
+
+static void
+_hb_face_builder_data_destroy (void *user_data)
+{
+ hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+ for (auto info : data->tables.values())
+ hb_blob_destroy (info.data);
+
+ data->tables.fini ();
+
+ hb_free (data);
+}
+
+static hb_blob_t *
+_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
+{
+
+ unsigned int table_count = data->tables.get_population ();
+ unsigned int face_length = table_count * 16 + 12;
+
+ for (auto info : data->tables.values())
+ face_length += hb_ceil_to_4 (hb_blob_get_length (info.data));
+
+ char *buf = (char *) hb_malloc (face_length);
+ if (unlikely (!buf))
+ return nullptr;
+
+ hb_serialize_context_t c (buf, face_length);
+ c.propagate_error (data->tables);
+ OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
+
+ bool is_cff = (data->tables.has (HB_TAG ('C','F','F',' '))
+ || data->tables.has (HB_TAG ('C','F','F','2')));
+ hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
+
+ // Sort the tags so that produced face is deterministic.
+ hb_vector_t<hb_pair_t <hb_tag_t, face_table_info_t>> sorted_entries;
+ data->tables.iter () | hb_sink (sorted_entries);
+ if (unlikely (sorted_entries.in_error ()))
+ {
+ hb_free (buf);
+ return nullptr;
+ }
+
+ sorted_entries.qsort (compare_entries);
+
+ bool ret = f->serialize_single (&c,
+ sfnt_tag,
+ + sorted_entries.iter()
+ | hb_map ([&] (hb_pair_t<hb_tag_t, face_table_info_t> _) {
+ return hb_pair_t<hb_tag_t, hb_blob_t*> (_.first, _.second.data);
+ }));
+
+ c.end_serialize ();
+
+ if (unlikely (!ret))
+ {
+ hb_free (buf);
+ return nullptr;
+ }
+
+ return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, hb_free);
+}
+
+static hb_blob_t *
+_hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
+{
+ hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+ if (!tag)
+ return _hb_face_builder_data_reference_blob (data);
+
+ return hb_blob_reference (data->tables[tag].data);
+}
+
+
+/**
+ * hb_face_builder_create:
+ *
+ * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
+ * After tables are added to the face, it can be compiled to a binary
+ * font file by calling hb_face_reference_blob().
+ *
+ * Return value: (transfer full): New face.
+ *
+ * Since: 1.9.0
+ **/
+hb_face_t *
+hb_face_builder_create ()
+{
+ hb_face_builder_data_t *data = _hb_face_builder_data_create ();
+ if (unlikely (!data)) return hb_face_get_empty ();
+
+ return hb_face_create_for_tables (_hb_face_builder_reference_table,
+ data,
+ _hb_face_builder_data_destroy);
+}
+
+/**
+ * hb_face_builder_add_table:
+ * @face: A face object created with hb_face_builder_create()
+ * @tag: The #hb_tag_t of the table to add
+ * @blob: The blob containing the table data to add
+ *
+ * Add table for @tag with data provided by @blob to the face. @face must
+ * be created using hb_face_builder_create().
+ *
+ * Since: 1.9.0
+ **/
+hb_bool_t
+hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
+{
+ if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+ return false;
+
+ if (tag == HB_MAP_VALUE_INVALID)
+ return false;
+
+ hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
+
+ hb_blob_t* previous = data->tables.get (tag).data;
+ if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), -1}))
+ {
+ hb_blob_destroy (blob);
+ return false;
+ }
+
+ hb_blob_destroy (previous);
+ return true;
+}
+
+/**
+ * hb_face_builder_sort_tables:
+ * @face: A face object created with hb_face_builder_create()
+ * @tags: (array zero-terminated=1): ordered list of table tags terminated by
+ * %HB_TAG_NONE
+ *
+ * Set the ordering of tables for serialization. Any tables not
+ * specified in the tags list will be ordered after the tables in
+ * tags, ordered by the default sort ordering.
+ *
+ * Since: 5.3.0
+ **/
+void
+hb_face_builder_sort_tables (hb_face_t *face,
+ const hb_tag_t *tags)
+{
+ if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+ return;
+
+ hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
+
+ // Sort all unspecified tables after any specified tables.
+ for (auto& info : data->tables.values_ref())
+ info.order = (unsigned) -1;
+
+ signed order = 0;
+ for (const hb_tag_t* tag = tags;
+ *tag;
+ tag++)
+ {
+ face_table_info_t* info;
+ if (!data->tables.has (*tag, &info)) continue;
+ info->order = order++;
+ }
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.cc b/src/3rdparty/harfbuzz-ng/src/hb-face.cc
index 8b4b635c7a..5fcc4e93d9 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-face.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-face.cc
@@ -33,7 +33,6 @@
#include "hb-open-file.hh"
#include "hb-ot-face.hh"
#include "hb-ot-cmap-table.hh"
-#include "hb-map.hh"
/**
@@ -472,6 +471,8 @@ hb_face_get_index (const hb_face_t *face)
*
* Sets the units-per-em (upem) for a face object to the specified value.
*
+ * This API is used in rare circumstances.
+ *
* Since: 0.9.2
**/
void
@@ -488,7 +489,10 @@ hb_face_set_upem (hb_face_t *face,
* hb_face_get_upem:
* @face: A face object
*
- * Fetches the units-per-em (upem) value of the specified face object.
+ * Fetches the units-per-em (UPEM) value of the specified face object.
+ *
+ * Typical UPEM values for fonts are 1000, or 2048, but any value
+ * in between 16 and 16,384 is allowed for OpenType fonts.
*
* Return value: The upem value of @face
*
@@ -507,6 +511,8 @@ hb_face_get_upem (const hb_face_t *face)
*
* Sets the glyph count for a face object to the specified value.
*
+ * This API is used in rare circumstances.
+ *
* Since: 0.9.7
**/
void
@@ -581,7 +587,7 @@ hb_face_get_table_tags (const hb_face_t *face,
/**
* hb_face_collect_unicodes:
* @face: A face object
- * @out: The set to add Unicode characters to
+ * @out: (out): The set to add Unicode characters to
*
* Collects all of the Unicode characters covered by @face and adds
* them to the #hb_set_t set @out.
@@ -595,9 +601,30 @@ hb_face_collect_unicodes (hb_face_t *face,
face->table.cmap->collect_unicodes (out, face->get_num_glyphs ());
}
/**
+ * hb_face_collect_nominal_glyph_mapping:
+ * @face: A face object
+ * @mapping: (out): The map to add Unicode-to-glyph mapping to
+ * @unicodes: (nullable) (out): The set to add Unicode characters to, or `NULL`
+ *
+ * Collects the mapping from Unicode characters to nominal glyphs of the @face,
+ * and optionally all of the Unicode characters covered by @face.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_face_collect_nominal_glyph_mapping (hb_face_t *face,
+ hb_map_t *mapping,
+ hb_set_t *unicodes)
+{
+ hb_set_t stack_unicodes;
+ if (!unicodes)
+ unicodes = &stack_unicodes;
+ face->table.cmap->collect_mapping (unicodes, mapping, face->get_num_glyphs ());
+}
+/**
* hb_face_collect_variation_selectors:
* @face: A face object
- * @out: The set to add Variation Selector characters to
+ * @out: (out): The set to add Variation Selector characters to
*
* Collects all Unicode "Variation Selector" characters covered by @face and adds
* them to the #hb_set_t set @out.
@@ -614,7 +641,7 @@ hb_face_collect_variation_selectors (hb_face_t *face,
* hb_face_collect_variation_unicodes:
* @face: A face object
* @variation_selector: The Variation Selector to query
- * @out: The set to add Unicode characters to
+ * @out: (out): The set to add Unicode characters to
*
* Collects all Unicode characters for @variation_selector covered by @face and adds
* them to the #hb_set_t set @out.
@@ -629,214 +656,3 @@ hb_face_collect_variation_unicodes (hb_face_t *face,
face->table.cmap->collect_variation_unicodes (variation_selector, out);
}
#endif
-
-
-/*
- * face-builder: A face that has add_table().
- */
-
-struct face_table_info_t
-{
- hb_blob_t* data;
- signed order;
-};
-
-struct hb_face_builder_data_t
-{
- hb_hashmap_t<hb_tag_t, face_table_info_t> tables;
-};
-
-static int compare_entries (const void* pa, const void* pb)
-{
- const auto& a = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pa;
- const auto& b = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pb;
-
- /* Order by blob size first (smallest to largest) and then table tag */
-
- if (a.second.order != b.second.order)
- return a.second.order < b.second.order ? -1 : +1;
-
- if (a.second.data->length != b.second.data->length)
- return a.second.data->length < b.second.data->length ? -1 : +1;
-
- return a.first < b.first ? -1 : a.first == b.first ? 0 : +1;
-}
-
-static hb_face_builder_data_t *
-_hb_face_builder_data_create ()
-{
- hb_face_builder_data_t *data = (hb_face_builder_data_t *) hb_calloc (1, sizeof (hb_face_builder_data_t));
- if (unlikely (!data))
- return nullptr;
-
- data->tables.init ();
-
- return data;
-}
-
-static void
-_hb_face_builder_data_destroy (void *user_data)
-{
- hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
-
- for (auto info : data->tables.values())
- hb_blob_destroy (info.data);
-
- data->tables.fini ();
-
- hb_free (data);
-}
-
-static hb_blob_t *
-_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
-{
-
- unsigned int table_count = data->tables.get_population ();
- unsigned int face_length = table_count * 16 + 12;
-
- for (auto info : data->tables.values())
- face_length += hb_ceil_to_4 (hb_blob_get_length (info.data));
-
- char *buf = (char *) hb_malloc (face_length);
- if (unlikely (!buf))
- return nullptr;
-
- hb_serialize_context_t c (buf, face_length);
- c.propagate_error (data->tables);
- OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
-
- bool is_cff = (data->tables.has (HB_TAG ('C','F','F',' '))
- || data->tables.has (HB_TAG ('C','F','F','2')));
- hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
-
- // Sort the tags so that produced face is deterministic.
- hb_vector_t<hb_pair_t <hb_tag_t, face_table_info_t>> sorted_entries;
- data->tables.iter () | hb_sink (sorted_entries);
- if (unlikely (sorted_entries.in_error ()))
- {
- hb_free (buf);
- return nullptr;
- }
-
- sorted_entries.qsort (compare_entries);
-
- bool ret = f->serialize_single (&c,
- sfnt_tag,
- + sorted_entries.iter()
- | hb_map ([&] (hb_pair_t<hb_tag_t, face_table_info_t> _) {
- return hb_pair_t<hb_tag_t, hb_blob_t*> (_.first, _.second.data);
- }));
-
- c.end_serialize ();
-
- if (unlikely (!ret))
- {
- hb_free (buf);
- return nullptr;
- }
-
- return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, hb_free);
-}
-
-static hb_blob_t *
-_hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
-{
- hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
-
- if (!tag)
- return _hb_face_builder_data_reference_blob (data);
-
- return hb_blob_reference (data->tables[tag].data);
-}
-
-
-/**
- * hb_face_builder_create:
- *
- * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
- * After tables are added to the face, it can be compiled to a binary
- * font file by calling hb_face_reference_blob().
- *
- * Return value: (transfer full): New face.
- *
- * Since: 1.9.0
- **/
-hb_face_t *
-hb_face_builder_create ()
-{
- hb_face_builder_data_t *data = _hb_face_builder_data_create ();
- if (unlikely (!data)) return hb_face_get_empty ();
-
- return hb_face_create_for_tables (_hb_face_builder_reference_table,
- data,
- _hb_face_builder_data_destroy);
-}
-
-/**
- * hb_face_builder_add_table:
- * @face: A face object created with hb_face_builder_create()
- * @tag: The #hb_tag_t of the table to add
- * @blob: The blob containing the table data to add
- *
- * Add table for @tag with data provided by @blob to the face. @face must
- * be created using hb_face_builder_create().
- *
- * Since: 1.9.0
- **/
-hb_bool_t
-hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
-{
- if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
- return false;
-
- if (tag == HB_MAP_VALUE_INVALID)
- return false;
-
- hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
-
- hb_blob_t* previous = data->tables.get (tag).data;
- if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), -1}))
- {
- hb_blob_destroy (blob);
- return false;
- }
-
- hb_blob_destroy (previous);
- return true;
-}
-
-/**
- * hb_face_builder_sort_tables:
- * @face: A face object created with hb_face_builder_create()
- * @tags: (array zero-terminated=1): ordered list of table tags terminated by
- * %HB_TAG_NONE
- *
- * Set the ordering of tables for serialization. Any tables not
- * specified in the tags list will be ordered after the tables in
- * tags, ordered by the default sort ordering.
- *
- * Since: 5.3.0
- **/
-void
-hb_face_builder_sort_tables (hb_face_t *face,
- const hb_tag_t *tags)
-{
- if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
- return;
-
- hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
-
- // Sort all unspecified tables after any specified tables.
- for (auto& info : data->tables.values_ref())
- info.order = (unsigned) -1;
-
- signed order = 0;
- for (const hb_tag_t* tag = tags;
- *tag;
- tag++)
- {
- face_table_info_t* info;
- if (!data->tables.has (*tag, &info)) continue;
- info->order = order++;
- }
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.h b/src/3rdparty/harfbuzz-ng/src/hb-face.h
index 38e7104af6..2e54ccf13b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-face.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-face.h
@@ -33,6 +33,7 @@
#include "hb-common.h"
#include "hb-blob.h"
+#include "hb-map.h"
#include "hb-set.h"
HB_BEGIN_DECLS
@@ -150,6 +151,11 @@ hb_face_collect_unicodes (hb_face_t *face,
hb_set_t *out);
HB_EXTERN void
+hb_face_collect_nominal_glyph_mapping (hb_face_t *face,
+ hb_map_t *mapping,
+ hb_set_t *unicodes);
+
+HB_EXTERN void
hb_face_collect_variation_selectors (hb_face_t *face,
hb_set_t *out);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-font.cc
index 0ce3e2608a..3868863105 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-font.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-font.cc
@@ -30,6 +30,7 @@
#include "hb-font.hh"
#include "hb-draw.hh"
+#include "hb-paint.hh"
#include "hb-machinery.hh"
#include "hb-ot.h"
@@ -503,23 +504,34 @@ hb_font_get_glyph_from_name_default (hb_font_t *font,
}
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)
+hb_font_draw_glyph_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)
{
}
+static void
+hb_font_paint_glyph_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph HB_UNUSED,
+ hb_paint_funcs_t *paint_funcs HB_UNUSED,
+ void *paint_data HB_UNUSED,
+ unsigned int palette HB_UNUSED,
+ hb_color_t foreground HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+}
-typedef struct hb_font_get_glyph_shape_default_adaptor_t {
+typedef struct hb_font_draw_glyph_default_adaptor_t {
hb_draw_funcs_t *draw_funcs;
void *draw_data;
float x_scale;
float y_scale;
float slant;
-} hb_font_get_glyph_shape_default_adaptor_t;
+} hb_font_draw_glyph_default_adaptor_t;
static void
hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
@@ -528,7 +540,7 @@ hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
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;
+ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
float slant = adaptor->slant;
@@ -543,7 +555,7 @@ hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
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;
+ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
float slant = adaptor->slant;
@@ -562,7 +574,7 @@ hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data
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;
+ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
float slant = adaptor->slant;
@@ -583,7 +595,7 @@ hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
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;
+ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
float slant = adaptor->slant;
@@ -602,7 +614,7 @@ 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;
+ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
adaptor->draw_funcs->emit_close_path (adaptor->draw_data, *st);
}
@@ -618,14 +630,14 @@ static const hb_draw_funcs_t _hb_draw_funcs_default = {
};
static void
-hb_font_get_glyph_shape_default (hb_font_t *font,
+hb_font_draw_glyph_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 = {
+ hb_font_draw_glyph_default_adaptor_t adaptor = {
draw_funcs,
draw_data,
font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
@@ -634,11 +646,34 @@ hb_font_get_glyph_shape_default (hb_font_t *font,
(float) font->x_scale / (float) font->parent->y_scale : 0.f
};
- font->parent->get_glyph_shape (glyph,
+ font->parent->draw_glyph (glyph,
const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default),
&adaptor);
}
+static void
+hb_font_paint_glyph_default (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs,
+ void *paint_data,
+ unsigned int palette,
+ hb_color_t foreground,
+ void *user_data)
+{
+ paint_funcs->push_transform (paint_data,
+ font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
+ font->parent->y_scale ? (font->slant - font->parent->slant) *
+ (float) font->x_scale / (float) font->parent->y_scale : 0.f,
+ 0.f,
+ font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f,
+ 0.f, 0.f);
+
+ font->parent->paint_glyph (glyph, paint_funcs, paint_data, palette, foreground);
+
+ paint_funcs->pop_transform (paint_data);
+}
+
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
{
HB_OBJECT_HEADER_STATIC,
@@ -647,7 +682,7 @@ DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
nullptr,
{
{
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
+#define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_font_##get_##name##_nil,
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
}
@@ -661,7 +696,7 @@ static const hb_font_funcs_t _hb_font_funcs_default = {
nullptr,
{
{
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default,
+#define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_font_##get_##name##_default,
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
}
@@ -739,7 +774,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
if (ffuncs->destroy)
{
-#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy->name) \
+#define HB_FONT_FUNC_IMPLEMENT(get_,name) if (ffuncs->destroy->name) \
ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name);
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
@@ -879,11 +914,11 @@ fail:
return false;
}
-#define HB_FONT_FUNC_IMPLEMENT(name) \
+#define HB_FONT_FUNC_IMPLEMENT(get_,name) \
\
void \
hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
- hb_font_get_##name##_func_t func, \
+ hb_font_##get_##name##_func_t func, \
void *user_data, \
hb_destroy_func_t destroy) \
{ \
@@ -899,7 +934,7 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
if (func) \
ffuncs->get.f.name = func; \
else \
- ffuncs->get.f.name = hb_font_get_##name##_default; \
+ ffuncs->get.f.name = hb_font_##get_##name##_default; \
\
if (ffuncs->user_data) \
ffuncs->user_data->name = user_data; \
@@ -1026,7 +1061,8 @@ hb_font_get_nominal_glyph (hb_font_t *font,
* @glyph_stride: The stride between successive glyph IDs
*
* Fetches the nominal glyph IDs for a sequence of Unicode code points. Glyph
- * IDs must be returned in a #hb_codepoint_t output parameter.
+ * IDs must be returned in a #hb_codepoint_t output parameter. Stopes at the
+ * first unsupported glyph ID.
*
* Return value: the number of code points processed
*
@@ -1308,6 +1344,9 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
*
* Fetches the glyph-name string for a glyph ID in the specified @font.
*
+ * According to the OpenType specification, glyph names are limited to 63
+ * characters and can only contain (a subset of) ASCII.
+ *
* Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
@@ -1357,13 +1396,67 @@ hb_font_get_glyph_from_name (hb_font_t *font,
* objects, with @draw_data passed to them.
*
* Since: 4.0.0
- **/
+ * Deprecated: 7.0.0: Use hb_font_draw_glyph() instead
+ */
void
hb_font_get_glyph_shape (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data)
+{
+ hb_font_draw_glyph (font, glyph, dfuncs, draw_data);
+}
+
+/**
+ * hb_font_draw_glyph:
+ * @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
+ *
+ * Draws the outline that corresponds to a glyph in the specified @font.
+ *
+ * The outline is returned by way of calls to the callbacks of the @dfuncs
+ * objects, with @draw_data passed to them.
+ *
+ * Since: 7.0.0
+ **/
+void
+hb_font_draw_glyph (hb_font_t *font,
hb_codepoint_t glyph,
hb_draw_funcs_t *dfuncs, void *draw_data)
{
- font->get_glyph_shape (glyph, dfuncs, draw_data);
+ font->draw_glyph (glyph, dfuncs, draw_data);
+}
+
+/**
+ * hb_font_paint_glyph:
+ * @font: #hb_font_t to work upon
+ * @glyph: The glyph ID
+ * @pfuncs: #hb_paint_funcs_t to paint with
+ * @paint_data: User data to pass to paint callbacks
+ * @palette_index: The index of the font's color palette to use
+ * @foreground: The foreground color, unpremultipled
+ *
+ * Paints the glyph.
+ *
+ * The painting instructions are returned by way of calls to
+ * the callbacks of the @funcs object, with @paint_data passed
+ * to them.
+ *
+ * If the font has color palettes (see hb_ot_color_has_palettes()),
+ * then @palette_index selects the palette to use. If the font only
+ * has one palette, this will be 0.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_font_paint_glyph (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *pfuncs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground)
+{
+ font->paint_glyph (glyph, pfuncs, paint_data, palette_index, foreground);
}
/* A bit higher-level, and with fallback */
@@ -1624,6 +1717,9 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
* If the glyph ID has no name in @font, a string of the form `gidDDD` is
* generated, with `DDD` being the glyph ID.
*
+ * According to the OpenType specification, glyph names are limited to 63
+ * characters and can only contain (a subset of) ASCII.
+ *
* Since: 0.9.2
**/
void
@@ -1677,8 +1773,13 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
1000, /* x_scale */
1000, /* y_scale */
- 0., /* slant */
- 0., /* slant_xy; */
+ 0.f, /* x_embolden */
+ 0.f, /* y_embolden */
+ true, /* embolden_in_place */
+ 0, /* x_strength */
+ 0, /* y_strength */
+ 0.f, /* slant */
+ 0.f, /* slant_xy; */
1.f, /* x_multf */
1.f, /* y_multf */
1<<16, /* x_mult */
@@ -1688,6 +1789,7 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
0, /* y_ppem */
0, /* ptem */
+ HB_FONT_NO_VAR_NAMED_INSTANCE, /* instance_index */
0, /* num_coords */
nullptr, /* coords */
nullptr, /* design_coords */
@@ -1715,8 +1817,10 @@ _hb_font_create (hb_face_t *face)
font->klass = hb_font_funcs_get_empty ();
font->data.init0 (font);
font->x_scale = font->y_scale = face->get_upem ();
+ font->embolden_in_place = true;
font->x_multf = font->y_multf = 1.f;
font->x_mult = font->y_mult = 1 << 16;
+ font->instance_index = HB_FONT_NO_VAR_NAMED_INSTANCE;
return font;
}
@@ -1798,6 +1902,9 @@ hb_font_create_sub_font (hb_font_t *parent)
font->x_scale = parent->x_scale;
font->y_scale = parent->y_scale;
+ font->x_embolden = parent->x_embolden;
+ font->y_embolden = parent->y_embolden;
+ font->embolden_in_place = parent->embolden_in_place;
font->slant = parent->slant;
font->x_ppem = parent->x_ppem;
font->y_ppem = parent->y_ppem;
@@ -2187,6 +2294,31 @@ hb_font_set_funcs_data (hb_font_t *font,
*
* Sets the horizontal and vertical scale of a font.
*
+ * The font scale is a number related to, but not the same as,
+ * font size. Typically the client establishes a scale factor
+ * to be used between the two. For example, 64, or 256, which
+ * would be the fractional-precision part of the font scale.
+ * This is necessary because #hb_position_t values are integer
+ * types and you need to leave room for fractional values
+ * in there.
+ *
+ * For example, to set the font size to 20, with 64
+ * levels of fractional precision you would call
+ * `hb_font_set_scale(font, 20 * 64, 20 * 64)`.
+ *
+ * In the example above, even what font size 20 means is up to
+ * you. It might be 20 pixels, or 20 points, or 20 millimeters.
+ * HarfBuzz does not care about that. You can set the point
+ * size of the font using hb_font_set_ptem(), and the pixel
+ * size using hb_font_set_ppem().
+ *
+ * The choice of scale is yours but needs to be consistent between
+ * what you set here, and what you expect out of #hb_position_t
+ * as well has draw / paint API output values.
+ *
+ * Fonts default to a scale equal to the UPEM value of their face.
+ * A font with this setting is sometimes called an "unscaled" font.
+ *
* Since: 0.9.2
**/
void
@@ -2232,7 +2364,11 @@ 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.
+ *
+ * These values are used for pixel-size-specific adjustment to
+ * shaping and draw results, though for the most part they are
+ * unused and can be left unset.
*
* Since: 0.9.2
**/
@@ -2317,6 +2453,76 @@ hb_font_get_ptem (hb_font_t *font)
}
/**
+ * hb_font_set_synthetic_bold:
+ * @font: #hb_font_t to work upon
+ * @x_embolden: the amount to embolden horizontally
+ * @y_embolden: the amount to embolden vertically
+ * @in_place: whether to embolden glyphs in-place
+ *
+ * Sets the "synthetic boldness" of a font.
+ *
+ * Positive values for @x_embolden / @y_embolden make a font
+ * bolder, negative values thinner. Typical values are in the
+ * 0.01 to 0.05 range. The default value is zero.
+ *
+ * Synthetic boldness is applied by offsetting the contour
+ * points of the glyph shape.
+ *
+ * Synthetic boldness is applied when rendering a glyph via
+ * hb_font_draw_glyph().
+ *
+ * If @in_place is `false`, then glyph advance-widths are also
+ * adjusted, otherwise they are not. The in-place mode is
+ * useful for simulating [font grading](https://fonts.google.com/knowledge/glossary/grade).
+ *
+ *
+ * Since: 7.0.0
+ **/
+void
+hb_font_set_synthetic_bold (hb_font_t *font,
+ float x_embolden,
+ float y_embolden,
+ hb_bool_t in_place)
+{
+ if (hb_object_is_immutable (font))
+ return;
+
+ if (font->x_embolden == x_embolden &&
+ font->y_embolden == y_embolden &&
+ font->embolden_in_place == (bool) in_place)
+ return;
+
+ font->serial++;
+
+ font->x_embolden = x_embolden;
+ font->y_embolden = y_embolden;
+ font->embolden_in_place = in_place;
+ font->mults_changed ();
+}
+
+/**
+ * hb_font_get_synthetic_bold:
+ * @font: #hb_font_t to work upon
+ * @x_embolden: (out): return location for horizontal value
+ * @y_embolden: (out): return location for vertical value
+ * @in_place: (out): return location for in-place value
+ *
+ * Fetches the "synthetic boldness" parameters of a font.
+ *
+ * Since: 7.0.0
+ **/
+void
+hb_font_get_synthetic_bold (hb_font_t *font,
+ float *x_embolden,
+ float *y_embolden,
+ hb_bool_t *in_place)
+{
+ if (x_embolden) *x_embolden = font->x_embolden;
+ if (y_embolden) *y_embolden = font->y_embolden;
+ if (in_place) *in_place = font->embolden_in_place;
+}
+
+/**
* hb_font_set_synthetic_slant:
* @font: #hb_font_t to work upon
* @slant: synthetic slant value.
@@ -2328,9 +2534,8 @@ hb_font_get_ptem (hb_font_t *font)
* 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 glyph shape fetched via the hb_font_draw_glyph()
+ * function 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>
@@ -2397,7 +2602,7 @@ hb_font_set_variations (hb_font_t *font,
font->serial_coords = ++font->serial;
- if (!variations_length)
+ if (!variations_length && font->instance_index == HB_FONT_NO_VAR_NAMED_INSTANCE)
{
hb_font_set_var_coords_normalized (font, nullptr, 0);
return;
@@ -2417,9 +2622,18 @@ hb_font_set_variations (hb_font_t *font,
return;
}
- /* Initialize design coords to default from fvar. */
+ /* Initialize design coords. */
for (unsigned int i = 0; i < coords_length; i++)
design_coords[i] = axes[i].get_default ();
+ if (font->instance_index != HB_FONT_NO_VAR_NAMED_INSTANCE)
+ {
+ unsigned count = coords_length;
+ /* This may fail if index is out-of-range;
+ * That's why we initialize design_coords from fvar above
+ * unconditionally. */
+ hb_ot_var_named_instance_get_design_coords (font->face, font->instance_index,
+ &count, design_coords);
+ }
for (unsigned int i = 0; i < variations_length; i++)
{
@@ -2427,13 +2641,11 @@ hb_font_set_variations (hb_font_t *font,
const auto v = variations[i].value;
for (unsigned axis_index = 0; axis_index < coords_length; axis_index++)
if (axes[axis_index].axisTag == tag)
- {
design_coords[axis_index] = v;
- normalized[axis_index] = fvar.normalize_axis_value (axis_index, v);
- }
}
font->face->table.avar->map_coords (normalized, coords_length);
+ hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized);
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
}
@@ -2484,28 +2696,40 @@ hb_font_set_var_coords_design (hb_font_t *font,
* @font: a font.
* @instance_index: named instance index.
*
- * Sets design coords of a font from a named instance index.
+ * Sets design coords of a font from a named-instance index.
*
* Since: 2.6.0
*/
void
hb_font_set_var_named_instance (hb_font_t *font,
- unsigned instance_index)
+ unsigned int instance_index)
{
if (hb_object_is_immutable (font))
return;
- font->serial_coords = ++font->serial;
+ if (font->instance_index == instance_index)
+ return;
- unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
+ font->serial_coords = ++font->serial;
- float *coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
- if (unlikely (coords_length && !coords))
- return;
+ font->instance_index = instance_index;
+ hb_font_set_variations (font, nullptr, 0);
+}
- hb_ot_var_named_instance_get_design_coords (font->face, instance_index, &coords_length, coords);
- hb_font_set_var_coords_design (font, coords, coords_length);
- hb_free (coords);
+/**
+ * hb_font_get_var_named_instance:
+ * @font: a font.
+ *
+ * Returns the currently-set named-instance index of the font.
+ *
+ * Return value: Named-instance index or %HB_FONT_NO_VAR_NAMED_INSTANCE.
+ *
+ * Since: 7.0.0
+ **/
+unsigned int
+hb_font_get_var_named_instance (hb_font_t *font)
+{
+ return font->instance_index;
}
/**
@@ -2754,3 +2978,13 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
trampoline_destroy);
}
#endif
+
+
+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 /* May be NULL. */)
+{
+ hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.h b/src/3rdparty/harfbuzz-ng/src/hb-font.h
index e2c3df4a5a..69457da577 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-font.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-font.h
@@ -34,18 +34,10 @@
#include "hb-common.h"
#include "hb-face.h"
#include "hb-draw.h"
+#include "hb-paint.h"
HB_BEGIN_DECLS
-/**
- * hb_font_t:
- *
- * Data type for holding fonts.
- *
- */
-typedef struct hb_font_t hb_font_t;
-
-
/*
* hb_font_funcs_t
*/
@@ -97,7 +89,7 @@ HB_EXTERN hb_bool_t
hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
-/* font and glyph extents */
+/* font extents */
/**
* hb_font_extents_t:
@@ -126,24 +118,6 @@ typedef struct hb_font_extents_t {
hb_position_t reserved1;
} hb_font_extents_t;
-/**
- * hb_glyph_extents_t:
- * @x_bearing: Distance from the x-origin to the left extremum of the glyph.
- * @y_bearing: Distance from the top extremum of the glyph to the y-origin.
- * @width: Distance from the left extremum of the glyph to the right extremum.
- * @height: Distance from the top extremum of the glyph to the bottom extremum.
- *
- * Glyph extent values, measured in font units.
- *
- * Note that @height is negative, in coordinate systems that grow up.
- **/
-typedef struct hb_glyph_extents_t {
- hb_position_t x_bearing;
- hb_position_t y_bearing;
- hb_position_t width;
- hb_position_t height;
-} hb_glyph_extents_t;
-
/* func types */
/**
@@ -523,13 +497,53 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* Since: 4.0.0
- *
+ * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead
**/
typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data);
+/**
+ * hb_font_draw_glyph_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @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: 7.0.0
+ *
+ **/
+typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data);
+
+/**
+ * hb_font_paint_glyph_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @paint_funcs: The paint functions to use
+ * @paint_data: The data accompanying the paint functions
+ * @palette_index: The color palette to use
+ * @foreground: The foreground color
+ * @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: 7.0.0
+ */
+typedef void (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground,
+ void *user_data);
/* func setters */
@@ -796,15 +810,50 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
* @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.
+ * Sets the implementation function for #hb_font_get_glyph_shape_func_t,
+ * which is the same as #hb_font_draw_glyph_func_t.
*
* Since: 4.0.0
+ * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead
**/
HB_EXTERN void
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_shape_func_t func,
void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_font_funcs_set_draw_glyph_func:
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets the implementation function for #hb_font_draw_glyph_func_t,
+ * which is the same as #hb_font_get_glyph_shape_func_t.
+ *
+ * Since: 7.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_draw_glyph_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_paint_glyph_func:
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is no longer needed
+ *
+ * Sets the implementation function for #hb_font_paint_glyph_func_t.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_paint_glyph_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
/* func dispatch */
HB_EXTERN hb_bool_t
@@ -890,6 +939,17 @@ hb_font_get_glyph_shape (hb_font_t *font,
hb_codepoint_t glyph,
hb_draw_funcs_t *dfuncs, void *draw_data);
+HB_EXTERN void
+hb_font_draw_glyph (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data);
+
+HB_EXTERN void
+hb_font_paint_glyph (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *pfuncs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground);
/* high-level funcs, with fallback */
@@ -1070,6 +1130,16 @@ HB_EXTERN float
hb_font_get_ptem (hb_font_t *font);
HB_EXTERN void
+hb_font_set_synthetic_bold (hb_font_t *font,
+ float x_embolden, float y_embolden,
+ hb_bool_t in_place);
+
+HB_EXTERN void
+hb_font_get_synthetic_bold (hb_font_t *font,
+ float *x_embolden, float *y_embolden,
+ hb_bool_t *in_place);
+
+HB_EXTERN void
hb_font_set_synthetic_slant (hb_font_t *font, float slant);
HB_EXTERN float
@@ -1098,10 +1168,23 @@ HB_EXTERN const int *
hb_font_get_var_coords_normalized (hb_font_t *font,
unsigned int *length);
+/**
+ * HB_FONT_NO_VAR_NAMED_INSTANCE:
+ *
+ * Constant signifying that a font does not have any
+ * named-instance index set. This is the default of
+ * a font.
+ *
+ * Since: 7.0.0
+ */
+#define HB_FONT_NO_VAR_NAMED_INSTANCE 0xFFFFFFFF
+
HB_EXTERN void
hb_font_set_var_named_instance (hb_font_t *font,
- unsigned instance_index);
+ unsigned int instance_index);
+HB_EXTERN unsigned int
+hb_font_get_var_named_instance (hb_font_t *font);
HB_END_DECLS
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.hh b/src/3rdparty/harfbuzz-ng/src/hb-font.hh
index 6942d99c70..f503575c34 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-font.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-font.hh
@@ -40,24 +40,25 @@
*/
#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
- HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
- HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
- HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
- HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \
- HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
- HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
- HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
- HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
- HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
- HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
- HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
- HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
- HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \
- HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
- 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) \
+ HB_FONT_FUNC_IMPLEMENT (get_,font_h_extents) \
+ HB_FONT_FUNC_IMPLEMENT (get_,font_v_extents) \
+ HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyph) \
+ HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyphs) \
+ HB_FONT_FUNC_IMPLEMENT (get_,variation_glyph) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advance) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advance) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advances) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advances) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origin) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origin) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_kerning) \
+ HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_kerning)) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_extents) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \
+ HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \
+ HB_FONT_FUNC_IMPLEMENT (,draw_glyph) \
+ HB_FONT_FUNC_IMPLEMENT (,paint_glyph) \
/* ^--- Add new callbacks here */
struct hb_font_funcs_t
@@ -65,13 +66,13 @@ struct hb_font_funcs_t
hb_object_header_t header;
struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
+#define HB_FONT_FUNC_IMPLEMENT(get_,name) void *name;
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
} *user_data;
struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+#define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_destroy_func_t name;
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
} *destroy;
@@ -79,12 +80,12 @@ struct hb_font_funcs_t
/* Don't access these directly. Call font->get_*() instead. */
union get_t {
struct get_funcs_t {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
+#define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_font_##get_##name##_func_t name;
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
} f;
void (*array[0
-#define HB_FONT_FUNC_IMPLEMENT(name) +1
+#define HB_FONT_FUNC_IMPLEMENT(get_,name) +1
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
]) ();
@@ -112,8 +113,16 @@ struct hb_font_t
int32_t x_scale;
int32_t y_scale;
+
+ float x_embolden;
+ float y_embolden;
+ bool embolden_in_place;
+ int32_t x_strength; /* x_embolden, in scaled units. */
+ int32_t y_strength; /* y_embolden, in scaled units. */
+
float slant;
float slant_xy;
+
float x_multf;
float y_multf;
int64_t x_mult;
@@ -125,6 +134,7 @@ struct hb_font_t
float ptem;
/* Font variation coordinates. */
+ unsigned int instance_index;
unsigned int num_coords;
int *coords;
float *design_coords;
@@ -179,6 +189,42 @@ struct hb_font_t
*y = parent_scale_y_position (*y);
}
+ void scale_glyph_extents (hb_glyph_extents_t *extents)
+ {
+ float x1 = em_fscale_x (extents->x_bearing);
+ float y1 = em_fscale_y (extents->y_bearing);
+ float x2 = em_fscale_x (extents->x_bearing + extents->width);
+ float y2 = em_fscale_y (extents->y_bearing + extents->height);
+
+ /* Apply slant. */
+ if (slant_xy)
+ {
+ x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
+ x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
+ }
+
+ extents->x_bearing = floorf (x1);
+ extents->y_bearing = floorf (y1);
+ extents->width = ceilf (x2) - extents->x_bearing;
+ extents->height = ceilf (y2) - extents->y_bearing;
+
+ if (x_strength || y_strength)
+ {
+ /* Y */
+ int y_shift = y_strength;
+ if (y_scale < 0) y_shift = -y_shift;
+ extents->y_bearing += y_shift;
+ extents->height -= y_shift;
+
+ /* X */
+ int x_shift = x_strength;
+ if (x_scale < 0) x_shift = -x_shift;
+ if (embolden_in_place)
+ extents->x_bearing -= x_shift / 2;
+ extents->width += x_shift;
+ }
+ }
+
/* Public getters */
@@ -186,7 +232,7 @@ struct hb_font_t
HB_INTERNAL bool has_func_set (unsigned int i);
/* has_* ... */
-#define HB_FONT_FUNC_IMPLEMENT(name) \
+#define HB_FONT_FUNC_IMPLEMENT(get_,name) \
bool \
has_##name##_func () \
{ \
@@ -380,15 +426,26 @@ struct hb_font_t
!klass->user_data ? nullptr : klass->user_data->glyph_from_name);
}
- void get_glyph_shape (hb_codepoint_t glyph,
- hb_draw_funcs_t *draw_funcs, void *draw_data)
+ void draw_glyph (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 ? nullptr : klass->user_data->glyph_shape);
+ klass->get.f.draw_glyph (this, user_data,
+ glyph,
+ draw_funcs, draw_data,
+ !klass->user_data ? nullptr : klass->user_data->draw_glyph);
}
+ void paint_glyph (hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette,
+ hb_color_t foreground)
+ {
+ klass->get.f.paint_glyph (this, user_data,
+ glyph,
+ paint_funcs, paint_data,
+ palette, foreground,
+ !klass->user_data ? nullptr : klass->user_data->paint_glyph);
+ }
/* A bit higher-level, and with fallback */
@@ -632,12 +689,17 @@ struct hb_font_t
void mults_changed ()
{
float upem = face->get_upem ();
+
x_multf = x_scale / upem;
y_multf = y_scale / upem;
bool x_neg = x_scale < 0;
x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem;
bool y_neg = y_scale < 0;
y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
+
+ x_strength = fabsf (roundf (x_scale * x_embolden));
+ y_strength = fabsf (roundf (y_scale * y_embolden));
+
slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
data.fini ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh b/src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh
new file mode 100644
index 0000000000..b3457933c0
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh
@@ -0,0 +1,567 @@
+/*
+ * 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.
+ */
+
+#ifndef HB_FT_COLR_HH
+#define HB_FT_COLR_HH
+
+#include "hb.hh"
+
+#include "hb-paint-extents.hh"
+
+#include FT_COLOR_H
+
+
+static hb_paint_composite_mode_t
+_hb_ft_paint_composite_mode (FT_Composite_Mode mode)
+{
+ switch (mode)
+ {
+ case FT_COLR_COMPOSITE_CLEAR: return HB_PAINT_COMPOSITE_MODE_CLEAR;
+ case FT_COLR_COMPOSITE_SRC: return HB_PAINT_COMPOSITE_MODE_SRC;
+ case FT_COLR_COMPOSITE_DEST: return HB_PAINT_COMPOSITE_MODE_DEST;
+ case FT_COLR_COMPOSITE_SRC_OVER: return HB_PAINT_COMPOSITE_MODE_SRC_OVER;
+ case FT_COLR_COMPOSITE_DEST_OVER: return HB_PAINT_COMPOSITE_MODE_DEST_OVER;
+ case FT_COLR_COMPOSITE_SRC_IN: return HB_PAINT_COMPOSITE_MODE_SRC_IN;
+ case FT_COLR_COMPOSITE_DEST_IN: return HB_PAINT_COMPOSITE_MODE_DEST_IN;
+ case FT_COLR_COMPOSITE_SRC_OUT: return HB_PAINT_COMPOSITE_MODE_SRC_OUT;
+ case FT_COLR_COMPOSITE_DEST_OUT: return HB_PAINT_COMPOSITE_MODE_DEST_OUT;
+ case FT_COLR_COMPOSITE_SRC_ATOP: return HB_PAINT_COMPOSITE_MODE_SRC_ATOP;
+ case FT_COLR_COMPOSITE_DEST_ATOP: return HB_PAINT_COMPOSITE_MODE_DEST_ATOP;
+ case FT_COLR_COMPOSITE_XOR: return HB_PAINT_COMPOSITE_MODE_XOR;
+ case FT_COLR_COMPOSITE_PLUS: return HB_PAINT_COMPOSITE_MODE_PLUS;
+ case FT_COLR_COMPOSITE_SCREEN: return HB_PAINT_COMPOSITE_MODE_SCREEN;
+ case FT_COLR_COMPOSITE_OVERLAY: return HB_PAINT_COMPOSITE_MODE_OVERLAY;
+ case FT_COLR_COMPOSITE_DARKEN: return HB_PAINT_COMPOSITE_MODE_DARKEN;
+ case FT_COLR_COMPOSITE_LIGHTEN: return HB_PAINT_COMPOSITE_MODE_LIGHTEN;
+ case FT_COLR_COMPOSITE_COLOR_DODGE: return HB_PAINT_COMPOSITE_MODE_COLOR_DODGE;
+ case FT_COLR_COMPOSITE_COLOR_BURN: return HB_PAINT_COMPOSITE_MODE_COLOR_BURN;
+ case FT_COLR_COMPOSITE_HARD_LIGHT: return HB_PAINT_COMPOSITE_MODE_HARD_LIGHT;
+ case FT_COLR_COMPOSITE_SOFT_LIGHT: return HB_PAINT_COMPOSITE_MODE_SOFT_LIGHT;
+ case FT_COLR_COMPOSITE_DIFFERENCE: return HB_PAINT_COMPOSITE_MODE_DIFFERENCE;
+ case FT_COLR_COMPOSITE_EXCLUSION: return HB_PAINT_COMPOSITE_MODE_EXCLUSION;
+ case FT_COLR_COMPOSITE_MULTIPLY: return HB_PAINT_COMPOSITE_MODE_MULTIPLY;
+ case FT_COLR_COMPOSITE_HSL_HUE: return HB_PAINT_COMPOSITE_MODE_HSL_HUE;
+ case FT_COLR_COMPOSITE_HSL_SATURATION: return HB_PAINT_COMPOSITE_MODE_HSL_SATURATION;
+ case FT_COLR_COMPOSITE_HSL_COLOR: return HB_PAINT_COMPOSITE_MODE_HSL_COLOR;
+ case FT_COLR_COMPOSITE_HSL_LUMINOSITY: return HB_PAINT_COMPOSITE_MODE_HSL_LUMINOSITY;
+
+ case FT_COLR_COMPOSITE_MAX: HB_FALLTHROUGH;
+ default: return HB_PAINT_COMPOSITE_MODE_CLEAR;
+ }
+}
+
+typedef struct hb_ft_paint_context_t hb_ft_paint_context_t;
+
+static void
+_hb_ft_paint (hb_ft_paint_context_t *c,
+ FT_OpaquePaint opaque_paint);
+
+struct hb_ft_paint_context_t
+{
+ hb_ft_paint_context_t (const hb_ft_font_t *ft_font,
+ hb_font_t *font,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ FT_Color *palette,
+ unsigned palette_index,
+ hb_color_t foreground) :
+ ft_font (ft_font), font(font),
+ funcs (paint_funcs), data (paint_data),
+ palette (palette), palette_index (palette_index), foreground (foreground) {}
+
+ void recurse (FT_OpaquePaint paint)
+ {
+ if (unlikely (depth_left <= 0 || edge_count <= 0)) return;
+ depth_left--;
+ edge_count--;
+ _hb_ft_paint (this, paint);
+ depth_left++;
+ }
+
+ const hb_ft_font_t *ft_font;
+ hb_font_t *font;
+ hb_paint_funcs_t *funcs;
+ void *data;
+ FT_Color *palette;
+ unsigned palette_index;
+ hb_color_t foreground;
+ int depth_left = HB_MAX_NESTING_LEVEL;
+ int edge_count = HB_COLRV1_MAX_EDGE_COUNT;
+};
+
+static unsigned
+_hb_ft_color_line_get_color_stops (hb_color_line_t *color_line,
+ void *color_line_data,
+ unsigned int start,
+ unsigned int *count,
+ hb_color_stop_t *color_stops,
+ void *user_data)
+{
+ FT_ColorLine *cl = (FT_ColorLine *) color_line_data;
+ hb_ft_paint_context_t *c = (hb_ft_paint_context_t *) user_data;
+
+ if (count)
+ {
+ FT_ColorStop stop;
+ unsigned wrote = 0;
+ FT_ColorStopIterator iter = cl->color_stop_iterator;
+
+ if (start >= cl->color_stop_iterator.num_color_stops)
+ {
+ *count = 0;
+ return cl->color_stop_iterator.num_color_stops;
+ }
+
+ while (cl->color_stop_iterator.current_color_stop < start)
+ FT_Get_Colorline_Stops(c->ft_font->ft_face,
+ &stop,
+ &cl->color_stop_iterator);
+
+ while (count && *count &&
+ FT_Get_Colorline_Stops(c->ft_font->ft_face,
+ &stop,
+ &cl->color_stop_iterator))
+ {
+ // https://github.com/harfbuzz/harfbuzz/issues/4013
+ if (sizeof stop.stop_offset == 2)
+ color_stops->offset = stop.stop_offset / 16384.f;
+ else
+ color_stops->offset = stop.stop_offset / 65536.f;
+
+ color_stops->is_foreground = stop.color.palette_index == 0xFFFF;
+ if (color_stops->is_foreground)
+ color_stops->color = HB_COLOR (hb_color_get_blue (c->foreground),
+ hb_color_get_green (c->foreground),
+ hb_color_get_red (c->foreground),
+ (hb_color_get_alpha (c->foreground) * stop.color.alpha) >> 14);
+ else
+ {
+ hb_color_t color;
+ if (c->funcs->custom_palette_color (c->data, stop.color.palette_index, &color))
+ {
+ color_stops->color = HB_COLOR (hb_color_get_blue (color),
+ hb_color_get_green (color),
+ hb_color_get_red (color),
+ (hb_color_get_alpha (color) * stop.color.alpha) >> 14);
+ }
+ else
+ {
+ FT_Color ft_color = c->palette[stop.color.palette_index];
+ color_stops->color = HB_COLOR (ft_color.blue,
+ ft_color.green,
+ ft_color.red,
+ (ft_color.alpha * stop.color.alpha) >> 14);
+ }
+ }
+
+ color_stops++;
+ wrote++;
+ }
+
+ *count = wrote;
+
+ // reset the iterator for next time
+ cl->color_stop_iterator = iter;
+ }
+
+ return cl->color_stop_iterator.num_color_stops;
+}
+
+static hb_paint_extend_t
+_hb_ft_color_line_get_extend (hb_color_line_t *color_line,
+ void *color_line_data,
+ void *user_data)
+{
+ FT_ColorLine *c = (FT_ColorLine *) color_line_data;
+ switch (c->extend)
+ {
+ default:
+ case FT_COLR_PAINT_EXTEND_PAD: return HB_PAINT_EXTEND_PAD;
+ case FT_COLR_PAINT_EXTEND_REPEAT: return HB_PAINT_EXTEND_REPEAT;
+ case FT_COLR_PAINT_EXTEND_REFLECT: return HB_PAINT_EXTEND_REFLECT;
+ }
+}
+
+void
+_hb_ft_paint (hb_ft_paint_context_t *c,
+ FT_OpaquePaint opaque_paint)
+{
+ FT_Face ft_face = c->ft_font->ft_face;
+ FT_COLR_Paint paint;
+ if (!FT_Get_Paint (ft_face, opaque_paint, &paint))
+ return;
+
+ switch (paint.format)
+ {
+ case FT_COLR_PAINTFORMAT_COLR_LAYERS:
+ {
+ FT_OpaquePaint other_paint = {0};
+ while (FT_Get_Paint_Layers (ft_face,
+ &paint.u.colr_layers.layer_iterator,
+ &other_paint))
+ {
+ c->funcs->push_group (c->data);
+ c->recurse (other_paint);
+ c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
+ }
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_SOLID:
+ {
+ bool is_foreground = paint.u.solid.color.palette_index == 0xFFFF;
+ hb_color_t color;
+ if (is_foreground)
+ color = HB_COLOR (hb_color_get_blue (c->foreground),
+ hb_color_get_green (c->foreground),
+ hb_color_get_red (c->foreground),
+ (hb_color_get_alpha (c->foreground) * paint.u.solid.color.alpha) >> 14);
+ else
+ {
+ if (c->funcs->custom_palette_color (c->data, paint.u.solid.color.palette_index, &color))
+ {
+ color = HB_COLOR (hb_color_get_blue (color),
+ hb_color_get_green (color),
+ hb_color_get_red (color),
+ (hb_color_get_alpha (color) * paint.u.solid.color.alpha) >> 14);
+ }
+ else
+ {
+ FT_Color ft_color = c->palette[paint.u.solid.color.palette_index];
+ color = HB_COLOR (ft_color.blue,
+ ft_color.green,
+ ft_color.red,
+ (ft_color.alpha * paint.u.solid.color.alpha) >> 14);
+ }
+ }
+ c->funcs->color (c->data, is_foreground, color);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
+ {
+ hb_color_line_t cl = {
+ &paint.u.linear_gradient.colorline,
+ _hb_ft_color_line_get_color_stops, c,
+ _hb_ft_color_line_get_extend, nullptr
+ };
+
+ c->funcs->linear_gradient (c->data, &cl,
+ paint.u.linear_gradient.p0.x / 65536.f,
+ paint.u.linear_gradient.p0.y / 65536.f,
+ paint.u.linear_gradient.p1.x / 65536.f,
+ paint.u.linear_gradient.p1.y / 65536.f,
+ paint.u.linear_gradient.p2.x / 65536.f,
+ paint.u.linear_gradient.p2.y / 65536.f);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
+ {
+ hb_color_line_t cl = {
+ &paint.u.linear_gradient.colorline,
+ _hb_ft_color_line_get_color_stops, c,
+ _hb_ft_color_line_get_extend, nullptr
+ };
+
+ c->funcs->radial_gradient (c->data, &cl,
+ paint.u.radial_gradient.c0.x / 65536.f,
+ paint.u.radial_gradient.c0.y / 65536.f,
+ paint.u.radial_gradient.r0 / 65536.f,
+ paint.u.radial_gradient.c1.x / 65536.f,
+ paint.u.radial_gradient.c1.y / 65536.f,
+ paint.u.radial_gradient.r1 / 65536.f);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT:
+ {
+ hb_color_line_t cl = {
+ &paint.u.linear_gradient.colorline,
+ _hb_ft_color_line_get_color_stops, c,
+ _hb_ft_color_line_get_extend, nullptr
+ };
+
+ c->funcs->sweep_gradient (c->data, &cl,
+ paint.u.sweep_gradient.center.x / 65536.f,
+ paint.u.sweep_gradient.center.y / 65536.f,
+ (paint.u.sweep_gradient.start_angle / 65536.f + 1) * (float) M_PI,
+ (paint.u.sweep_gradient.end_angle / 65536.f + 1) * (float) M_PI);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_GLYPH:
+ {
+ c->funcs->push_inverse_root_transform (c->data, c->font);
+ c->ft_font->lock.unlock ();
+ c->funcs->push_clip_glyph (c->data, paint.u.glyph.glyphID, c->font);
+ c->ft_font->lock.lock ();
+ c->funcs->push_root_transform (c->data, c->font);
+ c->recurse (paint.u.glyph.paint);
+ c->funcs->pop_transform (c->data);
+ c->funcs->pop_clip (c->data);
+ c->funcs->pop_transform (c->data);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_COLR_GLYPH:
+ {
+ FT_OpaquePaint other_paint = {0};
+ if (FT_Get_Color_Glyph_Paint (ft_face, paint.u.colr_glyph.glyphID,
+ FT_COLOR_NO_ROOT_TRANSFORM,
+ &other_paint))
+ {
+ bool has_clip_box;
+ FT_ClipBox clip_box;
+ has_clip_box = FT_Get_Color_Glyph_ClipBox (ft_face, paint.u.colr_glyph.glyphID, &clip_box);
+
+ if (has_clip_box)
+ {
+ /* The FreeType ClipBox is in scaled coordinates, whereas we need
+ * unscaled clipbox here. Oh well...
+ */
+
+ float upem = c->font->face->get_upem ();
+ float xscale = upem / (c->font->x_scale ? c->font->x_scale : upem);
+ float yscale = upem / (c->font->y_scale ? c->font->y_scale : upem);
+
+ c->funcs->push_clip_rectangle (c->data,
+ clip_box.bottom_left.x * xscale,
+ clip_box.bottom_left.y * yscale,
+ clip_box.top_right.x * xscale,
+ clip_box.top_right.y * yscale);
+ }
+
+ c->recurse (other_paint);
+
+ if (has_clip_box)
+ c->funcs->pop_clip (c->data);
+ }
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_TRANSFORM:
+ {
+ c->funcs->push_transform (c->data,
+ paint.u.transform.affine.xx / 65536.f,
+ paint.u.transform.affine.yx / 65536.f,
+ paint.u.transform.affine.xy / 65536.f,
+ paint.u.transform.affine.yy / 65536.f,
+ paint.u.transform.affine.dx / 65536.f,
+ paint.u.transform.affine.dy / 65536.f);
+ c->recurse (paint.u.transform.paint);
+ c->funcs->pop_transform (c->data);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_TRANSLATE:
+ {
+ float dx = paint.u.translate.dx / 65536.f;
+ float dy = paint.u.translate.dy / 65536.f;
+
+ bool p1 = c->funcs->push_translate (c->data, dx, dy);
+ c->recurse (paint.u.translate.paint);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_SCALE:
+ {
+ float dx = paint.u.scale.center_x / 65536.f;
+ float dy = paint.u.scale.center_y / 65536.f;
+ float sx = paint.u.scale.scale_x / 65536.f;
+ float sy = paint.u.scale.scale_y / 65536.f;
+
+ bool p1 = c->funcs->push_translate (c->data, +dx, +dy);
+ bool p2 = c->funcs->push_scale (c->data, sx, sy);
+ bool p3 = c->funcs->push_translate (c->data, -dx, -dy);
+ c->recurse (paint.u.scale.paint);
+ if (p3) c->funcs->pop_transform (c->data);
+ if (p2) c->funcs->pop_transform (c->data);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_ROTATE:
+ {
+ float dx = paint.u.rotate.center_x / 65536.f;
+ float dy = paint.u.rotate.center_y / 65536.f;
+ float a = paint.u.rotate.angle / 65536.f;
+
+ bool p1 = c->funcs->push_translate (c->data, +dx, +dy);
+ bool p2 = c->funcs->push_rotate (c->data, a);
+ bool p3 = c->funcs->push_translate (c->data, -dx, -dy);
+ c->recurse (paint.u.rotate.paint);
+ if (p3) c->funcs->pop_transform (c->data);
+ if (p2) c->funcs->pop_transform (c->data);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_SKEW:
+ {
+ float dx = paint.u.skew.center_x / 65536.f;
+ float dy = paint.u.skew.center_y / 65536.f;
+ float sx = paint.u.skew.x_skew_angle / 65536.f;
+ float sy = paint.u.skew.y_skew_angle / 65536.f;
+
+ bool p1 = c->funcs->push_translate (c->data, +dx, +dy);
+ bool p2 = c->funcs->push_skew (c->data, sx, sy);
+ bool p3 = c->funcs->push_translate (c->data, -dx, -dy);
+ c->recurse (paint.u.skew.paint);
+ if (p3) c->funcs->pop_transform (c->data);
+ if (p2) c->funcs->pop_transform (c->data);
+ if (p1) c->funcs->pop_transform (c->data);
+ }
+ break;
+ case FT_COLR_PAINTFORMAT_COMPOSITE:
+ {
+ c->recurse (paint.u.composite.backdrop_paint);
+ c->funcs->push_group (c->data);
+ c->recurse (paint.u.composite.source_paint);
+ c->funcs->pop_group (c->data, _hb_ft_paint_composite_mode (paint.u.composite.composite_mode));
+ }
+ break;
+
+ case FT_COLR_PAINT_FORMAT_MAX: break;
+ default: HB_FALLTHROUGH;
+ case FT_COLR_PAINTFORMAT_UNSUPPORTED: break;
+ }
+}
+
+
+static bool
+hb_ft_paint_glyph_colr (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t gid,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground,
+ void *user_data)
+{
+ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ FT_Face ft_face = ft_font->ft_face;
+
+ /* Face is locked. */
+
+ FT_Error error;
+ FT_Color* palette;
+ FT_LayerIterator iterator;
+
+ FT_Bool have_layers;
+ FT_UInt layer_glyph_index;
+ FT_UInt layer_color_index;
+
+ error = FT_Palette_Select(ft_face, palette_index, &palette);
+ if (error)
+ palette = NULL;
+
+ /* COLRv1 */
+ FT_OpaquePaint paint = {0};
+ if (FT_Get_Color_Glyph_Paint (ft_face, gid,
+ FT_COLOR_NO_ROOT_TRANSFORM,
+ &paint))
+ {
+ hb_ft_paint_context_t c (ft_font, font,
+ paint_funcs, paint_data,
+ palette, palette_index, foreground);
+
+ bool is_bounded = true;
+ FT_ClipBox clip_box;
+ if (FT_Get_Color_Glyph_ClipBox (ft_face, gid, &clip_box))
+ {
+ c.funcs->push_clip_rectangle (c.data,
+ clip_box.bottom_left.x +
+ roundf (hb_min (font->slant_xy * clip_box.bottom_left.y,
+ font->slant_xy * clip_box.top_left.y)),
+ clip_box.bottom_left.y,
+ clip_box.top_right.x +
+ roundf (hb_max (font->slant_xy * clip_box.bottom_right.y,
+ font->slant_xy * clip_box.top_right.y)),
+ clip_box.top_right.y);
+ }
+ else
+ {
+
+ auto *extents_funcs = hb_paint_extents_get_funcs ();
+ hb_paint_extents_context_t extents_data;
+ hb_ft_paint_context_t ce (ft_font, font,
+ extents_funcs, &extents_data,
+ palette, palette_index, foreground);
+ ce.funcs->push_root_transform (ce.data, font);
+ ce.recurse (paint);
+ ce.funcs->pop_transform (ce.data);
+ hb_extents_t extents = extents_data.get_extents ();
+ is_bounded = extents_data.is_bounded ();
+
+ c.funcs->push_clip_rectangle (c.data,
+ extents.xmin,
+ extents.ymin,
+ extents.xmax,
+ extents.ymax);
+ }
+
+ c.funcs->push_root_transform (c.data, font);
+
+ if (is_bounded)
+ c.recurse (paint);
+
+ c.funcs->pop_transform (c.data);
+ c.funcs->pop_clip (c.data);
+
+ return true;
+ }
+
+ /* COLRv0 */
+ iterator.p = NULL;
+ have_layers = FT_Get_Color_Glyph_Layer(ft_face,
+ gid,
+ &layer_glyph_index,
+ &layer_color_index,
+ &iterator);
+
+ if (palette && have_layers)
+ {
+ do
+ {
+ hb_bool_t is_foreground = true;
+ hb_color_t color = foreground;
+
+ if ( layer_color_index != 0xFFFF )
+ {
+ FT_Color layer_color = palette[layer_color_index];
+ color = HB_COLOR (layer_color.blue,
+ layer_color.green,
+ layer_color.red,
+ layer_color.alpha);
+ is_foreground = false;
+ }
+
+ ft_font->lock.unlock ();
+ paint_funcs->push_clip_glyph (paint_data, layer_glyph_index, font);
+ ft_font->lock.lock ();
+ paint_funcs->color (paint_data, is_foreground, color);
+ paint_funcs->pop_clip (paint_data);
+
+ } while (FT_Get_Color_Glyph_Layer(ft_face,
+ gid,
+ &layer_glyph_index,
+ &layer_color_index,
+ &iterator));
+ return true;
+ }
+
+ return false;
+}
+
+
+#endif /* HB_FT_COLR_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
index 3892dedc13..4bc10e0620 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
@@ -33,17 +33,22 @@
#include "hb-ft.h"
+#include "hb-cache.hh"
#include "hb-draw.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
-#include "hb-cache.hh"
#include "hb-ot-os2-table.hh"
#include "hb-ot-shaper-arabic-pua.hh"
+#include "hb-paint.hh"
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
#include FT_OUTLINE_H
#include FT_TRUETYPE_TABLES_H
+#include FT_SYNTHESIS_H
+#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
+#include FT_COLOR_H
+#endif
/**
@@ -80,7 +85,7 @@
*/
-using hb_ft_advance_cache_t = hb_cache_t<16, 24, 8, false>;
+using hb_ft_advance_cache_t = hb_cache_t<16, 8, 8, false>;
struct hb_ft_font_t
{
@@ -125,8 +130,6 @@ _hb_ft_font_destroy (void *data)
{
hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
- ft_font->advance_cache.fini ();
-
if (ft_font->unref)
_hb_ft_face_destroy (ft_font->ft_face);
@@ -157,9 +160,9 @@ static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face)
{
#ifdef HAVE_FT_GET_TRANSFORM
/* Bitmap font, eg. bitmap color emoji. */
- /* TODO Pick largest size? */
- int x_scale = ft_face->available_sizes[0].x_ppem;
- int y_scale = ft_face->available_sizes[0].y_ppem;
+ /* Pick largest size? */
+ int x_scale = ft_face->available_sizes[ft_face->num_fixed_sizes - 1].x_ppem;
+ int y_scale = ft_face->available_sizes[ft_face->num_fixed_sizes - 1].y_ppem;
FT_Set_Char_Size (ft_face,
x_scale, y_scale,
0, 0);
@@ -224,6 +227,9 @@ _hb_ft_hb_font_check_changed (hb_font_t *font,
* For more information, see
* https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
*
+ * This function works with #hb_font_t objects created by
+ * hb_ft_font_create() or hb_ft_font_create_referenced().
+ *
* Since: 1.0.5
**/
void
@@ -249,7 +255,10 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
* For more information, see
* https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
*
- * Return value: FT_Load_Glyph flags found
+ * This function works with #hb_font_t objects created by
+ * hb_ft_font_create() or hb_ft_font_create_referenced().
+ *
+ * Return value: FT_Load_Glyph flags found, or 0
*
* Since: 1.0.5
**/
@@ -271,6 +280,9 @@ hb_ft_font_get_load_flags (hb_font_t *font)
* Fetches the FT_Face associated with the specified #hb_font_t
* font object.
*
+ * This function works with #hb_font_t objects created by
+ * hb_ft_font_create() or hb_ft_font_create_referenced().
+ *
* Return value: (nullable): the FT_Face found or `NULL`
*
* Since: 0.9.2
@@ -290,8 +302,13 @@ hb_ft_font_get_face (hb_font_t *font)
* hb_ft_font_lock_face: (skip)
* @font: #hb_font_t to work upon
*
- * Gets the FT_Face associated with @font, This face will be kept around until
- * you call hb_ft_font_unlock_face().
+ * Gets the FT_Face associated with @font.
+ *
+ * This face will be kept around and access to the FT_Face object
+ * from other HarfBuzz API wil be blocked until you call hb_ft_font_unlock_face().
+ *
+ * This function works with #hb_font_t objects created by
+ * hb_ft_font_create() or hb_ft_font_create_referenced().
*
* Return value: (nullable) (transfer none): the FT_Face associated with @font or `NULL`
* Since: 2.6.5
@@ -431,6 +448,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ hb_position_t *orig_first_advance = first_advance;
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
int load_flags = ft_font->load_flags;
@@ -441,6 +459,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
FT_Matrix matrix;
FT_Get_Transform (ft_face, &matrix, nullptr);
x_mult = sqrtf ((float)matrix.xx * matrix.xx + (float)matrix.xy * matrix.xy) / 65536.f;
+ x_mult *= font->x_scale < 0 ? -1 : +1;
}
else
#endif
@@ -459,13 +478,29 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
else
{
FT_Get_Advance (ft_face, glyph, load_flags, &v);
+ /* Work around bug that FreeType seems to return negative advance
+ * for variable-set fonts if x_scale is negative! */
+ v = abs (v);
+ v = (int) (v * x_mult + (1<<9)) >> 10;
ft_font->advance_cache.set (glyph, v);
}
- *first_advance = (int) (v * x_mult + (1<<9)) >> 10;
+ *first_advance = v;
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
+
+ if (font->x_strength && !font->embolden_in_place)
+ {
+ /* Emboldening. */
+ hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength;
+ first_advance = orig_first_advance;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance += *first_advance ? x_strength : 0;
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
}
#ifndef HB_NO_VERTICAL
@@ -485,6 +520,7 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
FT_Matrix matrix;
FT_Get_Transform (ft_font->ft_face, &matrix, nullptr);
y_mult = sqrtf ((float)matrix.yx * matrix.yx + (float)matrix.yy * matrix.yy) / 65536.f;
+ y_mult *= font->y_scale < 0 ? -1 : +1;
}
else
#endif
@@ -500,7 +536,8 @@ 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;
+ hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
+ return ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength);
}
#endif
@@ -523,7 +560,9 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
FT_Matrix matrix;
FT_Get_Transform (ft_face, &matrix, nullptr);
x_mult = sqrtf ((float)matrix.xx * matrix.xx + (float)matrix.xy * matrix.xy) / 65536.f;
+ x_mult *= font->x_scale < 0 ? -1 : +1;
y_mult = sqrtf ((float)matrix.yx * matrix.yx + (float)matrix.yy * matrix.yy) / 65536.f;
+ y_mult *= font->y_scale < 0 ? -1 : +1;
}
else
#endif
@@ -578,13 +617,16 @@ hb_ft_get_glyph_extents (hb_font_t *font,
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
float x_mult, y_mult;
+ float slant_xy = font->slant_xy;
#ifdef HAVE_FT_GET_TRANSFORM
if (ft_font->transform)
{
FT_Matrix matrix;
FT_Get_Transform (ft_face, &matrix, nullptr);
x_mult = sqrtf ((float)matrix.xx * matrix.xx + (float)matrix.xy * matrix.xy) / 65536.f;
+ x_mult *= font->x_scale < 0 ? -1 : +1;
y_mult = sqrtf ((float)matrix.yx * matrix.yx + (float)matrix.yy * matrix.yy) / 65536.f;
+ y_mult *= font->y_scale < 0 ? -1 : +1;
}
else
#endif
@@ -596,10 +638,40 @@ hb_ft_get_glyph_extents (hb_font_t *font,
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
- extents->x_bearing = (hb_position_t) (x_mult * ft_face->glyph->metrics.horiBearingX);
- extents->y_bearing = (hb_position_t) (y_mult * ft_face->glyph->metrics.horiBearingY);
- extents->width = (hb_position_t) (x_mult * ft_face->glyph->metrics.width);
- extents->height = (hb_position_t) (y_mult * -ft_face->glyph->metrics.height);
+ /* Copied from hb_font_t::scale_glyph_extents. */
+
+ float x1 = x_mult * ft_face->glyph->metrics.horiBearingX;
+ float y1 = y_mult * ft_face->glyph->metrics.horiBearingY;
+ float x2 = x1 + x_mult * ft_face->glyph->metrics.width;
+ float y2 = y1 + y_mult * -ft_face->glyph->metrics.height;
+
+ /* Apply slant. */
+ if (slant_xy)
+ {
+ x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
+ x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
+ }
+
+ extents->x_bearing = floorf (x1);
+ extents->y_bearing = floorf (y1);
+ extents->width = ceilf (x2) - extents->x_bearing;
+ extents->height = ceilf (y2) - extents->y_bearing;
+
+ if (font->x_strength || font->y_strength)
+ {
+ /* Y */
+ int y_shift = font->y_strength;
+ if (font->y_scale < 0) y_shift = -y_shift;
+ extents->y_bearing += y_shift;
+ extents->height -= y_shift;
+
+ /* X */
+ int x_shift = font->x_strength;
+ if (font->x_scale < 0) x_shift = -x_shift;
+ if (font->embolden_in_place)
+ extents->x_bearing -= x_shift / 2;
+ extents->width += x_shift;
+ }
return true;
}
@@ -700,6 +772,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
FT_Matrix matrix;
FT_Get_Transform (ft_face, &matrix, nullptr);
y_mult = sqrtf ((float)matrix.yx * matrix.yx + (float)matrix.yy * matrix.yy) / 65536.f;
+ y_mult *= font->y_scale < 0 ? -1 : +1;
}
else
#endif
@@ -721,7 +794,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender);
}
- metrics->ascender = (hb_position_t) (y_mult * metrics->ascender);
+ metrics->ascender = (hb_position_t) (y_mult * (metrics->ascender + font->y_strength));
metrics->descender = (hb_position_t) (y_mult * metrics->descender);
metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap);
@@ -773,11 +846,11 @@ _hb_ft_cubic_to (const FT_Vector *control1,
}
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)
+hb_ft_draw_glyph (hb_font_t *font,
+ 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);
@@ -801,12 +874,129 @@ hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
+ /* Embolden */
+ if (font->x_strength || font->y_strength)
+ {
+ FT_Outline_EmboldenXY (&ft_face->glyph->outline, font->x_strength, font->y_strength);
+
+ int x_shift = 0;
+ int y_shift = 0;
+ if (font->embolden_in_place)
+ {
+ /* Undo the FreeType shift. */
+ x_shift = -font->x_strength / 2;
+ y_shift = 0;
+ if (font->y_scale < 0) y_shift = -font->y_strength;
+ }
+ else
+ {
+ /* FreeType applied things in the wrong direction for negative scale; fix up. */
+ if (font->x_scale < 0) x_shift = -font->x_strength;
+ if (font->y_scale < 0) y_shift = -font->y_strength;
+ }
+ if (x_shift || y_shift)
+ {
+ auto &outline = ft_face->glyph->outline;
+ for (auto &point : hb_iter (outline.points, outline.contours[outline.n_contours - 1] + 1))
+ {
+ point.x += x_shift;
+ point.y += y_shift;
+ }
+ }
+ }
+
+
FT_Outline_Decompose (&ft_face->glyph->outline,
&outline_funcs,
&draw_session);
}
#endif
+#ifndef HB_NO_PAINT
+#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
+
+#include "hb-ft-colr.hh"
+
+static void
+hb_ft_paint_glyph (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t gid,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette_index,
+ hb_color_t foreground,
+ void *user_data)
+{
+ 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;
+
+ /* We release the lock before calling into glyph callbacks, such that
+ * eg. draw API can call back into the face.*/
+
+ if (unlikely (FT_Load_Glyph (ft_face, gid,
+ ft_font->load_flags | FT_LOAD_COLOR)))
+ return;
+
+ if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
+ {
+ if (hb_ft_paint_glyph_colr (font, font_data, gid,
+ paint_funcs, paint_data,
+ palette_index, foreground,
+ user_data))
+ return;
+
+ /* Simple outline. */
+ ft_font->lock.unlock ();
+ paint_funcs->push_clip_glyph (paint_data, gid, font);
+ ft_font->lock.lock ();
+ paint_funcs->color (paint_data, true, foreground);
+ paint_funcs->pop_clip (paint_data);
+
+ return;
+ }
+
+ auto *glyph = ft_face->glyph;
+ if (glyph->format == FT_GLYPH_FORMAT_BITMAP)
+ {
+ auto &bitmap = glyph->bitmap;
+ if (bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
+ {
+ if (bitmap.pitch != (signed) bitmap.width * 4)
+ return;
+
+ ft_font->lock.unlock ();
+
+ hb_blob_t *blob = hb_blob_create ((const char *) bitmap.buffer,
+ bitmap.pitch * bitmap.rows,
+ HB_MEMORY_MODE_DUPLICATE,
+ nullptr, nullptr);
+
+ hb_glyph_extents_t extents;
+ if (!hb_font_get_glyph_extents (font, gid, &extents))
+ goto out;
+
+ if (!paint_funcs->image (paint_data,
+ blob,
+ bitmap.width,
+ bitmap.rows,
+ HB_PAINT_IMAGE_FORMAT_BGRA,
+ font->slant_xy,
+ &extents))
+ {
+ /* TODO Try a forced outline load and paint? */
+ }
+
+ out:
+ hb_blob_destroy (blob);
+ ft_font->lock.lock ();
+ }
+
+ return;
+ }
+}
+#endif
+#endif
+
static inline void free_static_ft_funcs ();
@@ -840,7 +1030,13 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
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);
+ hb_font_funcs_set_draw_glyph_func (funcs, hb_ft_draw_glyph, nullptr, nullptr);
+#endif
+
+#ifndef HB_NO_PAINT
+#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
+ hb_font_funcs_set_paint_glyph_func (funcs, hb_ft_paint_glyph, nullptr, nullptr);
+#endif
#endif
hb_font_funcs_make_immutable (funcs);
@@ -915,6 +1111,10 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data
*
* Creates an #hb_face_t face object from the specified FT_Face.
*
+ * Note that this is using the FT_Face object just to get at the underlying
+ * font data, and fonts created from the returned #hb_face_t will use the native
+ * HarfBuzz font implementation, unless you call hb_ft_font_set_funcs() on them.
+ *
* This variant of the function does not provide any life-cycle management.
*
* Most client programs should use hb_ft_face_create_referenced()
@@ -959,6 +1159,10 @@ hb_ft_face_create (FT_Face ft_face,
*
* Creates an #hb_face_t face object from the specified FT_Face.
*
+ * Note that this is using the FT_Face object just to get at the underlying
+ * font data, and fonts created from the returned #hb_face_t will use the native
+ * HarfBuzz font implementation, unless you call hb_ft_font_set_funcs() on them.
+ *
* This is the preferred variant of the hb_ft_face_create*
* function family, because it calls FT_Reference_Face() on @ft_face,
* ensuring that @ft_face remains alive as long as the resulting
@@ -991,6 +1195,10 @@ hb_ft_face_finalize (void *arg)
*
* Creates an #hb_face_t face object from the specified FT_Face.
*
+ * Note that this is using the FT_Face object just to get at the underlying
+ * font data, and fonts created from the returned #hb_face_t will use the native
+ * HarfBuzz font implementation, unless you call hb_ft_font_set_funcs() on them.
+ *
* This variant of the function caches the newly created #hb_face_t
* face object, using the @generic pointer of @ft_face. Subsequent function
* calls that are passed the same @ft_face parameter will have the same
@@ -1241,10 +1449,14 @@ _release_blob (void *arg)
* created with hb_face_create(), and therefore was not
* initially configured to use FreeType font functions.
*
- * An #hb_face_t face object created with hb_ft_face_create()
+ * An #hb_font_t object created with hb_ft_font_create()
* is preconfigured for FreeType font functions and does not
* require this function to be used.
*
+ * Note that if you modify the underlying #hb_font_t after
+ * calling this function, you need to call hb_ft_hb_font_changed()
+ * to update the underlying FT_Face.
+ *
* <note>Note: Internally, this function creates an FT_Face.
* </note>
*
@@ -1285,5 +1497,4 @@ hb_ft_font_set_funcs (hb_font_t *font)
_hb_ft_hb_font_changed (font, ft_face);
}
-
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc
index ef13f1e966..332cc84888 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc
@@ -91,6 +91,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 (paint_funcs)
HB_DEFINE_OBJECT_TYPE (face)
HB_DEFINE_OBJECT_TYPE (font)
HB_DEFINE_OBJECT_TYPE (font_funcs)
@@ -102,8 +103,12 @@ HB_DEFINE_VALUE_TYPE (feature)
HB_DEFINE_VALUE_TYPE (glyph_info)
HB_DEFINE_VALUE_TYPE (glyph_position)
HB_DEFINE_VALUE_TYPE (segment_properties)
+HB_DEFINE_VALUE_TYPE (draw_state)
+HB_DEFINE_VALUE_TYPE (color_stop)
+HB_DEFINE_VALUE_TYPE (color_line)
HB_DEFINE_VALUE_TYPE (user_data_key)
+HB_DEFINE_VALUE_TYPE (ot_var_axis_info)
HB_DEFINE_VALUE_TYPE (ot_math_glyph_variant)
HB_DEFINE_VALUE_TYPE (ot_math_glyph_part)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h
index 3914a2431a..b7b5f55ce6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.h
@@ -53,6 +53,10 @@ hb_gobject_draw_funcs_get_type (void);
#define HB_GOBJECT_TYPE_DRAW_FUNCS (hb_gobject_draw_funcs_get_type ())
HB_EXTERN GType
+hb_gobject_paint_funcs_get_type (void);
+#define HB_GOBJECT_TYPE_PAINT_FUNCS (hb_gobject_paint_funcs_get_type ())
+
+HB_EXTERN GType
hb_gobject_face_get_type (void);
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
@@ -99,10 +103,26 @@ hb_gobject_segment_properties_get_type (void);
#define HB_GOBJECT_TYPE_SEGMENT_PROPERTIES (hb_gobject_segment_properties_get_type ())
HB_EXTERN GType
+hb_gobject_draw_state_get_type (void);
+#define HB_GOBJECT_TYPE_DRAW_STATE (hb_gobject_draw_state_get_type ())
+
+HB_EXTERN GType
+hb_gobject_color_stop_get_type (void);
+#define HB_GOBJECT_TYPE_COLOR_STOP (hb_gobject_color_stop_get_type ())
+
+HB_EXTERN GType
+hb_gobject_color_line_get_type (void);
+#define HB_GOBJECT_TYPE_COLOR_LINE (hb_gobject_color_line_get_type ())
+
+HB_EXTERN GType
hb_gobject_user_data_key_get_type (void);
#define HB_GOBJECT_TYPE_USER_DATA_KEY (hb_gobject_user_data_key_get_type ())
HB_EXTERN GType
+hb_gobject_ot_var_axis_info_get_type (void);
+#define HB_GOBJECT_TYPE_OT_VAR_AXIS_INFO (hb_gobject_ot_var_axis_info_get_type ())
+
+HB_EXTERN GType
hb_gobject_ot_math_glyph_variant_get_type (void);
#define HB_GOBJECT_TYPE_OT_MATH_GLYPH_VARIANT (hb_gobject_ot_math_glyph_variant_get_type ())
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.h b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.h
index f299da9f71..ee9229b8b0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.h
@@ -49,7 +49,8 @@ hb_graphite2_face_get_gr_face (hb_face_t *face);
#ifndef HB_DISABLE_DEPRECATED
-HB_EXTERN HB_DEPRECATED_FOR (hb_graphite2_face_get_gr_face) gr_font *
+HB_DEPRECATED_FOR (hb_graphite2_face_get_gr_face)
+HB_EXTERN gr_font *
hb_graphite2_font_get_gr_font (hb_font_t *font);
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
index b57f37b132..b123b2f27c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
@@ -172,10 +172,16 @@ struct
HB_FUNCOBJ (hb_iter);
struct
{
- template <typename T> unsigned
- operator () (T&& c) const
- { return c.len (); }
+ template <typename T> auto
+ impl (T&& c, hb_priority<1>) const HB_RETURN (unsigned, c.len ())
+
+ template <typename T> auto
+ impl (T&& c, hb_priority<0>) const HB_RETURN (unsigned, c.len)
+
+ public:
+ template <typename T> auto
+ operator () (T&& c) const HB_RETURN (unsigned, impl (std::forward<T> (c), hb_prioritize))
}
HB_FUNCOBJ (hb_len);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-limits.hh b/src/3rdparty/harfbuzz-ng/src/hb-limits.hh
new file mode 100644
index 0000000000..0f60e9e210
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-limits.hh
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#ifndef HB_LIMITS_HH
+#define HB_LIMITS_HH
+
+#include "hb.hh"
+
+
+#ifndef HB_BUFFER_MAX_LEN_FACTOR
+#define HB_BUFFER_MAX_LEN_FACTOR 64
+#endif
+#ifndef HB_BUFFER_MAX_LEN_MIN
+#define HB_BUFFER_MAX_LEN_MIN 16384
+#endif
+#ifndef HB_BUFFER_MAX_LEN_DEFAULT
+#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
+#endif
+
+#ifndef HB_BUFFER_MAX_OPS_FACTOR
+#define HB_BUFFER_MAX_OPS_FACTOR 1024
+#endif
+#ifndef HB_BUFFER_MAX_OPS_MIN
+#define HB_BUFFER_MAX_OPS_MIN 16384
+#endif
+#ifndef HB_BUFFER_MAX_OPS_DEFAULT
+#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
+#endif
+
+
+#ifndef HB_MAX_NESTING_LEVEL
+#define HB_MAX_NESTING_LEVEL 64
+#endif
+
+
+#ifndef HB_MAX_CONTEXT_LENGTH
+#define HB_MAX_CONTEXT_LENGTH 64
+#endif
+
+#ifndef HB_CLOSURE_MAX_STAGES
+/*
+ * The maximum number of times a lookup can be applied during shaping.
+ * Used to limit the number of iterations of the closure algorithm.
+ * This must be larger than the number of times add_gsub_pause() is
+ * called in a collect_features call of any shaper.
+ */
+#define HB_CLOSURE_MAX_STAGES 12
+#endif
+
+#ifndef HB_MAX_SCRIPTS
+#define HB_MAX_SCRIPTS 500
+#endif
+
+#ifndef HB_MAX_LANGSYS
+#define HB_MAX_LANGSYS 2000
+#endif
+
+#ifndef HB_MAX_LANGSYS_FEATURE_COUNT
+#define HB_MAX_LANGSYS_FEATURE_COUNT 50000
+#endif
+
+#ifndef HB_MAX_FEATURE_INDICES
+#define HB_MAX_FEATURE_INDICES 1500
+#endif
+
+#ifndef HB_MAX_LOOKUP_VISIT_COUNT
+#define HB_MAX_LOOKUP_VISIT_COUNT 35000
+#endif
+
+
+#ifndef HB_GLYF_MAX_POINTS
+#define HB_GLYF_MAX_POINTS 20000
+#endif
+
+#ifndef HB_GLYF_MAX_EDGE_COUNT
+#define HB_GLYF_MAX_EDGE_COUNT 1024
+#endif
+
+#ifndef HB_CFF_MAX_OPS
+#define HB_CFF_MAX_OPS 10000
+#endif
+
+#ifndef HB_COLRV1_MAX_EDGE_COUNT
+#define HB_COLRV1_MAX_EDGE_COUNT 1024
+#endif
+
+
+#endif /* HB_LIMITS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
index b555739cfb..1084725af2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
@@ -34,7 +34,6 @@
#include "hb-dispatch.hh"
#include "hb-sanitize.hh"
-#include "hb-serialize.hh"
/*
@@ -305,22 +304,22 @@ struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
hb_blob_t* get_blob () const { return this->get_stored (); }
};
-template <typename Subclass>
-struct hb_font_funcs_lazy_loader_t : hb_lazy_loader_t<hb_font_funcs_t, Subclass>
-{
- static void destroy (hb_font_funcs_t *p)
- { hb_font_funcs_destroy (p); }
- static const hb_font_funcs_t *get_null ()
- { return hb_font_funcs_get_empty (); }
-};
-template <typename Subclass>
-struct hb_unicode_funcs_lazy_loader_t : hb_lazy_loader_t<hb_unicode_funcs_t, Subclass>
-{
- static void destroy (hb_unicode_funcs_t *p)
- { hb_unicode_funcs_destroy (p); }
- static const hb_unicode_funcs_t *get_null ()
- { return hb_unicode_funcs_get_empty (); }
-};
+#define HB_DEFINE_TYPE_FUNCS_LAZY_LOADER_T(Type) \
+ template <typename Subclass> \
+ struct hb_##Type##_funcs_lazy_loader_t : hb_lazy_loader_t<hb_##Type##_funcs_t, Subclass> \
+ { \
+ static void destroy (hb_##Type##_funcs_t *p) \
+ { hb_##Type##_funcs_destroy (p); } \
+ static const hb_##Type##_funcs_t *get_null () \
+ { return hb_##Type##_funcs_get_empty (); } \
+ }
+
+HB_DEFINE_TYPE_FUNCS_LAZY_LOADER_T (font);
+HB_DEFINE_TYPE_FUNCS_LAZY_LOADER_T (unicode);
+HB_DEFINE_TYPE_FUNCS_LAZY_LOADER_T (draw);
+HB_DEFINE_TYPE_FUNCS_LAZY_LOADER_T (paint);
+
+#undef HB_DEFINE_TYPE_FUNCS_LAZY_LOADER_T
#endif /* HB_MACHINERY_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.cc b/src/3rdparty/harfbuzz-ng/src/hb-map.cc
index 5c5f5de59e..0014570e8e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-map.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-map.cc
@@ -174,7 +174,7 @@ hb_map_allocation_successful (const hb_map_t *map)
*
* Allocate a copy of @map.
*
- * Return value: Newly-allocated map.
+ * Return value: (transfer full): Newly-allocated map.
*
* Since: 4.4.0
**/
@@ -182,9 +182,10 @@ hb_map_t *
hb_map_copy (const hb_map_t *map)
{
hb_map_t *copy = hb_map_create ();
- if (unlikely (!copy)) return nullptr;
- copy->resize (map->population);
- hb_copy (*map, *copy);
+ if (unlikely (copy->in_error ()))
+ return hb_map_get_empty ();
+
+ *copy = *map;
return copy;
}
@@ -335,9 +336,84 @@ hb_map_is_equal (const hb_map_t *map,
*
* Since: 4.4.0
**/
-HB_EXTERN unsigned int
+unsigned int
hb_map_hash (const hb_map_t *map)
{
return map->hash ();
}
+/**
+ * hb_map_update:
+ * @map: A map
+ * @other: Another map
+ *
+ * Add the contents of @other to @map.
+ *
+ * Since: 7.0.0
+ **/
+HB_EXTERN void
+hb_map_update (hb_map_t *map,
+ const hb_map_t *other)
+{
+ map->update (*other);
+}
+
+/**
+ * hb_map_next:
+ * @map: A map
+ * @idx: (inout): Iterator internal state
+ * @key: (out): Key retrieved
+ * @value: (out): Value retrieved
+ *
+ * Fetches the next key/value paire in @map.
+ *
+ * Set @idx to -1 to get started.
+ *
+ * If the map is modified during iteration, the behavior is undefined.
+ *
+ * The order in which the key/values are returned is undefined.
+ *
+ * Return value: `true` if there was a next value, `false` otherwise
+ *
+ * Since: 7.0.0
+ **/
+hb_bool_t
+hb_map_next (const hb_map_t *map,
+ int *idx,
+ hb_codepoint_t *key,
+ hb_codepoint_t *value)
+{
+ return map->next (idx, key, value);
+}
+
+/**
+ * hb_map_keys:
+ * @map: A map
+ * @keys: A set
+ *
+ * Add the keys of @map to @keys.
+ *
+ * Since: 7.0.0
+ **/
+void
+hb_map_keys (const hb_map_t *map,
+ hb_set_t *keys)
+{
+ map->keys (*keys);
+}
+
+/**
+ * hb_map_values:
+ * @map: A map
+ * @values: A set
+ *
+ * Add the values of @map to @values.
+ *
+ * Since: 7.0.0
+ **/
+void
+hb_map_values (const hb_map_t *map,
+ hb_set_t *values)
+{
+ map->values (*values);
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.h b/src/3rdparty/harfbuzz-ng/src/hb-map.h
index 3a067c5c73..e928628fa7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-map.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-map.h
@@ -32,6 +32,7 @@
#define HB_MAP_H
#include "hb-common.h"
+#include "hb-set.h"
HB_BEGIN_DECLS
@@ -118,6 +119,24 @@ HB_EXTERN hb_bool_t
hb_map_has (const hb_map_t *map,
hb_codepoint_t key);
+HB_EXTERN void
+hb_map_update (hb_map_t *map,
+ const hb_map_t *other);
+
+/* Pass -1 in for idx to get started. */
+HB_EXTERN hb_bool_t
+hb_map_next (const hb_map_t *map,
+ int *idx,
+ hb_codepoint_t *key,
+ hb_codepoint_t *value);
+
+HB_EXTERN void
+hb_map_keys (const hb_map_t *map,
+ hb_set_t *keys);
+
+HB_EXTERN void
+hb_map_values (const hb_map_t *map,
+ hb_set_t *values);
HB_END_DECLS
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-map.hh
index bfb1b3f768..615d1825ed 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-map.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-map.hh
@@ -29,6 +29,8 @@
#include "hb.hh"
+#include "hb-set.hh"
+
/*
* hb_hashmap_t
@@ -308,6 +310,23 @@ struct hb_hashmap_t
unsigned int get_population () const { return population; }
+ void update (const hb_hashmap_t &other)
+ {
+ if (unlikely (!successful)) return;
+
+ hb_copy (other, *this);
+ }
+
+ void keys (hb_set_t &keys_) const
+ {
+ hb_copy (keys() , keys_);
+ }
+
+ void values (hb_set_t &values_) const
+ {
+ hb_copy (values() , values_);
+ }
+
/*
* Iterator
*/
@@ -348,6 +367,30 @@ struct hb_hashmap_t
| hb_map (hb_ridentity)
)
+ /* C iterator. */
+ bool next (int *idx,
+ K *key,
+ V *value) const
+ {
+ unsigned i = (unsigned) (*idx + 1);
+
+ unsigned count = size ();
+ while (i < count && !items[i].is_real ())
+ i++;
+
+ if (i >= count)
+ {
+ *idx = -1;
+ return false;
+ }
+
+ *key = items[i].key;
+ *value = items[i].value;
+
+ *idx = (signed) i;
+ return true;
+ }
+
/* Sink interface. */
hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
{ set (v.first, v.second); return *this; }
@@ -451,37 +494,5 @@ struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_map_t (const Iterable &o) : hashmap (o) {}
};
-template <typename K, typename V>
-static inline
-hb_hashmap_t<K, V>* hb_hashmap_create ()
-{
- using hashmap = hb_hashmap_t<K, V>;
- hashmap* map;
- if (!(map = hb_object_create<hashmap> ()))
- return nullptr;
-
- return map;
-}
-
-template <typename K, typename V>
-static inline
-void hb_hashmap_destroy (hb_hashmap_t<K, V>* map)
-{
- if (!hb_object_destroy (map))
- return;
-
- hb_free (map);
-}
-
-namespace hb {
-
-template <typename K, typename V>
-struct vtable<hb_hashmap_t<K, V>>
-{
- static constexpr auto destroy = hb_hashmap_destroy<K,V>;
-};
-
-}
-
#endif /* HB_MAP_HH */
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 46a20c91ea..f7649ab76e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.hh
@@ -30,6 +30,9 @@
#include "hb.hh"
+/* Variations of this code exist in hb-coretext.cc as well
+ * as hb-aat-map.cc... */
+
typedef struct hb_ms_feature_t {
uint32_t tag_le;
uint32_t value;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh
index f0f95917aa..b4a8cc62a3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh
@@ -65,7 +65,7 @@ struct hb_multimap_t
hb_array_t<const hb_codepoint_t> get (hb_codepoint_t k) const
{
- hb_codepoint_t *v;
+ const hb_codepoint_t *v;
if (singulars.has (k, &v))
return hb_array (v, 1);
@@ -73,7 +73,7 @@ struct hb_multimap_t
if (multiples_indices.has (k, &i))
return multiples_values[*i].as_array ();
- return hb_array_t<hb_codepoint_t> ();
+ return hb_array_t<const hb_codepoint_t> ();
}
bool in_error () const
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh b/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh
index 053f9ddcc4..e329d9864f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh
@@ -60,7 +60,7 @@ typedef pthread_mutex_t hb_mutex_impl_t;
#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)
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0)
#else
#define hb_mutex_impl_init(M) InitializeCriticalSection (M)
@@ -97,6 +97,9 @@ struct hb_mutex_t
/* Create space for, but do not initialize m. */
alignas(hb_mutex_impl_t) char m[sizeof (hb_mutex_impl_t)];
+ hb_mutex_t () { init (); }
+ ~hb_mutex_t () { fini (); }
+
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
void init () { hb_mutex_impl_init ((hb_mutex_impl_t *) m); }
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-number.cc b/src/3rdparty/harfbuzz-ng/src/hb-number.cc
index 6e4f3f7ebd..c52b284e1d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-number.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-number.cc
@@ -24,7 +24,6 @@
*/
#include "hb.hh"
-#include "hb-machinery.hh"
#include "hb-number.hh"
#include "hb-number-parser.hh"
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-object.hh b/src/3rdparty/harfbuzz-ng/src/hb-object.hh
index a23c25f7ca..e2c2c3394c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-object.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-object.hh
@@ -69,7 +69,7 @@ struct hb_lockable_set_t
item = items.push (v);
l.unlock ();
}
- return item;
+ return items.in_error () ? nullptr : item;
}
template <typename T>
@@ -175,14 +175,34 @@ struct hb_user_data_array_t
void init () { lock.init (); items.init (); }
- HB_INTERNAL bool set (hb_user_data_key_t *key,
- void * data,
- hb_destroy_func_t destroy,
- hb_bool_t replace);
+ void fini () { items.fini (lock); lock.fini (); }
- HB_INTERNAL void *get (hb_user_data_key_t *key);
+ bool set (hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+ {
+ if (!key)
+ return false;
- void fini () { items.fini (lock); lock.fini (); }
+ if (replace) {
+ if (!data && !destroy) {
+ items.remove (key, lock);
+ return true;
+ }
+ }
+ hb_user_data_item_t item = {key, data, destroy};
+ bool ret = !!items.replace_or_insert (item, lock, (bool) replace);
+
+ return ret;
+ }
+
+ void *get (hb_user_data_key_t *key)
+ {
+ hb_user_data_item_t item = {nullptr, nullptr, nullptr};
+
+ return items.find (key, &item, lock) ? item.data : nullptr;
+ }
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
index 290799127a..4c9bfebcec 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
@@ -147,7 +147,10 @@ struct HBFixed : Type
static constexpr float shift = (float) (1 << fraction_bits);
static_assert (Type::static_size * 8 > fraction_bits, "");
- HBFixed& operator = (typename Type::type i ) { Type::operator= (i); return *this; }
+ operator signed () const = delete;
+ operator unsigned () const = delete;
+ typename Type::type to_int () const { return Type::v; }
+ void set_int (typename Type::type i ) { Type::v = i; }
float to_float (float offset = 0) const { return ((int32_t) Type::v + offset) / shift; }
void set_float (float f) { Type::v = roundf (f * shift); }
public:
@@ -156,9 +159,8 @@ struct HBFixed : Type
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
using F2DOT14 = HBFixed<HBINT16, 14>;
-
-/* 16-bit signed fixed number with the low 12 bits of fraction (4.12). */
using F4DOT12 = HBFixed<HBINT16, 12>;
+using F6DOT10 = HBFixed<HBINT16, 10>;
/* 32-bit signed fixed-point number (16.16). */
using F16DOT16 = HBFixed<HBINT32, 16>;
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 bd9fe5d6d4..5040c74623 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
@@ -422,8 +422,8 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
}
else
{
- extents->x_bearing = font->em_scalef_x (bounds.min.x.to_real ());
- extents->width = font->em_scalef_x (bounds.max.x.to_real ()) - extents->x_bearing;
+ extents->x_bearing = roundf (bounds.min.x.to_real ());
+ extents->width = roundf (bounds.max.x.to_real () - extents->x_bearing);
}
if (bounds.min.y >= bounds.max.y)
{
@@ -432,10 +432,12 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
}
else
{
- extents->y_bearing = font->em_scalef_y (bounds.max.y.to_real ());
- extents->height = font->em_scalef_y (bounds.min.y.to_real ()) - extents->y_bearing;
+ extents->y_bearing = roundf (bounds.max.y.to_real ());
+ extents->height = roundf (bounds.min.y.to_real () - extents->y_bearing);
}
+ font->scale_glyph_extents (extents);
+
return true;
}
@@ -551,6 +553,15 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
return true;
}
+bool OT::cff1::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
+{
+ funcs->push_clip_glyph (data, glyph, font);
+ funcs->color (data, true, foreground);
+ funcs->pop_clip (data);
+
+ return true;
+}
+
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
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 bb856c9ddb..f461a23044 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh
@@ -30,6 +30,7 @@
#include "hb-ot-cff-common.hh"
#include "hb-subset-cff1.hh"
#include "hb-draw.hh"
+#include "hb-paint.hh"
#define HB_STRING_ARRAY_NAME cff1_std_strings
#define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh"
@@ -901,8 +902,6 @@ struct cff1_private_dict_opset_t : dict_opset_t
case OpCode_FamilyOtherBlues:
case OpCode_StemSnapH:
case OpCode_StemSnapV:
- env.clear_args ();
- break;
case OpCode_StdHW:
case OpCode_StdVW:
case OpCode_BlueScale:
@@ -914,7 +913,6 @@ struct cff1_private_dict_opset_t : dict_opset_t
case OpCode_initialRandomSeed:
case OpCode_defaultWidthX:
case OpCode_nominalWidthX:
- val.single_val = env.argStack.pop_num ();
env.clear_args ();
break;
case OpCode_Subrs:
@@ -1343,6 +1341,7 @@ struct cff1
bool get_glyph_name (hb_codepoint_t glyph,
char *buf, unsigned int buf_len) const
{
+ if (unlikely (glyph >= num_glyphs)) return false;
if (unlikely (!is_valid ())) return false;
if (is_CID()) return false;
if (unlikely (!buf_len)) return true;
@@ -1426,6 +1425,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 paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
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 50c76daf93..7955565551 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc
@@ -124,8 +124,8 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
}
else
{
- extents->x_bearing = font->em_scalef_x (param.min_x.to_real ());
- extents->width = font->em_scalef_x (param.max_x.to_real ()) - extents->x_bearing;
+ extents->x_bearing = roundf (param.min_x.to_real ());
+ extents->width = roundf (param.max_x.to_real () - extents->x_bearing);
}
if (param.min_y >= param.max_y)
{
@@ -134,10 +134,21 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
}
else
{
- extents->y_bearing = font->em_scalef_y (param.max_y.to_real ());
- extents->height = font->em_scalef_y (param.min_y.to_real ()) - extents->y_bearing;
+ extents->y_bearing = roundf (param.max_y.to_real ());
+ extents->height = roundf (param.min_y.to_real () - extents->y_bearing);
}
+ font->scale_glyph_extents (extents);
+
+ return true;
+}
+
+bool OT::cff2::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
+{
+ funcs->push_clip_glyph (data, glyph, font);
+ funcs->color (data, true, foreground);
+ funcs->pop_clip (data);
+
return true;
}
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 9081930bbe..b9a8819ab8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh
@@ -30,6 +30,7 @@
#include "hb-ot-cff-common.hh"
#include "hb-subset-cff2.hh"
#include "hb-draw.hh"
+#include "hb-paint.hh"
namespace CFF {
@@ -282,9 +283,6 @@ struct cff2_private_dict_opset_t : dict_opset_t
case OpCode_BlueFuzz:
case OpCode_ExpansionFactor:
case OpCode_LanguageGroup:
- val.single_val = env.argStack.pop_num ();
- env.clear_args ();
- break;
case OpCode_BlueValues:
case OpCode_OtherBlues:
case OpCode_FamilyBlues:
@@ -516,6 +514,7 @@ struct cff2
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
+ HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
};
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 523196fa79..f5a03d2b00 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
@@ -31,6 +31,7 @@
#include "hb-ot-shaper-arabic-pua.hh"
#include "hb-open-type.hh"
#include "hb-set.hh"
+#include "hb-cache.hh"
/*
* cmap -- Character to Glyph Index Mapping
@@ -1414,7 +1415,7 @@ struct CmapSubtable
switch (format) {
case 4: return u.format4.serialize (c, it);
case 12: return u.format12.serialize (c, it);
- case 14: return u.format14.serialize (c, plan->unicodes, plan->glyphs_requested, plan->glyph_map, base);
+ case 14: return u.format14.serialize (c, &plan->unicodes, &plan->glyphs_requested, plan->glyph_map, base);
default: return;
}
}
@@ -1841,6 +1842,8 @@ struct cmap
struct accelerator_t
{
+ using cache_t = hb_cache_t<21, 16, 8, true>;
+
accelerator_t (hb_face_t *face)
{
this->table = hb_sanitize_context_t ().reference_table<cmap> (face);
@@ -1895,26 +1898,43 @@ struct cmap
}
~accelerator_t () { this->table.destroy (); }
+ inline bool _cached_get (hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ cache_t *cache) const
+ {
+ unsigned v;
+ if (cache && cache->get (unicode, &v))
+ {
+ *glyph = v;
+ return true;
+ }
+ bool ret = this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph);
+
+ if (cache && ret)
+ cache->set (unicode, *glyph);
+ return ret;
+ }
+
bool get_nominal_glyph (hb_codepoint_t unicode,
- hb_codepoint_t *glyph) const
+ hb_codepoint_t *glyph,
+ cache_t *cache = nullptr) const
{
- if (unlikely (!this->get_glyph_funcZ)) return false;
- return this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph);
+ if (unlikely (!this->get_glyph_funcZ)) return 0;
+ return _cached_get (unicode, glyph, cache);
}
+
unsigned int get_nominal_glyphs (unsigned int count,
const hb_codepoint_t *first_unicode,
unsigned int unicode_stride,
hb_codepoint_t *first_glyph,
- unsigned int glyph_stride) const
+ unsigned int glyph_stride,
+ cache_t *cache = nullptr) const
{
if (unlikely (!this->get_glyph_funcZ)) return 0;
- hb_cmap_get_glyph_func_t get_glyph_funcZ = this->get_glyph_funcZ;
- const void *get_glyph_data = this->get_glyph_data;
-
unsigned int done;
for (done = 0;
- done < count && get_glyph_funcZ (get_glyph_data, *first_unicode, first_glyph);
+ done < count && _cached_get (*first_unicode, first_glyph, cache);
done++)
{
first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
@@ -1925,7 +1945,8 @@ struct cmap
bool get_variation_glyph (hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph) const
+ hb_codepoint_t *glyph,
+ cache_t *cache = nullptr) const
{
switch (this->subtable_uvs->get_glyph_variant (unicode,
variation_selector,
@@ -1936,7 +1957,7 @@ struct cmap
case GLYPH_VARIANT_USE_DEFAULT: break;
}
- return get_nominal_glyph (unicode, glyph);
+ return get_nominal_glyph (unicode, glyph, cache);
}
void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc
index 696ca3e17f..37d42e08d9 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc
@@ -31,11 +31,11 @@
#include "hb-ot.h"
-#include "hb-ot-color-cbdt-table.hh"
-#include "hb-ot-color-colr-table.hh"
-#include "hb-ot-color-cpal-table.hh"
-#include "hb-ot-color-sbix-table.hh"
-#include "hb-ot-color-svg-table.hh"
+#include "OT/Color/CBDT/CBDT.hh"
+#include "OT/Color/COLR/COLR.hh"
+#include "OT/Color/CPAL/CPAL.hh"
+#include "OT/Color/sbix/sbix.hh"
+#include "OT/Color/svg/svg.hh"
/**
@@ -167,6 +167,10 @@ hb_ot_color_palette_get_flags (hb_face_t *face,
* for allocating a buffer of suitable size before calling
* hb_ot_color_palette_get_colors() a second time.
*
+ * The RGBA values in the palette are unpremultiplied. See the
+ * OpenType spec [CPAL](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal)
+ * section for details.
+ *
* Return value: the total number of colors in the palette
*
* Since: 2.1.0
@@ -190,7 +194,8 @@ hb_ot_color_palette_get_colors (hb_face_t *face,
* hb_ot_color_has_layers:
* @face: #hb_face_t to work upon
*
- * Tests whether a face includes any `COLR` color layers.
+ * Tests whether a face includes a `COLR` table
+ * with data according to COLRv0.
*
* Return value: `true` if data found, `false` otherwise
*
@@ -199,7 +204,43 @@ hb_ot_color_palette_get_colors (hb_face_t *face,
hb_bool_t
hb_ot_color_has_layers (hb_face_t *face)
{
- return face->table.COLR->has_data ();
+ return face->table.COLR->has_v0_data ();
+}
+
+/**
+ * hb_ot_color_has_paint:
+ * @face: #hb_face_t to work upon
+ *
+ * Tests where a face includes a `COLR` table
+ * with data according to COLRv1.
+ *
+ * Return value: `true` if data found, `false` otherwise
+ *
+ * Since: 7.0.0
+ */
+hb_bool_t
+hb_ot_color_has_paint (hb_face_t *face)
+{
+ return face->table.COLR->has_v1_data ();
+}
+
+/**
+ * hb_ot_color_glyph_has_paint:
+ * @face: #hb_face_t to work upon
+ * @glyph: The glyph index to query
+ *
+ * Tests where a face includes COLRv1 paint
+ * data for @glyph.
+ *
+ * Return value: `true` if data found, `false` otherwise
+ *
+ * Since: 7.0.0
+ */
+hb_bool_t
+hb_ot_color_glyph_has_paint (hb_face_t *face,
+ hb_codepoint_t glyph)
+{
+ return face->table.COLR->has_paint_for_glyph (glyph);
}
/**
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-color.h
index d11e07e230..22ee497e38 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-color.h
@@ -120,6 +120,15 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
unsigned int *layer_count, /* IN/OUT. May be NULL. */
hb_ot_color_layer_t *layers /* OUT. May be NULL. */);
+/* COLRv1 */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_paint (hb_face_t *face);
+
+HB_EXTERN hb_bool_t
+hb_ot_color_glyph_has_paint (hb_face_t *face,
+ hb_codepoint_t glyph);
+
/*
* SVG
*/
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h
index 5192ff73e3..60672ab128 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h
@@ -67,26 +67,30 @@ HB_BEGIN_DECLS
/* 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
+HB_DEPRECATED_FOR (hb_ot_layout_table_select_script)
+HB_EXTERN hb_bool_t
hb_ot_layout_table_choose_script (hb_face_t *face,
hb_tag_t table_tag,
const hb_tag_t *script_tags,
unsigned int *script_index,
hb_tag_t *chosen_script);
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_script_select_language) hb_bool_t
+HB_DEPRECATED_FOR (hb_ot_layout_script_select_language)
+HB_EXTERN hb_bool_t
hb_ot_layout_script_find_language (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
hb_tag_t language_tag,
unsigned int *language_index);
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) void
+HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language)
+HB_EXTERN void
hb_ot_tags_from_script (hb_script_t script,
hb_tag_t *script_tag_1,
hb_tag_t *script_tag_2);
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) hb_tag_t
+HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language)
+HB_EXTERN hb_tag_t
hb_ot_tag_from_language (hb_language_t language);
@@ -121,13 +125,15 @@ typedef struct hb_ot_var_axis_t {
float max_value;
} hb_ot_var_axis_t;
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_get_axis_infos) unsigned int
+HB_DEPRECATED_FOR (hb_ot_var_get_axis_infos)
+HB_EXTERN unsigned int
hb_ot_var_get_axes (hb_face_t *face,
unsigned int start_offset,
unsigned int *axes_count /* IN/OUT */,
hb_ot_var_axis_t *axes_array /* OUT */);
-HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_find_axis_info) hb_bool_t
+HB_DEPRECATED_FOR (hb_ot_var_find_axis_info)
+HB_EXTERN hb_bool_t
hb_ot_var_find_axis (hb_face_t *face,
hb_tag_t axis_tag,
unsigned int *axis_index,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-face.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-face.cc
index 5ef8df43ce..2243ee0287 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-face.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-face.cc
@@ -35,9 +35,9 @@
#include "hb-ot-meta-table.hh"
#include "hb-ot-name-table.hh"
#include "hb-ot-post-table.hh"
-#include "hb-ot-color-cbdt-table.hh"
-#include "hb-ot-color-sbix-table.hh"
-#include "hb-ot-color-svg-table.hh"
+#include "OT/Color/CBDT/CBDT.hh"
+#include "OT/Color/sbix/sbix.hh"
+#include "OT/Color/svg/svg.hh"
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
index 8405103423..19ae02e28b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
@@ -34,6 +34,7 @@
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-ot-face.hh"
+#include "hb-outline.hh"
#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
@@ -43,9 +44,10 @@
#include "hb-ot-post-table.hh"
#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
#include "hb-ot-vorg-table.hh"
-#include "hb-ot-color-cbdt-table.hh"
-#include "hb-ot-color-sbix-table.hh"
-#include "hb-ot-color-colr-table.hh"
+#include "OT/Color/CBDT/CBDT.hh"
+#include "OT/Color/COLR/COLR.hh"
+#include "OT/Color/sbix/sbix.hh"
+#include "OT/Color/svg/svg.hh"
/**
@@ -59,12 +61,17 @@
* never need to call these functions directly.
**/
+using hb_ot_font_cmap_cache_t = hb_cache_t<21, 16, 8, true>;
using hb_ot_font_advance_cache_t = hb_cache_t<24, 16, 8, true>;
+static hb_user_data_key_t hb_ot_font_cmap_cache_user_data_key;
+
struct hb_ot_font_t
{
const hb_ot_face_t *ot_face;
+ hb_ot_font_cmap_cache_t *cmap_cache;
+
/* h_advance caching */
mutable hb_atomic_int_t cached_coords_serial;
mutable hb_atomic_ptr_t<hb_ot_font_advance_cache_t> advance_cache;
@@ -79,6 +86,33 @@ _hb_ot_font_create (hb_font_t *font)
ot_font->ot_face = &font->face->table;
+ // retry:
+ auto *cmap_cache = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face,
+ &hb_ot_font_cmap_cache_user_data_key);
+ if (!cmap_cache)
+ {
+ cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t));
+ if (unlikely (!cmap_cache)) goto out;
+ cmap_cache->init ();
+ if (unlikely (!hb_face_set_user_data (font->face,
+ &hb_ot_font_cmap_cache_user_data_key,
+ cmap_cache,
+ hb_free,
+ false)))
+ {
+ hb_free (cmap_cache);
+ cmap_cache = nullptr;
+ /* Normally we would retry here, but that would
+ * infinite-loop if the face is the empty-face.
+ * Just let it go and this font will be uncached if it
+ * happened to collide with another thread creating the
+ * cache at the same time. */
+ // goto retry;
+ }
+ }
+ out:
+ ot_font->cmap_cache = cmap_cache;
+
return ot_font;
}
@@ -88,11 +122,7 @@ _hb_ot_font_destroy (void *font_data)
hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
auto *cache = ot_font->advance_cache.get_relaxed ();
- if (cache)
- {
- cache->fini ();
- hb_free (cache);
- }
+ hb_free (cache);
hb_free (ot_font);
}
@@ -106,7 +136,7 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
- return ot_face->cmap->get_nominal_glyph (unicode, glyph);
+ return ot_face->cmap->get_nominal_glyph (unicode, glyph, ot_font->cmap_cache);
}
static unsigned int
@@ -123,7 +153,8 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_nominal_glyphs (count,
first_unicode, unicode_stride,
- first_glyph, glyph_stride);
+ first_glyph, glyph_stride,
+ ot_font->cmap_cache);
}
static hb_bool_t
@@ -136,7 +167,9 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
- return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
+ return ot_face->cmap->get_variation_glyph (unicode,
+ variation_selector, glyph,
+ ot_font->cmap_cache);
}
static void
@@ -148,10 +181,13 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
+
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
+ hb_position_t *orig_first_advance = first_advance;
+
#ifndef HB_NO_VAR
const OT::HVAR &HVAR = *hmtx.var_table;
const OT::VariationStore &varStore = &HVAR + HVAR.varStore;
@@ -225,6 +261,18 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
#ifndef HB_NO_VAR
OT::VariationStore::destroy_cache (varStore_cache);
#endif
+
+ if (font->x_strength && !font->embolden_in_place)
+ {
+ /* Emboldening. */
+ hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength;
+ first_advance = orig_first_advance;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance += *first_advance ? x_strength : 0;
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
}
#ifndef HB_NO_VERTICAL
@@ -241,6 +289,8 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+ hb_position_t *orig_first_advance = first_advance;
+
if (vmtx.has_data ())
{
#ifndef HB_NO_VAR
@@ -275,6 +325,18 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
}
+
+ if (font->y_strength && !font->embolden_in_place)
+ {
+ /* Emboldening. */
+ hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
+ first_advance = orig_first_advance;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance += *first_advance ? y_strength : 0;
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
}
#endif
@@ -404,9 +466,16 @@ hb_ot_get_font_h_extents (hb_font_t *font,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
- return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
- _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
- _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
+ bool ret = _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
+ _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
+ _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
+
+ /* Embolden */
+ int y_shift = font->y_strength;
+ if (font->y_scale < 0) y_shift = -y_shift;
+ metrics->ascender += y_shift;
+
+ return ret;
}
#ifndef HB_NO_VERTICAL
@@ -424,17 +493,62 @@ hb_ot_get_font_v_extents (hb_font_t *font,
#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_ot_draw_glyph (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)
+{
+ bool embolden = font->x_strength || font->y_strength;
+ hb_outline_t outline;
+
+ { // Need draw_session to be destructed before emboldening.
+ hb_draw_session_t draw_session (embolden ? hb_outline_recording_pen_get_funcs () : draw_funcs,
+ embolden ? &outline : draw_data, font->slant_xy);
+ if (!font->face->table.glyf->get_path (font, glyph, draw_session))
+#ifndef HB_NO_CFF
+ if (!font->face->table.cff1->get_path (font, glyph, draw_session))
+ if (!font->face->table.cff2->get_path (font, glyph, draw_session))
+#endif
+ {}
+ }
+
+ if (embolden)
+ {
+ float x_shift = font->embolden_in_place ? 0 : (float) font->x_strength / 2;
+ float y_shift = (float) font->y_strength / 2;
+ if (font->x_scale < 0) x_shift = -x_shift;
+ if (font->y_scale < 0) y_shift = -y_shift;
+ outline.embolden (font->x_strength, font->y_strength,
+ x_shift, y_shift);
+
+ outline.replay (draw_funcs, draw_data);
+ }
+}
+#endif
+
+#ifndef HB_NO_PAINT
+static void
+hb_ot_paint_glyph (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_paint_funcs_t *paint_funcs, void *paint_data,
+ unsigned int palette,
+ hb_color_t foreground,
+ 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_COLOR
+ if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return;
+ if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
+#ifndef HB_NO_OT_FONT_BITMAP
+ if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
+ if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
+#endif
+#endif
+ if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
#ifndef HB_NO_CFF
- if (font->face->table.cff1->get_path (font, glyph, draw_session)) return;
- if (font->face->table.cff2->get_path (font, glyph, draw_session)) return;
+ if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
+ if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
#endif
}
#endif
@@ -462,7 +576,11 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
#endif
#ifndef HB_NO_DRAW
- hb_font_funcs_set_glyph_shape_func (funcs, hb_ot_get_glyph_shape, nullptr, nullptr);
+ hb_font_funcs_set_draw_glyph_func (funcs, hb_ot_draw_glyph, nullptr, nullptr);
+#endif
+
+#ifndef HB_NO_PAINT
+ hb_font_funcs_set_paint_glyph_func (funcs, hb_ot_paint_glyph, nullptr, nullptr);
#endif
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh
index dea2b7e29a..a86cc3c311 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh
@@ -156,6 +156,7 @@ struct hdmx
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
!hb_unsigned_mul_overflows (numRecords, sizeDeviceRecord) &&
+ min_size + numRecords * sizeDeviceRecord > numRecords * sizeDeviceRecord &&
sizeDeviceRecord >= DeviceRecord::min_size &&
c->check_range (this, get_size ()));
}
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 20991aab2b..798e82da6c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh
@@ -97,6 +97,7 @@ struct head
* entire font as HBUINT32, then store
* 0xB1B0AFBAu - sum. */
HBUINT32 magicNumber; /* Set to 0x5F0F3CF5u. */
+ public:
HBUINT16 flags; /* Bit 0: Baseline for font at y=0;
* Bit 1: Left sidebearing point at x=0;
* Bit 2: Instructions may depend on point size;
@@ -141,6 +142,7 @@ struct head
* encoded in the cmap subtables represent proper
* support for those code points.
* Bit 15: Reserved, set to 0. */
+ protected:
HBUINT16 unitsPerEm; /* Valid range is from 16 to 16384. This value
* should be a power of 2 for fonts that have
* TrueType outlines. */
@@ -148,10 +150,12 @@ struct head
January 1, 1904. 64-bit integer */
LONGDATETIME modified; /* Number of seconds since 12:00 midnight,
January 1, 1904. 64-bit integer */
+ public:
HBINT16 xMin; /* For all glyph bounding boxes. */
HBINT16 yMin; /* For all glyph bounding boxes. */
HBINT16 xMax; /* For all glyph bounding boxes. */
HBINT16 yMax; /* For all glyph bounding boxes. */
+ protected:
HBUINT16 macStyle; /* Bit 0: Bold (if set to 1);
* Bit 1: Italic (if set to 1)
* Bit 2: Underline (if set to 1)
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 96a394ba42..16eb1eb912 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
@@ -31,6 +31,7 @@
#include "hb-ot-maxp-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-var-hvar-table.hh"
+#include "hb-ot-var-mvar-table.hh"
#include "hb-ot-metrics.hh"
/*
@@ -73,13 +74,15 @@ struct hmtxvmtx
return_trace (true);
}
- const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>>* get_mtx_map (const hb_subset_plan_t *plan) const
- { return T::is_horizontal ? plan->hmtx_map : plan->vmtx_map; }
+ const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>>* get_mtx_map (const hb_subset_plan_t *plan) const
+ { return T::is_horizontal ? &plan->hmtx_map : &plan->vmtx_map; }
- bool subset_update_header (hb_subset_plan_t *plan,
- unsigned int num_hmetrics) const
+ bool subset_update_header (hb_subset_context_t *c,
+ unsigned int num_hmetrics,
+ const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map,
+ const hb_map_t *bounds_map) const
{
- hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
+ hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (c->plan->source, H::tableTag);
hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
hb_blob_destroy (src_blob);
@@ -91,7 +94,56 @@ struct hmtxvmtx
H *table = (H *) hb_blob_get_data (dest_blob, &length);
table->numberOfLongMetrics = num_hmetrics;
- bool result = plan->add_table (H::tableTag, dest_blob);
+#ifndef HB_NO_VAR
+ if (c->plan->normalized_coords)
+ {
+ auto &MVAR = *c->plan->source->table.MVAR;
+ if (T::is_horizontal)
+ {
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE, caretSlopeRise);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN, caretSlopeRun);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET, caretOffset);
+ }
+ else
+ {
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_RISE, caretSlopeRise);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_RUN, caretSlopeRun);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET, caretOffset);
+ }
+
+ int min_lsb = 0x7FFF;
+ int min_rsb = 0x7FFF;
+ int max_extent = -0x7FFF;
+ unsigned max_adv = 0;
+ for (const auto _ : *mtx_map)
+ {
+ hb_codepoint_t gid = _.first;
+ unsigned adv = _.second.first;
+ int lsb = _.second.second;
+ max_adv = hb_max (max_adv, adv);
+
+ if (bounds_map->has (gid))
+ {
+ unsigned bound_width = bounds_map->get (gid);
+ int rsb = adv - lsb - bound_width;
+ int extent = lsb + bound_width;
+ min_lsb = hb_min (min_lsb, lsb);
+ min_rsb = hb_min (min_rsb, rsb);
+ max_extent = hb_max (max_extent, extent);
+ }
+ }
+
+ table->advanceMax = max_adv;
+ if (!bounds_map->is_empty ())
+ {
+ table->minLeadingBearing = min_lsb;
+ table->minTrailingBearing = min_rsb;
+ table->maxExtent = max_extent;
+ }
+ }
+#endif
+
+ bool result = c->plan->add_table (H::tableTag, dest_blob);
hb_blob_destroy (dest_blob);
return result;
@@ -132,7 +184,7 @@ struct hmtxvmtx
accelerator_t _mtx (c->plan->source);
unsigned num_long_metrics;
- const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *mtx_map = get_mtx_map (c->plan);
+ const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map = get_mtx_map (c->plan);
{
/* Determine num_long_metrics to encode. */
auto& plan = c->plan;
@@ -169,7 +221,8 @@ struct hmtxvmtx
return_trace (false);
// Amend header num hmetrics
- if (unlikely (!subset_update_header (c->plan, num_long_metrics)))
+ if (unlikely (!subset_update_header (c, num_long_metrics, mtx_map,
+ T::is_horizontal ? &c->plan->bounds_width_map : &c->plan->bounds_height_map)))
return_trace (false);
return_trace (true);
@@ -291,8 +344,6 @@ struct hmtxvmtx
/* num_bearings <= glyph < num_glyphs;
* num_bearings <= num_advances */
- /* TODO Optimize */
-
if (num_bearings == num_advances)
return get_advance_without_var_unscaled (num_bearings - 1);
@@ -315,7 +366,7 @@ struct hmtxvmtx
if (var_table.get_length ())
return advance + roundf (var_table->get_advance_delta_unscaled (glyph,
font->coords, font->num_coords,
- store_cache)); // TODO Optimize?!
+ store_cache));
return _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
#else
@@ -340,19 +391,17 @@ struct hmtxvmtx
/* get advance: when no variations, call get_advance_without_var_unscaled.
* when there're variations, get advance value from mtx_map in subset_plan*/
unsigned get_new_gid_advance_unscaled (const hb_subset_plan_t *plan,
- const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *mtx_map,
+ const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map,
unsigned new_gid,
const accelerator_t &_mtx) const
{
- if (mtx_map->is_empty () ||
- (new_gid == 0 && !mtx_map->has (new_gid)))
+ if (mtx_map->is_empty ())
{
hb_codepoint_t old_gid = 0;
return plan->old_gid_for_new_gid (new_gid, &old_gid) ?
_mtx.get_advance_without_var_unscaled (old_gid) : 0;
}
- else
- { return mtx_map->get (new_gid).first; }
+ return mtx_map->get (new_gid).first;
}
protected:
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 0f424f5aa6..b53f2e9276 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh
@@ -44,42 +44,6 @@ using OT::Layout::Common::RangeRecord;
using OT::Layout::SmallTypes;
using OT::Layout::MediumTypes;
-#ifndef HB_MAX_NESTING_LEVEL
-#define HB_MAX_NESTING_LEVEL 64
-#endif
-#ifndef HB_MAX_CONTEXT_LENGTH
-#define HB_MAX_CONTEXT_LENGTH 64
-#endif
-#ifndef HB_CLOSURE_MAX_STAGES
-/*
- * The maximum number of times a lookup can be applied during shaping.
- * Used to limit the number of iterations of the closure algorithm.
- * This must be larger than the number of times add_gsub_pause() is
- * called in a collect_features call of any shaper.
- */
-#define HB_CLOSURE_MAX_STAGES 12
-#endif
-
-#ifndef HB_MAX_SCRIPTS
-#define HB_MAX_SCRIPTS 500
-#endif
-
-#ifndef HB_MAX_LANGSYS
-#define HB_MAX_LANGSYS 2000
-#endif
-
-#ifndef HB_MAX_LANGSYS_FEATURE_COUNT
-#define HB_MAX_LANGSYS_FEATURE_COUNT 50000
-#endif
-
-#ifndef HB_MAX_FEATURE_INDICES
-#define HB_MAX_FEATURE_INDICES 1500
-#endif
-
-#ifndef HB_MAX_LOOKUP_VISIT_COUNT
-#define HB_MAX_LOOKUP_VISIT_COUNT 35000
-#endif
-
namespace OT {
@@ -192,19 +156,19 @@ struct hb_subset_layout_context_t :
{
if (tag_ == HB_OT_TAG_GSUB)
{
- lookup_index_map = c_->plan->gsub_lookups;
- script_langsys_map = c_->plan->gsub_langsys;
- feature_index_map = c_->plan->gsub_features;
- feature_substitutes_map = c_->plan->gsub_feature_substitutes_map;
- feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gsub_feature_record_cond_idx_map;
+ lookup_index_map = &c_->plan->gsub_lookups;
+ script_langsys_map = &c_->plan->gsub_langsys;
+ feature_index_map = &c_->plan->gsub_features;
+ feature_substitutes_map = &c_->plan->gsub_feature_substitutes_map;
+ feature_record_cond_idx_map = c_->plan->user_axes_location.is_empty () ? nullptr : &c_->plan->gsub_feature_record_cond_idx_map;
}
else
{
- lookup_index_map = c_->plan->gpos_lookups;
- script_langsys_map = c_->plan->gpos_langsys;
- feature_index_map = c_->plan->gpos_features;
- feature_substitutes_map = c_->plan->gpos_feature_substitutes_map;
- feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gpos_feature_record_cond_idx_map;
+ lookup_index_map = &c_->plan->gpos_lookups;
+ script_langsys_map = &c_->plan->gpos_langsys;
+ feature_index_map = &c_->plan->gpos_features;
+ feature_substitutes_map = &c_->plan->gpos_feature_substitutes_map;
+ feature_record_cond_idx_map = c_->plan->user_axes_location.is_empty () ? nullptr : &c_->plan->gpos_feature_record_cond_idx_map;
}
}
@@ -1181,7 +1145,7 @@ struct Script
{
TRACE_SUBSET (this);
if (!l->visitScript ()) return_trace (false);
- if (tag && !c->plan->layout_scripts->has (*tag))
+ if (tag && !c->plan->layout_scripts.has (*tag))
return false;
auto *out = c->serializer->start_embed (*this);
@@ -1389,7 +1353,7 @@ struct Lookup
// Generally we shouldn't end up with an empty lookup as we pre-prune them during the planning
// phase, but it can happen in rare cases such as when during closure subtable is considered
// degenerate (see: https://github.com/harfbuzz/harfbuzz/issues/3853)
- return true;
+ return_trace (true);
}
template <typename TSubTable>
@@ -1568,7 +1532,7 @@ struct ClassDefFormat1_3
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
+ const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
@@ -1813,7 +1777,7 @@ struct ClassDefFormat2_4
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
+ const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
const hb_set_t &glyph_set = *c->plan->glyphset_gsub ();
hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
@@ -2269,7 +2233,7 @@ struct VarRegionAxis
{
float evaluate (int coord) const
{
- int start = startCoord, peak = peakCoord, end = endCoord;
+ int start = startCoord.to_int (), peak = peakCoord.to_int (), end = endCoord.to_int ();
/* TODO Move these to sanitize(). */
if (unlikely (start > peak || peak > end))
@@ -2389,6 +2353,9 @@ struct VarRegionList
struct VarData
{
+ unsigned int get_item_count () const
+ { return itemCount; }
+
unsigned int get_region_index_count () const
{ return regionIndices.len; }
@@ -2794,6 +2761,29 @@ struct VariationStore
return_trace (true);
}
+ VariationStore *copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->start_embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ hb_vector_t <hb_inc_bimap_t> inner_maps;
+ unsigned count = dataSets.len;
+ for (unsigned i = 0; i < count; i++)
+ {
+ hb_inc_bimap_t *map = inner_maps.push ();
+ auto &data = this+dataSets[i];
+
+ unsigned itemCount = data.get_item_count ();
+ for (unsigned j = 0; j < itemCount; j++)
+ map->add (j);
+ }
+
+ if (unlikely (!out->serialize (c, this, inner_maps))) return_trace (nullptr);
+
+ return_trace (out);
+ }
+
bool subset (hb_subset_context_t *c, const hb_array_t<const hb_inc_bimap_t> &inner_maps) const
{
TRACE_SUBSET (this);
@@ -2874,7 +2864,7 @@ struct ConditionFormat1
auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (false);
- const hb_map_t *index_map = c->plan->axes_index_map;
+ const hb_map_t *index_map = &c->plan->axes_index_map;
if (index_map->is_empty ()) return_trace (true);
if (!index_map->has (axisIndex))
@@ -2899,8 +2889,8 @@ struct ConditionFormat1
{
// add axisIndex->value into the hashmap so we can check if the record is
// unique with variations
- int16_t min_val = filterRangeMinValue;
- int16_t max_val = filterRangeMaxValue;
+ int16_t min_val = filterRangeMinValue.to_int ();
+ int16_t max_val = filterRangeMaxValue.to_int ();
hb_codepoint_t val = (max_val << 16) + min_val;
condition_map->set (axisIndex, val);
@@ -2912,7 +2902,7 @@ struct ConditionFormat1
int v = c->axes_location->get (axis_tag);
//condition not met, drop the entire record
- if (v < filterRangeMinValue || v > filterRangeMaxValue)
+ if (v < filterRangeMinValue.to_int () || v > filterRangeMaxValue.to_int ())
return DROP_RECORD_WITH_VAR;
//axis pinned and condition met, drop the condition
@@ -2922,7 +2912,7 @@ struct ConditionFormat1
bool evaluate (const int *coords, unsigned int coord_len) const
{
int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
- return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
+ return filterRangeMinValue.to_int () <= coord && coord <= filterRangeMaxValue.to_int ();
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2962,8 +2952,8 @@ struct Condition
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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 ());
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 a84edef162..c8a2cf817a 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
@@ -29,890 +29,6 @@
#ifndef HB_OT_LAYOUT_GDEF_TABLE_HH
#define HB_OT_LAYOUT_GDEF_TABLE_HH
-#include "hb-ot-layout-common.hh"
-
-#include "hb-font.hh"
-
-
-namespace OT {
-
-
-/*
- * Attachment List Table
- */
-
-/* Array of contour point indices--in increasing numerical order */
-struct AttachPoint : Array16Of<HBUINT16>
-{
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
-
- return_trace (out->serialize (c->serializer, + iter ()));
- }
-};
-
-struct AttachList
-{
- unsigned int get_attach_points (hb_codepoint_t glyph_id,
- unsigned int start_offset,
- unsigned int *point_count /* IN/OUT */,
- unsigned int *point_array /* OUT */) const
- {
- unsigned int index = (this+coverage).get_coverage (glyph_id);
- if (index == NOT_COVERED)
- {
- if (point_count)
- *point_count = 0;
- return 0;
- }
-
- const AttachPoint &points = this+attachPoint[index];
-
- if (point_count)
- {
- + points.as_array ().sub_array (start_offset, point_count)
- | hb_sink (hb_array (point_array, *point_count))
- ;
- }
-
- return points.len;
- }
-
- 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);
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + hb_zip (this+coverage, attachPoint)
- | hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->attachPoint, 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) && attachPoint.sanitize (c, this));
- }
-
- protected:
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table -- from
- * beginning of AttachList table */
- Array16OfOffset16To<AttachPoint>
- attachPoint; /* Array of AttachPoint tables
- * in Coverage Index order */
- public:
- DEFINE_SIZE_ARRAY (4, attachPoint);
-};
-
-/*
- * Ligature Caret Table
- */
-
-struct CaretValueFormat1
-{
- friend struct CaretValue;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (true);
- }
-
- private:
- hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
- {
- return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- protected:
- HBUINT16 caretValueFormat; /* Format identifier--format = 1 */
- FWORD coordinate; /* X or Y value, in design units */
- public:
- DEFINE_SIZE_STATIC (4);
-};
-
-struct CaretValueFormat2
-{
- friend struct CaretValue;
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- return_trace (true);
- }
-
- private:
- hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
- {
- hb_position_t x, y;
- font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y);
- return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- protected:
- HBUINT16 caretValueFormat; /* Format identifier--format = 2 */
- HBUINT16 caretValuePoint; /* Contour point index on glyph */
- public:
- DEFINE_SIZE_STATIC (4);
-};
-
-struct CaretValueFormat3
-{
- friend struct CaretValue;
-
- hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,
- const VariationStore &var_store) const
- {
- return HB_DIRECTION_IS_HORIZONTAL (direction) ?
- font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
- font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
- if (!c->serializer->embed (caretValueFormat)) return_trace (false);
- if (!c->serializer->embed (coordinate)) return_trace (false);
-
- unsigned varidx = (this+deviceTable).get_variation_index ();
- if (c->plan->layout_variation_idx_delta_map->has (varidx))
- {
- int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (varidx));
- if (delta != 0)
- {
- if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
- return_trace (false);
- }
- }
-
- if (c->plan->all_axes_pinned)
- return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
-
- if (!c->serializer->embed (deviceTable))
- return_trace (false);
-
- return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out),
- hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map));
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- { (this+deviceTable).collect_variation_indices (c); }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
- }
-
- protected:
- HBUINT16 caretValueFormat; /* Format identifier--format = 3 */
- FWORD coordinate; /* X or Y value, in design units */
- Offset16To<Device>
- deviceTable; /* Offset to Device table for X or Y
- * value--from beginning of CaretValue
- * table */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-
-struct CaretValue
-{
- hb_position_t get_caret_value (hb_font_t *font,
- hb_direction_t direction,
- hb_codepoint_t glyph_id,
- const VariationStore &var_store) const
- {
- switch (u.format) {
- case 1: return u.format1.get_caret_value (font, direction);
- case 2: return u.format2.get_caret_value (font, direction, glyph_id);
- case 3: return u.format3.get_caret_value (font, direction, var_store);
- default:return 0;
- }
- }
-
- 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)...));
- case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- switch (u.format) {
- case 1:
- case 2:
- return;
- case 3:
- u.format3.collect_variation_indices (c);
- return;
- default: return;
- }
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!u.format.sanitize (c)) return_trace (false);
- switch (u.format) {
- case 1: return_trace (u.format1.sanitize (c));
- case 2: return_trace (u.format2.sanitize (c));
- case 3: return_trace (u.format3.sanitize (c));
- default:return_trace (true);
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- CaretValueFormat1 format1;
- CaretValueFormat2 format2;
- CaretValueFormat3 format3;
- } u;
- public:
- DEFINE_SIZE_UNION (2, format);
-};
-
-struct LigGlyph
-{
- unsigned get_lig_carets (hb_font_t *font,
- hb_direction_t direction,
- hb_codepoint_t glyph_id,
- const VariationStore &var_store,
- unsigned start_offset,
- unsigned *caret_count /* IN/OUT */,
- hb_position_t *caret_array /* OUT */) const
- {
- if (caret_count)
- {
- + carets.as_array ().sub_array (start_offset, caret_count)
- | hb_map (hb_add (this))
- | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); })
- | hb_sink (hb_array (caret_array, *caret_count))
- ;
- }
-
- return carets.len;
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- + hb_iter (carets)
- | hb_apply (subset_offset_array (c, out->carets, this))
- ;
-
- return_trace (bool (out->carets));
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- for (const Offset16To<CaretValue>& offset : carets.iter ())
- (this+offset).collect_variation_indices (c);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (carets.sanitize (c, this));
- }
-
- protected:
- Array16OfOffset16To<CaretValue>
- carets; /* Offset array of CaretValue tables
- * --from beginning of LigGlyph table
- * --in increasing coordinate order */
- public:
- DEFINE_SIZE_ARRAY (2, carets);
-};
-
-struct LigCaretList
-{
- unsigned int get_lig_carets (hb_font_t *font,
- hb_direction_t direction,
- hb_codepoint_t glyph_id,
- const VariationStore &var_store,
- unsigned int start_offset,
- unsigned int *caret_count /* IN/OUT */,
- hb_position_t *caret_array /* OUT */) const
- {
- unsigned int index = (this+coverage).get_coverage (glyph_id);
- if (index == NOT_COVERED)
- {
- if (caret_count)
- *caret_count = 0;
- return 0;
- }
- const LigGlyph &lig_glyph = this+ligGlyph[index];
- return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_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);
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + hb_zip (this+coverage, ligGlyph)
- | hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->ligGlyph, this), hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
- return_trace (bool (new_coverage));
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+coverage, ligGlyph)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); })
- ;
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
- }
-
- protected:
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of LigCaretList table */
- Array16OfOffset16To<LigGlyph>
- ligGlyph; /* Array of LigGlyph tables
- * in Coverage Index order */
- public:
- DEFINE_SIZE_ARRAY (4, ligGlyph);
-};
-
-
-struct MarkGlyphSetsFormat1
-{
- bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
- { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- bool ret = true;
- for (const Offset32To<Coverage>& offset : coverage.iter ())
- {
- auto *o = out->coverage.serialize_append (c->serializer);
- if (unlikely (!o))
- {
- ret = false;
- break;
- }
-
- //not using o->serialize_subset (c, offset, this, out) here because
- //OTS doesn't allow null offset.
- //See issue: https://github.com/khaledhosny/ots/issues/172
- c->serializer->push ();
- c->dispatch (this+offset);
- c->serializer->add_link (*o, c->serializer->pop_pack ());
- }
-
- return_trace (ret && out->coverage.len);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Array16Of<Offset32To<Coverage>>
- coverage; /* Array of long offsets to mark set
- * coverage tables */
- public:
- DEFINE_SIZE_ARRAY (4, coverage);
-};
-
-struct MarkGlyphSets
-{
- bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
- {
- switch (u.format) {
- case 1: return u.format1.covers (set_index, glyph_id);
- default:return false;
- }
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- switch (u.format) {
- case 1: return_trace (u.format1.subset (c));
- default:return_trace (false);
- }
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!u.format.sanitize (c)) return_trace (false);
- switch (u.format) {
- case 1: return_trace (u.format1.sanitize (c));
- default:return_trace (true);
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkGlyphSetsFormat1 format1;
- } u;
- public:
- DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * GDEF -- Glyph Definition
- * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef
- */
-
-
-template <typename Types>
-struct GDEFVersion1_2
-{
- friend struct GDEF;
-
- protected:
- FixedVersion<>version; /* Version of the GDEF table--currently
- * 0x00010003u */
- typename Types::template OffsetTo<ClassDef>
- glyphClassDef; /* Offset to class definition table
- * for glyph type--from beginning of
- * GDEF header (may be Null) */
- typename Types::template OffsetTo<AttachList>
- attachList; /* Offset to list of glyphs with
- * attachment points--from beginning
- * of GDEF header (may be Null) */
- typename Types::template OffsetTo<LigCaretList>
- ligCaretList; /* Offset to list of positioning points
- * for ligature carets--from beginning
- * of GDEF header (may be Null) */
- typename Types::template OffsetTo<ClassDef>
- markAttachClassDef; /* Offset to class definition table for
- * mark attachment type--from beginning
- * of GDEF header (may be Null) */
- typename Types::template OffsetTo<MarkGlyphSets>
- markGlyphSetsDef; /* Offset to the table of mark set
- * definitions--from beginning of GDEF
- * header (may be NULL). Introduced
- * in version 0x00010002. */
- Offset32To<VariationStore>
- varStore; /* Offset to the table of Item Variation
- * Store--from beginning of GDEF
- * header (may be NULL). Introduced
- * in version 0x00010003. */
- public:
- DEFINE_SIZE_MIN (4 + 4 * Types::size);
-
- unsigned int get_size () const
- {
- return min_size +
- (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
- (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (version.sanitize (c) &&
- glyphClassDef.sanitize (c, this) &&
- attachList.sanitize (c, this) &&
- ligCaretList.sanitize (c, this) &&
- markAttachClassDef.sanitize (c, this) &&
- (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
- (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (*this);
- if (unlikely (!out)) return_trace (false);
-
- bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
- bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
- bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
- bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
-
- bool subset_markglyphsetsdef = false;
- if (version.to_int () >= 0x00010002u)
- {
- subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
- }
-
- bool subset_varstore = false;
- if (version.to_int () >= 0x00010003u)
- {
- if (c->plan->all_axes_pinned)
- out->varStore = 0;
- else
- subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ());
- }
-
- if (subset_varstore)
- {
- out->version.minor = 3;
- } else if (subset_markglyphsetsdef) {
- out->version.minor = 2;
- } else {
- out->version.minor = 0;
- }
-
- return_trace (subset_glyphclassdef || subset_attachlist ||
- subset_ligcaretlist || subset_markattachclassdef ||
- (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||
- (out->version.to_int () >= 0x00010003u && subset_varstore));
- }
-};
-
-struct GDEF
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
-
- enum GlyphClasses {
- UnclassifiedGlyph = 0,
- BaseGlyph = 1,
- LigatureGlyph = 2,
- MarkGlyph = 3,
- ComponentGlyph = 4
- };
-
- unsigned int get_size () const
- {
- switch (u.version.major) {
- case 1: return u.version1.get_size ();
-#ifndef HB_NO_BEYOND_64K
- case 2: return u.version2.get_size ();
-#endif
- default: return u.version.static_size;
- }
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (unlikely (!u.version.sanitize (c))) return_trace (false);
- switch (u.version.major) {
- case 1: return_trace (u.version1.sanitize (c));
-#ifndef HB_NO_BEYOND_64K
- case 2: return_trace (u.version2.sanitize (c));
-#endif
- default: return_trace (true);
- }
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- switch (u.version.major) {
- case 1: return u.version1.subset (c);
-#ifndef HB_NO_BEYOND_64K
- case 2: return u.version2.subset (c);
-#endif
- default: return false;
- }
- }
-
- bool has_glyph_classes () const
- {
- switch (u.version.major) {
- case 1: return u.version1.glyphClassDef != 0;
-#ifndef HB_NO_BEYOND_64K
- case 2: return u.version2.glyphClassDef != 0;
-#endif
- default: return false;
- }
- }
- const ClassDef &get_glyph_class_def () const
- {
- switch (u.version.major) {
- case 1: return this+u.version1.glyphClassDef;
-#ifndef HB_NO_BEYOND_64K
- case 2: return this+u.version2.glyphClassDef;
-#endif
- default: return Null(ClassDef);
- }
- }
- bool has_attach_list () const
- {
- switch (u.version.major) {
- case 1: return u.version1.attachList != 0;
-#ifndef HB_NO_BEYOND_64K
- case 2: return u.version2.attachList != 0;
-#endif
- default: return false;
- }
- }
- const AttachList &get_attach_list () const
- {
- switch (u.version.major) {
- case 1: return this+u.version1.attachList;
-#ifndef HB_NO_BEYOND_64K
- case 2: return this+u.version2.attachList;
-#endif
- default: return Null(AttachList);
- }
- }
- bool has_lig_carets () const
- {
- switch (u.version.major) {
- case 1: return u.version1.ligCaretList != 0;
-#ifndef HB_NO_BEYOND_64K
- case 2: return u.version2.ligCaretList != 0;
-#endif
- default: return false;
- }
- }
- const LigCaretList &get_lig_caret_list () const
- {
- switch (u.version.major) {
- case 1: return this+u.version1.ligCaretList;
-#ifndef HB_NO_BEYOND_64K
- case 2: return this+u.version2.ligCaretList;
-#endif
- default: return Null(LigCaretList);
- }
- }
- bool has_mark_attachment_types () const
- {
- switch (u.version.major) {
- case 1: return u.version1.markAttachClassDef != 0;
-#ifndef HB_NO_BEYOND_64K
- case 2: return u.version2.markAttachClassDef != 0;
-#endif
- default: return false;
- }
- }
- const ClassDef &get_mark_attach_class_def () const
- {
- switch (u.version.major) {
- case 1: return this+u.version1.markAttachClassDef;
-#ifndef HB_NO_BEYOND_64K
- case 2: return this+u.version2.markAttachClassDef;
-#endif
- default: return Null(ClassDef);
- }
- }
- bool has_mark_glyph_sets () const
- {
- switch (u.version.major) {
- case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0;
-#ifndef HB_NO_BEYOND_64K
- case 2: return u.version2.markGlyphSetsDef != 0;
-#endif
- default: return false;
- }
- }
- const MarkGlyphSets &get_mark_glyph_sets () const
- {
- switch (u.version.major) {
- case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);
-#ifndef HB_NO_BEYOND_64K
- case 2: return this+u.version2.markGlyphSetsDef;
-#endif
- default: return Null(MarkGlyphSets);
- }
- }
- bool has_var_store () const
- {
- switch (u.version.major) {
- case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0;
-#ifndef HB_NO_BEYOND_64K
- case 2: return u.version2.varStore != 0;
-#endif
- default: return false;
- }
- }
- const VariationStore &get_var_store () const
- {
- switch (u.version.major) {
- case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore);
-#ifndef HB_NO_BEYOND_64K
- case 2: return this+u.version2.varStore;
-#endif
- default: return Null(VariationStore);
- }
- }
-
-
- bool has_data () const { return u.version.to_int (); }
- unsigned int get_glyph_class (hb_codepoint_t glyph) const
- { return get_glyph_class_def ().get_class (glyph); }
- void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
- { get_glyph_class_def ().collect_class (glyphs, klass); }
-
- unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
- { return get_mark_attach_class_def ().get_class (glyph); }
-
- unsigned int get_attach_points (hb_codepoint_t glyph_id,
- unsigned int start_offset,
- unsigned int *point_count /* IN/OUT */,
- unsigned int *point_array /* OUT */) const
- { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); }
-
- unsigned int get_lig_carets (hb_font_t *font,
- hb_direction_t direction,
- hb_codepoint_t glyph_id,
- unsigned int start_offset,
- unsigned int *caret_count /* IN/OUT */,
- hb_position_t *caret_array /* OUT */) const
- { return get_lig_caret_list ().get_lig_carets (font,
- direction, glyph_id, get_var_store(),
- start_offset, caret_count, caret_array); }
-
- bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
- { return get_mark_glyph_sets ().covers (set_index, glyph_id); }
-
- /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
- * glyph class and other bits, and high 8-bit the mark attachment type (if any).
- * Not to be confused with lookup_props which is very similar. */
- unsigned int get_glyph_props (hb_codepoint_t glyph) const
- {
- unsigned int klass = get_glyph_class (glyph);
-
- static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), "");
- static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), "");
- static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), "");
-
- switch (klass) {
- default: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
- case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
- case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
- case MarkGlyph:
- klass = get_mark_attachment_type (glyph);
- return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8);
- }
- }
-
- HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
- hb_face_t *face) const;
-
- struct accelerator_t
- {
- accelerator_t (hb_face_t *face)
- {
- table = hb_sanitize_context_t ().reference_table<GDEF> (face);
- if (unlikely (table->is_blocklisted (table.get_blob (), face)))
- {
- hb_blob_destroy (table.get_blob ());
- table = hb_blob_get_empty ();
- }
- }
- ~accelerator_t () { table.destroy (); }
-
- hb_blob_ptr_t<GDEF> table;
- };
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- { get_lig_caret_list ().collect_variation_indices (c); }
-
- void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
- hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const
- {
- if (!has_var_store ()) return;
- if (layout_variation_indices->is_empty ()) return;
-
- unsigned new_major = 0, new_minor = 0;
- unsigned last_major = (layout_variation_indices->get_min ()) >> 16;
- for (unsigned idx : layout_variation_indices->iter ())
- {
- uint16_t major = idx >> 16;
- if (major >= get_var_store ().get_sub_table_count ()) break;
- if (major != last_major)
- {
- new_minor = 0;
- ++new_major;
- }
-
- unsigned new_idx = (new_major << 16) + new_minor;
- if (!layout_variation_idx_delta_map->has (idx))
- continue;
- int delta = hb_second (layout_variation_idx_delta_map->get (idx));
-
- layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
- ++new_minor;
- last_major = major;
- }
- }
-
- protected:
- union {
- FixedVersion<> version; /* Version identifier */
- GDEFVersion1_2<SmallTypes> version1;
-#ifndef HB_NO_BEYOND_64K
- GDEFVersion1_2<MediumTypes> version2;
-#endif
- } u;
- public:
- DEFINE_SIZE_MIN (4);
-};
-
-struct GDEF_accelerator_t : GDEF::accelerator_t {
- GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {}
-};
-
-} /* namespace OT */
-
+#include "OT/Layout/GDEF/GDEF.hh"
#endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */
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 8fe987fc50..0cfa139a26 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
@@ -56,12 +56,17 @@ PosLookup::dispatch_recurse_func<hb_closure_lookups_context_t> (hb_closure_looku
template <>
inline bool PosLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
- const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
+ auto *gpos = c->face->table.GPOS.get_relaxed ();
+ const PosLookup &l = gpos->table->get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
unsigned int saved_lookup_index = c->lookup_index;
c->set_lookup_index (lookup_index);
c->set_lookup_props (l.get_props ());
- bool ret = l.dispatch (c);
+
+ bool ret = false;
+ auto *accel = gpos->get_accel (lookup_index);
+ ret = accel && accel->apply (c, l.get_subtable_count (), false);
+
c->set_lookup_index (saved_lookup_index);
c->set_lookup_props (saved_lookup_props);
return ret;
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 50301ff1d9..fd8a68be02 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
@@ -69,12 +69,17 @@ SubstLookup::dispatch_recurse_func<hb_closure_lookups_context_t> (hb_closure_loo
template <>
inline bool SubstLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
- const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
+ auto *gsub = c->face->table.GSUB.get_relaxed ();
+ const SubstLookup &l = gsub->table->get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
unsigned int saved_lookup_index = c->lookup_index;
c->set_lookup_index (lookup_index);
c->set_lookup_props (l.get_props ());
- bool ret = l.dispatch (c);
+
+ bool ret = false;
+ auto *accel = gsub->get_accel (lookup_index);
+ ret = accel && accel->apply (c, l.get_subtable_count (), false);
+
c->set_lookup_index (saved_lookup_index);
c->set_lookup_props (saved_lookup_props);
return ret;
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 04ccefd108..10cc105de4 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh
@@ -115,7 +115,7 @@ struct hb_closure_context_t :
return true;
}
- hb_set_clear (done_lookups_glyph_set->get (lookup_index));
+ done_lookups_glyph_set->get (lookup_index)->clear ();
}
hb_set_t *covered_glyph_set = done_lookups_glyph_set->get (lookup_index);
@@ -532,6 +532,30 @@ struct hb_ot_apply_context_t :
may_skip (const hb_glyph_info_t &info) const
{ return matcher.may_skip (c, info); }
+ enum match_t {
+ MATCH,
+ NOT_MATCH,
+ SKIP
+ };
+
+ match_t match (hb_glyph_info_t &info)
+ {
+ matcher_t::may_skip_t skip = matcher.may_skip (c, info);
+ if (unlikely (skip == matcher_t::SKIP_YES))
+ return SKIP;
+
+ matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
+ if (match == matcher_t::MATCH_YES ||
+ (match == matcher_t::MATCH_MAYBE &&
+ skip == matcher_t::SKIP_NO))
+ return MATCH;
+
+ if (skip == matcher_t::SKIP_NO)
+ return NOT_MATCH;
+
+ return SKIP;
+ }
+
bool next (unsigned *unsafe_to = nullptr)
{
assert (num_items > 0);
@@ -543,27 +567,22 @@ struct hb_ot_apply_context_t :
while ((signed) idx < stop)
{
idx++;
- hb_glyph_info_t &info = c->buffer->info[idx];
-
- matcher_t::may_skip_t skip = matcher.may_skip (c, info);
- if (unlikely (skip == matcher_t::SKIP_YES))
- continue;
-
- matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
- if (match == matcher_t::MATCH_YES ||
- (match == matcher_t::MATCH_MAYBE &&
- skip == matcher_t::SKIP_NO))
- {
- num_items--;
- advance_glyph_data ();
- return true;
- }
-
- if (skip == matcher_t::SKIP_NO)
+ switch (match (c->buffer->info[idx]))
{
- if (unsafe_to)
- *unsafe_to = idx + 1;
- return false;
+ case MATCH:
+ {
+ num_items--;
+ advance_glyph_data ();
+ return true;
+ }
+ case NOT_MATCH:
+ {
+ if (unsafe_to)
+ *unsafe_to = idx + 1;
+ return false;
+ }
+ case SKIP:
+ continue;
}
}
if (unsafe_to)
@@ -581,27 +600,22 @@ struct hb_ot_apply_context_t :
while (idx > stop)
{
idx--;
- hb_glyph_info_t &info = c->buffer->out_info[idx];
-
- matcher_t::may_skip_t skip = matcher.may_skip (c, info);
- if (unlikely (skip == matcher_t::SKIP_YES))
- continue;
-
- matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
- if (match == matcher_t::MATCH_YES ||
- (match == matcher_t::MATCH_MAYBE &&
- skip == matcher_t::SKIP_NO))
- {
- num_items--;
- advance_glyph_data ();
- return true;
- }
-
- if (skip == matcher_t::SKIP_NO)
+ switch (match (c->buffer->out_info[idx]))
{
- if (unsafe_from)
- *unsafe_from = hb_max (1u, idx) - 1u;
- return false;
+ case MATCH:
+ {
+ num_items--;
+ advance_glyph_data ();
+ return true;
+ }
+ case NOT_MATCH:
+ {
+ if (unsafe_from)
+ *unsafe_from = hb_max (1u, idx) - 1u;
+ return false;
+ }
+ case SKIP:
+ continue;
}
}
if (unsafe_from)
@@ -698,6 +712,9 @@ struct hb_ot_apply_context_t :
uint32_t random_state = 1;
unsigned new_syllables = (unsigned) -1;
+ signed last_base = -1; // GPOS uses
+ unsigned last_base_until = 0; // GPOS uses
+
hb_ot_apply_context_t (unsigned int table_index_,
hb_font_t *font_,
hb_buffer_t *buffer_) :
@@ -736,7 +753,7 @@ struct hb_ot_apply_context_t :
iter_context.init (this, true);
}
- void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
+ void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; last_base = -1; last_base_until = 0; 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 (); }
@@ -944,8 +961,6 @@ struct hb_accelerate_subtables_context_t :
hb_set_digest_t digest;
};
- typedef hb_vector_t<hb_applicable_t> array_t;
-
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
template <typename T>
auto cache_cost (const T &obj, hb_priority<1>) HB_AUTO_RETURN ( obj.cache_cost () )
@@ -957,17 +972,15 @@ struct hb_accelerate_subtables_context_t :
template <typename T>
return_t dispatch (const T &obj)
{
- hb_applicable_t entry;
+ hb_applicable_t *entry = &array[i++];
- entry.init (obj,
- apply_to<T>
+ entry->init (obj,
+ apply_to<T>
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
- , apply_cached_to<T>
- , cache_func_to<T>
+ , apply_cached_to<T>
+ , cache_func_to<T>
#endif
- );
-
- array.push (entry);
+ );
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
/* Cache handling
@@ -979,9 +992,9 @@ struct hb_accelerate_subtables_context_t :
* and we allocate the cache opportunity to the costliest subtable.
*/
unsigned cost = cache_cost (obj, hb_prioritize);
- if (cost > cache_user_cost && !array.in_error ())
+ if (cost > cache_user_cost)
{
- cache_user_idx = array.length - 1;
+ cache_user_idx = i - 1;
cache_user_cost = cost;
}
#endif
@@ -990,10 +1003,11 @@ struct hb_accelerate_subtables_context_t :
}
static return_t default_return_value () { return hb_empty_t (); }
- hb_accelerate_subtables_context_t (array_t &array_) :
+ hb_accelerate_subtables_context_t (hb_applicable_t *array_) :
array (array_) {}
- array_t &array;
+ hb_applicable_t *array;
+ unsigned i = 0;
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
unsigned cache_user_idx = (unsigned) -1;
@@ -1538,18 +1552,19 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
intersected_glyphs_func_t intersected_glyphs_func,
void *cache)
{
- hb_set_t *covered_seq_indicies = hb_set_create ();
+ hb_set_t covered_seq_indicies;
+ hb_set_t pos_glyphs;
for (unsigned int i = 0; i < lookupCount; i++)
{
unsigned seqIndex = lookupRecord[i].sequenceIndex;
if (seqIndex >= inputCount) continue;
bool has_pos_glyphs = false;
- hb_set_t pos_glyphs;
- if (!hb_set_has (covered_seq_indicies, seqIndex))
+ if (!covered_seq_indicies.has (seqIndex))
{
has_pos_glyphs = true;
+ pos_glyphs.clear ();
if (seqIndex == 0)
{
switch (context_format) {
@@ -1578,7 +1593,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
}
}
- covered_seq_indicies->add (seqIndex);
+ covered_seq_indicies.add (seqIndex);
if (has_pos_glyphs) {
c->push_cur_active_glyphs () = std::move (pos_glyphs);
} else {
@@ -1589,12 +1604,10 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
if (context_format == ContextFormat::CoverageBasedContext)
endIndex += 1;
- c->recurse (lookupRecord[i].lookupListIndex, covered_seq_indicies, seqIndex, endIndex);
+ c->recurse (lookupRecord[i].lookupListIndex, &covered_seq_indicies, seqIndex, endIndex);
c->pop_cur_done_glyphs ();
}
-
- hb_set_destroy (covered_seq_indicies);
}
template <typename context_t>
@@ -1651,7 +1664,7 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
if (buffer->have_output)
c->buffer->sync_so_far ();
c->buffer->message (c->font,
- "recursing to lookup %u at %d",
+ "recursing to lookup %u at %u",
(unsigned) lookupRecord[i].lookupListIndex,
buffer->idx);
}
@@ -2224,7 +2237,7 @@ struct ContextFormat1_4
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->format = format;
- const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+ const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ hb_zip (this+coverage, ruleSet)
| hb_filter (glyphset, hb_first)
@@ -2461,7 +2474,7 @@ struct ContextFormat2_5
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;
+ 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 = -1, index = 0;
auto snapshot = c->serializer->snapshot();
@@ -2641,7 +2654,7 @@ struct ContextFormat3
}
const auto& 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;
+ const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (lookupCount), lookup_map);
@@ -2681,8 +2694,8 @@ struct Context
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
@@ -3305,7 +3318,7 @@ struct ChainContextFormat1_4
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->format = format;
- const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+ const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ hb_zip (this+coverage, ruleSet)
| hb_filter (glyphset, hb_first)
@@ -3541,7 +3554,7 @@ struct ChainContextFormat2_5
*/
struct ChainContextApplyLookupContext lookup_context = {
- {{cached && &backtrack_class_def == &input_class_def ? match_class_cached : match_class,
+ {{cached && &backtrack_class_def == &lookahead_class_def ? match_class_cached : match_class,
cached && &input_class_def == &lookahead_class_def ? match_class_cached : match_class,
cached ? match_class_cached : match_class}},
{&backtrack_class_def,
@@ -3585,7 +3598,7 @@ struct ChainContextFormat2_5
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;
+ 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 auto& _ : + hb_enumerate (ruleSet)
| hb_filter (input_klass_map, hb_first))
@@ -3827,7 +3840,7 @@ struct ChainContextFormat3
return_trace (false);
const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
- const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+ const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookup.len);
if (!lookupCount) return_trace (false);
@@ -3875,8 +3888,8 @@ struct ChainContext
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
@@ -3915,8 +3928,8 @@ struct ExtensionFormat1
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, this))) return c->no_dispatch_return_value ();
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 (), std::forward<Ts> (ds)...));
}
@@ -3994,8 +4007,8 @@ struct Extension
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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, std::forward<Ts> (ds)...));
default:return_trace (c->default_return_value ());
@@ -4017,35 +4030,50 @@ struct Extension
struct hb_ot_layout_lookup_accelerator_t
{
template <typename TLookup>
- void init (const TLookup &lookup)
+ static hb_ot_layout_lookup_accelerator_t *create (const TLookup &lookup)
{
- subtables.init ();
- hb_accelerate_subtables_context_t c_accelerate_subtables (subtables);
+ unsigned count = lookup.get_subtable_count ();
+
+ unsigned size = sizeof (hb_ot_layout_lookup_accelerator_t) -
+ HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
+ count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
+
+ /* The following is a calloc because when we are collecting subtables,
+ * some of them might be invalid and hence not collect; as a result,
+ * we might not fill in all the count entries of the subtables array.
+ * Zeroing it allows the set digest to gatekeep it without having to
+ * initialize it further. */
+ auto *thiz = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (1, size);
+ if (unlikely (!thiz))
+ return nullptr;
+
+ hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables);
lookup.dispatch (&c_accelerate_subtables);
- digest.init ();
- for (auto& subtable : hb_iter (subtables))
- digest.add (subtable.digest);
+ thiz->digest.init ();
+ for (auto& subtable : hb_iter (thiz->subtables, count))
+ thiz->digest.add (subtable.digest);
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
- cache_user_idx = c_accelerate_subtables.cache_user_idx;
- for (unsigned i = 0; i < subtables.length; i++)
- if (i != cache_user_idx)
- subtables[i].apply_cached_func = subtables[i].apply_func;
+ thiz->cache_user_idx = c_accelerate_subtables.cache_user_idx;
+ for (unsigned i = 0; i < count; i++)
+ if (i != thiz->cache_user_idx)
+ thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
#endif
+
+ return thiz;
}
- void fini () { subtables.fini (); }
bool may_have (hb_codepoint_t g) const
{ return digest.may_have (g); }
- bool apply (hb_ot_apply_context_t *c, bool use_cache) const
+ bool apply (hb_ot_apply_context_t *c, unsigned subtables_count, bool use_cache) const
{
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
if (use_cache)
{
return
- + hb_iter (subtables)
+ + hb_iter (hb_iter (subtables, subtables_count))
| hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply_cached (c); })
| hb_any
;
@@ -4054,7 +4082,7 @@ struct hb_ot_layout_lookup_accelerator_t
#endif
{
return
- + hb_iter (subtables)
+ + hb_iter (hb_iter (subtables, subtables_count))
| hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply (c); })
| hb_any
;
@@ -4081,10 +4109,10 @@ struct hb_ot_layout_lookup_accelerator_t
hb_set_digest_t digest;
private:
- hb_accelerate_subtables_context_t::array_t subtables;
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
unsigned cache_user_idx = (unsigned) -1;
#endif
+ hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
};
template <typename Types>
@@ -4142,8 +4170,11 @@ struct GSUBGPOSVersion1_2
bool subset (hb_subset_layout_context_t *c) const
{
TRACE_SUBSET (this);
- auto *out = c->subset_context->serializer->embed (*this);
- if (unlikely (!out)) return_trace (false);
+
+ auto *out = c->subset_context->serializer->start_embed (this);
+ if (unlikely (!c->subset_context->serializer->extend_min (out))) return_trace (false);
+
+ out->version = version;
typedef LookupOffsetList<TLookup, typename Types::HBUINT> TLookupList;
reinterpret_cast<typename Types::template OffsetTo<TLookupList> &> (out->lookupList)
@@ -4166,9 +4197,23 @@ struct GSUBGPOSVersion1_2
#ifndef HB_NO_VAR
if (version.to_int () >= 0x00010001u)
{
- bool ret = out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
+ auto snapshot = c->subset_context->serializer->snapshot ();
+ if (!c->subset_context->serializer->extend_min (&out->featureVars))
+ return_trace (false);
+
+ // TODO(qxliu76): the current implementation doesn't correctly handle feature variations
+ // that are dropped by instancing when the associated conditions don't trigger.
+ // Since partial instancing isn't yet supported this isn't an issue yet but will
+ // need to be fixed for partial instancing.
+
+
+
+ // if all axes are pinned all feature vars are dropped.
+ bool ret = !c->subset_context->plan->all_axes_pinned
+ && out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
if (!ret && version.major == 1)
{
+ c->subset_context->serializer->revert (snapshot);
out->version.major = 1;
out->version.minor = 0;
}
@@ -4430,28 +4475,47 @@ struct GSUBGPOS
this->lookup_count = table->get_lookup_count ();
- this->accels = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (this->lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
+ this->accels = (hb_atomic_ptr_t<hb_ot_layout_lookup_accelerator_t> *) hb_calloc (this->lookup_count, sizeof (*accels));
if (unlikely (!this->accels))
{
this->lookup_count = 0;
this->table.destroy ();
this->table = hb_blob_get_empty ();
}
-
- for (unsigned int i = 0; i < this->lookup_count; i++)
- this->accels[i].init (table->get_lookup (i));
}
~accelerator_t ()
{
for (unsigned int i = 0; i < this->lookup_count; i++)
- this->accels[i].fini ();
+ hb_free (this->accels[i]);
hb_free (this->accels);
this->table.destroy ();
}
+ hb_ot_layout_lookup_accelerator_t *get_accel (unsigned lookup_index) const
+ {
+ if (unlikely (lookup_index >= lookup_count)) return nullptr;
+
+ retry:
+ auto *accel = accels[lookup_index].get_acquire ();
+ if (unlikely (!accel))
+ {
+ accel = hb_ot_layout_lookup_accelerator_t::create (table->get_lookup (lookup_index));
+ if (unlikely (!accel))
+ return nullptr;
+
+ if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
+ {
+ hb_free (accel);
+ goto retry;
+ }
+ }
+
+ return accel;
+ }
+
hb_blob_ptr_t<T> table;
unsigned int lookup_count;
- hb_ot_layout_lookup_accelerator_t *accels;
+ hb_atomic_ptr_t<hb_ot_layout_lookup_accelerator_t> *accels;
};
protected:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
index e8091ec3e0..6c4055e046 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
@@ -500,8 +500,8 @@ hb_ot_layout_table_find_script (hb_face_t *face,
* @face: #hb_face_t to work upon
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_tags: Array of #hb_tag_t script tags
- * @script_index: (out): The index of the requested script tag
- * @chosen_script: (out): #hb_tag_t of the script tag requested
+ * @script_index: (out): The index of the chosen script
+ * @chosen_script: (out): #hb_tag_t of the chosen script
*
* Deprecated since 2.0.0
**/
@@ -531,8 +531,8 @@ hb_ot_layout_table_choose_script (hb_face_t *face,
*
* If the table does not have any of the requested scripts, then `DFLT`,
* `dflt`, and `latn` tags are tried in that order. If the table still does not
- * have any of these scripts, @script_index and @chosen_script are set to
- * #HB_OT_LAYOUT_NO_SCRIPT_INDEX.
+ * have any of these scripts, @script_index is set to
+ * #HB_OT_LAYOUT_NO_SCRIPT_INDEX and @chosen_script is set to #HB_TAG_NONE.
*
* Return value:
* `true` if one of the requested scripts is selected, `false` if a fallback
@@ -586,7 +586,7 @@ hb_ot_layout_table_select_script (hb_face_t *face,
if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
if (chosen_script)
- *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
+ *chosen_script = HB_TAG_NONE;
return false;
}
@@ -727,32 +727,35 @@ hb_ot_layout_script_find_language (hb_face_t *face,
/**
- * hb_ot_layout_script_select_language:
+ * hb_ot_layout_script_select_language2:
* @face: #hb_face_t to work upon
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag
* @language_count: The number of languages in the specified script
* @language_tags: The array of language tags
- * @language_index: (out): The index of the requested language
+ * @language_index: (out): The index of the chosen language
+ * @chosen_language: (out): #hb_tag_t of the chosen language
*
* 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.
*
* If none of the given language tags is found, `false` is returned and
- * @language_index is set to the default language index.
+ * @language_index is set to #HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX and
+ * @chosen_language is set to #HB_TAG_NONE.
*
* Return value: `true` if one of the given language tags is found, `false` otherwise
*
- * Since: 2.0.0
+ * Since: 7.0.0
**/
hb_bool_t
-hb_ot_layout_script_select_language (hb_face_t *face,
+hb_ot_layout_script_select_language2 (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_count,
const hb_tag_t *language_tags,
- unsigned int *language_index /* OUT */)
+ unsigned int *language_index /* OUT */,
+ hb_tag_t *chosen_language /* OUT */)
{
static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX), "");
const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
@@ -761,18 +764,61 @@ hb_ot_layout_script_select_language (hb_face_t *face,
for (i = 0; i < language_count; i++)
{
if (s.find_lang_sys_index (language_tags[i], language_index))
+ {
+ if (chosen_language)
+ *chosen_language = language_tags[i];
return true;
+ }
}
/* try finding 'dflt' */
if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
+ {
+ if (chosen_language)
+ *chosen_language = HB_OT_TAG_DEFAULT_LANGUAGE;
return false;
+ }
if (language_index)
*language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
+ if (chosen_language)
+ *chosen_language = HB_TAG_NONE;
return false;
}
+/**
+ * hb_ot_layout_script_select_language:
+ * @face: #hb_face_t to work upon
+ * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
+ * @script_index: The index of the requested script tag
+ * @language_count: The number of languages in the specified script
+ * @language_tags: The array of language tags
+ * @language_index: (out): The index of the requested language
+ *
+ * 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.
+ *
+ * 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
+ **/
+hb_bool_t
+hb_ot_layout_script_select_language (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int script_index,
+ unsigned int language_count,
+ const hb_tag_t *language_tags,
+ unsigned int *language_index /* OUT */)
+{
+ return hb_ot_layout_script_select_language2 (face, table_tag,
+ script_index,
+ language_count, language_tags,
+ language_index, nullptr);
+}
/**
* hb_ot_layout_language_get_required_feature_index:
@@ -1441,11 +1487,13 @@ hb_ot_layout_lookup_would_substitute (hb_face_t *face,
unsigned int glyphs_length,
hb_bool_t zero_context)
{
- if (unlikely (lookup_index >= face->table.GSUB->lookup_count)) return false;
+ auto &gsub = face->table.GSUB;
+ if (unlikely (lookup_index >= gsub->lookup_count)) return false;
OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
- const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
- return l.would_apply (&c, &face->table.GSUB->accels[lookup_index]);
+ const OT::SubstLookup& l = gsub->table->get_lookup (lookup_index);
+ auto *accel = gsub->get_accel (lookup_index);
+ return accel && l.would_apply (&c, accel);
}
@@ -1784,11 +1832,9 @@ struct GSUBProxy
typedef OT::SubstLookup Lookup;
GSUBProxy (hb_face_t *face) :
- table (*face->table.GSUB->table),
- accels (face->table.GSUB->accels) {}
+ accel (*face->table.GSUB) {}
- const GSUB &table;
- const OT::hb_ot_layout_lookup_accelerator_t *accels;
+ const GSUB::accelerator_t &accel;
};
struct GPOSProxy
@@ -1798,17 +1844,16 @@ struct GPOSProxy
typedef OT::PosLookup Lookup;
GPOSProxy (hb_face_t *face) :
- table (*face->table.GPOS->table),
- accels (face->table.GPOS->accels) {}
+ accel (*face->table.GPOS) {}
- const GPOS &table;
- const OT::hb_ot_layout_lookup_accelerator_t *accels;
+ const GPOS::accelerator_t &accel;
};
static inline bool
apply_forward (OT::hb_ot_apply_context_t *c,
- const OT::hb_ot_layout_lookup_accelerator_t &accel)
+ const OT::hb_ot_layout_lookup_accelerator_t &accel,
+ unsigned subtable_count)
{
bool use_cache = accel.cache_enter (c);
@@ -1821,7 +1866,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
- applied = accel.apply (c, use_cache);
+ applied = accel.apply (c, subtable_count, use_cache);
}
if (applied)
@@ -1838,7 +1883,8 @@ apply_forward (OT::hb_ot_apply_context_t *c,
static inline bool
apply_backward (OT::hb_ot_apply_context_t *c,
- const OT::hb_ot_layout_lookup_accelerator_t &accel)
+ const OT::hb_ot_layout_lookup_accelerator_t &accel,
+ unsigned subtable_count)
{
bool ret = false;
hb_buffer_t *buffer = c->buffer;
@@ -1847,7 +1893,7 @@ apply_backward (OT::hb_ot_apply_context_t *c,
if (accel.digest.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
- ret |= accel.apply (c, false);
+ ret |= accel.apply (c, subtable_count, false);
/* The reverse lookup doesn't "advance" cursor (for good reason). */
buffer->idx--;
@@ -1863,11 +1909,13 @@ apply_string (OT::hb_ot_apply_context_t *c,
const typename Proxy::Lookup &lookup,
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
- bool ret = false;
hb_buffer_t *buffer = c->buffer;
+ unsigned subtable_count = lookup.get_subtable_count ();
if (unlikely (!buffer->len || !c->lookup_mask))
- return ret;
+ return false;
+
+ bool ret = false;
c->set_lookup_props (lookup.get_props ());
@@ -1878,7 +1926,7 @@ apply_string (OT::hb_ot_apply_context_t *c,
buffer->clear_output ();
buffer->idx = 0;
- ret = apply_forward (c, accel);
+ ret = apply_forward (c, accel, subtable_count);
if (!Proxy::always_inplace)
buffer->sync ();
@@ -1888,7 +1936,7 @@ apply_string (OT::hb_ot_apply_context_t *c,
/* in-place backward substitution/positioning */
assert (!buffer->have_output);
buffer->idx = buffer->len - 1;
- ret = apply_backward (c, accel);
+ ret = apply_backward (c, accel, subtable_count);
}
return ret;
@@ -1913,13 +1961,18 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
auto &lookup = lookups[table_index][i];
unsigned int lookup_index = lookup.index;
- if (!buffer->message (font, "start lookup %d feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag))) continue;
+
+ auto *accel = proxy.accel.get_accel (lookup_index);
+ if (unlikely (!accel)) continue;
+
+ if (buffer->messaging () &&
+ !buffer->message (font, "start lookup %u feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag))) continue;
/* c.digest is a digest of all the current glyphs in the buffer
* (plus some past glyphs).
*
* Only try applying the lookup if there is any overlap. */
- if (proxy.accels[lookup_index].digest.may_have (c.digest))
+ if (accel->digest.may_have (c.digest))
{
c.set_lookup_index (lookup_index);
c.set_lookup_mask (lookup.mask);
@@ -1929,13 +1982,14 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
c.set_per_syllable (lookup.per_syllable);
apply_string<Proxy> (&c,
- proxy.table.get_lookup (lookup_index),
- proxy.accels[lookup_index]);
+ proxy.accel.table->get_lookup (lookup_index),
+ *accel);
}
- else
- (void) buffer->message (font, "skipped lookup %d feature '%c%c%c%c' because no glyph matches", lookup_index, HB_UNTAG (lookup.feature_tag));
+ else if (buffer->messaging ())
+ (void) buffer->message (font, "skipped lookup %u feature '%c%c%c%c' because no glyph matches", lookup_index, HB_UNTAG (lookup.feature_tag));
- (void) buffer->message (font, "end lookup %d feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag));
+ if (buffer->messaging ())
+ (void) buffer->message (font, "end lookup %u feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag));
}
if (stage->pause_func)
@@ -1952,17 +2006,21 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
{
GSUBProxy proxy (font->face);
- if (!buffer->message (font, "start table GSUB")) return;
+ if (buffer->messaging () &&
+ !buffer->message (font, "start table GSUB")) return;
apply (proxy, plan, font, buffer);
- (void) buffer->message (font, "end table GSUB");
+ if (buffer->messaging ())
+ (void) buffer->message (font, "end table GSUB");
}
void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
{
GPOSProxy proxy (font->face);
- if (!buffer->message (font, "start table GPOS")) return;
+ if (buffer->messaging () &&
+ !buffer->message (font, "start table GPOS")) return;
apply (proxy, plan, font, buffer);
- (void) buffer->message (font, "end table GPOS");
+ if (buffer->messaging ())
+ (void) buffer->message (font, "end table GPOS");
}
void
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
index f7b488f870..10dcc65ac0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
@@ -255,6 +255,15 @@ hb_ot_layout_script_select_language (hb_face_t *face,
unsigned int *language_index /* OUT */);
HB_EXTERN hb_bool_t
+hb_ot_layout_script_select_language2 (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int script_index,
+ unsigned int language_count,
+ const hb_tag_t *language_tags,
+ unsigned int *language_index /* OUT */,
+ hb_tag_t *chosen_language /* OUT */);
+
+HB_EXTERN hb_bool_t
hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
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 93953370e2..dccf720f46 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
@@ -201,7 +201,7 @@ struct MathItalicsCorrectionInfo
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
+ 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);
@@ -254,7 +254,7 @@ struct MathTopAccentAttachment
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
+ 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);
@@ -486,7 +486,7 @@ struct MathKernInfo
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
+ 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);
@@ -567,7 +567,7 @@ struct MathGlyphInfo
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_set_t &glyphset = c->plan->_glyphset_mathed;
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it =
@@ -938,7 +938,7 @@ struct MathVariants
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
+ 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);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh
index 3a019ef782..05cbf2cedf 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh
@@ -109,11 +109,24 @@ struct maxp
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
drop_hint_fields (dest_v1);
+
+ if (c->plan->normalized_coords)
+ instancing_update_fields (c->plan->head_maxp_info, dest_v1);
}
return_trace (true);
}
+ void instancing_update_fields (head_maxp_info_t& maxp_info, maxpV1Tail* dest_v1) const
+ {
+ dest_v1->maxPoints = maxp_info.maxPoints;
+ dest_v1->maxContours = maxp_info.maxContours;
+ dest_v1->maxCompositePoints = maxp_info.maxCompositePoints;
+ dest_v1->maxCompositeContours = maxp_info.maxCompositeContours;
+ dest_v1->maxComponentElements = maxp_info.maxComponentElements;
+ dest_v1->maxComponentDepth = maxp_info.maxComponentDepth;
+ }
+
static void drop_hint_fields (maxpV1Tail* dest_v1)
{
dest_v1->maxZones = 1;
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 6f4461cc15..85653224cc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh
@@ -27,569 +27,6 @@
#ifndef HB_OT_NAME_TABLE_HH
#define HB_OT_NAME_TABLE_HH
-#include "hb-open-type.hh"
-#include "hb-ot-name-language.hh"
-#include "hb-aat-layout.hh"
-#include "hb-utf.hh"
-
-
-namespace OT {
-
-template <typename in_utf_t, typename out_utf_t>
-inline unsigned int
-hb_ot_name_convert_utf (hb_bytes_t bytes,
- unsigned int *text_size /* IN/OUT */,
- typename out_utf_t::codepoint_t *text /* OUT */)
-{
- unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
- const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
- const typename in_utf_t::codepoint_t *src_end = src + src_len;
-
- typename out_utf_t::codepoint_t *dst = text;
-
- hb_codepoint_t unicode;
- const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
-
- if (text_size && *text_size)
- {
- (*text_size)--; /* Save room for NUL-termination. */
- const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
-
- while (src < src_end && dst < dst_end)
- {
- const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
- typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
- if (dst_next == dst)
- break; /* Out-of-room. */
-
- dst = dst_next;
- src = src_next;
- }
-
- *text_size = dst - text;
- *dst = 0; /* NUL-terminate. */
- }
-
- /* Accumulate length of rest. */
- unsigned int dst_len = dst - text;
- while (src < src_end)
- {
- src = in_utf_t::next (src, src_end, &unicode, replacement);
- dst_len += out_utf_t::encode_len (unicode);
- }
- return dst_len;
-}
-
-#define entry_score var.u16[0]
-#define entry_index var.u16[1]
-
-
-/*
- * name -- Naming
- * https://docs.microsoft.com/en-us/typography/opentype/spec/name
- */
-#define HB_OT_TAG_name HB_TAG('n','a','m','e')
-
-#define UNSUPPORTED 42
-
-struct NameRecord
-{
- hb_language_t language (hb_face_t *face) const
- {
-#ifndef HB_NO_OT_NAME_LANGUAGE
- unsigned int p = platformID;
- unsigned int l = languageID;
-
- if (p == 3)
- return _hb_ot_name_language_for_ms_code (l);
-
- if (p == 1)
- return _hb_ot_name_language_for_mac_code (l);
-
-#ifndef HB_NO_OT_NAME_LANGUAGE_AAT
- if (p == 0)
- return face->table.ltag->get_language (l);
-#endif
-
-#endif
- return HB_LANGUAGE_INVALID;
- }
-
- uint16_t score () const
- {
- /* Same order as in cmap::find_best_subtable(). */
- unsigned int p = platformID;
- unsigned int e = encodingID;
-
- /* 32-bit. */
- if (p == 3 && e == 10) return 0;
- if (p == 0 && e == 6) return 1;
- if (p == 0 && e == 4) return 2;
-
- /* 16-bit. */
- if (p == 3 && e == 1) return 3;
- if (p == 0 && e == 3) return 4;
- if (p == 0 && e == 2) return 5;
- if (p == 0 && e == 1) return 6;
- if (p == 0 && e == 0) return 7;
-
- /* Symbol. */
- if (p == 3 && e == 0) return 8;
-
- /* We treat all Mac Latin names as ASCII only. */
- if (p == 1 && e == 0) return 10; /* 10 is magic number :| */
-
- return UNSUPPORTED;
- }
-
- NameRecord* copy (hb_serialize_context_t *c, const void *base
-#ifdef HB_EXPERIMENTAL_API
- , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
-#endif
- ) const
- {
- TRACE_SERIALIZE (this);
- HB_UNUSED auto snap = c->snapshot ();
- auto *out = c->embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-#ifdef HB_EXPERIMENTAL_API
- hb_ot_name_record_ids_t record_ids (platformID, encodingID, languageID, nameID);
- hb_bytes_t* name_bytes;
-
- if (name_table_overrides->has (record_ids, &name_bytes)) {
- hb_bytes_t encoded_bytes = *name_bytes;
- char *name_str_utf16_be = nullptr;
-
- if (platformID != 1)
- {
- unsigned text_size = hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, nullptr, nullptr);
-
- text_size++; // needs to consider NULL terminator for use in hb_ot_name_convert_utf()
- unsigned byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
- name_str_utf16_be = (char *) hb_calloc (byte_len, 1);
- if (!name_str_utf16_be)
- {
- c->revert (snap);
- return_trace (nullptr);
- }
- hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, &text_size,
- (hb_utf16_be_t::codepoint_t *) name_str_utf16_be);
-
- unsigned encoded_byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
- if (!encoded_byte_len || !c->check_assign (out->length, encoded_byte_len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
- c->revert (snap);
- hb_free (name_str_utf16_be);
- return_trace (nullptr);
- }
-
- encoded_bytes = hb_bytes_t (name_str_utf16_be, encoded_byte_len);
- }
- else
- {
- // mac platform, copy the UTF-8 string(all ascii characters) as is
- if (!c->check_assign (out->length, encoded_bytes.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
- c->revert (snap);
- return_trace (nullptr);
- }
- }
-
- out->offset = 0;
- c->push ();
- encoded_bytes.copy (c);
- c->add_link (out->offset, c->pop_pack (), hb_serialize_context_t::Tail, 0);
- hb_free (name_str_utf16_be);
- }
- else
-#endif
- {
- out->offset.serialize_copy (c, offset, base, 0, hb_serialize_context_t::Tail, length);
- }
- return_trace (out);
- }
-
- bool isUnicode () const
- {
- unsigned int p = platformID;
- unsigned int e = encodingID;
-
- return (p == 0 ||
- (p == 3 && (e == 0 || e == 1 || e == 10)));
- }
-
- static int cmp (const void *pa, const void *pb)
- {
- const NameRecord *a = (const NameRecord *)pa;
- const NameRecord *b = (const NameRecord *)pb;
-
- if (a->platformID != b->platformID)
- return a->platformID - b->platformID;
-
- if (a->encodingID != b->encodingID)
- return a->encodingID - b->encodingID;
-
- if (a->languageID != b->languageID)
- return a->languageID - b->languageID;
-
- if (a->nameID != b->nameID)
- return a->nameID - b->nameID;
-
- if (a->length != b->length)
- return a->length - b->length;
-
- return 0;
- }
-
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && offset.sanitize (c, base, length));
- }
-
- HBUINT16 platformID; /* Platform ID. */
- HBUINT16 encodingID; /* Platform-specific encoding ID. */
- HBUINT16 languageID; /* Language ID. */
- HBUINT16 nameID; /* Name ID. */
- HBUINT16 length; /* String length (in bytes). */
- NNOffset16To<UnsizedArrayOf<HBUINT8>>
- offset; /* String offset from start of storage area (in bytes). */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-static int
-_hb_ot_name_entry_cmp_key (const void *pa, const void *pb, bool exact)
-{
- const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
- const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
-
- /* Compare by name_id, then language. */
-
- if (a->name_id != b->name_id)
- return a->name_id - b->name_id;
-
- if (a->language == b->language) return 0;
- if (!a->language) return -1;
- if (!b->language) return +1;
-
- const char *astr = hb_language_to_string (a->language);
- const char *bstr = hb_language_to_string (b->language);
-
- signed c = strcmp (astr, bstr);
-
- // 'a' is the user request, and 'b' is string in the font.
- // If eg. user asks for "en-us" and font has "en", approve.
- if (!exact && c &&
- hb_language_matches (b->language, a->language))
- return 0;
-
- return c;
-}
-
-static int
-_hb_ot_name_entry_cmp (const void *pa, const void *pb)
-{
- /* Compare by name_id, then language, then score, then index. */
-
- int v = _hb_ot_name_entry_cmp_key (pa, pb, true);
- if (v)
- return v;
-
- const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
- const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
-
- if (a->entry_score != b->entry_score)
- return a->entry_score - b->entry_score;
-
- if (a->entry_index != b->entry_index)
- return a->entry_index - b->entry_index;
-
- return 0;
-}
-
-struct name
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_name;
-
- unsigned int get_size () const
- { return min_size + count * nameRecordZ.item_size; }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, const NameRecord &))>
- bool serialize (hb_serialize_context_t *c,
- Iterator it,
- const void *src_string_pool
-#ifdef HB_EXPERIMENTAL_API
- , const hb_vector_t<hb_ot_name_record_ids_t>& insert_name_records
- , const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides
-#endif
- )
- {
- TRACE_SERIALIZE (this);
-
- if (unlikely (!c->extend_min ((*this)))) return_trace (false);
-
- unsigned total_count = it.len ()
-#ifdef HB_EXPERIMENTAL_API
- + insert_name_records.length
-#endif
- ;
- this->format = 0;
- if (!c->check_assign (this->count, total_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
- return false;
-
- NameRecord *name_records = (NameRecord *) hb_calloc (total_count, NameRecord::static_size);
- if (unlikely (!name_records)) return_trace (false);
-
- hb_array_t<NameRecord> records (name_records, total_count);
-
- for (const NameRecord& record : it)
- {
- hb_memcpy (name_records, &record, NameRecord::static_size);
- name_records++;
- }
-
-#ifdef HB_EXPERIMENTAL_API
- for (unsigned i = 0; i < insert_name_records.length; i++)
- {
- const hb_ot_name_record_ids_t& ids = insert_name_records[i];
- NameRecord record;
- record.platformID = ids.platform_id;
- record.encodingID = ids.encoding_id;
- record.languageID = ids.language_id;
- record.nameID = ids.name_id;
- record.length = 0; // handled in NameRecord copy()
- record.offset = 0;
- memcpy (name_records, &record, NameRecord::static_size);
- name_records++;
- }
-#endif
-
- records.qsort ();
-
- c->copy_all (records,
- src_string_pool
-#ifdef HB_EXPERIMENTAL_API
- , name_table_overrides
-#endif
- );
- hb_free (records.arrayZ);
-
-
- if (unlikely (c->ran_out_of_room ())) return_trace (false);
-
- this->stringOffset = c->length ();
-
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
-
- name *name_prime = c->serializer->start_embed<name> ();
- if (unlikely (!name_prime)) return_trace (false);
-
-#ifdef HB_EXPERIMENTAL_API
- const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides =
- c->plan->name_table_overrides;
-#endif
-
- auto it =
- + nameRecordZ.as_array (count)
- | hb_filter (c->plan->name_ids, &NameRecord::nameID)
- | hb_filter (c->plan->name_languages, &NameRecord::languageID)
- | hb_filter ([&] (const NameRecord& namerecord) {
- return
- (c->plan->flags & HB_SUBSET_FLAGS_NAME_LEGACY)
- || namerecord.isUnicode ();
- })
-#ifdef HB_EXPERIMENTAL_API
- | hb_filter ([&] (const NameRecord& namerecord) {
- if (name_table_overrides->is_empty ())
- return true;
- hb_ot_name_record_ids_t rec_ids (namerecord.platformID,
- namerecord.encodingID,
- namerecord.languageID,
- namerecord.nameID);
-
- hb_bytes_t *p;
- if (name_table_overrides->has (rec_ids, &p) &&
- (*p).length == 0)
- return false;
- return true;
- })
-#endif
- ;
-
-#ifdef HB_EXPERIMENTAL_API
- hb_vector_t<hb_ot_name_record_ids_t> insert_name_records;
- if (!name_table_overrides->is_empty ())
- {
- if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population ())))
- return_trace (false);
- for (const auto& record_ids : name_table_overrides->keys ())
- {
- if (name_table_overrides->get (record_ids).length == 0)
- continue;
- if (has_name_record_with_ids (record_ids))
- continue;
- insert_name_records.push (record_ids);
- }
- }
-#endif
-
- return (name_prime->serialize (c->serializer, it,
- std::addressof (this + stringOffset)
-#ifdef HB_EXPERIMENTAL_API
- , insert_name_records
- , name_table_overrides
-#endif
- ));
- }
-
- bool sanitize_records (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- const void *string_pool = (this+stringOffset).arrayZ;
- return_trace (nameRecordZ.sanitize (c, count, string_pool));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- likely (format == 0 || format == 1) &&
- c->check_array (nameRecordZ.arrayZ, count) &&
- c->check_range (this, stringOffset) &&
- sanitize_records (c));
- }
-
- struct accelerator_t
- {
- accelerator_t (hb_face_t *face)
- {
- this->table = hb_sanitize_context_t ().reference_table<name> (face);
- assert (this->table.get_length () >= this->table->stringOffset);
- this->pool = (const char *) (const void *) (this->table+this->table->stringOffset);
- this->pool_len = this->table.get_length () - this->table->stringOffset;
- const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
- this->table->count);
-
- this->names.alloc (all_names.length);
-
- for (unsigned int i = 0; i < all_names.length; i++)
- {
- hb_ot_name_entry_t *entry = this->names.push ();
-
- entry->name_id = all_names[i].nameID;
- entry->language = all_names[i].language (face);
- entry->entry_score = all_names[i].score ();
- entry->entry_index = i;
- }
-
- this->names.qsort (_hb_ot_name_entry_cmp);
- /* Walk and pick best only for each name_id,language pair,
- * while dropping unsupported encodings. */
- unsigned int j = 0;
- for (unsigned int i = 0; i < this->names.length; i++)
- {
- if (this->names[i].entry_score == UNSUPPORTED ||
- this->names[i].language == HB_LANGUAGE_INVALID)
- continue;
- if (i &&
- this->names[i - 1].name_id == this->names[i].name_id &&
- this->names[i - 1].language == this->names[i].language)
- continue;
- this->names[j++] = this->names[i];
- }
- this->names.resize (j);
- }
- ~accelerator_t ()
- {
- this->table.destroy ();
- }
-
- int get_index (hb_ot_name_id_t name_id,
- hb_language_t language,
- unsigned int *width=nullptr) const
- {
- const hb_ot_name_entry_t key = {name_id, {0}, language};
- const hb_ot_name_entry_t *entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
- this->names.length,
- sizeof (hb_ot_name_entry_t),
- _hb_ot_name_entry_cmp_key,
- true);
-
- if (!entry)
- {
- entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
- this->names.length,
- sizeof (hb_ot_name_entry_t),
- _hb_ot_name_entry_cmp_key,
- false);
- }
-
- if (!entry)
- return -1;
-
- if (width)
- *width = entry->entry_score < 10 ? 2 : 1;
-
- return entry->entry_index;
- }
-
- hb_bytes_t get_name (unsigned int idx) const
- {
- const hb_array_t<const NameRecord> all_names (table->nameRecordZ.arrayZ, table->count);
- const NameRecord &record = all_names[idx];
- const hb_bytes_t string_pool (pool, pool_len);
- return string_pool.sub_array (record.offset, record.length);
- }
-
- private:
- const char *pool;
- unsigned int pool_len;
- public:
- hb_blob_ptr_t<name> table;
- hb_vector_t<hb_ot_name_entry_t> names;
- };
-
- private:
- // sometimes NameRecords are not sorted in the font file, so use linear search
- // here
- bool has_name_record_with_ids (const hb_ot_name_record_ids_t& record_ids) const
- {
- for (const auto& record : nameRecordZ.as_array (count))
- {
- if (record.platformID == record_ids.platform_id &&
- record.encodingID == record_ids.encoding_id &&
- record.languageID == record_ids.language_id &&
- record.nameID == record_ids.name_id)
- return true;
- }
- return false;
- }
-
- public:
- /* We only implement format 0 for now. */
- HBUINT16 format; /* Format selector (=0/1). */
- HBUINT16 count; /* Number of name records. */
- NNOffset16To<UnsizedArrayOf<HBUINT8>>
- stringOffset; /* Offset to start of string storage (from start of table). */
- UnsizedArrayOf<NameRecord>
- nameRecordZ; /* The name records where count is the number of records. */
- public:
- DEFINE_SIZE_ARRAY (6, nameRecordZ);
-};
-
-#undef entry_index
-#undef entry_score
-
-struct name_accelerator_t : name::accelerator_t {
- name_accelerator_t (hb_face_t *face) : name::accelerator_t (face) {}
-};
-
-} /* namespace OT */
-
+#include "OT/name/name.hh"
#endif /* HB_OT_NAME_TABLE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc
index 6adf1e8fbe..0323364aef 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc
@@ -181,4 +181,6 @@ hb_ot_name_get_utf32 (hb_face_t *face,
return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
}
+#include "hb-ot-name-language-static.hh"
+
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-name.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-name.h
index 1ea4b55e5c..03e664bb93 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name.h
@@ -33,9 +33,8 @@
HB_BEGIN_DECLS
-
/**
- * hb_ot_name_id_t:
+ * hb_ot_name_id_predefined_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
@@ -65,16 +64,14 @@ HB_BEGIN_DECLS
* @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.
+ * An enum type representing the pre-defined name IDs.
*
* 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
+ * Since: 7.0.0
**/
-enum
+typedef enum
{
HB_OT_NAME_ID_COPYRIGHT = 0,
HB_OT_NAME_ID_FONT_FAMILY = 1,
@@ -104,8 +101,17 @@ enum
HB_OT_NAME_ID_VARIATIONS_PS_PREFIX = 25,
HB_OT_NAME_ID_INVALID = 0xFFFF
-};
+} hb_ot_name_id_predefined_t;
+/**
+ * hb_ot_name_id_t:
+ *
+ * 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.
+ *
+ * Since: 2.0.0
+ **/
typedef unsigned int hb_ot_name_id_t;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh
index 5b017d56a6..97d18b9d75 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh
@@ -30,6 +30,7 @@
#include "hb-open-type.hh"
#include "hb-ot-os2-unicode-ranges.hh"
+#include "hb-ot-var-mvar-table.hh"
#include "hb-set.hh"
@@ -62,6 +63,7 @@ struct OS2V2Tail
bool has_data () const { return sxHeight || sCapHeight; }
const OS2V2Tail * operator -> () const { return this; }
+ OS2V2Tail * operator -> () { return this; }
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -213,20 +215,51 @@ struct OS2
OS2 *os2_prime = c->serializer->embed (this);
if (unlikely (!os2_prime)) return_trace (false);
- if (c->plan->user_axes_location->has (HB_TAG ('w','g','h','t')) &&
+#ifndef HB_NO_VAR
+ if (c->plan->normalized_coords)
+ {
+ auto &MVAR = *c->plan->source->table.MVAR;
+ auto *table = os2_prime;
+
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, sTypoAscender);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, sTypoDescender);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, sTypoLineGap);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT, usWinAscent);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT, usWinDescent);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE, ySubscriptXSize);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE, ySubscriptYSize);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET, ySubscriptXOffset);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET, ySubscriptYOffset);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE, ySuperscriptXSize);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE, ySuperscriptYSize);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET, ySuperscriptXOffset);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET, ySuperscriptYOffset);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_STRIKEOUT_SIZE, yStrikeoutSize);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_STRIKEOUT_OFFSET, yStrikeoutPosition);
+
+ if (os2_prime->version >= 2)
+ {
+ auto *table = & const_cast<OS2V2Tail &> (os2_prime->v2 ());
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_X_HEIGHT, sxHeight);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_CAP_HEIGHT, sCapHeight);
+ }
+ }
+#endif
+
+ if (c->plan->user_axes_location.has (HB_TAG ('w','g','h','t')) &&
!c->plan->pinned_at_default)
{
- float weight_class = c->plan->user_axes_location->get (HB_TAG ('w','g','h','t'));
+ float weight_class = c->plan->user_axes_location.get (HB_TAG ('w','g','h','t'));
if (!c->serializer->check_assign (os2_prime->usWeightClass,
roundf (hb_clamp (weight_class, 1.0f, 1000.0f)),
HB_SERIALIZE_ERROR_INT_OVERFLOW))
return_trace (false);
}
- if (c->plan->user_axes_location->has (HB_TAG ('w','d','t','h')) &&
+ if (c->plan->user_axes_location.has (HB_TAG ('w','d','t','h')) &&
!c->plan->pinned_at_default)
{
- float width = c->plan->user_axes_location->get (HB_TAG ('w','d','t','h'));
+ float width = c->plan->user_axes_location.get (HB_TAG ('w','d','t','h'));
if (!c->serializer->check_assign (os2_prime->usWidthClass,
roundf (map_wdth_to_widthclass (width)),
HB_SERIALIZE_ERROR_INT_OVERFLOW))
@@ -236,14 +269,10 @@ struct OS2
if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
return_trace (true);
- /* when --gids option is not used, no need to do collect_mapping that is
- * iterating all codepoints in each subtable, which is not efficient */
- uint16_t min_cp, max_cp;
- find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
- os2_prime->usFirstCharIndex = min_cp;
- os2_prime->usLastCharIndex = max_cp;
+ os2_prime->usFirstCharIndex = hb_min (0xFFFFu, c->plan->unicodes.get_min ());
+ os2_prime->usLastCharIndex = hb_min (0xFFFFu, c->plan->unicodes.get_max ());
- _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
+ _update_unicode_ranges (&c->plan->unicodes, os2_prime->ulUnicodeRange);
return_trace (true);
}
@@ -251,12 +280,16 @@ struct OS2
void _update_unicode_ranges (const hb_set_t *codepoints,
HBUINT32 ulUnicodeRange[4]) const
{
- HBUINT32 newBits[4];
+ HBUINT32 newBits[4];
for (unsigned int i = 0; i < 4; i++)
newBits[i] = 0;
- hb_codepoint_t cp = HB_SET_VALUE_INVALID;
- while (codepoints->next (&cp)) {
+ /* This block doesn't show up in profiles. If it ever did,
+ * we can rewrite it to iterate over OS/2 ranges and use
+ * set iteration to check if the range matches. */
+ for (hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+ codepoints->next (&cp);)
+ {
unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
if (bit < 128)
{
@@ -278,14 +311,6 @@ struct OS2
ulUnicodeRange[i] = ulUnicodeRange[i] & newBits[i]; // set bits only if set in the original
}
- static void find_min_and_max_codepoint (const hb_set_t *codepoints,
- uint16_t *min_cp, /* OUT */
- uint16_t *max_cp /* OUT */)
- {
- *min_cp = hb_min (0xFFFFu, codepoints->get_min ());
- *max_cp = hb_min (0xFFFFu, codepoints->get_max ());
- }
-
/* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
* https://docs.microsoft.com/en-us/typography/legacy/legacy_arabic_fonts */
enum font_page_t
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-unicode-ranges.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-unicode-ranges.hh
index 9613d2d186..01e6a46e63 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-unicode-ranges.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-unicode-ranges.hh
@@ -34,10 +34,10 @@ namespace OT {
struct OS2Range
{
int cmp (hb_codepoint_t key) const
- { return (key < start) ? -1 : key <= end ? 0 : +1; }
+ { return (key < first) ? -1 : key <= last ? 0 : +1; }
- hb_codepoint_t start;
- hb_codepoint_t end;
+ hb_codepoint_t first;
+ hb_codepoint_t last;
unsigned int bit;
};
@@ -223,7 +223,7 @@ static unsigned int
_hb_ot_os2_get_unicode_range_bit (hb_codepoint_t cp)
{
auto *range = hb_sorted_array (_hb_os2_unicode_ranges).bsearch (cp);
- return range ? range->bit : -1;
+ return range ? range->bit : (unsigned) -1;
}
} /* 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 a04b80357b..e0eb770948 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh
@@ -28,6 +28,7 @@
#define HB_OT_POST_TABLE_HH
#include "hb-open-type.hh"
+#include "hb-ot-var-mvar-table.hh"
#define HB_STRING_ARRAY_NAME format1_names
#define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
@@ -98,14 +99,25 @@ struct post
post *post_prime = c->serializer->start_embed<post> ();
if (unlikely (!post_prime)) return_trace (false);
+#ifndef HB_NO_VAR
+ if (c->plan->normalized_coords)
+ {
+ auto &MVAR = *c->plan->source->table.MVAR;
+ auto *table = post_prime;
+
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_UNDERLINE_SIZE, underlineThickness);
+ HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_UNDERLINE_OFFSET, underlinePosition);
+ }
+#endif
+
bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
if (!serialize (c->serializer, glyph_names))
return_trace (false);
- if (c->plan->user_axes_location->has (HB_TAG ('s','l','n','t')) &&
+ if (c->plan->user_axes_location.has (HB_TAG ('s','l','n','t')) &&
!c->plan->pinned_at_default)
{
- float italic_angle = c->plan->user_axes_location->get (HB_TAG ('s','l','n','t'));
+ float italic_angle = c->plan->user_axes_location.get (HB_TAG ('s','l','n','t'));
italic_angle = hb_max (-90.f, hb_min (italic_angle, 90.f));
post_prime->italicAngle.set_float (italic_angle);
}
@@ -134,6 +146,7 @@ struct post
pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
const uint8_t *end = (const uint8_t *) (const void *) table + table_length;
+ index_to_offset.alloc (hb_min (face->get_num_glyphs (), table_length / 8));
for (const uint8_t *data = pool;
index_to_offset.length < 65535 && data < end && data + *data < end;
data += 1 + *data)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
index bbdfc214a1..3d207e0681 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
@@ -80,8 +80,7 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
const hb_segment_properties_t &props) :
face (face),
props (props),
- map (face, props),
- aat_map (face, props)
+ map (face, props)
#ifndef HB_NO_AAT_SHAPE
, apply_morx (_hb_apply_morx (face, props))
#endif
@@ -105,10 +104,6 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
plan.props = props;
plan.shaper = shaper;
map.compile (plan.map, key);
-#ifndef HB_NO_AAT_SHAPE
- if (apply_morx)
- aat_map.compile (plan.aat_map);
-#endif
#ifndef HB_NO_OT_SHAPE_FRACTIONS
plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
@@ -222,9 +217,6 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face,
const hb_shape_plan_key_t *key)
{
map.init ();
-#ifndef HB_NO_AAT_SHAPE
- aat_map.init ();
-#endif
hb_ot_shape_planner_t planner (face,
key->props);
@@ -241,9 +233,6 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face,
if (unlikely (!data))
{
map.fini ();
-#ifndef HB_NO_AAT_SHAPE
- aat_map.fini ();
-#endif
return false;
}
}
@@ -258,21 +247,13 @@ hb_ot_shape_plan_t::fini ()
shaper->data_destroy (const_cast<void *> (data));
map.fini ();
-#ifndef HB_NO_AAT_SHAPE
- aat_map.fini ();
-#endif
}
void
hb_ot_shape_plan_t::substitute (hb_font_t *font,
hb_buffer_t *buffer) const
{
-#ifndef HB_NO_AAT_SHAPE
- if (unlikely (apply_morx))
- hb_aat_layout_substitute (this, font, buffer);
- else
-#endif
- map.substitute (this, font, buffer);
+ map.substitute (this, font, buffer);
}
void
@@ -406,18 +387,6 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
feature->value);
}
-#ifndef HB_NO_AAT_SHAPE
- if (planner->apply_morx)
- {
- hb_aat_map_builder_t *aat_map = &planner->aat_map;
- for (unsigned int i = 0; i < num_user_features; i++)
- {
- const hb_feature_t *feature = &user_features[i];
- aat_map->add_feature (feature->tag, feature->value);
- }
- }
-#endif
-
if (planner->shaper->override_features)
planner->shaper->override_features (planner);
}
@@ -940,7 +909,13 @@ hb_ot_substitute_plan (const hb_ot_shape_context_t *c)
if (c->plan->fallback_glyph_classes)
hb_synthesize_glyph_classes (c->buffer);
- c->plan->substitute (c->font, buffer);
+#ifndef HB_NO_AAT_SHAPE
+ if (unlikely (c->plan->apply_morx))
+ hb_aat_layout_substitute (c->plan, c->font, c->buffer,
+ c->user_features, c->num_user_features);
+ else
+#endif
+ c->plan->substitute (c->font, buffer);
}
static inline void
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh
index ace28602f6..f84aa5c49e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh
@@ -65,7 +65,6 @@ struct hb_ot_shape_plan_t
hb_segment_properties_t props;
const struct hb_ot_shaper_t *shaper;
hb_ot_map_t map;
- hb_aat_map_t aat_map;
const void *data;
#ifndef HB_NO_OT_SHAPE_FRACTIONS
hb_mask_t frac_mask, numr_mask, dnom_mask;
@@ -152,7 +151,6 @@ struct hb_ot_shape_planner_t
hb_face_t *face;
hb_segment_properties_t props;
hb_ot_map_builder_t map;
- hb_aat_map_builder_t aat_map;
#ifndef HB_NO_AAT_SHAPE
bool apply_morx : 1;
#else
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh
index b9f92f72d6..e7a69008b7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh
@@ -154,16 +154,22 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
const auto &components = ligature_table[first_glyph_idx].ligatures[ligature_idx].components;
unsigned component_count = ARRAY_LENGTH_CONST (components);
- for (unsigned i = 0; i < component_count; i++)
+ bool matched = true;
+ for (unsigned j = 0; j < component_count; j++)
{
- hb_codepoint_t component_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[i];
+ hb_codepoint_t component_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[j];
hb_codepoint_t component_glyph;
if (!component_u ||
- !hb_font_get_glyph (font, component_u, 0, &component_glyph))
- continue;
+ !hb_font_get_nominal_glyph (font, component_u, &component_glyph))
+ {
+ matched = false;
+ break;
+ }
component_list[num_components++] = component_glyph;
}
+ if (!matched)
+ continue;
component_count_list[num_ligatures] = 1 + component_count;
ligature_list[num_ligatures] = ligature_glyph;
@@ -222,7 +228,7 @@ struct arabic_fallback_plan_t
hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
- OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
+ OT::hb_ot_layout_lookup_accelerator_t *accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
};
#if defined(_WIN32) && !defined(HB_NO_WIN1256)
@@ -272,7 +278,7 @@ arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUS
fallback_plan->lookup_array[j] = const_cast<OT::SubstLookup*> (&(&manifest+manifest[i].lookupOffset));
if (fallback_plan->lookup_array[j])
{
- fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
+ fallback_plan->accel_array[j] = OT::hb_ot_layout_lookup_accelerator_t::create (*fallback_plan->lookup_array[j]);
j++;
}
}
@@ -302,7 +308,7 @@ arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i);
if (fallback_plan->lookup_array[j])
{
- fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
+ fallback_plan->accel_array[j] = OT::hb_ot_layout_lookup_accelerator_t::create (*fallback_plan->lookup_array[j]);
j++;
}
}
@@ -349,7 +355,7 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
if (fallback_plan->lookup_array[i])
{
- fallback_plan->accel_array[i].fini ();
+ hb_free (fallback_plan->accel_array[i]);
if (fallback_plan->free_lookups)
hb_free (fallback_plan->lookup_array[i]);
}
@@ -366,9 +372,10 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
if (fallback_plan->lookup_array[i]) {
c.set_lookup_mask (fallback_plan->mask_array[i]);
- hb_ot_layout_substitute_lookup (&c,
- *fallback_plan->lookup_array[i],
- fallback_plan->accel_array[i]);
+ if (fallback_plan->accel_array[i])
+ hb_ot_layout_substitute_lookup (&c,
+ *fallback_plan->lookup_array[i],
+ *fallback_plan->accel_array[i]);
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.cc
index 2332ae3697..256f8f1d14 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.cc
@@ -556,9 +556,9 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
i++; // Don't touch i again.
- DEBUG_MSG (ARABIC, nullptr, "%s stretch at (%d,%d,%d)",
+ DEBUG_MSG (ARABIC, nullptr, "%s stretch at (%u,%u,%u)",
step == MEASURE ? "measuring" : "cutting", context, start, end);
- DEBUG_MSG (ARABIC, nullptr, "rest of word: count=%d width %d", start - context, w_total);
+ DEBUG_MSG (ARABIC, nullptr, "rest of word: count=%u width %d", start - context, w_total);
DEBUG_MSG (ARABIC, nullptr, "fixed tiles: count=%d width=%d", n_fixed, w_fixed);
DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%d", n_repeating, w_repeating);
@@ -597,7 +597,7 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
if (info[k - 1].arabic_shaping_action() == STCH_REPEATING)
repeat += n_copies;
- DEBUG_MSG (ARABIC, nullptr, "appending %d copies of glyph %d; j=%d",
+ DEBUG_MSG (ARABIC, nullptr, "appending %u copies of glyph %u; j=%u",
repeat, info[k - 1].codepoint, j);
for (unsigned int n = 0; n < repeat; n++)
{
@@ -675,15 +675,15 @@ reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
{
hb_glyph_info_t *info = buffer->info;
- DEBUG_MSG (ARABIC, buffer, "Reordering marks from %d to %d", start, end);
+ DEBUG_MSG (ARABIC, buffer, "Reordering marks from %u to %u", start, end);
unsigned int i = start;
for (unsigned int cc = 220; cc <= 230; cc += 10)
{
- DEBUG_MSG (ARABIC, buffer, "Looking for %d's starting at %d", cc, i);
+ DEBUG_MSG (ARABIC, buffer, "Looking for %u's starting at %u", cc, i);
while (i < end && info_cc(info[i]) < cc)
i++;
- DEBUG_MSG (ARABIC, buffer, "Looking for %d's stopped at %d", cc, i);
+ DEBUG_MSG (ARABIC, buffer, "Looking for %u's stopped at %u", cc, i);
if (i == end)
break;
@@ -698,10 +698,10 @@ reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
if (i == j)
continue;
- DEBUG_MSG (ARABIC, buffer, "Found %d's from %d to %d", cc, i, j);
+ DEBUG_MSG (ARABIC, buffer, "Found %u's from %u to %u", cc, i, j);
/* Shift it! */
- DEBUG_MSG (ARABIC, buffer, "Shifting %d's: %d %d", cc, i, j);
+ DEBUG_MSG (ARABIC, buffer, "Shifting %u's: %u %u", cc, i, j);
hb_glyph_info_t temp[HB_OT_SHAPE_MAX_COMBINING_MARKS];
assert (j - i <= ARRAY_LENGTH (temp));
buffer->merge_clusters (start, j);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh
index d6c67b81bd..7dd47755af 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh
@@ -446,7 +446,7 @@ static const int indic_syllable_machine_en_main = 31;
#define found_syllable(syllable_type) \
HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ if (0) fprintf (stderr, "syllable %u..%u %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
syllable_serial++; \
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.cc
index 7652210d9d..e3818cc37f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.cc
@@ -482,9 +482,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
is_one_of (info[start+2], FLAG (I_Cat(ZWJ))))
{
buffer->merge_clusters (start+1, start+3);
- hb_glyph_info_t tmp = info[start+1];
- info[start+1] = info[start+2];
- info[start+2] = tmp;
+ hb_swap (info[start+1], info[start+2]);
}
/* 1. Find base consonant:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh
index fd91ee0caf..848ed231f7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh
@@ -280,7 +280,7 @@ static const int khmer_syllable_machine_en_main = 21;
#define found_syllable(syllable_type) \
HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ if (0) fprintf (stderr, "syllable %u..%u %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
syllable_serial++; \
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh
index 87cded4ed8..f7b456b11f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh
@@ -50,7 +50,7 @@ enum myanmar_syllable_type_t {
};
-#line 51 "hb-ot-shaper-myanmar-machine.hh"
+#line 54 "hb-ot-shaper-myanmar-machine.hh"
#define myanmar_syllable_machine_ex_A 9u
#define myanmar_syllable_machine_ex_As 32u
#define myanmar_syllable_machine_ex_C 1u
@@ -77,7 +77,7 @@ enum myanmar_syllable_type_t {
#define myanmar_syllable_machine_ex_ZWNJ 5u
-#line 76 "hb-ot-shaper-myanmar-machine.hh"
+#line 81 "hb-ot-shaper-myanmar-machine.hh"
static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
1u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u,
5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 39u, 3u, 39u,
@@ -429,7 +429,7 @@ static const int myanmar_syllable_machine_en_main = 0;
#define found_syllable(syllable_type) \
HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ if (0) fprintf (stderr, "syllable %u..%u %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
syllable_serial++; \
@@ -443,7 +443,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
-#line 436 "hb-ot-shaper-myanmar-machine.hh"
+#line 447 "hb-ot-shaper-myanmar-machine.hh"
{
cs = myanmar_syllable_machine_start;
ts = 0;
@@ -459,7 +459,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
unsigned int syllable_serial = 1;
-#line 448 "hb-ot-shaper-myanmar-machine.hh"
+#line 463 "hb-ot-shaper-myanmar-machine.hh"
{
int _slen;
int _trans;
@@ -473,7 +473,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 460 "hb-ot-shaper-myanmar-machine.hh"
+#line 477 "hb-ot-shaper-myanmar-machine.hh"
}
_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -519,7 +519,7 @@ _eof_trans:
#line 113 "hb-ot-shaper-myanmar-machine.rl"
{te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
break;
-#line 498 "hb-ot-shaper-myanmar-machine.hh"
+#line 523 "hb-ot-shaper-myanmar-machine.hh"
}
_again:
@@ -528,7 +528,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 505 "hb-ot-shaper-myanmar-machine.hh"
+#line 532 "hb-ot-shaper-myanmar-machine.hh"
}
if ( ++p != pe )
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh
index f2fbdb725b..7249c33356 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh
@@ -835,7 +835,7 @@ static const int use_syllable_machine_en_main = 0;
#define found_syllable(syllable_type) \
HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
+ if (0) fprintf (stderr, "syllable %u..%u %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
syllable_serial++; \
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh
index 59bb2daccd..2006f677d1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh
@@ -112,7 +112,7 @@ struct AxisValueFormat1
const hb_array_t<const StatAxisRecord> axis_records) const
{
TRACE_SUBSET (this);
- const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
if (keep_axis_value (axis_records, user_axes_location))
return_trace (c->serializer->embed (this));
@@ -171,7 +171,7 @@ struct AxisValueFormat2
const hb_array_t<const StatAxisRecord> axis_records) const
{
TRACE_SUBSET (this);
- const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
if (keep_axis_value (axis_records, user_axes_location))
return_trace (c->serializer->embed (this));
@@ -234,7 +234,7 @@ struct AxisValueFormat3
const hb_array_t<const StatAxisRecord> axis_records) const
{
TRACE_SUBSET (this);
- const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
if (keep_axis_value (axis_records, user_axes_location))
return_trace (c->serializer->embed (this));
@@ -313,7 +313,7 @@ struct AxisValueFormat4
const hb_array_t<const StatAxisRecord> axis_records) const
{
TRACE_SUBSET (this);
- const hb_hashmap_t<hb_tag_t, float> *user_axes_location = c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location = &c->plan->user_axes_location;
if (!keep_axis_value (axis_records, user_axes_location))
return_trace (false);
@@ -390,8 +390,8 @@ struct AxisValue
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
+ if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
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)...));
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
index f6ba3b0d47..547f9573d0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
@@ -119,6 +119,17 @@ hb_ot_new_tag_to_script (hb_tag_t tag)
}
#ifndef HB_DISABLE_DEPRECATED
+/**
+ * hb_ot_tags_from_script:
+ * @script: an #hb_script_t to convert.
+ * @script_tag_1: (out): output #hb_tag_t.
+ * @script_tag_2: (out): output #hb_tag_t.
+ *
+ * Converts an #hb_script_t to script tags.
+ *
+ * Since: 0.6.0
+ * Deprecated: 2.0.0: use hb_ot_tags_from_script_and_language() instead
+ **/
void
hb_ot_tags_from_script (hb_script_t script,
hb_tag_t *script_tag_1,
@@ -249,6 +260,15 @@ struct LangTag
/*{"zh?", {HB_TAG('Z','H','P',' ')}},*/ /* Chinese Phonetic */
#ifndef HB_DISABLE_DEPRECATED
+/**
+ * hb_ot_tag_from_language:
+ * @language: an #hb_language_t to convert.
+ *
+ * Converts an #hb_language_t to an #hb_tag_t.
+ *
+ * Since: 0.6.0
+ * Deprecated: 2.0.0: use hb_ot_tags_from_script_and_language() instead
+ **/
hb_tag_t
hb_ot_tag_from_language (hb_language_t language)
{
@@ -606,7 +626,7 @@ test_langs_sorted ()
int c = ot_languages2[i].cmp (&ot_languages2[i - 1]);
if (c > 0)
{
- fprintf (stderr, "ot_languages2 not sorted at index %d: %08x %d %08x\n",
+ fprintf (stderr, "ot_languages2 not sorted at index %u: %08x %d %08x\n",
i, ot_languages2[i-1].language, c, ot_languages2[i].language);
abort();
}
@@ -617,7 +637,7 @@ test_langs_sorted ()
int c = ot_languages3[i].cmp (&ot_languages3[i - 1]);
if (c > 0)
{
- fprintf (stderr, "ot_languages3 not sorted at index %d: %08x %d %08x\n",
+ fprintf (stderr, "ot_languages3 not sorted at index %u: %08x %d %08x\n",
i, ot_languages3[i-1].language, c, ot_languages3[i].language);
abort();
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh
index cc5c5c0068..3449b30499 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh
@@ -86,8 +86,8 @@ struct SegmentMaps : Array16Of<AxisValueMap>
{
int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
{
-#define fromCoord coords[from_offset]
-#define toCoord coords[to_offset]
+#define fromCoord coords[from_offset].to_int ()
+#define toCoord coords[to_offset].to_int ()
/* The following special-cases are not part of OpenType, which requires
* that at least -1, 0, and +1 must be mapped. But we include these as
* part of a better error recovery scheme. */
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 c1d57a002a..a384dfa531 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
@@ -56,18 +56,18 @@ struct InstanceRecord
if (unlikely (!c->serializer->embed (flags))) return_trace (false);
const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count);
- const hb_hashmap_t<hb_tag_t, float> *axes_location = c->plan->user_axes_location;
+ const hb_hashmap_t<hb_tag_t, float> *axes_location = &c->plan->user_axes_location;
for (unsigned i = 0 ; i < axis_count; i++)
{
uint32_t *axis_tag;
// only keep instances whose coordinates == pinned axis location
- if (!c->plan->axes_old_index_tag_map->has (i, &axis_tag)) continue;
+ if (!c->plan->axes_old_index_tag_map.has (i, &axis_tag)) continue;
if (axes_location->has (*axis_tag) &&
fabsf (axes_location->get (*axis_tag) - coords[i].to_float ()) > 0.001f)
return_trace (false);
- if (!c->plan->axes_index_map->has (i))
+ if (!c->plan->axes_index_map.has (i))
continue;
if (!c->serializer->embed (coords[i]))
@@ -175,15 +175,15 @@ struct AxisRecord
void get_coordinates (float &min, float &default_, float &max) const
{
- default_ = defaultValue / 65536.f;
+ default_ = defaultValue.to_float ();
/* Ensure order, to simplify client math. */
- min = hb_min (default_, minValue / 65536.f);
- max = hb_max (default_, maxValue / 65536.f);
+ min = hb_min (default_, minValue.to_float ());
+ max = hb_max (default_, maxValue.to_float ());
}
float get_default () const
{
- return defaultValue / 65536.f;
+ return defaultValue.to_float ();
}
public:
@@ -362,7 +362,7 @@ struct fvar
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- unsigned retained_axis_count = c->plan->axes_index_map->get_population ();
+ unsigned retained_axis_count = c->plan->axes_index_map.get_population ();
if (!retained_axis_count) //all axes are pinned
return_trace (false);
@@ -383,7 +383,7 @@ struct fvar
auto axes_records = get_axes ();
for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
{
- if (!c->plan->axes_index_map->has (i)) continue;
+ if (!c->plan->axes_index_map.has (i)) continue;
if (unlikely (!c->serializer->embed (axes_records[i])))
return_trace (false);
}
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 e02063ca43..1eae6a3532 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
@@ -128,13 +128,13 @@ struct TupleVariationHeader
for (unsigned int i = 0; i < coord_count; i++)
{
int v = coords[i];
- int peak = peak_tuple[i];
+ int peak = peak_tuple[i].to_int ();
if (!peak || v == peak) continue;
if (has_intermediate ())
{
- int start = start_tuple[i];
- int end = end_tuple[i];
+ int start = start_tuple[i].to_int ();
+ int end = end_tuple[i].to_int ();
if (unlikely (start > peak || peak > end ||
(start < 0 && end > 0 && peak))) continue;
if (v < start || v > end) return 0.f;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-mvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-mvar-table.hh
index 420366fbb3..d27ebb39c0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-mvar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-mvar-table.hh
@@ -116,4 +116,13 @@ protected:
} /* namespace OT */
+#define HB_ADD_MVAR_VAR(tag, field) \
+ c->serializer->check_assign (table->field, \
+ roundf (table->field + \
+ MVAR.get_var (tag, \
+ c->plan->normalized_coords.arrayZ, \
+ c->plan->normalized_coords.length)), \
+ HB_SERIALIZE_ERROR_INT_OVERFLOW)
+
+
#endif /* HB_OT_VAR_MVAR_TABLE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-outline.cc b/src/3rdparty/harfbuzz-ng/src/hb-outline.cc
new file mode 100644
index 0000000000..184e48cfb7
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-outline.cc
@@ -0,0 +1,322 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ * Copyright © 1999 David Turner
+ * Copyright © 2005 Werner Lemberg
+ * Copyright © 2013-2015 Alexei Podtelezhnikov
+ *
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OUTLINE
+
+#include "hb-outline.hh"
+
+#include "hb-machinery.hh"
+
+
+void hb_outline_t::replay (hb_draw_funcs_t *pen, void *pen_data) const
+{
+ hb_draw_state_t st = HB_DRAW_STATE_DEFAULT;
+
+ unsigned first = 0;
+ for (unsigned contour : contours)
+ {
+ auto it = points.as_array ().sub_array (first, contour - first);
+ while (it)
+ {
+ hb_outline_point_t p1 = *it++;
+ switch (p1.type)
+ {
+ case hb_outline_point_t::type_t::MOVE_TO:
+ {
+ pen->move_to (pen_data, st,
+ p1.x, p1.y);
+ }
+ break;
+ case hb_outline_point_t::type_t::LINE_TO:
+ {
+ pen->line_to (pen_data, st,
+ p1.x, p1.y);
+ }
+ break;
+ case hb_outline_point_t::type_t::QUADRATIC_TO:
+ {
+ hb_outline_point_t p2 = *it++;
+ pen->quadratic_to (pen_data, st,
+ p1.x, p1.y,
+ p2.x, p2.y);
+ }
+ break;
+ case hb_outline_point_t::type_t::CUBIC_TO:
+ {
+ hb_outline_point_t p2 = *it++;
+ hb_outline_point_t p3 = *it++;
+ pen->cubic_to (pen_data, st,
+ p1.x, p1.y,
+ p2.x, p2.y,
+ p3.x, p3.y);
+ }
+ break;
+ }
+ }
+ pen->close_path (pen_data, st);
+ first = contour;
+ }
+}
+
+float hb_outline_t::area () const
+{
+ float a = 0;
+ unsigned first = 0;
+ for (unsigned contour : contours)
+ {
+ for (unsigned i = first; i < contour; i++)
+ {
+ unsigned j = i + 1 < contour ? i + 1 : first;
+
+ auto &pi = points[i];
+ auto &pj = points[j];
+ a += pi.x * pj.y - pi.y * pj.x;
+ }
+
+ first = contour;
+ }
+ return a * .5f;
+}
+
+void hb_outline_t::embolden (float x_strength, float y_strength,
+ float x_shift, float y_shift)
+{
+ /* This function is a straight port of FreeType's FT_Outline_EmboldenXY.
+ * Permission has been obtained from the FreeType authors of the code
+ * to relicense it under the HarfBuzz license. */
+
+ if (!x_strength && !y_strength) return;
+ if (!points) return;
+
+ x_strength /= 2.f;
+ y_strength /= 2.f;
+
+ bool orientation_negative = area () < 0;
+
+ signed first = 0;
+ for (unsigned c = 0; c < contours.length; c++)
+ {
+ hb_outline_vector_t in, out, anchor, shift;
+ float l_in, l_out, l_anchor = 0, l, q, d;
+
+ l_in = 0;
+ signed last = (int) contours[c] - 1;
+
+ /* pacify compiler */
+ in.x = in.y = anchor.x = anchor.y = 0;
+
+ /* Counter j cycles though the points; counter i advances only */
+ /* when points are moved; anchor k marks the first moved point. */
+ for ( signed i = last, j = first, k = -1;
+ j != i && i != k;
+ j = j < last ? j + 1 : first )
+ {
+ if ( j != k )
+ {
+ out.x = points[j].x - points[i].x;
+ out.y = points[j].y - points[i].y;
+ l_out = out.normalize_len ();
+
+ if ( l_out == 0 )
+ continue;
+ }
+ else
+ {
+ out = anchor;
+ l_out = l_anchor;
+ }
+
+ if ( l_in != 0 )
+ {
+ if ( k < 0 )
+ {
+ k = i;
+ anchor = in;
+ l_anchor = l_in;
+ }
+
+ d = in.x * out.x + in.y * out.y;
+
+ /* shift only if turn is less than ~160 degrees */
+ if ( d > -15.f/16.f )
+ {
+ d = d + 1.f;
+
+ /* shift components along lateral bisector in proper orientation */
+ shift.x = in.y + out.y;
+ shift.y = in.x + out.x;
+
+ if ( orientation_negative )
+ shift.x = -shift.x;
+ else
+ shift.y = -shift.y;
+
+ /* restrict shift magnitude to better handle collapsing segments */
+ q = out.x * in.y - out.y * in.x;
+ if ( orientation_negative )
+ q = -q;
+
+ l = hb_min (l_in, l_out);
+
+ /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
+ if (x_strength * q <= l * d)
+ shift.x = shift.x * x_strength / d;
+ else
+ shift.x = shift.x * l / q;
+
+
+ if (y_strength * q <= l * d)
+ shift.y = shift.y * y_strength / d;
+ else
+ shift.y = shift.y * l / q;
+ }
+ else
+ shift.x = shift.y = 0;
+
+ for ( ;
+ i != j;
+ i = i < last ? i + 1 : first )
+ {
+ points[i].x += x_shift + shift.x;
+ points[i].y += y_shift + shift.y;
+ }
+ }
+ else
+ i = j;
+
+ in = out;
+ l_in = l_out;
+ }
+
+ first = last + 1;
+ }
+}
+
+static void
+hb_outline_recording_pen_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_outline_t *c = (hb_outline_t *) data;
+
+ c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::MOVE_TO});
+}
+
+static void
+hb_outline_recording_pen_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_outline_t *c = (hb_outline_t *) data;
+
+ c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::LINE_TO});
+}
+
+static void
+hb_outline_recording_pen_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_outline_t *c = (hb_outline_t *) data;
+
+ c->points.push (hb_outline_point_t {control_x, control_y, hb_outline_point_t::type_t::QUADRATIC_TO});
+ c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::QUADRATIC_TO});
+}
+
+static void
+hb_outline_recording_pen_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *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_outline_t *c = (hb_outline_t *) data;
+
+ c->points.push (hb_outline_point_t {control1_x, control1_y, hb_outline_point_t::type_t::CUBIC_TO});
+ c->points.push (hb_outline_point_t {control2_x, control2_y, hb_outline_point_t::type_t::CUBIC_TO});
+ c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::CUBIC_TO});
+}
+
+static void
+hb_outline_recording_pen_close_path (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ void *user_data HB_UNUSED)
+{
+ hb_outline_t *c = (hb_outline_t *) data;
+
+ c->contours.push (c->points.length);
+}
+
+static inline void free_static_outline_recording_pen_funcs ();
+
+static struct hb_outline_recording_pen_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_outline_recording_pen_funcs_lazy_loader_t>
+{
+ static hb_draw_funcs_t *create ()
+ {
+ hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
+
+ hb_draw_funcs_set_move_to_func (funcs, hb_outline_recording_pen_move_to, nullptr, nullptr);
+ hb_draw_funcs_set_line_to_func (funcs, hb_outline_recording_pen_line_to, nullptr, nullptr);
+ hb_draw_funcs_set_quadratic_to_func (funcs, hb_outline_recording_pen_quadratic_to, nullptr, nullptr);
+ hb_draw_funcs_set_cubic_to_func (funcs, hb_outline_recording_pen_cubic_to, nullptr, nullptr);
+ hb_draw_funcs_set_close_path_func (funcs, hb_outline_recording_pen_close_path, nullptr, nullptr);
+
+ hb_draw_funcs_make_immutable (funcs);
+
+ hb_atexit (free_static_outline_recording_pen_funcs);
+
+ return funcs;
+ }
+} static_outline_recording_pen_funcs;
+
+static inline
+void free_static_outline_recording_pen_funcs ()
+{
+ static_outline_recording_pen_funcs.free_instance ();
+}
+
+hb_draw_funcs_t *
+hb_outline_recording_pen_get_funcs ()
+{
+ return static_outline_recording_pen_funcs.get_unconst ();
+}
+
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/test-unicode-ranges.cc b/src/3rdparty/harfbuzz-ng/src/hb-outline.hh
index 33cac6b715..c463993cfb 100644
--- a/src/3rdparty/harfbuzz-ng/src/test-unicode-ranges.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-outline.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2018 Google, Inc.
+ * Copyright © 2023 Behdad Esfahbod
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -20,47 +20,64 @@
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger
*/
+#ifndef HB_OUTLINE_HH
+#define HB_OUTLINE_HH
+
#include "hb.hh"
-#include "hb-ot-os2-unicode-ranges.hh"
-static void
-test (hb_codepoint_t cp, unsigned int bit)
+#include "hb-draw.hh"
+
+
+struct hb_outline_point_t
+{
+ enum class type_t
+ {
+ MOVE_TO,
+ LINE_TO,
+ QUADRATIC_TO,
+ CUBIC_TO,
+ };
+
+ hb_outline_point_t (float x, float y, type_t type) :
+ x (x), y (y), type (type) {}
+
+ float x, y;
+ type_t type;
+};
+
+struct hb_outline_vector_t
{
- if (OT::_hb_ot_os2_get_unicode_range_bit (cp) != bit)
+ float normalize_len ()
{
- fprintf (stderr, "got incorrect bit (%d) for cp 0x%X. Should have been %d.",
- OT::_hb_ot_os2_get_unicode_range_bit (cp),
- cp,
- bit);
- abort();
+ float len = hypotf (x, y);
+ if (len)
+ {
+ x /= len;
+ y /= len;
+ }
+ return len;
}
-}
-static void
-test_get_unicode_range_bit ()
+ float x, y;
+};
+
+struct hb_outline_t
{
- test (0x0000, 0);
- test (0x0042, 0);
- test (0x007F, 0);
- test (0x0080, 1);
+ void reset () { points.shrink (0, false); contours.resize (0); }
- test (0x30A0, 50);
- test (0x30B1, 50);
- test (0x30FF, 50);
+ HB_INTERNAL void replay (hb_draw_funcs_t *pen, void *pen_data) const;
+ HB_INTERNAL float area () const;
+ HB_INTERNAL void embolden (float x_strength, float y_strength,
+ float x_shift, float y_shift);
- test (0x10FFFD, 90);
+ hb_vector_t<hb_outline_point_t> points;
+ hb_vector_t<unsigned> contours;
+};
- test (0x30000, -1);
- test (0x110000, -1);
-}
+HB_INTERNAL hb_draw_funcs_t *
+hb_outline_recording_pen_get_funcs ();
-int
-main ()
-{
- test_get_unicode_range_bit ();
- return 0;
-}
+
+#endif /* HB_OUTLINE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-paint-extents.cc b/src/3rdparty/harfbuzz-ng/src/hb-paint-extents.cc
new file mode 100644
index 0000000000..2393322b71
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-paint-extents.cc
@@ -0,0 +1,330 @@
+/*
+ * 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"
+
+#ifndef HB_NO_PAINT
+
+#include "hb-paint-extents.hh"
+
+#include "hb-draw.h"
+
+#include "hb-machinery.hh"
+
+
+/*
+ * This file implements bounds-extraction as well as boundedness
+ * computation of COLRv1 fonts as described in:
+ *
+ * https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness
+ */
+
+static void
+hb_paint_extents_push_transform (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ float xx, float yx,
+ float xy, float yy,
+ float dx, float dy,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ c->push_transform (hb_transform_t {xx, yx, xy, yy, dx, dy});
+}
+
+static void
+hb_paint_extents_pop_transform (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ c->pop_transform ();
+}
+
+static void
+hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_extents_t *extents = (hb_extents_t *) data;
+
+ extents->add_point (to_x, to_y);
+}
+
+static void
+hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_extents_t *extents = (hb_extents_t *) data;
+
+ extents->add_point (to_x, to_y);
+}
+
+static void
+hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_extents_t *extents = (hb_extents_t *) data;
+
+ extents->add_point (control_x, control_y);
+ extents->add_point (to_x, to_y);
+}
+
+static void
+hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *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_extents_t *extents = (hb_extents_t *) data;
+
+ extents->add_point (control1_x, control1_y);
+ extents->add_point (control2_x, control2_y);
+ extents->add_point (to_x, to_y);
+}
+
+static inline void free_static_draw_extents_funcs ();
+
+static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_draw_extents_funcs_lazy_loader_t>
+{
+ static hb_draw_funcs_t *create ()
+ {
+ hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
+
+ hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr);
+ hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr);
+ hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr);
+ hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr);
+
+ hb_draw_funcs_make_immutable (funcs);
+
+ hb_atexit (free_static_draw_extents_funcs);
+
+ return funcs;
+ }
+} static_draw_extents_funcs;
+
+static inline
+void free_static_draw_extents_funcs ()
+{
+ static_draw_extents_funcs.free_instance ();
+}
+
+static hb_draw_funcs_t *
+hb_draw_extents_get_funcs ()
+{
+ return static_draw_extents_funcs.get_unconst ();
+}
+
+static void
+hb_paint_extents_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ hb_codepoint_t glyph,
+ hb_font_t *font,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ hb_extents_t extents;
+ hb_draw_funcs_t *draw_extent_funcs = hb_draw_extents_get_funcs ();
+ hb_font_draw_glyph (font, glyph, draw_extent_funcs, &extents);
+ c->push_clip (extents);
+}
+
+static void
+hb_paint_extents_push_clip_rectangle (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ float xmin, float ymin, float xmax, float ymax,
+ void *user_data)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ hb_extents_t extents = {xmin, ymin, xmax, ymax};
+ c->push_clip (extents);
+}
+
+static void
+hb_paint_extents_pop_clip (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ c->pop_clip ();
+}
+
+static void
+hb_paint_extents_push_group (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ c->push_group ();
+}
+
+static void
+hb_paint_extents_pop_group (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ hb_paint_composite_mode_t mode,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ c->pop_group (mode);
+}
+
+static hb_bool_t
+hb_paint_extents_paint_image (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ hb_blob_t *blob HB_UNUSED,
+ unsigned int width HB_UNUSED,
+ unsigned int height HB_UNUSED,
+ hb_tag_t format HB_UNUSED,
+ float slant HB_UNUSED,
+ hb_glyph_extents_t *glyph_extents,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ hb_extents_t extents = {(float) glyph_extents->x_bearing,
+ (float) glyph_extents->y_bearing + glyph_extents->height,
+ (float) glyph_extents->x_bearing + glyph_extents->width,
+ (float) glyph_extents->y_bearing};
+ c->push_clip (extents);
+ c->paint ();
+ c->pop_clip ();
+
+ return true;
+}
+
+static void
+hb_paint_extents_paint_color (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ hb_bool_t use_foreground HB_UNUSED,
+ hb_color_t color HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ c->paint ();
+}
+
+static void
+hb_paint_extents_paint_linear_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ hb_color_line_t *color_line HB_UNUSED,
+ float x0 HB_UNUSED, float y0 HB_UNUSED,
+ float x1 HB_UNUSED, float y1 HB_UNUSED,
+ float x2 HB_UNUSED, float y2 HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ c->paint ();
+}
+
+static void
+hb_paint_extents_paint_radial_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ hb_color_line_t *color_line HB_UNUSED,
+ float x0 HB_UNUSED, float y0 HB_UNUSED, float r0 HB_UNUSED,
+ float x1 HB_UNUSED, float y1 HB_UNUSED, float r1 HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ c->paint ();
+}
+
+static void
+hb_paint_extents_paint_sweep_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
+ void *paint_data,
+ hb_color_line_t *color_line HB_UNUSED,
+ float cx HB_UNUSED, float cy HB_UNUSED,
+ float start_angle HB_UNUSED,
+ float end_angle HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
+
+ c->paint ();
+}
+
+static inline void free_static_paint_extents_funcs ();
+
+static struct hb_paint_extents_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t<hb_paint_extents_funcs_lazy_loader_t>
+{
+ static hb_paint_funcs_t *create ()
+ {
+ hb_paint_funcs_t *funcs = hb_paint_funcs_create ();
+
+ hb_paint_funcs_set_push_transform_func (funcs, hb_paint_extents_push_transform, nullptr, nullptr);
+ hb_paint_funcs_set_pop_transform_func (funcs, hb_paint_extents_pop_transform, nullptr, nullptr);
+ hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_paint_extents_push_clip_glyph, nullptr, nullptr);
+ hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_paint_extents_push_clip_rectangle, nullptr, nullptr);
+ hb_paint_funcs_set_pop_clip_func (funcs, hb_paint_extents_pop_clip, nullptr, nullptr);
+ hb_paint_funcs_set_push_group_func (funcs, hb_paint_extents_push_group, nullptr, nullptr);
+ hb_paint_funcs_set_pop_group_func (funcs, hb_paint_extents_pop_group, nullptr, nullptr);
+ hb_paint_funcs_set_color_func (funcs, hb_paint_extents_paint_color, nullptr, nullptr);
+ hb_paint_funcs_set_image_func (funcs, hb_paint_extents_paint_image, nullptr, nullptr);
+ hb_paint_funcs_set_linear_gradient_func (funcs, hb_paint_extents_paint_linear_gradient, nullptr, nullptr);
+ hb_paint_funcs_set_radial_gradient_func (funcs, hb_paint_extents_paint_radial_gradient, nullptr, nullptr);
+ hb_paint_funcs_set_sweep_gradient_func (funcs, hb_paint_extents_paint_sweep_gradient, nullptr, nullptr);
+
+ hb_paint_funcs_make_immutable (funcs);
+
+ hb_atexit (free_static_paint_extents_funcs);
+
+ return funcs;
+ }
+} static_paint_extents_funcs;
+
+static inline
+void free_static_paint_extents_funcs ()
+{
+ static_paint_extents_funcs.free_instance ();
+}
+
+hb_paint_funcs_t *
+hb_paint_extents_get_funcs ()
+{
+ return static_paint_extents_funcs.get_unconst ();
+}
+
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-paint-extents.hh b/src/3rdparty/harfbuzz-ng/src/hb-paint-extents.hh
new file mode 100644
index 0000000000..f172bd42f9
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-paint-extents.hh
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+#ifndef HB_PAINT_EXTENTS_HH
+#define HB_PAINT_EXTENTS_HH
+
+#include "hb.hh"
+#include "hb-paint.h"
+
+
+typedef struct hb_extents_t
+{
+ hb_extents_t () {}
+ hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
+ xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
+
+ bool is_empty () const { return xmin >= xmax || ymin >= ymax; }
+ bool is_void () const { return xmin > xmax; }
+
+ void union_ (const hb_extents_t &o)
+ {
+ xmin = hb_min (xmin, o.xmin);
+ ymin = hb_min (ymin, o.ymin);
+ xmax = hb_max (xmax, o.xmax);
+ ymax = hb_max (ymax, o.ymax);
+ }
+
+ void intersect (const hb_extents_t &o)
+ {
+ xmin = hb_max (xmin, o.xmin);
+ ymin = hb_max (ymin, o.ymin);
+ xmax = hb_min (xmax, o.xmax);
+ ymax = hb_min (ymax, o.ymax);
+ }
+
+ void
+ add_point (float x, float y)
+ {
+ if (unlikely (is_void ()))
+ {
+ xmin = xmax = x;
+ ymin = ymax = y;
+ }
+ else
+ {
+ xmin = hb_min (xmin, x);
+ ymin = hb_min (ymin, y);
+ xmax = hb_max (xmax, x);
+ ymax = hb_max (ymax, y);
+ }
+ }
+
+ float xmin = 0.f;
+ float ymin = 0.f;
+ float xmax = -1.f;
+ float ymax = -1.f;
+} hb_extents_t;
+
+typedef struct hb_transform_t
+{
+ hb_transform_t () {}
+ hb_transform_t (float xx, float yx,
+ float xy, float yy,
+ float x0, float y0) :
+ xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {}
+
+ void multiply (const hb_transform_t &o)
+ {
+ /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */
+ hb_transform_t r;
+
+ r.xx = o.xx * xx + o.yx * xy;
+ r.yx = o.xx * yx + o.yx * yy;
+
+ r.xy = o.xy * xx + o.yy * xy;
+ r.yy = o.xy * yx + o.yy * yy;
+
+ r.x0 = o.x0 * xx + o.y0 * xy + x0;
+ r.y0 = o.x0 * yx + o.y0 * yy + y0;
+
+ *this = r;
+ }
+
+ void transform_distance (float &dx, float &dy) const
+ {
+ float new_x = xx * dx + xy * dy;
+ float new_y = yx * dx + yy * dy;
+ dx = new_x;
+ dy = new_y;
+ }
+
+ void transform_point (float &x, float &y) const
+ {
+ transform_distance (x, y);
+ x += x0;
+ y += y0;
+ }
+
+ void transform_extents (hb_extents_t &extents) const
+ {
+ float quad_x[4], quad_y[4];
+
+ quad_x[0] = extents.xmin;
+ quad_y[0] = extents.ymin;
+ quad_x[1] = extents.xmin;
+ quad_y[1] = extents.ymax;
+ quad_x[2] = extents.xmax;
+ quad_y[2] = extents.ymin;
+ quad_x[3] = extents.xmax;
+ quad_y[3] = extents.ymax;
+
+ extents = hb_extents_t {};
+ for (unsigned i = 0; i < 4; i++)
+ {
+ transform_point (quad_x[i], quad_y[i]);
+ extents.add_point (quad_x[i], quad_y[i]);
+ }
+ }
+
+ float xx = 1.f;
+ float yx = 0.f;
+ float xy = 0.f;
+ float yy = 1.f;
+ float x0 = 0.f;
+ float y0 = 0.f;
+} hb_transform_t;
+
+typedef struct hb_bounds_t
+{
+ enum status_t {
+ UNBOUNDED,
+ BOUNDED,
+ EMPTY,
+ };
+
+ hb_bounds_t (status_t status) : status (status) {}
+ hb_bounds_t (const hb_extents_t &extents) :
+ status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
+
+ void union_ (const hb_bounds_t &o)
+ {
+ if (o.status == UNBOUNDED)
+ status = UNBOUNDED;
+ else if (o.status == BOUNDED)
+ {
+ if (status == EMPTY)
+ *this = o;
+ else if (status == BOUNDED)
+ extents.union_ (o.extents);
+ }
+ }
+
+ void intersect (const hb_bounds_t &o)
+ {
+ if (o.status == EMPTY)
+ status = EMPTY;
+ else if (o.status == BOUNDED)
+ {
+ if (status == UNBOUNDED)
+ *this = o;
+ else if (status == BOUNDED)
+ {
+ extents.intersect (o.extents);
+ if (extents.is_empty ())
+ status = EMPTY;
+ }
+ }
+ }
+
+ status_t status;
+ hb_extents_t extents;
+} hb_bounds_t;
+
+typedef struct hb_paint_extents_context_t hb_paint_extents_context_t;
+
+struct hb_paint_extents_context_t
+{
+ hb_paint_extents_context_t ()
+ {
+ transforms.push (hb_transform_t{});
+ clips.push (hb_bounds_t{hb_bounds_t::UNBOUNDED});
+ groups.push (hb_bounds_t{hb_bounds_t::EMPTY});
+ }
+
+ hb_extents_t get_extents ()
+ {
+ return groups.tail().extents;
+ }
+
+ bool is_bounded ()
+ {
+ return groups.tail().status != hb_bounds_t::UNBOUNDED;
+ }
+
+ void push_transform (const hb_transform_t &trans)
+ {
+ hb_transform_t t = transforms.tail ();
+ t.multiply (trans);
+ transforms.push (t);
+ }
+
+ void pop_transform ()
+ {
+ transforms.pop ();
+ }
+
+ void push_clip (hb_extents_t extents)
+ {
+ /* Transform extents and push a new clip. */
+ const hb_transform_t &t = transforms.tail ();
+ t.transform_extents (extents);
+
+ clips.push (hb_bounds_t {extents});
+ }
+
+ void pop_clip ()
+ {
+ clips.pop ();
+ }
+
+ void push_group ()
+ {
+ groups.push (hb_bounds_t {hb_bounds_t::EMPTY});
+ }
+
+ void pop_group (hb_paint_composite_mode_t mode)
+ {
+ const hb_bounds_t src_bounds = groups.pop ();
+ hb_bounds_t &backdrop_bounds = groups.tail ();
+
+ // https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite
+ switch ((int) mode)
+ {
+ case HB_PAINT_COMPOSITE_MODE_CLEAR:
+ backdrop_bounds.status = hb_bounds_t::EMPTY;
+ break;
+ case HB_PAINT_COMPOSITE_MODE_SRC:
+ case HB_PAINT_COMPOSITE_MODE_SRC_OUT:
+ backdrop_bounds = src_bounds;
+ break;
+ case HB_PAINT_COMPOSITE_MODE_DEST:
+ case HB_PAINT_COMPOSITE_MODE_DEST_OUT:
+ break;
+ case HB_PAINT_COMPOSITE_MODE_SRC_IN:
+ case HB_PAINT_COMPOSITE_MODE_DEST_IN:
+ backdrop_bounds.intersect (src_bounds);
+ break;
+ default:
+ backdrop_bounds.union_ (src_bounds);
+ break;
+ }
+ }
+
+ void paint ()
+ {
+ const hb_bounds_t &clip = clips.tail ();
+ hb_bounds_t &group = groups.tail ();
+
+ group.union_ (clip);
+ }
+
+ protected:
+ hb_vector_t<hb_transform_t> transforms;
+ hb_vector_t<hb_bounds_t> clips;
+ hb_vector_t<hb_bounds_t> groups;
+};
+
+HB_INTERNAL hb_paint_funcs_t *
+hb_paint_extents_get_funcs ();
+
+
+#endif /* HB_PAINT_EXTENTS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-paint.cc b/src/3rdparty/harfbuzz-ng/src/hb-paint.cc
new file mode 100644
index 0000000000..28150f1638
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-paint.cc
@@ -0,0 +1,703 @@
+/*
+ * Copyright © 2022 Matthias Clasen
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_PAINT
+
+#include "hb-paint.hh"
+
+/**
+ * SECTION: hb-paint
+ * @title: hb-paint
+ * @short_description: Glyph painting
+ * @include: hb.h
+ *
+ * Functions for painting glyphs.
+ *
+ * The main purpose of these functions is to paint (extract) color glyph layers
+ * from the COLRv1 table, but the API works for drawing ordinary outlines and
+ * images as well.
+ *
+ * The #hb_paint_funcs_t struct can be used with hb_font_paint_glyph().
+ **/
+
+static void
+hb_paint_push_transform_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ float xx, float yx,
+ float xy, float yy,
+ float dx, float dy,
+ void *user_data) {}
+
+static void
+hb_paint_pop_transform_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ void *user_data) {}
+
+static void
+hb_paint_push_clip_glyph_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_codepoint_t glyph,
+ hb_font_t *font,
+ void *user_data) {}
+
+static void
+hb_paint_push_clip_rectangle_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ float xmin, float ymin, float xmax, float ymax,
+ void *user_data) {}
+
+static void
+hb_paint_pop_clip_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ void *user_data) {}
+
+static void
+hb_paint_color_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_bool_t is_foreground,
+ hb_color_t color,
+ void *user_data) {}
+
+static hb_bool_t
+hb_paint_image_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_blob_t *image,
+ unsigned int width,
+ unsigned int height,
+ hb_tag_t format,
+ float slant_xy,
+ hb_glyph_extents_t *extents,
+ void *user_data) { return false; }
+
+static void
+hb_paint_linear_gradient_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float x1, float y1,
+ float x2, float y2,
+ void *user_data) {}
+
+static void
+hb_paint_radial_gradient_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0, float r0,
+ float x1, float y1, float r1,
+ void *user_data) {}
+
+static void
+hb_paint_sweep_gradient_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float start_angle,
+ float end_angle,
+ void *user_data) {}
+
+static void
+hb_paint_push_group_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ void *user_data) {}
+
+static void
+hb_paint_pop_group_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_paint_composite_mode_t mode,
+ void *user_data) {}
+
+static hb_bool_t
+hb_paint_custom_palette_color_nil (hb_paint_funcs_t *funcs, void *paint_data,
+ unsigned int color_index,
+ hb_color_t *color,
+ void *user_data) { return false; }
+
+static bool
+_hb_paint_funcs_set_preamble (hb_paint_funcs_t *funcs,
+ bool func_is_null,
+ void **user_data,
+ hb_destroy_func_t *destroy)
+{
+ if (hb_object_is_immutable (funcs))
+ {
+ if (*destroy)
+ (*destroy) (*user_data);
+ return false;
+ }
+
+ if (func_is_null)
+ {
+ if (*destroy)
+ (*destroy) (*user_data);
+ *destroy = nullptr;
+ *user_data = nullptr;
+ }
+
+ return true;
+}
+
+static bool
+_hb_paint_funcs_set_middle (hb_paint_funcs_t *funcs,
+ void *user_data,
+ hb_destroy_func_t destroy)
+{
+ if (user_data && !funcs->user_data)
+ {
+ funcs->user_data = (decltype (funcs->user_data)) hb_calloc (1, sizeof (*funcs->user_data));
+ if (unlikely (!funcs->user_data))
+ goto fail;
+ }
+ if (destroy && !funcs->destroy)
+ {
+ funcs->destroy = (decltype (funcs->destroy)) hb_calloc (1, sizeof (*funcs->destroy));
+ if (unlikely (!funcs->destroy))
+ goto fail;
+ }
+
+ return true;
+
+fail:
+ if (destroy)
+ (destroy) (user_data);
+ return false;
+}
+
+#define HB_PAINT_FUNC_IMPLEMENT(name) \
+ \
+void \
+hb_paint_funcs_set_##name##_func (hb_paint_funcs_t *funcs, \
+ hb_paint_##name##_func_t func, \
+ void *user_data, \
+ hb_destroy_func_t destroy) \
+{ \
+ if (!_hb_paint_funcs_set_preamble (funcs, !func, &user_data, &destroy)) \
+ return; \
+ \
+ if (funcs->destroy && funcs->destroy->name) \
+ funcs->destroy->name (!funcs->user_data ? nullptr : funcs->user_data->name);\
+ \
+ if (!_hb_paint_funcs_set_middle (funcs, user_data, destroy)) \
+ return; \
+ \
+ if (func) \
+ funcs->func.name = func; \
+ else \
+ funcs->func.name = hb_paint_##name##_nil; \
+ \
+ if (funcs->user_data) \
+ funcs->user_data->name = user_data; \
+ if (funcs->destroy) \
+ funcs->destroy->name = destroy; \
+}
+
+HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_PAINT_FUNC_IMPLEMENT
+
+/**
+ * hb_paint_funcs_create:
+ *
+ * Creates a new #hb_paint_funcs_t structure of paint functions.
+ *
+ * The initial reference count of 1 should be released with hb_paint_funcs_destroy()
+ * when you are done using the #hb_paint_funcs_t. This function never returns
+ * `NULL`. If memory cannot be allocated, a special singleton #hb_paint_funcs_t
+ * object will be returned.
+ *
+ * Returns value: (transfer full): the paint-functions structure
+ *
+ * Since: 7.0.0
+ */
+hb_paint_funcs_t *
+hb_paint_funcs_create ()
+{
+ hb_paint_funcs_t *funcs;
+ if (unlikely (!(funcs = hb_object_create<hb_paint_funcs_t> ())))
+ return const_cast<hb_paint_funcs_t *> (&Null (hb_paint_funcs_t));
+
+ funcs->func = Null (hb_paint_funcs_t).func;
+
+ return funcs;
+}
+
+DEFINE_NULL_INSTANCE (hb_paint_funcs_t) =
+{
+ HB_OBJECT_HEADER_STATIC,
+
+ {
+#define HB_PAINT_FUNC_IMPLEMENT(name) hb_paint_##name##_nil,
+ HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_PAINT_FUNC_IMPLEMENT
+ }
+};
+
+/**
+ * hb_paint_funcs_get_empty:
+ *
+ * Fetches the singleton empty paint-functions structure.
+ *
+ * Return value: (transfer full): The empty paint-functions structure
+ *
+ * Since: 7.0.0
+ **/
+hb_paint_funcs_t *
+hb_paint_funcs_get_empty ()
+{
+ return const_cast<hb_paint_funcs_t *> (&Null (hb_paint_funcs_t));
+}
+
+/**
+ * hb_paint_funcs_reference: (skip)
+ * @funcs: The paint-functions structure
+ *
+ * Increases the reference count on a paint-functions structure.
+ *
+ * This prevents @funcs from being destroyed until a matching
+ * call to hb_paint_funcs_destroy() is made.
+ *
+ * Return value: The paint-functions structure
+ *
+ * Since: 7.0.0
+ */
+hb_paint_funcs_t *
+hb_paint_funcs_reference (hb_paint_funcs_t *funcs)
+{
+ return hb_object_reference (funcs);
+}
+
+/**
+ * hb_paint_funcs_destroy: (skip)
+ * @funcs: The paint-functions structure
+ *
+ * Decreases the reference count on a paint-functions structure.
+ *
+ * When the reference count reaches zero, the structure
+ * is destroyed, freeing all memory.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_funcs_destroy (hb_paint_funcs_t *funcs)
+{
+ if (!hb_object_destroy (funcs)) return;
+
+ if (funcs->destroy)
+ {
+#define HB_PAINT_FUNC_IMPLEMENT(name) \
+ if (funcs->destroy->name) funcs->destroy->name (!funcs->user_data ? nullptr : funcs->user_data->name);
+ HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_PAINT_FUNC_IMPLEMENT
+ }
+
+ hb_free (funcs->destroy);
+ hb_free (funcs->user_data);
+ hb_free (funcs);
+}
+
+/**
+ * hb_paint_funcs_set_user_data: (skip)
+ * @funcs: The paint-functions structure
+ * @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 paint-functions structure.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: 7.0.0
+ **/
+hb_bool_t
+hb_paint_funcs_set_user_data (hb_paint_funcs_t *funcs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (funcs, key, data, destroy, replace);
+}
+
+/**
+ * hb_paint_funcs_get_user_data: (skip)
+ * @funcs: The paint-functions structure
+ * @key: The user-data key to query
+ *
+ * Fetches the user-data associated with the specified key,
+ * attached to the specified paint-functions structure.
+ *
+ * Return value: (transfer none): A pointer to the user data
+ *
+ * Since: 7.0.0
+ **/
+void *
+hb_paint_funcs_get_user_data (const hb_paint_funcs_t *funcs,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (funcs, key);
+}
+
+/**
+ * hb_paint_funcs_make_immutable:
+ * @funcs: The paint-functions structure
+ *
+ * Makes a paint-functions structure immutable.
+ *
+ * After this call, all attempts to set one of the callbacks
+ * on @funcs will fail.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_funcs_make_immutable (hb_paint_funcs_t *funcs)
+{
+ if (hb_object_is_immutable (funcs))
+ return;
+
+ hb_object_make_immutable (funcs);
+}
+
+/**
+ * hb_paint_funcs_is_immutable:
+ * @funcs: The paint-functions structure
+ *
+ * Tests whether a paint-functions structure is immutable.
+ *
+ * Return value: `true` if @funcs is immutable, `false` otherwise
+ *
+ * Since: 7.0.0
+ */
+hb_bool_t
+hb_paint_funcs_is_immutable (hb_paint_funcs_t *funcs)
+{
+ return hb_object_is_immutable (funcs);
+}
+
+
+/**
+ * hb_color_line_get_color_stops:
+ * @color_line: a #hb_color_line_t object
+ * @start: the index of the first color stop to return
+ * @count: (inout) (optional): Input = the maximum number of feature tags to return;
+ * Output = the actual number of feature tags returned (may be zero)
+ * @color_stops: (out) (array length=count) (optional): Array of #hb_color_stop_t to populate
+ *
+ * Fetches a list of color stops from the given color line object.
+ *
+ * Note that due to variations being applied, the returned color stops
+ * may be out of order. It is the callers responsibility to ensure that
+ * color stops are sorted by their offset before they are used.
+ *
+ * Return value: the total number of color stops in @color_line
+ *
+ * Since: 7.0.0
+ */
+unsigned int
+hb_color_line_get_color_stops (hb_color_line_t *color_line,
+ unsigned int start,
+ unsigned int *count,
+ hb_color_stop_t *color_stops)
+{
+ return color_line->get_color_stops (color_line,
+ color_line->data,
+ start, count,
+ color_stops,
+ color_line->get_color_stops_user_data);
+}
+
+/**
+ * hb_color_line_get_extend:
+ * @color_line: a #hb_color_line_t object
+ *
+ * Fetches the extend mode of the color line object.
+ *
+ * Return value: the extend mode of @color_line
+ *
+ * Since: 7.0.0
+ */
+hb_paint_extend_t
+hb_color_line_get_extend (hb_color_line_t *color_line)
+{
+ return color_line->get_extend (color_line,
+ color_line->data,
+ color_line->get_extend_user_data);
+}
+
+
+/**
+ * hb_paint_push_transform:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @xx: xx component of the transform matrix
+ * @yx: yx component of the transform matrix
+ * @xy: xy component of the transform matrix
+ * @yy: yy component of the transform matrix
+ * @dx: dx component of the transform matrix
+ * @dy: dy component of the transform matrix
+ *
+ * Perform a "push-transform" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_push_transform (hb_paint_funcs_t *funcs, void *paint_data,
+ float xx, float yx,
+ float xy, float yy,
+ float dx, float dy)
+{
+ funcs->push_transform (paint_data, xx, yx, xy, yy, dx, dy);
+}
+
+/**
+ * hb_paint_pop_transform:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ *
+ * Perform a "pop-transform" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data)
+{
+ funcs->pop_transform (paint_data);
+}
+
+/**
+ * hb_paint_push_clip_glyph:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @glyph: the glyph ID
+ * @font: the font
+ *
+ * Perform a "push-clip-glyph" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_push_clip_glyph (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_codepoint_t glyph,
+ hb_font_t *font)
+{
+ funcs->push_clip_glyph (paint_data, glyph, font);
+}
+
+/**
+ * hb_paint_push_clip_rectangle:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @xmin: min X for the rectangle
+ * @ymin: min Y for the rectangle
+ * @xmax: max X for the rectangle
+ * @ymax: max Y for the rectangle
+ *
+ * Perform a "push-clip-rect" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_push_clip_rectangle (hb_paint_funcs_t *funcs, void *paint_data,
+ float xmin, float ymin, float xmax, float ymax)
+{
+ funcs->push_clip_rectangle (paint_data, xmin, ymin, xmax, ymax);
+}
+
+/**
+ * hb_paint_pop_clip:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ *
+ * Perform a "pop-clip" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_pop_clip (hb_paint_funcs_t *funcs, void *paint_data)
+{
+ funcs->pop_clip (paint_data);
+}
+
+/**
+ * hb_paint_color:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @is_foreground: whether the color is the foreground
+ * @color: The color to use
+ *
+ * Perform a "color" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_color (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_bool_t is_foreground,
+ hb_color_t color)
+{
+ funcs->color (paint_data, is_foreground, color);
+}
+
+/**
+ * hb_paint_image:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @image: image data
+ * @width: width of the raster image in pixels, or 0
+ * @height: height of the raster image in pixels, or 0
+ * @format: the image format as a tag
+ * @slant: the synthetic slant ratio to be applied to the image during rendering
+ * @extents: (nullable): the extents of the glyph
+ *
+ * Perform a "image" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_image (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_blob_t *image,
+ unsigned int width,
+ unsigned int height,
+ hb_tag_t format,
+ float slant,
+ hb_glyph_extents_t *extents)
+{
+ funcs->image (paint_data, image, width, height, format, slant, extents);
+}
+
+/**
+ * hb_paint_linear_gradient:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @color_line: Color information for the gradient
+ * @x0: X coordinate of the first point
+ * @y0: Y coordinate of the first point
+ * @x1: X coordinate of the second point
+ * @y1: Y coordinate of the second point
+ * @x2: X coordinate of the third point
+ * @y2: Y coordinate of the third point
+ *
+ * Perform a "linear-gradient" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_linear_gradient (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float x1, float y1,
+ float x2, float y2)
+{
+ funcs->linear_gradient (paint_data, color_line, x0, y0, x1, y1, x2, y2);
+}
+
+/**
+ * hb_paint_radial_gradient:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @color_line: Color information for the gradient
+ * @x0: X coordinate of the first circle's center
+ * @y0: Y coordinate of the first circle's center
+ * @r0: radius of the first circle
+ * @x1: X coordinate of the second circle's center
+ * @y1: Y coordinate of the second circle's center
+ * @r1: radius of the second circle
+ *
+ * Perform a "radial-gradient" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_radial_gradient (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0, float r0,
+ float x1, float y1, float r1)
+{
+ funcs->radial_gradient (paint_data, color_line, x0, y0, r0, y1, x1, r1);
+}
+
+/**
+ * hb_paint_sweep_gradient:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @color_line: Color information for the gradient
+ * @x0: X coordinate of the circle's center
+ * @y0: Y coordinate of the circle's center
+ * @start_angle: the start angle
+ * @end_angle: the end angle
+ *
+ * Perform a "sweep-gradient" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_sweep_gradient (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float start_angle, float end_angle)
+{
+ funcs->sweep_gradient (paint_data, color_line, x0, y0, start_angle, end_angle);
+}
+
+/**
+ * hb_paint_push_group:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ *
+ * Perform a "push-group" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_push_group (hb_paint_funcs_t *funcs, void *paint_data)
+{
+ funcs->push_group (paint_data);
+}
+
+/**
+ * hb_paint_pop_group:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @mode: the compositing mode to use
+ *
+ * Perform a "pop-group" paint operation.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_paint_pop_group (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_paint_composite_mode_t mode)
+{
+ funcs->pop_group (paint_data, mode);
+}
+
+/**
+ * hb_paint_custom_palette_color:
+ * @funcs: paint functions
+ * @paint_data: associated data passed by the caller
+ * @color_index: color index
+ * @color: (out): fetched color
+ *
+ * Gets the custom palette color for @color_index.
+ *
+ * Return value: `true` if found, `false` otherwise
+ *
+ * Since: 7.0.0
+ */
+hb_bool_t
+hb_paint_custom_palette_color (hb_paint_funcs_t *funcs, void *paint_data,
+ unsigned int color_index,
+ hb_color_t *color)
+{
+ return funcs->custom_palette_color (paint_data, color_index, color);
+}
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-paint.h b/src/3rdparty/harfbuzz-ng/src/hb-paint.h
new file mode 100644
index 0000000000..a734f112cc
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-paint.h
@@ -0,0 +1,987 @@
+/*
+ * Copyright © 2022 Matthias Clasen
+ *
+ * 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.
+ */
+
+#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
+#error "Include <hb.h> instead."
+#endif
+
+#ifndef HB_PAINT_H
+#define HB_PAINT_H
+
+#include "hb-common.h"
+
+HB_BEGIN_DECLS
+
+
+/**
+ * hb_paint_funcs_t:
+ *
+ * Glyph paint callbacks.
+ *
+ * The callbacks assume that the caller maintains a stack
+ * of current transforms, clips and intermediate surfaces,
+ * as evidenced by the pairs of push/pop callbacks. The
+ * push/pop calls will be properly nested, so it is fine
+ * to store the different kinds of object on a single stack.
+ *
+ * Not all callbacks are required for all kinds of glyphs.
+ * For rendering COLRv0 or non-color outline glyphs, the
+ * gradient callbacks are not needed, and the composite
+ * callback only needs to handle simple alpha compositing
+ * (#HB_PAINT_COMPOSITE_MODE_SRC_OVER).
+ *
+ * The paint-image callback is only needed for glyphs
+ * with image blobs in the CBDT, sbix or SVG tables.
+ *
+ * The custom-palette-color callback is only necessary if
+ * you want to override colors from the font palette with
+ * custom colors.
+ *
+ * Since: 7.0.0
+ **/
+typedef struct hb_paint_funcs_t hb_paint_funcs_t;
+
+HB_EXTERN hb_paint_funcs_t *
+hb_paint_funcs_create (void);
+
+HB_EXTERN hb_paint_funcs_t *
+hb_paint_funcs_get_empty (void);
+
+HB_EXTERN hb_paint_funcs_t *
+hb_paint_funcs_reference (hb_paint_funcs_t *funcs);
+
+HB_EXTERN void
+hb_paint_funcs_destroy (hb_paint_funcs_t *funcs);
+
+HB_EXTERN hb_bool_t
+hb_paint_funcs_set_user_data (hb_paint_funcs_t *funcs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+
+HB_EXTERN void *
+hb_paint_funcs_get_user_data (const hb_paint_funcs_t *funcs,
+ hb_user_data_key_t *key);
+
+HB_EXTERN void
+hb_paint_funcs_make_immutable (hb_paint_funcs_t *funcs);
+
+HB_EXTERN hb_bool_t
+hb_paint_funcs_is_immutable (hb_paint_funcs_t *funcs);
+
+/**
+ * hb_paint_push_transform_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @xx: xx component of the transform matrix
+ * @yx: yx component of the transform matrix
+ * @xy: xy component of the transform matrix
+ * @yy: yy component of the transform matrix
+ * @dx: dx component of the transform matrix
+ * @dy: dy component of the transform matrix
+ * @user_data: User data pointer passed to hb_paint_funcs_set_push_transform_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to apply
+ * a transform to subsequent paint calls.
+ *
+ * This transform is applied after the current transform,
+ * and remains in effect until a matching call to
+ * the #hb_paint_funcs_pop_transform_func_t vfunc.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_push_transform_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ float xx, float yx,
+ float xy, float yy,
+ float dx, float dy,
+ void *user_data);
+
+/**
+ * hb_paint_pop_transform_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @user_data: User data pointer passed to hb_paint_funcs_set_pop_transform_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to undo
+ * the effect of a prior call to the #hb_paint_funcs_push_transform_func_t
+ * vfunc.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_pop_transform_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ void *user_data);
+
+/**
+ * hb_paint_push_clip_glyph_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @glyph: the glyph ID
+ * @font: the font
+ * @user_data: User data pointer passed to hb_paint_funcs_set_push_clip_glyph_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to clip
+ * subsequent paint calls to the outline of a glyph.
+ *
+ * The coordinates of the glyph outline are interpreted according
+ * to the current transform.
+ *
+ * This clip is applied in addition to the current clip,
+ * and remains in effect until a matching call to
+ * the #hb_paint_funcs_pop_clip_func_t vfunc.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_push_clip_glyph_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ hb_codepoint_t glyph,
+ hb_font_t *font,
+ void *user_data);
+
+/**
+ * hb_paint_push_clip_rectangle_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @xmin: min X for the rectangle
+ * @ymin: min Y for the rectangle
+ * @xmax: max X for the rectangle
+ * @ymax: max Y for the rectangle
+ * @user_data: User data pointer passed to hb_paint_funcs_set_push_clip_rectangle_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to clip
+ * subsequent paint calls to a rectangle.
+ *
+ * The coordinates of the rectangle are interpreted according
+ * to the current transform.
+ *
+ * This clip is applied in addition to the current clip,
+ * and remains in effect until a matching call to
+ * the #hb_paint_funcs_pop_clip_func_t vfunc.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_push_clip_rectangle_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ float xmin, float ymin,
+ float xmax, float ymax,
+ void *user_data);
+
+/**
+ * hb_paint_pop_clip_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @user_data: User data pointer passed to hb_paint_funcs_set_pop_clip_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to undo
+ * the effect of a prior call to the #hb_paint_funcs_push_clip_glyph_func_t
+ * or #hb_paint_funcs_push_clip_rectangle_func_t vfuncs.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_pop_clip_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ void *user_data);
+
+/**
+ * hb_paint_color_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @is_foreground: whether the color is the foreground
+ * @color: The color to use, unpremultiplied
+ * @user_data: User data pointer passed to hb_paint_funcs_set_color_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to paint a
+ * color everywhere within the current clip.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_color_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ hb_bool_t is_foreground,
+ hb_color_t color,
+ void *user_data);
+
+/**
+ * HB_PAINT_IMAGE_FORMAT_PNG:
+ *
+ * Tag identifying PNG images in #hb_paint_image_func_t callbacks.
+ *
+ * Since: 7.0.0
+ */
+#define HB_PAINT_IMAGE_FORMAT_PNG HB_TAG('p','n','g',' ')
+
+/**
+ * HB_PAINT_IMAGE_FORMAT_SVG:
+ *
+ * Tag identifying SVG images in #hb_paint_image_func_t callbacks.
+ *
+ * Since: 7.0.0
+ */
+#define HB_PAINT_IMAGE_FORMAT_SVG HB_TAG('s','v','g',' ')
+
+/**
+ * HB_PAINT_IMAGE_FORMAT_BGRA:
+ *
+ * Tag identifying raw pixel-data images in #hb_paint_image_func_t callbacks.
+ * The data is in BGRA pre-multiplied sRGBA color-space format.
+ *
+ * Since: 7.0.0
+ */
+#define HB_PAINT_IMAGE_FORMAT_BGRA HB_TAG('B','G','R','A')
+
+/**
+ * hb_paint_image_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @image: the image data
+ * @width: width of the raster image in pixels, or 0
+ * @height: height of the raster image in pixels, or 0
+ * @format: the image format as a tag
+ * @slant: the synthetic slant ratio to be applied to the image during rendering
+ * @extents: (nullable): glyph extents for desired rendering
+ * @user_data: User data pointer passed to hb_paint_funcs_set_image_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to paint a glyph image.
+ *
+ * This method is called for glyphs with image blobs in the CBDT,
+ * sbix or SVG tables. The @format identifies the kind of data that
+ * is contained in @image. Possible values include #HB_PAINT_IMAGE_FORMAT_PNG,
+ * #HB_PAINT_IMAGE_FORMAT_SVG and #HB_PAINT_IMAGE_FORMAT_BGRA.
+ *
+ * The image dimensions and glyph extents are provided if available,
+ * and should be used to size and position the image.
+ *
+ * Return value: Whether the operation was successful.
+ *
+ * Since: 7.0.0
+ */
+typedef hb_bool_t (*hb_paint_image_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ hb_blob_t *image,
+ unsigned int width,
+ unsigned int height,
+ hb_tag_t format,
+ float slant,
+ hb_glyph_extents_t *extents,
+ void *user_data);
+
+/**
+ * hb_color_stop_t:
+ * @offset: the offset of the color stop
+ * @is_foreground: whether the color is the foreground
+ * @color: the color, unpremultiplied
+ *
+ * Information about a color stop on a color line.
+ *
+ * Color lines typically have offsets ranging between 0 and 1,
+ * but that is not required.
+ *
+ * Note: despite @color being unpremultiplied here, interpolation in
+ * gradients shall happen in premultiplied space. See the OpenType spec
+ * [COLR](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)
+ * section for details.
+ *
+ * Since: 7.0.0
+ */
+typedef struct {
+ float offset;
+ hb_bool_t is_foreground;
+ hb_color_t color;
+} hb_color_stop_t;
+
+/**
+ * hb_paint_extend_t:
+ * @HB_PAINT_EXTEND_PAD: Outside the defined interval,
+ * the color of the closest color stop is used.
+ * @HB_PAINT_EXTEND_REPEAT: The color line is repeated over
+ * repeated multiples of the defined interval
+ * @HB_PAINT_EXTEND_REFLECT: The color line is repeated over
+ * repeated intervals, as for the repeat mode.
+ * However, in each repeated interval, the ordering of
+ * color stops is the reverse of the adjacent interval.
+ *
+ * The values of this enumeration determine how color values
+ * outside the minimum and maximum defined offset on a #hb_color_line_t
+ * are determined.
+ *
+ * See the OpenType spec [COLR](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)
+ * section for details.
+ *
+ * Since: 7.0.0
+ */
+typedef enum {
+ HB_PAINT_EXTEND_PAD,
+ HB_PAINT_EXTEND_REPEAT,
+ HB_PAINT_EXTEND_REFLECT
+} hb_paint_extend_t;
+
+typedef struct hb_color_line_t hb_color_line_t;
+
+/**
+ * hb_color_line_get_color_stops_func_t:
+ * @color_line: a #hb_color_line_t object
+ * @color_line_data: the data accompanying @color_line
+ * @start: the index of the first color stop to return
+ * @count: (inout) (optional): Input = the maximum number of feature tags to return;
+ * Output = the actual number of feature tags returned (may be zero)
+ * @color_stops: (out) (array length=count) (optional): Array of #hb_color_stop_t to populate
+ * @user_data: the data accompanying this method
+ *
+ * A virtual method for the #hb_color_line_t to fetch color stops.
+ *
+ * Return value: the total number of color stops in @color_line
+ *
+ * Since: 7.0.0
+ */
+typedef unsigned int (*hb_color_line_get_color_stops_func_t) (hb_color_line_t *color_line,
+ void *color_line_data,
+ unsigned int start,
+ unsigned int *count,
+ hb_color_stop_t *color_stops,
+ void *user_data);
+
+/**
+ * hb_color_line_get_extend_func_t:
+ * @color_line: a #hb_color_line_t object
+ * @color_line_data: the data accompanying @color_line
+ * @user_data: the data accompanying this method
+ *
+ * A virtual method for the @hb_color_line_t to fetches the extend mode.
+ *
+ * Return value: the extend mode of @color_line
+ *
+ * Since: 7.0.0
+ */
+typedef hb_paint_extend_t (*hb_color_line_get_extend_func_t) (hb_color_line_t *color_line,
+ void *color_line_data,
+ void *user_data);
+
+/**
+ * hb_color_line_t:
+ *
+ * A struct containing color information for a gradient.
+ *
+ * Since: 7.0.0
+ */
+struct hb_color_line_t {
+ void *data;
+
+ hb_color_line_get_color_stops_func_t get_color_stops;
+ void *get_color_stops_user_data;
+
+ hb_color_line_get_extend_func_t get_extend;
+ void *get_extend_user_data;
+
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+ void *reserved3;
+ void *reserved5;
+ void *reserved6;
+ void *reserved7;
+ void *reserved8;
+};
+
+HB_EXTERN unsigned int
+hb_color_line_get_color_stops (hb_color_line_t *color_line,
+ unsigned int start,
+ unsigned int *count,
+ hb_color_stop_t *color_stops);
+
+HB_EXTERN hb_paint_extend_t
+hb_color_line_get_extend (hb_color_line_t *color_line);
+
+/**
+ * hb_paint_linear_gradient_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @color_line: Color information for the gradient
+ * @x0: X coordinate of the first point
+ * @y0: Y coordinate of the first point
+ * @x1: X coordinate of the second point
+ * @y1: Y coordinate of the second point
+ * @x2: X coordinate of the third point
+ * @y2: Y coordinate of the third point
+ * @user_data: User data pointer passed to hb_paint_funcs_set_linear_gradient_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to paint a linear
+ * gradient everywhere within the current clip.
+ *
+ * The @color_line object contains information about the colors of the gradients.
+ * It is only valid for the duration of the callback, you cannot keep it around.
+ *
+ * The coordinates of the points are interpreted according
+ * to the current transform.
+ *
+ * See the OpenType spec [COLR](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)
+ * section for details on how the points define the direction
+ * of the gradient, and how to interpret the @color_line.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_linear_gradient_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float x1, float y1,
+ float x2, float y2,
+ void *user_data);
+
+/**
+ * hb_paint_radial_gradient_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @color_line: Color information for the gradient
+ * @x0: X coordinate of the first circle's center
+ * @y0: Y coordinate of the first circle's center
+ * @r0: radius of the first circle
+ * @x1: X coordinate of the second circle's center
+ * @y1: Y coordinate of the second circle's center
+ * @r1: radius of the second circle
+ * @user_data: User data pointer passed to hb_paint_funcs_set_radial_gradient_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to paint a radial
+ * gradient everywhere within the current clip.
+ *
+ * The @color_line object contains information about the colors of the gradients.
+ * It is only valid for the duration of the callback, you cannot keep it around.
+ *
+ * The coordinates of the points are interpreted according
+ * to the current transform.
+ *
+ * See the OpenType spec [COLR](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)
+ * section for details on how the points define the direction
+ * of the gradient, and how to interpret the @color_line.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_radial_gradient_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0, float r0,
+ float x1, float y1, float r1,
+ void *user_data);
+
+/**
+ * hb_paint_sweep_gradient_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @color_line: Color information for the gradient
+ * @x0: X coordinate of the circle's center
+ * @y0: Y coordinate of the circle's center
+ * @start_angle: the start angle, in radians
+ * @end_angle: the end angle, in radians
+ * @user_data: User data pointer passed to hb_paint_funcs_set_sweep_gradient_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to paint a sweep
+ * gradient everywhere within the current clip.
+ *
+ * The @color_line object contains information about the colors of the gradients.
+ * It is only valid for the duration of the callback, you cannot keep it around.
+ *
+ * The coordinates of the points are interpreted according
+ * to the current transform.
+ *
+ * See the OpenType spec [COLR](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)
+ * section for details on how the points define the direction
+ * of the gradient, and how to interpret the @color_line.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_sweep_gradient_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float start_angle,
+ float end_angle,
+ void *user_data);
+
+/**
+ * hb_paint_composite_mode_t:
+ * @HB_PAINT_COMPOSITE_MODE_CLEAR: clear destination layer (bounded)
+ * @HB_PAINT_COMPOSITE_MODE_SRC: replace destination layer (bounded)
+ * @HB_PAINT_COMPOSITE_MODE_SRC_OVER: draw source layer on top of destination layer
+ * (bounded)
+ * @HB_PAINT_COMPOSITE_MODE_SRC_IN: draw source where there was destination content
+ * (unbounded)
+ * @HB_PAINT_COMPOSITE_MODE_SRC_OUT: draw source where there was no destination
+ * content (unbounded)
+ * @HB_PAINT_COMPOSITE_MODE_SRC_ATOP: draw source on top of destination content and
+ * only there
+ * @HB_PAINT_COMPOSITE_MODE_DEST: ignore the source
+ * @HB_PAINT_COMPOSITE_MODE_DEST_OVER: draw destination on top of source
+ * @HB_PAINT_COMPOSITE_MODE_DEST_IN: leave destination only where there was
+ * source content (unbounded)
+ * @HB_PAINT_COMPOSITE_MODE_DEST_OUT: leave destination only where there was no
+ * source content
+ * @HB_PAINT_COMPOSITE_MODE_DEST_ATOP: leave destination on top of source content
+ * and only there (unbounded)
+ * @HB_PAINT_COMPOSITE_MODE_XOR: source and destination are shown where there is only
+ * one of them
+ * @HB_PAINT_COMPOSITE_MODE_PLUS: source and destination layers are accumulated
+ * @HB_PAINT_COMPOSITE_MODE_MULTIPLY: source and destination layers are multiplied.
+ * This causes the result to be at least as dark as the darker inputs.
+ * @HB_PAINT_COMPOSITE_MODE_SCREEN: source and destination are complemented and
+ * multiplied. This causes the result to be at least as light as the lighter
+ * inputs.
+ * @HB_PAINT_COMPOSITE_MODE_OVERLAY: multiplies or screens, depending on the
+ * lightness of the destination color.
+ * @HB_PAINT_COMPOSITE_MODE_DARKEN: replaces the destination with the source if it
+ * is darker, otherwise keeps the source.
+ * @HB_PAINT_COMPOSITE_MODE_LIGHTEN: replaces the destination with the source if it
+ * is lighter, otherwise keeps the source.
+ * @HB_PAINT_COMPOSITE_MODE_COLOR_DODGE: brightens the destination color to reflect
+ * the source color.
+ * @HB_PAINT_COMPOSITE_MODE_COLOR_BURN: darkens the destination color to reflect
+ * the source color.
+ * @HB_PAINT_COMPOSITE_MODE_HARD_LIGHT: Multiplies or screens, dependent on source
+ * color.
+ * @HB_PAINT_COMPOSITE_MODE_SOFT_LIGHT: Darkens or lightens, dependent on source
+ * color.
+ * @HB_PAINT_COMPOSITE_MODE_DIFFERENCE: Takes the difference of the source and
+ * destination color.
+ * @HB_PAINT_COMPOSITE_MODE_EXCLUSION: Produces an effect similar to difference, but
+ * with lower contrast.
+ * @HB_PAINT_COMPOSITE_MODE_HSL_HUE: Creates a color with the hue of the source
+ * and the saturation and luminosity of the target.
+ * @HB_PAINT_COMPOSITE_MODE_HSL_SATURATION: Creates a color with the saturation
+ * of the source and the hue and luminosity of the target. Painting with
+ * this mode onto a gray area produces no change.
+ * @HB_PAINT_COMPOSITE_MODE_HSL_COLOR: Creates a color with the hue and saturation
+ * of the source and the luminosity of the target. This preserves the gray
+ * levels of the target and is useful for coloring monochrome images or
+ * tinting color images.
+ * @HB_PAINT_COMPOSITE_MODE_HSL_LUMINOSITY: Creates a color with the luminosity of
+ * the source and the hue and saturation of the target. This produces an
+ * inverse effect to @HB_PAINT_COMPOSITE_MODE_HSL_COLOR.
+ *
+ * The values of this enumeration describe the compositing modes
+ * that can be used when combining temporary redirected drawing
+ * with the backdrop.
+ *
+ * See the OpenType spec [COLR](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)
+ * section for details.
+ *
+ * Since: 7.0.0
+ */
+typedef enum {
+ HB_PAINT_COMPOSITE_MODE_CLEAR,
+ HB_PAINT_COMPOSITE_MODE_SRC,
+ HB_PAINT_COMPOSITE_MODE_DEST,
+ HB_PAINT_COMPOSITE_MODE_SRC_OVER,
+ HB_PAINT_COMPOSITE_MODE_DEST_OVER,
+ HB_PAINT_COMPOSITE_MODE_SRC_IN,
+ HB_PAINT_COMPOSITE_MODE_DEST_IN,
+ HB_PAINT_COMPOSITE_MODE_SRC_OUT,
+ HB_PAINT_COMPOSITE_MODE_DEST_OUT,
+ HB_PAINT_COMPOSITE_MODE_SRC_ATOP,
+ HB_PAINT_COMPOSITE_MODE_DEST_ATOP,
+ HB_PAINT_COMPOSITE_MODE_XOR,
+ HB_PAINT_COMPOSITE_MODE_PLUS,
+ HB_PAINT_COMPOSITE_MODE_SCREEN,
+ HB_PAINT_COMPOSITE_MODE_OVERLAY,
+ HB_PAINT_COMPOSITE_MODE_DARKEN,
+ HB_PAINT_COMPOSITE_MODE_LIGHTEN,
+ HB_PAINT_COMPOSITE_MODE_COLOR_DODGE,
+ HB_PAINT_COMPOSITE_MODE_COLOR_BURN,
+ HB_PAINT_COMPOSITE_MODE_HARD_LIGHT,
+ HB_PAINT_COMPOSITE_MODE_SOFT_LIGHT,
+ HB_PAINT_COMPOSITE_MODE_DIFFERENCE,
+ HB_PAINT_COMPOSITE_MODE_EXCLUSION,
+ HB_PAINT_COMPOSITE_MODE_MULTIPLY,
+ HB_PAINT_COMPOSITE_MODE_HSL_HUE,
+ HB_PAINT_COMPOSITE_MODE_HSL_SATURATION,
+ HB_PAINT_COMPOSITE_MODE_HSL_COLOR,
+ HB_PAINT_COMPOSITE_MODE_HSL_LUMINOSITY,
+} hb_paint_composite_mode_t;
+
+/**
+ * hb_paint_push_group_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @user_data: User data pointer passed to hb_paint_funcs_set_push_group_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to use
+ * an intermediate surface for subsequent paint calls.
+ *
+ * The drawing will be redirected to an intermediate surface
+ * until a matching call to the #hb_paint_funcs_pop_group_func_t
+ * vfunc.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_push_group_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ void *user_data);
+
+/**
+ * hb_paint_pop_group_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @mode: the compositing mode to use
+ * @user_data: User data pointer passed to hb_paint_funcs_set_pop_group_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to undo
+ * the effect of a prior call to the #hb_paint_funcs_push_group_func_t
+ * vfunc.
+ *
+ * This call stops the redirection to the intermediate surface,
+ * and then composites it on the previous surface, using the
+ * compositing mode passed to this call.
+ *
+ * Since: 7.0.0
+ */
+typedef void (*hb_paint_pop_group_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ hb_paint_composite_mode_t mode,
+ void *user_data);
+
+/**
+ * hb_paint_custom_palette_color_func_t:
+ * @funcs: paint functions object
+ * @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
+ * @color_index: the color index
+ * @color: (out): fetched color
+ * @user_data: User data pointer passed to hb_paint_funcs_set_pop_group_func()
+ *
+ * A virtual method for the #hb_paint_funcs_t to fetch a color from the custom
+ * color palette.
+ *
+ * Custom palette colors override the colors from the fonts selected color
+ * palette. It is not necessary to override all palette entries; for entries
+ * that should be taken from the font palette, return `false`.
+ *
+ * This function might get called multiple times, but the custom palette is
+ * expected to remain unchanged for duration of a hb_font_paint_glyph() call.
+ *
+ * Return value: `true` if found, `false` otherwise
+ *
+ * Since: 7.0.0
+ */
+typedef hb_bool_t (*hb_paint_custom_palette_color_func_t) (hb_paint_funcs_t *funcs,
+ void *paint_data,
+ unsigned int color_index,
+ hb_color_t *color,
+ void *user_data);
+
+
+/**
+ * hb_paint_funcs_set_push_transform_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The push-transform callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the push-transform callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_push_transform_func (hb_paint_funcs_t *funcs,
+ hb_paint_push_transform_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_pop_transform_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The pop-transform callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the pop-transform callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_pop_transform_func (hb_paint_funcs_t *funcs,
+ hb_paint_pop_transform_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_push_clip_glyph_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The push-clip-glyph callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the push-clip-glyph callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_push_clip_glyph_func (hb_paint_funcs_t *funcs,
+ hb_paint_push_clip_glyph_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_push_clip_rectangle_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The push-clip-rectangle callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the push-clip-rect callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_push_clip_rectangle_func (hb_paint_funcs_t *funcs,
+ hb_paint_push_clip_rectangle_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_pop_clip_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The pop-clip callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the pop-clip callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_pop_clip_func (hb_paint_funcs_t *funcs,
+ hb_paint_pop_clip_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_color_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The paint-color callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the paint-color callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_color_func (hb_paint_funcs_t *funcs,
+ hb_paint_color_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_image_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The paint-image callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the paint-image callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_image_func (hb_paint_funcs_t *funcs,
+ hb_paint_image_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_linear_gradient_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The linear-gradient callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the linear-gradient callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_linear_gradient_func (hb_paint_funcs_t *funcs,
+ hb_paint_linear_gradient_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_radial_gradient_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The radial-gradient callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the radial-gradient callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_radial_gradient_func (hb_paint_funcs_t *funcs,
+ hb_paint_radial_gradient_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_sweep_gradient_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The sweep-gradient callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the sweep-gradient callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_sweep_gradient_func (hb_paint_funcs_t *funcs,
+ hb_paint_sweep_gradient_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_push_group_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The push-group callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the push-group callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_push_group_func (hb_paint_funcs_t *funcs,
+ hb_paint_push_group_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_pop_group_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The pop-group callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the pop-group callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_pop_group_func (hb_paint_funcs_t *funcs,
+ hb_paint_pop_group_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+
+/**
+ * hb_paint_funcs_set_custom_palette_color_func:
+ * @funcs: A paint functions struct
+ * @func: (closure user_data) (destroy destroy) (scope notified): The custom-palette-color callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): Function to call when @user_data is no longer needed
+ *
+ * Sets the custom-palette-color callback on the paint functions struct.
+ *
+ * Since: 7.0.0
+ */
+HB_EXTERN void
+hb_paint_funcs_set_custom_palette_color_func (hb_paint_funcs_t *funcs,
+ hb_paint_custom_palette_color_func_t func,
+ void *user_data,
+ hb_destroy_func_t destroy);
+/*
+ * Manual API
+ */
+
+HB_EXTERN void
+hb_paint_push_transform (hb_paint_funcs_t *funcs, void *paint_data,
+ float xx, float yx,
+ float xy, float yy,
+ float dx, float dy);
+
+HB_EXTERN void
+hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data);
+
+HB_EXTERN void
+hb_paint_push_clip_glyph (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_codepoint_t glyph,
+ hb_font_t *font);
+
+HB_EXTERN void
+hb_paint_push_clip_rectangle (hb_paint_funcs_t *funcs, void *paint_data,
+ float xmin, float ymin,
+ float xmax, float ymax);
+
+HB_EXTERN void
+hb_paint_pop_clip (hb_paint_funcs_t *funcs, void *paint_data);
+
+HB_EXTERN void
+hb_paint_color (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_bool_t is_foreground,
+ hb_color_t color);
+
+HB_EXTERN void
+hb_paint_image (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_blob_t *image,
+ unsigned int width,
+ unsigned int height,
+ hb_tag_t format,
+ float slant,
+ hb_glyph_extents_t *extents);
+
+HB_EXTERN void
+hb_paint_linear_gradient (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float x1, float y1,
+ float x2, float y2);
+
+HB_EXTERN void
+hb_paint_radial_gradient (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float r0,
+ float x1, float y1,
+ float r1);
+
+HB_EXTERN void
+hb_paint_sweep_gradient (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float start_angle, float end_angle);
+
+HB_EXTERN void
+hb_paint_push_group (hb_paint_funcs_t *funcs, void *paint_data);
+
+HB_EXTERN void
+hb_paint_pop_group (hb_paint_funcs_t *funcs, void *paint_data,
+ hb_paint_composite_mode_t mode);
+
+HB_EXTERN hb_bool_t
+hb_paint_custom_palette_color (hb_paint_funcs_t *funcs, void *paint_data,
+ unsigned int color_index,
+ hb_color_t *color);
+
+HB_END_DECLS
+
+#endif /* HB_PAINT_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-paint.hh b/src/3rdparty/harfbuzz-ng/src/hb-paint.hh
new file mode 100644
index 0000000000..f7b71aa19b
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-paint.hh
@@ -0,0 +1,228 @@
+/*
+ * Copyright © 2022 Matthias Clasen
+ *
+ * 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_PAINT_HH
+#define HB_PAINT_HH
+
+#include "hb.hh"
+#include "hb-face.hh"
+#include "hb-font.hh"
+
+#define HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS \
+ HB_PAINT_FUNC_IMPLEMENT (push_transform) \
+ HB_PAINT_FUNC_IMPLEMENT (pop_transform) \
+ HB_PAINT_FUNC_IMPLEMENT (push_clip_glyph) \
+ HB_PAINT_FUNC_IMPLEMENT (push_clip_rectangle) \
+ HB_PAINT_FUNC_IMPLEMENT (pop_clip) \
+ HB_PAINT_FUNC_IMPLEMENT (color) \
+ HB_PAINT_FUNC_IMPLEMENT (image) \
+ HB_PAINT_FUNC_IMPLEMENT (linear_gradient) \
+ HB_PAINT_FUNC_IMPLEMENT (radial_gradient) \
+ HB_PAINT_FUNC_IMPLEMENT (sweep_gradient) \
+ HB_PAINT_FUNC_IMPLEMENT (push_group) \
+ HB_PAINT_FUNC_IMPLEMENT (pop_group) \
+ HB_PAINT_FUNC_IMPLEMENT (custom_palette_color) \
+ /* ^--- Add new callbacks here */
+
+struct hb_paint_funcs_t
+{
+ hb_object_header_t header;
+
+ struct {
+#define HB_PAINT_FUNC_IMPLEMENT(name) hb_paint_##name##_func_t name;
+ HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_PAINT_FUNC_IMPLEMENT
+ } func;
+
+ struct {
+#define HB_PAINT_FUNC_IMPLEMENT(name) void *name;
+ HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_PAINT_FUNC_IMPLEMENT
+ } *user_data;
+
+ struct {
+#define HB_PAINT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+ HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_PAINT_FUNC_IMPLEMENT
+ } *destroy;
+
+ void push_transform (void *paint_data,
+ float xx, float yx,
+ float xy, float yy,
+ float dx, float dy)
+ { func.push_transform (this, paint_data,
+ xx, yx, xy, yy, dx, dy,
+ !user_data ? nullptr : user_data->push_transform); }
+ void pop_transform (void *paint_data)
+ { func.pop_transform (this, paint_data,
+ !user_data ? nullptr : user_data->pop_transform); }
+ void push_clip_glyph (void *paint_data,
+ hb_codepoint_t glyph,
+ hb_font_t *font)
+ { func.push_clip_glyph (this, paint_data,
+ glyph,
+ font,
+ !user_data ? nullptr : user_data->push_clip_glyph); }
+ void push_clip_rectangle (void *paint_data,
+ float xmin, float ymin, float xmax, float ymax)
+ { func.push_clip_rectangle (this, paint_data,
+ xmin, ymin, xmax, ymax,
+ !user_data ? nullptr : user_data->push_clip_rectangle); }
+ void pop_clip (void *paint_data)
+ { func.pop_clip (this, paint_data,
+ !user_data ? nullptr : user_data->pop_clip); }
+ void color (void *paint_data,
+ hb_bool_t is_foreground,
+ hb_color_t color)
+ { func.color (this, paint_data,
+ is_foreground, color,
+ !user_data ? nullptr : user_data->color); }
+ bool image (void *paint_data,
+ hb_blob_t *image,
+ unsigned width, unsigned height,
+ hb_tag_t format,
+ float slant,
+ hb_glyph_extents_t *extents)
+ { return func.image (this, paint_data,
+ image, width, height, format, slant, extents,
+ !user_data ? nullptr : user_data->image); }
+ void linear_gradient (void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float x1, float y1,
+ float x2, float y2)
+ { func.linear_gradient (this, paint_data,
+ color_line, x0, y0, x1, y1, x2, y2,
+ !user_data ? nullptr : user_data->linear_gradient); }
+ void radial_gradient (void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0, float r0,
+ float x1, float y1, float r1)
+ { func.radial_gradient (this, paint_data,
+ color_line, x0, y0, r0, x1, y1, r1,
+ !user_data ? nullptr : user_data->radial_gradient); }
+ void sweep_gradient (void *paint_data,
+ hb_color_line_t *color_line,
+ float x0, float y0,
+ float start_angle,
+ float end_angle)
+ { func.sweep_gradient (this, paint_data,
+ color_line, x0, y0, start_angle, end_angle,
+ !user_data ? nullptr : user_data->sweep_gradient); }
+ void push_group (void *paint_data)
+ { func.push_group (this, paint_data,
+ !user_data ? nullptr : user_data->push_group); }
+ void pop_group (void *paint_data,
+ hb_paint_composite_mode_t mode)
+ { func.pop_group (this, paint_data,
+ mode,
+ !user_data ? nullptr : user_data->pop_group); }
+ bool custom_palette_color (void *paint_data,
+ unsigned int color_index,
+ hb_color_t *color)
+ { return func.custom_palette_color (this, paint_data,
+ color_index,
+ color,
+ !user_data ? nullptr : user_data->custom_palette_color); }
+
+
+ /* Internal specializations. */
+
+ void push_root_transform (void *paint_data,
+ const hb_font_t *font)
+ {
+ float upem = font->face->get_upem ();
+ int xscale = font->x_scale, yscale = font->y_scale;
+ float slant = font->slant_xy;
+
+ push_transform (paint_data,
+ xscale/upem, 0, slant * yscale/upem, yscale/upem, 0, 0);
+ }
+
+ void push_inverse_root_transform (void *paint_data,
+ hb_font_t *font)
+ {
+ float upem = font->face->get_upem ();
+ int xscale = font->x_scale ? font->x_scale : upem;
+ int yscale = font->y_scale ? font->y_scale : upem;
+ float slant = font->slant_xy;
+
+ push_transform (paint_data,
+ upem/xscale, 0, -slant * upem/xscale, upem/yscale, 0, 0);
+ }
+
+ HB_NODISCARD
+ bool push_translate (void *paint_data,
+ float dx, float dy)
+ {
+ if (!dx && !dy)
+ return false;
+
+ push_transform (paint_data,
+ 1.f, 0.f, 0.f, 1.f, dx, dy);
+ return true;
+ }
+
+ HB_NODISCARD
+ bool push_scale (void *paint_data,
+ float sx, float sy)
+ {
+ if (sx == 1.f && sy == 1.f)
+ return false;
+
+ push_transform (paint_data,
+ sx, 0.f, 0.f, sy, 0.f, 0.f);
+ return true;
+ }
+
+ HB_NODISCARD
+ bool push_rotate (void *paint_data,
+ float a)
+ {
+ if (!a)
+ return false;
+
+ float cc = cosf (a * (float) M_PI);
+ float ss = sinf (a * (float) M_PI);
+ push_transform (paint_data, cc, ss, -ss, cc, 0.f, 0.f);
+ return true;
+ }
+
+ HB_NODISCARD
+ bool push_skew (void *paint_data,
+ float sx, float sy)
+ {
+ if (!sx && !sy)
+ return false;
+
+ float x = tanf (-sx * (float) M_PI);
+ float y = tanf (+sy * (float) M_PI);
+ push_transform (paint_data, 1.f, y, x, 1.f, 0.f, 0.f);
+ return true;
+ }
+};
+DECLARE_NULL_INSTANCE (hb_paint_funcs_t);
+
+
+#endif /* HB_PAINT_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-pool.hh b/src/3rdparty/harfbuzz-ng/src/hb-pool.hh
index e4bb64f627..ee43721a38 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-pool.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-pool.hh
@@ -31,7 +31,7 @@
/* Memory pool for persistent allocation of small objects. */
-template <typename T, unsigned ChunkLen = 16>
+template <typename T, unsigned ChunkLen = 32>
struct hb_pool_t
{
hb_pool_t () : next (nullptr) {}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh b/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh
index ac76b7d955..93a7842eb0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh
@@ -62,7 +62,7 @@ struct hb_priority_queue_t
item_t result = heap.arrayZ[0];
heap.arrayZ[0] = heap.arrayZ[heap.length - 1];
- heap.shrink (heap.length - 1);
+ heap.resize (heap.length - 1);
if (!is_empty ())
bubble_down (0);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh b/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
index 7a3143cec3..cd57ade072 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
@@ -115,7 +115,7 @@ bool _promote_extensions_if_needed (graph::gsubgpos_graph_context_t& ext_context
if (!ext_context.lookups) return true;
hb_vector_t<lookup_size_t> lookup_sizes;
- lookup_sizes.alloc (ext_context.lookups.get_population ());
+ lookup_sizes.alloc (ext_context.lookups.get_population (), true);
for (unsigned lookup_index : ext_context.lookups.keys ())
{
@@ -216,7 +216,7 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& over
}
DEBUG_MSG (SUBSET_REPACK, nullptr,
- "Overflow in space %d (%d roots). Moving %d roots to space %d.",
+ "Overflow in space %u (%u roots). Moving %u roots to space %u.",
space,
sorted_graph.num_roots_for_space (space),
roots_to_isolate.get_population (),
@@ -326,7 +326,7 @@ hb_resolve_graph_overflows (hb_tag_t table_tag,
while (!sorted_graph.in_error ()
&& graph::will_overflow (sorted_graph, &overflows)
&& round < max_rounds) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %d ===", round);
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %u ===", round);
print_overflows (sorted_graph, overflows);
hb_set_t priority_bumped_parents;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
index bd3250e580..eb907c6b2a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
@@ -240,7 +240,7 @@ struct hb_sanitize_context_t :
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"check_range [%p..%p]"
- " (%d bytes) in [%p..%p] -> %s",
+ " (%u bytes) in [%p..%p] -> %s",
p, p + len, len,
this->start, this->end,
ok ? "OK" : "OUT-OF-RANGE");
@@ -308,7 +308,7 @@ struct hb_sanitize_context_t :
this->edit_count++;
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
- "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
+ "may_edit(%u) [%p..%p] (%u bytes) in [%p..%p] -> %s",
this->edit_count,
p, p + len, len,
this->start, this->end,
@@ -353,13 +353,13 @@ struct hb_sanitize_context_t :
{
if (edit_count)
{
- DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %d edits; going for second round", edit_count);
+ DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %u edits; going for second round", edit_count);
/* sanitize again to ensure no toe-stepping */
edit_count = 0;
sane = t->sanitize (this);
if (edit_count) {
- DEBUG_MSG_FUNC (SANITIZE, start, "requested %d edits in second round; FAILLING", edit_count);
+ DEBUG_MSG_FUNC (SANITIZE, start, "requested %u edits in second round; FAILLING", edit_count);
sane = false;
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh b/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
index d5573281f1..61ec0253a0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
@@ -81,11 +81,11 @@ struct hb_serialize_context_t
head = o.head;
tail = o.tail;
next = nullptr;
- real_links.alloc (o.num_real_links);
+ real_links.alloc (o.num_real_links, true);
for (unsigned i = 0 ; i < o.num_real_links; i++)
real_links.push (o.real_links[i]);
- virtual_links.alloc (o.num_virtual_links);
+ virtual_links.alloc (o.num_virtual_links, true);
for (unsigned i = 0; i < o.num_virtual_links; i++)
virtual_links.push (o.virtual_links[i]);
}
@@ -629,6 +629,13 @@ struct hb_serialize_context_t
template <typename Type>
Type *embed (const Type &obj)
{ return embed (std::addressof (obj)); }
+ char *embed (const char *obj, unsigned size)
+ {
+ char *ret = this->allocate_size<char> (size, false);
+ if (unlikely (!ret)) return nullptr;
+ hb_memcpy (ret, obj, size);
+ return ret;
+ }
template <typename Type, typename ...Ts> auto
_copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.cc b/src/3rdparty/harfbuzz-ng/src/hb-set.cc
index 0270b21998..97caddb226 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.cc
@@ -174,7 +174,7 @@ hb_set_allocation_successful (const hb_set_t *set)
*
* Allocate a copy of @set.
*
- * Return value: Newly-allocated set.
+ * Return value: (transfer full): Newly-allocated set.
*
* Since: 2.8.2
**/
@@ -182,7 +182,9 @@ hb_set_t *
hb_set_copy (const hb_set_t *set)
{
hb_set_t *copy = hb_set_create ();
- if (unlikely (!copy)) return nullptr;
+ if (unlikely (copy->in_error ()))
+ return hb_set_get_empty ();
+
copy->set (*set);
return copy;
}
@@ -492,6 +494,22 @@ hb_set_invert (hb_set_t *set)
}
/**
+ * hb_set_is_inverted:
+ * @set: A set
+ *
+ * Returns whether the set is inverted.
+ *
+ * Return value: `true` if the set is inverted, `false` otherwise
+ *
+ * Since: 7.0.0
+ **/
+hb_bool_t
+hb_set_is_inverted (const hb_set_t *set)
+{
+ return set->is_inverted ();
+}
+
+/**
* hb_set_get_population:
* @set: A set
*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.h b/src/3rdparty/harfbuzz-ng/src/hb-set.h
index 93636ab5d7..de53231030 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.h
@@ -98,6 +98,9 @@ HB_EXTERN void
hb_set_invert (hb_set_t *set);
HB_EXTERN hb_bool_t
+hb_set_is_inverted (const hb_set_t *set);
+
+HB_EXTERN hb_bool_t
hb_set_has (const hb_set_t *set,
hb_codepoint_t codepoint);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-set.hh
index f958a081fb..604802381b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.hh
@@ -79,6 +79,7 @@ struct hb_sparseset_t
void reset () { s.reset (); }
void clear () { s.clear (); }
void invert () { s.invert (); }
+ bool is_inverted () const { return s.is_inverted (); }
bool is_empty () const { return s.is_empty (); }
uint32_t hash () const { return s.hash (); }
@@ -170,6 +171,11 @@ struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t>
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
hb_set_t (const Iterable &o) : sparseset (o) {}
+
+ hb_set_t& operator << (hb_codepoint_t v)
+ { sparseset::operator<< (v); return *this; }
+ hb_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
+ { sparseset::operator<< (range); return *this; }
};
static_assert (hb_set_t::INVALID == HB_SET_VALUE_INVALID, "");
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
index cabcbd4e72..312eeb653e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
@@ -227,7 +227,7 @@ hb_shape_plan_create2 (hb_face_t *face,
const char * const *shaper_list)
{
DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr,
- "face=%p num_features=%d num_coords=%d shaper_list=%p",
+ "face=%p num_features=%u num_coords=%u shaper_list=%p",
face,
num_user_features,
num_coords,
@@ -391,7 +391,7 @@ _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan,
unsigned int num_features)
{
DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
- "num_features=%d shaper_func=%p, shaper_name=%s",
+ "num_features=%u shaper_func=%p, shaper_name=%s",
num_features,
shape_plan->key.shaper_func,
shape_plan->key.shaper_name);
@@ -520,7 +520,7 @@ hb_shape_plan_create_cached2 (hb_face_t *face,
const char * const *shaper_list)
{
DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr,
- "face=%p num_features=%d shaper_list=%p",
+ "face=%p num_features=%u shaper_list=%p",
face,
num_user_features,
shaper_list);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-static.cc b/src/3rdparty/harfbuzz-ng/src/hb-static.cc
index eac50754c2..5f647c6ad9 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-static.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-static.cc
@@ -33,13 +33,12 @@
#include "hb-aat-layout-feat-table.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-cmap-table.hh"
-#include "hb-ot-color-colr-table.hh"
+#include "OT/Color/COLR/COLR.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
#ifndef HB_NO_VISIBILITY
-#include "hb-ot-name-language-static.hh"
uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
@@ -109,36 +108,4 @@ hb_face_t::load_upem () const
}
-/* hb_user_data_array_t */
-
-bool
-hb_user_data_array_t::set (hb_user_data_key_t *key,
- void * data,
- hb_destroy_func_t destroy,
- hb_bool_t replace)
-{
- if (!key)
- return false;
-
- if (replace) {
- if (!data && !destroy) {
- items.remove (key, lock);
- return true;
- }
- }
- hb_user_data_item_t item = {key, data, destroy};
- bool ret = !!items.replace_or_insert (item, lock, (bool) replace);
-
- return ret;
-}
-
-void *
-hb_user_data_array_t::get (hb_user_data_key_t *key)
-{
- hb_user_data_item_t item = {nullptr, nullptr, nullptr};
-
- return items.find (key, &item, lock) ? item.data : nullptr;
-}
-
-
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh
index 63ae6d77e2..e523c25820 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh
@@ -56,37 +56,48 @@ struct hb_subset_accelerator_t
const hb_set_t& unicodes_,
bool has_seac_) {
hb_subset_accelerator_t* accel =
- (hb_subset_accelerator_t*) hb_malloc (sizeof(hb_subset_accelerator_t));
- new (accel) hb_subset_accelerator_t (unicode_to_gid_, gid_to_unicodes_, unicodes_);
- accel->has_seac = has_seac_;
- return accel;
- }
+ (hb_subset_accelerator_t*) hb_calloc (1, sizeof(hb_subset_accelerator_t));
- static void destroy(void* value) {
- if (!value) return;
+ new (accel) hb_subset_accelerator_t (unicode_to_gid_,
+ gid_to_unicodes_,
+ unicodes_,
+ has_seac_);
- hb_subset_accelerator_t* accel = (hb_subset_accelerator_t*) value;
+ return accel;
+ }
- if (accel->cff_accelerator && accel->destroy_cff_accelerator)
- accel->destroy_cff_accelerator ((void*) accel->cff_accelerator);
+ static void destroy (void* p)
+ {
+ if (!p) return;
- if (accel->cmap_cache && accel->destroy_cmap_cache)
- accel->destroy_cmap_cache ((void*) accel->cmap_cache);
+ hb_subset_accelerator_t *accel = (hb_subset_accelerator_t *) p;
accel->~hb_subset_accelerator_t ();
+
hb_free (accel);
}
hb_subset_accelerator_t (const hb_map_t& unicode_to_gid_,
const hb_multimap_t& gid_to_unicodes_,
- const hb_set_t& unicodes_)
- : unicode_to_gid(unicode_to_gid_), gid_to_unicodes (gid_to_unicodes_), unicodes(unicodes_),
- cmap_cache(nullptr), destroy_cmap_cache(nullptr),
- has_seac(false), cff_accelerator(nullptr), destroy_cff_accelerator(nullptr)
- { sanitized_table_cache_lock.init (); }
+ const hb_set_t& unicodes_,
+ bool has_seac_) :
+ unicode_to_gid(unicode_to_gid_),
+ gid_to_unicodes (gid_to_unicodes_),
+ unicodes(unicodes_),
+ cmap_cache(nullptr),
+ destroy_cmap_cache(nullptr),
+ has_seac(has_seac_),
+ cff_accelerator(nullptr),
+ destroy_cff_accelerator(nullptr) {}
~hb_subset_accelerator_t ()
- { sanitized_table_cache_lock.fini (); }
+ {
+ if (cff_accelerator && destroy_cff_accelerator)
+ destroy_cff_accelerator ((void*) cff_accelerator);
+
+ if (cmap_cache && destroy_cmap_cache)
+ destroy_cmap_cache ((void*) cmap_cache);
+ }
// Generic
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 8bbc017656..ff50b0e518 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
@@ -81,7 +81,8 @@ struct str_encoder_t
}
}
- void encode_num (const number_t& n)
+ // Encode number for CharString
+ void encode_num_cs (const number_t& n)
{
if (n.in_int_range ())
{
@@ -98,6 +99,91 @@ struct str_encoder_t
}
}
+ // Encode number for TopDict / Private
+ void encode_num_tp (const number_t& n)
+ {
+ if (n.in_int_range ())
+ {
+ // TODO longint
+ encode_int (n.to_int ());
+ }
+ else
+ {
+ // Sigh. BCD
+ // https://learn.microsoft.com/en-us/typography/opentype/spec/cff2#table-5-nibble-definitions
+ double v = n.to_real ();
+ encode_byte (OpCode_BCD);
+
+ // Based on:
+ // https://github.com/fonttools/fonttools/blob/97ed3a61cde03e17b8be36f866192fbd56f1d1a7/Lib/fontTools/misc/psCharStrings.py#L265-L294
+
+ char buf[16];
+ /* FontTools has the following comment:
+ *
+ * # Note: 14 decimal digits seems to be the limitation for CFF real numbers
+ * # in macOS. However, we use 8 here to match the implementation of AFDKO.
+ *
+ * We use 8 here to match FontTools X-).
+ */
+
+ hb_locale_t clocale HB_UNUSED;
+ hb_locale_t oldlocale HB_UNUSED;
+ oldlocale = hb_uselocale (clocale = newlocale (LC_ALL_MASK, "C", NULL));
+ snprintf (buf, sizeof (buf), "%.8G", v);
+ (void) hb_uselocale (((void) freelocale (clocale), oldlocale));
+
+ char *s = buf;
+ if (s[0] == '0' && s[1] == '.')
+ s++;
+ else if (s[0] == '-' && s[1] == '0' && s[2] == '.')
+ {
+ s[1] = '-';
+ s++;
+ }
+ hb_vector_t<char> nibbles;
+ while (*s)
+ {
+ char c = s[0];
+ s++;
+
+ switch (c)
+ {
+ case 'E':
+ {
+ char c2 = *s;
+ if (c2 == '-')
+ {
+ s++;
+ nibbles.push (0x0C); // E-
+ continue;
+ }
+ if (c2 == '+')
+ s++;
+ nibbles.push (0x0B); // E
+ continue;
+ }
+
+ case '.': case ',': // Comma for some European locales in case no uselocale available.
+ nibbles.push (0x0A); // .
+ continue;
+
+ case '-':
+ nibbles.push (0x0E); // .
+ continue;
+ }
+
+ nibbles.push (c - '0');
+ }
+ nibbles.push (0x0F);
+ if (nibbles.length % 2)
+ nibbles.push (0x0F);
+
+ unsigned count = nibbles.length;
+ for (unsigned i = 0; i < count; i += 2)
+ encode_byte ((nibbles[i] << 4) | nibbles[i+1]);
+ }
+ }
+
void encode_op (op_code_t op)
{
if (Is_OpCode_ESC (op))
@@ -190,39 +276,11 @@ struct cff_font_dict_op_serializer_t : op_serializer_t
}
};
-struct cff_private_dict_op_serializer_t : op_serializer_t
-{
- cff_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_)
- : desubroutinize (desubroutinize_), drop_hints (drop_hints_) {}
-
- bool serialize (hb_serialize_context_t *c,
- const op_str_t &opstr,
- objidx_t subrs_link) const
- {
- TRACE_SERIALIZE (this);
-
- if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
- return true;
- if (opstr.op == OpCode_Subrs)
- {
- if (desubroutinize || !subrs_link)
- return_trace (true);
- else
- return_trace (FontDict::serialize_link2_op (c, opstr.op, subrs_link));
- }
- else
- return_trace (copy_opstr (c, opstr));
- }
-
- protected:
- const bool desubroutinize;
- const bool drop_hints;
-};
-
struct flatten_param_t
{
str_buff_t &flatStr;
bool drop_hints;
+ const hb_subset_plan_t *plan;
};
template <typename ACC, typename ENV, typename OPSET, op_code_t endchar_op=OpCode_Invalid>
@@ -235,7 +293,7 @@ struct subr_flattener_t
bool flatten (str_buff_vec_t &flat_charstrings)
{
unsigned count = plan->num_output_glyphs ();
- if (!flat_charstrings.resize (count))
+ if (!flat_charstrings.resize_exact (count))
return false;
for (unsigned int i = 0; i < count; i++)
{
@@ -250,11 +308,15 @@ struct subr_flattener_t
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- ENV env (str, acc, fd);
+
+
+ ENV env (str, acc, fd,
+ plan->normalized_coords.arrayZ, plan->normalized_coords.length);
cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env);
flatten_param_t param = {
flat_charstrings.arrayZ[i],
- (bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ (bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING),
+ plan
};
if (unlikely (!interp.interpret (param)))
return false;
@@ -270,7 +332,7 @@ struct subr_closures_t
{
subr_closures_t (unsigned int fd_count) : global_closure (), local_closures ()
{
- local_closures.resize (fd_count);
+ local_closures.resize_exact (fd_count);
}
void reset ()
@@ -361,6 +423,35 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
bool has_calls () const { return has_calls_; }
+ void compact ()
+ {
+ unsigned count = values.length;
+ if (!count) return;
+ auto &opstr = values.arrayZ;
+ unsigned j = 0;
+ for (unsigned i = 1; i < count; i++)
+ {
+ /* See if we can combine op j and op i. */
+ bool combine =
+ (opstr[j].op != OpCode_callsubr && opstr[j].op != OpCode_callgsubr) &&
+ (opstr[i].op != OpCode_callsubr && opstr[i].op != OpCode_callgsubr) &&
+ (opstr[j].is_hinting () == opstr[i].is_hinting ()) &&
+ (opstr[j].ptr + opstr[j].length == opstr[i].ptr) &&
+ (opstr[j].length + opstr[i].length <= 255);
+
+ if (combine)
+ {
+ opstr[j].length += opstr[i].length;
+ opstr[j].op = OpCode_Invalid;
+ }
+ else
+ {
+ opstr[++j] = opstr[i];
+ }
+ }
+ values.shrink (j + 1);
+ }
+
protected:
bool parsed : 1;
bool hint_dropped : 1;
@@ -486,7 +577,7 @@ struct subr_subset_param_t
else
{
if (!parsed_str->is_parsed ())
- parsed_str->alloc (env.str_ref.total_size () / 2);
+ parsed_str->alloc (env.str_ref.total_size ());
current_parsed_str = parsed_str;
}
}
@@ -589,12 +680,12 @@ struct subr_subsetter_t
if (cff_accelerator) {
// If we are not dropping hinting then charstrings are not modified so we can
// just use a reference to the cached copies.
- cached_charstrings.resize (plan->num_output_glyphs ());
+ cached_charstrings.resize_exact (plan->num_output_glyphs ());
parsed_global_subrs = &cff_accelerator->parsed_global_subrs;
parsed_local_subrs = &cff_accelerator->parsed_local_subrs;
} else {
- parsed_charstrings.resize (plan->num_output_glyphs ());
- parsed_global_subrs_storage.resize (acc.globalSubrs->count);
+ parsed_charstrings.resize_exact (plan->num_output_glyphs ());
+ parsed_global_subrs_storage.resize_exact (acc.globalSubrs->count);
if (unlikely (!parsed_local_subrs_storage.resize (fd_count))) return false;
@@ -644,7 +735,7 @@ struct subr_subsetter_t
ENV env (str, acc, fd);
cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env);
- parsed_charstrings[i].alloc (str.length / 2);
+ parsed_charstrings[i].alloc (str.length);
subr_subset_param_t param (&parsed_charstrings[i],
&parsed_global_subrs_storage,
&parsed_local_subrs_storage[fd],
@@ -657,28 +748,10 @@ struct subr_subsetter_t
/* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
- }
-
- // Since parsed strings were loaded from accelerator, we still need
- // to compute the subroutine closures which would have normally happened during
- // parsing.
- if (cff_accelerator &&
- !closure_subroutines(*parsed_global_subrs,
- *parsed_local_subrs))
- return false;
- if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING && !cff_accelerator) ||
- plan->inprogress_accelerator)
- {
/* mark hint ops and arguments for drop */
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+ if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING) || plan->inprogress_accelerator)
{
- hb_codepoint_t glyph;
- if (!plan->old_gid_for_new_gid (i, &glyph))
- continue;
- unsigned int fd = acc.fdSelect->get_fd (glyph);
- if (unlikely (fd >= acc.fdCount))
- return false;
subr_subset_param_t param (&parsed_charstrings[i],
&parsed_global_subrs_storage,
&parsed_local_subrs_storage[fd],
@@ -695,21 +768,36 @@ struct subr_subsetter_t
}
}
- /* after dropping hints recreate closures of actually used subrs */
- if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING &&
- !cff_accelerator &&
- !closure_subroutines(*parsed_global_subrs, *parsed_local_subrs)) return false;
+ /* Doing this here one by one instead of compacting all at the en
+ * has massive peak-memory saving.
+ *
+ * The compacting both saves memory and makes further operations
+ * faster.
+ */
+ parsed_charstrings[i].compact ();
}
+ /* Since parsed strings were loaded from accelerator, we still need
+ * to compute the subroutine closures which would have normally happened during
+ * parsing.
+ *
+ * Or if we are dropping hinting, redo closure to get actually used subrs.
+ */
+ if ((cff_accelerator ||
+ (!cff_accelerator && plan->flags & HB_SUBSET_FLAGS_NO_HINTING)) &&
+ !closure_subroutines(*parsed_global_subrs,
+ *parsed_local_subrs))
+ return false;
+
remaps.create (closures);
populate_subset_accelerator ();
return true;
}
- bool encode_charstrings (str_buff_vec_t &buffArray) const
+ bool encode_charstrings (str_buff_vec_t &buffArray, bool encode_prefix = true) const
{
- if (unlikely (!buffArray.resize (plan->num_output_glyphs ())))
+ if (unlikely (!buffArray.resize_exact (plan->num_output_glyphs ())))
return false;
for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
{
@@ -723,7 +811,7 @@ struct subr_subsetter_t
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- if (unlikely (!encode_str (get_parsed_charstring (i), fd, buffArray.arrayZ[i])))
+ if (unlikely (!encode_str (get_parsed_charstring (i), fd, buffArray.arrayZ[i], encode_prefix)))
return false;
}
return true;
@@ -733,7 +821,7 @@ struct subr_subsetter_t
{
unsigned int count = remap.get_population ();
- if (unlikely (!buffArray.resize (count)))
+ if (unlikely (!buffArray.resize_exact (count)))
return false;
for (unsigned int new_num = 0; new_num < count; new_num++)
{
@@ -953,16 +1041,16 @@ struct subr_subsetter_t
}
}
- bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
+ bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff, bool encode_prefix = true) const
{
str_encoder_t encoder (buff);
encoder.reset ();
bool hinting = !(plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
/* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
* re-insert it at the beginning of charstreing */
- if (str.has_prefix () && !hinting && str.is_hint_dropped ())
+ if (encode_prefix && str.has_prefix () && !hinting && str.is_hint_dropped ())
{
- encoder.encode_num (str.prefix_num ());
+ encoder.encode_num_cs (str.prefix_num ());
if (str.prefix_op () != OpCode_Invalid)
encoder.encode_op (str.prefix_op ());
}
@@ -974,7 +1062,7 @@ struct subr_subsetter_t
if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr)
size += 3;
}
- if (!buff.alloc (buff.length + size))
+ if (!buff.alloc (buff.length + size, true))
return false;
for (auto &opstr : str.values)
@@ -1002,51 +1090,20 @@ struct subr_subsetter_t
return !encoder.in_error ();
}
- void compact_parsed_strings () const
+ void compact_parsed_subrs () const
{
- for (auto &cs : parsed_charstrings)
- compact_string (cs);
for (auto &cs : parsed_global_subrs_storage)
- compact_string (cs);
+ cs.compact ();
for (auto &vec : parsed_local_subrs_storage)
for (auto &cs : vec)
- compact_string (cs);
- }
-
- static void compact_string (parsed_cs_str_t &str)
- {
- unsigned count = str.values.length;
- if (unlikely (!count)) return;
- auto &opstr = str.values.arrayZ;
- unsigned j = 0;
- for (unsigned i = 1; i < count; i++)
- {
- /* See if we can combine op j and op i. */
- bool combine =
- (opstr[j].op != OpCode_callsubr && opstr[j].op != OpCode_callgsubr) &&
- (opstr[i].op != OpCode_callsubr && opstr[i].op != OpCode_callgsubr) &&
- (opstr[j].is_hinting () == opstr[i].is_hinting ()) &&
- (opstr[j].ptr + opstr[j].length == opstr[i].ptr) &&
- (opstr[j].length + opstr[i].length <= 255);
-
- if (combine)
- {
- opstr[j].length += opstr[i].length;
- opstr[j].op = OpCode_Invalid;
- }
- else
- {
- opstr[++j] = opstr[i];
- }
- }
- str.values.shrink (j + 1);
+ cs.compact ();
}
void populate_subset_accelerator () const
{
if (!plan->inprogress_accelerator) return;
- compact_parsed_strings ();
+ compact_parsed_subrs ();
plan->inprogress_accelerator->cff_accelerator =
cff_subset_accelerator_t::create(acc.blob,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
index 538f28f5aa..1d7ed6444a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
@@ -234,7 +234,7 @@ struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatte
{
str_encoder_t encoder (param.flatStr);
for (unsigned int i = env.arg_start; i < env.argStack.get_count (); i++)
- encoder.encode_num (env.eval_arg (i));
+ encoder.encode_num_cs (env.eval_arg (i));
SUPER::flush_args (env, param);
}
@@ -248,7 +248,7 @@ struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatte
{
assert (env.has_width);
str_encoder_t encoder (param.flatStr);
- encoder.encode_num (env.width);
+ encoder.encode_num_cs (env.width);
}
static void flush_hintmask (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
@@ -335,6 +335,36 @@ struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t<cff1_cs_opset_subr_subset_t
typedef cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
};
+struct cff1_private_dict_op_serializer_t : op_serializer_t
+{
+ cff1_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_)
+ : desubroutinize (desubroutinize_), drop_hints (drop_hints_) {}
+
+ bool serialize (hb_serialize_context_t *c,
+ const op_str_t &opstr,
+ objidx_t subrs_link) const
+ {
+ TRACE_SERIALIZE (this);
+
+ if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
+ return_trace (true);
+
+ if (opstr.op == OpCode_Subrs)
+ {
+ if (desubroutinize || !subrs_link)
+ return_trace (true);
+ else
+ return_trace (FontDict::serialize_link2_op (c, opstr.op, subrs_link));
+ }
+
+ return_trace (copy_opstr (c, opstr));
+ }
+
+ protected:
+ const bool desubroutinize;
+ const bool drop_hints;
+};
+
struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t, OpCode_endchar>
{
cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
@@ -721,7 +751,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
PrivateDict *pd = c->start_embed<PrivateDict> ();
if (unlikely (!pd)) return false;
c->push ();
- cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+ cff1_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link)))
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
index 60946b0281..8ab4620194 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
@@ -59,7 +59,10 @@ struct cff2_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<>
switch (opstr.op)
{
case OpCode_vstore:
- return_trace (FontDict::serialize_link4_op(c, opstr.op, info.var_store_link));
+ if (info.var_store_link)
+ return_trace (FontDict::serialize_link4_op(c, opstr.op, info.var_store_link));
+ else
+ return_trace (true);
default:
return_trace (cff_top_dict_op_serializer_t<>::serialize (c, opstr, info));
@@ -115,7 +118,7 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
else
{
str_encoder_t encoder (param.flatStr);
- encoder.encode_num (arg);
+ encoder.encode_num_cs (arg);
i++;
}
}
@@ -135,14 +138,14 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
env.set_error ();
return;
}
- encoder.encode_num (arg1);
+ encoder.encode_num_cs (arg1);
}
/* flatten deltas for each value */
for (unsigned int j = 0; j < arg.numValues; j++)
{
const blend_arg_t &arg1 = env.argStack[i + j];
for (unsigned int k = 0; k < arg1.deltas.length; k++)
- encoder.encode_num (arg1.deltas[k]);
+ encoder.encode_num_cs (arg1.deltas[k]);
}
/* flatten the number of values followed by blend operator */
encoder.encode_int (arg.numValues);
@@ -162,6 +165,17 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
}
}
+ static void flush_hintmask (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
+ {
+ SUPER::flush_hintmask (op, env, param);
+ if (!param.drop_hints)
+ {
+ str_encoder_t encoder (param.flatStr);
+ for (unsigned int i = 0; i < env.hintmask_size; i++)
+ encoder.encode_byte (env.str_ref[i]);
+ }
+ }
+
private:
typedef cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t, blend_arg_t> SUPER;
typedef cs_opset_t<blend_arg_t, cff2_cs_opset_flatten_t, cff2_cs_opset_flatten_t, cff2_cs_interp_env_t<blend_arg_t>, flatten_param_t> CSOPSET;
@@ -232,15 +246,193 @@ struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs
}
};
-struct cff2_subset_plan {
+struct cff2_private_blend_encoder_param_t
+{
+ cff2_private_blend_encoder_param_t (hb_serialize_context_t *c,
+ const CFF2VariationStore *varStore,
+ hb_array_t<int> normalized_coords) :
+ c (c), varStore (varStore), normalized_coords (normalized_coords) {}
+
+ void init () {}
+
+ void process_blend ()
+ {
+ if (!seen_blend)
+ {
+ region_count = varStore->varStore.get_region_index_count (ivs);
+ scalars.resize_exact (region_count);
+ varStore->varStore.get_region_scalars (ivs, normalized_coords.arrayZ, normalized_coords.length,
+ &scalars[0], region_count);
+ seen_blend = true;
+ }
+ }
+
+ double blend_deltas (hb_array_t<const number_t> deltas) const
+ {
+ double v = 0;
+ if (likely (scalars.length == deltas.length))
+ {
+ unsigned count = scalars.length;
+ for (unsigned i = 0; i < count; i++)
+ v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
+ }
+ return v;
+ }
+
+
+ hb_serialize_context_t *c = nullptr;
+ bool seen_blend = false;
+ unsigned ivs = 0;
+ unsigned region_count = 0;
+ hb_vector_t<float> scalars;
+ const CFF2VariationStore *varStore = nullptr;
+ hb_array_t<int> normalized_coords;
+};
+
+struct cff2_private_dict_blend_opset_t : dict_opset_t
+{
+ static void process_arg_blend (cff2_private_blend_encoder_param_t& param,
+ number_t &arg,
+ const hb_array_t<const number_t> blends,
+ unsigned n, unsigned i)
+ {
+ arg.set_int (round (arg.to_real () + param.blend_deltas (blends)));
+ }
+
+ static void process_blend (cff2_priv_dict_interp_env_t& env, cff2_private_blend_encoder_param_t& param)
+ {
+ unsigned int n, k;
+
+ param.process_blend ();
+ k = param.region_count;
+ n = env.argStack.pop_uint ();
+ /* copy the blend values into blend array of the default values */
+ unsigned int start = env.argStack.get_count () - ((k+1) * n);
+ /* let an obvious error case fail, but note CFF2 spec doesn't forbid n==0 */
+ if (unlikely (start > env.argStack.get_count ()))
+ {
+ env.set_error ();
+ return;
+ }
+ for (unsigned int i = 0; i < n; i++)
+ {
+ const hb_array_t<const number_t> blends = env.argStack.sub_array (start + n + (i * k), k);
+ process_arg_blend (param, env.argStack[start + i], blends, n, i);
+ }
+
+ /* pop off blend values leaving default values now adorned with blend values */
+ env.argStack.pop (k * n);
+ }
+
+ static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_blend_encoder_param_t& param)
+ {
+ switch (op) {
+ case OpCode_StdHW:
+ case OpCode_StdVW:
+ case OpCode_BlueScale:
+ case OpCode_BlueShift:
+ case OpCode_BlueFuzz:
+ case OpCode_ExpansionFactor:
+ case OpCode_LanguageGroup:
+ case OpCode_BlueValues:
+ case OpCode_OtherBlues:
+ case OpCode_FamilyBlues:
+ case OpCode_FamilyOtherBlues:
+ case OpCode_StemSnapH:
+ case OpCode_StemSnapV:
+ break;
+ case OpCode_vsindexdict:
+ env.process_vsindex ();
+ param.ivs = env.get_ivs ();
+ env.clear_args ();
+ return;
+ case OpCode_blenddict:
+ process_blend (env, param);
+ return;
+
+ default:
+ dict_opset_t::process_op (op, env);
+ if (!env.argStack.is_empty ()) return;
+ break;
+ }
+
+ if (unlikely (env.in_error ())) return;
+
+ // Write args then op
+
+ str_buff_t str;
+ str_encoder_t encoder (str);
+
+ unsigned count = env.argStack.get_count ();
+ for (unsigned i = 0; i < count; i++)
+ encoder.encode_num_tp (env.argStack[i]);
+
+ encoder.encode_op (op);
+
+ auto bytes = str.as_bytes ();
+ param.c->embed (&bytes, bytes.length);
+
+ env.clear_args ();
+ }
+};
+
+struct cff2_private_dict_op_serializer_t : op_serializer_t
+{
+ cff2_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_, bool pinned_,
+ const CFF::CFF2VariationStore* varStore_,
+ hb_array_t<int> normalized_coords_)
+ : desubroutinize (desubroutinize_), drop_hints (drop_hints_), pinned (pinned_),
+ varStore (varStore_), normalized_coords (normalized_coords_) {}
+ bool serialize (hb_serialize_context_t *c,
+ const op_str_t &opstr,
+ objidx_t subrs_link) const
+ {
+ TRACE_SERIALIZE (this);
+
+ if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
+ return_trace (true);
+
+ if (opstr.op == OpCode_Subrs)
+ {
+ if (desubroutinize || !subrs_link)
+ return_trace (true);
+ else
+ return_trace (FontDict::serialize_link2_op (c, opstr.op, subrs_link));
+ }
+
+ if (pinned)
+ {
+ // Reinterpret opstr and process blends.
+ cff2_priv_dict_interp_env_t env {hb_ubytes_t (opstr.ptr, opstr.length)};
+ cff2_private_blend_encoder_param_t param (c, varStore, normalized_coords);
+ dict_interpreter_t<cff2_private_dict_blend_opset_t, cff2_private_blend_encoder_param_t, cff2_priv_dict_interp_env_t> interp (env);
+ return_trace (interp.interpret (param));
+ }
+
+ return_trace (copy_opstr (c, opstr));
+ }
+
+ protected:
+ const bool desubroutinize;
+ const bool drop_hints;
+ const bool pinned;
+ const CFF::CFF2VariationStore* varStore;
+ hb_array_t<int> normalized_coords;
+};
+
+
+struct cff2_subset_plan
+{
bool create (const OT::cff2::accelerator_subset_t &acc,
hb_subset_plan_t *plan)
{
orig_fdcount = acc.fdArray->count;
drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
- desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE;
+ pinned = (bool) plan->normalized_coords;
+ desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE ||
+ pinned; // For instancing we need this path
if (desubroutinize)
{
@@ -259,7 +451,7 @@ struct cff2_subset_plan {
return false;
/* encode charstrings, global subrs, local subrs with new subroutine numbers */
- if (!subr_subsetter.encode_charstrings (subset_charstrings))
+ if (!subr_subsetter.encode_charstrings (subset_charstrings, !pinned))
return false;
if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
@@ -299,8 +491,9 @@ struct cff2_subset_plan {
unsigned int orig_fdcount = 0;
unsigned int subset_fdcount = 1;
- unsigned int subset_fdselect_size = 0;
+ unsigned int subset_fdselect_size = 0;
unsigned int subset_fdselect_format = 0;
+ bool pinned = false;
hb_vector_t<code_pair_t> subset_fdselect_ranges;
hb_inc_bimap_t fdmap;
@@ -316,7 +509,8 @@ struct cff2_subset_plan {
static bool _serialize_cff2 (hb_serialize_context_t *c,
cff2_subset_plan &plan,
const OT::cff2::accelerator_subset_t &acc,
- unsigned int num_glyphs)
+ unsigned int num_glyphs,
+ hb_array_t<int> normalized_coords)
{
/* private dicts & local subrs */
hb_vector_t<table_info_t> private_dict_infos;
@@ -344,7 +538,8 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
PrivateDict *pd = c->start_embed<PrivateDict> ();
if (unlikely (!pd)) return false;
c->push ();
- cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+ cff2_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints, plan.pinned,
+ acc.varStore, normalized_coords);
if (likely (pd->serialize (c, acc.privateDicts[i], privSzr, subrs_link)))
{
unsigned fd = plan.fdmap[i];
@@ -412,7 +607,8 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
}
/* variation store */
- if (acc.varStore != &Null (CFF2VariationStore))
+ if (acc.varStore != &Null (CFF2VariationStore) &&
+ !plan.pinned)
{
c->push ();
CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> ();
@@ -451,7 +647,8 @@ _hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc,
cff2_subset_plan cff2_plan;
if (unlikely (!cff2_plan.create (acc, c->plan))) return false;
- return _serialize_cff2 (c->serializer, cff2_plan, acc, c->plan->num_output_glyphs ());
+ return _serialize_cff2 (c->serializer, cff2_plan, acc, c->plan->num_output_glyphs (),
+ c->plan->normalized_coords.as_array ());
}
bool
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
index 42434ae0ef..ca59de79a2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
@@ -27,46 +27,20 @@
#include "hb-subset.hh"
#include "hb-set.hh"
#include "hb-utf.hh"
-/**
- * hb_subset_input_create_or_fail:
- *
- * Creates a new subset input object.
- *
- * Return value: (transfer full): New subset input, or `NULL` if failed. Destroy
- * with hb_subset_input_destroy().
- *
- * Since: 1.8.0
- **/
-hb_subset_input_t *
-hb_subset_input_create_or_fail (void)
-{
- hb_subset_input_t *input = hb_object_create<hb_subset_input_t>();
-
- if (unlikely (!input))
- return nullptr;
- for (auto& set : input->sets_iter ())
- set = hb_set_create ();
- input->axes_location = hb_hashmap_create<hb_tag_t, float> ();
-#ifdef HB_EXPERIMENTAL_API
- input->name_table_overrides = hb_hashmap_create<hb_ot_name_record_ids_t, hb_bytes_t> ();
-#endif
+hb_subset_input_t::hb_subset_input_t ()
+{
+ for (auto& set : sets_iter ())
+ set = hb::shared_ptr<hb_set_t> (hb_set_create ());
- if (!input->axes_location ||
-#ifdef HB_EXPERIMENTAL_API
- !input->name_table_overrides ||
-#endif
- input->in_error ())
- {
- hb_subset_input_destroy (input);
- return nullptr;
- }
+ if (in_error ())
+ return;
- input->flags = HB_SUBSET_FLAGS_DEFAULT;
+ flags = HB_SUBSET_FLAGS_DEFAULT;
- hb_set_add_range (input->sets.name_ids, 0, 6);
- hb_set_add (input->sets.name_languages, 0x0409);
+ hb_set_add_range (sets.name_ids, 0, 6);
+ hb_set_add (sets.name_languages, 0x0409);
hb_tag_t default_drop_tables[] = {
// Layout disabled by default
@@ -92,7 +66,7 @@ hb_subset_input_create_or_fail (void)
HB_TAG ('S', 'i', 'l', 'f'),
HB_TAG ('S', 'i', 'l', 'l'),
};
- input->sets.drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
+ sets.drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
hb_tag_t default_no_subset_tables[] = {
HB_TAG ('a', 'v', 'a', 'r'),
@@ -105,8 +79,8 @@ hb_subset_input_create_or_fail (void)
HB_TAG ('M', 'V', 'A', 'R'),
HB_TAG ('c', 'v', 'a', 'r'),
};
- input->sets.no_subset_tables->add_array (default_no_subset_tables,
- ARRAY_LENGTH (default_no_subset_tables));
+ sets.no_subset_tables->add_array (default_no_subset_tables,
+ ARRAY_LENGTH (default_no_subset_tables));
//copied from _layout_features_groups in fonttools
hb_tag_t default_layout_features[] = {
@@ -208,15 +182,35 @@ hb_subset_input_create_or_fail (void)
HB_TAG ('b', 'l', 'w', 'm'),
};
- input->sets.layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features));
+ sets.layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features));
+
+ sets.layout_scripts->invert (); // Default to all scripts.
+}
+
+/**
+ * hb_subset_input_create_or_fail:
+ *
+ * Creates a new subset input object.
+ *
+ * Return value: (transfer full): New subset input, or `NULL` if failed. Destroy
+ * with hb_subset_input_destroy().
+ *
+ * Since: 1.8.0
+ **/
+hb_subset_input_t *
+hb_subset_input_create_or_fail (void)
+{
+ hb_subset_input_t *input = hb_object_create<hb_subset_input_t>();
- input->sets.layout_scripts->invert (); // Default to all scripts.
+ if (unlikely (!input))
+ return nullptr;
if (input->in_error ())
{
hb_subset_input_destroy (input);
return nullptr;
}
+
return input;
}
@@ -250,20 +244,6 @@ hb_subset_input_destroy (hb_subset_input_t *input)
{
if (!hb_object_destroy (input)) return;
- for (hb_set_t* set : input->sets_iter ())
- hb_set_destroy (set);
-
- hb_hashmap_destroy (input->axes_location);
-
-#ifdef HB_EXPERIMENTAL_API
- if (input->name_table_overrides)
- {
- for (auto _ : *input->name_table_overrides)
- _.second.fini ();
- }
- hb_hashmap_destroy (input->name_table_overrides);
-#endif
-
hb_free (input);
}
@@ -395,16 +375,56 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input,
return hb_object_get_user_data (input, key);
}
+/**
+ * hb_subset_input_keep_everything:
+ * @input: a #hb_subset_input_t object
+ *
+ * Configure input object to keep everything in the font face.
+ * That is, all Unicodes, glyphs, names, layout items,
+ * glyph names, etc.
+ *
+ * The input can be tailored afterwards by the caller.
+ *
+ * Since: 7.0.0
+ */
+void
+hb_subset_input_keep_everything (hb_subset_input_t *input)
+{
+ const hb_subset_sets_t indices[] = {HB_SUBSET_SETS_UNICODE,
+ HB_SUBSET_SETS_GLYPH_INDEX,
+ HB_SUBSET_SETS_NAME_ID,
+ HB_SUBSET_SETS_NAME_LANG_ID,
+ HB_SUBSET_SETS_LAYOUT_FEATURE_TAG,
+ HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG};
+
+ for (auto idx : hb_iter (indices))
+ {
+ hb_set_t *set = hb_subset_input_set (input, idx);
+ hb_set_clear (set);
+ hb_set_invert (set);
+ }
+
+ // Don't drop any tables
+ hb_set_clear (hb_subset_input_set (input, HB_SUBSET_SETS_DROP_TABLE_TAG));
+
+ hb_subset_input_set_flags (input,
+ HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
+ HB_SUBSET_FLAGS_GLYPH_NAMES |
+ HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES |
+ HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED);
+}
+
#ifndef HB_NO_VAR
/**
* hb_subset_input_pin_axis_to_default: (skip)
* @input: a #hb_subset_input_t object.
+ * @face: a #hb_face_t object.
* @axis_tag: Tag of the axis to be pinned
*
* Pin an axis to its default location in the given subset input object.
*
- * Currently only works for fonts with 'glyf' tables. CFF and CFF2 is not
- * yet supported. Additionally all axes in a font must be pinned.
+ * All axes in a font must be pinned. Additionally, `CFF2` table, if present,
+ * will be de-subroutinized.
*
* Return value: `true` if success, `false` otherwise
*
@@ -419,19 +439,20 @@ hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
return false;
- return input->axes_location->set (axis_tag, axis_info.default_value);
+ return input->axes_location.set (axis_tag, axis_info.default_value);
}
/**
* hb_subset_input_pin_axis_location: (skip)
* @input: a #hb_subset_input_t object.
+ * @face: a #hb_face_t object.
* @axis_tag: Tag of the axis to be pinned
* @axis_value: Location on the axis to be pinned at
*
* Pin an axis to a fixed location in the given subset input object.
*
- * Currently only works for fonts with 'glyf' tables. CFF and CFF2 is not
- * yet supported. Additionally all axes in a font must be pinned.
+ * All axes in a font must be pinned. Additionally, `CFF2` table, if present,
+ * will be de-subroutinized.
*
* Return value: `true` if success, `false` otherwise
*
@@ -448,7 +469,7 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
return false;
float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value);
- return input->axes_location->set (axis_tag, val);
+ return input->axes_location.set (axis_tag, val);
}
#endif
@@ -478,39 +499,10 @@ hb_subset_preprocess (hb_face_t *source)
{
hb_subset_input_t* input = hb_subset_input_create_or_fail ();
if (!input)
- return source;
-
- hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
- hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
-
- hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_GLYPH_INDEX));
- hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_GLYPH_INDEX));
-
- hb_set_clear (hb_subset_input_set(input,
- HB_SUBSET_SETS_LAYOUT_FEATURE_TAG));
- hb_set_invert (hb_subset_input_set(input,
- HB_SUBSET_SETS_LAYOUT_FEATURE_TAG));
-
- hb_set_clear (hb_subset_input_set(input,
- HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG));
- hb_set_invert (hb_subset_input_set(input,
- HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG));
-
- hb_set_clear (hb_subset_input_set(input,
- HB_SUBSET_SETS_NAME_ID));
- hb_set_invert (hb_subset_input_set(input,
- HB_SUBSET_SETS_NAME_ID));
-
- hb_set_clear (hb_subset_input_set(input,
- HB_SUBSET_SETS_NAME_LANG_ID));
- hb_set_invert (hb_subset_input_set(input,
- HB_SUBSET_SETS_NAME_LANG_ID));
-
- hb_subset_input_set_flags(input,
- HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
- HB_SUBSET_FLAGS_GLYPH_NAMES |
- HB_SUBSET_FLAGS_RETAIN_GIDS |
- HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES);
+ return hb_face_reference (source);
+
+ hb_subset_input_keep_everything (input);
+
input->attach_accelerator_data = true;
// Always use long loca in the preprocessed version. This allows
@@ -523,7 +515,7 @@ hb_subset_preprocess (hb_face_t *source)
if (!new_source) {
DEBUG_MSG (SUBSET, nullptr, "Preprocessing failed due to subset failure.");
- return source;
+ return hb_face_reference (source);
}
return new_source;
@@ -547,7 +539,7 @@ hb_subset_preprocess (hb_face_t *source)
* Note: for mac platform, we only support name_str with all ascii characters,
* name_str with non-ascii characters will be ignored.
*
- * Since: EXPERIMENTAL
+ * XSince: EXPERIMENTAL
**/
HB_EXTERN hb_bool_t
hb_subset_input_override_name_table (hb_subset_input_t *input,
@@ -593,7 +585,7 @@ hb_subset_input_override_name_table (hb_subset_input_t *input,
hb_memcpy (override_name, name_str, str_len);
name_bytes = hb_bytes_t (override_name, str_len);
}
- input->name_table_overrides->set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes);
+ input->name_table_overrides.set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes);
return true;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
index ecd47b7abf..1550e8b2c3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
@@ -33,7 +33,7 @@
#include "hb-subset.h"
#include "hb-map.hh"
#include "hb-set.hh"
-
+#include "hb-cplusplus.hh"
#include "hb-font.hh"
struct hb_ot_name_record_ids_t
@@ -82,22 +82,34 @@ HB_MARK_AS_FLAG_T (hb_subset_flags_t);
struct hb_subset_input_t
{
+ HB_INTERNAL hb_subset_input_t ();
+
+ ~hb_subset_input_t ()
+ {
+ sets.~sets_t ();
+
+#ifdef HB_EXPERIMENTAL_API
+ for (auto _ : name_table_overrides.values ())
+ _.fini ();
+#endif
+ }
+
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;
- hb_set_t *layout_scripts;
+ hb::shared_ptr<hb_set_t> glyphs;
+ hb::shared_ptr<hb_set_t> unicodes;
+ hb::shared_ptr<hb_set_t> no_subset_tables;
+ hb::shared_ptr<hb_set_t> drop_tables;
+ hb::shared_ptr<hb_set_t> name_ids;
+ hb::shared_ptr<hb_set_t> name_languages;
+ hb::shared_ptr<hb_set_t> layout_features;
+ hb::shared_ptr<hb_set_t> layout_scripts;
};
union {
sets_t sets;
- hb_set_t* set_ptrs[sizeof (sets_t) / sizeof (hb_set_t*)];
+ hb::shared_ptr<hb_set_t> set_ptrs[sizeof (sets_t) / sizeof (hb_set_t*)];
};
unsigned flags;
@@ -106,9 +118,9 @@ struct hb_subset_input_t
// If set loca format will always be the long version.
bool force_long_loca = false;
- hb_hashmap_t<hb_tag_t, float> *axes_location;
+ hb_hashmap_t<hb_tag_t, float> axes_location;
#ifdef HB_EXPERIMENTAL_API
- hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides;
+ hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> name_table_overrides;
#endif
inline unsigned num_sets () const
@@ -116,9 +128,9 @@ struct hb_subset_input_t
return sizeof (set_ptrs) / sizeof (hb_set_t*);
}
- inline hb_array_t<hb_set_t*> sets_iter ()
+ inline hb_array_t<hb::shared_ptr<hb_set_t>> sets_iter ()
{
- return hb_array_t<hb_set_t*> (set_ptrs, num_sets ());
+ return hb_array (set_ptrs);
}
bool in_error () const
@@ -129,9 +141,9 @@ struct hb_subset_input_t
return true;
}
- return axes_location->in_error ()
+ return axes_location.in_error ()
#ifdef HB_EXPERIMENTAL_API
- || name_table_overrides->in_error ()
+ || name_table_overrides.in_error ()
#endif
;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc
new file mode 100644
index 0000000000..5c0f43ad4b
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc
@@ -0,0 +1,464 @@
+/*
+ * Copyright © 2023 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "hb.hh"
+
+/* This file is a straight port of the following:
+ *
+ * https://github.com/fonttools/fonttools/blob/f73220816264fc383b8a75f2146e8d69e455d398/Lib/fontTools/varLib/instancer/solver.py
+ *
+ * Where that file returns None for a triple, we return Triple{}.
+ * This should be safe.
+ */
+
+constexpr static float EPSILON = 1.f / (1 << 14);
+constexpr static float MAX_F2DOT14 = float (0x7FFF) / (1 << 14);
+
+struct Triple {
+
+ Triple () :
+ minimum (0.f), middle (0.f), maximum (0.f) {}
+
+ Triple (float minimum_, float middle_, float maximum_) :
+ minimum (minimum_), middle (middle_), maximum (maximum_) {}
+
+ bool operator == (const Triple &o) const
+ {
+ return minimum == o.minimum &&
+ middle == o.middle &&
+ maximum == o.maximum;
+ }
+
+ float minimum;
+ float middle;
+ float maximum;
+};
+
+static inline Triple _reverse_negate(const Triple &v)
+{ return {-v.maximum, -v.middle, -v.minimum}; }
+
+
+static inline float supportScalar (float coord, const Triple &tent)
+{
+ /* Copied from VarRegionAxis::evaluate() */
+ float start = tent.minimum, peak = tent.middle, end = tent.maximum;
+
+ if (unlikely (start > peak || peak > end))
+ return 1.;
+ if (unlikely (start < 0 && end > 0 && peak != 0))
+ return 1.;
+
+ if (peak == 0 || coord == peak)
+ return 1.;
+
+ if (coord <= start || end <= coord)
+ return 0.;
+
+ /* Interpolate */
+ if (coord < peak)
+ return (coord - start) / (peak - start);
+ else
+ return (end - coord) / (end - peak);
+}
+
+
+using result_item_t = hb_pair_t<float, Triple>;
+using result_t = hb_vector_t<result_item_t>;
+
+static inline result_t
+_solve (Triple tent, Triple axisLimit, bool negative = false)
+{
+ float axisMin = axisLimit.minimum;
+ float axisDef = axisLimit.middle;
+ float axisMax = axisLimit.maximum;
+ float lower = tent.minimum;
+ float peak = tent.middle;
+ float upper = tent.maximum;
+
+ // Mirror the problem such that axisDef <= peak
+ if (axisDef > peak)
+ {
+ result_t vec = _solve (_reverse_negate (tent),
+ _reverse_negate (axisLimit),
+ !negative);
+
+ for (auto &p : vec)
+ p = hb_pair (p.first, _reverse_negate (p.second));
+
+ return vec;
+ }
+ // axisDef <= peak
+
+ /* case 1: The whole deltaset falls outside the new limit; we can drop it
+ *
+ * peak
+ * 1.........................................o..........
+ * / \
+ * / \
+ * / \
+ * / \
+ * 0---|-----------|----------|-------- o o----1
+ * axisMin axisDef axisMax lower upper
+ */
+ if (axisMax <= lower && axisMax < peak)
+ return result_t{}; // No overlap
+
+ /* case 2: Only the peak and outermost bound fall outside the new limit;
+ * we keep the deltaset, update peak and outermost bound and and scale deltas
+ * by the scalar value for the restricted axis at the new limit, and solve
+ * recursively.
+ *
+ * |peak
+ * 1...............................|.o..........
+ * |/ \
+ * / \
+ * /| \
+ * / | \
+ * 0--------------------------- o | o----1
+ * lower | upper
+ * |
+ * axisMax
+ *
+ * Convert to:
+ *
+ * 1............................................
+ * |
+ * o peak
+ * /|
+ * /x|
+ * 0--------------------------- o o upper ----1
+ * lower |
+ * |
+ * axisMax
+ */
+ if (axisMax < peak)
+ {
+ float mult = supportScalar (axisMax, tent);
+ tent = Triple{lower, axisMax, axisMax};
+
+ result_t vec = _solve (tent, axisLimit);
+
+ for (auto &p : vec)
+ p = hb_pair (p.first * mult, p.second);
+
+ return vec;
+ }
+
+ // lower <= axisDef <= peak <= axisMax
+
+ float gain = supportScalar (axisDef, tent);
+ result_t out {hb_pair (gain, Triple{})};
+
+ // First, the positive side
+
+ // outGain is the scalar of axisMax at the tent.
+ float outGain = supportScalar (axisMax, tent);
+
+ /* Case 3a: Gain is more than outGain. The tent down-slope crosses
+ * the axis into negative. We have to split it into multiples.
+ *
+ * | peak |
+ * 1...................|.o.....|..............
+ * |/x\_ |
+ * gain................+....+_.|..............
+ * /| |y\|
+ * ................../.|....|..+_......outGain
+ * / | | | \
+ * 0---|-----------o | | | o----------1
+ * axisMin lower | | | upper
+ * | | |
+ * axisDef | axisMax
+ * |
+ * crossing
+ */
+ if (gain > outGain)
+ {
+ // Crossing point on the axis.
+ float crossing = peak + ((1 - gain) * (upper - peak) / (1 - outGain));
+
+ Triple loc{peak, peak, crossing};
+ float scalar = 1.f;
+
+ // The part before the crossing point.
+ out.push (hb_pair (scalar - gain, loc));
+
+ /* The part after the crossing point may use one or two tents,
+ * depending on whether upper is before axisMax or not, in one
+ * case we need to keep it down to eternity.
+ *
+ * Case 3a1, similar to case 1neg; just one tent needed, as in
+ * the drawing above.
+ */
+ if (upper >= axisMax)
+ {
+ Triple loc {crossing, axisMax, axisMax};
+ float scalar = supportScalar (axisMax, tent);
+
+ out.push (hb_pair (scalar - gain, loc));
+ }
+
+ /* Case 3a2: Similar to case 2neg; two tents needed, to keep
+ * down to eternity.
+ *
+ * | peak |
+ * 1...................|.o................|...
+ * |/ \_ |
+ * gain................+....+_............|...
+ * /| | \xxxxxxxxxxy|
+ * / | | \_xxxxxyyyy|
+ * / | | \xxyyyyyy|
+ * 0---|-----------o | | o-------|--1
+ * axisMin lower | | upper |
+ * | | |
+ * axisDef | axisMax
+ * |
+ * crossing
+ */
+ else
+ {
+ // A tent's peak cannot fall on axis default. Nudge it.
+ if (upper == axisDef)
+ upper += EPSILON;
+
+ // Downslope.
+ Triple loc1 {crossing, upper, axisMax};
+ float scalar1 = 0.f;
+
+ // Eternity justify.
+ Triple loc2 {upper, axisMax, axisMax};
+ float scalar2 = 1.f; // supportScalar({"tag": axisMax}, {"tag": tent})
+
+ out.push (hb_pair (scalar1 - gain, loc1));
+ out.push (hb_pair (scalar2 - gain, loc2));
+ }
+ }
+
+ /* Case 3: Outermost limit still fits within F2Dot14 bounds;
+ * we keep deltas as is and only scale the axes bounds. Deltas beyond -1.0
+ * or +1.0 will never be applied as implementations must clamp to that range.
+ *
+ * A second tent is needed for cases when gain is positive, though we add it
+ * unconditionally and it will be dropped because scalar ends up 0.
+ *
+ * TODO: See if we can just move upper closer to adjust the slope, instead of
+ * second tent.
+ *
+ * | peak |
+ * 1.........|............o...|..................
+ * | /x\ |
+ * | /xxx\ |
+ * | /xxxxx\|
+ * | /xxxxxxx+
+ * | /xxxxxxxx|\
+ * 0---|-----|------oxxxxxxxxx|xo---------------1
+ * axisMin | lower | upper
+ * | |
+ * axisDef axisMax
+ */
+ else if (axisDef + (axisMax - axisDef) * 2 >= upper)
+ {
+ if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper)
+ {
+ // we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience
+ upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14;
+ assert (peak < upper);
+ }
+
+ // Special-case if peak is at axisMax.
+ if (axisMax == peak)
+ upper = peak;
+
+ Triple loc1 {hb_max (axisDef, lower), peak, upper};
+ float scalar1 = 1.f;
+
+ Triple loc2 {peak, upper, upper};
+ float scalar2 = 0.f;
+
+ // Don't add a dirac delta!
+ if (axisDef < upper)
+ out.push (hb_pair (scalar1 - gain, loc1));
+ if (peak < upper)
+ out.push (hb_pair (scalar2 - gain, loc2));
+ }
+
+ /* Case 4: New limit doesn't fit; we need to chop into two tents,
+ * because the shape of a triangle with part of one side cut off
+ * cannot be represented as a triangle itself.
+ *
+ * | peak |
+ * 1.........|......o.|...................
+ * | /x\|
+ * | |xxy|\_
+ * | /xxxy| \_
+ * | |xxxxy| \_
+ * | /xxxxy| \_
+ * 0---|-----|-oxxxxxx| o----------1
+ * axisMin | lower | upper
+ * | |
+ * axisDef axisMax
+ */
+ else
+ {
+ Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
+ float scalar1 = 1.f;
+
+ Triple loc2 {peak, axisMax, axisMax};
+ float scalar2 = supportScalar (axisMax, tent);
+
+ out.push (hb_pair (scalar1 - gain, loc1));
+ // Don't add a dirac delta!
+ if (peak < axisMax)
+ out.push (hb_pair (scalar2 - gain, loc2));
+ }
+
+ /* Now, the negative side
+ *
+ * Case 1neg: Lower extends beyond axisMin: we chop. Simple.
+ *
+ * | |peak
+ * 1..................|...|.o.................
+ * | |/ \
+ * gain...............|...+...\...............
+ * |x_/| \
+ * |/ | \
+ * _/| | \
+ * 0---------------o | | o----------1
+ * lower | | upper
+ * | |
+ * axisMin axisDef
+ */
+ if (lower <= axisMin)
+ {
+ Triple loc {axisMin, axisMin, axisDef};
+ float scalar = supportScalar (axisMin, tent);
+
+ out.push (hb_pair (scalar - gain, loc));
+ }
+
+ /* Case 2neg: Lower is betwen axisMin and axisDef: we add two
+ * tents to keep it down all the way to eternity.
+ *
+ * | |peak
+ * 1...|...............|.o.................
+ * | |/ \
+ * gain|...............+...\...............
+ * |yxxxxxxxxxxxxx/| \
+ * |yyyyyyxxxxxxx/ | \
+ * |yyyyyyyyyyyx/ | \
+ * 0---|-----------o | o----------1
+ * axisMin lower | upper
+ * |
+ * axisDef
+ */
+ else
+ {
+ // A tent's peak cannot fall on axis default. Nudge it.
+ if (lower == axisDef)
+ lower -= EPSILON;
+
+ // Downslope.
+ Triple loc1 {axisMin, lower, axisDef};
+ float scalar1 = 0.f;
+
+ // Eternity justify.
+ Triple loc2 {axisMin, axisMin, lower};
+ float scalar2 = 0.f;
+
+ out.push (hb_pair (scalar1 - gain, loc1));
+ out.push (hb_pair (scalar2 - gain, loc2));
+ }
+
+ return out;
+}
+
+/* Normalizes value based on a min/default/max triple. */
+static inline float normalizeValue (float v, const Triple &triple, bool extrapolate = false)
+{
+ /*
+ >>> normalizeValue(400, (100, 400, 900))
+ 0.0
+ >>> normalizeValue(100, (100, 400, 900))
+ -1.0
+ >>> normalizeValue(650, (100, 400, 900))
+ 0.5
+ */
+ float lower = triple.minimum, def = triple.middle, upper = triple.maximum;
+ assert (lower <= def && def <= upper);
+
+ if (!extrapolate)
+ v = hb_max (hb_min (v, upper), lower);
+
+ if ((v == def) || (lower == upper))
+ return 0.f;
+
+ if ((v < def && lower != def) || (v > def && upper == def))
+ return (v - def) / (def - lower);
+ else
+ {
+ assert ((v > def && upper != def) ||
+ (v < def && lower == def));
+ return (v - def) / (upper - def);
+ }
+}
+
+/* Given a tuple (lower,peak,upper) "tent" and new axis limits
+ * (axisMin,axisDefault,axisMax), solves how to represent the tent
+ * under the new axis configuration. All values are in normalized
+ * -1,0,+1 coordinate system. Tent values can be outside this range.
+ *
+ * Return value: a list of tuples. Each tuple is of the form
+ * (scalar,tent), where scalar is a multipler to multiply any
+ * delta-sets by, and tent is a new tent for that output delta-set.
+ * If tent value is Triple{}, that is a special deltaset that should
+ * be always-enabled (called "gain").
+ */
+HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit);
+
+result_t
+rebase_tent (Triple tent, Triple axisLimit)
+{
+ assert (-1.f <= axisLimit.minimum && axisLimit.minimum <= axisLimit.middle && axisLimit.middle <= axisLimit.maximum && axisLimit.maximum <= +1.f);
+ assert (-2.f <= tent.minimum && tent.minimum <= tent.middle && tent.middle <= tent.maximum && tent.maximum <= +2.f);
+ assert (tent.middle != 0.f);
+
+ result_t sols = _solve (tent, axisLimit);
+
+ auto n = [&axisLimit] (float v) { return normalizeValue (v, axisLimit, true); };
+
+ result_t out;
+ for (auto &p : sols)
+ {
+ if (!p.first) continue;
+ if (p.second == Triple{})
+ {
+ out.push (p);
+ continue;
+ }
+ Triple t = p.second;
+ out.push (hb_pair (p.first,
+ Triple{n (t.minimum), n (t.middle), n (t.maximum)}));
+ }
+
+ return sols;
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
index 71bc908ffb..088fdca07b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
@@ -36,8 +36,8 @@
#include "hb-ot-layout-gpos-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-cff1-table.hh"
-#include "hb-ot-color-colr-table.hh"
-#include "hb-ot-color-colrv1-closure.hh"
+#include "OT/Color/COLR/COLR.hh"
+#include "OT/Color/COLR/colrv1-closure.hh"
#include "hb-ot-var-fvar-table.hh"
#include "hb-ot-var-avar-table.hh"
#include "hb-ot-stat-table.hh"
@@ -139,13 +139,13 @@ static void _collect_layout_indices (hb_subset_plan_t *plan,
hb_vector_t<hb_tag_t> features;
if (!plan->check_success (features.resize (num_features))) return;
table.get_feature_tags (0, &num_features, features.arrayZ);
- bool retain_all_features = !_filter_tag_list (&features, plan->layout_features);
+ bool retain_all_features = !_filter_tag_list (&features, &plan->layout_features);
unsigned num_scripts = table.get_script_count ();
hb_vector_t<hb_tag_t> scripts;
if (!plan->check_success (scripts.resize (num_scripts))) return;
table.get_script_tags (0, &num_scripts, scripts.arrayZ);
- bool retain_all_scripts = !_filter_tag_list (&scripts, plan->layout_scripts);
+ bool retain_all_scripts = !_filter_tag_list (&scripts, &plan->layout_scripts);
if (!plan->check_success (!features.in_error ()) || !features
|| !plan->check_success (!scripts.in_error ()) || !scripts)
@@ -160,13 +160,13 @@ static void _collect_layout_indices (hb_subset_plan_t *plan,
#ifndef HB_NO_VAR
// collect feature substitutes with variations
- if (!plan->user_axes_location->is_empty ())
+ if (!plan->user_axes_location.is_empty ())
{
hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> conditionset_map;
OT::hb_collect_feature_substitutes_with_var_context_t c =
{
- plan->axes_old_index_tag_map,
- plan->axes_location,
+ &plan->axes_old_index_tag_map,
+ &plan->axes_location,
feature_record_cond_idx_map,
feature_substitutes_map,
feature_indices,
@@ -188,7 +188,17 @@ static void _collect_layout_indices (hb_subset_plan_t *plan,
f->add_lookup_indexes_to (lookup_indices);
}
- table.feature_variation_collect_lookups (feature_indices, feature_substitutes_map, lookup_indices);
+ // If all axes are pinned then all feature variations will be dropped so there's no need
+ // to collect lookups from them.
+ if (!plan->all_axes_pinned)
+ {
+ // TODO(qxliu76): this collection doesn't work correctly for feature variations that are dropped
+ // but not applied. The collection will collect and retain the lookup indices
+ // associated with those dropped but not activated rules. Since partial instancing
+ // isn't yet supported this isn't an issue yet but will need to be fixed for
+ // partial instancing.
+ table.feature_variation_collect_lookups (feature_indices, feature_substitutes_map, lookup_indices);
+ }
}
@@ -228,7 +238,7 @@ _GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
const OT::Feature* other_f = &(g.get_feature (other_f_index));
if (feature_substitutes_map->has (other_f_index, &p))
- f = *p;
+ other_f = *p;
auto f_iter =
+ hb_iter (f->lookupIndex)
@@ -294,14 +304,14 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
// prune features
table->prune_features (lookups,
- plan->user_axes_location->is_empty () ? nullptr : feature_record_cond_idx_map,
+ plan->user_axes_location.is_empty () ? nullptr : feature_record_cond_idx_map,
feature_substitutes_map,
&feature_indices);
hb_map_t duplicate_feature_map;
_GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map);
feature_indices.clear ();
- table->prune_langsys (&duplicate_feature_map, plan->layout_scripts, langsys_map, &feature_indices);
+ table->prune_langsys (&duplicate_feature_map, &plan->layout_scripts, langsys_map, &feature_indices);
_remap_indexes (&feature_indices, features);
table.destroy ();
@@ -335,9 +345,9 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan)
hb_font_t *font = hb_font_create (plan->source);
hb_vector_t<hb_variation_t> vars;
- vars.alloc (plan->user_axes_location->get_population ());
+ vars.alloc (plan->user_axes_location.get_population ());
- for (auto _ : *plan->user_axes_location)
+ for (auto _ : plan->user_axes_location)
{
hb_variation_t var;
var.tag = _.first;
@@ -346,7 +356,7 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan)
}
#ifndef HB_NO_VAR
- hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
+ hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
#endif
return font;
}
@@ -380,10 +390,10 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan)
}
OT::hb_collect_variation_indices_context_t c (&varidx_set,
- plan->layout_variation_idx_delta_map,
+ &plan->layout_variation_idx_delta_map,
font, var_store,
- plan->_glyphset_gsub,
- plan->gpos_lookups,
+ &plan->_glyphset_gsub,
+ &plan->gpos_lookups,
store_cache);
gdef->collect_variation_indices (&c);
@@ -393,7 +403,7 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan)
hb_font_destroy (font);
var_store->destroy_cache (store_cache);
- gdef->remap_layout_variation_indices (&varidx_set, plan->layout_variation_idx_delta_map);
+ gdef->remap_layout_variation_indices (&varidx_set, &plan->layout_variation_idx_delta_map);
unsigned subtable_count = gdef->has_var_store () ? gdef->get_var_store ().get_sub_table_count () : 0;
_generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps);
@@ -569,15 +579,15 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
{
if (gid >= plan->source->get_num_glyphs ())
break;
- plan->_glyphset_gsub->add (gid);
+ plan->_glyphset_gsub.add (gid);
}
}
auto &arr = plan->unicode_to_new_gid_list;
if (arr.length)
{
- plan->unicodes->add_sorted_array (&arr.arrayZ->first, arr.length, sizeof (*arr.arrayZ));
- plan->_glyphset_gsub->add_array (&arr.arrayZ->second, arr.length, sizeof (*arr.arrayZ));
+ plan->unicodes.add_sorted_array (&arr.arrayZ->first, arr.length, sizeof (*arr.arrayZ));
+ plan->_glyphset_gsub.add_array (&arr.arrayZ->second, arr.length, sizeof (*arr.arrayZ));
}
}
@@ -619,71 +629,71 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
OT::cff1::accelerator_t cff (plan->source);
#endif
- plan->_glyphset_gsub->add (0); // Not-def
+ plan->_glyphset_gsub.add (0); // Not-def
- _cmap_closure (plan->source, plan->unicodes, plan->_glyphset_gsub);
+ _cmap_closure (plan->source, &plan->unicodes, &plan->_glyphset_gsub);
#ifndef HB_NO_SUBSET_LAYOUT
if (!drop_tables->has (HB_OT_TAG_GSUB))
// closure all glyphs/lookups/features needed for GSUB substitutions.
_closure_glyphs_lookups_features<GSUB> (
plan,
- plan->_glyphset_gsub,
- plan->gsub_lookups,
- plan->gsub_features,
- plan->gsub_langsys,
- plan->gsub_feature_record_cond_idx_map,
- plan->gsub_feature_substitutes_map);
+ &plan->_glyphset_gsub,
+ &plan->gsub_lookups,
+ &plan->gsub_features,
+ &plan->gsub_langsys,
+ &plan->gsub_feature_record_cond_idx_map,
+ &plan->gsub_feature_substitutes_map);
if (!drop_tables->has (HB_OT_TAG_GPOS))
_closure_glyphs_lookups_features<GPOS> (
plan,
- plan->_glyphset_gsub,
- plan->gpos_lookups,
- plan->gpos_features,
- plan->gpos_langsys,
- plan->gpos_feature_record_cond_idx_map,
- plan->gpos_feature_substitutes_map);
+ &plan->_glyphset_gsub,
+ &plan->gpos_lookups,
+ &plan->gpos_features,
+ &plan->gpos_langsys,
+ &plan->gpos_feature_record_cond_idx_map,
+ &plan->gpos_feature_substitutes_map);
#endif
- _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
+ _remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ());
- hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
+ plan->_glyphset_mathed = plan->_glyphset_gsub;
if (!drop_tables->has (HB_OT_TAG_MATH))
{
- _math_closure (plan, plan->_glyphset_mathed);
- _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
+ _math_closure (plan, &plan->_glyphset_mathed);
+ _remove_invalid_gids (&plan->_glyphset_mathed, plan->source->get_num_glyphs ());
}
- hb_set_t cur_glyphset = *plan->_glyphset_mathed;
+ hb_set_t cur_glyphset = plan->_glyphset_mathed;
if (!drop_tables->has (HB_OT_TAG_COLR))
{
- _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
+ _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);
+ plan->_glyphset_colred = cur_glyphset;
/* Populate a full set of glyphs to retain by adding all referenced
* composite glyphs. */
if (glyf.has_data ())
for (hb_codepoint_t gid : cur_glyphset)
- _glyf_add_gid_and_children (glyf, gid, plan->_glyphset,
+ _glyf_add_gid_and_children (glyf, gid, &plan->_glyphset,
cur_glyphset.get_population () * HB_COMPOSITE_OPERATIONS_PER_GLYPH);
else
- plan->_glyphset->union_ (cur_glyphset);
+ plan->_glyphset.union_ (cur_glyphset);
#ifndef HB_NO_SUBSET_CFF
if (!plan->accelerator || plan->accelerator->has_seac)
{
bool has_seac = false;
if (cff.is_valid ())
for (hb_codepoint_t gid : cur_glyphset)
- if (_add_cff_seac_components (cff, gid, plan->_glyphset))
+ if (_add_cff_seac_components (cff, gid, &plan->_glyphset))
has_seac = true;
plan->has_seac = has_seac;
}
#endif
- _remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
+ _remove_invalid_gids (&plan->_glyphset, plan->source->get_num_glyphs ());
#ifndef HB_NO_VAR
@@ -765,10 +775,11 @@ _nameid_closure (hb_face_t *face,
static void
_normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
{
- if (plan->user_axes_location->is_empty ())
+ if (plan->user_axes_location.is_empty ())
return;
hb_array_t<const OT::AxisRecord> axes = face->table.fvar->get_axes ();
+ plan->normalized_coords.resize (axes.length);
bool has_avar = face->table.avar->has_data ();
const OT::SegmentMaps *seg_maps = nullptr;
@@ -777,201 +788,175 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
bool axis_not_pinned = false;
unsigned old_axis_idx = 0, new_axis_idx = 0;
+ unsigned int i = 0;
for (const auto& axis : axes)
{
hb_tag_t axis_tag = axis.get_axis_tag ();
- plan->axes_old_index_tag_map->set (old_axis_idx, axis_tag);
+ plan->axes_old_index_tag_map.set (old_axis_idx, axis_tag);
- if (!plan->user_axes_location->has (axis_tag))
+ if (!plan->user_axes_location.has (axis_tag))
{
axis_not_pinned = true;
- plan->axes_index_map->set (old_axis_idx, new_axis_idx);
+ plan->axes_index_map.set (old_axis_idx, new_axis_idx);
new_axis_idx++;
}
else
{
- int normalized_v = axis.normalize_axis_value (plan->user_axes_location->get (axis_tag));
+ int normalized_v = axis.normalize_axis_value (plan->user_axes_location.get (axis_tag));
if (has_avar && old_axis_idx < face->table.avar->get_axis_count ())
{
normalized_v = seg_maps->map (normalized_v);
}
- plan->axes_location->set (axis_tag, normalized_v);
+ plan->axes_location.set (axis_tag, normalized_v);
if (normalized_v != 0)
plan->pinned_at_default = false;
+
+ plan->normalized_coords[i] = normalized_v;
}
if (has_avar)
seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
old_axis_idx++;
+
+ i++;
}
plan->all_axes_pinned = !axis_not_pinned;
}
#endif
-/**
- * hb_subset_plan_create_or_fail:
- * @face: font face to create the plan for.
- * @input: a #hb_subset_input_t input.
- *
- * Computes a plan for subsetting the supplied face according
- * to a provided input. The plan describes
- * which tables and glyphs should be retained.
- *
- * Return value: (transfer full): New subset plan. Destroy with
- * hb_subset_plan_destroy(). If there is a failure creating the plan
- * nullptr will be returned.
- *
- * Since: 4.0.0
- **/
-hb_subset_plan_t *
-hb_subset_plan_create_or_fail (hb_face_t *face,
- const hb_subset_input_t *input)
+
+hb_subset_plan_t::hb_subset_plan_t (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 nullptr;
+ successful = true;
+ flags = input->flags;
+
+ unicode_to_new_gid_list.init ();
- plan->successful = true;
- plan->flags = input->flags;
- plan->unicodes = hb_set_create ();
-
- plan->unicode_to_new_gid_list.init ();
-
- plan->name_ids = hb_set_copy (input->sets.name_ids);
- plan->name_languages = hb_set_copy (input->sets.name_languages);
- plan->layout_features = hb_set_copy (input->sets.layout_features);
- plan->layout_scripts = hb_set_copy (input->sets.layout_scripts);
- plan->glyphs_requested = hb_set_copy (input->sets.glyphs);
- plan->drop_tables = hb_set_copy (input->sets.drop_tables);
- plan->no_subset_tables = hb_set_copy (input->sets.no_subset_tables);
- plan->source = hb_face_reference (face);
- plan->dest = hb_face_builder_create ();
-
- 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 ();
- plan->glyph_map_gsub = hb_map_create ();
- plan->gsub_lookups = hb_map_create ();
- plan->gpos_lookups = hb_map_create ();
-
- plan->check_success (plan->gsub_langsys = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ());
- plan->check_success (plan->gpos_langsys = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ());
-
- plan->gsub_features = hb_map_create ();
- plan->gpos_features = hb_map_create ();
-
- plan->check_success (plan->gsub_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ());
- plan->check_success (plan->gpos_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ());
-
- plan->check_success (plan->gsub_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
- plan->check_success (plan->gpos_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
-
- plan->colrv1_layers = hb_map_create ();
- plan->colr_palettes = hb_map_create ();
- plan->check_success (plan->layout_variation_idx_delta_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
- plan->gdef_varstore_inner_maps.init ();
-
- plan->check_success (plan->sanitized_table_cache = hb_hashmap_create<hb_tag_t, hb::unique_ptr<hb_blob_t>> ());
- plan->check_success (plan->axes_location = hb_hashmap_create<hb_tag_t, int> ());
- plan->check_success (plan->user_axes_location = hb_hashmap_create<hb_tag_t, float> ());
- if (plan->user_axes_location && input->axes_location)
- *plan->user_axes_location = *input->axes_location;
- plan->check_success (plan->axes_index_map = hb_map_create ());
- plan->check_success (plan->axes_old_index_tag_map = hb_map_create ());
- plan->all_axes_pinned = false;
- plan->pinned_at_default = true;
-
- plan->check_success (plan->vmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
- plan->check_success (plan->hmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
+ name_ids = *input->sets.name_ids;
+ name_languages = *input->sets.name_languages;
+ layout_features = *input->sets.layout_features;
+ layout_scripts = *input->sets.layout_scripts;
+ glyphs_requested = *input->sets.glyphs;
+ drop_tables = *input->sets.drop_tables;
+ no_subset_tables = *input->sets.no_subset_tables;
+ source = hb_face_reference (face);
+ dest = hb_face_builder_create ();
+
+ codepoint_to_glyph = hb_map_create ();
+ glyph_map = hb_map_create ();
+ reverse_glyph_map = hb_map_create ();
+
+ gdef_varstore_inner_maps.init ();
+
+ user_axes_location = input->axes_location;
+ all_axes_pinned = false;
+ pinned_at_default = true;
#ifdef HB_EXPERIMENTAL_API
- plan->check_success (plan->name_table_overrides = hb_hashmap_create<hb_ot_name_record_ids_t, hb_bytes_t> ());
- if (plan->name_table_overrides && input->name_table_overrides)
+ for (auto _ : input->name_table_overrides)
{
- for (auto _ : *input->name_table_overrides)
- {
- hb_bytes_t name_bytes = _.second;
- unsigned len = name_bytes.length;
- char *name_str = (char *) hb_malloc (len);
- if (unlikely (!plan->check_success (name_str)))
- break;
-
- hb_memcpy (name_str, name_bytes.arrayZ, len);
- plan->name_table_overrides->set (_.first, hb_bytes_t (name_str, len));
- }
+ hb_bytes_t name_bytes = _.second;
+ unsigned len = name_bytes.length;
+ char *name_str = (char *) hb_malloc (len);
+ if (unlikely (!check_success (name_str)))
+ break;
+
+ hb_memcpy (name_str, name_bytes.arrayZ, len);
+ name_table_overrides.set (_.first, hb_bytes_t (name_str, len));
}
#endif
void* accel = hb_face_get_user_data(face, hb_subset_accelerator_t::user_data_key());
- plan->attach_accelerator_data = input->attach_accelerator_data;
- plan->force_long_loca = input->force_long_loca;
+ attach_accelerator_data = input->attach_accelerator_data;
+ force_long_loca = input->force_long_loca;
if (accel)
- plan->accelerator = (hb_subset_accelerator_t*) accel;
+ accelerator = (hb_subset_accelerator_t*) accel;
- if (unlikely (plan->in_error ())) {
- hb_subset_plan_destroy (plan);
- return nullptr;
- }
+ if (unlikely (in_error ()))
+ return;
#ifndef HB_NO_VAR
- _normalize_axes_location (face, plan);
+ _normalize_axes_location (face, this);
#endif
- _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
+ _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this);
- _populate_gids_to_retain (plan, input->sets.drop_tables);
+ _populate_gids_to_retain (this, input->sets.drop_tables);
_create_old_gid_to_new_gid_map (face,
input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,
- plan->_glyphset,
- plan->glyph_map,
- plan->reverse_glyph_map,
- &plan->_num_output_glyphs);
+ &_glyphset,
+ glyph_map,
+ reverse_glyph_map,
+ &_num_output_glyphs);
_create_glyph_map_gsub (
- plan->_glyphset_gsub,
- plan->glyph_map,
- plan->glyph_map_gsub);
+ &_glyphset_gsub,
+ glyph_map,
+ &glyph_map_gsub);
// Now that we have old to new gid map update the unicode to new gid list.
- for (unsigned i = 0; i < plan->unicode_to_new_gid_list.length; i++)
+ for (unsigned i = 0; i < unicode_to_new_gid_list.length; i++)
{
// Use raw array access for performance.
- plan->unicode_to_new_gid_list.arrayZ[i].second =
- plan->glyph_map->get(plan->unicode_to_new_gid_list.arrayZ[i].second);
- }
-
- _nameid_closure (face, plan->name_ids, plan->all_axes_pinned, plan->user_axes_location);
- if (unlikely (plan->in_error ())) {
- hb_subset_plan_destroy (plan);
- return nullptr;
+ unicode_to_new_gid_list.arrayZ[i].second =
+ glyph_map->get(unicode_to_new_gid_list.arrayZ[i].second);
}
+ _nameid_closure (face, &name_ids, all_axes_pinned, &user_axes_location);
+ if (unlikely (in_error ()))
+ return;
- if (plan->attach_accelerator_data)
+ if (attach_accelerator_data)
{
hb_multimap_t gid_to_unicodes;
- hb_map_t &unicode_to_gid = *plan->codepoint_to_glyph;
+ hb_map_t &unicode_to_gid = *codepoint_to_glyph;
- for (auto unicode : *plan->unicodes)
+ for (auto unicode : unicodes)
{
auto gid = unicode_to_gid[unicode];
gid_to_unicodes.add (gid, unicode);
}
- plan->inprogress_accelerator =
- hb_subset_accelerator_t::create (*plan->codepoint_to_glyph,
+ inprogress_accelerator =
+ hb_subset_accelerator_t::create (*codepoint_to_glyph,
gid_to_unicodes,
- *plan->unicodes,
- plan->has_seac);
+ unicodes,
+ has_seac);
}
+}
+/**
+ * hb_subset_plan_create_or_fail:
+ * @face: font face to create the plan for.
+ * @input: a #hb_subset_input_t input.
+ *
+ * Computes a plan for subsetting the supplied face according
+ * to a provided input. The plan describes
+ * which tables and glyphs should be retained.
+ *
+ * Return value: (transfer full): New subset plan. Destroy with
+ * hb_subset_plan_destroy(). If there is a failure creating the plan
+ * nullptr will be returned.
+ *
+ * Since: 4.0.0
+ **/
+hb_subset_plan_t *
+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> (face, input))))
+ return nullptr;
+
+ if (unlikely (plan->in_error ()))
+ {
+ hb_subset_plan_destroy (plan);
+ return nullptr;
+ }
return plan;
}
@@ -1005,7 +990,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
*
* Since: 4.0.0
**/
-const hb_map_t*
+hb_map_t *
hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan)
{
return plan->glyph_map;
@@ -1023,7 +1008,7 @@ hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan)
*
* Since: 4.0.0
**/
-const hb_map_t*
+hb_map_t *
hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan)
{
return plan->reverse_glyph_map;
@@ -1041,7 +1026,7 @@ hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan)
*
* Since: 4.0.0
**/
-const hb_map_t*
+hb_map_t *
hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan)
{
return plan->codepoint_to_glyph;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
index 1b2aee7825..c0a85e12dc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
@@ -41,69 +41,53 @@ namespace OT {
struct Feature;
}
+struct head_maxp_info_t
+{
+ head_maxp_info_t ()
+ :xMin (0x7FFF), xMax (-0x7FFF), yMin (0x7FFF), yMax (-0x7FFF),
+ maxPoints (0), maxContours (0),
+ maxCompositePoints (0),
+ maxCompositeContours (0),
+ maxComponentElements (0),
+ maxComponentDepth (0),
+ allXMinIsLsb (true) {}
+
+ int xMin;
+ int xMax;
+ int yMin;
+ int yMax;
+ unsigned maxPoints;
+ unsigned maxContours;
+ unsigned maxCompositePoints;
+ unsigned maxCompositeContours;
+ unsigned maxComponentElements;
+ unsigned maxComponentDepth;
+ bool allXMinIsLsb;
+};
+
+typedef struct head_maxp_info_t head_maxp_info_t;
+
struct hb_subset_plan_t
{
- hb_subset_plan_t ()
- {}
+ HB_INTERNAL hb_subset_plan_t (hb_face_t *,
+ const hb_subset_input_t *input);
~hb_subset_plan_t()
{
- hb_set_destroy (unicodes);
- hb_set_destroy (name_ids);
- hb_set_destroy (name_languages);
- hb_set_destroy (layout_features);
- hb_set_destroy (layout_scripts);
- hb_set_destroy (glyphs_requested);
- hb_set_destroy (drop_tables);
- hb_set_destroy (no_subset_tables);
hb_face_destroy (source);
hb_face_destroy (dest);
+
hb_map_destroy (codepoint_to_glyph);
hb_map_destroy (glyph_map);
hb_map_destroy (reverse_glyph_map);
- hb_map_destroy (glyph_map_gsub);
- hb_set_destroy (_glyphset);
- hb_set_destroy (_glyphset_gsub);
- hb_set_destroy (_glyphset_mathed);
- hb_set_destroy (_glyphset_colred);
- hb_map_destroy (gsub_lookups);
- hb_map_destroy (gpos_lookups);
- hb_map_destroy (gsub_features);
- hb_map_destroy (gpos_features);
- hb_map_destroy (colrv1_layers);
- hb_map_destroy (colr_palettes);
- hb_map_destroy (axes_index_map);
- hb_map_destroy (axes_old_index_tag_map);
-
- hb_hashmap_destroy (gsub_langsys);
- hb_hashmap_destroy (gpos_langsys);
- hb_hashmap_destroy (gsub_feature_record_cond_idx_map);
- hb_hashmap_destroy (gpos_feature_record_cond_idx_map);
- hb_hashmap_destroy (gsub_feature_substitutes_map);
- hb_hashmap_destroy (gpos_feature_substitutes_map);
- hb_hashmap_destroy (axes_location);
- hb_hashmap_destroy (sanitized_table_cache);
- hb_hashmap_destroy (hmtx_map);
- hb_hashmap_destroy (vmtx_map);
- hb_hashmap_destroy (layout_variation_idx_delta_map);
#ifdef HB_EXPERIMENTAL_API
- if (name_table_overrides)
- {
- for (auto _ : *name_table_overrides)
- _.second.fini ();
- }
- hb_hashmap_destroy (name_table_overrides);
+ for (auto _ : name_table_overrides)
+ _.second.fini ();
#endif
if (inprogress_accelerator)
hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
-
- if (user_axes_location)
- {
- hb_object_destroy (user_axes_location);
- hb_free (user_axes_location);
- }
}
hb_object_header_t header;
@@ -114,101 +98,109 @@ struct hb_subset_plan_t
bool force_long_loca = false;
// For each cp that we'd like to retain maps to the corresponding gid.
- hb_set_t *unicodes;
+ hb_set_t unicodes;
hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list;
// name_ids we would like to retain
- hb_set_t *name_ids;
+ hb_set_t name_ids;
// name_languages we would like to retain
- hb_set_t *name_languages;
+ hb_set_t name_languages;
//layout features which will be preserved
- hb_set_t *layout_features;
+ hb_set_t layout_features;
// layout scripts which will be preserved.
- hb_set_t *layout_scripts;
+ hb_set_t layout_scripts;
//glyph ids requested to retain
- hb_set_t *glyphs_requested;
+ hb_set_t glyphs_requested;
// Tables which should not be processed, just pass them through.
- hb_set_t *no_subset_tables;
+ hb_set_t no_subset_tables;
// Tables which should be dropped.
- hb_set_t *drop_tables;
+ hb_set_t drop_tables;
// The glyph subset
- hb_map_t *codepoint_to_glyph;
+ hb_map_t *codepoint_to_glyph; // Needs to be heap-allocated
// Old -> New glyph id mapping
- hb_map_t *glyph_map;
- hb_map_t *reverse_glyph_map;
- hb_map_t *glyph_map_gsub;
+ hb_map_t *glyph_map; // Needs to be heap-allocated
+ hb_map_t *reverse_glyph_map; // Needs to be heap-allocated
+ hb_map_t glyph_map_gsub;
// Plan is only good for a specific source/dest so keep them with it
hb_face_t *source;
hb_face_t *dest;
unsigned int _num_output_glyphs;
- hb_set_t *_glyphset;
- hb_set_t *_glyphset_gsub;
- hb_set_t *_glyphset_mathed;
- hb_set_t *_glyphset_colred;
+ 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;
+ hb_map_t gsub_lookups;
+ hb_map_t gpos_lookups;
//active langsys we'd like to retain
- hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gsub_langsys;
- hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gpos_langsys;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> gsub_langsys;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> gpos_langsys;
//active features after removing redundant langsys and prune_features
- hb_map_t *gsub_features;
- hb_map_t *gpos_features;
+ hb_map_t gsub_features;
+ hb_map_t gpos_features;
//active feature variation records/condition index with variations
- hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gsub_feature_record_cond_idx_map;
- hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gpos_feature_record_cond_idx_map;
+ hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> gsub_feature_record_cond_idx_map;
+ hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> gpos_feature_record_cond_idx_map;
//feature index-> address of substituation feature table mapping with
//variations
- hb_hashmap_t<unsigned, const OT::Feature*> *gsub_feature_substitutes_map;
- hb_hashmap_t<unsigned, const OT::Feature*> *gpos_feature_substitutes_map;
+ hb_hashmap_t<unsigned, const OT::Feature*> gsub_feature_substitutes_map;
+ hb_hashmap_t<unsigned, const OT::Feature*> gpos_feature_substitutes_map;
//active layers/palettes we'd like to retain
- hb_map_t *colrv1_layers;
- hb_map_t *colr_palettes;
+ hb_map_t colrv1_layers;
+ hb_map_t colr_palettes;
//Old layout item variation index -> (New varidx, delta) mapping
- hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map;
+ hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> layout_variation_idx_delta_map;
//gdef varstore retained varidx mapping
hb_vector_t<hb_inc_bimap_t> gdef_varstore_inner_maps;
- hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache;
+ hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>> sanitized_table_cache;
//normalized axes location map
- hb_hashmap_t<hb_tag_t, int> *axes_location;
+ hb_hashmap_t<hb_tag_t, int> axes_location;
+ hb_vector_t<int> normalized_coords;
//user specified axes location map
- hb_hashmap_t<hb_tag_t, float> *user_axes_location;
+ hb_hashmap_t<hb_tag_t, float> user_axes_location;
//retained old axis index -> new axis index mapping in fvar axis array
- hb_map_t *axes_index_map;
+ hb_map_t axes_index_map;
//axis_index->axis_tag mapping in fvar axis array
- hb_map_t *axes_old_index_tag_map;
+ hb_map_t axes_old_index_tag_map;
bool all_axes_pinned;
bool pinned_at_default;
bool has_seac;
//hmtx metrics map: new gid->(advance, lsb)
- hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *hmtx_map;
+ mutable hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> hmtx_map;
//vmtx metrics map: new gid->(advance, lsb)
- hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *vmtx_map;
+ mutable hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> vmtx_map;
+ //boundsWidth map: new gid->boundsWidth, boundWidth=xMax - xMin
+ mutable hb_map_t bounds_width_map;
+ //boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin
+ mutable hb_map_t bounds_height_map;
+
+ //recalculated head/maxp table info after instancing
+ mutable head_maxp_info_t head_maxp_info;
#ifdef HB_EXPERIMENTAL_API
// name table overrides map: hb_ot_name_record_ids_t-> name string new value or
// None to indicate should remove
- hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides;
+ hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> name_table_overrides;
#endif
const hb_subset_accelerator_t* accelerator;
@@ -221,7 +213,7 @@ struct hb_subset_plan_t
{
hb_lock_t (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
- auto *cache = accelerator ? &accelerator->sanitized_table_cache : sanitized_table_cache;
+ auto *cache = accelerator ? &accelerator->sanitized_table_cache : &sanitized_table_cache;
if (cache
&& !cache->in_error ()
&& cache->has (+T::tableTag)) {
@@ -253,7 +245,7 @@ struct hb_subset_plan_t
inline const hb_set_t *
glyphset () const
{
- return _glyphset;
+ return &_glyphset;
}
/*
@@ -262,7 +254,7 @@ struct hb_subset_plan_t
inline const hb_set_t *
glyphset_gsub () const
{
- return _glyphset_gsub;
+ return &_glyphset_gsub;
}
/*
@@ -280,7 +272,7 @@ struct hb_subset_plan_t
*/
inline bool is_empty_glyph (hb_codepoint_t gid) const
{
- return !_glyphset->has (gid);
+ return !_glyphset.has (gid);
}
inline bool new_gid_for_codepoint (hb_codepoint_t codepoint,
@@ -322,7 +314,7 @@ struct hb_subset_plan_t
if (HB_DEBUG_SUBSET)
{
hb_blob_t *source_blob = source->reference_table (tag);
- DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes",
+ DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %u bytes, source %u bytes",
HB_UNTAG(tag),
hb_blob_get_length (contents),
hb_blob_get_length (source_blob));
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc
index 55ca48d709..6a29b35be7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc
@@ -38,7 +38,7 @@
* Table specific optimizations (eg. extension promotion in GSUB/GPOS) may be performed.
* Passing HB_TAG_NONE will disable table specific optimizations.
*
- * Since: EXPERIMENTAL
+ * XSince: EXPERIMENTAL
**/
hb_blob_t* hb_subset_repack_or_fail (hb_tag_t table_tag,
hb_object_t* hb_objects,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
index 186b12dbb8..82df3386f5 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
@@ -37,9 +37,10 @@
#include "hb-ot-hhea-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-maxp-table.hh"
-#include "hb-ot-color-sbix-table.hh"
-#include "hb-ot-color-colr-table.hh"
-#include "hb-ot-color-cpal-table.hh"
+#include "OT/Color/CBDT/CBDT.hh"
+#include "OT/Color/COLR/COLR.hh"
+#include "OT/Color/CPAL/CPAL.hh"
+#include "OT/Color/sbix/sbix.hh"
#include "hb-ot-os2-table.hh"
#include "hb-ot-post-table.hh"
#include "hb-ot-post-table-v2subset.hh"
@@ -47,7 +48,6 @@
#include "hb-ot-cff2-table.hh"
#include "hb-ot-vorg-table.hh"
#include "hb-ot-name-table.hh"
-#include "hb-ot-color-cbdt-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
#include "hb-ot-var-fvar-table.hh"
@@ -168,11 +168,11 @@ _get_table_tags (const hb_subset_plan_t* plan,
hb_concat (
+ hb_array (known_tables)
| hb_filter ([&] (hb_tag_t tag) {
- return !_table_is_empty (plan->source, tag) && !plan->no_subset_tables->has (tag);
+ return !_table_is_empty (plan->source, tag) && !plan->no_subset_tables.has (tag);
})
| hb_map ([] (hb_tag_t tag) -> hb_tag_t { return tag; }),
- plan->no_subset_tables->iter ()
+ plan->no_subset_tables.iter ()
| hb_filter([&] (hb_tag_t tag) {
return !_table_is_empty (plan->source, tag);
}));
@@ -208,13 +208,6 @@ _plan_estimate_subset_table_size (hb_subset_plan_t *plan,
static hb_blob_t*
_repack (hb_tag_t tag, const hb_serialize_context_t& c)
{
- if (tag != HB_OT_TAG_GPOS
- && tag != HB_OT_TAG_GSUB)
- {
- // Check for overflow in a non-handled table.
- return c.successful () ? c.copy_blob () : nullptr;
- }
-
if (!c.offset_overflow ())
return c.copy_blob ();
@@ -257,7 +250,7 @@ _try_subset (const TableType *table,
HB_UNTAG (c->table_tag), buf_size);
if (unlikely (buf_size > c->source_blob->length * 16 ||
- !buf->alloc (buf_size)))
+ !buf->alloc (buf_size, true)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
HB_UNTAG (c->table_tag), buf_size);
@@ -362,7 +355,7 @@ _is_table_present (hb_face_t *source, hb_tag_t tag)
static bool
_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
{
- if (plan->drop_tables->has (tag))
+ if (plan->drop_tables.has (tag))
return true;
switch (tag)
@@ -420,7 +413,8 @@ _dependencies_satisfied (hb_subset_plan_t *plan, hb_tag_t tag,
{
case HB_OT_TAG_hmtx:
case HB_OT_TAG_vmtx:
- return plan->pinned_at_default || !pending_subset_tags.has (HB_OT_TAG_glyf);
+ case HB_OT_TAG_maxp:
+ return !plan->normalized_coords || !pending_subset_tags.has (HB_OT_TAG_glyf);
default:
return true;
}
@@ -431,7 +425,7 @@ _subset_table (hb_subset_plan_t *plan,
hb_vector_t<char> &buf,
hb_tag_t tag)
{
- if (plan->no_subset_tables->has (tag)) {
+ if (plan->no_subset_tables.has (tag)) {
return _passthrough (plan, tag);
}
@@ -476,7 +470,7 @@ _subset_table (hb_subset_plan_t *plan,
case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf);
#endif
case HB_OT_TAG_fvar:
- if (plan->user_axes_location->is_empty ()) return _passthrough (plan, tag);
+ if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
return _subset<const OT::fvar> (plan, buf);
case HB_OT_TAG_STAT:
/*TODO(qxliu): change the condition as we support more complex
@@ -632,3 +626,8 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
end:
return success ? hb_face_reference (plan->dest) : nullptr;
}
+
+#ifndef HB_NO_VISIBILITY
+/* If NO_VISIBILITY, libharfbuzz has this. */
+#include "hb-ot-name-language-static.hh"
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.h b/src/3rdparty/harfbuzz-ng/src/hb-subset.h
index b83264ea5e..c14b1b1803 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.h
@@ -71,14 +71,6 @@ typedef struct hb_subset_plan_t hb_subset_plan_t;
* in the final subset.
* @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in
* OS/2 will not be recalculated.
- * @HB_SUBSET_FLAGS_PATCH_MODE: If set the subsetter behaviour will be modified
- * to produce a subset that is better suited to patching. For example cmap
- * subtable format will be kept stable.
- * @HB_SUBSET_FLAGS_OMIT_GLYF: If set the subsetter won't actually produce the final
- * glyf table bytes. The table directory will include and entry as if the table was
- * there but the actual final font blob will be truncated prior to the glyf data. This
- * is a useful performance optimization when a font aware binary patching algorithm
- * is being used to diff two subsets.
*
* List of boolean properties that can be configured on the subset input.
*
@@ -95,8 +87,6 @@ typedef enum { /*< flags >*/
HB_SUBSET_FLAGS_NOTDEF_OUTLINE = 0x00000040u,
HB_SUBSET_FLAGS_GLYPH_NAMES = 0x00000080u,
HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u,
- // Not supported yet: HB_SUBSET_FLAGS_PATCH_MODE = 0x00000200u,
- // Not supported yet: HB_SUBSET_FLAGS_OMIT_GLYF = 0x00000400u,
} hb_subset_flags_t;
/**
@@ -149,6 +139,9 @@ HB_EXTERN void *
hb_subset_input_get_user_data (const hb_subset_input_t *input,
hb_user_data_key_t *key);
+HB_EXTERN void
+hb_subset_input_keep_everything (hb_subset_input_t *input);
+
HB_EXTERN hb_set_t *
hb_subset_input_unicode_set (hb_subset_input_t *input);
@@ -204,13 +197,13 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
HB_EXTERN void
hb_subset_plan_destroy (hb_subset_plan_t *plan);
-HB_EXTERN const hb_map_t*
+HB_EXTERN hb_map_t *
hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan);
-HB_EXTERN const hb_map_t*
+HB_EXTERN hb_map_t *
hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan);
-HB_EXTERN const hb_map_t*
+HB_EXTERN hb_map_t *
hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset.hh
index 98c5f06fbf..4f192aae40 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.hh
@@ -33,6 +33,7 @@
#include "hb-subset.h"
#include "hb-machinery.hh"
+#include "hb-serialize.hh"
#include "hb-subset-input.hh"
#include "hb-subset-plan.hh"
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
index 9a6471e52c..aa2735bedb 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
@@ -165,7 +165,7 @@ hb_unicode_funcs_get_default ()
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
#error "Could not find any Unicode functions implementation, you have to provide your own"
-#error "Consider building hb-ucd.cc. If you absolutely want to build without any, check the code."
+#error "Consider building hb-ucd.cc. If you absolutely want to build without any, define HB_NO_UNICODE_FUNCS."
#endif
/**
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-utf.hh b/src/3rdparty/harfbuzz-ng/src/hb-utf.hh
index ff5712d16d..1120bd1ccc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-utf.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-utf.hh
@@ -35,6 +35,7 @@
struct hb_utf8_t
{
typedef uint8_t codepoint_t;
+ static constexpr unsigned max_len = 4;
static const codepoint_t *
next (const codepoint_t *text,
@@ -182,6 +183,7 @@ struct hb_utf16_xe_t
{
static_assert (sizeof (TCodepoint) == 2, "");
typedef TCodepoint codepoint_t;
+ static constexpr unsigned max_len = 2;
static const codepoint_t *
next (const codepoint_t *text,
@@ -290,6 +292,7 @@ struct hb_utf32_xe_t
{
static_assert (sizeof (TCodepoint) == 4, "");
typedef TCodepoint codepoint_t;
+ static constexpr unsigned max_len = 1;
static const TCodepoint *
next (const TCodepoint *text,
@@ -348,6 +351,7 @@ typedef hb_utf32_xe_t<uint32_t, false> hb_utf32_novalidate_t;
struct hb_latin1_t
{
typedef uint8_t codepoint_t;
+ static constexpr unsigned max_len = 1;
static const codepoint_t *
next (const codepoint_t *text,
@@ -399,12 +403,13 @@ struct hb_latin1_t
struct hb_ascii_t
{
typedef uint8_t codepoint_t;
+ static constexpr unsigned max_len = 1;
static const codepoint_t *
next (const codepoint_t *text,
const codepoint_t *end HB_UNUSED,
hb_codepoint_t *unicode,
- hb_codepoint_t replacement HB_UNUSED)
+ hb_codepoint_t replacement)
{
*unicode = *text++;
if (*unicode >= 0x0080u)
@@ -450,4 +455,27 @@ struct hb_ascii_t
}
};
+template <typename utf_t>
+static inline const typename utf_t::codepoint_t *
+hb_utf_offset_to_pointer (const typename utf_t::codepoint_t *start,
+ signed offset)
+{
+ hb_codepoint_t unicode;
+
+ while (offset-- > 0)
+ start = utf_t::next (start,
+ start + utf_t::max_len,
+ &unicode,
+ HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
+
+ while (offset++ < 0)
+ start = utf_t::prev (start,
+ start - utf_t::max_len,
+ &unicode,
+ HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
+
+ return start;
+}
+
+
#endif /* HB_UTF_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
index 9b52f5ca95..58d467a405 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
@@ -45,7 +45,7 @@ struct hb_vector_t
hb_vector_t () = default;
hb_vector_t (std::initializer_list<Type> lst) : hb_vector_t ()
{
- alloc (lst.size ());
+ alloc (lst.size (), true);
for (auto&& item : lst)
push (item);
}
@@ -55,12 +55,12 @@ struct hb_vector_t
{
auto iter = hb_iter (o);
if (iter.is_random_access_iterator)
- alloc (hb_len (iter));
+ alloc (hb_len (iter), true);
hb_copy (iter, *this);
}
hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
{
- alloc (o.length);
+ alloc (o.length, true);
if (unlikely (in_error ())) return;
copy_vector (o);
}
@@ -116,7 +116,7 @@ struct hb_vector_t
hb_vector_t& operator = (const hb_vector_t &o)
{
reset ();
- alloc (o.length);
+ alloc (o.length, true);
if (unlikely (in_error ())) return *this;
copy_vector (o);
@@ -233,6 +233,11 @@ struct hb_vector_t
Type *
realloc_vector (unsigned new_allocated)
{
+ if (!new_allocated)
+ {
+ hb_free (arrayZ);
+ return nullptr;
+ }
return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
}
template <typename T = Type,
@@ -240,6 +245,11 @@ struct hb_vector_t
Type *
realloc_vector (unsigned new_allocated)
{
+ if (!new_allocated)
+ {
+ hb_free (arrayZ);
+ return nullptr;
+ }
Type *new_array = (Type *) hb_malloc (new_allocated * sizeof (Type));
if (likely (new_array))
{
@@ -337,30 +347,53 @@ struct hb_vector_t
}
/* Allocate for size but don't adjust length. */
- bool alloc (unsigned int size)
+ bool alloc (unsigned int size, bool exact=false)
{
if (unlikely (in_error ()))
return false;
- if (likely (size <= (unsigned) allocated))
- return true;
+ unsigned int new_allocated;
+ if (exact)
+ {
+ /* If exact was specified, we allow shrinking the storage. */
+ size = hb_max (size, length);
+ if (size <= (unsigned) allocated &&
+ size >= (unsigned) allocated >> 2)
+ return true;
- /* Reallocate */
+ new_allocated = size;
+ }
+ else
+ {
+ if (likely (size <= (unsigned) allocated))
+ return true;
+
+ new_allocated = allocated;
+ while (size > new_allocated)
+ new_allocated += (new_allocated >> 1) + 8;
+ }
- unsigned int new_allocated = allocated;
- while (size >= new_allocated)
- new_allocated += (new_allocated >> 1) + 8;
- Type *new_array = nullptr;
+ /* Reallocate */
+
bool overflows =
(int) in_error () ||
- (new_allocated < (unsigned) allocated) ||
+ (new_allocated < size) ||
hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
- if (likely (!overflows))
- new_array = realloc_vector (new_allocated);
- if (unlikely (!new_array))
+ if (unlikely (overflows))
+ {
+ allocated = -1;
+ return false;
+ }
+
+ Type *new_array = realloc_vector (new_allocated);
+
+ if (unlikely (new_allocated && !new_array))
{
+ if (new_allocated <= (unsigned) allocated)
+ return true; // shrinking failed; it's okay; happens in our fuzzer
+
allocated = -1;
return false;
}
@@ -371,10 +404,10 @@ struct hb_vector_t
return true;
}
- bool resize (int size_, bool initialize = true)
+ bool resize (int size_, bool initialize = true, bool exact = false)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
- if (!alloc (size))
+ if (!alloc (size, exact))
return false;
if (size > length)
@@ -391,6 +424,10 @@ struct hb_vector_t
length = size;
return true;
}
+ bool resize_exact (int size_, bool initialize = true)
+ {
+ return resize (size_, initialize, true);
+ }
Type pop ()
{
@@ -422,13 +459,16 @@ struct hb_vector_t
length--;
}
- void shrink (int size_)
+ void shrink (int size_, bool shrink_memory = true)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (size >= length)
return;
shrink_vector (size);
+
+ if (shrink_memory)
+ alloc (size, true); /* To force shrinking memory if needed. */
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-version.h b/src/3rdparty/harfbuzz-ng/src/hb-version.h
index 1070262a3b..e7efeb395c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-version.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-version.h
@@ -41,7 +41,7 @@ HB_BEGIN_DECLS
*
* The major component of the library version available at compile-time.
*/
-#define HB_VERSION_MAJOR 6
+#define HB_VERSION_MAJOR 7
/**
* HB_VERSION_MINOR:
*
@@ -53,14 +53,14 @@ HB_BEGIN_DECLS
*
* 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 "6.0.0"
+#define HB_VERSION_STRING "7.0.1"
/**
* HB_VERSION_ATLEAST:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb.h b/src/3rdparty/harfbuzz-ng/src/hb.h
index 360686ca68..5a6ae6607c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb.h
@@ -36,6 +36,7 @@
#include "hb-face.h"
#include "hb-font.h"
#include "hb-map.h"
+#include "hb-paint.h"
#include "hb-set.h"
#include "hb-shape.h"
#include "hb-shape-plan.h"
diff --git a/src/3rdparty/harfbuzz-ng/src/hb.hh b/src/3rdparty/harfbuzz-ng/src/hb.hh
index 410d090d36..857571b42f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb.hh
@@ -103,20 +103,20 @@
#pragma GCC diagnostic warning "-Wdisabled-optimization"
#pragma GCC diagnostic warning "-Wdouble-promotion"
#pragma GCC diagnostic warning "-Wformat=2"
+#pragma GCC diagnostic warning "-Wformat-signedness"
#pragma GCC diagnostic warning "-Wignored-pragma-optimize"
#pragma GCC diagnostic warning "-Wlogical-op"
#pragma GCC diagnostic warning "-Wmaybe-uninitialized"
#pragma GCC diagnostic warning "-Wmissing-format-attribute"
#pragma GCC diagnostic warning "-Wundef"
+#pragma GCC diagnostic warning "-Wunsafe-loop-optimizations"
#pragma GCC diagnostic warning "-Wunused-but-set-variable"
#endif
/* Ignored currently, but should be fixed at some point. */
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
#pragma GCC diagnostic ignored "-Wconversion" // TODO fix
-#pragma GCC diagnostic ignored "-Wformat-signedness" // TODO fix
#pragma GCC diagnostic ignored "-Wshadow" // TODO fix
-#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" // TODO fix
#pragma GCC diagnostic ignored "-Wunused-parameter" // TODO fix
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic ignored "-Wunused-result" // TODO fix
@@ -127,6 +127,7 @@
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#pragma GCC diagnostic ignored "-Wcast-function-type-strict" // https://github.com/harfbuzz/harfbuzz/pull/3859#issuecomment-1295409126
+#pragma GCC diagnostic ignored "-Wdangling-reference" // https://github.com/harfbuzz/harfbuzz/issues/4043
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#pragma GCC diagnostic ignored "-Wformat-zero-length"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
@@ -142,6 +143,7 @@
#include "hb-config.hh"
+#include "hb-limits.hh"
/*
@@ -461,6 +463,37 @@ static int HB_UNUSED _hb_errno = 0;
#endif
#endif
+
+// Locale business
+
+#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)
+
+#endif
+
+
/* Lets assert int types. Saves trouble down the road. */
static_assert ((sizeof (hb_codepoint_t) == 4), "");
static_assert ((sizeof (hb_position_t) == 4), "");
diff --git a/src/3rdparty/harfbuzz-ng/src/main.cc b/src/3rdparty/harfbuzz-ng/src/main.cc
index bb18ebe386..edc9872eed 100644
--- a/src/3rdparty/harfbuzz-ng/src/main.cc
+++ b/src/3rdparty/harfbuzz-ng/src/main.cc
@@ -220,7 +220,7 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index
hb_glyph_extents_t extents = {0};
if (!hb_font_get_glyph_extents (font, gid, &extents))
{
- printf ("Skip gid: %d\n", gid);
+ printf ("Skip gid: %u\n", gid);
continue;
}
@@ -270,7 +270,7 @@ dump_glyphs (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index)
hb_glyph_extents_t extents = {0};
if (!hb_font_get_glyph_extents (font, gid, &extents))
{
- printf ("Skip gid: %d\n", gid);
+ printf ("Skip gid: %u\n", gid);
continue;
}
@@ -393,18 +393,18 @@ print_layout_info_using_private_api (hb_blob_t *blob)
}
unsigned num_faces = hb_face_count (blob);
- printf ("%d font(s) found in file\n", num_faces);
+ printf ("%u font(s) found in file\n", num_faces);
for (unsigned n_font = 0; n_font < num_faces; ++n_font)
{
const OpenTypeFontFace &font = ot.get_face (n_font);
- printf ("Font %d of %d:\n", n_font, num_faces);
+ printf ("Font %u of %u:\n", n_font, num_faces);
unsigned num_tables = font.get_table_count ();
- printf (" %d table(s) found in font\n", num_tables);
+ printf (" %u table(s) found in font\n", num_tables);
for (unsigned n_table = 0; n_table < num_tables; ++n_table)
{
const OpenTypeTable &table = font.get_table (n_table);
- printf (" Table %2d of %2d: %.4s (0x%08x+0x%08x)\n", n_table, num_tables,
+ printf (" Table %2u of %2u: %.4s (0x%08x+0x%08x)\n", n_table, num_tables,
(const char *) table.tag,
(unsigned) table.offset,
(unsigned) table.length);
@@ -419,11 +419,11 @@ print_layout_info_using_private_api (hb_blob_t *blob)
const GSUBGPOS &g = *reinterpret_cast<const GSUBGPOS *> (font_data + table.offset);
unsigned num_scripts = g.get_script_count ();
- printf (" %d script(s) found in table\n", num_scripts);
+ printf (" %u script(s) found in table\n", num_scripts);
for (unsigned n_script = 0; n_script < num_scripts; ++n_script)
{
const Script &script = g.get_script (n_script);
- printf (" Script %2d of %2d: %.4s\n", n_script, num_scripts,
+ printf (" Script %2u of %2u: %.4s\n", n_script, num_scripts,
(const char *) g.get_script_tag (n_script));
if (!script.has_default_lang_sys ())
@@ -443,41 +443,41 @@ print_layout_info_using_private_api (hb_blob_t *blob)
if (!langsys.has_required_feature ())
printf (" No required feature\n");
else
- printf (" Required feature index: %d\n",
+ printf (" Required feature index: %u\n",
langsys.get_required_feature_index ());
unsigned num_features = langsys.get_feature_count ();
- printf (" %d feature(s) found in language system\n", num_features);
+ printf (" %u feature(s) found in language system\n", num_features);
for (unsigned n_feature = 0; n_feature < num_features; ++n_feature)
{
- printf (" Feature index %2d of %2d: %d\n", n_feature, num_features,
+ printf (" Feature index %2u of %2u: %u\n", n_feature, num_features,
langsys.get_feature_index (n_feature));
}
}
}
unsigned num_features = g.get_feature_count ();
- printf (" %d feature(s) found in table\n", num_features);
+ printf (" %u feature(s) found in table\n", num_features);
for (unsigned n_feature = 0; n_feature < num_features; ++n_feature)
{
const Feature &feature = g.get_feature (n_feature);
unsigned num_lookups = feature.get_lookup_count ();
- printf (" Feature %2d of %2d: %c%c%c%c\n", n_feature, num_features,
+ printf (" Feature %2u of %2u: %c%c%c%c\n", n_feature, num_features,
HB_UNTAG (g.get_feature_tag (n_feature)));
- printf (" %d lookup(s) found in feature\n", num_lookups);
+ printf (" %u lookup(s) found in feature\n", num_lookups);
for (unsigned n_lookup = 0; n_lookup < num_lookups; ++n_lookup) {
- printf (" Lookup index %2d of %2d: %d\n", n_lookup, num_lookups,
+ printf (" Lookup index %2u of %2u: %u\n", n_lookup, num_lookups,
feature.get_lookup_index (n_lookup));
}
}
unsigned num_lookups = g.get_lookup_count ();
- printf (" %d lookup(s) found in table\n", num_lookups);
+ printf (" %u lookup(s) found in table\n", num_lookups);
for (unsigned n_lookup = 0; n_lookup < num_lookups; ++n_lookup)
{
const Lookup &lookup = g.get_lookup (n_lookup);
- printf (" Lookup %2d of %2d: type %d, props 0x%04X\n", n_lookup, num_lookups,
+ printf (" Lookup %2u of %2u: type %u, props 0x%04X\n", n_lookup, num_lookups,
lookup.get_type (), lookup.get_props ());
}
@@ -519,7 +519,7 @@ main (int argc, char **argv)
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
assert (blob);
- printf ("Opened font file %s: %d bytes long\n", argv[1], hb_blob_get_length (blob));
+ printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob));
#ifndef MAIN_CC_NO_PRIVATE_API
print_layout_info_using_private_api (blob);
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/test-algs.cc b/src/3rdparty/harfbuzz-ng/src/test-algs.cc
deleted file mode 100644
index 450a7c439b..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-algs.cc
+++ /dev/null
@@ -1,110 +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-algs.hh"
-#include "hb-set.hh"
-
-
-static char *
-test_func (int a, char **b)
-{
- return b ? b[a] : nullptr;
-}
-
-struct A
-{
- void a () {}
-};
-
-int
-main (int argc, char **argv)
-{
- int i = 1;
- auto p = hb_pair (1, i);
-
- p.second = 2;
- assert (i == 2);
-
- const int c = 3;
- auto pc = hb_pair (1, c);
- assert (pc.second == 3);
-
- auto q = p;
- assert (&q != &p);
- q.second = 4;
- assert (i == 4);
-
- hb_invoke (test_func, 0, nullptr);
-
- A a;
- hb_invoke (&A::a, a);
-
- assert (1 == hb_min (8, 1));
- assert (8 == hb_max (8, 1));
-
- int x = 1, y = 2;
- hb_min (x, 3);
- hb_min (3, x);
- hb_min (x, 4 + 3);
- int &z = hb_min (x, y);
- z = 3;
- assert (x == 3);
-
- hb_pair_t<const int*, int> xp = hb_pair_t<int *, long> (nullptr, 0);
- xp = hb_pair_t<int *, double> (nullptr, 1);
- xp = hb_pair_t<const int*, int> (nullptr, 1);
-
- assert (3 == hb_partial (hb_min, 3) (4));
- assert (3 == hb_partial<1> (hb_min, 4) (3));
-
- auto M0 = hb_partial<2> (hb_max, 0);
- assert (M0 (-2) == 0);
- assert (M0 (+2) == 2);
-
- assert (hb_add (2) (5) == 7);
- assert (hb_add (5) (2) == 7);
-
- x = 1;
- assert (++hb_inc (x) == 3);
- assert (x == 3);
-
- hb_set_t set1 {1};
- hb_set_t set2 {2};
-
- assert (hb_hash (set1) != hb_hash (set2));
- assert (hb_hash (set1) == hb_hash (hb_set_t {1}));
- assert (hb_hash (set1) != hb_hash (hb_set_t {}));
- assert (hb_hash (set1) != hb_hash (hb_set_t {2}));
- assert (hb_hash (set2) == hb_hash (hb_set_t {2}));
-
- /* hb_hash, unlike std::hash, dereferences pointers. */
- assert (hb_hash (set1) == hb_hash (&set1));
- assert (hb_hash (set1) == hb_hash (hb::shared_ptr<hb_set_t> {hb_set_reference (&set1)}));
- assert (hb_hash (set1) == hb_hash (hb::unique_ptr<hb_set_t> {hb_set_reference (&set1)}));
-
- return 0;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-array.cc b/src/3rdparty/harfbuzz-ng/src/test-array.cc
deleted file mode 100644
index 28cd023646..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-array.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright © 2020 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger
- */
-
-#include "hb.hh"
-#include "hb-array.hh"
-
-static void
-test_reverse ()
-{
- int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- hb_array_t<int> a (values, 9);
- a.reverse();
-
- int expected_values[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};
- hb_array_t<int> expected (expected_values, 9);
- assert (a == expected);
-}
-
-static void
-test_reverse_range ()
-{
- int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- hb_array_t<int> a (values, 9);
- a.reverse(2, 6);
-
- int expected_values[] = {1, 2, 6, 5, 4, 3, 7, 8, 9};
- hb_array_t<int> expected (expected_values, 9);
- assert (a == expected);
-}
-
-static void
-test_reverse_invalid ()
-{
- int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- hb_array_t<int> a (values, 9);
-
- a.reverse(4, 3);
- a.reverse(2, 3);
- a.reverse(5, 5);
- a.reverse(12, 15);
-
- int expected_values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- hb_array_t<int> expected (expected_values, 9);
- assert (a == expected);
-}
-
-int
-main (int argc, char **argv)
-{
- /* The following fails on MSVC. */
- // assert (sizeof (hb_array_t<int>) == sizeof (hb_sorted_array_t<int>));
-
- test_reverse ();
- test_reverse_range ();
- test_reverse_invalid ();
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-bimap.cc b/src/3rdparty/harfbuzz-ng/src/test-bimap.cc
deleted file mode 100644
index 1253d0c1df..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-bimap.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright © 2019 Adobe, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Adobe Author(s): Michiharu Ariza
- */
-
-#include "hb.hh"
-#include "hb-bimap.hh"
-
-int
-main (int argc, char **argv)
-{
- hb_bimap_t bm;
-
- assert (bm.is_empty () == true);
- bm.set (1, 4);
- bm.set (2, 5);
- bm.set (3, 6);
- assert (bm.get_population () == 3);
- assert (bm.has (1) == true);
- assert (bm.has (4) == false);
- assert (bm[2] == 5);
- assert (bm.backward (6) == 3);
- bm.del (1);
- assert (bm.has (1) == false);
- assert (bm.has (3) == true);
- bm.clear ();
- assert (bm.get_population () == 0);
-
- hb_inc_bimap_t ibm;
-
- assert (ibm.add (13) == 0);
- assert (ibm.add (8) == 1);
- assert (ibm.add (10) == 2);
- assert (ibm.add (8) == 1);
- assert (ibm.add (7) == 3);
- assert (ibm.get_population () == 4);
- assert (ibm[7] == 3);
-
- ibm.sort ();
- assert (ibm.get_population () == 4);
- assert (ibm[7] == 0);
- assert (ibm[13] == 3);
-
- ibm.identity (3);
- assert (ibm.get_population () == 3);
- assert (ibm[0] == 0);
- assert (ibm[1] == 1);
- assert (ibm[2] == 2);
- assert (ibm.backward (0) == 0);
- assert (ibm.backward (1) == 1);
- assert (ibm.backward (2) == 2);
- assert (ibm.has (4) == false);
-
- return 0;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-buffer-serialize.cc b/src/3rdparty/harfbuzz-ng/src/test-buffer-serialize.cc
deleted file mode 100644
index 8a887922be..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-buffer-serialize.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright © 2010,2011,2013 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#include "hb.h"
-#include "hb-ot.h"
-#ifdef HAVE_FREETYPE
-#include "hb-ft.h"
-#endif
-
-#ifdef HB_NO_OPEN
-#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
-#endif
-
-int
-main (int argc, char **argv)
-{
- bool ret = true;
-
-#ifndef HB_NO_BUFFER_SERIALIZE
-
- if (argc < 2)
- argv[1] = (char *) "/dev/null";
-
- hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
- assert (blob);
- hb_face_t *face = hb_face_create (blob, 0 /* first face */);
- hb_blob_destroy (blob);
- blob = nullptr;
-
- unsigned int upem = hb_face_get_upem (face);
- hb_font_t *font = hb_font_create (face);
- hb_face_destroy (face);
- hb_font_set_scale (font, upem, upem);
- //hb_ot_font_set_funcs (font);
-#ifdef HAVE_FREETYPE
- //hb_ft_font_set_funcs (font);
-#endif
-
- hb_buffer_t *buf;
- buf = hb_buffer_create ();
-
- char line[BUFSIZ], out[BUFSIZ];
- while (fgets (line, sizeof(line), stdin))
- {
- hb_buffer_clear_contents (buf);
-
- const char *p = line;
- while (hb_buffer_deserialize_glyphs (buf,
- p, -1, &p,
- font,
- HB_BUFFER_SERIALIZE_FORMAT_TEXT))
- ;
- if (*p && *p != '\n')
- ret = false;
-
- hb_buffer_serialize_glyphs (buf, 0, hb_buffer_get_length (buf),
- out, sizeof (out), nullptr,
- font, HB_BUFFER_SERIALIZE_FORMAT_TEXT,
- HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS);
- puts (out);
- }
-
- hb_buffer_destroy (buf);
-
- hb_font_destroy (font);
-
-#endif
-
- return !ret;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-gpos-size-params.cc b/src/3rdparty/harfbuzz-ng/src/test-gpos-size-params.cc
deleted file mode 100644
index b96381ddcb..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-gpos-size-params.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright © 2010,2011 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#include "hb.h"
-#include "hb-ot.h"
-
-#ifdef HB_NO_OPEN
-#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
-#endif
-
-int
-main (int argc, char **argv)
-{
- if (argc != 2) {
- fprintf (stderr, "usage: %s font-file\n", argv[0]);
- exit (1);
- }
-
- /* Create the face */
- hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
- assert (blob);
- hb_face_t *face = hb_face_create (blob, 0 /* first face */);
- hb_blob_destroy (blob);
- blob = nullptr;
-
- bool ret = true;
-
-#ifndef HB_NO_LAYOUT_FEATURE_PARAMS
- unsigned int p[5];
- ret = hb_ot_layout_get_size_params (face, p, p+1, (p+2), p+3, p+4);
- printf ("%g %u %u %g %g\n", p[0]/10., p[1], p[2], p[3]/10., p[4]/10.);
-#endif
-
- hb_face_destroy (face);
-
- return !ret;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-gsub-would-substitute.cc b/src/3rdparty/harfbuzz-ng/src/test-gsub-would-substitute.cc
deleted file mode 100644
index 87123030ed..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-gsub-would-substitute.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright © 2010,2011 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#include "hb.h"
-#include "hb-ot.h"
-
-#ifdef HAVE_FREETYPE
-#include "hb-ft.h"
-#endif
-
-#ifdef HB_NO_OPEN
-#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
-#endif
-
-int
-main (int argc, char **argv)
-{
- if (argc != 4 && argc != 5) {
- fprintf (stderr, "usage: %s font-file lookup-index first-glyph [second-glyph]\n", argv[0]);
- exit (1);
- }
-
- /* Create the face */
- hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
- assert (blob);
- hb_face_t *face = hb_face_create (blob, 0 /* first face */);
- hb_blob_destroy (blob);
- blob = nullptr;
-
- hb_font_t *font = hb_font_create (face);
-#ifdef HAVE_FREETYPE
- hb_ft_font_set_funcs (font);
-#endif
-
- unsigned int len = argc - 3;
- hb_codepoint_t glyphs[2];
- if (!hb_font_glyph_from_string (font, argv[3], -1, &glyphs[0]) ||
- (argc > 4 &&
- !hb_font_glyph_from_string (font, argv[4], -1, &glyphs[1])))
- return 2;
- return !hb_ot_layout_lookup_would_substitute (face, strtol (argv[2], nullptr, 0), glyphs, len, false);
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-iter.cc b/src/3rdparty/harfbuzz-ng/src/test-iter.cc
deleted file mode 100644
index bb966d4c9c..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-iter.cc
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright © 2018 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-#include "hb-iter.hh"
-
-#include "hb-array.hh"
-#include "hb-set.hh"
-#include "hb-ot-layout-common.hh"
-
-template <typename T>
-struct array_iter_t : hb_iter_with_fallback_t<array_iter_t<T>, T&>
-{
- array_iter_t (hb_array_t<T> arr_) : arr (arr_) {}
-
- typedef T& __item_t__;
- static constexpr bool is_random_access_iterator = true;
- T& __item_at__ (unsigned i) const { return arr[i]; }
- void __forward__ (unsigned n) { arr += n; }
- void __rewind__ (unsigned n) { arr -= n; }
- unsigned __len__ () const { return arr.length; }
- bool operator != (const array_iter_t& o) { return arr != o.arr; }
-
- private:
- hb_array_t<T> arr;
-};
-
-template <typename T>
-struct some_array_t
-{
- some_array_t (hb_array_t<T> arr_) : arr (arr_) {}
-
- typedef array_iter_t<T> iter_t;
- array_iter_t<T> iter () { return array_iter_t<T> (arr); }
- operator array_iter_t<T> () { return iter (); }
- operator hb_iter_t<array_iter_t<T>> () { return iter (); }
-
- private:
- hb_array_t<T> arr;
-};
-
-
-template <typename Iter,
- hb_requires (hb_is_iterator (Iter))>
-static void
-test_iterator_non_default_constructable (Iter it)
-{
- /* Iterate over a copy of it. */
- for (auto c = it.iter (); c; c++)
- *c;
-
- /* Same. */
- for (auto c = +it; c; c++)
- *c;
-
- /* Range-based for over a copy. */
- for (auto _ : +it)
- (void) _;
-
- it += it.len ();
- it = it + 10;
- it = 10 + it;
-
- assert (*it == it[0]);
-
- static_assert (true || it.is_random_access_iterator, "");
- static_assert (true || it.is_sorted_iterator, "");
-}
-
-template <typename Iter,
- hb_requires (hb_is_iterator (Iter))>
-static void
-test_iterator (Iter it)
-{
- Iter default_constructed;
- assert (!default_constructed);
-
- test_iterator_non_default_constructable (it);
-}
-
-template <typename Iterable,
- hb_requires (hb_is_iterable (Iterable))>
-static void
-test_iterable (const Iterable &lst = Null (Iterable))
-{
- for (auto _ : lst)
- (void) _;
-
- // Test that can take iterator from.
- 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)
-{
- const int src[10] = {};
- int dst[20];
- hb_vector_t<int> v;
-
- array_iter_t<const int> s (src); /* Implicit conversion from static array. */
- array_iter_t<const int> s2 (v); /* Implicit conversion from vector. */
- array_iter_t<int> t (dst);
-
- static_assert (array_iter_t<int>::is_random_access_iterator, "");
-
- some_array_t<const int> a (src);
-
- s2 = s;
-
- hb_iter (src);
- hb_iter (src, 2);
-
- hb_fill (t, 42);
- hb_copy (s, t);
- hb_copy (a.iter (), t);
-
- test_iterable (v);
- hb_set_t st;
- st << 1 << 15 << 43;
- test_iterable (st);
- hb_sorted_array_t<int> sa;
- (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, hb_sorted_array_t<int>::item_t>&> (sa);
- (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, hb_sorted_array_t<int>::__item_t__>&> (sa);
- (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, int&>&>(sa);
- (void) static_cast<hb_iter_t<hb_sorted_array_t<int>>&>(sa);
- (void) static_cast<hb_iter_t<hb_array_t<int>, int&>&> (sa);
- test_iterable (sa);
-
- test_iterable<hb_array_t<int>> ();
- test_iterable<hb_sorted_array_t<const int>> ();
- test_iterable<hb_vector_t<float>> ();
- test_iterable<hb_set_t> ();
- test_iterable<OT::Array16Of<OT::HBUINT16>> ();
-
- test_iterator (hb_zip (st, v));
- test_iterator_non_default_constructable (hb_enumerate (st));
- test_iterator_non_default_constructable (hb_enumerate (st, -5));
- test_iterator_non_default_constructable (hb_enumerate (hb_iter (st)));
- test_iterator_non_default_constructable (hb_enumerate (hb_iter (st) + 1));
- test_iterator_non_default_constructable (hb_iter (st) | hb_filter ());
- test_iterator_non_default_constructable (hb_iter (st) | hb_map (hb_lidentity));
-
- assert (true == hb_all (st));
- assert (false == hb_all (st, 42u));
- assert (true == hb_any (st));
- assert (false == hb_any (st, 14u));
- assert (true == hb_any (st, 14u, [] (unsigned _) { return _ - 1u; }));
- assert (true == hb_any (st, [] (unsigned _) { return _ == 15u; }));
- assert (true == hb_any (st, 15u));
- assert (false == hb_none (st));
- assert (false == hb_none (st, 15u));
- assert (true == hb_none (st, 17u));
-
- hb_array_t<hb_vector_t<int>> pa;
- pa->as_array ();
-
- hb_map_t m;
-
- hb_iter (st);
- hb_iter (&st);
-
- + hb_iter (src)
- | hb_map (m)
- | hb_map (&m)
- | hb_filter ()
- | hb_filter (st)
- | hb_filter (&st)
- | hb_filter (hb_bool)
- | hb_filter (hb_bool, hb_identity)
- | hb_sink (st)
- ;
-
- + hb_iter (src)
- | hb_sink (hb_array (dst))
- ;
-
- + hb_iter (src)
- | hb_apply (&st)
- ;
-
- + hb_iter (src)
- | hb_map ([] (int i) { return 1; })
- | hb_reduce ([=] (int acc, int value) { return acc; }, 2)
- ;
-
- using map_pair_t = hb_item_type<hb_map_t>;
- + hb_iter (m)
- | hb_map ([] (map_pair_t p) { return p.first * p.second; })
- ;
-
- m.keys ();
- using map_key_t = decltype (*m.keys());
- + hb_iter (m.keys ())
- | hb_filter ([] (map_key_t k) { return k < 42; })
- | hb_drain
- ;
-
- m.values ();
- using map_value_t = decltype (*m.values());
- + hb_iter (m.values ())
- | hb_filter ([] (map_value_t k) { return k < 42; })
- | hb_drain
- ;
-
- unsigned int temp1 = 10;
- unsigned int temp2 = 0;
- hb_map_t *result =
- + hb_iter (src)
- | hb_map ([&] (int i) -> hb_set_t *
- {
- hb_set_t *set = hb_set_create ();
- for (unsigned int i = 0; i < temp1; ++i)
- hb_set_add (set, i);
- temp1++;
- return set;
- })
- | hb_reduce ([&] (hb_map_t *acc, hb_set_t *value) -> hb_map_t *
- {
- hb_map_set (acc, temp2++, hb_set_get_population (value));
- /* This is not a memory managed language, take care! */
- hb_set_destroy (value);
- return acc;
- }, hb_map_create ())
- ;
- /* The result should be something like 0->10, 1->11, ..., 9->19 */
- assert (hb_map_get (result, 9) == 19);
- hb_map_destroy (result);
-
- /* Like above, but passing hb_set_t instead of hb_set_t * */
- temp1 = 10;
- temp2 = 0;
- result =
- + hb_iter (src)
- | hb_map ([&] (int i) -> hb_set_t
- {
- hb_set_t set;
- for (unsigned int i = 0; i < temp1; ++i)
- hb_set_add (&set, i);
- temp1++;
- return set;
- })
- | hb_reduce ([&] (hb_map_t *acc, hb_set_t value) -> hb_map_t *
- {
- hb_map_set (acc, temp2++, hb_set_get_population (&value));
- return acc;
- }, hb_map_create ())
- ;
- /* The result should be something like 0->10, 1->11, ..., 9->19 */
- assert (hb_map_get (result, 9) == 19);
- hb_map_destroy (result);
-
- unsigned int temp3 = 0;
- + hb_iter(src)
- | hb_map([&] (int i) { return ++temp3; })
- | hb_reduce([&] (float acc, int value) { return acc + value; }, 0)
- ;
-
- + hb_iter (src)
- | hb_drain
- ;
-
- t << 1;
- long vl;
- s >> vl;
-
- hb_iota ();
- hb_iota (3);
- hb_iota (3, 2);
- assert ((&vl) + 1 == *++hb_iota (&vl, hb_inc));
- hb_range ();
- hb_repeat (7u);
- hb_repeat (nullptr);
- hb_repeat (vl) | hb_chop (3);
- assert (hb_len (hb_range (10) | hb_take (3)) == 3);
- assert (hb_range (9).len () == 9);
- assert (hb_range (2, 9).len () == 7);
- assert (hb_range (2, 9, 3).len () == 3);
- assert (hb_range (2, 8, 3).len () == 2);
- assert (hb_range (2, 7, 3).len () == 2);
- assert (hb_range (-2, -9, -3).len () == 3);
- 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
deleted file mode 100644
index 7fc9c24b59..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-machinery.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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
deleted file mode 100644
index da77a2f6c4..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-map.cc
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * 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 "hb-set.hh"
-#include <string>
-
-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 s {};
- s.set (1, 2);
- hb_map_t v (std::move (s));
- assert (s.get_population () == 0);
- assert (v.get_population () == 1);
- }
-
- /* Test move assignment. */
- {
- hb_map_t s {};
- s.set (1, 2);
- hb_map_t v;
- v = std::move (s);
- assert (s.get_population () == 0);
- assert (v.get_population () == 1);
- }
-
- /* Test initializing from iterable. */
- {
- hb_map_t s;
-
- s.set (1, 2);
- s.set (3, 4);
-
- hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> v (s);
- hb_map_t v0 (v);
- hb_map_t v1 (s);
- hb_map_t v2 (std::move (s));
-
- assert (s.get_population () == 0);
- assert (v0.get_population () == 2);
- assert (v1.get_population () == 2);
- assert (v2.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> m1;
- hb_hashmap_t<int, hb_bytes_t> m2;
- hb_hashmap_t<hb_bytes_t, hb_bytes_t> m3;
- assert (m1.get_population () == 0);
- assert (m2.get_population () == 0);
- assert (m3.get_population () == 0);
- }
-
- {
- hb_hashmap_t<int, int> m0;
- hb_hashmap_t<std::string, int> m1;
- hb_hashmap_t<int, std::string> m2;
- hb_hashmap_t<std::string, std::string> 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);
- }
- }
-
- /* Test hashing maps. */
- {
- using pair = hb_pair_t<hb_codepoint_t, hb_codepoint_t>;
-
- hb_hashmap_t<hb_map_t, hb_map_t> m1;
-
- m1.set (hb_map_t (), hb_map_t {});
- m1.set (hb_map_t (), hb_map_t {pair (1u, 2u)});
- m1.set (hb_map_t {pair (1u, 2u)}, hb_map_t {pair (2u, 3u)});
-
- assert (m1.get (hb_map_t ()) == hb_map_t {pair (1u, 2u)});
- assert (m1.get (hb_map_t {pair (1u, 2u)}) == hb_map_t {pair (2u, 3u)});
- }
-
- /* Test hashing sets. */
- {
- hb_hashmap_t<hb_set_t, hb_set_t> m1;
-
- m1.set (hb_set_t (), hb_set_t ());
- m1.set (hb_set_t (), hb_set_t {1});
- m1.set (hb_set_t {1, 1000}, hb_set_t {2});
-
- assert (m1.get (hb_set_t ()) == hb_set_t {1});
- assert (m1.get (hb_set_t {1000, 1}) == hb_set_t {2});
- }
-
- /* Test hashing vectors. */
- {
- using vector_t = hb_vector_t<unsigned>;
-
- hb_hashmap_t<vector_t, vector_t> m1;
-
- m1.set (vector_t (), vector_t {1});
- m1.set (vector_t {1}, vector_t {2});
-
- m1 << hb_pair_t<vector_t, vector_t> {vector_t {2}, vector_t ()};
-
- assert (m1.get (vector_t ()) == vector_t {1});
- assert (m1.get (vector_t {1}) == vector_t {2});
- }
-
- /* Test moving values */
- {
- using vector_t = hb_vector_t<unsigned>;
-
- hb_hashmap_t<vector_t, vector_t> m1;
- vector_t v {3};
- assert (v.length == 1);
- m1 << hb_pair_t<vector_t, vector_t> {vector_t {3}, v};
- assert (v.length == 1);
- m1 << hb_pair_t<vector_t, vector_t&&> {vector_t {4}, std::move (v)};
- assert (v.length == 0);
- m1 << hb_pair_t<vector_t&&, vector_t> {vector_t {4}, vector_t {5}};
- m1 << hb_pair_t<vector_t&&, vector_t&&> {vector_t {4}, vector_t {5}};
-
- hb_hashmap_t<vector_t, vector_t> m2;
- vector_t v2 {3};
- m2.set (vector_t {4}, v2);
- assert (v2.length == 1);
- m2.set (vector_t {5}, std::move (v2));
- assert (v2.length == 0);
- }
-
- /* Test hb::shared_ptr. */
- {
- hb_hashmap_t<hb::shared_ptr<hb_set_t>, hb::shared_ptr<hb_set_t>> m;
-
- m.set (hb::shared_ptr<hb_set_t> (hb_set_get_empty ()),
- hb::shared_ptr<hb_set_t> (hb_set_get_empty ()));
- m.get (hb::shared_ptr<hb_set_t> (hb_set_get_empty ()));
- m.iter ();
- m.keys ();
- m.values ();
- m.iter_ref ();
- m.keys_ref ();
- m.values_ref ();
- }
- /* Test hb::unique_ptr. */
- {
- hb_hashmap_t<hb::unique_ptr<hb_set_t>, hb::unique_ptr<hb_set_t>> m;
-
- m.set (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()),
- hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
- m.get (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
- hb::unique_ptr<hb_set_t> *v;
- m.has (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()), &v);
- m.iter_ref ();
- m.keys_ref ();
- m.values_ref ();
- }
- /* Test more complex unique_ptr's. */
- {
- hb_hashmap_t<int, hb::unique_ptr<hb_hashmap_t<int, int>>> m;
-
- m.get (0);
- const hb::unique_ptr<hb_hashmap_t<int, int>> *v1;
- m.has (0, &v1);
- hb::unique_ptr<hb_hashmap_t<int, int>> *v2;
- m.has (0, &v2);
- }
- /* Test hashmap with complex shared_ptrs as keys. */
- {
- hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> m;
-
- hb_map_t *m1 = hb_map_create ();
- hb_map_t *m2 = hb_map_create ();
- m1->set (1,3);
- m2->set (1,3);
-
- hb::shared_ptr<hb_map_t> p1 {m1};
- hb::shared_ptr<hb_map_t> p2 {m2};
- m.set (p1,1);
-
- assert (m.has (p2));
-
- m1->set (2,4);
- assert (!m.has (p2));
- }
- /* Test value type with hb_bytes_t. */
- {
- hb_hashmap_t<int, hb_bytes_t> m;
- char c_str[] = "Test";
- hb_bytes_t bytes (c_str);
-
- m.set (1, bytes);
- assert (m.has (1));
- }
- /* Test operators. */
- {
- hb_map_t m1, m2, m3;
- m1.set (1, 2);
- m1.set (2, 4);
- m2.set (1, 2);
- m2.set (2, 4);
- m3.set (1, 3);
- m3.set (3, 5);
-
- assert (m1 == m2);
- assert (m1 != m3);
- assert (!(m2 == m3));
-
- m2 = m3;
- assert (m2.has (1));
- assert (!m2.has (2));
- assert (m2.has (3));
-
- assert (m3.has (3));
- }
- /* Test reset. */
- {
- hb_hashmap_t<int, hb_set_t> m;
- m.set (1, hb_set_t {1, 2, 3});
- m.reset ();
- }
-
- return 0;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-number.cc b/src/3rdparty/harfbuzz-ng/src/test-number.cc
deleted file mode 100644
index 57835288c4..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-number.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright © 2019 Ebrahim Byagowi
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- */
-
-#include "hb.hh"
-#include "hb-number.hh"
-
-
-int
-main (int argc, char **argv)
-{
- {
- const char str[] = "123";
- const char *pp = str;
- const char *end = str + 3;
-
- int pv;
- assert (hb_parse_int (&pp, end, &pv));
- assert (pv == 123);
- assert (pp - str == 3);
- assert (end - pp == 0);
- assert (!*end);
- }
-
- {
- const char str[] = "123";
- const char *pp = str;
- const char *end = str + strlen (str);
-
- unsigned int pv;
- assert (hb_parse_uint (&pp, end, &pv));
- assert (pv == 123);
- assert (pp - str == 3);
- assert (end - pp == 0);
- assert (!*end);
- }
-
- {
- const char str[] = "12F";
- const char *pp = str;
- const char *end = str + 3;
-
- unsigned int pv;
- assert (hb_parse_uint (&pp, end, &pv, true, 16));
- assert (pv == 0x12F);
- assert (pp - str == 3);
- assert (end - pp == 0);
- assert (!*end);
- }
-
- {
- const char str[] = "12Fq";
- const char *pp = str;
- const char *end = str + 4;
-
- unsigned int pv;
- assert (!hb_parse_uint (&pp, end, &pv, true, 16));
- assert (hb_parse_uint (&pp, end, &pv, false, 16));
- assert (pv == 0x12F);
- assert (pp - str == 3);
- assert (end - pp == 1);
- assert (!*end);
- }
-
- {
- const char str[] = "-123";
- const char *pp = str;
- const char *end = str + 4;
-
- int pv;
- assert (hb_parse_int (&pp, end, &pv));
- assert (pv == -123);
- assert (pp - str == 4);
- assert (end - pp == 0);
- assert (!*end);
- }
-
- {
- const char str[] = "123";
- const char *pp = str;
- assert (ARRAY_LENGTH (str) == 4);
- const char *end = str + ARRAY_LENGTH (str);
-
- unsigned int pv;
- assert (hb_parse_uint (&pp, end, &pv));
- assert (pv == 123);
- assert (pp - str == 3);
- assert (end - pp == 1);
- }
-
- {
- const char str[] = "123\0";
- const char *pp = str;
- assert (ARRAY_LENGTH (str) == 5);
- const char *end = str + ARRAY_LENGTH (str);
-
- unsigned int pv;
- assert (hb_parse_uint (&pp, end, &pv));
- assert (pv == 123);
- assert (pp - str == 3);
- assert (end - pp == 2);
- }
-
- {
- const char str[] = "123V";
- const char *pp = str;
- assert (ARRAY_LENGTH (str) == 5);
- const char *end = str + ARRAY_LENGTH (str);
-
- unsigned int pv;
- assert (hb_parse_uint (&pp, end, &pv));
- assert (pv == 123);
- assert (pp - str == 3);
- assert (end - pp == 2);
- }
-
- {
- const char str[] = ".123";
- const char *pp = str;
- const char *end = str + ARRAY_LENGTH (str);
-
- double pv;
- assert (hb_parse_double (&pp, end, &pv));
- assert ((int) roundf (pv * 1000.) == 123);
- assert (pp - str == 4);
- assert (end - pp == 1);
- }
-
- {
- const char str[] = "0.123";
- const char *pp = str;
- const char *end = str + ARRAY_LENGTH (str) - 1;
-
- double pv;
- assert (hb_parse_double (&pp, end, &pv));
- assert ((int) roundf (pv * 1000.) == 123);
- assert (pp - str == 5);
- assert (end - pp == 0);
- }
-
- {
- const char str[] = "0.123e0";
- const char *pp = str;
- const char *end = str + ARRAY_LENGTH (str) - 1;
-
- double pv;
- assert (hb_parse_double (&pp, end, &pv));
- assert ((int) roundf (pv * 1000.) == 123);
- assert (pp - str == 7);
- assert (end - pp == 0);
- }
-
- {
- const char str[] = "123e-3";
- const char *pp = str;
- const char *end = str + ARRAY_LENGTH (str) - 1;
-
- double pv;
- assert (hb_parse_double (&pp, end, &pv));
- assert ((int) roundf (pv * 1000.) == 123);
- assert (pp - str == 6);
- assert (end - pp == 0);
- }
-
- {
- const char str[] = ".000123e+3";
- const char *pp = str;
- const char *end = str + ARRAY_LENGTH (str) - 1;
-
- double pv;
- assert (hb_parse_double (&pp, end, &pv));
- assert ((int) roundf (pv * 1000.) == 123);
- assert (pp - str == 10);
- assert (end - pp == 0);
- }
-
- {
- const char str[] = "-.000000123e6";
- const char *pp = str;
- const char *end = str + ARRAY_LENGTH (str) - 1;
-
- double pv;
- assert (hb_parse_double (&pp, end, &pv));
- assert ((int) roundf (pv * 1000.) == -123);
- assert (pp - str == 13);
- assert (end - pp == 0);
-
- }
-
- {
- const char str[] = "-1.23E-1";
- const char *pp = str;
- const char *end = str + ARRAY_LENGTH (str) - 1;
-
- double pv;
- assert (hb_parse_double (&pp, end, &pv));
- assert ((int) roundf (pv * 1000.) == -123);
- assert (pp - str == 8);
- assert (end - pp == 0);
- }
-
- return 0;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-ot-glyphname.cc b/src/3rdparty/harfbuzz-ng/src/test-ot-glyphname.cc
deleted file mode 100644
index ec6e149a56..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-ot-glyphname.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright © 2019 Adobe, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Adobe Author(s): Michiharu Ariza
- */
-
-#include "hb.hh"
-#include "hb-ot.h"
-
-#ifdef HB_NO_OPEN
-#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
-#endif
-
-int
-main (int argc, char **argv)
-{
- if (argc != 2) {
- fprintf (stderr, "usage: %s font-file\n", argv[0]);
- exit (1);
- }
-
- hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
- assert (blob);
- hb_face_t *face = hb_face_create (blob, 0 /* first face */);
- hb_font_t *font = hb_font_create (face);
- hb_blob_destroy (blob);
- blob = nullptr;
-
-
- const unsigned int num_glyphs = hb_face_get_glyph_count (face);
- int result = 1;
-
- for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
- {
- char buf[64];
- unsigned int buf_size = sizeof (buf);
- if (hb_font_get_glyph_name (font, gid, buf, buf_size))
- {
- hb_codepoint_t gid_inv;
- if (hb_font_get_glyph_from_name(font, buf, strlen (buf), &gid_inv))
- {
- if (gid == gid_inv)
- {
- printf ("%u <-> %s\n", gid, buf);
- }
- else
- {
- printf ("%u -> %s -> %u\n", gid, buf, gid_inv);
- result = 0;
- }
- }
- else
- {
- printf ("%u -> %s -> ?\n", gid, buf);
- result = 0;
- }
- }
- else
- {
- printf ("%u -> ?\n", gid);
- result = 0;
- }
- }
-
- hb_font_destroy (font);
- hb_face_destroy (face);
-
- return !result;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-ot-meta.cc b/src/3rdparty/harfbuzz-ng/src/test-ot-meta.cc
deleted file mode 100644
index 7cf69dbcc3..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-ot-meta.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright © 2019 Ebrahim Byagowi
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-#include "hb.hh"
-#include "hb-ot.h"
-
-#ifdef HB_NO_OPEN
-#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
-#endif
-
-int
-main (int argc, char **argv)
-{
- if (argc != 2) {
- fprintf (stderr, "usage: %s font-file\n", argv[0]);
- exit (1);
- }
-
- hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
- assert (blob);
- hb_face_t *face = hb_face_create (blob, 0 /* first face */);
- hb_blob_destroy (blob);
- blob = nullptr;
-
- unsigned int count = 0;
-
-#ifndef HB_NO_META
- count = hb_ot_meta_get_entry_tags (face, 0, nullptr, nullptr);
-
- hb_ot_meta_tag_t *tags = (hb_ot_meta_tag_t *)
- malloc (sizeof (hb_ot_meta_tag_t) * count);
- hb_ot_meta_get_entry_tags (face, 0, &count, tags);
- for (unsigned i = 0; i < count; ++i)
- {
- hb_blob_t *entry = hb_ot_meta_reference_entry (face, tags[i]);
- printf ("%c%c%c%c, size: %d: %.*s\n",
- HB_UNTAG (tags[i]), hb_blob_get_length (entry),
- hb_blob_get_length (entry), hb_blob_get_data (entry, nullptr));
- hb_blob_destroy (entry);
- }
- free (tags);
-#endif
-
- hb_face_destroy (face);
-
- return !count;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-ot-name.cc b/src/3rdparty/harfbuzz-ng/src/test-ot-name.cc
deleted file mode 100644
index bfa654a7c1..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-ot-name.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright © 2018 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-#include "hb-ot.h"
-
-#ifdef HB_NO_OPEN
-#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
-#endif
-
-int
-main (int argc, char **argv)
-{
- if (argc != 2) {
- fprintf (stderr, "usage: %s font-file\n", argv[0]);
- exit (1);
- }
-
- hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
- assert (blob);
- hb_face_t *face = hb_face_create (blob, 0 /* first face */);
- hb_blob_destroy (blob);
- blob = nullptr;
-
- unsigned int count = 0;
-
-#ifndef HB_NO_NAME
- const hb_ot_name_entry_t *entries = hb_ot_name_list_names (face, &count);
-
- for (unsigned int i = 0; i < count; i++)
- {
- printf ("%u %s ",
- entries[i].name_id,
- hb_language_to_string (entries[i].language));
-
- char buf[64];
- unsigned int buf_size = sizeof (buf);
- hb_ot_name_get_utf8 (face,
- entries[i].name_id,
- entries[i].language,
- &buf_size,
- buf);
-
- printf ("%s\n", buf);
- }
-#endif
-
- hb_face_destroy (face);
-
- return count ? 0 : 1;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-priority-queue.cc b/src/3rdparty/harfbuzz-ng/src/test-priority-queue.cc
deleted file mode 100644
index e83d72c7ea..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-priority-queue.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright © 2020 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger
- */
-
-#include "hb.hh"
-#include "hb-priority-queue.hh"
-
-static void
-test_insert ()
-{
- hb_priority_queue_t queue;
- assert (queue.is_empty ());
-
- queue.insert (10, 0);
- assert (!queue.is_empty ());
- assert (queue.minimum () == hb_pair (10, 0));
-
- queue.insert (20, 1);
- assert (queue.minimum () == hb_pair (10, 0));
-
- queue.insert (5, 2);
- assert (queue.minimum () == hb_pair (5, 2));
-
- queue.insert (15, 3);
- assert (queue.minimum () == hb_pair (5, 2));
-
- queue.insert (1, 4);
- assert (queue.minimum () == hb_pair (1, 4));
-}
-
-static void
-test_extract ()
-{
- hb_priority_queue_t queue;
- queue.insert (0, 0);
- queue.insert (60, 6);
- queue.insert (30, 3);
- queue.insert (40 ,4);
- queue.insert (20, 2);
- queue.insert (50, 5);
- queue.insert (70, 7);
- queue.insert (10, 1);
-
- for (int i = 0; i < 8; i++)
- {
- assert (!queue.is_empty ());
- assert (queue.minimum () == hb_pair (i * 10, i));
- assert (queue.pop_minimum () == hb_pair (i * 10, i));
- }
-
- assert (queue.is_empty ());
-}
-
-int
-main (int argc, char **argv)
-{
- test_insert ();
- test_extract ();
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-repacker.cc b/src/3rdparty/harfbuzz-ng/src/test-repacker.cc
deleted file mode 100644
index 94ff0849a6..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-repacker.cc
+++ /dev/null
@@ -1,2138 +0,0 @@
-/*
- * Copyright © 2020 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger
- */
-
-#include <string>
-
-#include "hb-repacker.hh"
-#include "hb-open-type.hh"
-#include "graph/serialize.hh"
-
-static void extend (const char* value,
- unsigned len,
- hb_serialize_context_t* c)
-{
- char* obj = c->allocate_size<char> (len);
- hb_memcpy (obj, value, len);
-}
-
-static void start_object(const char* tag,
- unsigned len,
- hb_serialize_context_t* c)
-{
- c->push ();
- extend (tag, len, c);
-}
-
-static unsigned add_object(const char* tag,
- unsigned len,
- hb_serialize_context_t* c)
-{
- start_object (tag, len, c);
- return c->pop_pack (false);
-}
-
-
-static void add_offset (unsigned id,
- hb_serialize_context_t* c)
-{
- OT::Offset16* offset = c->start_embed<OT::Offset16> ();
- c->extend_min (offset);
- c->add_link (*offset, id);
-}
-
-static void add_24_offset (unsigned id,
- hb_serialize_context_t* c)
-{
- OT::Offset24* offset = c->start_embed<OT::Offset24> ();
- c->extend_min (offset);
- 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 add_gsubgpos_header (unsigned lookup_list,
- hb_serialize_context_t* c)
-{
- char header[] = {
- 0, 1, // major
- 0, 0, // minor
- 0, 0, // script list
- 0, 0, // feature list
- };
-
- start_object (header, 8, c);
- add_offset (lookup_list, c);
- c->pop_pack (false);
-}
-
-static unsigned add_lookup_list (const unsigned* lookups,
- char count,
- hb_serialize_context_t* c)
-{
- char lookup_count[] = {0, count};
- start_object ((char *) &lookup_count, 2, c);
-
- for (int i = 0; i < count; i++)
- add_offset (lookups[i], c);
-
- return c->pop_pack (false);
-}
-
-static void start_lookup (int8_t type,
- int8_t num_subtables,
- hb_serialize_context_t* c)
-{
- char lookup[] = {
- 0, (char)type, // type
- 0, 0, // flag
- 0, (char)num_subtables, // num subtables
- };
-
- start_object (lookup, 6, c);
-}
-
-static unsigned finish_lookup (hb_serialize_context_t* c)
-{
- char filter[] = {0, 0};
- extend (filter, 2, c);
- return c->pop_pack (false);
-}
-
-static unsigned add_extension (unsigned child,
- uint8_t type,
- hb_serialize_context_t* c)
-{
- char ext[] = {
- 0, 1,
- 0, (char) type,
- };
-
- start_object (ext, 4, c);
- add_wide_offset (child, c);
-
- return c->pop_pack (false);
-
-}
-
-// Adds coverage table fro [start, end]
-static unsigned add_coverage (unsigned start, unsigned end,
- hb_serialize_context_t* c)
-{
- if (end - start == 1)
- {
- uint8_t coverage[] = {
- 0, 1, // format
- 0, 2, // count
-
- (uint8_t) ((start >> 8) & 0xFF),
- (uint8_t) (start & 0xFF), // glyph[0]
-
- (uint8_t) ((end >> 8) & 0xFF),
- (uint8_t) (end & 0xFF), // glyph[1]
- };
- return add_object ((char*) coverage, 8, c);
- }
-
- uint8_t coverage[] = {
- 0, 2, // format
- 0, 1, // range count
-
- (uint8_t) ((start >> 8) & 0xFF),
- (uint8_t) (start & 0xFF), // start
-
- (uint8_t) ((end >> 8) & 0xFF),
- (uint8_t) (end & 0xFF), // end
-
- 0, 0,
- };
- return add_object ((char*) coverage, 10, c);
-}
-
-
-template<typename It>
-static unsigned add_coverage (It it,
- hb_serialize_context_t* c)
-{
- c->push ();
- OT::Layout::Common::Coverage_serialize (c, it);
- return c->pop_pack (false);
-}
-
-// Adds a class that maps glyphs from [start_glyph, end_glyph)
-// to classes 1...n
-static unsigned add_class_def (uint16_t start_glyph,
- uint16_t end_glyph,
- hb_serialize_context_t* c)
-{
- unsigned count = end_glyph - start_glyph;
- uint8_t header[] = {
- 0, 1, // format
-
- (uint8_t) ((start_glyph >> 8) & 0xFF),
- (uint8_t) (start_glyph & 0xFF), // start_glyph
-
- (uint8_t) ((count >> 8) & 0xFF),
- (uint8_t) (count & 0xFF), // count
- };
-
- start_object ((char*) header, 6, c);
- for (uint16_t i = 1; i <= count; i++)
- {
- uint8_t class_value[] = {
- (uint8_t) ((i >> 8) & 0xFF),
- (uint8_t) (i & 0xFF), // count
- };
- extend ((char*) class_value, 2, c);
- }
-
- return c->pop_pack (false);
-}
-
-static unsigned add_pair_pos_1 (unsigned* pair_sets,
- char count,
- unsigned coverage,
- hb_serialize_context_t* c)
-{
- char format[] = {
- 0, 1
- };
-
- start_object (format, 2, c);
- add_offset (coverage, c);
-
- char value_format[] = {
- 0, 0,
- 0, 0,
- 0, count,
- };
- extend (value_format, 6, c);
-
- for (char i = 0; i < count; i++)
- add_offset (pair_sets[(unsigned) i], c);
-
- return c->pop_pack (false);
-}
-
-static unsigned add_pair_pos_2 (unsigned starting_class,
- unsigned coverage,
- unsigned class_def_1, uint16_t class_def_1_count,
- unsigned class_def_2, uint16_t class_def_2_count,
- unsigned* device_tables,
- hb_serialize_context_t* c)
-{
- uint8_t format[] = {
- 0, 2
- };
-
- start_object ((char*) format, 2, c);
- add_offset (coverage, c);
-
- unsigned num_values = 4;
- uint8_t format1 = 0x01 | 0x02 | 0x08;
- uint8_t format2 = 0x04;
- if (device_tables) {
- format2 |= 0x20;
- num_values += 1;
- }
- uint8_t value_format[] = {
- 0, format1,
- 0, format2,
- };
-
- extend ((char*) value_format, 4, c);
-
- add_offset (class_def_1, c);
- add_offset (class_def_2, c);
-
- uint8_t class_counts[] = {
- (uint8_t) ((class_def_1_count >> 8) & 0xFF),
- (uint8_t) (class_def_1_count & 0xFF),
- (uint8_t) ((class_def_2_count >> 8) & 0xFF),
- (uint8_t) (class_def_2_count & 0xFF),
- };
- extend ((char*) class_counts, 4, c);
-
- unsigned num_bytes_per_record = class_def_2_count * num_values * 2;
- uint8_t* record = (uint8_t*) calloc (1, num_bytes_per_record);
- int device_index = 0;
- for (uint16_t i = 0; i < class_def_1_count; i++)
- {
-
- for (uint16_t j = 0; j < class_def_2_count; j++)
- {
- for (int k = 0; k < 4; k++) {
- uint8_t value[] = {
- (uint8_t) (i + starting_class),
- (uint8_t) (i + starting_class),
- };
- extend ((char*) value, 2, c);
- }
-
- if (device_tables) {
- add_offset (device_tables[device_index++], c);
- }
- }
- }
- free (record);
-
- return c->pop_pack (false);
-}
-
-static unsigned add_mark_base_pos_1 (unsigned mark_coverage,
- unsigned base_coverage,
- unsigned mark_array,
- unsigned base_array,
- unsigned class_count,
- hb_serialize_context_t* c)
-{
- uint8_t format[] = {
- 0, 1
- };
-
- start_object ((char*) format, 2, c);
- add_offset (mark_coverage, c);
- add_offset (base_coverage, c);
-
- uint8_t count[] = {
- (uint8_t) ((class_count >> 8) & 0xFF),
- (uint8_t) (class_count & 0xFF),
- };
- extend ((char*) count, 2, c);
-
- add_offset (mark_array, c);
- add_offset (base_array, c);
-
- return c->pop_pack (false);
-}
-
-template<int mark_count,
- int class_count,
- int base_count,
- int table_count>
-struct MarkBasePosBuffers
-{
- unsigned base_anchors[class_count * base_count];
- unsigned mark_anchors[mark_count];
- uint8_t anchor_buffers[class_count * base_count + 100];
- uint8_t class_buffer[class_count * 2];
-
- MarkBasePosBuffers(hb_serialize_context_t* c)
- {
- for (unsigned i = 0; i < sizeof(anchor_buffers) / 2; i++)
- {
- OT::HBUINT16* value = (OT::HBUINT16*) (&anchor_buffers[2*i]);
- *value = i;
- }
-
- for (unsigned i = 0; i < class_count * base_count; i++)
- {
- base_anchors[i] = add_object ((char*) &anchor_buffers[i], 100, c);
- if (i < class_count) {
- class_buffer[i*2] = (uint8_t) ((i >> 8) & 0xFF);
- class_buffer[i*2 + 1] = (uint8_t) (i & 0xFF);
- }
- }
-
- for (unsigned i = 0; i < mark_count; i++)
- {
- mark_anchors[i] = add_object ((char*) &anchor_buffers[i], 4, c);
- }
- }
-
- unsigned create_mark_base_pos_1 (unsigned table_index, hb_serialize_context_t* c)
- {
- unsigned class_per_table = class_count / table_count;
- unsigned mark_per_class = mark_count / class_count;
- unsigned start_class = class_per_table * table_index;
- unsigned end_class = class_per_table * (table_index + 1) - 1;
-
- // baseArray
- uint8_t base_count_buffer[] = {
- (uint8_t) ((base_count >> 8) & 0xFF),
- (uint8_t) (base_count & 0xFF),
-
- };
- start_object ((char*) base_count_buffer, 2, c);
- for (unsigned base = 0; base < base_count; base++)
- {
- for (unsigned klass = start_class; klass <= end_class; klass++)
- {
- unsigned i = base * class_count + klass;
- add_offset (base_anchors[i], c);
- }
- }
- unsigned base_array = c->pop_pack (false);
-
- // markArray
- unsigned num_marks = class_per_table * mark_per_class;
- uint8_t mark_count_buffer[] = {
- (uint8_t) ((num_marks >> 8) & 0xFF),
- (uint8_t) (num_marks & 0xFF),
- };
- start_object ((char*) mark_count_buffer, 2, c);
- for (unsigned mark = 0; mark < mark_count; mark++)
- {
- unsigned klass = mark % class_count;
- if (klass < start_class || klass > end_class) continue;
- klass -= start_class;
-
- extend ((char*) &class_buffer[2 * klass], 2, c);
- add_offset (mark_anchors[mark], c);
- }
- unsigned mark_array = c->pop_pack (false);
-
- // markCoverage
- auto it =
- + hb_range ((hb_codepoint_t) mark_count)
- | hb_filter ([&] (hb_codepoint_t mark) {
- unsigned klass = mark % class_count;
- return klass >= class_per_table * table_index &&
- klass < class_per_table * (table_index + 1);
- })
- ;
- unsigned mark_coverage = add_coverage (it, c);
-
- // baseCoverage
- unsigned base_coverage = add_coverage (10, 10 + base_count - 1, c);
-
- return add_mark_base_pos_1 (mark_coverage,
- base_coverage,
- mark_array,
- base_array,
- class_per_table,
- c);
- }
-};
-
-
-
-
-
-static void run_resolve_overflow_test (const char* name,
- hb_serialize_context_t& overflowing,
- hb_serialize_context_t& expected,
- unsigned num_iterations = 0,
- bool recalculate_extensions = false,
- hb_tag_t tag = HB_TAG ('G', 'S', 'U', 'B'))
-{
- printf (">>> Testing overflowing resolution for %s\n",
- name);
-
- graph_t graph (overflowing.object_graph ());
- graph_t expected_graph (expected.object_graph ());
- if (graph::will_overflow (expected_graph))
- {
- expected_graph.assign_spaces ();
- expected_graph.sort_shortest_distance ();
- }
-
- // Check that overflow resolution succeeds
- assert (overflowing.offset_overflow ());
- assert (hb_resolve_graph_overflows (tag,
- num_iterations,
- recalculate_extensions,
- graph));
-
- // Check the graphs can be serialized.
- hb_blob_t* out = graph::serialize (graph);
- assert (out);
- hb_blob_destroy (out);
- out = graph::serialize (expected_graph);
- assert (out);
- hb_blob_destroy (out);
-
- // Check the graphs are equivalent
- graph.normalize ();
- expected_graph.normalize ();
- assert (graph == expected_graph);
-}
-
-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)
-{
- c->start_serialize<char> ();
-
- unsigned obj_1 = add_object ("ghi", 3, c);
- unsigned obj_2 = add_object ("def", 3, c);
-
- start_object ("abc", 3, c);
- add_offset (obj_2, c);
- add_offset (obj_1, c);
- c->pop_pack (false);
-
- c->end_serialize();
-}
-
-static void
-populate_serializer_with_overflow (hb_serialize_context_t* c)
-{
- std::string large_string(50000, 'a');
- c->start_serialize<char> ();
-
- unsigned obj_1 = add_object (large_string.c_str(), 10000, c);
- unsigned obj_2 = add_object (large_string.c_str(), 20000, c);
- unsigned obj_3 = add_object (large_string.c_str(), 50000, c);
-
- start_object ("abc", 3, c);
- add_offset (obj_3, c);
- add_offset (obj_2, c);
- add_offset (obj_1, c);
- 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');
- c->start_serialize<char> ();
-
- unsigned obj_1 = add_object ("def", 3, c);
-
- start_object (large_string.c_str(), 60000, c);
- add_offset (obj_1, c);
- unsigned obj_2 = c->pop_pack (false);
-
- start_object (large_string.c_str(), 10000, c);
- add_offset (obj_2, c);
- add_offset (obj_1, c);
- c->pop_pack (false);
-
- c->end_serialize();
-}
-
-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_2 (hb_serialize_context_t* c)
-{
- c->start_serialize<char> ();
-
- unsigned obj_5 = add_object ("mn", 2, c);
-
- unsigned obj_4 = add_object ("jkl", 3, c);
-
- start_object ("ghi", 3, c);
- add_offset (obj_4, c);
- unsigned obj_3 = c->pop_pack (false);
-
- start_object ("def", 3, c);
- add_offset (obj_3, c);
- unsigned obj_2 = c->pop_pack (false);
-
- start_object ("abc", 3, c);
- add_offset (obj_2, c);
- add_offset (obj_4, c);
- add_offset (obj_5, c);
- c->pop_pack (false);
-
- c->end_serialize();
-}
-
-static void
-populate_serializer_complex_3 (hb_serialize_context_t* c)
-{
- c->start_serialize<char> ();
-
- unsigned obj_6 = add_object ("opqrst", 6, c);
-
- unsigned obj_5 = add_object ("mn", 2, c);
-
- start_object ("jkl", 3, c);
- add_offset (obj_6, c);
- unsigned obj_4 = c->pop_pack (false);
-
- start_object ("ghi", 3, c);
- add_offset (obj_4, c);
- unsigned obj_3 = c->pop_pack (false);
-
- start_object ("def", 3, c);
- add_offset (obj_3, c);
- unsigned obj_2 = c->pop_pack (false);
-
- start_object ("abc", 3, c);
- add_offset (obj_2, c);
- add_offset (obj_4, c);
- add_offset (obj_5, c);
- 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();
-}
-
-static void
-populate_serializer_with_24_and_32_bit_offsets (hb_serialize_context_t* c)
-{
- std::string large_string(60000, 'a');
- c->start_serialize<char> ();
-
- unsigned obj_f = add_object ("f", 1, c);
- unsigned obj_g = add_object ("g", 1, c);
- unsigned obj_j = add_object ("j", 1, c);
- unsigned obj_k = add_object ("k", 1, c);
-
- start_object (large_string.c_str (), 40000, c);
- add_offset (obj_f, c);
- unsigned obj_c = c->pop_pack (false);
-
- start_object (large_string.c_str (), 40000, c);
- add_offset (obj_g, c);
- unsigned obj_d = c->pop_pack (false);
-
- start_object (large_string.c_str (), 40000, c);
- add_offset (obj_j, c);
- unsigned obj_h = c->pop_pack (false);
-
- start_object (large_string.c_str (), 40000, c);
- add_offset (obj_k, c);
- unsigned obj_i = c->pop_pack (false);
-
- start_object ("e", 1, c);
- add_wide_offset (obj_h, c);
- add_wide_offset (obj_i, c);
- unsigned obj_e = c->pop_pack (false);
-
- start_object ("b", 1, c);
- add_24_offset (obj_c, c);
- add_24_offset (obj_d, c);
- add_24_offset (obj_e, c);
- unsigned obj_b = c->pop_pack (false);
-
- start_object ("a", 1, c);
- add_24_offset (obj_b, c);
- c->pop_pack (false);
-
- c->end_serialize();
-}
-
-static void
-populate_serializer_with_extension_promotion (hb_serialize_context_t* c,
- int num_extensions = 0)
-{
- constexpr int num_lookups = 5;
- constexpr int num_subtables = num_lookups * 2;
- unsigned int lookups[num_lookups];
- unsigned int subtables[num_subtables];
- unsigned int extensions[num_subtables];
-
- std::string large_string(60000, 'a');
- c->start_serialize<char> ();
-
-
- for (int i = num_subtables - 1; i >= 0; i--)
- subtables[i] = add_object(large_string.c_str (), 15000, c);
-
- for (int i = num_subtables - 1;
- i >= (num_lookups - num_extensions) * 2;
- i--)
- {
- unsigned ext_index = i - (num_lookups - num_extensions) * 2;
- unsigned subtable_index = num_subtables - ext_index - 1;
- extensions[i] = add_extension (subtables[subtable_index], 5, c);
- }
-
- for (int i = num_lookups - 1; i >= 0; i--)
- {
- bool is_ext = (i >= (num_lookups - num_extensions));
-
- start_lookup (is_ext ? (char) 7 : (char) 5,
- 2,
- c);
-
- if (is_ext) {
- add_offset (extensions[i * 2], c);
- add_offset (extensions[i * 2 + 1], c);
- } else {
- add_offset (subtables[i * 2], c);
- add_offset (subtables[i * 2 + 1], c);
- }
-
- lookups[i] = finish_lookup (c);
- }
-
- unsigned lookup_list = add_lookup_list (lookups, num_lookups, c);
-
- add_gsubgpos_header (lookup_list, c);
-
- c->end_serialize();
-}
-
-template<int num_pair_pos_1, int num_pair_set>
-static void
-populate_serializer_with_large_pair_pos_1 (hb_serialize_context_t* c,
- bool as_extension = false)
-{
- std::string large_string(60000, 'a');
- c->start_serialize<char> ();
-
- constexpr int total_pair_set = num_pair_pos_1 * num_pair_set;
- unsigned pair_set[total_pair_set];
- unsigned coverage[num_pair_pos_1];
- unsigned pair_pos_1[num_pair_pos_1];
-
- for (int i = num_pair_pos_1 - 1; i >= 0; i--)
- {
- for (int j = (i + 1) * num_pair_set - 1; j >= i * num_pair_set; j--)
- pair_set[j] = add_object (large_string.c_str (), 30000 + j, c);
-
- coverage[i] = add_coverage (i * num_pair_set,
- (i + 1) * num_pair_set - 1, c);
-
- pair_pos_1[i] = add_pair_pos_1 (&pair_set[i * num_pair_set],
- num_pair_set,
- coverage[i],
- c);
- }
-
- unsigned pair_pos_2 = add_object (large_string.c_str(), 200, c);
-
- if (as_extension) {
- pair_pos_2 = add_extension (pair_pos_2, 2, c);
- for (int i = num_pair_pos_1 - 1; i >= 0; i--)
- pair_pos_1[i] = add_extension (pair_pos_1[i], 2, c);
- }
-
- start_lookup (as_extension ? 9 : 2, 1 + num_pair_pos_1, c);
-
- for (int i = 0; i < num_pair_pos_1; i++)
- add_offset (pair_pos_1[i], c);
- add_offset (pair_pos_2, c);
-
- unsigned lookup = finish_lookup (c);
-
- unsigned lookup_list = add_lookup_list (&lookup, 1, c);
-
- add_gsubgpos_header (lookup_list, c);
-
- c->end_serialize();
-}
-
-template<int num_pair_pos_2, int num_class_1, int num_class_2>
-static void
-populate_serializer_with_large_pair_pos_2 (hb_serialize_context_t* c,
- bool as_extension = false,
- bool with_device_tables = false,
- bool extra_table = true)
-{
- std::string large_string(100000, 'a');
- c->start_serialize<char> ();
-
- unsigned coverage[num_pair_pos_2];
- unsigned class_def_1[num_pair_pos_2];
- unsigned class_def_2[num_pair_pos_2];
- unsigned pair_pos_2[num_pair_pos_2];
-
- unsigned* device_tables = (unsigned*) calloc (num_pair_pos_2 * num_class_1 * num_class_2,
- sizeof(unsigned));
-
- // Total glyphs = num_class_1 * num_pair_pos_2
- for (int i = num_pair_pos_2 - 1; i >= 0; i--)
- {
- unsigned start_glyph = 5 + i * num_class_1;
- if (num_class_2 >= num_class_1)
- {
- class_def_2[i] = add_class_def (11,
- 10 + num_class_2, c);
- class_def_1[i] = add_class_def (start_glyph + 1,
- start_glyph + num_class_1,
- c);
- } else {
- class_def_1[i] = add_class_def (start_glyph + 1,
- start_glyph + num_class_1,
- c);
- class_def_2[i] = add_class_def (11,
- 10 + num_class_2, c);
- }
-
- coverage[i] = add_coverage (start_glyph,
- start_glyph + num_class_1 - 1,
- c);
-
- if (with_device_tables)
- {
- for(int j = (i + 1) * num_class_1 * num_class_2 - 1;
- j >= i * num_class_1 * num_class_2;
- j--)
- {
- uint8_t table[] = {
- (uint8_t) ((j >> 8) & 0xFF),
- (uint8_t) (j & 0xFF),
- };
- device_tables[j] = add_object ((char*) table, 2, c);
- }
- }
-
- pair_pos_2[i] = add_pair_pos_2 (1 + i * num_class_1,
- coverage[i],
- class_def_1[i], num_class_1,
- class_def_2[i], num_class_2,
- with_device_tables
- ? &device_tables[i * num_class_1 * num_class_2]
- : nullptr,
- c);
- }
-
-
- unsigned pair_pos_1 = 0;
- if (extra_table) pair_pos_1 = add_object (large_string.c_str(), 100000, c);
-
- if (as_extension) {
- for (int i = num_pair_pos_2 - 1; i >= 0; i--)
- pair_pos_2[i] = add_extension (pair_pos_2[i], 2, c);
-
- if (extra_table)
- pair_pos_1 = add_extension (pair_pos_1, 2, c);
- }
-
- start_lookup (as_extension ? 9 : 2, 1 + num_pair_pos_2, c);
-
- if (extra_table)
- add_offset (pair_pos_1, c);
-
- for (int i = 0; i < num_pair_pos_2; i++)
- add_offset (pair_pos_2[i], c);
-
- unsigned lookup = finish_lookup (c);
-
- unsigned lookup_list = add_lookup_list (&lookup, 1, c);
-
- add_gsubgpos_header (lookup_list, c);
-
- c->end_serialize();
-
- free (device_tables);
-}
-
-template<int mark_count,
- int class_count,
- int base_count,
- int table_count>
-static void
-populate_serializer_with_large_mark_base_pos_1 (hb_serialize_context_t* c)
-{
- c->start_serialize<char> ();
-
- MarkBasePosBuffers<mark_count, class_count, base_count, table_count> buffers (c);
-
- unsigned mark_base_pos[table_count];
- for (unsigned i = 0; i < table_count; i++)
- mark_base_pos[i] = buffers.create_mark_base_pos_1 (i, c);
-
- for (int i = 0; i < table_count; i++)
- mark_base_pos[i] = add_extension (mark_base_pos[i], 4, c);
-
- start_lookup (9, table_count, c);
-
- for (int i = 0; i < table_count; i++)
- add_offset (mark_base_pos[i], c);
-
- unsigned lookup = finish_lookup (c);
-
- unsigned lookup_list = add_lookup_list (&lookup, 1, c);
-
- add_gsubgpos_header (lookup_list, c);
-
- c->end_serialize();
-}
-
-static void test_sort_shortest ()
-{
- size_t buffer_size = 100;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_complex_2 (&c);
-
- graph_t graph (c.object_graph ());
- graph.sort_shortest_distance ();
- assert (!graph.in_error ());
-
- assert(strncmp (graph.object (4).head, "abc", 3) == 0);
- 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).real_links.length == 0);
-
- assert(strncmp (graph.object (2).head, "def", 3) == 0);
- 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).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).real_links.length == 0);
-
- free (buffer);
-}
-
-static void test_duplicate_leaf ()
-{
- size_t buffer_size = 100;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_complex_2 (&c);
-
- graph_t graph (c.object_graph ());
- graph.duplicate (4, 1);
-
- assert(strncmp (graph.object (5).head, "abc", 3) == 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).real_links.length == 0);
-
- assert(strncmp (graph.object (3).head, "def", 3) == 0);
- 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).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).real_links.length == 0);
-
- assert(strncmp (graph.object (0).head, "mn", 2) == 0);
- assert(graph.object (0).real_links.length == 0);
-
- free (buffer);
-}
-
-static void test_duplicate_interior ()
-{
- size_t buffer_size = 100;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_complex_3 (&c);
-
- graph_t graph (c.object_graph ());
- graph.duplicate (3, 2);
-
- assert(strncmp (graph.object (6).head, "abc", 3) == 0);
- 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).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).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).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).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).real_links.length == 0);
-
- assert(strncmp (graph.object (0).head, "opqrst", 6) == 0);
- assert(graph.object (0).real_links.length == 0);
-
- free (buffer);
-}
-
-static void
-test_serialize ()
-{
- size_t buffer_size = 100;
- void* buffer_1 = malloc (buffer_size);
- hb_serialize_context_t c1 (buffer_1, buffer_size);
- populate_serializer_simple (&c1);
- hb_bytes_t expected = c1.copy_bytes ();
-
- graph_t graph (c1.object_graph ());
- hb_blob_t* out = graph::serialize (graph);
- free (buffer_1);
-
- hb_bytes_t actual = out->as_bytes ();
- assert (actual == expected);
- expected.fini ();
- hb_blob_destroy (out);
-}
-
-static void test_will_overflow_1 ()
-{
- size_t buffer_size = 100;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_complex_2 (&c);
- graph_t graph (c.object_graph ());
-
- assert (!graph::will_overflow (graph, nullptr));
-
- free (buffer);
-}
-
-static void test_will_overflow_2 ()
-{
- size_t buffer_size = 160000;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_overflow (&c);
- graph_t graph (c.object_graph ());
-
- assert (graph::will_overflow (graph, nullptr));
-
- free (buffer);
-}
-
-static void test_will_overflow_3 ()
-{
- size_t buffer_size = 160000;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_dedup_overflow (&c);
- graph_t graph (c.object_graph ());
-
- assert (graph::will_overflow (graph, nullptr));
-
- free (buffer);
-}
-
-static void test_resolve_overflows_via_sort ()
-{
- size_t buffer_size = 160000;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_overflow (&c);
- graph_t graph (c.object_graph ());
-
- 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));
-
- free (buffer);
- hb_blob_destroy (out);
-}
-
-static void test_resolve_overflows_via_duplication ()
-{
- size_t buffer_size = 160000;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_dedup_overflow (&c);
- graph_t graph (c.object_graph ());
-
- 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));
-
- free (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_mixed_overflows_via_isolation_spaces ()
-{
- size_t buffer_size = 200000;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_24_and_32_bit_offsets (&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 =
- // Objects
- 7 +
- 4 * 40000;
-
- expected_length +=
- // Links
- 2 * 4 + // 32
- 4 * 3 + // 24
- 4 * 2; // 16
-
- assert (result.length == expected_length);
-
- free (buffer);
- hb_blob_destroy (out);
-}
-
-static void test_resolve_with_extension_promotion ()
-{
- size_t buffer_size = 200000;
- void* buffer = malloc (buffer_size);
- assert (buffer);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_extension_promotion (&c);
-
- void* expected_buffer = malloc (buffer_size);
- assert (expected_buffer);
- hb_serialize_context_t e (expected_buffer, buffer_size);
- populate_serializer_with_extension_promotion (&e, 3);
-
- run_resolve_overflow_test ("test_resolve_with_extension_promotion",
- c,
- e,
- 20,
- true);
- free (buffer);
- free (expected_buffer);
-}
-
-static void test_resolve_with_basic_pair_pos_1_split ()
-{
- size_t buffer_size = 200000;
- void* buffer = malloc (buffer_size);
- assert (buffer);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_large_pair_pos_1 <1, 4>(&c);
-
- void* expected_buffer = malloc (buffer_size);
- assert (expected_buffer);
- hb_serialize_context_t e (expected_buffer, buffer_size);
- populate_serializer_with_large_pair_pos_1 <2, 2>(&e, true);
-
- run_resolve_overflow_test ("test_resolve_with_basic_pair_pos_1_split",
- c,
- e,
- 20,
- true,
- HB_TAG('G', 'P', 'O', 'S'));
- free (buffer);
- free (expected_buffer);
-}
-
-static void test_resolve_with_extension_pair_pos_1_split ()
-{
- size_t buffer_size = 200000;
- void* buffer = malloc (buffer_size);
- assert (buffer);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_large_pair_pos_1 <1, 4>(&c, true);
-
- void* expected_buffer = malloc (buffer_size);
- assert (expected_buffer);
- hb_serialize_context_t e (expected_buffer, buffer_size);
- populate_serializer_with_large_pair_pos_1 <2, 2>(&e, true);
-
- run_resolve_overflow_test ("test_resolve_with_extension_pair_pos_1_split",
- c,
- e,
- 20,
- true,
- HB_TAG('G', 'P', 'O', 'S'));
- free (buffer);
- free (expected_buffer);
-}
-
-static void test_resolve_with_basic_pair_pos_2_split ()
-{
- size_t buffer_size = 300000;
- void* buffer = malloc (buffer_size);
- assert (buffer);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_large_pair_pos_2 <1, 4, 3000>(&c);
-
- void* expected_buffer = malloc (buffer_size);
- assert (expected_buffer);
- hb_serialize_context_t e (expected_buffer, buffer_size);
- populate_serializer_with_large_pair_pos_2 <2, 2, 3000>(&e, true);
-
- run_resolve_overflow_test ("test_resolve_with_basic_pair_pos_2_split",
- c,
- e,
- 20,
- true,
- HB_TAG('G', 'P', 'O', 'S'));
- free (buffer);
- free (expected_buffer);
-}
-
-static void test_resolve_with_close_to_limit_pair_pos_2_split ()
-{
- size_t buffer_size = 300000;
- void* buffer = malloc (buffer_size);
- assert (buffer);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_large_pair_pos_2 <1, 1596, 10>(&c, true, false, false);
-
- void* expected_buffer = malloc (buffer_size);
- assert (expected_buffer);
- hb_serialize_context_t e (expected_buffer, buffer_size);
- populate_serializer_with_large_pair_pos_2 <2, 798, 10>(&e, true, false, false);
-
- run_resolve_overflow_test ("test_resolve_with_close_to_limit_pair_pos_2_split",
- c,
- e,
- 20,
- true,
- HB_TAG('G', 'P', 'O', 'S'));
- free (buffer);
- free (expected_buffer);
-}
-
-static void test_resolve_with_pair_pos_2_split_with_device_tables ()
-{
- size_t buffer_size = 300000;
- void* buffer = malloc (buffer_size);
- assert (buffer);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_large_pair_pos_2 <1, 4, 2000>(&c, false, true);
-
- void* expected_buffer = malloc (buffer_size);
- assert (expected_buffer);
- hb_serialize_context_t e (expected_buffer, buffer_size);
- populate_serializer_with_large_pair_pos_2 <2, 2, 2000>(&e, true, true);
-
- run_resolve_overflow_test ("test_resolve_with_pair_pos_2_split_with_device_tables",
- c,
- e,
- 20,
- true,
- HB_TAG('G', 'P', 'O', 'S'));
- free (buffer);
- free (expected_buffer);
-}
-
-static void test_resolve_with_basic_mark_base_pos_1_split ()
-{
- size_t buffer_size = 200000;
- void* buffer = malloc (buffer_size);
- assert (buffer);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_with_large_mark_base_pos_1 <40, 10, 110, 1>(&c);
-
- void* expected_buffer = malloc (buffer_size);
- assert (expected_buffer);
- hb_serialize_context_t e (expected_buffer, buffer_size);
- populate_serializer_with_large_mark_base_pos_1 <40, 10, 110, 2>(&e);
-
- run_resolve_overflow_test ("test_resolve_with_basic_mark_base_pos_1_split",
- c,
- e,
- 20,
- true,
- HB_TAG('G', 'P', 'O', 'S'));
- free (buffer);
- free (expected_buffer);
-}
-
-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 tests for priority raising.
-
-int
-main (int argc, char **argv)
-{
- test_serialize ();
- test_sort_shortest ();
- test_will_overflow_1 ();
- test_will_overflow_2 ();
- 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_resolve_mixed_overflows_via_isolation_spaces ();
- test_duplicate_leaf ();
- test_duplicate_interior ();
- test_virtual_link ();
- test_shared_node_with_virtual_links ();
- test_resolve_with_extension_promotion ();
- test_resolve_with_basic_pair_pos_1_split ();
- test_resolve_with_extension_pair_pos_1_split ();
- test_resolve_with_basic_pair_pos_2_split ();
- test_resolve_with_pair_pos_2_split_with_device_tables ();
- test_resolve_with_close_to_limit_pair_pos_2_split ();
- test_resolve_with_basic_mark_base_pos_1_split ();
-
- // TODO(grieger): have run overflow tests compare graph equality not final packed binary.
- // TODO(grieger): split test where multiple subtables in one lookup are split to test link ordering.
- // TODO(grieger): split test where coverage table in subtable that is being split is shared.
- // TODO(grieger): test with extensions already mixed in as well.
- // TODO(grieger): test two layer ext promotion setup.
- // TODO(grieger): test sorting by subtables per byte in ext. promotion.
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-serialize.cc b/src/3rdparty/harfbuzz-ng/src/test-serialize.cc
deleted file mode 100644
index 4c90abb114..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-serialize.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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"
-
-using OT::Layout::Common::Coverage;
-
-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<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
deleted file mode 100644
index e760c98f82..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-set.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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 (hb_len (hb_iter (v1)) == 2);
- assert (v2.get_population () == 2);
- }
-
- /* Test copy assignment. */
- {
- hb_set_t v1 {1, 2};
- hb_set_t v2;
- v2 = v1;
- assert (v1.get_population () == 2);
- assert (v2.get_population () == 2);
- }
-
- /* Test move constructor. */
- {
- hb_set_t s {1, 2};
- hb_set_t v (std::move (s));
- assert (s.get_population () == 0);
- assert (hb_len (hb_iter (s)) == 0);
- assert (v.get_population () == 2);
- }
-
- /* Test move assignment. */
- {
- hb_set_t s = hb_set_t {1, 2};
- hb_set_t v;
- v = std::move (s);
- assert (s.get_population () == 0);
- assert (v.get_population () == 2);
- }
-
- /* Test initializing from iterable. */
- {
- hb_set_t s;
-
- s.add (18);
- s.add (12);
-
- hb_vector_t<hb_codepoint_t> v (s);
- hb_set_t v0 (v);
- hb_set_t v1 (s);
- hb_set_t v2 (std::move (s));
-
- assert (s.get_population () == 0);
- assert (v0.get_population () == 2);
- assert (v1.get_population () == 2);
- assert (v2.get_population () == 2);
- }
-
- /* Test initializing from iterator. */
- {
- hb_set_t s;
-
- s.add (18);
- s << 12;
-
- /* Sink a range. */
- s << hb_pair_t<hb_codepoint_t, hb_codepoint_t> {1, 3};
-
- hb_set_t v (hb_iter (s));
-
- assert (v.get_population () == 5);
- }
-
- /* 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
deleted file mode 100644
index 65e51c6572..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-vector.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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 "hb-map.hh"
-#include <string>
-
-
-int
-main (int argc, char **argv)
-{
- assert (sizeof (hb_vector_t<int>) == sizeof (hb_sorted_vector_t<int>));
-
- /* 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> s {1, 2};
- hb_sorted_vector_t<int> S {1, 2};
- hb_vector_t<int> v (std::move (s));
- hb_sorted_vector_t<int> V (std::move (S));
- assert (s.length == 0);
- assert (S.length == 0);
- assert (v.length == 2);
- assert (v[0] == 1);
- assert (v[1] == 2);
- }
-
- /* Test move assignment. */
- {
- hb_vector_t<int> s {1, 2};
- hb_sorted_vector_t<int> S {1, 2};
- hb_vector_t<int> v;
- hb_sorted_vector_t<int> V;
- v = std::move (s);
- V = std::move (S);
- assert (s.length == 0);
- assert (S.length == 0);
- assert (v.length == 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);
- }
-
- {
- hb_vector_t<std::string> v;
-
- std::string s;
- for (unsigned i = 1; i < 100; i++)
- {
- s += "x";
- v.push (s);
- }
-
- hb_vector_t<std::string> v2;
-
- v2 = v;
-
- v2.remove_ordered (50);
- v2.remove_unordered (50);
- }
-
- {
- hb_vector_t<hb_set_t> v;
- hb_set_t s {1, 5, 7};
- v.push (s);
- v << s;
- assert (s.get_population () == 3);
- v << std::move (s);
- assert (s.get_population () == 0);
- }
-
- {
- hb_vector_t<hb_map_t> v;
- hb_map_t m;
- v.push (m);
- }
-
- return 0;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test.cc b/src/3rdparty/harfbuzz-ng/src/test.cc
index d848cf1062..f7e4e7ecde 100644
--- a/src/3rdparty/harfbuzz-ng/src/test.cc
+++ b/src/3rdparty/harfbuzz-ng/src/test.cc
@@ -75,7 +75,7 @@ main (int argc, char **argv)
hb_glyph_info_t *info = &infos[i];
hb_glyph_position_t *pos = &positions[i];
- printf ("cluster %d glyph 0x%x at (%d,%d)+(%d,%d)\n",
+ printf ("cluster %u glyph 0x%x at (%d,%d)+(%d,%d)\n",
info->cluster,
info->codepoint,
pos->x_offset,