summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2023-02-27 12:11:51 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-03-02 05:21:49 +0000
commit7f8020f1f7177d8f3a626e0b746f07dd7727b7e6 (patch)
tree8cdf4986c75789e01b7538a16d47e5452d439732
parent474e2c9208a9cc7398b1882dd73b4034da6d44b6 (diff)
downloadqtbase-7f8020f1f7177d8f3a626e0b746f07dd7727b7e6.tar.gz
Update Harfbuzz to 7.0.1
This is the 6.4-specific update of Harfbuzz, since Harfbuzz was currently on an older version in 6.4 compared to other branches. This also backports the change to the qtextlayout test that was done on other branches for the 6.0.0 update. Fixes: QTBUG-111535 Change-Id: Ie8217f1541a02d3800142b88cf0007be0ed0d1e2 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit 13549fa7c2d27ba588471f97a640f4dbcf86b10c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/3rdparty/harfbuzz-ng/CMakeLists.txt80
-rw-r--r--src/3rdparty/harfbuzz-ng/COPYING20
-rw-r--r--src/3rdparty/harfbuzz-ng/NEWS366
-rw-r--r--src/3rdparty/harfbuzz-ng/README.md74
-rw-r--r--src/3rdparty/harfbuzz-ng/import_from_tarball.sh14
-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)85
-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)764
-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)79
-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)75
-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.hh337
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh133
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh232
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh85
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh918
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Anchor.hh83
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat1.hh46
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat2.hh58
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh100
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh77
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ChainContextPos.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Common.hh33
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ContextPos.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh35
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh301
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ExtensionPos.hh17
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh171
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh56
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh128
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh41
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh244
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh41
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh223
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh42
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh228
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh52
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh46
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh217
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh351
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh207
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh99
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookup.hh79
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookupSubTable.hh79
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh100
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh156
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh176
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh394
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh22
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh19
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh16
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ExtensionSubst.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/GSUB.hh21
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh62
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh15
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh20
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh23
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh25
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubstFormat1.hh42
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh40
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh66
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh42
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh88
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh49
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookup.hh36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookupSubTable.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/Layout/types.hh66
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh369
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh537
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/GlyphHeader.hh52
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh339
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh85
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh354
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/composite-iter.hh68
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh34
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh104
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh474
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/loca.hh43
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh174
-rw-r--r--src/3rdparty/harfbuzz-ng/src/OT/name/name.hh589
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh216
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh152
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/graph.hh1392
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc (renamed from src/3rdparty/harfbuzz-ng/src/test-array.cc)72
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh (renamed from src/3rdparty/harfbuzz-ng/src/test-unicode-ranges.cc)61
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh414
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh510
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh647
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/serialize.hh270
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/split-helpers.hh69
-rw-r--r--src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc119
-rw-r--r--src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc62
-rw-r--r--src/3rdparty/harfbuzz-ng/src/harfbuzz.cc40
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh125
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-feat-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh32
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-kerx-table.hh20
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-morx-table.hh76
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-opbd-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc23
-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.hh51
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-algs.hh182
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-array.hh131
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-atomic.hh61
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bimap.hh15
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh113
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh22
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh161
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-blob.cc26
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-blob.h2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-blob.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh455
-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.hh853
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc57
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc37
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.cc255
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.h65
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-buffer.hh143
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cache.hh33
-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.hh197
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh23
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff-interp-dict-common.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff1-interp-cs.hh9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh110
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-common.cc102
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-common.h37
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-config.hh34
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-coretext.cc70
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-cplusplus.hh223
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-debug.hh21
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-deprecated.h5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc55
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-draw.cc171
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-draw.h35
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-draw.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-face-builder.cc246
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-face.cc211
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-face.h10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-face.hh6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.cc642
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.h171
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-font.hh205
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh567
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ft.cc584
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ft.h9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-glib.cc77
-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.cc10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-graphite2.h3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-iter.hh46
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-limits.hh109
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-machinery.hh53
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-map.cc148
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-map.h31
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-map.hh361
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-meta.hh28
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ms-feature-ranges.hh5
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-multimap.hh92
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-mutex.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-null.hh35
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-number-parser.hh8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-number.cc1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-object.hh73
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-open-file.hh4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-open-type.hh154
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh278
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc64
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh186
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc57
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh46
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh437
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc67
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-color.h13
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-deprecated.h18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-face-table-list.hh28
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-face.cc6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc360
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh1328
-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.hh179
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh2454
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh692
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh3103
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh24
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh1692
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc437
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h20
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc98
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh36
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh18
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh13
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-meta-table.hh2
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name-language-static.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh350
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc51
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-name.h22
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh127
-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-v2subset.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh37
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh603
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc501
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.hh431
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer-machine.hh396
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.hh115
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh492
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.hh177
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh849
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.hh1570
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc13
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc112
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh12
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh)101
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-joining-list.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-joining-list.hh)14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-pua.hh118
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-table.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh)149
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-win1256.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh)8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc)95
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.hh)8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-default.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-default.cc)16
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-hangul.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc)10
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-hebrew.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc)38
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh627
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-table.cc561
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc)431
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.hh (renamed from src/3rdparty/harfbuzz-ng/src/test-serialize.cc)49
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh428
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc)50
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh553
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc)128
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.cc)41
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.hh)15
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-thai.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc)26
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh1080
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-table.hh674
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc)55
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-vowel-constraints.cc (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.cc)42
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-vowel-constraints.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.hh)8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-shaper.hh (renamed from src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex.hh)107
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh276
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh3565
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc150
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh85
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh84
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh165
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh329
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh32
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var-mvar-table.hh11
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc4
-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-machinery.cc)65
-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.hh14
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh38
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-repacker.hh1279
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh23
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-serialize.hh108
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh65
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.cc66
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.h8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-set.hh43
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc34
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shape-plan.h4
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shape-plan.hh3
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shape.cc37
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shaper.cc16
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-static.cc51
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh132
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc11
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh681
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc86
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc272
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc305
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh93
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc464
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc949
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh188
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc17
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.h11
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.cc374
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.h39
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset.hh1
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ucd-table.hh7469
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ucd.cc16
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-unicode-emoji-table.hh71
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-unicode.cc42
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-unicode.h8
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-unicode.hh7
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc6
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-utf.hh30
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-vector.hh248
-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.hh43
-rw-r--r--src/3rdparty/harfbuzz-ng/src/main.cc53
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-algs.cc95
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-bimap.cc76
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-buffer-serialize.cc97
-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.cc360
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-map.cc139
-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.cc89
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-repacker.cc1360
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-set.cc97
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test-vector.cc154
-rw-r--r--src/3rdparty/harfbuzz-ng/src/test.cc95
-rw-r--r--tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp41
338 files changed, 44685 insertions, 28976 deletions
diff --git a/src/3rdparty/harfbuzz-ng/CMakeLists.txt b/src/3rdparty/harfbuzz-ng/CMakeLists.txt
index d52a5b7c5b..f46d0d43f1 100644
--- a/src/3rdparty/harfbuzz-ng/CMakeLists.txt
+++ b/src/3rdparty/harfbuzz-ng/CMakeLists.txt
@@ -1,5 +1,3 @@
-# Generated from harfbuzz-ng.pro.
-
#####################################################################
## BundledHarfbuzz Generic Library:
#####################################################################
@@ -7,7 +5,7 @@
qt_internal_add_3rdparty_library(BundledHarfbuzz
QMAKE_LIB_NAME harfbuzz
STATIC
- SKIP_AUTOMOC # special case
+ SKIP_AUTOMOC
SOURCES
hb-dummy.cc
src/hb.h
@@ -18,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
@@ -27,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
@@ -51,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
@@ -64,8 +70,8 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
HB_NO_UNICODE_FUNCS
QT_NO_VERSION_TAGGING
INCLUDE_DIRECTORIES
- $<TARGET_PROPERTY:Core,INCLUDE_DIRECTORIES> # special case
- "${CMAKE_CURRENT_SOURCE_DIR}" # special case
+ $<TARGET_PROPERTY:Core,INCLUDE_DIRECTORIES>
+ "${CMAKE_CURRENT_SOURCE_DIR}"
PUBLIC_INCLUDE_DIRECTORIES
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/harfbuzz>
)
@@ -78,16 +84,9 @@ endif()
qt_disable_warnings(BundledHarfbuzz)
qt_set_symbol_visibility_hidden(BundledHarfbuzz)
-#### Keys ignored in scope 1:.:.:harfbuzz-ng.pro:<TRUE>:
-# OTHER_FILES = "$$PWD/src/harfbuzz.cc"
-# SHAPERS = "opentype"
-
## Scopes:
#####################################################################
-#### Keys ignored in scope 2:.:.:harfbuzz-ng.pro:APPLE:
-# SHAPERS = "coretext"
-
qt_internal_extend_target(BundledHarfbuzz CONDITION UNIX
DEFINES
HAVE_PTHREAD
@@ -100,7 +99,7 @@ qt_internal_extend_target(BundledHarfbuzz CONDITION WIN32
HB_NO_WIN1256
)
-qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE # special case
+qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE
SOURCES
src/hb-ot.h
src/hb-ot-cff1-std-str.hh
@@ -108,8 +107,6 @@ qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE # special case
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
@@ -135,27 +132,32 @@ qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE # special case
src/hb-ot-post-table.hh
src/hb-ot-post-table-v2subset.hh
src/hb-ot-shape.cc src/hb-ot-shape.h src/hb-ot-shape.hh
- src/hb-ot-shape-complex-arabic.cc src/hb-ot-shape-complex-arabic.hh
- src/hb-ot-shape-complex-arabic-fallback.hh
- src/hb-ot-shape-complex-arabic-joining-list.hh
- src/hb-ot-shape-complex-arabic-table.hh
- src/hb-ot-shape-complex-default.cc
- src/hb-ot-shape-complex-hangul.cc
- src/hb-ot-shape-complex-hebrew.cc
- src/hb-ot-shape-complex-indic.cc src/hb-ot-shape-complex-indic.hh
- src/hb-ot-shape-complex-indic-machine.hh
- src/hb-ot-shape-complex-indic-table.cc
- src/hb-ot-shape-complex-khmer.cc
- src/hb-ot-shape-complex-myanmar.cc
- src/hb-ot-shape-complex-myanmar-machine.hh
- src/hb-ot-shape-complex-syllabic.cc src/hb-ot-shape-complex-syllabic.hh
- src/hb-ot-shape-complex-thai.cc
- src/hb-ot-shape-complex-use.cc
- src/hb-ot-shape-complex-use-machine.hh
- src/hb-ot-shape-complex-use-table.hh
- src/hb-ot-shape-complex-vowel-constraints.cc
src/hb-ot-shape-fallback.cc src/hb-ot-shape-fallback.hh
src/hb-ot-shape-normalize.cc src/hb-ot-shape-normalize.hh
+ src/hb-ot-shaper-arabic-fallback.hh
+ src/hb-ot-shaper-arabic-joining-list.hh
+ src/hb-ot-shaper-arabic-pua.hh
+ src/hb-ot-shaper-arabic-table.hh
+ src/hb-ot-shaper-arabic.cc src/hb-ot-shaper-arabic.hh
+ src/hb-ot-shaper-default.cc
+ src/hb-ot-shaper-hangul.cc
+ src/hb-ot-shaper-hebrew.cc
+ src/hb-ot-shaper-indic-machine.hh
+ src/hb-ot-shaper-indic-table.cc
+ src/hb-ot-shaper-indic.cc src/hb-ot-shaper-indic.hh
+ src/hb-ot-shaper-khmer-machine.hh
+ src/hb-ot-shaper-khmer.cc
+ src/hb-ot-shaper-myanmar-machine.hh
+ src/hb-ot-shaper-myanmar.cc
+ src/hb-ot-shaper-syllabic.cc src/hb-ot-shaper-syllabic.hh
+ src/hb-ot-shaper-thai.cc
+ src/hb-ot-shaper-use-machine.hh
+ src/hb-ot-shaper-use-table.hh
+ src/hb-ot-shaper-use.cc
+ src/hb-ot-shaper-vowel-constraints.cc
+ src/hb-ot-shaper-vowel-constraints.hh
+ src/hb-ot-shaper.hh
+ src/hb-subset-accelerator.hh
src/hb-ot-tag.cc
src/hb-ot-var.cc src/hb-ot-var.h
src/hb-ot-var-common.hh
@@ -163,6 +165,14 @@ qt_internal_extend_target(BundledHarfbuzz CONDITION TRUE # special case
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 0559840cf3..9a5914525c 100644
--- a/src/3rdparty/harfbuzz-ng/NEWS
+++ b/src/3rdparty/harfbuzz-ng/NEWS
@@ -1,3 +1,369 @@
+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
+====================================
+- A new API have been added to pre-process the face and speed up future
+ subsetting operations on that face. Provides up to a 95% reduction in
+ subsetting times when the same face is subset more than once.
+
+ For more details and benchmarks, see:
+ https://github.com/harfbuzz/harfbuzz/blob/main/docs/subset-preprocessing.md
+
+ (Garret Rieger, Behdad Esfahbod)
+
+- Shaping have been speedup by skipping entire lookups when the buffer contents
+ don't intersect with the lookup. Shows up to a 10% speedup in shaping some
+ fonts. (Behdad Esfahbod)
+
+- A new experimental feature, “Variable Composites” (enabled by passing
+ -Dexperimental_api=true to meson), is also featured in this release.
+ This technology enables drastic compression of fonts in the Chinese,
+ Japanese, Korean, and other writing systems, by reusing the OpenType Font
+ Variations technology for encoding “smart components” into the font.
+
+ The specification for these extensions to the font format can be found in:
+ https://github.com/harfbuzz/boring-expansion-spec/blob/glyf1/glyf1.md
+
+ A test variable-font with ~7160 Hangul syllables derived from the
+ NotoSerifKR-VF font has been built, with existing OpenType technology, as
+ well as with the new Variable Composites (VarComposites) technology. The
+ VarComposites font is over 90% smaller than the OpenType version of the font!
+ Both fonts can be obtained from the “smarties” repository:
+ https://github.com/behdad/smarties/tree/3.0/fonts/hangul/serif
+
+ When building HarfBuzz with experimental features enabled, you can test
+ the “smarties” font with a sample character like this:
+
+ $ hb-view butchered-hangul-serif-smarties-variable.ttf -u AE01 --variations=wght=700
+
+ (Behdad Esfahbod)
+
+- The HarfBuzz subsetter can now drop axes by pinning them to specific values
+ (also referred to as instancing). There are a couple of restrictions
+ currently:
+
+ - Only works with TrueType (“glyf”) based fonts. “CFF2” fonts are not yet
+ supported.
+ - Only supports the case where all axes in a font are pinned.
+
+ (Garret Rieger, Qunxin Liu)
+
+- Miscellaneous fixes and improvements.
+
+ (Behdad Esfahbod, Christoph Reiter, David Corbett, Eli Schwartz, Garret
+ Rieger, Joel Auterson, Jordan Petridis, Khaled Hosny, Lorenz Wildberg,
+ Marco Rebhan, Martin Storsjö, Matthias Clasen, Qunxin Liu, Satadru Pramanik)
+
+
+- New API
++hb_subset_input_pin_axis_location()
++hb_subset_input_pin_axis_to_default()
++hb_subset_preprocess()
+
+
+Overview of changes leading to 5.3.1
+Wednesday, October 19, 2022
+====================================
+- Subsetter repacker fixes. (Garret Rieger)
+- Adjust Grapheme clusters for Katakana voiced sound marks. (Behdad Esfahbod)
+- New “hb-subset” option “--preprocess-face”. (Garret Rieger)
+
+
+Overview of changes leading to 5.3.0
+Saturday, October 8, 2022
+"Women, Life, Freedom" #MahsaAmini
+====================================
+- Don’t add glyphs from dropped MATH or COLR tables to the subset glyphs.
+ (Khaled Hosny)
+- Map “rlig” to appropriate AAT feature selectors. (Jonathan Kew)
+- Update USE data files to latest version. (David Corbett)
+- Check “CBDT” extents first before outline tables, to help with fonts that
+ also include an empty “glyf” table. (Khaled Hosny)
+- More work towards variable font instancing in the subsetter. (Qunxin Liu)
+- Subsetter repacker improvements. (Garret Rieger)
+- New API:
++hb_ot_layout_lookup_get_optical_bound()
++hb_face_builder_sort_tables()
+
+
+Overview of changes leading to 5.2.0
+Saturday, September 17, 2022
+====================================
+- Fix regressions in hb-ft font functions for FT_Face’s with transformation
+ matrix. (Behdad Esfahbod)
+- The experimental hb-repacker API now supports splitting several GPOS subtable
+ types when needed. (Garret Rieger)
+- The HarfBuzz extensions to OpenType font format are now opt-in behind
+ build-time flags. (Behdad Esfahbod)
+- The experimental hb-subset variable fonts instantiation API can now
+ instantiate more font tables and arbitrary axis locations. (Qunxin Liu)
+- Unicode 15 support. (David Corbett)
+- Various documentation improvements. (Behdad Esfahbod, Matthias Clasen)
+- The hb-view command line tool now detects WezTerm inline images support.
+ (Wez Furlong)
+- Fix FreeType and ICU dependency lookup with meson. (Xavier Claessens)
+
+- New API:
++HB_SCRIPT_KAWI
++HB_SCRIPT_NAG_MUNDARI
+
+
+Overview of changes leading to 5.1.0
+Sunday, July 31, 2022
+====================================
+- More extensive buffer tracing messages. (Behdad Esfahbod)
+- Fix hb-ft regression in bitmap fonts rendering. (Behdad Esfahbod)
+- Support extension promotion of lookups in hb-subset-repacker. (Garret Rieger)
+- A new HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL for scripts that use elongation
+ (e.g. Arabic) to signify where it is safe to insert tatweel glyph without
+ interrupting shaping. (Behdad Esfahbod)
+- Add “--safe-to-insert-tatweel” to “hb-shape” tool. (Behdad Esfahbod)
+
+- New API
++HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL
++HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL
+
+
+Overview of changes leading to 5.0.1
+Saturday, July 23, 2022
+====================================
+- Fix version 2 “avar” table with hb-ft. (Behdad Esfahbod)
+
+
+Overview of changes leading to 5.0.0
+Saturday, July 23, 2022
+====================================
+- Support fonts with more than 65535 glyphs in “GDEF”, “GSUB”, and “GPOS”
+ tables. This is part of https://github.com/be-fonts/boring-expansion-spec to
+ extend OpenType in a backward-compatible way.
+ (Behdad Esfahbod, Garret Rieger)
+- Complete support for more than 65535 glyphs in “glyf” table that started in
+ 4.0.0 release. Part of boring-expansion-spec. (Behdad Esfahbod)
+- Support version 2 of “avar” table. Part of boring-expansion-spec.
+ (Behdad Esfahbod)
+- Fix mark attachment on multiple substitutions in some cases.
+ (Behdad Esfahbod)
+- Fix application of “calt”, “rclt”, and “ccmp” features to better match
+ Uniscribe behaviour with some Arabic fonts. (Behdad Esfahbod)
+- Improvement to interaction between multiple cursive attachments.
+ (Behdad Esfahbod)
+- Improve multiple mark interactions in Hebrew. (Behdad Esfahbod)
+- Implement language-specific forms in AAT shaping. (Behdad Esfahbod)
+- Fix variation of “VORG” table. (Behdad Esfahbod)
+- Support for specific script tags to be retained in the subsetter, and add
+ “--layout-scripts” option to “hb-subset” tool. (Garret Rieger)
+- Accept space as delimiter for --features/--variations in command line tools.
+- Improve subsetting of “COLR” table. (Qunxin Liu)
+- Improved fuzzing coverage for ot-math API. (Frédéric Wang)
+- Fix “kern” table version 2 (AAT) sanitization on 32-bit systems.
+ (Behdad Esfahbod)
+- Allow negative glyph advances from “graphite2” shaper. (Stephan Bergmann)
+- Implement loading (color) bitmap fonts with hb-ft. (Behdad Esfahbod)
+- Fix regression in hb-ft when changing font size. (Behdad Esfahbod)
+- Fix build on GCC < 7. (Kleis Auke Wolthuizen)
+- Dynamically load dwrite.dll on windows if “directwrite” shaper is enabled.
+ (Luca Bacci)
+- Provide a single-file harfbuzz-subset.cc file for easier alternate building
+ of hb-subset library, similar to harfbuzz.cc. (Khaled Hosny)
+
+- New API
++HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG
++hb_language_matches()
+
+
+Overview of changes leading to 4.4.1
+Wednesday, June 29, 2022
+====================================
+- Fix test failure with some compilers.
+- Fix Telugu and Kannada kerning regression.
+
+
+Overview of changes leading to 4.4.0
+Monday, June 27, 2022
+====================================
+- Caching of variable fonts shaping, in particular when using HarfBuzz’s own
+ font loading functions (ot). Bringing performance of variable shaping in par
+ with non-variable fonts shaping. (Behdad Esfahbod)
+- Caching of format 2 “Contextual Substitution” and “Chained Contexts
+ Substitution” lookups. Resulting in up to 20% speedup of lookup-heavy fonts
+ like Gulzar or Noto Nastaliq Urdu. (Behdad Esfahbod)
+- Improved ANSI output from hb-view. (Behdad Esfahbod)
+- Support for shaping legacy, pre-OpenType Windows 3.1-era, Arabic fonts that
+ relied on a fixed PUA encoding. (Khaled Hosny, Behdad Esfahbod)
+- Sinhala script is now shaped by the USE shaper instead of “indic” one.
+ (Behdad Esfahbod, David Corbett)
+- Thai shaper improvements. (David Corbett)
+- hb-ot-name API supports approximate BCP-47 language matching, for example
+ asking for “en_US” in a font that has only “en” names will return them.
+ (Behdad Esfahbod)
+- Optimized TrueType glyph shape loading. (Behdad Esfahbod)
+- Fix subsetting of HarfBuzz faces created via hb_face_create_for_tables().
+ (Garret Rieger)
+- Add 32 bit var store support to the subsetter. (Garret Rieger)
+
+- New API
++HB_BUFFER_FLAG_DEFINED
++HB_BUFFER_SERIALIZE_FLAG_DEFINED
++hb_font_changed()
++hb_font_get_serial()
++hb_ft_hb_font_changed()
++hb_set_hash()
++hb_map_copy()
++hb_map_hash()
+
+
+Overview of changes leading to 4.3.0
+Friday, May 20, 2022
+====================================
+- Major speed up in loading and subsetting fonts, especially in
+ handling CFF table. Subsetting some fonts is now 3 times faster.
+ (Behdad Esfahbod, Garret Rieger)
+- Speed up blending CFF2 table. (Behdad Esfahbod)
+- Speed up hb_ot_tags_from_language(). (Behdad Esfahbod, David Corbett)
+- Fix USE classification of U+10A38 to fix multiple marks on single Kharoshthi
+ base. (David Corbett)
+- Fix parsing of empty CFF Index. (Behdad Esfahbod)
+- Fix subsetting CPAL table with partial palette overlaps. (Garret Rieger)
+
+- New API
++hb_map_is_equal() (Behdad Esfahbod)
+
+
Overview of changes leading to 4.2.1
Sunday, April 24, 2022
====================================
diff --git a/src/3rdparty/harfbuzz-ng/README.md b/src/3rdparty/harfbuzz-ng/README.md
index fc12c65568..4202961e04 100644
--- a/src/3rdparty/harfbuzz-ng/README.md
+++ b/src/3rdparty/harfbuzz-ng/README.md
@@ -6,7 +6,12 @@
[![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
[![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions)
-This is HarfBuzz, a text shaping library.
+# HarfBuzz
+
+HarfBuzz is a text shaping engine. It primarily supports [OpenType][1], but also
+[Apple Advanced Typography][2]. HarfBuzz is used in Android, Chrome,
+ChromeOS, Firefox, GNOME, GTK+, KDE, LibreOffice, OpenJDK, PlayStation, Qt,
+XeTeX, and other places.
For bug reports, mailing list, and other information please visit:
@@ -14,14 +19,66 @@ For bug reports, mailing list, and other information please visit:
For license information, see [COPYING](COPYING).
+## Documentation
+
+For user manual as well as API documentation, check: https://harfbuzz.github.io
+
+## Download
+
+For tarball releases of HarfBuzz, look [here][3]. At the same place you
+will also find Win32/Win64 binary bundles that include libharfbuzz DLL,
+hb-view.exe, hb-shape.exe, and all dependencies.
+
+The canonical source tree is available on [github][4].
+
+The API that comes with `hb.h` will not change incompatibly. Other, peripheral,
+headers are more likely to go through minor modifications, but again, we do our
+best to never change API in an incompatible way. We will never break the ABI.
+
+If you are not sure whether Pango or HarfBuzz is right for you, read [Pango vs
+HarfBuzz][5].
+
+## Development
+
For build information, see [BUILD.md](BUILD.md).
For custom configurations, see [CONFIG.md](CONFIG.md).
-For test execution, see [TESTING.md](TESTING.md).
+For testing and profiling, see [TESTING.md](TESTING.md).
-Documentation: https://harfbuzz.github.io
+To get a better idea of where HarfBuzz stands in the text rendering stack you
+may want to read [State of Text Rendering][6], though, that document is many
+years old. Here are a few presentation slides about HarfBuzz at the
+Internationalization and Unicode Conference over the years:
+* November 2014, [Unicode, OpenType, and HarfBuzz: Closing the Circle][7],
+* October 2012, [HarfBuzz, The Free and Open Text Shaping Engine][8],
+* October 2009, [HarfBuzz: the Free and Open Shaping Engine][9].
+
+Both development and user support discussion around HarfBuzz happens on the
+[github][4].
+
+To report bugs or submit patches please use [github][4] issues and
+pull-requests.
+
+For a comparison of old vs new HarfBuzz memory consumption see [this][10].
+
+<!--See past and upcoming [HarfBuzz Hackfests](https://freedesktop.org/wiki/Software/HarfBuzz/Hackfests/)!-->
+
+## Name
+
+HarfBuzz (حرف‌باز) is my Persian translation of “[OpenType][1]”,
+transliterated using the Latin script. It sports a second meaning, but that
+ain’t translatable.
+
+> Background: Originally there was this font format called TrueType. People and
+> companies started calling their type engines all things ending in Type:
+> FreeType, CoolType, ClearType, etc. And then came OpenType, which is the
+> successor of TrueType. So, for my OpenType implementation, I decided to stick
+> with the concept but use the Persian translation. Which is fitting given that
+> Persian is written in the Arabic script, and OpenType is an extension of
+> TrueType that adds support for complex script rendering, and HarfBuzz is an
+> implementation of OpenType complex text shaping.
<details>
<summary>Packaging status of HarfBuzz</summary>
@@ -29,3 +86,14 @@ Documentation: https://harfbuzz.github.io
[![Packaging status](https://repology.org/badge/vertical-allrepos/harfbuzz.svg?header=harfbuzz)](https://repology.org/project/harfbuzz/versions)
</details>
+
+[1]: https://docs.microsoft.com/en-us/typography/opentype/spec/
+[2]: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html
+[3]: https://github.com/harfbuzz/harfbuzz/releases
+[4]: https://github.com/harfbuzz/harfbuzz
+[5]: http://mces.blogspot.com/2009/11/pango-vs-harfbuzz.html
+[6]: http://behdad.org/text/
+[7]: https://goo.gl/FSIQuC
+[8]: https://goo.gl/2wSRu
+[9]: http://behdad.org/download/Presentations/slippy/harfbuzz_slides.pdf
+[10]: https://goo.gl/woyty
diff --git a/src/3rdparty/harfbuzz-ng/import_from_tarball.sh b/src/3rdparty/harfbuzz-ng/import_from_tarball.sh
index 7bcaf22cdc..627cc51b28 100644
--- a/src/3rdparty/harfbuzz-ng/import_from_tarball.sh
+++ b/src/3rdparty/harfbuzz-ng/import_from_tarball.sh
@@ -90,16 +90,4 @@ for i in ${FILES[*]}; do
copy_file_or_dir "$i"
done
-CODEFILES=($HB_DIR/src/*.cc
- $HB_DIR/src/*.hh
- $HB_DIR/src/*.h)
-
-for i in ${CODEFILES[*]}; do
- cp $i $TARGET_DIR/src/
-done
-
-GSUBFILES=($HB_DIR/src/OT/Layout/GSUB/*.hh)
-
-for i in ${GSUBFILES[*]}; do
- cp $i $TARGET_DIR/src/OT/Layout/GSUB/
-done
+cp -R $HB_DIR/src $TARGET_DIR
diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json
index d5e2bccfa0..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": "4.2.1",
+ "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 23fa56c4f6..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
@@ -67,7 +68,7 @@ _copy_data_to_cbdt (hb_vector_t<char> *cbdt_prime,
{
unsigned int new_len = cbdt_prime->length + length;
if (unlikely (!cbdt_prime->alloc (new_len))) return false;
- memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length);
+ hb_memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length);
cbdt_prime->length = new_len;
return true;
}
@@ -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)
{
@@ -468,13 +472,13 @@ struct IndexSubtableRecord
if (unlikely (!c->serializer->check_success (records->resize (records->length + 1))))
return_trace (false);
- (*records)[records->length - 1].firstGlyphIndex = 1;
- (*records)[records->length - 1].lastGlyphIndex = 0;
+ records->tail ().firstGlyphIndex = 1;
+ records->tail ().lastGlyphIndex = 0;
bitmap_size_context->size += IndexSubtableRecord::min_size;
c->serializer->push ();
- if (unlikely (!add_new_subtable (c, bitmap_size_context, &((*records)[records->length - 1]), lookup, base, start)))
+ if (unlikely (!add_new_subtable (c, bitmap_size_context, &(records->tail ()), lookup, base, start)))
{
c->serializer->pop_discard ();
c->serializer->revert (snap);
@@ -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 dac755c02c..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,17 +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 100
-#endif
-#ifndef COLRV1_ENABLE_SUBSETTING
-#define COLRV1_ENABLE_SUBSETTING 1
-#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>
{
@@ -102,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_),
@@ -145,7 +212,7 @@ struct BaseGlyphRecord
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
public:
@@ -164,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);
@@ -186,8 +255,26 @@ 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:
VarIdx varIdxBase;
public:
DEFINE_SIZE_STATIC (4 + T::static_size);
@@ -196,6 +283,10 @@ 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
{
TRACE_SERIALIZE (this);
@@ -217,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);
@@ -234,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));
}
@@ -244,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;
@@ -295,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:
@@ -358,14 +523,25 @@ struct Affine2x3
return_trace (c->check_struct (this));
}
- HBFixed xx;
- HBFixed yx;
- HBFixed xy;
- HBFixed yy;
- HBFixed dx;
- HBFixed dy;
+ 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;
+ F16DOT16 yy;
+ F16DOT16 dx;
+ F16DOT16 dy;
public:
- DEFINE_SIZE_STATIC (6 * HBFixed::static_size);
+ DEFINE_SIZE_STATIC (6 * F16DOT16::static_size);
};
struct PaintColrLayers
@@ -377,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);
@@ -389,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 */
@@ -406,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));
}
@@ -416,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;
@@ -444,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. */
@@ -478,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. */
@@ -512,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. */
@@ -523,7 +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 */
@@ -887,6 +1262,11 @@ struct PaintComposite
DEFINE_SIZE_STATIC (8);
};
+struct ClipBoxData
+{
+ int xMin, yMin, xMax, yMax;
+};
+
struct ClipBoxFormat1
{
bool sanitize (hb_sanitize_context_t *c) const
@@ -895,6 +1275,14 @@ struct ClipBoxFormat1
return_trace (c->check_struct (this));
}
+ void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer HB_UNUSED) const
+ {
+ clip_box.xMin = xMin;
+ clip_box.yMin = yMin;
+ clip_box.xMax = xMax;
+ clip_box.yMax = yMax;
+ }
+
public:
HBUINT8 format; /* format = 1(noVar) or 2(Var)*/
FWORD xMin;
@@ -905,7 +1293,20 @@ struct ClipBoxFormat1
DEFINE_SIZE_STATIC (1 + 4 * FWORD::static_size);
};
-struct ClipBoxFormat2 : Variable<ClipBoxFormat1> {};
+struct ClipBoxFormat2 : Variable<ClipBoxFormat1>
+{
+ void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer) const
+ {
+ value.get_clip_box(clip_box, instancer);
+ if (instancer)
+ {
+ clip_box.xMin += _hb_roundf (instancer (varIdxBase, 0));
+ clip_box.yMin += _hb_roundf (instancer (varIdxBase, 1));
+ clip_box.xMax += _hb_roundf (instancer (varIdxBase, 2));
+ clip_box.yMax += _hb_roundf (instancer (varIdxBase, 3));
+ }
+ }
+};
struct ClipBox
{
@@ -922,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)...));
@@ -931,6 +1332,28 @@ struct ClipBox
}
}
+ bool get_extents (hb_glyph_extents_t *extents,
+ const VarStoreInstancer &instancer) const
+ {
+ ClipBoxData clip_box;
+ switch (u.format) {
+ case 1:
+ u.format1.get_clip_box (clip_box, instancer);
+ break;
+ case 2:
+ u.format2.get_clip_box (clip_box, instancer);
+ break;
+ default:
+ return false;
+ }
+
+ extents->x_bearing = clip_box.xMin;
+ extents->y_bearing = clip_box.yMax;
+ extents->width = clip_box.xMax - clip_box.xMin;
+ extents->height = clip_box.yMin - clip_box.yMax;
+ return true;
+ }
+
protected:
union {
HBUINT8 format; /* Format identifier */
@@ -941,6 +1364,9 @@ struct ClipBox
struct ClipRecord
{
+ int cmp (hb_codepoint_t g) const
+ { return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
+
ClipRecord* copy (hb_serialize_context_t *c, const void *base) const
{
TRACE_SERIALIZE (this);
@@ -956,6 +1382,13 @@ struct ClipRecord
return_trace (c->check_struct (this) && clipBox.sanitize (c, base));
}
+ bool get_extents (hb_glyph_extents_t *extents,
+ const void *base,
+ const VarStoreInstancer &instancer) const
+ {
+ return (base+clipBox).get_extents (extents, instancer);
+ }
+
public:
HBUINT16 startGlyphID; // first gid clip applies to
HBUINT16 endGlyphID; // last gid clip applies to, inclusive
@@ -963,6 +1396,7 @@ struct ClipRecord
public:
DEFINE_SIZE_STATIC (7);
};
+DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord);
struct ClipList
{
@@ -1025,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;
@@ -1051,11 +1485,26 @@ struct ClipList
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
+ // TODO Make a formatted struct!
return_trace (c->check_struct (this) && clips.sanitize (c, this));
}
+ bool
+ get_extents (hb_codepoint_t gid,
+ hb_glyph_extents_t *extents,
+ const VarStoreInstancer &instancer) const
+ {
+ auto *rec = clips.as_array ().bsearch (gid);
+ if (rec)
+ {
+ rec->get_extents (extents, this, instancer);
+ return true;
+ }
+ return false;
+ }
+
HBUINT8 format; // Set to 1.
- Array32Of<ClipRecord> clips; // Clip records, sorted by startGlyphID
+ SortedArray32Of<ClipRecord> clips; // Clip records, sorted by startGlyphID
public:
DEFINE_SIZE_ARRAY_SIZED (5, clips);
};
@@ -1068,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)...)));
@@ -1077,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)...));
@@ -1120,38 +1569,40 @@ 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;
+ public:
+ DEFINE_SIZE_MIN (2);
};
struct BaseGlyphPaintRecord
@@ -1193,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 ())
{
@@ -1247,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,
@@ -1356,7 +1814,7 @@ struct COLR
(this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
(this+layersZ).sanitize (c, numLayers) &&
(version == 0 ||
- (COLRV1_ENABLE_SUBSETTING && version == 1 &&
+ (version == 1 &&
baseGlyphList.sanitize (c, this) &&
layerList.sanitize (c, this) &&
clipList.sanitize (c, this) &&
@@ -1427,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 ())
@@ -1476,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);
@@ -1509,10 +1967,171 @@ 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
+ {
+ if (version != 1)
+ return false;
+
+ VarStoreInstancer instancer (this+varStore,
+ this+varIdxMap,
+ hb_array (font->coords, font->num_coords));
+
+ if (get_clip (glyph, extents, instancer))
+ {
+ 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;
+ }
+
+ return false;
+ }
+
protected:
HBUINT16 version; /* Table version number (starts at 0). */
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */
@@ -1535,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 a9deeba9a7..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"
/*
@@ -97,9 +97,10 @@ struct CPALV1Tail
c->push ();
for (const auto _ : colorLabels)
{
- if (!color_index_map->has (_)) continue;
+ const hb_codepoint_t *v;
+ if (!color_index_map->has (_, &v)) continue;
NameID new_color_idx;
- new_color_idx = color_index_map->get (_);
+ new_color_idx = *v;
if (!c->copy<NameID> (new_color_idx))
{
c->pop_discard ();
@@ -197,30 +198,38 @@ struct CPAL
public:
bool serialize (hb_serialize_context_t *c,
- const hb_array_t<const BGRAColor> &color_records,
const hb_array_t<const HBUINT16> &color_record_indices,
- const hb_map_t &color_record_index_map,
- const hb_set_t &retained_color_record_indices) const
+ const hb_array_t<const BGRAColor> &color_records,
+ const hb_vector_t<unsigned>& first_color_index_for_layer,
+ const hb_map_t& first_color_to_layer_index,
+ const hb_set_t &retained_color_indices) const
{
TRACE_SERIALIZE (this);
+ // TODO(grieger): limit total final size.
+
for (const auto idx : color_record_indices)
{
+ hb_codepoint_t layer_index = first_color_to_layer_index[idx];
+
HBUINT16 new_idx;
- if (idx == 0) new_idx = 0;
- else new_idx = color_record_index_map.get (idx);
+ new_idx = layer_index * retained_color_indices.get_population ();
if (!c->copy<HBUINT16> (new_idx)) return_trace (false);
}
c->push ();
- for (const auto _ : retained_color_record_indices.iter ())
+ for (unsigned first_color_index : first_color_index_for_layer)
{
- if (!c->copy<BGRAColor> (color_records[_]))
+ for (hb_codepoint_t color_index : retained_color_indices)
{
- c->pop_discard ();
- return_trace (false);
+ if (!c->copy<BGRAColor> (color_records[first_color_index + color_index]))
+ {
+ c->pop_discard ();
+ return_trace (false);
+ }
}
}
+
c->add_link (colorRecordsZ, c->pop_pack ());
return_trace (true);
}
@@ -228,7 +237,9 @@ struct CPAL
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_map_t *color_index_map = c->plan->colr_palettes;
+ if (!numPalettes) return_trace (false);
+
+ 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;
@@ -242,30 +253,34 @@ struct CPAL
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
out->version = version;
out->numColors = retained_color_indices.get_population ();
out->numPalettes = numPalettes;
- const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
- hb_map_t color_record_index_map;
- hb_set_t retained_color_record_indices;
+ hb_vector_t<unsigned> first_color_index_for_layer;
+ hb_map_t first_color_to_layer_index;
- unsigned record_count = 0;
+ const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
for (const auto first_color_record_idx : colorRecordIndices)
{
- for (unsigned retained_color_idx : retained_color_indices.iter ())
- {
- unsigned color_record_idx = first_color_record_idx + retained_color_idx;
- if (color_record_index_map.has (color_record_idx)) continue;
- color_record_index_map.set (color_record_idx, record_count);
- retained_color_record_indices.add (color_record_idx);
- record_count++;
- }
+ if (first_color_to_layer_index.has (first_color_record_idx)) continue;
+
+ first_color_index_for_layer.push (first_color_record_idx);
+ first_color_to_layer_index.set (first_color_record_idx,
+ first_color_index_for_layer.length - 1);
}
- out->numColorRecords = record_count;
+ out->numColorRecords = first_color_index_for_layer.length
+ * retained_color_indices.get_population ();
+
const hb_array_t<const BGRAColor> color_records = (this+colorRecordsZ).as_array (numColorRecords);
- if (!out->serialize (c->serializer, color_records, colorRecordIndices, color_record_index_map, retained_color_record_indices))
+ if (!out->serialize (c->serializer,
+ colorRecordIndices,
+ color_records,
+ first_color_index_for_layer,
+ first_color_to_layer_index,
+ retained_color_indices))
return_trace (false);
if (version == 1)
@@ -304,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 9741ebd450..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. */
@@ -298,28 +331,30 @@ struct sbix
const PNGHeader &png = *blob->as<PNGHeader>();
+ if (png.IHDR.height >= 65536 || png.IHDR.width >= 65536)
+ {
+ hb_blob_destroy (blob);
+ return false;
+ }
+
extents->x_bearing = x_offset;
extents->y_bearing = png.IHDR.height + y_offset;
extents->width = png.IHDR.width;
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;
@@ -414,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
new file mode 100644
index 0000000000..d35654e245
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh
@@ -0,0 +1,337 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_COVERAGE_HH
+#define OT_LAYOUT_COMMON_COVERAGE_HH
+
+#include "../types.hh"
+#include "CoverageFormat1.hh"
+#include "CoverageFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template<typename Iterator>
+static inline void Coverage_serialize (hb_serialize_context_t *c,
+ Iterator it);
+
+struct Coverage
+{
+
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ CoverageFormat1_3<SmallTypes> format1;
+ CoverageFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BEYOND_64K
+ CoverageFormat1_3<MediumTypes>format3;
+ CoverageFormat2_4<MediumTypes>format4;
+#endif
+ } u;
+ public:
+ DEFINE_SIZE_UNION (2, format);
+
+ 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));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.sanitize (c));
+ case 4: return_trace (u.format4.sanitize (c));
+#endif
+ default:return_trace (true);
+ }
+ }
+
+ /* Has interface. */
+ unsigned operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k] != NOT_COVERED; }
+ /* Predicate. */
+ bool operator () (hb_codepoint_t k) const { return has (k); }
+
+ unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
+ unsigned int get_coverage (hb_codepoint_t glyph_id) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.get_coverage (glyph_id);
+ case 2: return u.format2.get_coverage (glyph_id);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.get_coverage (glyph_id);
+ case 4: return u.format4.get_coverage (glyph_id);
+#endif
+ default:return NOT_COVERED;
+ }
+ }
+
+ unsigned get_population () const
+ {
+ switch (u.format) {
+ case 1: return u.format1.get_population ();
+ case 2: return u.format2.get_population ();
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.get_population ();
+ case 4: return u.format4.get_population ();
+#endif
+ default:return NOT_COVERED;
+ }
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+
+ unsigned count = 0;
+ unsigned num_ranges = 0;
+ hb_codepoint_t last = (hb_codepoint_t) -2;
+ for (auto g: glyphs)
+ {
+ if (last + 1 != g)
+ num_ranges++;
+ last = g;
+ count++;
+ }
+ u.format = count <= num_ranges * 3 ? 1 : 2;
+
+#ifndef HB_NO_BEYOND_64K
+ if (count && last > 0xFFFFu)
+ u.format += 2;
+#endif
+
+ switch (u.format)
+ {
+ case 1: return_trace (u.format1.serialize (c, glyphs));
+ case 2: return_trace (u.format2.serialize (c, glyphs));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.serialize (c, glyphs));
+ case 4: return_trace (u.format4.serialize (c, glyphs));
+#endif
+ default:return_trace (false);
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ 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)
+ ;
+
+ // Cache the iterator result as it will be iterated multiple times
+ // by the serialize code below.
+ hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
+ Coverage_serialize (c->serializer, glyphs.iter ());
+ return_trace (bool (glyphs));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.intersects (glyphs);
+ case 2: return u.format2.intersects (glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersects (glyphs);
+ case 4: return u.format4.intersects (glyphs);
+#endif
+ default:return false;
+ }
+ }
+ bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.intersects_coverage (glyphs, index);
+ case 2: return u.format2.intersects_coverage (glyphs, index);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersects_coverage (glyphs, index);
+ case 4: return u.format4.intersects_coverage (glyphs, index);
+#endif
+ default:return false;
+ }
+ }
+
+ /* Might return false if array looks unsorted.
+ * Used for faster rejection of corrupt data. */
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.collect_coverage (glyphs);
+ case 2: return u.format2.collect_coverage (glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.collect_coverage (glyphs);
+ case 4: return u.format4.collect_coverage (glyphs);
+#endif
+ default:return false;
+ }
+ }
+
+ template <typename IterableOut,
+ hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+ void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
+ case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
+ case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
+#endif
+ default:return ;
+ }
+ }
+
+ struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
+ {
+ static constexpr bool is_sorted_iterator = true;
+ iter_t (const Coverage &c_ = Null (Coverage))
+ {
+ hb_memset (this, 0, sizeof (*this));
+ format = c_.u.format;
+ switch (format)
+ {
+ case 1: u.format1.init (c_.u.format1); return;
+ case 2: u.format2.init (c_.u.format2); return;
+#ifndef HB_NO_BEYOND_64K
+ case 3: u.format3.init (c_.u.format3); return;
+ case 4: u.format4.init (c_.u.format4); return;
+#endif
+ default: return;
+ }
+ }
+ bool __more__ () const
+ {
+ switch (format)
+ {
+ case 1: return u.format1.__more__ ();
+ case 2: return u.format2.__more__ ();
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.__more__ ();
+ case 4: return u.format4.__more__ ();
+#endif
+ default:return false;
+ }
+ }
+ void __next__ ()
+ {
+ switch (format)
+ {
+ case 1: u.format1.__next__ (); break;
+ case 2: u.format2.__next__ (); break;
+#ifndef HB_NO_BEYOND_64K
+ case 3: u.format3.__next__ (); break;
+ case 4: u.format4.__next__ (); break;
+#endif
+ default: break;
+ }
+ }
+ typedef hb_codepoint_t __item_t__;
+ __item_t__ __item__ () const { return get_glyph (); }
+
+ hb_codepoint_t get_glyph () const
+ {
+ switch (format)
+ {
+ case 1: return u.format1.get_glyph ();
+ case 2: return u.format2.get_glyph ();
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.get_glyph ();
+ case 4: return u.format4.get_glyph ();
+#endif
+ default:return 0;
+ }
+ }
+ bool operator != (const iter_t& o) const
+ {
+ if (unlikely (format != o.format)) return true;
+ switch (format)
+ {
+ case 1: return u.format1 != o.u.format1;
+ case 2: return u.format2 != o.u.format2;
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3 != o.u.format3;
+ case 4: return u.format4 != o.u.format4;
+#endif
+ default:return false;
+ }
+ }
+ iter_t __end__ () const
+ {
+ iter_t it = {};
+ it.format = format;
+ switch (format)
+ {
+ case 1: it.u.format1 = u.format1.__end__ (); break;
+ case 2: it.u.format2 = u.format2.__end__ (); break;
+#ifndef HB_NO_BEYOND_64K
+ case 3: it.u.format3 = u.format3.__end__ (); break;
+ case 4: it.u.format4 = u.format4.__end__ (); break;
+#endif
+ default: break;
+ }
+ return it;
+ }
+
+ private:
+ unsigned int format;
+ union {
+#ifndef HB_NO_BEYOND_64K
+ CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */
+ CoverageFormat1_3<MediumTypes>::iter_t format3;
+#endif
+ CoverageFormat2_4<SmallTypes>::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
+ CoverageFormat1_3<SmallTypes>::iter_t format1;
+ } u;
+ };
+ iter_t iter () const { return iter_t (*this); }
+};
+
+template<typename Iterator>
+static inline void
+Coverage_serialize (hb_serialize_context_t *c,
+ Iterator it)
+{ c->start_embed<Coverage> ()->serialize (c, it); }
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_COMMON_COVERAGE_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh
new file mode 100644
index 0000000000..5d68e3d15e
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh
@@ -0,0 +1,133 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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, Garret Rieger
+ */
+
+
+#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
+#define OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+#define NOT_COVERED ((unsigned int) -1)
+
+template <typename Types>
+struct CoverageFormat1_3
+{
+ friend struct Coverage;
+
+ protected:
+ HBUINT16 coverageFormat; /* Format identifier--format = 1 */
+ SortedArray16Of<typename Types::HBGlyphID>
+ glyphArray; /* Array of GlyphIDs--in numerical order */
+ public:
+ DEFINE_SIZE_ARRAY (4, glyphArray);
+
+ private:
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (glyphArray.sanitize (c));
+ }
+
+ unsigned int get_coverage (hb_codepoint_t glyph_id) const
+ {
+ unsigned int i;
+ glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
+ return i;
+ }
+
+ unsigned get_population () const
+ {
+ return glyphArray.len;
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (glyphArray.serialize (c, glyphs));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
+ {
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ if (get_coverage (g) != NOT_COVERED)
+ return true;
+ return false;
+ }
+
+ for (const auto& g : glyphArray.as_array ())
+ if (glyphs->has (g))
+ return true;
+ return false;
+ }
+ bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+ { return glyphs->has (glyphArray[index]); }
+
+ template <typename IterableOut,
+ hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+ void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
+ {
+ unsigned count = glyphArray.len;
+ for (unsigned i = 0; i < count; i++)
+ if (glyphs.has (glyphArray[i]))
+ intersect_glyphs << glyphArray[i];
+ }
+
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ { return glyphs->add_sorted_array (glyphArray.as_array ()); }
+
+ public:
+ /* Older compilers need this to be public. */
+ struct iter_t
+ {
+ void init (const struct CoverageFormat1_3 &c_) { c = &c_; i = 0; }
+ bool __more__ () const { return i < c->glyphArray.len; }
+ void __next__ () { i++; }
+ hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
+ bool operator != (const iter_t& o) const
+ { return i != o.i; }
+ iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
+
+ private:
+ const struct CoverageFormat1_3 *c;
+ unsigned int i;
+ };
+ private:
+};
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh
new file mode 100644
index 0000000000..d7fcc35202
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh
@@ -0,0 +1,232 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
+#define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
+
+#include "RangeRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template <typename Types>
+struct CoverageFormat2_4
+{
+ friend struct Coverage;
+
+ protected:
+ HBUINT16 coverageFormat; /* Format identifier--format = 2 */
+ SortedArray16Of<RangeRecord<Types>>
+ rangeRecord; /* Array of glyph ranges--ordered by
+ * Start GlyphID. rangeCount entries
+ * long */
+ public:
+ DEFINE_SIZE_ARRAY (4, rangeRecord);
+
+ private:
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (rangeRecord.sanitize (c));
+ }
+
+ unsigned int get_coverage (hb_codepoint_t glyph_id) const
+ {
+ const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
+ return likely (range.first <= range.last)
+ ? (unsigned int) range.value + (glyph_id - range.first)
+ : NOT_COVERED;
+ }
+
+ unsigned get_population () const
+ {
+ typename Types::large_int ret = 0;
+ for (const auto &r : rangeRecord)
+ ret += r.get_population ();
+ return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+
+ unsigned num_ranges = 0;
+ hb_codepoint_t last = (hb_codepoint_t) -2;
+ for (auto g: glyphs)
+ {
+ if (last + 1 != g)
+ num_ranges++;
+ last = g;
+ }
+
+ if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
+ if (!num_ranges) return_trace (true);
+
+ unsigned count = 0;
+ unsigned range = (unsigned) -1;
+ last = (hb_codepoint_t) -2;
+ for (auto g: glyphs)
+ {
+ if (last + 1 != g)
+ {
+ range++;
+ rangeRecord[range].first = g;
+ rangeRecord[range].value = count;
+ }
+ rangeRecord[range].last = g;
+ last = g;
+ count++;
+ }
+
+ return_trace (true);
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
+ {
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ if (get_coverage (g) != NOT_COVERED)
+ return true;
+ return false;
+ }
+
+ return hb_any (+ hb_iter (rangeRecord)
+ | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
+ }
+ bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+ {
+ auto *range = rangeRecord.as_array ().bsearch (index);
+ if (range)
+ return range->intersects (*glyphs);
+ return false;
+ }
+
+ template <typename IterableOut,
+ hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+ void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
+ {
+ /* Break out of loop for overlapping, broken, tables,
+ * to avoid fuzzer timouts. */
+ hb_codepoint_t last = 0;
+ for (const auto& range : rangeRecord)
+ {
+ if (unlikely (range.first < last))
+ break;
+ last = range.last;
+ for (hb_codepoint_t g = range.first - 1;
+ glyphs.next (&g) && g <= last;)
+ intersect_glyphs << g;
+ }
+ }
+
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ {
+ for (const auto& range: rangeRecord)
+ if (unlikely (!range.collect_coverage (glyphs)))
+ return false;
+ return true;
+ }
+
+ public:
+ /* Older compilers need this to be public. */
+ struct iter_t
+ {
+ void init (const CoverageFormat2_4 &c_)
+ {
+ c = &c_;
+ coverage = 0;
+ i = 0;
+ j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
+ if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
+ {
+ /* Broken table. Skip. */
+ i = c->rangeRecord.len;
+ j = 0;
+ }
+ }
+ bool __more__ () const { return i < c->rangeRecord.len; }
+ void __next__ ()
+ {
+ if (j >= c->rangeRecord[i].last)
+ {
+ i++;
+ if (__more__ ())
+ {
+ unsigned int old = coverage;
+ j = c->rangeRecord[i].first;
+ coverage = c->rangeRecord[i].value;
+ if (unlikely (coverage != old + 1))
+ {
+ /* Broken table. Skip. Important to avoid DoS.
+ * Also, our callers depend on coverage being
+ * consecutive and monotonically increasing,
+ * ie. iota(). */
+ i = c->rangeRecord.len;
+ j = 0;
+ return;
+ }
+ }
+ else
+ j = 0;
+ return;
+ }
+ coverage++;
+ j++;
+ }
+ hb_codepoint_t get_glyph () const { return j; }
+ bool operator != (const iter_t& o) const
+ { return i != o.i || j != o.j; }
+ iter_t __end__ () const
+ {
+ iter_t it;
+ it.init (*c);
+ it.i = c->rangeRecord.len;
+ it.j = 0;
+ return it;
+ }
+
+ private:
+ const struct CoverageFormat2_4 *c;
+ unsigned int i, coverage;
+ hb_codepoint_t j;
+ };
+ private:
+};
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh
new file mode 100644
index 0000000000..a62629fad3
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
+#define OT_LAYOUT_COMMON_RANGERECORD_HH
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template <typename Types>
+struct RangeRecord
+{
+ typename Types::HBGlyphID first; /* First GlyphID in the range */
+ typename Types::HBGlyphID last; /* Last GlyphID in the range */
+ HBUINT16 value; /* Value */
+
+ DEFINE_SIZE_STATIC (2 + 2 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ int cmp (hb_codepoint_t g) const
+ { return g < first ? -1 : g <= last ? 0 : +1; }
+
+ unsigned get_population () const
+ {
+ if (unlikely (last < first)) return 0;
+ return (last - first + 1);
+ }
+
+ bool intersects (const hb_set_t &glyphs) const
+ { return glyphs.intersects (first, last); }
+
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ { return glyphs->add_range (first, last); }
+};
+
+}
+}
+}
+
+// TODO(garretrieger): This was previously implemented using
+// DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9);
+// but that only works when there is only a single namespace level.
+// The macro should probably be fixed so it can work in this situation.
+extern HB_INTERNAL const unsigned char _hb_Null_OT_RangeRecord[9];
+template <typename Spec>
+struct Null<OT::Layout::Common::RangeRecord<Spec>> {
+ static OT::Layout::Common::RangeRecord<Spec> const & get_null () {
+ return *reinterpret_cast<const OT::Layout::Common::RangeRecord<Spec> *> (_hb_Null_OT_RangeRecord);
+ }
+};
+
+
+#endif // #ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
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/Anchor.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Anchor.hh
new file mode 100644
index 0000000000..49e76e7750
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Anchor.hh
@@ -0,0 +1,83 @@
+#ifndef OT_LAYOUT_GPOS_ANCHOR_HH
+#define OT_LAYOUT_GPOS_ANCHOR_HH
+
+#include "AnchorFormat1.hh"
+#include "AnchorFormat2.hh"
+#include "AnchorFormat3.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct Anchor
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ AnchorFormat1 format1;
+ AnchorFormat2 format2;
+ AnchorFormat3 format3;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (2, format);
+
+ 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);
+ }
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+ float *x, float *y) const
+ {
+ *x = *y = 0;
+ switch (u.format) {
+ case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
+ case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
+ case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
+ default: return;
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ switch (u.format) {
+ case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+ case 2:
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ {
+ // AnchorFormat 2 just containins extra hinting information, so
+ // if hints are being dropped convert to format 1.
+ return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+ }
+ return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
+ case 3: return_trace (u.format3.subset (c));
+ default:return_trace (false);
+ }
+ }
+
+ 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;
+ }
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHOR_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat1.hh
new file mode 100644
index 0000000000..738cc31bbf
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat1.hh
@@ -0,0 +1,46 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ public:
+ DEFINE_SIZE_STATIC (6);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+ float *x, float *y) const
+ {
+ hb_font_t *font = c->font;
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+ }
+
+ AnchorFormat1* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ AnchorFormat1* out = c->embed<AnchorFormat1> (this);
+ if (!out) return_trace (out);
+ out->format = 1;
+ return_trace (out);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat2.hh
new file mode 100644
index 0000000000..70b4d19f53
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat2.hh
@@ -0,0 +1,58 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat2
+{
+
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ HBUINT16 anchorPoint; /* Index to glyph contour point */
+ public:
+ DEFINE_SIZE_STATIC (8);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+ float *x, float *y) const
+ {
+ hb_font_t *font = c->font;
+
+#ifdef HB_NO_HINTING
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+ return;
+#endif
+
+ unsigned int x_ppem = font->x_ppem;
+ unsigned int y_ppem = font->y_ppem;
+ hb_position_t cx = 0, cy = 0;
+ bool ret;
+
+ ret = (x_ppem || y_ppem) &&
+ font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+ *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
+ *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
+ }
+
+ AnchorFormat2* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed<AnchorFormat2> (this));
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHORFORMAT2_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
new file mode 100644
index 0000000000..e7e3c5c6d1
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh
@@ -0,0 +1,100 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat3
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 3 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ Offset16To<Device>
+ xDeviceTable; /* Offset to Device table for X
+ * coordinate-- from beginning of
+ * Anchor table (may be NULL) */
+ Offset16To<Device>
+ yDeviceTable; /* Offset to Device table for Y
+ * coordinate-- from beginning of
+ * Anchor table (may be NULL) */
+ public:
+ DEFINE_SIZE_STATIC (10);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+ float *x, float *y) const
+ {
+ hb_font_t *font = c->font;
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+
+ if (font->x_ppem || font->num_coords)
+ *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
+ if (font->y_ppem || font->num_coords)
+ *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
+ }
+
+ 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 (unlikely (!c->serializer->embed (format))) return_trace (false);
+ if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
+ if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
+
+ 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))
+ {
+ 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,
+ HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+ }
+ }
+
+ 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))
+ {
+ 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,
+ HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+ }
+ }
+
+ if (c->plan->all_axes_pinned)
+ return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
+
+ 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);
+ return_trace (out);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ (this+xDeviceTable).collect_variation_indices (c);
+ (this+yDeviceTable).collect_variation_indices (c);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh
new file mode 100644
index 0000000000..c442efa1ea
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh
@@ -0,0 +1,77 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORMATRIX_HH
+#define OT_LAYOUT_GPOS_ANCHORMATRIX_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorMatrix
+{
+ HBUINT16 rows; /* Number of rows */
+ UnsizedArrayOf<Offset16To<Anchor>>
+ matrixZ; /* Matrix of offsets to Anchor tables--
+ * from beginning of AnchorMatrix table */
+ public:
+ DEFINE_SIZE_ARRAY (2, matrixZ);
+
+ bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
+ {
+ TRACE_SANITIZE (this);
+ if (!c->check_struct (this)) return_trace (false);
+ if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
+ unsigned int count = rows * cols;
+ if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
+ for (unsigned int i = 0; i < count; i++)
+ if (!matrixZ[i].sanitize (c, this)) return_trace (false);
+ return_trace (true);
+ }
+
+ const Anchor& get_anchor (unsigned int row, unsigned int col,
+ unsigned int cols, bool *found) const
+ {
+ *found = false;
+ if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
+ *found = !matrixZ[row * cols + col].is_null ();
+ return this+matrixZ[row * cols + col];
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ Iterator index_iter) const
+ {
+ for (unsigned i : index_iter)
+ (this+matrixZ[i]).collect_variation_indices (c);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ unsigned num_rows,
+ Iterator index_iter) const
+ {
+ TRACE_SUBSET (this);
+
+ auto *out = c->serializer->start_embed (this);
+
+ if (!index_iter) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ out->rows = num_rows;
+ for (const unsigned i : index_iter)
+ {
+ auto *offset = c->serializer->embed (matrixZ[i]);
+ if (!offset) return_trace (false);
+ offset->serialize_subset (c, matrixZ[i], this);
+ }
+
+ return_trace (true);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_ANCHORMATRIX_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ChainContextPos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ChainContextPos.hh
new file mode 100644
index 0000000000..d551ac2a2b
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ChainContextPos.hh
@@ -0,0 +1,14 @@
+#ifndef OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
+#define OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ChainContextPos : ChainContext {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Common.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Common.hh
new file mode 100644
index 0000000000..408197454f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Common.hh
@@ -0,0 +1,33 @@
+#ifndef OT_LAYOUT_GPOS_COMMON_HH
+#define OT_LAYOUT_GPOS_COMMON_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+enum attach_type_t {
+ ATTACH_TYPE_NONE = 0X00,
+
+ /* Each attachment should be either a mark or a cursive; can't be both. */
+ ATTACH_TYPE_MARK = 0X01,
+ ATTACH_TYPE_CURSIVE = 0X02,
+};
+
+/* buffer **position** var allocations */
+#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
+#define attach_type() var.u8[2] /* attachment type */
+/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
+
+template<typename Iterator, typename SrcLookup>
+static void SinglePos_serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
+ bool all_axes_pinned);
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_COMMON_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ContextPos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ContextPos.hh
new file mode 100644
index 0000000000..2a01eaa3a6
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ContextPos.hh
@@ -0,0 +1,14 @@
+#ifndef OT_LAYOUT_GPOS_CONTEXTPOS_HH
+#define OT_LAYOUT_GPOS_CONTEXTPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ContextPos : Context {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CONTEXTPOS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh
new file mode 100644
index 0000000000..0105a9b854
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh
@@ -0,0 +1,35 @@
+#ifndef OT_LAYOUT_GPOS_CURSIVEPOS_HH
+#define OT_LAYOUT_GPOS_CURSIVEPOS_HH
+
+#include "CursivePosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct CursivePos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ CursivePosFormat1 format1;
+ } u;
+
+ public:
+ 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)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CURSIVEPOS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
new file mode 100644
index 0000000000..ff255e090a
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
@@ -0,0 +1,301 @@
+#ifndef OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
+
+#include "Anchor.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct EntryExitRecord
+{
+ friend struct CursivePosFormat1;
+
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const void *src_base) const
+ {
+ (src_base+entryAnchor).collect_variation_indices (c);
+ (src_base+exitAnchor).collect_variation_indices (c);
+ }
+
+ EntryExitRecord* subset (hb_subset_context_t *c,
+ const void *src_base) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
+ out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
+ return_trace (out);
+ }
+
+ protected:
+ Offset16To<Anchor>
+ entryAnchor; /* Offset to EntryAnchor table--from
+ * beginning of CursivePos
+ * subtable--may be NULL */
+ Offset16To<Anchor>
+ exitAnchor; /* Offset to ExitAnchor table--from
+ * beginning of CursivePos
+ * subtable--may be NULL */
+ public:
+ DEFINE_SIZE_STATIC (4);
+};
+
+static void
+reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) {
+ int chain = pos[i].attach_chain(), type = pos[i].attach_type();
+ if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
+ return;
+
+ pos[i].attach_chain() = 0;
+
+ unsigned int j = (int) i + chain;
+
+ /* Stop if we see new parent in the chain. */
+ if (j == new_parent)
+ return;
+
+ reverse_cursive_minor_offset (pos, j, direction, new_parent);
+
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ pos[j].y_offset = -pos[i].y_offset;
+ else
+ pos[j].x_offset = -pos[i].x_offset;
+
+ pos[j].attach_chain() = -chain;
+ pos[j].attach_type() = type;
+}
+
+
+struct CursivePosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ Array16Of<EntryExitRecord>
+ entryExitRecord; /* Array of EntryExit records--in
+ * Coverage Index order */
+ public:
+ DEFINE_SIZE_ARRAY (6, entryExitRecord);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+coverage, entryExitRecord)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+
+ const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
+ if (!this_record.entryAnchor) return_trace (false);
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
+ if (!prev_record.exitAnchor)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ unsigned int i = skippy_iter.idx;
+ unsigned int j = buffer->idx;
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "cursive attaching glyph at %u to glyph at %u",
+ i, j);
+ }
+
+ buffer->unsafe_to_break (i, j + 1);
+ float entry_x, entry_y, exit_x, exit_y;
+ (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
+ (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
+
+ hb_glyph_position_t *pos = buffer->pos;
+
+ hb_position_t d;
+ /* Main-direction adjustment */
+ switch (c->direction) {
+ case HB_DIRECTION_LTR:
+ pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
+
+ d = roundf (entry_x) + pos[j].x_offset;
+ pos[j].x_advance -= d;
+ pos[j].x_offset -= d;
+ break;
+ case HB_DIRECTION_RTL:
+ d = roundf (exit_x) + pos[i].x_offset;
+ pos[i].x_advance -= d;
+ pos[i].x_offset -= d;
+
+ pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
+ break;
+ case HB_DIRECTION_TTB:
+ pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
+
+ d = roundf (entry_y) + pos[j].y_offset;
+ pos[j].y_advance -= d;
+ pos[j].y_offset -= d;
+ break;
+ case HB_DIRECTION_BTT:
+ d = roundf (exit_y) + pos[i].y_offset;
+ pos[i].y_advance -= d;
+ pos[i].y_offset -= d;
+
+ pos[j].y_advance = roundf (entry_y);
+ break;
+ case HB_DIRECTION_INVALID:
+ default:
+ break;
+ }
+
+ /* Cross-direction adjustment */
+
+ /* We attach child to parent (think graph theory and rooted trees whereas
+ * the root stays on baseline and each node aligns itself against its
+ * parent.
+ *
+ * Optimize things for the case of RightToLeft, as that's most common in
+ * Arabic. */
+ unsigned int child = i;
+ unsigned int parent = j;
+ hb_position_t x_offset = entry_x - exit_x;
+ hb_position_t y_offset = entry_y - exit_y;
+ if (!(c->lookup_props & LookupFlag::RightToLeft))
+ {
+ unsigned int k = child;
+ child = parent;
+ parent = k;
+ x_offset = -x_offset;
+ y_offset = -y_offset;
+ }
+
+ /* If child was already connected to someone else, walk through its old
+ * chain and reverse the link direction, such that the whole tree of its
+ * previous connection now attaches to new parent. Watch out for case
+ * where new parent is on the path from old chain...
+ */
+ reverse_cursive_minor_offset (pos, child, c->direction, parent);
+
+ pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
+ pos[child].attach_chain() = (int) parent - (int) child;
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
+ pos[child].y_offset = y_offset;
+ else
+ pos[child].x_offset = x_offset;
+
+ /* If parent was attached to child, separate them.
+ * https://github.com/harfbuzz/harfbuzz/issues/2469
+ */
+ if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
+ {
+ pos[parent].attach_chain() = 0;
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
+ pos[parent].y_offset = 0;
+ else
+ pos[parent].x_offset = 0;
+ }
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "cursive attached glyph at %u to glyph at %u",
+ i, j);
+ }
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_subset_context_t *c,
+ Iterator it,
+ const void *src_base)
+ {
+ if (unlikely (!c->serializer->extend_min ((*this)))) return;
+ this->format = 1;
+ this->entryExitRecord.len = it.len ();
+
+ for (const EntryExitRecord& entry_record : + it
+ | hb_map (hb_second))
+ entry_record.subset (c, src_base);
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize_serialize (c->serializer, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ auto it =
+ + hb_zip (this+coverage, entryExitRecord)
+ | hb_filter (glyphset, hb_first)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
+ { return hb_pair (glyph_map[p.first], p.second);})
+ ;
+
+ bool ret = bool (it);
+ out->serialize (c, it, this);
+ return_trace (ret);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ExtensionPos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ExtensionPos.hh
new file mode 100644
index 0000000000..d1808adab4
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ExtensionPos.hh
@@ -0,0 +1,17 @@
+#ifndef OT_LAYOUT_GPOS_EXTENSIONPOS_HH
+#define OT_LAYOUT_GPOS_EXTENSIONPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ExtensionPos : Extension<ExtensionPos>
+{
+ typedef struct PosLookupSubTable SubTable;
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_EXTENSIONPOS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh
new file mode 100644
index 0000000000..9493ec987e
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh
@@ -0,0 +1,171 @@
+#ifndef OT_LAYOUT_GPOS_GPOS_HH
+#define OT_LAYOUT_GPOS_GPOS_HH
+
+#include "../../../hb-ot-layout-common.hh"
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+#include "PosLookup.hh"
+
+namespace OT {
+
+using Layout::GPOS_impl::PosLookup;
+
+namespace Layout {
+
+static void
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+ unsigned int len,
+ unsigned int i,
+ hb_direction_t direction,
+ unsigned nesting_level = HB_MAX_NESTING_LEVEL);
+
+/*
+ * GPOS -- Glyph Positioning
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
+ */
+
+struct GPOS : GSUBGPOS
+{
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
+
+ using Lookup = PosLookup;
+
+ const PosLookup& get_lookup (unsigned int i) const
+ { return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
+
+ static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
+ static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
+ static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ hb_subset_layout_context_t l (c, tableTag);
+ return GSUBGPOS::subset<PosLookup> (&l);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (GSUBGPOS::sanitize<PosLookup> (c));
+ }
+
+ HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
+ {
+ if (!c->gpos_lookups->has (i)) continue;
+ const PosLookup &l = get_lookup (i);
+ l.dispatch (c);
+ }
+ }
+
+ void closure_lookups (hb_face_t *face,
+ const hb_set_t *glyphs,
+ hb_set_t *lookup_indexes /* IN/OUT */) const
+ { GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); }
+
+ typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
+};
+
+
+static void
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+ unsigned int len,
+ unsigned int i,
+ hb_direction_t direction,
+ unsigned nesting_level)
+{
+ /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
+ * offset of glyph they are attached to. */
+ int chain = pos[i].attach_chain(), type = pos[i].attach_type();
+ if (likely (!chain))
+ return;
+
+ pos[i].attach_chain() = 0;
+
+ unsigned int j = (int) i + chain;
+
+ if (unlikely (j >= len))
+ return;
+
+ if (unlikely (!nesting_level))
+ return;
+
+ propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1);
+
+ assert (!!(type & GPOS_impl::ATTACH_TYPE_MARK) ^ !!(type & GPOS_impl::ATTACH_TYPE_CURSIVE));
+
+ if (type & GPOS_impl::ATTACH_TYPE_CURSIVE)
+ {
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ pos[i].y_offset += pos[j].y_offset;
+ else
+ pos[i].x_offset += pos[j].x_offset;
+ }
+ else /*if (type & GPOS_impl::ATTACH_TYPE_MARK)*/
+ {
+ pos[i].x_offset += pos[j].x_offset;
+ pos[i].y_offset += pos[j].y_offset;
+
+ assert (j < i);
+ if (HB_DIRECTION_IS_FORWARD (direction))
+ for (unsigned int k = j; k < i; k++) {
+ pos[i].x_offset -= pos[k].x_advance;
+ pos[i].y_offset -= pos[k].y_advance;
+ }
+ else
+ for (unsigned int k = j + 1; k < i + 1; k++) {
+ pos[i].x_offset += pos[k].x_advance;
+ pos[i].y_offset += pos[k].y_advance;
+ }
+ }
+}
+
+void
+GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
+{
+ unsigned int count = buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
+}
+
+void
+GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
+{
+ //_hb_buffer_assert_gsubgpos_vars (buffer);
+}
+
+void
+GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
+{
+ _hb_buffer_assert_gsubgpos_vars (buffer);
+
+ unsigned int len;
+ hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
+ hb_direction_t direction = buffer->props.direction;
+
+ /* Handle attachments */
+ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
+ for (unsigned i = 0; i < len; i++)
+ propagate_attachment_offsets (pos, len, i, direction);
+
+ if (unlikely (font->slant))
+ {
+ for (unsigned i = 0; i < len; i++)
+ if (unlikely (pos[i].y_offset))
+ pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset);
+ }
+}
+
+}
+
+struct GPOS_accelerator_t : Layout::GPOS::accelerator_t {
+ GPOS_accelerator_t (hb_face_t *face) : Layout::GPOS::accelerator_t (face) {}
+};
+
+}
+
+#endif /* OT_LAYOUT_GPOS_GPOS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh
new file mode 100644
index 0000000000..a2d807cc32
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh
@@ -0,0 +1,56 @@
+#ifndef OT_LAYOUT_GPOS_LIGATUREARRAY_HH
+#define OT_LAYOUT_GPOS_LIGATUREARRAY_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+typedef AnchorMatrix LigatureAttach; /* component-major--
+ * in order of writing direction--,
+ * mark-minor--
+ * ordered by class--zero-based. */
+
+/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
+struct LigatureArray : List16OfOffset16To<LigatureAttach>
+{
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ Iterator coverage,
+ unsigned class_count,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ for (const auto _ : + hb_zip (coverage, *this)
+ | hb_filter (glyphset, hb_first))
+ {
+ auto *matrix = out->serialize_append (c->serializer);
+ if (unlikely (!matrix)) return_trace (false);
+
+ const LigatureAttach& src = (this + _.second);
+ auto indexes =
+ + hb_range (src.rows * class_count)
+ | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
+ ;
+ matrix->serialize_subset (c,
+ _.second,
+ this,
+ src.rows,
+ indexes);
+ }
+ return_trace (this->len);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_LIGATUREARRAY_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
new file mode 100644
index 0000000000..ff43ffb8c5
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
@@ -0,0 +1,128 @@
+#ifndef OT_LAYOUT_GPOS_MARKARRAY_HH
+#define OT_LAYOUT_GPOS_MARKARRAY_HH
+
+#include "AnchorMatrix.hh"
+#include "MarkRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
+{
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (Array16Of<MarkRecord>::sanitize (c, this));
+ }
+
+ bool apply (hb_ot_apply_context_t *c,
+ unsigned int mark_index, unsigned int glyph_index,
+ const AnchorMatrix &anchors, unsigned int class_count,
+ unsigned int glyph_pos) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
+ unsigned int mark_class = record.klass;
+
+ const Anchor& mark_anchor = this + record.markAnchor;
+ bool found;
+ const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
+ /* If this subtable doesn't have an anchor for this base and this class,
+ * return false such that the subsequent subtables have a chance at it. */
+ if (unlikely (!found)) return_trace (false);
+
+ float mark_x, mark_y, base_x, base_y;
+
+ buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
+ mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
+ glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "attaching mark glyph at %u to glyph at %u",
+ c->buffer->idx, glyph_pos);
+ }
+
+ hb_glyph_position_t &o = buffer->cur_pos();
+ o.x_offset = roundf (base_x - mark_x);
+ o.y_offset = roundf (base_y - mark_y);
+ o.attach_type() = ATTACH_TYPE_MARK;
+ o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "attached mark glyph at %u to glyph at %u",
+ c->buffer->idx, glyph_pos);
+ }
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ Iterator coverage,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+ auto* out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ auto mark_iter =
+ + hb_zip (coverage, this->iter ())
+ | hb_filter (glyphset, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ unsigned new_length = 0;
+ for (const auto& mark_record : mark_iter) {
+ if (unlikely (!mark_record.subset (c, this, klass_mapping)))
+ return_trace (false);
+ new_length++;
+ }
+
+ if (unlikely (!c->serializer->check_assign (out->len, new_length,
+ HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
+ return_trace (false);
+
+ return_trace (true);
+ }
+};
+
+HB_INTERNAL inline
+void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
+ const MarkArray &mark_array,
+ const hb_set_t &glyphset,
+ hb_map_t* klass_mapping /* INOUT */)
+{
+ hb_set_t orig_classes;
+
+ + hb_zip (mark_coverage, mark_array)
+ | hb_filter (glyphset, hb_first)
+ | hb_map (hb_second)
+ | hb_map (&MarkRecord::get_class)
+ | hb_sink (orig_classes)
+ ;
+
+ unsigned idx = 0;
+ for (auto klass : orig_classes.iter ())
+ {
+ if (klass_mapping->has (klass)) continue;
+ klass_mapping->set (klass, idx);
+ idx++;
+ }
+}
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh
new file mode 100644
index 0000000000..cd2fc7ccfd
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh
@@ -0,0 +1,41 @@
+#ifndef OT_LAYOUT_GPOS_MARKBASEPOS_HH
+#define OT_LAYOUT_GPOS_MARKBASEPOS_HH
+
+#include "MarkBasePosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkBasePos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkBasePosFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BEYOND_64K
+ MarkBasePosFormat1_2<MediumTypes> format2;
+#endif
+ } u;
+
+ public:
+ 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)...));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKBASEPOS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
new file mode 100644
index 0000000000..eb4712049b
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
@@ -0,0 +1,244 @@
+#ifndef OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
+
+#include "MarkArray.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef AnchorMatrix BaseArray; /* base-major--
+ * in order of BaseCoverage Index--,
+ * mark-minor--
+ * ordered by class--zero-based. */
+
+template <typename Types>
+struct MarkBasePosFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ markCoverage; /* Offset to MarkCoverage table--from
+ * beginning of MarkBasePos subtable */
+ typename Types::template OffsetTo<Coverage>
+ baseCoverage; /* Offset to BaseCoverage table--from
+ * beginning of MarkBasePos subtable */
+ HBUINT16 classCount; /* Number of classes defined for marks */
+ typename Types::template OffsetTo<MarkArray>
+ markArray; /* Offset to MarkArray table--from
+ * beginning of MarkBasePos subtable */
+ typename Types::template OffsetTo<BaseArray>
+ baseArray; /* Offset to BaseArray table--from
+ * beginning of MarkBasePos subtable */
+
+ public:
+ DEFINE_SIZE_STATIC (4 + 4 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ markCoverage.sanitize (c, this) &&
+ baseCoverage.sanitize (c, this) &&
+ markArray.sanitize (c, this) &&
+ baseArray.sanitize (c, this, (unsigned int) classCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+markCoverage).intersects (glyphs) &&
+ (this+baseCoverage).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
+ ;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
+
+ unsigned basecount = (this+baseArray).rows;
+ auto base_iter =
+ + hb_zip (this+baseCoverage, hb_range (basecount))
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ hb_sorted_vector_t<unsigned> base_indexes;
+ for (const unsigned row : base_iter)
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (base_indexes)
+ ;
+ }
+ (this+baseArray).collect_variation_indices (c, base_indexes.iter ());
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+markCoverage; }
+
+ 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);
+ hb_buffer_t *buffer = c->buffer;
+ 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.
+ * 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.set_lookup_props (LookupFlag::IgnoreMarks);
+
+ 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)
+ {
+ 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);
+ }
+
+ 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[idx])) { return_trace (false); }
+
+ unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[idx].codepoint);
+ if (base_index == NOT_COVERED)
+ {
+ 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, idx));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark_iter =
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + mark_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ out->markArray.serialize_subset (c, markArray, this,
+ (this+markCoverage).iter (),
+ &klass_mapping);
+
+ unsigned basecount = (this+baseArray).rows;
+ auto base_iter =
+ + hb_zip (this+baseCoverage, hb_range (basecount))
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ new_coverage.reset ();
+ + base_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ hb_sorted_vector_t<unsigned> base_indexes;
+ for (const unsigned row : + base_iter
+ | hb_map (hb_second))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (base_indexes)
+ ;
+ }
+
+ out->baseArray.serialize_subset (c, baseArray, this,
+ base_iter.len (),
+ base_indexes.iter ());
+
+ return_trace (true);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh
new file mode 100644
index 0000000000..739c325411
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh
@@ -0,0 +1,41 @@
+#ifndef OT_LAYOUT_GPOS_MARKLIGPOS_HH
+#define OT_LAYOUT_GPOS_MARKLIGPOS_HH
+
+#include "MarkLigPosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkLigPos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkLigPosFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BEYOND_64K
+ MarkLigPosFormat1_2<MediumTypes> format2;
+#endif
+ } u;
+
+ public:
+ 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)...));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKLIGPOS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
new file mode 100644
index 0000000000..7e7b438aa7
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
@@ -0,0 +1,223 @@
+#ifndef OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
+
+#include "LigatureArray.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct MarkLigPosFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ markCoverage; /* Offset to Mark Coverage table--from
+ * beginning of MarkLigPos subtable */
+ typename Types::template OffsetTo<Coverage>
+ ligatureCoverage; /* Offset to Ligature Coverage
+ * table--from beginning of MarkLigPos
+ * subtable */
+ HBUINT16 classCount; /* Number of defined mark classes */
+ typename Types::template OffsetTo<MarkArray>
+ markArray; /* Offset to MarkArray table--from
+ * beginning of MarkLigPos subtable */
+ typename Types::template OffsetTo<LigatureArray>
+ ligatureArray; /* Offset to LigatureArray table--from
+ * beginning of MarkLigPos subtable */
+ public:
+ DEFINE_SIZE_STATIC (4 + 4 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ markCoverage.sanitize (c, this) &&
+ ligatureCoverage.sanitize (c, this) &&
+ markArray.sanitize (c, this) &&
+ ligatureArray.sanitize (c, this, (unsigned int) classCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+markCoverage).intersects (glyphs) &&
+ (this+ligatureCoverage).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
+ ;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
+
+ unsigned ligcount = (this+ligatureArray).len;
+ auto lig_iter =
+ + hb_zip (this+ligatureCoverage, hb_range (ligcount))
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ const LigatureArray& lig_array = this+ligatureArray;
+ for (const unsigned i : lig_iter)
+ {
+ hb_sorted_vector_t<unsigned> lig_indexes;
+ unsigned row_count = lig_array[i].rows;
+ for (unsigned row : + hb_range (row_count))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (lig_indexes)
+ ;
+ }
+
+ lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
+ }
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+markCoverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ 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 */
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
+
+ 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)
+ {
+ 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[j])) { return_trace (false); }
+
+ unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
+ if (lig_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ const LigatureArray& lig_array = this+ligatureArray;
+ const LigatureAttach& lig_attach = lig_array[lig_index];
+
+ /* Find component to attach to */
+ unsigned int comp_count = lig_attach.rows;
+ if (unlikely (!comp_count))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ /* We must now check whether the ligature ID of the current mark glyph
+ * is identical to the ligature ID of the found ligature. If yes, we
+ * can directly use the component index. If not, we attach the mark
+ * glyph to the last component of the ligature. */
+ unsigned int comp_index;
+ unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
+ unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+ unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+ if (lig_id && lig_id == mark_id && mark_comp > 0)
+ comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
+ else
+ comp_index = comp_count - 1;
+
+ return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark_iter =
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ auto new_mark_coverage =
+ + mark_iter
+ | hb_map_retains_sorting (hb_first)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
+ return_trace (false);
+
+ out->markArray.serialize_subset (c, markArray, this,
+ (this+markCoverage).iter (),
+ &klass_mapping);
+
+ auto new_ligature_coverage =
+ + hb_iter (this + ligatureCoverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
+ return_trace (false);
+
+ out->ligatureArray.serialize_subset (c, ligatureArray, this,
+ hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
+
+ return_trace (true);
+ }
+
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh
new file mode 100644
index 0000000000..cddd2a3d50
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh
@@ -0,0 +1,42 @@
+#ifndef OT_LAYOUT_GPOS_MARKMARKPOS_HH
+#define OT_LAYOUT_GPOS_MARKMARKPOS_HH
+
+#include "MarkMarkPosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkMarkPos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkMarkPosFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BEYOND_64K
+ MarkMarkPosFormat1_2<MediumTypes> format2;
+#endif
+ } u;
+
+ public:
+ 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)...));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKMARKPOS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
new file mode 100644
index 0000000000..fbcebb8044
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
@@ -0,0 +1,228 @@
+#ifndef OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
+
+#include "MarkMarkPosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef AnchorMatrix Mark2Array; /* mark2-major--
+ * in order of Mark2Coverage Index--,
+ * mark1-minor--
+ * ordered by class--zero-based. */
+
+template <typename Types>
+struct MarkMarkPosFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ mark1Coverage; /* Offset to Combining Mark1 Coverage
+ * table--from beginning of MarkMarkPos
+ * subtable */
+ typename Types::template OffsetTo<Coverage>
+ mark2Coverage; /* Offset to Combining Mark2 Coverage
+ * table--from beginning of MarkMarkPos
+ * subtable */
+ HBUINT16 classCount; /* Number of defined mark classes */
+ typename Types::template OffsetTo<MarkArray>
+ mark1Array; /* Offset to Mark1Array table--from
+ * beginning of MarkMarkPos subtable */
+ typename Types::template OffsetTo<Mark2Array>
+ mark2Array; /* Offset to Mark2Array table--from
+ * beginning of MarkMarkPos subtable */
+ public:
+ DEFINE_SIZE_STATIC (4 + 4 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ mark1Coverage.sanitize (c, this) &&
+ mark2Coverage.sanitize (c, this) &&
+ mark1Array.sanitize (c, this) &&
+ mark2Array.sanitize (c, this, (unsigned int) classCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+mark1Coverage).intersects (glyphs) &&
+ (this+mark2Coverage).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+mark1Coverage, this+mark1Array)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
+ ;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
+
+ unsigned mark2_count = (this+mark2Array).rows;
+ auto mark2_iter =
+ + hb_zip (this+mark2Coverage, hb_range (mark2_count))
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ hb_sorted_vector_t<unsigned> mark2_indexes;
+ for (const unsigned row : mark2_iter)
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (mark2_indexes)
+ ;
+ }
+ (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+mark1Coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (mark1_index == NOT_COVERED)) return_trace (false);
+
+ /* now we search backwards for a suitable mark glyph until a non-mark glyph */
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ unsigned int j = skippy_iter.idx;
+
+ unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
+ unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
+ unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
+ unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
+
+ if (likely (id1 == id2))
+ {
+ if (id1 == 0) /* Marks belonging to the same base. */
+ goto good;
+ else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
+ goto good;
+ }
+ else
+ {
+ /* If ligature ids don't match, it may be the case that one of the marks
+ * itself is a ligature. In which case match. */
+ if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
+ goto good;
+ }
+
+ /* Didn't match. */
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+
+ good:
+ unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
+ if (mark2_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark1_iter =
+ + hb_zip (this+mark1Coverage, this+mark1Array)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + mark1_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ out->mark1Array.serialize_subset (c, mark1Array, this,
+ (this+mark1Coverage).iter (),
+ &klass_mapping);
+
+ unsigned mark2count = (this+mark2Array).rows;
+ auto mark2_iter =
+ + hb_zip (this+mark2Coverage, hb_range (mark2count))
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ new_coverage.reset ();
+ + mark2_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ hb_sorted_vector_t<unsigned> mark2_indexes;
+ for (const unsigned row : + mark2_iter
+ | hb_map (hb_second))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (mark2_indexes)
+ ;
+ }
+
+ out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
+
+ return_trace (true);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh
new file mode 100644
index 0000000000..a7d489d2a5
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh
@@ -0,0 +1,52 @@
+#ifndef OT_LAYOUT_GPOS_MARKRECORD_HH
+#define OT_LAYOUT_GPOS_MARKRECORD_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkRecord
+{
+ friend struct MarkArray;
+
+ public:
+ HBUINT16 klass; /* Class defined for this mark */
+ Offset16To<Anchor>
+ markAnchor; /* Offset to Anchor table--from
+ * beginning of MarkArray table */
+ public:
+ DEFINE_SIZE_STATIC (4);
+
+ unsigned get_class () const { return (unsigned) klass; }
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
+ }
+
+ MarkRecord *subset (hb_subset_context_t *c,
+ const void *src_base,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->klass = klass_mapping->get (klass);
+ out->markAnchor.serialize_subset (c, markAnchor, src_base);
+ return_trace (out);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const void *src_base) const
+ {
+ (src_base+markAnchor).collect_variation_indices (c);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKRECORD_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh
new file mode 100644
index 0000000000..c13d4f4894
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh
@@ -0,0 +1,46 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOS_HH
+#define OT_LAYOUT_GPOS_PAIRPOS_HH
+
+#include "PairPosFormat1.hh"
+#include "PairPosFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PairPos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ PairPosFormat1_3<SmallTypes> format1;
+ PairPosFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BEYOND_64K
+ PairPosFormat1_3<MediumTypes> format3;
+ PairPosFormat2_4<MediumTypes> format4;
+#endif
+ } u;
+
+ public:
+ 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)...));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRPOS_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
new file mode 100644
index 0000000000..b4a9a9ad53
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
@@ -0,0 +1,217 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
+
+#include "PairSet.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct PairPosFormat1_3
+{
+ using PairSet = GPOS_impl::PairSet<Types>;
+ using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
+
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat[2]; /* [0] Defines the types of data in
+ * ValueRecord1--for the first glyph
+ * in the pair--may be zero (0) */
+ /* [1] Defines the types of data in
+ * ValueRecord2--for the second glyph
+ * in the pair--may be zero (0) */
+ Array16Of<typename Types::template OffsetTo<PairSet>>
+ pairSet; /* Array of PairSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (8 + Types::size, pairSet);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+
+ if (!c->check_struct (this)) return_trace (false);
+
+ unsigned int len1 = valueFormat[0].get_len ();
+ unsigned int len2 = valueFormat[1].get_len ();
+ typename PairSet::sanitize_closure_t closure =
+ {
+ valueFormat,
+ len1,
+ PairSet::get_size (len1, len2)
+ };
+
+ return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ auto &cov = this+coverage;
+
+ if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
+ {
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ {
+ unsigned i = cov.get_coverage (g);
+ if ((this+pairSet[i]).intersects (glyphs, valueFormat))
+ return true;
+ }
+ return false;
+ }
+
+ return
+ + hb_zip (cov, pairSet)
+ | hb_filter (*glyphs, hb_first)
+ | hb_map (hb_second)
+ | hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
+ { return (this+_).intersects (glyphs, valueFormat); })
+ | hb_any
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
+
+ auto it =
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ if (!it) return;
+ + it
+ | hb_map (hb_add (this))
+ | hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ unsigned int count = pairSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ (this+pairSet[i]).collect_glyphs (c, valueFormat);
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ buffer->unsafe_to_concat (buffer->idx, unsafe_to);
+ return_trace (false);
+ }
+
+ return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+ out->valueFormat[0] = valueFormat[0];
+ out->valueFormat[1] = valueFormat[1];
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ {
+ hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
+ out->valueFormat[0] = newFormats.first;
+ out->valueFormat[1] = newFormats.second;
+ }
+
+ if (c->plan->all_axes_pinned)
+ {
+ out->valueFormat[0] = out->valueFormat[0].drop_device_table_flags ();
+ out->valueFormat[1] = out->valueFormat[1].drop_device_table_flags ();
+ }
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter ([this, c, out] (const typename Types::template OffsetTo<PairSet>& _)
+ {
+ auto snap = c->serializer->snapshot ();
+ auto *o = out->pairSet.serialize_append (c->serializer);
+ if (unlikely (!o)) return false;
+ bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
+ if (!ret)
+ {
+ out->pairSet.pop ();
+ c->serializer->revert (snap);
+ }
+ return ret;
+ },
+ 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));
+ }
+
+
+ hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
+ {
+ unsigned record_size = PairSet::get_size (valueFormat);
+
+ unsigned format1 = 0;
+ unsigned format2 = 0;
+ for (const auto & _ :
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (glyphset, hb_first)
+ | hb_map (hb_second)
+ )
+ {
+ const PairSet& set = (this + _);
+ const PairValueRecord *record = &set.firstPairValueRecord;
+
+ unsigned count = set.len;
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (record->intersects (glyphset))
+ {
+ format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
+ format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
+ }
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+
+ if (format1 == valueFormat[0] && format2 == valueFormat[1])
+ break;
+ }
+
+ return hb_pair (format1, format2);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
new file mode 100644
index 0000000000..de15a29e3c
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
@@ -0,0 +1,351 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
+#define OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
+
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+template <typename Types>
+struct PairPosFormat2_4
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ typename Types::template OffsetTo<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat1; /* ValueRecord definition--for the
+ * first glyph of the pair--may be zero
+ * (0) */
+ ValueFormat valueFormat2; /* ValueRecord definition--for the
+ * second glyph of the pair--may be
+ * zero (0) */
+ typename Types::template OffsetTo<ClassDef>
+ classDef1; /* Offset to ClassDef table--from
+ * beginning of PairPos subtable--for
+ * the first glyph of the pair */
+ typename Types::template OffsetTo<ClassDef>
+ classDef2; /* Offset to ClassDef table--from
+ * beginning of PairPos subtable--for
+ * the second glyph of the pair */
+ HBUINT16 class1Count; /* Number of classes in ClassDef1
+ * table--includes Class0 */
+ HBUINT16 class2Count; /* Number of classes in ClassDef2
+ * table--includes Class0 */
+ ValueRecord values; /* Matrix of value pairs:
+ * class1-major, class2-minor,
+ * Each entry has value1 and value2 */
+ public:
+ DEFINE_SIZE_ARRAY (10 + 3 * Types::size, values);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!(c->check_struct (this)
+ && coverage.sanitize (c, this)
+ && classDef1.sanitize (c, this)
+ && classDef2.sanitize (c, this))) return_trace (false);
+
+ unsigned int len1 = valueFormat1.get_len ();
+ unsigned int len2 = valueFormat2.get_len ();
+ 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,
+ count,
+ record_size) &&
+ valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
+ valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+coverage).intersects (glyphs) &&
+ (this+classDef2).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if (!intersects (c->glyph_set)) return;
+ if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
+
+ hb_set_t klass1_glyphs, klass2_glyphs;
+ if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
+ if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
+
+ hb_set_t class1_set, class2_set;
+ for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
+ {
+ if (!klass1_glyphs.has (cp)) class1_set.add (0);
+ else
+ {
+ unsigned klass1 = (this+classDef1).get (cp);
+ class1_set.add (klass1);
+ }
+ }
+
+ class2_set.add (0);
+ for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
+ {
+ unsigned klass2 = (this+classDef2).get (cp);
+ class2_set.add (klass2);
+ }
+
+ if (class1_set.is_empty ()
+ || class2_set.is_empty ()
+ || (class2_set.get_population() == 1 && class2_set.has(0)))
+ return;
+
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+ const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
+ for (const unsigned class1_idx : class1_set.iter ())
+ {
+ for (const unsigned class2_idx : class2_set.iter ())
+ {
+ unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ if (valueFormat1.has_device ())
+ valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
+
+ if (valueFormat2.has_device ())
+ valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
+ }
+ }
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ buffer->unsafe_to_concat (buffer->idx, unsafe_to);
+ return_trace (false);
+ }
+
+ unsigned int len1 = valueFormat1.get_len ();
+ unsigned int len2 = valueFormat2.get_len ();
+ unsigned int record_len = len1 + len2;
+
+ unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
+ unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
+ if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
+ {
+ buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+ return_trace (false);
+ }
+
+ const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
+
+ bool applied_first = false, applied_second = false;
+
+
+ /* Isolate simple kerning and apply it half to each side.
+ * Results in better cursor positinoing / underline drawing.
+ *
+ * Disabled, because causes issues... :-(
+ * https://github.com/harfbuzz/harfbuzz/issues/3408
+ * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978
+ */
+#ifndef HB_SPLIT_KERN
+ if (0)
+#endif
+ {
+ if (!len2)
+ {
+ const hb_direction_t dir = buffer->props.direction;
+ const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
+ const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
+ unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
+ if (backward)
+ mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
+ /* Add Devices. */
+ mask |= mask << 4;
+
+ if (valueFormat1 & ~mask)
+ goto bail;
+
+ /* Is simple kern. Apply value on an empty position slot,
+ * then split it between sides. */
+
+ hb_glyph_position_t pos{};
+ if (valueFormat1.apply_value (c, this, v, pos))
+ {
+ hb_position_t *src = &pos.x_advance;
+ hb_position_t *dst1 = &buffer->cur_pos().x_advance;
+ hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
+ unsigned i = horizontal ? 0 : 1;
+
+ hb_position_t kern = src[i];
+ hb_position_t kern1 = kern >> 1;
+ hb_position_t kern2 = kern - kern1;
+
+ if (!backward)
+ {
+ dst1[i] += kern1;
+ dst2[i] += kern2;
+ dst2[i + 2] += kern2;
+ }
+ else
+ {
+ dst1[i] += kern1;
+ dst1[i + 2] += src[i + 2] - kern2;
+ dst2[i] += kern2;
+ }
+
+ applied_first = applied_second = kern != 0;
+ goto success;
+ }
+ goto boring;
+ }
+ }
+ bail:
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "try kerning glyphs at %u,%u",
+ c->buffer->idx, skippy_iter.idx);
+ }
+
+ applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
+ applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+
+ if (applied_first || applied_second)
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "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 %u,%u",
+ c->buffer->idx, skippy_iter.idx);
+ }
+
+ success:
+ if (applied_first || applied_second)
+ buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
+ else
+ boring:
+ buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+
+ if (len2)
+ {
+ skippy_iter.idx++;
+ // https://github.com/harfbuzz/harfbuzz/issues/3824
+ // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
+ buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
+ }
+
+ buffer->idx = skippy_iter.idx;
+
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass1_map;
+ out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
+ out->class1Count = klass1_map.get_population ();
+
+ hb_map_t klass2_map;
+ out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
+ out->class2Count = klass2_map.get_population ();
+
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+
+ hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ newFormats = compute_effective_value_formats (klass1_map, klass2_map);
+
+ out->valueFormat1 = newFormats.first;
+ out->valueFormat2 = newFormats.second;
+
+ if (c->plan->all_axes_pinned)
+ {
+ out->valueFormat1 = out->valueFormat1.drop_device_table_flags ();
+ out->valueFormat2 = out->valueFormat2.drop_device_table_flags ();
+ }
+
+ for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+ {
+ 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);
+ }
+ }
+
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (this+coverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ out->coverage.serialize_serialize (c->serializer, it);
+ return_trace (out->class1Count && out->class2Count && bool (it));
+ }
+
+
+ hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
+ const hb_map_t& klass2_map) const
+ {
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+ unsigned record_size = len1 + len2;
+
+ unsigned format1 = 0;
+ unsigned format2 = 0;
+
+ for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+ {
+ for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+ {
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_size;
+ format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
+ format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
+ }
+
+ if (format1 == valueFormat1 && format2 == valueFormat2)
+ break;
+ }
+
+ return hb_pair (format1, format2);
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
new file mode 100644
index 0000000000..147b8e00ea
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
@@ -0,0 +1,207 @@
+#ifndef OT_LAYOUT_GPOS_PAIRSET_HH
+#define OT_LAYOUT_GPOS_PAIRSET_HH
+
+#include "PairValueRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct PairSet
+{
+ template <typename Types2>
+ friend struct PairPosFormat1_3;
+
+ using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
+
+ protected:
+ HBUINT16 len; /* Number of PairValueRecords */
+ PairValueRecord firstPairValueRecord;
+ /* Array of PairValueRecords--ordered
+ * by GlyphID of the second glyph */
+ 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; /* bytes */
+ };
+
+ bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
+ {
+ TRACE_SANITIZE (this);
+ if (!(c->check_struct (this)
+ && c->check_range (&firstPairValueRecord,
+ len,
+ closure->stride))) return_trace (false);
+
+ unsigned int count = len;
+ const PairValueRecord *record = &firstPairValueRecord;
+ return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
+ closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
+ }
+
+ bool intersects (const hb_set_t *glyphs,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned record_size = get_size (valueFormats);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (glyphs->has (record->secondGlyph))
+ return true;
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ return false;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned record_size = get_size (valueFormats);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ c->input->add_array (&record->secondGlyph, len, record_size);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned record_size = get_size (valueFormats);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned count = len;
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (c->glyph_set->has (record->secondGlyph))
+ { record->collect_variation_indices (c, valueFormats, this); }
+
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ }
+
+ bool apply (hb_ot_apply_context_t *c,
+ const ValueFormat *valueFormats,
+ unsigned int pos) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int len1 = valueFormats[0].get_len ();
+ unsigned int len2 = valueFormats[1].get_len ();
+ unsigned record_size = get_size (len1, len2);
+
+ const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
+ &firstPairValueRecord,
+ len,
+ record_size);
+ if (record)
+ {
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "try kerning glyphs at %u,%u",
+ c->buffer->idx, pos);
+ }
+
+ bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
+ bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+
+ if (applied_first || applied_second)
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "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 %u,%u",
+ c->buffer->idx, pos);
+ }
+
+ if (applied_first || applied_second)
+ buffer->unsafe_to_break (buffer->idx, pos + 1);
+
+ if (len2)
+ {
+ pos++;
+ // https://github.com/harfbuzz/harfbuzz/issues/3824
+ // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
+ buffer->unsafe_to_break (buffer->idx, pos + 1);
+ }
+
+ buffer->idx = pos;
+ return_trace (true);
+ }
+ buffer->unsafe_to_concat (buffer->idx, pos + 1);
+ return_trace (false);
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const ValueFormat valueFormats[2],
+ const ValueFormat newFormats[2]) const
+ {
+ TRACE_SUBSET (this);
+ auto snap = c->serializer->snapshot ();
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->len = 0;
+
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ unsigned len1 = valueFormats[0].get_len ();
+ unsigned len2 = valueFormats[1].get_len ();
+ unsigned record_size = get_size (len1, len2);
+
+ typename PairValueRecord::context_t context =
+ {
+ this,
+ valueFormats,
+ newFormats,
+ len1,
+ &glyph_map,
+ &c->plan->layout_variation_idx_delta_map
+ };
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned count = len, num = 0;
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (glyphset.has (record->secondGlyph)
+ && record->subset (c, &context)) num++;
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+
+ out->len = num;
+ if (!num) c->serializer->revert (snap);
+ return_trace (num);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRSET_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh
new file mode 100644
index 0000000000..3222477764
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh
@@ -0,0 +1,99 @@
+#ifndef OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
+#define OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
+
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct PairValueRecord
+{
+ template <typename Types2>
+ friend struct PairSet;
+
+ protected:
+ typename Types::HBGlyphID
+ secondGlyph; /* GlyphID of second glyph in the
+ * pair--first glyph is listed in the
+ * Coverage table */
+ ValueRecord values; /* Positioning data for the first glyph
+ * followed by for second glyph */
+ public:
+ DEFINE_SIZE_ARRAY (Types::size, values);
+
+ int cmp (hb_codepoint_t k) const
+ { return secondGlyph.cmp (k); }
+
+ struct context_t
+ {
+ const void *base;
+ const ValueFormat *valueFormats;
+ const ValueFormat *newFormats;
+ unsigned len1; /* valueFormats[0].get_len() */
+ const hb_map_t *glyph_map;
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map;
+ };
+
+ bool subset (hb_subset_context_t *c,
+ context_t *closure) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *s = c->serializer;
+ auto *out = s->start_embed (*this);
+ if (unlikely (!s->extend_min (out))) return_trace (false);
+
+ out->secondGlyph = (*closure->glyph_map)[secondGlyph];
+
+ closure->valueFormats[0].copy_values (s,
+ closure->newFormats[0],
+ closure->base, &values[0],
+ closure->layout_variation_idx_delta_map);
+ closure->valueFormats[1].copy_values (s,
+ closure->newFormats[1],
+ closure->base,
+ &values[closure->len1],
+ closure->layout_variation_idx_delta_map);
+
+ return_trace (true);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const ValueFormat *valueFormats,
+ const void *base) const
+ {
+ unsigned record1_len = valueFormats[0].get_len ();
+ unsigned record2_len = valueFormats[1].get_len ();
+ const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
+
+ if (valueFormats[0].has_device ())
+ valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
+
+ if (valueFormats[1].has_device ())
+ valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
+ }
+
+ bool intersects (const hb_set_t& glyphset) const
+ {
+ return glyphset.has(secondGlyph);
+ }
+
+ const Value* get_values_1 () const
+ {
+ return &values[0];
+ }
+
+ const Value* get_values_2 (ValueFormat format1) const
+ {
+ return &values[format1.get_len ()];
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookup.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookup.hh
new file mode 100644
index 0000000000..c4e57bb543
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookup.hh
@@ -0,0 +1,79 @@
+#ifndef OT_LAYOUT_GPOS_POSLOOKUP_HH
+#define OT_LAYOUT_GPOS_POSLOOKUP_HH
+
+#include "PosLookupSubTable.hh"
+#include "../../../hb-ot-layout-common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PosLookup : Lookup
+{
+ using SubTable = PosLookupSubTable;
+
+ const SubTable& get_subtable (unsigned int i) const
+ { return Lookup::get_subtable<SubTable> (i); }
+
+ bool is_reverse () const
+ {
+ return false;
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ return_trace (dispatch (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c);
+ }
+
+ hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { return dispatch (c); }
+
+ hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
+ {
+ if (c->is_lookup_visited (this_index))
+ return hb_closure_lookups_context_t::default_return_value ();
+
+ c->set_lookup_visited (this_index);
+ if (!intersects (c->glyphs))
+ {
+ c->set_lookup_inactive (this_index);
+ return hb_closure_lookups_context_t::default_return_value ();
+ }
+
+ hb_closure_lookups_context_t::return_t ret = dispatch (c);
+ return ret;
+ }
+
+ template <typename set_t>
+ void collect_coverage (set_t *glyphs) const
+ {
+ hb_collect_coverage_context_t<set_t> c (glyphs);
+ dispatch (&c);
+ }
+
+ template <typename context_t>
+ static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
+
+ bool subset (hb_subset_context_t *c) const
+ { return Lookup::subset<SubTable> (c); }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return Lookup::sanitize<SubTable> (c); }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_POSLOOKUP_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookupSubTable.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookupSubTable.hh
new file mode 100644
index 0000000000..c19fbc323f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookupSubTable.hh
@@ -0,0 +1,79 @@
+#ifndef OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
+#define OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
+
+#include "SinglePos.hh"
+#include "PairPos.hh"
+#include "CursivePos.hh"
+#include "MarkBasePos.hh"
+#include "MarkLigPos.hh"
+#include "MarkMarkPos.hh"
+#include "ContextPos.hh"
+#include "ChainContextPos.hh"
+#include "ExtensionPos.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PosLookupSubTable
+{
+ friend struct ::OT::Lookup;
+ friend struct PosLookup;
+
+ enum Type {
+ Single = 1,
+ Pair = 2,
+ Cursive = 3,
+ MarkBase = 4,
+ MarkLig = 5,
+ MarkMark = 6,
+ Context = 7,
+ ChainContext = 8,
+ Extension = 9
+ };
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, lookup_type);
+ switch (lookup_type) {
+ case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
+ case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
+ case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
+ case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
+ case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
+ case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
+ default: return_trace (c->default_return_value ());
+ }
+ }
+
+ bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c, lookup_type);
+ }
+
+ protected:
+ union {
+ SinglePos single;
+ PairPos pair;
+ CursivePos cursive;
+ MarkBasePos markBase;
+ MarkLigPos markLig;
+ MarkMarkPos markMark;
+ ContextPos context;
+ ChainContextPos chainContext;
+ ExtensionPos extension;
+ } u;
+ public:
+ DEFINE_SIZE_MIN (0);
+};
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh
new file mode 100644
index 0000000000..3af6c49965
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh
@@ -0,0 +1,100 @@
+#ifndef OT_LAYOUT_GPOS_SINGLEPOS_HH
+#define OT_LAYOUT_GPOS_SINGLEPOS_HH
+
+#include "SinglePosFormat1.hh"
+#include "SinglePosFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct SinglePos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ SinglePosFormat1 format1;
+ SinglePosFormat2 format2;
+ } u;
+
+ public:
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ unsigned get_format (Iterator glyph_val_iter_pairs)
+ {
+ hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
+
+ for (const auto iter : glyph_val_iter_pairs)
+ for (const auto _ : hb_zip (iter.second, first_val_iter))
+ if (_.first != _.second)
+ return 2;
+
+ return 1;
+ }
+
+ template<typename Iterator,
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ const SrcLookup* src,
+ Iterator glyph_val_iter_pairs,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
+ bool all_axes_pinned)
+ {
+ if (unlikely (!c->extend_min (u.format))) return;
+ unsigned format = 2;
+ ValueFormat new_format = src->get_value_format ();
+
+ if (all_axes_pinned)
+ new_format = new_format.drop_device_table_flags ();
+
+ if (glyph_val_iter_pairs)
+ format = get_format (glyph_val_iter_pairs);
+
+ u.format = format;
+ switch (u.format) {
+ case 1: u.format1.serialize (c,
+ src,
+ glyph_val_iter_pairs,
+ new_format,
+ layout_variation_idx_delta_map);
+ return;
+ case 2: u.format2.serialize (c,
+ src,
+ glyph_val_iter_pairs,
+ new_format,
+ layout_variation_idx_delta_map);
+ return;
+ default:return;
+ }
+ }
+
+ 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)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+
+template<typename Iterator, typename SrcLookup>
+static void
+SinglePos_serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
+ bool all_axes_pinned)
+{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_delta_map, all_axes_pinned); }
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_SINGLEPOS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
new file mode 100644
index 0000000000..f7a170f34e
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
@@ -0,0 +1,156 @@
+#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
+
+#include "Common.hh"
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct SinglePosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat; /* Defines the types of data in the
+ * ValueRecord */
+ ValueRecord values; /* Defines positioning
+ * value(s)--applied to all glyphs in
+ * the Coverage table */
+ public:
+ DEFINE_SIZE_ARRAY (6, values);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ coverage.sanitize (c, this) &&
+ valueFormat.sanitize_value (c, this, values));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if (!valueFormat.has_device ()) return;
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (*c->glyph_set, intersection);
+ if (!intersection) return;
+
+ valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ ValueFormat get_value_format () const { return valueFormat; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioning glyph at %u",
+ c->buffer->idx);
+ }
+
+ valueFormat.apply_value (c, this, values, buffer->cur_pos());
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioned glyph at %u",
+ c->buffer->idx);
+ }
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ bool
+ position_single (hb_font_t *font,
+ hb_direction_t direction,
+ hb_codepoint_t gid,
+ hb_glyph_position_t &pos) const
+ {
+ unsigned int index = (this+coverage).get_coverage (gid);
+ if (likely (index == NOT_COVERED)) return false;
+
+ /* This is ugly... */
+ hb_buffer_t buffer;
+ buffer.props.direction = direction;
+ OT::hb_ot_apply_context_t c (1, font, &buffer);
+
+ valueFormat.apply_value (&c, this, values, pos);
+ return true;
+ }
+
+ template<typename Iterator,
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ ValueFormat newFormat,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
+ {
+ if (unlikely (!c->extend_min (this))) return;
+ if (unlikely (!c->check_assign (valueFormat,
+ newFormat,
+ HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
+
+ for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
+ {
+ src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map);
+ // Only serialize the first entry in the iterator, the rest are assumed to
+ // be the same.
+ break;
+ }
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize_serialize (c, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (glyphset, intersection);
+
+ auto it =
+ + hb_iter (intersection)
+ | hb_map_retains_sorting (glyph_map)
+ | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
+ ;
+
+ bool ret = bool (it);
+ SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
+ return_trace (ret);
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
new file mode 100644
index 0000000000..e8f2d7c2c6
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
@@ -0,0 +1,176 @@
+#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
+#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct SinglePosFormat2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat; /* Defines the types of data in the
+ * ValueRecord */
+ HBUINT16 valueCount; /* Number of ValueRecords */
+ ValueRecord values; /* Array of ValueRecords--positioning
+ * values applied to glyphs */
+ public:
+ DEFINE_SIZE_ARRAY (8, values);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ coverage.sanitize (c, this) &&
+ valueFormat.sanitize_values (c, this, values, valueCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if (!valueFormat.has_device ()) return;
+
+ auto it =
+ + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
+ | hb_filter (c->glyph_set, hb_first)
+ ;
+
+ if (!it) return;
+
+ unsigned sub_length = valueFormat.get_len ();
+ const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
+
+ for (unsigned i : + it
+ | hb_map (hb_second))
+ valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
+
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ ValueFormat get_value_format () const { return valueFormat; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ if (unlikely (index >= valueCount)) return_trace (false);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioning glyph at %u",
+ c->buffer->idx);
+ }
+
+ valueFormat.apply_value (c, this,
+ &values[index * valueFormat.get_len ()],
+ buffer->cur_pos());
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioned glyph at %u",
+ c->buffer->idx);
+ }
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ bool
+ position_single (hb_font_t *font,
+ hb_direction_t direction,
+ hb_codepoint_t gid,
+ hb_glyph_position_t &pos) const
+ {
+ unsigned int index = (this+coverage).get_coverage (gid);
+ if (likely (index == NOT_COVERED)) return false;
+ if (unlikely (index >= valueCount)) return false;
+
+ /* This is ugly... */
+ hb_buffer_t buffer;
+ buffer.props.direction = direction;
+ OT::hb_ot_apply_context_t c (1, font, &buffer);
+
+ valueFormat.apply_value (&c, this,
+ &values[index * valueFormat.get_len ()],
+ pos);
+ return true;
+ }
+
+
+ template<typename Iterator,
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ ValueFormat newFormat,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
+ {
+ auto out = c->extend_min (this);
+ if (unlikely (!out)) return;
+ if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
+ if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
+
+ + it
+ | hb_map (hb_second)
+ | hb_apply ([&] (hb_array_t<const Value> _)
+ { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map); })
+ ;
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize_serialize (c, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ unsigned sub_length = valueFormat.get_len ();
+ auto values_array = values.as_array (valueCount * sub_length);
+
+ auto it =
+ + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
+ | hb_filter (glyphset, hb_first)
+ | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
+ {
+ return hb_pair (glyph_map[_.first],
+ values_array.sub_array (_.second * sub_length,
+ sub_length));
+ })
+ ;
+
+ bool ret = bool (it);
+ SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
+ return_trace (ret);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
new file mode 100644
index 0000000000..1aa451abcc
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
@@ -0,0 +1,394 @@
+#ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
+#define OT_LAYOUT_GPOS_VALUEFORMAT_HH
+
+#include "../../../hb-ot-layout-gsubgpos.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef HBUINT16 Value;
+
+typedef UnsizedArrayOf<Value> ValueRecord;
+
+struct ValueFormat : HBUINT16
+{
+ enum Flags {
+ xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
+ yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
+ xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
+ yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
+ xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
+ yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
+ xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
+ yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
+ ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
+ reserved = 0xF000u, /* For future use */
+
+ devices = 0x00F0u /* Mask for having any Device table */
+ };
+
+/* All fields are options. Only those available advance the value pointer. */
+#if 0
+ HBINT16 xPlacement; /* Horizontal adjustment for
+ * placement--in design units */
+ HBINT16 yPlacement; /* Vertical adjustment for
+ * placement--in design units */
+ HBINT16 xAdvance; /* Horizontal adjustment for
+ * advance--in design units (only used
+ * for horizontal writing) */
+ HBINT16 yAdvance; /* Vertical adjustment for advance--in
+ * design units (only used for vertical
+ * writing) */
+ Offset16To<Device> xPlaDevice; /* Offset to Device table for
+ * horizontal placement--measured from
+ * beginning of PosTable (may be NULL) */
+ Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
+ * placement--measured from beginning
+ * of PosTable (may be NULL) */
+ Offset16To<Device> xAdvDevice; /* Offset to Device table for
+ * horizontal advance--measured from
+ * beginning of PosTable (may be NULL) */
+ Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
+ * advance--measured from beginning of
+ * PosTable (may be NULL) */
+#endif
+
+ IntType& operator = (uint16_t i) { v = i; return *this; }
+
+ unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
+ unsigned int get_size () const { return get_len () * Value::static_size; }
+
+ hb_vector_t<unsigned> get_device_table_indices () const {
+ unsigned i = 0;
+ hb_vector_t<unsigned> result;
+ unsigned format = *this;
+
+ if (format & xPlacement) i++;
+ if (format & yPlacement) i++;
+ if (format & xAdvance) i++;
+ if (format & yAdvance) i++;
+
+ if (format & xPlaDevice) result.push (i++);
+ if (format & yPlaDevice) result.push (i++);
+ if (format & xAdvDevice) result.push (i++);
+ if (format & yAdvDevice) result.push (i++);
+
+ return result;
+ }
+
+ bool apply_value (hb_ot_apply_context_t *c,
+ const void *base,
+ const Value *values,
+ hb_glyph_position_t &glyph_pos) const
+ {
+ bool ret = false;
+ unsigned int format = *this;
+ if (!format) return ret;
+
+ hb_font_t *font = c->font;
+ bool horizontal =
+#ifndef HB_NO_VERTICAL
+ HB_DIRECTION_IS_HORIZONTAL (c->direction)
+#else
+ true
+#endif
+ ;
+
+ if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
+ if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
+ if (format & xAdvance) {
+ if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
+ values++;
+ }
+ /* y_advance values grow downward but font-space grows upward, hence negation */
+ if (format & yAdvance) {
+ if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
+ values++;
+ }
+
+ if (!has_device ()) return ret;
+
+ bool use_x_device = font->x_ppem || font->num_coords;
+ bool use_y_device = font->y_ppem || font->num_coords;
+
+ if (!use_x_device && !use_y_device) return ret;
+
+ const VariationStore &store = c->var_store;
+ auto *cache = c->var_store_cache;
+
+ /* pixel -> fractional pixel */
+ if (format & xPlaDevice) {
+ if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+ values++;
+ }
+ if (format & yPlaDevice) {
+ if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+ values++;
+ }
+ if (format & xAdvDevice) {
+ if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+ values++;
+ }
+ if (format & yAdvDevice) {
+ /* y_advance values grow downward but font-space grows upward, hence negation */
+ if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+ values++;
+ }
+ return ret;
+ }
+
+ unsigned int get_effective_format (const Value *values) const
+ {
+ unsigned int format = *this;
+ for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
+ if (format & flag) should_drop (*values++, (Flags) flag, &format);
+ }
+
+ return format;
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ unsigned int get_effective_format (Iterator it) const {
+ unsigned int new_format = 0;
+
+ for (const hb_array_t<const Value>& values : it)
+ new_format = new_format | get_effective_format (&values);
+
+ return new_format;
+ }
+
+ void copy_values (hb_serialize_context_t *c,
+ unsigned int new_format,
+ const void *base,
+ const Value *values,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
+ {
+ unsigned int format = *this;
+ if (!format) return;
+
+ HBINT16 *x_placement = nullptr, *y_placement = nullptr, *x_adv = nullptr, *y_adv = nullptr;
+ if (format & xPlacement) x_placement = copy_value (c, new_format, xPlacement, *values++);
+ if (format & yPlacement) y_placement = copy_value (c, new_format, yPlacement, *values++);
+ if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++);
+ if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++);
+
+ if (format & xPlaDevice)
+ {
+ add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map);
+ copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xPlaDevice);
+ }
+
+ if (format & yPlaDevice)
+ {
+ add_delta_to_value (y_placement, base, values, layout_variation_idx_delta_map);
+ copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yPlaDevice);
+ }
+
+ if (format & xAdvDevice)
+ {
+ add_delta_to_value (x_adv, base, values, layout_variation_idx_delta_map);
+ copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xAdvDevice);
+ }
+
+ if (format & yAdvDevice)
+ {
+ add_delta_to_value (y_adv, base, values, layout_variation_idx_delta_map);
+ copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yAdvDevice);
+ }
+ }
+
+ HBINT16* copy_value (hb_serialize_context_t *c,
+ unsigned int new_format,
+ Flags flag,
+ Value value) const
+ {
+ // Filter by new format.
+ if (!(new_format & flag)) return nullptr;
+ return reinterpret_cast<HBINT16 *> (c->copy (value));
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const void *base,
+ const hb_array_t<const Value>& values) const
+ {
+ unsigned format = *this;
+ unsigned i = 0;
+ if (format & xPlacement) i++;
+ if (format & yPlacement) i++;
+ if (format & xAdvance) i++;
+ if (format & yAdvance) i++;
+ if (format & xPlaDevice)
+ {
+ (base + get_device (&(values[i]))).collect_variation_indices (c);
+ i++;
+ }
+
+ if (format & ValueFormat::yPlaDevice)
+ {
+ (base + get_device (&(values[i]))).collect_variation_indices (c);
+ i++;
+ }
+
+ if (format & ValueFormat::xAdvDevice)
+ {
+
+ (base + get_device (&(values[i]))).collect_variation_indices (c);
+ i++;
+ }
+
+ if (format & ValueFormat::yAdvDevice)
+ {
+
+ (base + get_device (&(values[i]))).collect_variation_indices (c);
+ i++;
+ }
+ }
+
+ unsigned drop_device_table_flags () const
+ {
+ unsigned format = *this;
+ for (unsigned flag = xPlaDevice; flag <= yAdvDevice; flag = flag << 1)
+ format = format & ~flag;
+
+ return format;
+ }
+
+ private:
+ bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
+ {
+ unsigned int format = *this;
+
+ if (format & xPlacement) values++;
+ if (format & yPlacement) values++;
+ if (format & xAdvance) values++;
+ if (format & yAdvance) values++;
+
+ if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
+ if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
+ if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
+ if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
+
+ return true;
+ }
+
+ static inline Offset16To<Device>& get_device (Value* value)
+ {
+ return *static_cast<Offset16To<Device> *> (value);
+ }
+ static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
+ {
+ if (worked) *worked |= bool (*value);
+ return *static_cast<const Offset16To<Device> *> (value);
+ }
+
+ void add_delta_to_value (HBINT16 *value,
+ const void *base,
+ const Value *src_value,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
+ {
+ if (!value) return;
+ unsigned varidx = (base + get_device (src_value)).get_variation_index ();
+ hb_pair_t<unsigned, int> *varidx_delta;
+ if (!layout_variation_idx_delta_map->has (varidx, &varidx_delta)) return;
+
+ *value += hb_second (*varidx_delta);
+ }
+
+ bool copy_device (hb_serialize_context_t *c, const void *base,
+ const Value *src_value,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
+ unsigned int new_format, Flags flag) const
+ {
+ // Filter by new format.
+ if (!(new_format & flag)) return true;
+
+ Value *dst_value = c->copy (*src_value);
+
+ if (!dst_value) return false;
+ if (*dst_value == 0) return true;
+
+ *dst_value = 0;
+ c->push ();
+ if ((base + get_device (src_value)).copy (c, layout_variation_idx_delta_map))
+ {
+ c->add_link (*dst_value, c->pop_pack ());
+ return true;
+ }
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
+ }
+
+ static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
+ {
+ if (worked) *worked |= bool (*value);
+ return *reinterpret_cast<const HBINT16 *> (value);
+ }
+
+ public:
+
+ bool has_device () const
+ {
+ unsigned int format = *this;
+ return (format & devices) != 0;
+ }
+
+ bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
+ }
+
+ bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
+ {
+ TRACE_SANITIZE (this);
+ unsigned int len = get_len ();
+
+ if (!c->check_range (values, count, get_size ())) return_trace (false);
+
+ if (!has_device ()) return_trace (true);
+
+ for (unsigned int i = 0; i < count; i++) {
+ if (!sanitize_value_devices (c, base, values))
+ return_trace (false);
+ values += len;
+ }
+
+ return_trace (true);
+ }
+
+ /* Just sanitize referenced Device tables. Doesn't check the values themselves. */
+ bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
+ {
+ TRACE_SANITIZE (this);
+
+ if (!has_device ()) return_trace (true);
+
+ for (unsigned int i = 0; i < count; i++) {
+ if (!sanitize_value_devices (c, base, values))
+ return_trace (false);
+ values = &StructAtOffset<const Value> (values, stride);
+ }
+
+ return_trace (true);
+ }
+
+ private:
+
+ void should_drop (Value value, Flags flag, unsigned int* format) const
+ {
+ if (value) return;
+ *format = *format & ~flag;
+ }
+
+};
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
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 484f347468..b4466119be 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh
@@ -5,12 +5,13 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
+template <typename Types>
struct AlternateSet
{
protected:
- Array16Of<HBGlyphID16>
+ Array16Of<typename Types::HBGlyphID>
alternates; /* Array of alternate GlyphIDs--in
* arbitrary order */
public:
@@ -56,8 +57,23 @@ struct AlternateSet
if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %u (alternate substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (alternates[alt_index - 1]);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %u (alternate substitution)",
+ c->buffer->idx - 1u);
+ }
+
return_trace (true);
}
@@ -68,7 +84,7 @@ struct AlternateSet
{
if (alternates.len && alternate_count)
{
- + alternates.sub_array (start_offset, alternate_count)
+ + alternates.as_array ().sub_array (start_offset, alternate_count)
| hb_sink (hb_array (alternate_glyphs, *alternate_count))
;
}
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 e5d999261f..04a052a783 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh
@@ -6,28 +6,36 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct AlternateSubst
{
protected:
union {
- HBUINT16 format; /* Format identifier */
- AlternateSubstFormat1 format1;
+ HBUINT16 format; /* Format identifier */
+ AlternateSubstFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BEYOND_64K
+ AlternateSubstFormat1_2<MediumTypes> format2;
+#endif
} u;
public:
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
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
+ /* TODO This function is unused and not updated to 24bit GIDs. Should be done by using
+ * iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */
bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t<const HBGlyphID16> glyphs,
hb_array_t<const unsigned int> alternate_len_list,
@@ -42,6 +50,9 @@ struct AlternateSubst
default:return_trace (false);
}
}
+
+ /* TODO subset() should choose format. */
+
};
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
index af1cd7bedb..adec65d586 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
@@ -6,20 +6,21 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct AlternateSubstFormat1
+template <typename Types>
+struct AlternateSubstFormat1_2
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- Array16OfOffset16To<AlternateSet>
+ Array16Of<typename Types::template OffsetTo<AlternateSet<Types>>>
alternateSet; /* Array of AlternateSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, alternateSet);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, alternateSet);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -39,9 +40,8 @@ struct AlternateSubstFormat1
| hb_filter (c->parent_active_glyphs (), hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
+ | hb_apply ([c] (const AlternateSet<Types> &_) { _.closure (c); })
;
-
}
void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -52,7 +52,7 @@ struct AlternateSubstFormat1
+ hb_zip (this+coverage, alternateSet)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
+ | hb_apply ([c] (const AlternateSet<Types> &_) { _.collect_glyphs (c); })
;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh
index bbb88b222f..08fd779f73 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh
@@ -7,7 +7,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ChainContextSubst : ChainContext {};
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
index f4c78a9f02..968bba0481 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
@@ -6,7 +6,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh
index 2af54e8ff4..9f8cb46b5e 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh
@@ -7,7 +7,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ContextSubst : Context {};
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ExtensionSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ExtensionSubst.hh
index 40a3ff439f..831a7dfa2d 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ExtensionSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ExtensionSubst.hh
@@ -7,7 +7,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ExtensionSubst : Extension<ExtensionSubst>
{
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/GSUB.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/GSUB.hh
index ad153ce8d7..900cf603e4 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/GSUB.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/GSUB.hh
@@ -1,16 +1,15 @@
#ifndef OT_LAYOUT_GSUB_GSUB_HH
#define OT_LAYOUT_GSUB_GSUB_HH
-// TODO(garretrieger): move to new layout.
#include "../../../hb-ot-layout-gsubgpos.hh"
#include "Common.hh"
#include "SubstLookup.hh"
-using OT::Layout::GSUB::SubstLookup;
-
namespace OT {
+
+using Layout::GSUB_impl::SubstLookup;
+
namespace Layout {
-namespace GSUB {
/*
* GSUB -- Glyph Substitution
@@ -19,6 +18,8 @@ namespace GSUB {
struct GSUB : GSUBGPOS
{
+ using Lookup = SubstLookup;
+
static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
const SubstLookup& get_lookup (unsigned int i) const
@@ -26,12 +27,15 @@ struct GSUB : GSUBGPOS
bool subset (hb_subset_context_t *c) const
{
- hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
+ hb_subset_layout_context_t l (c, tableTag);
return GSUBGPOS::subset<SubstLookup> (&l);
}
bool sanitize (hb_sanitize_context_t *c) const
- { return GSUBGPOS::sanitize<SubstLookup> (c); }
+ {
+ TRACE_SANITIZE (this);
+ return_trace (GSUBGPOS::sanitize<SubstLookup> (c));
+ }
HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
hb_face_t *face) const;
@@ -46,10 +50,9 @@ struct GSUB : GSUBGPOS
}
-}
-struct GSUB_accelerator_t : Layout::GSUB::GSUB::accelerator_t {
- GSUB_accelerator_t (hb_face_t *face) : Layout::GSUB::GSUB::accelerator_t (face) {}
+struct GSUB_accelerator_t : Layout::GSUB::accelerator_t {
+ GSUB_accelerator_t (hb_face_t *face) : Layout::GSUB::accelerator_t (face) {}
};
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 0448d925d1..ffe39d52ab 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh
@@ -5,18 +5,20 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
+template <typename Types>
struct Ligature
{
protected:
- HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */
- HeadlessArrayOf<HBGlyphID16>
- component; /* Array of component GlyphIDs--start
+ typename Types::HBGlyphID
+ ligGlyph; /* GlyphID of ligature to substitute */
+ HeadlessArrayOf<typename Types::HBGlyphID>
+ component; /* Array of component GlyphIDs--start
* with the second component--ordered
* in writing direction */
public:
- DEFINE_SIZE_ARRAY (4, component);
+ DEFINE_SIZE_ARRAY (Types::size + 2, component);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -62,7 +64,24 @@ struct Ligature
* as a "ligated" substitution. */
if (unlikely (count == 1))
{
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %u (ligature substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (ligGlyph);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %u (ligature substitution)",
+ c->buffer->idx - 1u);
+ }
+
return_trace (true);
}
@@ -83,6 +102,31 @@ struct Ligature
return_trace (false);
}
+ unsigned pos = 0;
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ unsigned delta = c->buffer->sync_so_far ();
+
+ pos = c->buffer->idx;
+
+ char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0};
+ char *p = buf;
+
+ match_end += delta;
+ for (unsigned i = 0; i < count; i++)
+ {
+ match_positions[i] += delta;
+ if (i)
+ *p++ = ',';
+ snprintf (p, sizeof(buf) - (p - buf), "%u", match_positions[i]);
+ p += strlen(p);
+ }
+
+ c->buffer->message (c->font,
+ "ligating glyphs at %s",
+ buf);
+ }
+
ligate_input (c,
count,
match_positions,
@@ -90,6 +134,14 @@ struct Ligature
ligGlyph,
total_component_count);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "ligated glyph at %u",
+ pos);
+ }
+
return_trace (true);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh
index 185b324b35..637cec7137 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh
@@ -6,12 +6,13 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
+template <typename Types>
struct LigatureSet
{
protected:
- Array16OfOffset16To<Ligature>
+ Array16OfOffset16To<Ligature<Types>>
ligature; /* Array LigatureSet tables
* ordered by preference */
public:
@@ -28,7 +29,7 @@ struct LigatureSet
return
+ hb_iter (ligature)
| hb_map (hb_add (this))
- | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
+ | hb_map ([glyphs] (const Ligature<Types> &_) { return _.intersects (glyphs); })
| hb_any
;
}
@@ -37,7 +38,7 @@ struct LigatureSet
{
+ hb_iter (ligature)
| hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.closure (c); })
+ | hb_apply ([c] (const Ligature<Types> &_) { _.closure (c); })
;
}
@@ -45,7 +46,7 @@ struct LigatureSet
{
+ hb_iter (ligature)
| hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); })
+ | hb_apply ([c] (const Ligature<Types> &_) { _.collect_glyphs (c); })
;
}
@@ -54,7 +55,7 @@ struct LigatureSet
return
+ hb_iter (ligature)
| hb_map (hb_add (this))
- | hb_map ([c] (const Ligature &_) { return _.would_apply (c); })
+ | hb_map ([c] (const Ligature<Types> &_) { return _.would_apply (c); })
| hb_any
;
}
@@ -65,7 +66,7 @@ struct LigatureSet
unsigned int num_ligs = ligature.len;
for (unsigned int i = 0; i < num_ligs; i++)
{
- const Ligature &lig = this+ligature[i];
+ const auto &lig = this+ligature[i];
if (lig.apply (c)) return_trace (true);
}
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 a029bf5e9f..18f6e35581 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubst.hh
@@ -6,28 +6,37 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct LigatureSubst
{
protected:
union {
- HBUINT16 format; /* Format identifier */
- LigatureSubstFormat1 format1;
+ HBUINT16 format; /* Format identifier */
+ LigatureSubstFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BEYOND_64K
+ LigatureSubstFormat1_2<MediumTypes> format2;
+#endif
} u;
public:
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
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
+ /* TODO This function is only used by small GIDs, and not updated to 24bit GIDs. Should
+ * be done by using iterators. While at it perhaps using iterator of arrays of hb_codepoint_t
+ * instead. */
bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t<const HBGlyphID16> first_glyphs,
hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
@@ -49,6 +58,9 @@ struct LigatureSubst
default:return_trace (false);
}
}
+
+ /* TODO subset() should choose format. */
+
};
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
index 19dfe98469..32b642c38a 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
@@ -6,20 +6,21 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct LigatureSubstFormat1
+template <typename Types>
+struct LigatureSubstFormat1_2
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- Array16OfOffset16To<LigatureSet>
+ Array16Of<typename Types::template OffsetTo<LigatureSet<Types>>>
ligatureSet; /* Array LigatureSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, ligatureSet);
+ DEFINE_SIZE_ARRAY (4 + Types::size, ligatureSet);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -33,7 +34,7 @@ struct LigatureSubstFormat1
+ hb_zip (this+coverage, ligatureSet)
| hb_filter (*glyphs, hb_first)
| hb_map (hb_second)
- | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
+ | hb_map ([this, glyphs] (const typename Types::template OffsetTo<LigatureSet<Types>> &_)
{ return (this+_).intersects (glyphs); })
| hb_any
;
@@ -48,7 +49,7 @@ struct LigatureSubstFormat1
| hb_filter (c->parent_active_glyphs (), hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
+ | hb_apply ([c] (const LigatureSet<Types> &_) { _.closure (c); })
;
}
@@ -62,7 +63,7 @@ struct LigatureSubstFormat1
+ hb_zip (this+coverage, ligatureSet)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); })
+ | hb_apply ([c] (const LigatureSet<Types> &_) { _.collect_glyphs (c); })
;
}
@@ -73,7 +74,7 @@ struct LigatureSubstFormat1
unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
if (likely (index == NOT_COVERED)) return false;
- const LigatureSet &lig_set = this+ligatureSet[index];
+ const auto &lig_set = this+ligatureSet[index];
return lig_set.would_apply (c);
}
@@ -84,7 +85,7 @@ struct LigatureSubstFormat1
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- const LigatureSet &lig_set = this+ligatureSet[index];
+ const auto &lig_set = this+ligatureSet[index];
return_trace (lig_set.apply (c));
}
@@ -128,7 +129,7 @@ struct LigatureSubstFormat1
hb_set_t new_coverage;
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
| hb_filter (glyphset, hb_first)
- | hb_filter ([&] (const LigatureSet& _) {
+ | hb_filter ([&] (const LigatureSet<Types>& _) {
return _.intersects (&glyphset);
}, hb_second)
| hb_map (hb_first)
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 b289175504..742c8587ee 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubst.hh
@@ -6,14 +6,17 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct MultipleSubst
{
protected:
union {
- HBUINT16 format; /* Format identifier */
- MultipleSubstFormat1 format1;
+ HBUINT16 format; /* Format identifier */
+ MultipleSubstFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BEYOND_64K
+ MultipleSubstFormat1_2<MediumTypes> format2;
+#endif
} u;
public:
@@ -21,28 +24,34 @@ 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
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_iterator (Iterator))>
bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ Iterator it)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (u.format))) return_trace (false);
unsigned int format = 1;
u.format = format;
switch (u.format) {
- case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
+ case 1: return_trace (u.format1.serialize (c, it));
default:return_trace (false);
}
}
+
+ /* TODO subset() should choose format. */
+
};
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
index 54c6dc8478..3b4bd11694 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
@@ -6,20 +6,21 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct MultipleSubstFormat1
+template <typename Types>
+struct MultipleSubstFormat1_2
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- Array16OfOffset16To<Sequence>
+ Array16Of<typename Types::template OffsetTo<Sequence<Types>>>
sequence; /* Array of Sequence tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, sequence);
+ DEFINE_SIZE_ARRAY (4 + Types::size, sequence);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -39,7 +40,7 @@ struct MultipleSubstFormat1
| hb_filter (c->parent_active_glyphs (), hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.closure (c); })
+ | hb_apply ([c] (const Sequence<Types> &_) { _.closure (c); })
;
}
@@ -51,7 +52,7 @@ struct MultipleSubstFormat1
+ hb_zip (this+coverage, sequence)
| hb_map (hb_second)
| hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
+ | hb_apply ([c] (const Sequence<Types> &_) { _.collect_glyphs (c); })
;
}
@@ -70,22 +71,31 @@ struct MultipleSubstFormat1
return_trace ((this+sequence[index]).apply (c));
}
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_iterator (Iterator))>
bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ Iterator it)
{
TRACE_SERIALIZE (this);
+ auto sequences =
+ + it
+ | hb_map (hb_second)
+ ;
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < glyphs.length; i++)
+
+ if (unlikely (!sequence.serialize (c, sequences.length))) return_trace (false);
+
+ for (auto& pair : hb_zip (sequences, sequence))
{
- unsigned int substitute_len = substitute_len_list[i];
- if (unlikely (!sequence[i]
- .serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
+ if (unlikely (!pair.second
+ .serialize_serialize (c, pair.first)))
return_trace (false);
- substitute_glyphs_list += substitute_len;
}
+
return_trace (coverage.serialize_serialize (c, glyphs));
}
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 435d80fd31..5ad463fea7 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
@@ -6,7 +6,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ReverseChainSingleSubst
{
@@ -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 7a79a9df25..2c2e1aa44f 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
@@ -5,7 +5,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct ReverseChainSingleSubstFormat1
{
@@ -33,10 +33,10 @@ struct ReverseChainSingleSubstFormat1
TRACE_SANITIZE (this);
if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
if (!lookahead.sanitize (c, this))
return_trace (false);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
return_trace (substitute.sanitize (c));
}
@@ -45,7 +45,7 @@ struct ReverseChainSingleSubstFormat1
if (!(this+coverage).intersects (glyphs))
return false;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
unsigned int count;
@@ -69,8 +69,8 @@ struct ReverseChainSingleSubstFormat1
{
if (!intersects (c->glyphs)) return;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
+ hb_zip (this+coverage, substitute)
| hb_filter (c->parent_active_glyphs (), hb_first)
@@ -91,12 +91,12 @@ struct ReverseChainSingleSubstFormat1
for (unsigned int i = 0; i < count; i++)
if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
count = lookahead.len;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
count = substitute.len;
c->output->add_array (substitute.arrayZ, substitute.len);
}
@@ -115,8 +115,8 @@ struct ReverseChainSingleSubstFormat1
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
if (unlikely (index >= substitute.len)) return_trace (false);
@@ -131,7 +131,23 @@ struct ReverseChainSingleSubstFormat1
c->buffer->idx + 1, &end_index))
{
c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replacing glyph at %u (reverse chaining substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph_inplace (substitute[index]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %u (reverse chaining substitution)",
+ c->buffer->idx);
+ }
+
/* Note: We DON'T decrease buffer->idx. The main loop does it
* for us. This is useful for preventing surprises if someone
* calls us through a Context lookup. */
@@ -206,8 +222,8 @@ struct ReverseChainSingleSubstFormat1
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
auto it =
+ hb_zip (this+coverage, substitute)
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 ebd451e6ba..ae3292f329 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh
@@ -5,12 +5,13 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
+template <typename Types>
struct Sequence
{
protected:
- Array16Of<HBGlyphID16>
+ Array16Of<typename Types::HBGlyphID>
substitute; /* String of GlyphIDs to substitute */
public:
DEFINE_SIZE_ARRAY (2, substitute);
@@ -39,17 +40,58 @@ struct Sequence
* as a "multiplied" substitution. */
if (unlikely (count == 1))
{
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %u (multiple substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (substitute.arrayZ[0]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %u (multiple subtitution)",
+ c->buffer->idx - 1u);
+ }
+
return_trace (true);
}
/* Spec disallows this, but Uniscribe allows it.
* https://github.com/harfbuzz/harfbuzz/issues/253 */
else if (unlikely (count == 0))
{
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "deleting glyph at %u (multiple substitution)",
+ c->buffer->idx);
+ }
+
c->buffer->delete_glyph ();
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "deleted glyph at %u (multiple substitution)",
+ c->buffer->idx);
+ }
+
return_trace (true);
}
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "multiplying glyph at %u",
+ c->buffer->idx);
+ }
+
unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
@@ -64,6 +106,26 @@ struct Sequence
}
c->buffer->skip_glyph ();
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+
+ char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0};
+ char *p = buf;
+
+ for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++)
+ {
+ if (buf < p)
+ *p++ = ',';
+ snprintf (p, sizeof(buf) - (p - buf), "%u", i);
+ p += strlen(p);
+ }
+
+ c->buffer->message (c->font,
+ "multiplied glyphs at %s",
+ buf);
+ }
+
return_trace (true);
}
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 786428fe45..4529927ba6 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh
@@ -7,15 +7,19 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct SingleSubst
{
protected:
union {
- HBUINT16 format; /* Format identifier */
- SingleSubstFormat1 format1;
- SingleSubstFormat2 format2;
+ HBUINT16 format; /* Format identifier */
+ SingleSubstFormat1_3<SmallTypes> format1;
+ SingleSubstFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BEYOND_64K
+ SingleSubstFormat1_3<MediumTypes> format3;
+ SingleSubstFormat2_4<MediumTypes> format4;
+#endif
} u;
public:
@@ -23,11 +27,15 @@ 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)...));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
@@ -45,11 +53,24 @@ struct SingleSubst
if (glyphs)
{
format = 1;
+ hb_codepoint_t mask = 0xFFFFu;
+
+#ifndef HB_NO_BEYOND_64K
+ if (+ glyphs
+ | hb_map_retains_sorting (hb_first)
+ | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
+ {
+ format += 2;
+ mask = 0xFFFFFFu;
+ }
+#endif
+
auto get_delta = [=] (hb_codepoint_pair_t _)
- { return (unsigned) (_.second - _.first) & 0xFFFF; };
+ { return (unsigned) (_.second - _.first) & mask; };
delta = get_delta (*glyphs);
- if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
+ if (!hb_all (++(+glyphs), delta, get_delta)) format += 1;
}
+
u.format = format;
switch (u.format) {
case 1: return_trace (u.format1.serialize (c,
@@ -57,6 +78,13 @@ struct SingleSubst
| hb_map_retains_sorting (hb_first),
delta));
case 2: return_trace (u.format2.serialize (c, glyphs));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.serialize (c,
+ + glyphs
+ | hb_map_retains_sorting (hb_first),
+ delta));
+ case 4: return_trace (u.format4.serialize (c, glyphs));
+#endif
default:return_trace (false);
}
}
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 3c6b2954ce..78725352c2 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat1.hh
@@ -5,20 +5,22 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct SingleSubstFormat1
+template <typename Types>
+struct SingleSubstFormat1_3
{
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- HBUINT16 deltaGlyphID; /* Add to original GlyphID to get
+ typename Types::HBUINT
+ deltaGlyphID; /* Add to original GlyphID to get
* substitute GlyphID, modulo 0x10000 */
public:
- DEFINE_SIZE_STATIC (6);
+ DEFINE_SIZE_STATIC (2 + 2 * Types::size);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -26,6 +28,9 @@ struct SingleSubstFormat1
return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
}
+ hb_codepoint_t get_mask () const
+ { return (1 << (8 * Types::size)) - 1; }
+
bool intersects (const hb_set_t *glyphs) const
{ return (this+coverage).intersects (glyphs); }
@@ -34,14 +39,33 @@ struct SingleSubstFormat1
void closure (hb_closure_context_t *c) const
{
- unsigned d = deltaGlyphID;
-
- + hb_iter (this+coverage)
- | hb_filter (c->parent_active_glyphs ())
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ /* Help fuzzer avoid this function as much. */
+ unsigned pop = (this+coverage).get_population ();
+ if (pop >= mask)
+ return;
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (c->parent_active_glyphs (), intersection);
+
+ /* In degenerate fuzzer-found fonts, but not real fonts,
+ * this table can keep adding new glyphs in each round of closure.
+ * Refuse to close-over, if it maps glyph range to overlapping range. */
+ hb_codepoint_t min_before = intersection.get_min ();
+ hb_codepoint_t max_before = intersection.get_max ();
+ hb_codepoint_t min_after = (min_before + d) & mask;
+ hb_codepoint_t max_after = (max_before + d) & mask;
+ if (intersection.get_population () == max_before - min_before + 1 &&
+ ((min_before <= min_after && min_after <= max_before) ||
+ (min_before <= max_after && max_after <= max_before)))
+ return;
+
+ + hb_iter (intersection)
+ | hb_map ([d, mask] (hb_codepoint_t g) { return (g + d) & mask; })
| hb_sink (c->output)
;
-
}
void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -49,9 +73,11 @@ struct SingleSubstFormat1
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- unsigned d = deltaGlyphID;
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ hb_iter (this+coverage)
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
+ | hb_map ([d, mask] (hb_codepoint_t g) { return (g + d) & mask; })
| hb_sink (c->output)
;
}
@@ -68,11 +94,28 @@ struct SingleSubstFormat1
unsigned int index = (this+coverage).get_coverage (glyph_id);
if (likely (index == NOT_COVERED)) return_trace (false);
- /* According to the Adobe Annotated OpenType Suite, result is always
- * limited to 16bit. */
- glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ glyph_id = (glyph_id + d) & mask;
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %u (single substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (glyph_id);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %u (single substitution)",
+ c->buffer->idx - 1u);
+ }
+
return_trace (true);
}
@@ -95,14 +138,17 @@ struct SingleSubstFormat1
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
- hb_codepoint_t delta = deltaGlyphID;
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (glyphset, intersection);
auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting ([&] (hb_codepoint_t g) {
+ + hb_iter (intersection)
+ | hb_map_retains_sorting ([d, mask] (hb_codepoint_t g) {
return hb_codepoint_pair_t (g,
- (g + delta) & 0xFFFF); })
+ (g + d) & mask); })
| hb_filter (glyphset, hb_second)
| hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
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 df75bb52bb..17aa087363 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubstFormat2.hh
@@ -5,21 +5,22 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
-struct SingleSubstFormat2
+template <typename Types>
+struct SingleSubstFormat2_4
{
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of Substitution table */
- Array16Of<HBGlyphID16>
+ Array16Of<typename Types::HBGlyphID>
substitute; /* Array of substitute
* GlyphIDs--ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, substitute);
+ DEFINE_SIZE_ARRAY (4 + Types::size, substitute);
bool sanitize (hb_sanitize_context_t *c) const
{
@@ -35,12 +36,27 @@ struct SingleSubstFormat2
void closure (hb_closure_context_t *c) const
{
- + hb_zip (this+coverage, substitute)
- | hb_filter (c->parent_active_glyphs (), hb_first)
+ auto &cov = this+coverage;
+ auto &glyph_set = c->parent_active_glyphs ();
+
+ if (substitute.len > glyph_set.get_population () * 4)
+ {
+ for (auto g : glyph_set)
+ {
+ unsigned i = cov.get_coverage (g);
+ if (i == NOT_COVERED || i >= substitute.len)
+ continue;
+ c->output->add (substitute.arrayZ[i]);
+ }
+
+ return;
+ }
+
+ + hb_zip (cov, substitute)
+ | hb_filter (glyph_set, hb_first)
| hb_map (hb_second)
| hb_sink (c->output)
;
-
}
void closure_lookups (hb_closure_lookups_context_t *c) const {}
@@ -67,8 +83,23 @@ struct SingleSubstFormat2
if (unlikely (index >= substitute.len)) return_trace (false);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %u (single substitution)",
+ c->buffer->idx);
+ }
+
c->replace_glyph (substitute[index]);
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %u (single substitution)",
+ c->buffer->idx - 1u);
+ }
+
return_trace (true);
}
@@ -103,7 +134,7 @@ struct SingleSubstFormat2
+ hb_zip (this+coverage, substitute)
| hb_filter (glyphset, hb_first)
| hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const typename Types::HBGlyphID &> p) -> hb_codepoint_pair_t
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
;
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookup.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookup.hh
index 3419b5a734..d49dcc0e0f 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookup.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookup.hh
@@ -6,11 +6,11 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct SubstLookup : Lookup
{
- typedef SubstLookupSubTable SubTable;
+ using SubTable = SubstLookupSubTable;
bool sanitize (hb_sanitize_context_t *c) const
{ return Lookup::sanitize<SubTable> (c); }
@@ -25,7 +25,7 @@ struct SubstLookup : Lookup
{
unsigned int type = get_type ();
if (unlikely (type == SubTable::Extension))
- return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse ();
+ return get_subtable (0).u.extension.is_reverse ();
return lookup_type_is_reverse (type);
}
@@ -73,8 +73,6 @@ struct SubstLookup : Lookup
return hb_closure_lookups_context_t::default_return_value ();
}
- c->set_recurse_func (dispatch_closure_lookups_recurse_func);
-
hb_closure_lookups_context_t::return_t ret = dispatch (c);
return ret;
}
@@ -100,12 +98,15 @@ struct SubstLookup : Lookup
return dispatch (c);
}
- static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
+ template<typename Glyphs, typename Substitutes,
+ hb_requires (hb_is_sorted_source_of (Glyphs,
+ const hb_codepoint_t) &&
+ hb_is_source_of (Substitutes,
+ const hb_codepoint_t))>
bool serialize_single (hb_serialize_context_t *c,
uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const HBGlyphID16> substitutes)
+ Glyphs glyphs,
+ Substitutes substitutes)
{
TRACE_SERIALIZE (this);
if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
@@ -118,19 +119,16 @@ struct SubstLookup : Lookup
return_trace (false);
}
- bool serialize_multiple (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_iterator (Iterator))>
+ bool serialize (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ Iterator it)
{
TRACE_SERIALIZE (this);
if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
if (c->push<SubTable> ()->u.multiple.
- serialize (c,
- glyphs,
- substitute_len_list,
- substitute_glyphs_list))
+ serialize (c, it))
{
c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
return_trace (true);
@@ -206,8 +204,6 @@ struct SubstLookup : Lookup
return ret;
}
- HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
-
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{ return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookupSubTable.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookupSubTable.hh
index 53e963e2a2..a525fba039 100644
--- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookupSubTable.hh
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SubstLookupSubTable.hh
@@ -13,7 +13,7 @@
namespace OT {
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct SubstLookupSubTable
{
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/types.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/types.hh
new file mode 100644
index 0000000000..6a43403e94
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/types.hh
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,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, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_TYPES_HH
+#define OT_LAYOUT_TYPES_HH
+
+namespace OT {
+namespace Layout {
+
+struct SmallTypes {
+ static constexpr unsigned size = 2;
+ using large_int = uint32_t;
+ using HBUINT = HBUINT16;
+ using HBGlyphID = HBGlyphID16;
+ using Offset = Offset16;
+ template <typename Type, bool has_null=true>
+ using OffsetTo = OT::Offset16To<Type, has_null>;
+ template <typename Type>
+ using ArrayOf = OT::Array16Of<Type>;
+ template <typename Type>
+ using SortedArrayOf = OT::SortedArray16Of<Type>;
+};
+
+struct MediumTypes {
+ static constexpr unsigned size = 3;
+ using large_int = uint64_t;
+ using HBUINT = HBUINT24;
+ using HBGlyphID = HBGlyphID24;
+ using Offset = Offset24;
+ template <typename Type, bool has_null=true>
+ using OffsetTo = OT::Offset24To<Type, has_null>;
+ template <typename Type>
+ using ArrayOf = OT::Array24Of<Type>;
+ template <typename Type>
+ using SortedArrayOf = OT::SortedArray24Of<Type>;
+};
+
+}
+}
+
+#endif /* OT_LAYOUT_TYPES_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh
new file mode 100644
index 0000000000..edf8cd8797
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh
@@ -0,0 +1,369 @@
+#ifndef OT_GLYF_COMPOSITEGLYPH_HH
+#define OT_GLYF_COMPOSITEGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+#include "composite-iter.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct CompositeGlyphRecord
+{
+ protected:
+ enum composite_glyph_flag_t
+ {
+ ARG_1_AND_2_ARE_WORDS = 0x0001,
+ ARGS_ARE_XY_VALUES = 0x0002,
+ ROUND_XY_TO_GRID = 0x0004,
+ WE_HAVE_A_SCALE = 0x0008,
+ MORE_COMPONENTS = 0x0020,
+ WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
+ WE_HAVE_A_TWO_BY_TWO = 0x0080,
+ WE_HAVE_INSTRUCTIONS = 0x0100,
+ USE_MY_METRICS = 0x0200,
+ OVERLAP_COMPOUND = 0x0400,
+ SCALED_COMPONENT_OFFSET = 0x0800,
+ UNSCALED_COMPONENT_OFFSET = 0x1000,
+#ifndef HB_NO_BEYOND_64K
+ GID_IS_24BIT = 0x2000
+#endif
+ };
+
+ public:
+ unsigned int get_size () const
+ {
+ unsigned int size = min_size;
+ /* glyphIndex is 24bit instead of 16bit */
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT) size += HBGlyphID24::static_size - HBGlyphID16::static_size;
+#endif
+ /* arg1 and 2 are int16 */
+ if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
+ /* arg1 and 2 are int8 */
+ else size += 2;
+
+ /* One x 16 bit (scale) */
+ if (flags & WE_HAVE_A_SCALE) size += 2;
+ /* Two x 16 bit (xscale, yscale) */
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
+ /* Four x 16 bit (xscale, scale01, scale10, yscale) */
+ else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
+
+ return size;
+ }
+
+ void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
+ void set_overlaps_flag ()
+ {
+ flags = (uint16_t) flags | OVERLAP_COMPOUND;
+ }
+
+ bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
+
+ bool has_more () const { return flags & MORE_COMPONENTS; }
+ bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
+ bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
+ void get_anchor_points (unsigned int &point1, unsigned int &point2) const
+ {
+ const auto *p = &StructAfter<const HBUINT8> (flags);
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ p += HBGlyphID24::static_size;
+ else
+#endif
+ p += HBGlyphID16::static_size;
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ point1 = ((const HBUINT16 *) p)[0];
+ point2 = ((const HBUINT16 *) p)[1];
+ }
+ else
+ {
+ point1 = p[0];
+ point2 = p[1];
+ }
+ }
+
+ void transform_points (contour_point_vector_t &points) const
+ {
+ float matrix[4];
+ contour_point_t trans;
+ if (get_transformation (matrix, trans))
+ {
+ if (scaled_offsets ())
+ {
+ points.translate (trans);
+ points.transform (matrix);
+ }
+ else
+ {
+ points.transform (matrix);
+ points.translate (trans);
+ }
+ }
+ }
+
+ unsigned compile_with_deltas (const contour_point_t &p_delta,
+ char *out) const
+ {
+ const HBINT8 *p = &StructAfter<const HBINT8> (flags);
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ p += HBGlyphID24::static_size;
+ else
+#endif
+ p += HBGlyphID16::static_size;
+
+ unsigned len = get_size ();
+ unsigned len_before_val = (const char *)p - (const char *)this;
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ // no overflow, copy and update value with deltas
+ hb_memcpy (out, this, len);
+
+ const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p);
+ HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
+ o[0] = px[0] + roundf (p_delta.x);
+ o[1] = px[1] + roundf (p_delta.y);
+ }
+ else
+ {
+ int new_x = p[0] + roundf (p_delta.x);
+ int new_y = p[1] + roundf (p_delta.y);
+ if (new_x <= 127 && new_x >= -128 &&
+ new_y <= 127 && new_y >= -128)
+ {
+ hb_memcpy (out, this, len);
+ HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val);
+ o[0] = new_x;
+ o[1] = new_y;
+ }
+ else
+ {
+ // int8 overflows after deltas applied
+ hb_memcpy (out, this, len_before_val);
+
+ //update flags
+ CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out);
+ o->flags = flags | ARG_1_AND_2_ARE_WORDS;
+ out += len_before_val;
+
+ HBINT16 new_value;
+ new_value = new_x;
+ hb_memcpy (out, &new_value, HBINT16::static_size);
+ out += HBINT16::static_size;
+
+ new_value = new_y;
+ hb_memcpy (out, &new_value, HBINT16::static_size);
+ out += HBINT16::static_size;
+
+ hb_memcpy (out, p+2, len - len_before_val - 2);
+ len += 2;
+ }
+ }
+ return len;
+ }
+
+ protected:
+ bool scaled_offsets () const
+ { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
+
+ bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
+ {
+ matrix[0] = matrix[3] = 1.f;
+ matrix[1] = matrix[2] = 0.f;
+
+ const auto *p = &StructAfter<const HBINT8> (flags);
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ p += HBGlyphID24::static_size;
+ else
+#endif
+ p += HBGlyphID16::static_size;
+ int tx, ty;
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ tx = *(const HBINT16 *) p;
+ p += HBINT16::static_size;
+ ty = *(const HBINT16 *) p;
+ p += HBINT16::static_size;
+ }
+ else
+ {
+ tx = *p++;
+ ty = *p++;
+ }
+ if (is_anchored ()) tx = ty = 0;
+
+ trans.init ((float) tx, (float) ty);
+
+ {
+ const F2DOT14 *points = (const F2DOT14 *) p;
+ if (flags & WE_HAVE_A_SCALE)
+ {
+ matrix[0] = matrix[3] = points[0].to_float ();
+ return true;
+ }
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+ {
+ matrix[0] = points[0].to_float ();
+ matrix[3] = points[1].to_float ();
+ return true;
+ }
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ {
+ matrix[0] = points[0].to_float ();
+ matrix[1] = points[1].to_float ();
+ matrix[2] = points[2].to_float ();
+ matrix[3] = points[3].to_float ();
+ return true;
+ }
+ }
+ return tx || ty;
+ }
+
+ public:
+ hb_codepoint_t get_gid () const
+ {
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ return StructAfter<const HBGlyphID24> (flags);
+ else
+#endif
+ return StructAfter<const HBGlyphID16> (flags);
+ }
+ void set_gid (hb_codepoint_t gid)
+ {
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ StructAfter<HBGlyphID24> (flags) = gid;
+ else
+#endif
+ /* TODO assert? */
+ StructAfter<HBGlyphID16> (flags) = gid;
+ }
+
+ protected:
+ HBUINT16 flags;
+ HBUINT24 pad;
+ public:
+ DEFINE_SIZE_MIN (4);
+};
+
+using composite_iter_t = composite_iter_tmpl<CompositeGlyphRecord>;
+
+struct CompositeGlyph
+{
+ const GlyphHeader &header;
+ hb_bytes_t bytes;
+ CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+ header (header_), bytes (bytes_) {}
+
+ composite_iter_t iter () const
+ { return composite_iter_t (bytes, &StructAfter<CompositeGlyphRecord, GlyphHeader> (header)); }
+
+ unsigned int instructions_length (hb_bytes_t bytes) const
+ {
+ unsigned int start = bytes.length;
+ unsigned int end = bytes.length;
+ const CompositeGlyphRecord *last = nullptr;
+ for (auto &item : iter ())
+ last = &item;
+ if (unlikely (!last)) return 0;
+
+ if (last->has_instructions ())
+ start = (char *) last - &bytes + last->get_size ();
+ if (unlikely (start > end)) return 0;
+ return end - start;
+ }
+
+ /* Trimming for composites not implemented.
+ * If removing hints it falls out of that. */
+ const hb_bytes_t trim_padding () const { return bytes; }
+
+ void drop_hints ()
+ {
+ for (const auto &_ : iter ())
+ const_cast<CompositeGlyphRecord &> (_).drop_instructions_flag ();
+ }
+
+ /* Chop instructions off the end */
+ void drop_hints_bytes (hb_bytes_t &dest_start) const
+ { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
+
+ void set_overlaps_flag ()
+ {
+ CompositeGlyphRecord& glyph_chain = const_cast<CompositeGlyphRecord &> (
+ StructAfter<CompositeGlyphRecord, GlyphHeader> (header));
+ if (!bytes.check_range(&glyph_chain, CompositeGlyphRecord::min_size))
+ return;
+ glyph_chain.set_overlaps_flag ();
+ }
+
+ bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes,
+ const contour_point_vector_t &deltas,
+ hb_bytes_t &dest_bytes /* OUT */)
+ {
+ if (source_bytes.length <= GlyphHeader::static_size ||
+ header.numberOfContours != -1)
+ {
+ dest_bytes = hb_bytes_t ();
+ return true;
+ }
+
+ unsigned source_len = source_bytes.length - GlyphHeader::static_size;
+
+ /* try to allocate more memories than source glyph bytes
+ * in case that there might be an overflow for int8 value
+ * and we would need to use int16 instead */
+ char *o = (char *) hb_calloc (source_len + source_len/2, sizeof (char));
+ if (unlikely (!o)) return false;
+
+ const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size);
+ auto it = composite_iter_t (hb_bytes_t ((const char *)c, source_len), c);
+
+ char *p = o;
+ unsigned i = 0, source_comp_len = 0;
+ for (const auto &component : it)
+ {
+ /* last 4 points in deltas are phantom points and should not be included */
+ if (i >= deltas.length - 4) return false;
+
+ unsigned comp_len = component.get_size ();
+ if (component.is_anchored ())
+ {
+ hb_memcpy (p, &component, comp_len);
+ p += comp_len;
+ }
+ else
+ {
+ unsigned new_len = component.compile_with_deltas (deltas[i], p);
+ p += new_len;
+ }
+ i++;
+ source_comp_len += comp_len;
+ }
+
+ //copy instructions if any
+ if (source_len > source_comp_len)
+ {
+ unsigned instr_len = source_len - source_comp_len;
+ hb_memcpy (p, (const char *)c + source_comp_len, instr_len);
+ p += instr_len;
+ }
+
+ unsigned len = p - o;
+ dest_bytes = hb_bytes_t (o, len);
+ return true;
+ }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_COMPOSITEGLYPH_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
new file mode 100644
index 0000000000..5574ae0722
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
@@ -0,0 +1,537 @@
+#ifndef OT_GLYF_GLYPH_HH
+#define OT_GLYF_GLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+#include "GlyphHeader.hh"
+#include "SimpleGlyph.hh"
+#include "CompositeGlyph.hh"
+#include "VarCompositeGlyph.hh"
+#include "coord-setter.hh"
+
+
+namespace OT {
+
+struct glyf_accelerator_t;
+
+namespace glyf_impl {
+
+
+enum phantom_point_index_t
+{
+ PHANTOM_LEFT = 0,
+ PHANTOM_RIGHT = 1,
+ PHANTOM_TOP = 2,
+ PHANTOM_BOTTOM = 3,
+ PHANTOM_COUNT = 4
+};
+
+struct Glyph
+{
+ enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE, VAR_COMPOSITE };
+
+ public:
+ composite_iter_t get_composite_iterator () const
+ {
+ if (type != COMPOSITE) return composite_iter_t ();
+ return CompositeGlyph (*header, bytes).iter ();
+ }
+ var_composite_iter_t get_var_composite_iterator () const
+ {
+ if (type != VAR_COMPOSITE) return var_composite_iter_t ();
+ return VarCompositeGlyph (*header, bytes).iter ();
+ }
+
+ const hb_bytes_t trim_padding () const
+ {
+ switch (type) {
+ case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
+ case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
+ default: return bytes;
+ }
+ }
+
+ void drop_hints ()
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
+ default: return;
+ }
+ }
+
+ void set_overlaps_flag ()
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
+ default: return;
+ }
+ }
+
+ void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
+ default: return;
+ }
+ }
+
+ void update_mtx (const hb_subset_plan_t *plan,
+ 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;
+
+ signed hori_aw = roundf (rightSideX - leftSideX);
+ if (hori_aw < 0) hori_aw = 0;
+ int lsb = roundf (xMin - leftSideX);
+ plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
+ //flag value should be computed using non-empty glyphs
+ if (type != EMPTY && lsb != xMin)
+ plan->head_maxp_info.allXMinIsLsb = false;
+
+ signed vert_aw = roundf (topSideY - bottomSideY);
+ if (vert_aw < 0) vert_aw = 0;
+ int tsb = roundf (topSideY - yMax);
+ plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
+ }
+
+ bool compile_header_bytes (const hb_subset_plan_t *plan,
+ const contour_point_vector_t &all_points,
+ hb_bytes_t &dest_bytes /* OUT */) const
+ {
+ GlyphHeader *glyph_header = nullptr;
+ 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;
+ }
+
+ float xMin = 0, xMax = 0;
+ float yMin = 0, yMax = 0;
+ if (all_points.length > 4)
+ {
+ xMin = xMax = all_points[0].x;
+ yMin = yMax = all_points[0].y;
+ }
+
+ for (unsigned i = 1; i < all_points.length - 4; i++)
+ {
+ float x = all_points[i].x;
+ float y = all_points[i].y;
+ xMin = hb_min (xMin, x);
+ xMax = hb_max (xMax, x);
+ yMin = hb_min (yMin, y);
+ yMax = hb_max (yMax, y);
+ }
+
+ 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);
+ }
+
+ /* 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 = 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;
+ }
+
+ bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
+ hb_font_t *font,
+ const glyf_accelerator_t &glyf,
+ hb_bytes_t &dest_start, /* IN/OUT */
+ hb_bytes_t &dest_end /* OUT */)
+ {
+ contour_point_vector_t all_points, deltas;
+ 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;
+ dest_start = hb_bytes_t ();
+ dest_end = hb_bytes_t ();
+ }
+
+ //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))
+ {
+ dest_end.fini ();
+ return false;
+ }
+ return true;
+ }
+
+
+ /* Note: Recursively calls itself.
+ * all_points includes phantom points
+ */
+ template <typename accelerator_t>
+ 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,
+ 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);
+
+ contour_point_vector_t stack_points;
+ bool inplace = type == SIMPLE && all_points.length == 0;
+ /* Load into all_points if it's empty, as an optimization. */
+ contour_point_vector_t &points = inplace ? all_points : stack_points;
+
+ 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;
+ case COMPOSITE:
+ {
+ /* pseudo component points for each component in composite glyph */
+ unsigned num_points = hb_len (CompositeGlyph (*header, bytes).iter ());
+ if (unlikely (!points.resize (num_points))) return false;
+ break;
+ }
+#ifndef HB_NO_VAR_COMPOSITES
+ case VAR_COMPOSITE:
+ {
+ for (auto &item : get_var_composite_iterator ())
+ if (unlikely (!item.get_points (points))) return false;
+ }
+#endif
+ default:
+ break;
+ }
+
+ /* Init phantom points */
+ if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
+ hb_array_t<contour_point_t> phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
+ {
+ int lsb = 0;
+ int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
+ (int) header->xMin - lsb : 0;
+ HB_UNUSED int tsb = 0;
+ int v_orig = (int) header->yMax +
+#ifndef HB_NO_VERTICAL
+ ((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
+#else
+ 0
+#endif
+ ;
+ unsigned h_adv = glyf_accelerator.hmtx->get_advance_without_var_unscaled (gid);
+ unsigned v_adv =
+#ifndef HB_NO_VERTICAL
+ glyf_accelerator.vmtx->get_advance_without_var_unscaled (gid)
+#else
+ - font->face->get_upem ()
+#endif
+ ;
+ phantoms[PHANTOM_LEFT].x = h_delta;
+ phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
+ phantoms[PHANTOM_TOP].y = v_orig;
+ phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
+ }
+
+ if (deltas != nullptr && depth == 0 && type == COMPOSITE)
+ {
+ if (unlikely (!deltas->resize (points.length))) return false;
+ deltas->copy_vector (points);
+ }
+
+#ifndef HB_NO_VAR
+ glyf_accelerator.gvar->apply_deltas_to_points (gid,
+ coords,
+ points.as_array ());
+#endif
+
+ // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
+ // with child glyphs' points
+ if (deltas != nullptr && depth == 0 && type == COMPOSITE)
+ {
+ for (unsigned i = 0 ; i < points.length; i++)
+ {
+ deltas->arrayZ[i].x = points.arrayZ[i].x - deltas->arrayZ[i].x;
+ deltas->arrayZ[i].y = points.arrayZ[i].y - deltas->arrayZ[i].y;
+ }
+ }
+
+ 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;
+ case COMPOSITE:
+ {
+ contour_point_vector_t comp_points;
+ unsigned int comp_index = 0;
+ 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,
+ edge_count)))
+ return false;
+
+ /* Copy phantom points from component if USE_MY_METRICS flag set */
+ if (use_my_metrics && item.is_use_my_metrics ())
+ for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
+ phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
+
+ /* Apply component transformation & translation */
+ item.transform_points (comp_points);
+
+ /* Apply translation from gvar */
+ comp_points.translate (points[comp_index]);
+
+ if (item.is_anchored ())
+ {
+ unsigned int p1, p2;
+ item.get_anchor_points (p1, p2);
+ if (likely (p1 < all_points.length && p2 < comp_points.length))
+ {
+ contour_point_t delta;
+ delta.init (all_points[p1].x - comp_points[p2].x,
+ all_points[p1].y - comp_points[p2].y);
+
+ comp_points.translate (delta);
+ }
+ }
+
+ all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT));
+
+ if (all_points.length > HB_GLYF_MAX_POINTS)
+ return false;
+
+ 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
+ case VAR_COMPOSITE:
+ {
+ contour_point_vector_t comp_points;
+ hb_array_t<contour_point_t> points_left = points.as_array ();
+ for (auto &item : get_var_composite_iterator ())
+ {
+ hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item.get_num_points ());
+
+ comp_points.reset ();
+
+ 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 ())
+ .get_points (font,
+ glyf_accelerator,
+ comp_points,
+ deltas,
+ head_maxp_info,
+ nullptr,
+ shift_points_hori,
+ use_my_metrics,
+ phantom_only,
+ coord_setter.get_coords (),
+ depth + 1,
+ edge_count)))
+ return false;
+
+ /* Apply component transformation */
+ item.transform_points (record_points, comp_points);
+
+ /* Copy phantom points from component if USE_MY_METRICS flag set */
+ if (use_my_metrics && item.is_use_my_metrics ())
+ for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
+ phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
+
+ all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT));
+
+ if (all_points.length > HB_GLYF_MAX_POINTS)
+ return false;
+
+ points_left += item.get_num_points ();
+ }
+ all_points.extend (phantoms);
+ } break;
+#endif
+ default:
+ all_points.extend (phantoms);
+ break;
+ }
+
+ if (depth == 0 && shift_points_hori) /* Apply at top level */
+ {
+ /* Undocumented rasterizer behavior:
+ * Shift points horizontally by the updated left side bearing
+ */
+ contour_point_t delta;
+ delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
+ if (delta.x) all_points.translate (delta);
+ }
+
+ return !all_points.in_error ();
+ }
+
+ bool get_extents_without_var_scaled (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator,
+ hb_glyph_extents_t *extents) const
+ {
+ if (type == EMPTY) return true; /* Empty glyph; zero extents. */
+ return header->get_extents_without_var_scaled (font, glyf_accelerator, gid, extents);
+ }
+
+ hb_bytes_t get_bytes () const { return bytes; }
+
+ Glyph () : bytes (),
+ header (bytes.as<GlyphHeader> ()),
+ gid (-1),
+ type(EMPTY)
+ {}
+
+ Glyph (hb_bytes_t bytes_,
+ hb_codepoint_t gid_ = (unsigned) -1) : bytes (bytes_),
+ header (bytes.as<GlyphHeader> ()),
+ gid (gid_)
+ {
+ int num_contours = header->numberOfContours;
+ if (unlikely (num_contours == 0)) type = EMPTY;
+ else if (num_contours > 0) type = SIMPLE;
+ else if (num_contours == -2) type = VAR_COMPOSITE;
+ else type = COMPOSITE; /* negative numbers */
+ }
+
+ protected:
+ hb_bytes_t bytes;
+ const GlyphHeader *header;
+ hb_codepoint_t gid;
+ unsigned type;
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYPH_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/GlyphHeader.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/GlyphHeader.hh
new file mode 100644
index 0000000000..a43b6691ab
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/GlyphHeader.hh
@@ -0,0 +1,52 @@
+#ifndef OT_GLYF_GLYPHHEADER_HH
+#define OT_GLYF_GLYPHHEADER_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct GlyphHeader
+{
+ bool has_data () const { return numberOfContours; }
+
+ template <typename accelerator_t>
+ bool get_extents_without_var_scaled (hb_font_t *font, const accelerator_t &glyf_accelerator,
+ hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+ {
+ /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
+ /* 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 = 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;
+ }
+
+ HBINT16 numberOfContours;
+ /* If the number of contours is
+ * greater than or equal to zero,
+ * this is a simple glyph; if negative,
+ * this is a composite glyph. */
+ FWORD xMin; /* Minimum x for coordinate data. */
+ FWORD yMin; /* Minimum y for coordinate data. */
+ FWORD xMax; /* Maximum x for coordinate data. */
+ FWORD yMax; /* Maximum y for coordinate data. */
+ public:
+ DEFINE_SIZE_STATIC (10);
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYPHHEADER_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh
new file mode 100644
index 0000000000..b6fefce1ac
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh
@@ -0,0 +1,339 @@
+#ifndef OT_GLYF_SIMPLEGLYPH_HH
+#define OT_GLYF_SIMPLEGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct SimpleGlyph
+{
+ enum simple_glyph_flag_t
+ {
+ FLAG_ON_CURVE = 0x01,
+ FLAG_X_SHORT = 0x02,
+ FLAG_Y_SHORT = 0x04,
+ FLAG_REPEAT = 0x08,
+ FLAG_X_SAME = 0x10,
+ FLAG_Y_SAME = 0x20,
+ FLAG_OVERLAP_SIMPLE = 0x40,
+ FLAG_CUBIC = 0x80
+ };
+
+ const GlyphHeader &header;
+ hb_bytes_t bytes;
+ SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+ header (header_), bytes (bytes_) {}
+
+ unsigned int instruction_len_offset () const
+ { return GlyphHeader::static_size + 2 * header.numberOfContours; }
+
+ unsigned int length (unsigned int instruction_len) const
+ { return instruction_len_offset () + 2 + instruction_len; }
+
+ unsigned int instructions_length () const
+ {
+ unsigned int instruction_length_offset = instruction_len_offset ();
+ if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
+
+ const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
+ /* Out of bounds of the current glyph */
+ if (unlikely (length (instructionLength) > bytes.length)) return 0;
+ return instructionLength;
+ }
+
+ const hb_bytes_t trim_padding () const
+ {
+ /* based on FontTools _g_l_y_f.py::trim */
+ const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
+ const uint8_t *glyph_end = glyph + bytes.length;
+ /* simple glyph w/contours, possibly trimmable */
+ glyph += instruction_len_offset ();
+
+ if (unlikely (glyph + 2 >= glyph_end)) return hb_bytes_t ();
+ unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
+ unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
+
+ glyph += 2 + num_instructions;
+
+ unsigned int coord_bytes = 0;
+ unsigned int coords_with_flags = 0;
+ while (glyph < glyph_end)
+ {
+ uint8_t flag = *glyph;
+ glyph++;
+
+ unsigned int repeat = 1;
+ if (flag & FLAG_REPEAT)
+ {
+ if (unlikely (glyph >= glyph_end)) return hb_bytes_t ();
+ repeat = *glyph + 1;
+ glyph++;
+ }
+
+ unsigned int xBytes, yBytes;
+ xBytes = yBytes = 0;
+ if (flag & FLAG_X_SHORT) xBytes = 1;
+ else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
+
+ if (flag & FLAG_Y_SHORT) yBytes = 1;
+ else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
+
+ coord_bytes += (xBytes + yBytes) * repeat;
+ coords_with_flags += repeat;
+ if (coords_with_flags >= num_coordinates) break;
+ }
+
+ if (unlikely (coords_with_flags != num_coordinates)) return hb_bytes_t ();
+ return bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph));
+ }
+
+ /* zero instruction length */
+ void drop_hints ()
+ {
+ GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
+ (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
+ }
+
+ void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
+ {
+ unsigned int instructions_len = instructions_length ();
+ unsigned int glyph_length = length (instructions_len);
+ dest_start = bytes.sub_array (0, glyph_length - instructions_len);
+ dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
+ }
+
+ void set_overlaps_flag ()
+ {
+ if (unlikely (!header.numberOfContours)) return;
+
+ unsigned flags_offset = length (instructions_length ());
+ if (unlikely (flags_offset + 1 > bytes.length)) return;
+
+ HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
+ first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
+ }
+
+ static bool read_flags (const HBUINT8 *&p /* IN/OUT */,
+ contour_point_vector_t &points_ /* IN/OUT */,
+ const HBUINT8 *end)
+ {
+ unsigned count = points_.length;
+ for (unsigned int i = 0; i < count;)
+ {
+ if (unlikely (p + 1 > end)) return false;
+ uint8_t flag = *p++;
+ points_.arrayZ[i++].flag = flag;
+ if (flag & FLAG_REPEAT)
+ {
+ if (unlikely (p + 1 > end)) return false;
+ unsigned int repeat_count = *p++;
+ unsigned stop = hb_min (i + repeat_count, count);
+ for (; i < stop; i++)
+ points_.arrayZ[i].flag = flag;
+ }
+ }
+ return true;
+ }
+
+ static bool read_points (const HBUINT8 *&p /* IN/OUT */,
+ contour_point_vector_t &points_ /* IN/OUT */,
+ const HBUINT8 *end,
+ float contour_point_t::*m,
+ const simple_glyph_flag_t short_flag,
+ const simple_glyph_flag_t same_flag)
+ {
+ int v = 0;
+
+ unsigned count = points_.length;
+ for (unsigned i = 0; i < count; i++)
+ {
+ unsigned flag = points_[i].flag;
+ if (flag & short_flag)
+ {
+ if (unlikely (p + 1 > end)) return false;
+ if (flag & same_flag)
+ v += *p++;
+ else
+ v -= *p++;
+ }
+ else
+ {
+ if (!(flag & same_flag))
+ {
+ if (unlikely (p + HBINT16::static_size > end)) return false;
+ v += *(const HBINT16 *) p;
+ p += HBINT16::static_size;
+ }
+ }
+ points_.arrayZ[i].*m = v;
+ }
+ return true;
+ }
+
+ bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
+ bool phantom_only = false) const
+ {
+ const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
+ int num_contours = header.numberOfContours;
+ assert (num_contours);
+ /* One extra item at the end, for the instruction-count below. */
+ if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false;
+ unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
+
+ 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;
+
+ for (int i = 0; i < num_contours; i++)
+ points_[endPtsOfContours[i]].is_end_point = true;
+
+ /* Skip instructions */
+ const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
+ endPtsOfContours[num_contours]);
+
+ if (unlikely ((const char *) p < bytes.arrayZ)) return false; /* Unlikely overflow */
+ const HBUINT8 *end = (const HBUINT8 *) (bytes.arrayZ + bytes.length);
+ if (unlikely (p >= end)) return false;
+
+ /* Read x & y coordinates */
+ return read_flags (p, points_, end)
+ && read_points (p, points_, end, &contour_point_t::x,
+ FLAG_X_SHORT, FLAG_X_SAME)
+ && read_points (p, points_, end, &contour_point_t::y,
+ FLAG_Y_SHORT, FLAG_Y_SAME);
+ }
+
+ static void encode_coord (int value,
+ uint8_t &flag,
+ const simple_glyph_flag_t short_flag,
+ const simple_glyph_flag_t same_flag,
+ hb_vector_t<uint8_t> &coords /* OUT */)
+ {
+ if (value == 0)
+ {
+ flag |= same_flag;
+ }
+ else if (value >= -255 && value <= 255)
+ {
+ flag |= short_flag;
+ if (value > 0) flag |= same_flag;
+ else value = -value;
+
+ coords.arrayZ[coords.length++] = (uint8_t) value;
+ }
+ else
+ {
+ int16_t val = value;
+ coords.arrayZ[coords.length++] = val >> 8;
+ coords.arrayZ[coords.length++] = val & 0xff;
+ }
+ }
+
+ static void encode_flag (uint8_t &flag,
+ uint8_t &repeat,
+ uint8_t lastflag,
+ hb_vector_t<uint8_t> &flags /* OUT */)
+ {
+ if (flag == lastflag && repeat != 255)
+ {
+ repeat++;
+ if (repeat == 1)
+ {
+ /* We know there's room. */
+ flags.arrayZ[flags.length++] = flag;
+ }
+ else
+ {
+ unsigned len = flags.length;
+ flags.arrayZ[len-2] = flag | FLAG_REPEAT;
+ flags.arrayZ[len-1] = repeat;
+ }
+ }
+ else
+ {
+ repeat = 0;
+ flags.push (flag);
+ }
+ }
+
+ bool compile_bytes_with_deltas (const contour_point_vector_t &all_points,
+ bool no_hinting,
+ hb_bytes_t &dest_bytes /* OUT */)
+ {
+ if (header.numberOfContours == 0 || all_points.length <= 4)
+ {
+ dest_bytes = hb_bytes_t ();
+ return true;
+ }
+ unsigned num_points = all_points.length - 4;
+
+ hb_vector_t<uint8_t> flags, x_coords, y_coords;
+ 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;
+
+ for (unsigned i = 0; i < num_points; i++)
+ {
+ uint8_t flag = all_points.arrayZ[i].flag;
+ flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
+
+ int cur_x = roundf (all_points.arrayZ[i].x);
+ int cur_y = roundf (all_points.arrayZ[i].y);
+ encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
+ encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
+ encode_flag (flag, repeat, lastflag, flags);
+
+ prev_x = cur_x;
+ prev_y = cur_y;
+ lastflag = flag;
+ }
+
+ unsigned len_before_instrs = 2 * header.numberOfContours + 2;
+ unsigned len_instrs = instructions_length ();
+ unsigned total_len = len_before_instrs + flags.length + x_coords.length + y_coords.length;
+
+ if (!no_hinting)
+ total_len += len_instrs;
+
+ char *p = (char *) hb_malloc (total_len);
+ if (unlikely (!p)) return false;
+
+ const char *src = bytes.arrayZ + GlyphHeader::static_size;
+ char *cur = p;
+ hb_memcpy (p, src, len_before_instrs);
+
+ cur += len_before_instrs;
+ src += len_before_instrs;
+
+ if (!no_hinting)
+ {
+ hb_memcpy (cur, src, len_instrs);
+ cur += len_instrs;
+ }
+
+ hb_memcpy (cur, flags.arrayZ, flags.length);
+ cur += flags.length;
+
+ hb_memcpy (cur, x_coords.arrayZ, x_coords.length);
+ cur += x_coords.length;
+
+ hb_memcpy (cur, y_coords.arrayZ, y_coords.length);
+
+ dest_bytes = hb_bytes_t (p, total_len);
+ return true;
+ }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_SIMPLEGLYPH_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh
new file mode 100644
index 0000000000..795925bba5
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh
@@ -0,0 +1,85 @@
+#ifndef OT_GLYF_SUBSETGLYPH_HH
+#define OT_GLYF_SUBSETGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+
+struct glyf_accelerator_t;
+
+namespace glyf_impl {
+
+
+struct SubsetGlyph
+{
+ hb_codepoint_t old_gid;
+ Glyph source_glyph;
+ hb_bytes_t dest_start; /* region of source_glyph to copy first */
+ hb_bytes_t dest_end; /* region of source_glyph to copy second */
+
+ bool serialize (hb_serialize_context_t *c,
+ bool use_short_loca,
+ const hb_subset_plan_t *plan)
+ {
+ TRACE_SERIALIZE (this);
+
+ hb_bytes_t dest_glyph = dest_start.copy (c);
+ dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
+ unsigned int pad_length = use_short_loca ? padding () : 0;
+ 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;
+ while (pad_length > 0)
+ {
+ c->embed (pad);
+ pad_length--;
+ }
+
+ if (unlikely (!dest_glyph.length)) return_trace (true);
+
+ /* update components gids */
+ for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
+ {
+ hb_codepoint_t new_gid;
+ if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
+ const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
+ }
+
+ if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ Glyph (dest_glyph).drop_hints ();
+
+ if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
+ Glyph (dest_glyph).set_overlaps_flag ();
+
+ return_trace (true);
+ }
+
+ bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
+ hb_font_t *font,
+ const glyf_accelerator_t &glyf)
+ { return source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end); }
+
+ void free_compiled_bytes ()
+ {
+ dest_start.fini ();
+ dest_end.fini ();
+ }
+
+ void drop_hints_bytes ()
+ { source_glyph.drop_hints_bytes (dest_start, dest_end); }
+
+ unsigned int length () const { return dest_start.length + dest_end.length; }
+ /* pad to 2 to ensure 2-byte loca will be ok */
+ unsigned int padding () const { return length () % 2; }
+ unsigned int padded_size () const { return length () + padding (); }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_SUBSETGLYPH_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh
new file mode 100644
index 0000000000..3685da7913
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh
@@ -0,0 +1,354 @@
+#ifndef OT_GLYF_VARCOMPOSITEGLYPH_HH
+#define OT_GLYF_VARCOMPOSITEGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+#include "coord-setter.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct VarCompositeGlyphRecord
+{
+ protected:
+ enum var_composite_glyph_flag_t
+ {
+ USE_MY_METRICS = 0x0001,
+ AXIS_INDICES_ARE_SHORT = 0x0002,
+ UNIFORM_SCALE = 0x0004,
+ HAVE_TRANSLATE_X = 0x0008,
+ HAVE_TRANSLATE_Y = 0x0010,
+ HAVE_ROTATION = 0x0020,
+ HAVE_SCALE_X = 0x0040,
+ HAVE_SCALE_Y = 0x0080,
+ HAVE_SKEW_X = 0x0100,
+ HAVE_SKEW_Y = 0x0200,
+ HAVE_TCENTER_X = 0x0400,
+ HAVE_TCENTER_Y = 0x0800,
+ GID_IS_24 = 0x1000,
+ AXES_HAVE_VARIATION = 0x2000,
+ RESET_UNSPECIFIED_AXES = 0x4000,
+ };
+
+ public:
+
+ unsigned int get_size () const
+ {
+ unsigned int size = min_size;
+
+ unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3;
+ size += numAxes * axis_width;
+
+ // gid
+ size += 2;
+ if (flags & GID_IS_24) size += 1;
+
+ if (flags & HAVE_TRANSLATE_X) size += 2;
+ if (flags & HAVE_TRANSLATE_Y) size += 2;
+ if (flags & HAVE_ROTATION) size += 2;
+ if (flags & HAVE_SCALE_X) size += 2;
+ if (flags & HAVE_SCALE_Y) size += 2;
+ if (flags & HAVE_SKEW_X) size += 2;
+ if (flags & HAVE_SKEW_Y) size += 2;
+ if (flags & HAVE_TCENTER_X) size += 2;
+ if (flags & HAVE_TCENTER_Y) size += 2;
+
+ return size;
+ }
+
+ 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
+ {
+ if (flags & GID_IS_24)
+ return StructAfter<const HBGlyphID24> (numAxes);
+ else
+ return StructAfter<const HBGlyphID16> (numAxes);
+ }
+
+ unsigned get_numAxes () const
+ {
+ return numAxes;
+ }
+
+ unsigned get_num_points () const
+ {
+ unsigned num = 0;
+ if (flags & AXES_HAVE_VARIATION) num += numAxes;
+ if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) num++;
+ if (flags & HAVE_ROTATION) num++;
+ if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) num++;
+ if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) num++;
+ if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) num++;
+ return num;
+ }
+
+ void transform_points (hb_array_t<contour_point_t> record_points,
+ contour_point_vector_t &points) const
+ {
+ float matrix[4];
+ contour_point_t trans;
+
+ get_transformation_from_points (record_points, matrix, trans);
+
+ points.transform (matrix);
+ points.translate (trans);
+ }
+
+ static inline void transform (float (&matrix)[4], contour_point_t &trans,
+ float (other)[6])
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L268
+ float xx1 = other[0];
+ float xy1 = other[1];
+ float yx1 = other[2];
+ float yy1 = other[3];
+ float dx1 = other[4];
+ float dy1 = other[5];
+ float xx2 = matrix[0];
+ float xy2 = matrix[1];
+ float yx2 = matrix[2];
+ float yy2 = matrix[3];
+ float dx2 = trans.x;
+ float dy2 = trans.y;
+
+ matrix[0] = xx1*xx2 + xy1*yx2;
+ matrix[1] = xx1*xy2 + xy1*yy2;
+ matrix[2] = yx1*xx2 + yy1*yx2;
+ matrix[3] = yx1*xy2 + yy1*yy2;
+ trans.x = xx2*dx1 + yx2*dy1 + dx2;
+ trans.y = xy2*dx1 + yy2*dy1 + dy2;
+ }
+
+ static void translate (float (&matrix)[4], contour_point_t &trans,
+ float translateX, float translateY)
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L213
+ float other[6] = {1.f, 0.f, 0.f, 1.f, translateX, translateY};
+ transform (matrix, trans, other);
+ }
+
+ static void scale (float (&matrix)[4], contour_point_t &trans,
+ float scaleX, float scaleY)
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L224
+ float other[6] = {scaleX, 0.f, 0.f, scaleY, 0.f, 0.f};
+ transform (matrix, trans, other);
+ }
+
+ static void rotate (float (&matrix)[4], contour_point_t &trans,
+ float rotation)
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
+ rotation = rotation * float (M_PI);
+ float c = cosf (rotation);
+ float s = sinf (rotation);
+ float other[6] = {c, s, -s, c, 0.f, 0.f};
+ transform (matrix, trans, other);
+ }
+
+ static void skew (float (&matrix)[4], contour_point_t &trans,
+ float skewX, float skewY)
+ {
+ // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
+ skewX = skewX * float (M_PI);
+ skewY = skewY * float (M_PI);
+ float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
+ transform (matrix, trans, other);
+ }
+
+ bool get_points (contour_point_vector_t &points) const
+ {
+ float translateX = 0.f;
+ float translateY = 0.f;
+ float rotation = 0.f;
+ float scaleX = 1.f * (1 << 10);
+ float scaleY = 1.f * (1 << 10);
+ float skewX = 0.f;
+ float skewY = 0.f;
+ float tCenterX = 0.f;
+ float tCenterY = 0.f;
+
+ if (unlikely (!points.resize (points.length + get_num_points ()))) return false;
+
+ unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
+ unsigned axes_size = numAxes * axis_width;
+
+ const F2DOT14 *q = (const F2DOT14 *) (axes_size +
+ (flags & GID_IS_24 ? 3 : 2) +
+ &StructAfter<const HBUINT8> (numAxes));
+
+ hb_array_t<contour_point_t> rec_points = points.as_array ().sub_array (points.length - get_num_points ());
+
+ unsigned count = numAxes;
+ if (flags & AXES_HAVE_VARIATION)
+ {
+ for (unsigned i = 0; i < count; i++)
+ rec_points[i].x = q++->to_int ();
+ rec_points += count;
+ }
+ else
+ q += count;
+
+ const HBUINT16 *p = (const HBUINT16 *) q;
+
+ if (flags & HAVE_TRANSLATE_X) translateX = * (const FWORD *) p++;
+ if (flags & HAVE_TRANSLATE_Y) translateY = * (const FWORD *) 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++;
+
+ if ((flags & UNIFORM_SCALE) && !(flags & HAVE_SCALE_Y))
+ scaleY = scaleX;
+
+ if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
+ {
+ rec_points[0].x = translateX;
+ rec_points[0].y = translateY;
+ rec_points++;
+ }
+ if (flags & HAVE_ROTATION)
+ {
+ rec_points[0].x = rotation;
+ rec_points++;
+ }
+ if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))
+ {
+ rec_points[0].x = scaleX;
+ rec_points[0].y = scaleY;
+ rec_points++;
+ }
+ if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y))
+ {
+ rec_points[0].x = skewX;
+ rec_points[0].y = skewY;
+ rec_points++;
+ }
+ if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
+ {
+ rec_points[0].x = tCenterX;
+ rec_points[0].y = tCenterY;
+ rec_points++;
+ }
+ assert (!rec_points);
+
+ return true;
+ }
+
+ void get_transformation_from_points (hb_array_t<contour_point_t> rec_points,
+ float (&matrix)[4], contour_point_t &trans) const
+ {
+ if (flags & AXES_HAVE_VARIATION)
+ rec_points += numAxes;
+
+ matrix[0] = matrix[3] = 1.f;
+ matrix[1] = matrix[2] = 0.f;
+ trans.init (0.f, 0.f);
+
+ float translateX = 0.f;
+ float translateY = 0.f;
+ float rotation = 0.f;
+ float scaleX = 1.f;
+ float scaleY = 1.f;
+ float skewX = 0.f;
+ float skewY = 0.f;
+ float tCenterX = 0.f;
+ float tCenterY = 0.f;
+
+ if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
+ {
+ translateX = rec_points[0].x;
+ translateY = rec_points[0].y;
+ rec_points++;
+ }
+ if (flags & HAVE_ROTATION)
+ {
+ rotation = rec_points[0].x / (1 << 12);
+ rec_points++;
+ }
+ if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y))
+ {
+ 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 << 12);
+ skewY = rec_points[0].y / (1 << 12);
+ rec_points++;
+ }
+ if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
+ {
+ tCenterX = rec_points[0].x;
+ tCenterY = rec_points[0].y;
+ rec_points++;
+ }
+ assert (!rec_points);
+
+ translate (matrix, trans, translateX + tCenterX, translateY + tCenterY);
+ rotate (matrix, trans, rotation);
+ scale (matrix, trans, scaleX, scaleY);
+ skew (matrix, trans, -skewX, skewY);
+ translate (matrix, trans, -tCenterX, -tCenterY);
+ }
+
+ void set_variations (coord_setter_t &setter,
+ hb_array_t<contour_point_t> rec_points) const
+ {
+ bool have_variations = flags & AXES_HAVE_VARIATION;
+ unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
+
+ const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
+ const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
+
+ const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes)));
+
+ unsigned count = numAxes;
+ for (unsigned i = 0; i < count; i++)
+ {
+ unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++;
+
+ signed v = have_variations ? rec_points[i].x : a++->to_int ();
+
+ v = hb_clamp (v, -(1<<14), (1<<14));
+ setter[axis_index] = v;
+ }
+ }
+
+ protected:
+ HBUINT16 flags;
+ HBUINT8 numAxes;
+ public:
+ DEFINE_SIZE_MIN (3);
+};
+
+using var_composite_iter_t = composite_iter_tmpl<VarCompositeGlyphRecord>;
+
+struct VarCompositeGlyph
+{
+ const GlyphHeader &header;
+ hb_bytes_t bytes;
+ VarCompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+ header (header_), bytes (bytes_) {}
+
+ var_composite_iter_t iter () const
+ { return var_composite_iter_t (bytes, &StructAfter<VarCompositeGlyphRecord, GlyphHeader> (header)); }
+
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_VARCOMPOSITEGLYPH_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/composite-iter.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/composite-iter.hh
new file mode 100644
index 0000000000..d05701f3d1
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/composite-iter.hh
@@ -0,0 +1,68 @@
+#ifndef OT_GLYF_COMPOSITE_ITER_HH
+#define OT_GLYF_COMPOSITE_ITER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+template <typename CompositeGlyphRecord>
+struct composite_iter_tmpl : hb_iter_with_fallback_t<composite_iter_tmpl<CompositeGlyphRecord>,
+ const CompositeGlyphRecord &>
+{
+ typedef const CompositeGlyphRecord *__item_t__;
+ composite_iter_tmpl (hb_bytes_t glyph_, __item_t__ current_) :
+ glyph (glyph_), current (nullptr), current_size (0)
+ {
+ set_current (current_);
+ }
+
+ composite_iter_tmpl () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
+
+ const CompositeGlyphRecord & __item__ () const { return *current; }
+ bool __more__ () const { return current; }
+ void __next__ ()
+ {
+ if (!current->has_more ()) { current = nullptr; return; }
+
+ set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size));
+ }
+ composite_iter_tmpl __end__ () const { return composite_iter_tmpl (); }
+ bool operator != (const composite_iter_tmpl& o) const
+ { return current != o.current; }
+
+
+ void set_current (__item_t__ current_)
+ {
+ if (!glyph.check_range (current_, CompositeGlyphRecord::min_size))
+ {
+ current = nullptr;
+ current_size = 0;
+ return;
+ }
+ unsigned size = current_->get_size ();
+ if (!glyph.check_range (current_, size))
+ {
+ current = nullptr;
+ current_size = 0;
+ return;
+ }
+
+ current = current_;
+ current_size = size;
+ }
+
+ private:
+ hb_bytes_t glyph;
+ __item_t__ current;
+ unsigned current_size;
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+#endif /* OT_GLYF_COMPOSITE_ITER_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh
new file mode 100644
index 0000000000..df64ed5af7
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh
@@ -0,0 +1,34 @@
+#ifndef OT_GLYF_COORD_SETTER_HH
+#define OT_GLYF_COORD_SETTER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct coord_setter_t
+{
+ coord_setter_t (hb_array_t<int> coords) :
+ coords (coords) {}
+
+ int& operator [] (unsigned idx)
+ {
+ if (coords.length < idx + 1)
+ coords.resize (idx + 1);
+ return coords[idx];
+ }
+
+ hb_array_t<int> get_coords ()
+ { return coords.as_array (); }
+
+ hb_vector_t<int> coords;
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+#endif /* OT_GLYF_COORD_SETTER_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh
new file mode 100644
index 0000000000..30106b2b98
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh
@@ -0,0 +1,104 @@
+#ifndef OT_GLYF_GLYF_HELPERS_HH
+#define OT_GLYF_GLYF_HELPERS_HH
+
+
+#include "../../hb-open-type.hh"
+#include "../../hb-subset-plan.hh"
+
+#include "loca.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+template<typename IteratorIn, typename IteratorOut,
+ hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
+ hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
+static void
+_write_loca (IteratorIn&& it, bool short_offsets, IteratorOut&& dest)
+{
+ unsigned right_shift = short_offsets ? 1 : 0;
+ unsigned int offset = 0;
+ dest << 0;
+ + it
+ | hb_map ([=, &offset] (unsigned int padded_size)
+ {
+ offset += padded_size;
+ DEBUG_MSG (SUBSET, nullptr, "loca entry offset %u", offset);
+ return offset >> right_shift;
+ })
+ | hb_sink (dest)
+ ;
+}
+
+static bool
+_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
+{
+ hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
+ hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
+ hb_blob_destroy (head_blob);
+
+ if (unlikely (!head_prime_blob))
+ return false;
+
+ 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);
+ return success;
+}
+
+template<typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, unsigned int))>
+static bool
+_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
+{
+ unsigned num_offsets = padded_offsets.len () + 1;
+ unsigned entry_size = use_short_loca ? 2 : 4;
+ char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
+
+ if (unlikely (!loca_prime_data)) return false;
+
+ DEBUG_MSG (SUBSET, nullptr, "loca entry_size %u num_offsets %u size %u",
+ entry_size, num_offsets, entry_size * num_offsets);
+
+ if (use_short_loca)
+ _write_loca (padded_offsets, true, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
+ else
+ _write_loca (padded_offsets, false, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
+
+ hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
+ entry_size * num_offsets,
+ HB_MEMORY_MODE_WRITABLE,
+ loca_prime_data,
+ hb_free);
+
+ bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
+ && _add_head_and_set_loca_version (plan, use_short_loca);
+
+ hb_blob_destroy (loca_blob);
+ return result;
+}
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYF_HELPERS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
new file mode 100644
index 0000000000..29328c7627
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
@@ -0,0 +1,474 @@
+#ifndef OT_GLYF_GLYF_HH
+#define OT_GLYF_GLYF_HH
+
+
+#include "../../hb-open-type.hh"
+#include "../../hb-ot-head-table.hh"
+#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"
+#include "SubsetGlyph.hh"
+#include "loca.hh"
+#include "path-builder.hh"
+
+
+namespace OT {
+
+
+/*
+ * glyf -- TrueType Glyph Data
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
+ */
+#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
+
+struct glyf
+{
+ friend struct glyf_accelerator_t;
+
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
+
+ bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
+ {
+ TRACE_SANITIZE (this);
+ /* Runtime checks as eager sanitizing each glyph is costy */
+ return_trace (true);
+ }
+
+ /* requires source of SubsetGlyph complains the identifier isn't declared */
+ template <typename Iterator>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator it,
+ bool use_short_loca,
+ const hb_subset_plan_t *plan)
+ {
+ TRACE_SERIALIZE (this);
+
+ unsigned init_len = c->length ();
+ for (auto &_ : it)
+ 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
+ * to the table, so that OTS doesn’t reject it, and to make the table work
+ * on Windows as well.
+ * See https://github.com/khaledhosny/ots/issues/52 */
+ if (init_len == c->length ())
+ {
+ HBUINT8 empty_byte;
+ empty_byte = 0;
+ c->copy (empty_byte);
+ }
+ return_trace (true);
+ }
+
+ /* Byte region(s) per glyph to output
+ unpadded, hints removed if so requested
+ If we fail to process a glyph we produce an empty (0-length) glyph */
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ glyf *glyf_prime = c->serializer->start_embed <glyf> ();
+ if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
+
+ hb_font_t *font = nullptr;
+ if (c->plan->normalized_coords)
+ {
+ font = _create_font_for_instancing (c->plan);
+ if (unlikely (!font)) return false;
+ }
+
+ 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))
+ use_short_loca = max_offset < 0x1FFFF;
+
+ if (!use_short_loca) {
+ for (unsigned i = 0; i < num_glyphs; i++)
+ padded_offsets[i] = glyphs[i].length ();
+ }
+
+ 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.iter (),
+ use_short_loca)));
+ }
+
+ 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, unsigned index) const
+ {
+ for (unsigned i = 0; i <= index && i < glyphs.length; i++)
+ glyphs[i].free_compiled_bytes ();
+ }
+
+ protected:
+ UnsizedArrayOf<HBUINT8>
+ dataZ; /* Glyphs data. */
+ public:
+ DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+ * check the size externally, allow Null() object of it by
+ * defining it _MIN instead. */
+};
+
+struct glyf_accelerator_t
+{
+ glyf_accelerator_t (hb_face_t *face)
+ {
+ short_offset = false;
+ num_glyphs = 0;
+ loca_table = nullptr;
+ glyf_table = nullptr;
+#ifndef HB_NO_VAR
+ gvar = nullptr;
+#endif
+ hmtx = nullptr;
+#ifndef HB_NO_VERTICAL
+ vmtx = nullptr;
+#endif
+ const OT::head &head = *face->table.head;
+ if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
+ /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
+ return;
+ short_offset = 0 == head.indexToLocFormat;
+
+ loca_table = face->table.loca.get_blob (); // Needs no destruct!
+ glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
+#ifndef HB_NO_VAR
+ gvar = face->table.gvar;
+#endif
+ hmtx = face->table.hmtx;
+#ifndef HB_NO_VERTICAL
+ vmtx = face->table.vmtx;
+#endif
+
+ num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
+ num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
+ }
+ ~glyf_accelerator_t ()
+ {
+ glyf_table.destroy ();
+ }
+
+ bool has_data () const { return num_glyphs; }
+
+ protected:
+ template<typename T>
+ bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
+ {
+ if (gid >= num_glyphs) return false;
+
+ /* Making this allocfree is not that easy
+ https://github.com/harfbuzz/harfbuzz/issues/2095
+ mostly because of gvar handling in VF fonts,
+ perhaps a separate path for non-VF fonts can be considered */
+ contour_point_vector_t all_points;
+
+ bool phantom_only = !consumer.is_consuming_contour_points ();
+ 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 ())
+ {
+ unsigned count = all_points.length;
+ assert (count >= glyf_impl::PHANTOM_COUNT);
+ count -= glyf_impl::PHANTOM_COUNT;
+ for (unsigned point_index = 0; point_index < count; point_index++)
+ consumer.consume_point (all_points[point_index]);
+ consumer.points_end ();
+ }
+
+ /* Where to write phantoms, nullptr if not requested */
+ contour_point_t *phantoms = consumer.get_phantoms_sink ();
+ if (phantoms)
+ for (unsigned i = 0; i < glyf_impl::PHANTOM_COUNT; ++i)
+ phantoms[i] = all_points[all_points.length - glyf_impl::PHANTOM_COUNT + i];
+
+ return true;
+ }
+
+#ifndef HB_NO_VAR
+ struct points_aggregator_t
+ {
+ hb_font_t *font;
+ hb_glyph_extents_t *extents;
+ contour_point_t *phantoms;
+ bool scaled;
+
+ struct contour_bounds_t
+ {
+ contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
+
+ void add (const contour_point_t &p)
+ {
+ min_x = hb_min (min_x, p.x);
+ min_y = hb_min (min_y, p.y);
+ max_x = hb_max (max_x, p.x);
+ max_y = hb_max (max_y, p.y);
+ }
+
+ bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
+
+ void get_extents (hb_font_t *font, hb_glyph_extents_t *extents, bool scaled)
+ {
+ if (unlikely (empty ()))
+ {
+ extents->width = 0;
+ extents->x_bearing = 0;
+ extents->height = 0;
+ extents->y_bearing = 0;
+ return;
+ }
+ {
+ 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);
+ }
+ }
+
+ protected:
+ float min_x, min_y, max_x, max_y;
+ } bounds;
+
+ points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_, bool scaled_)
+ {
+ font = font_;
+ extents = extents_;
+ phantoms = phantoms_;
+ scaled = scaled_;
+ if (extents) bounds = contour_bounds_t ();
+ }
+
+ void consume_point (const contour_point_t &point) { bounds.add (point); }
+ void points_end () { bounds.get_extents (font, extents, scaled); }
+
+ bool is_consuming_contour_points () { return extents; }
+ contour_point_t *get_phantoms_sink () { return phantoms; }
+ };
+
+ public:
+ unsigned
+ get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
+ {
+ if (unlikely (gid >= num_glyphs)) return 0;
+
+ bool success = false;
+
+ contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
+ if (font->num_coords)
+ success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false));
+
+ if (unlikely (!success))
+ return
+#ifndef HB_NO_VERTICAL
+ is_vertical ? vmtx->get_advance_without_var_unscaled (gid) :
+#endif
+ hmtx->get_advance_without_var_unscaled (gid);
+
+ float result = is_vertical
+ ? phantoms[glyf_impl::PHANTOM_TOP].y - phantoms[glyf_impl::PHANTOM_BOTTOM].y
+ : phantoms[glyf_impl::PHANTOM_RIGHT].x - phantoms[glyf_impl::PHANTOM_LEFT].x;
+ return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
+ }
+
+ bool get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical, int *lsb) const
+ {
+ if (unlikely (gid >= num_glyphs)) return false;
+
+ hb_glyph_extents_t extents;
+
+ contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
+ if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false))))
+ return false;
+
+ *lsb = is_vertical
+ ? roundf (phantoms[glyf_impl::PHANTOM_TOP].y) - extents.y_bearing
+ : roundf (phantoms[glyf_impl::PHANTOM_LEFT].x);
+ return true;
+ }
+#endif
+
+ public:
+ bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+ {
+ if (unlikely (gid >= num_glyphs)) return false;
+
+#ifndef HB_NO_VAR
+ if (font->num_coords)
+ return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true));
+#endif
+ 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
+ {
+ if (unlikely (gid >= num_glyphs)) return glyf_impl::Glyph ();
+
+ unsigned int start_offset, end_offset;
+
+ if (short_offset)
+ {
+ const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
+ start_offset = 2 * offsets[gid];
+ end_offset = 2 * offsets[gid + 1];
+ }
+ else
+ {
+ const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
+ start_offset = offsets[gid];
+ end_offset = offsets[gid + 1];
+ }
+
+ if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
+ return glyf_impl::Glyph ();
+
+ glyf_impl::Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
+ end_offset - start_offset), gid);
+ return needs_padding_removal ? glyf_impl::Glyph (glyph.trim_padding (), gid) : glyph;
+ }
+
+ bool
+ get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
+ { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); }
+
+#ifndef HB_NO_VAR
+ const gvar_accelerator_t *gvar;
+#endif
+ const hmtx_accelerator_t *hmtx;
+#ifndef HB_NO_VERTICAL
+ const vmtx_accelerator_t *vmtx;
+#endif
+
+ private:
+ bool short_offset;
+ unsigned int num_glyphs;
+ hb_blob_ptr_t<loca> loca_table;
+ hb_blob_ptr_t<glyf> glyf_table;
+};
+
+
+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 false;
+
+ unsigned idx = 0;
+ for (auto p : plan->glyph_map->iter ())
+ {
+ unsigned new_gid = p.second;
+ glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid];
+ subset_glyph.old_gid = p.first;
+
+ if (unlikely (new_gid == 0 &&
+ !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
+ !plan->normalized_coords)
+ subset_glyph.source_glyph = glyf_impl::Glyph ();
+ else
+ {
+ /* If plan has an accelerator, the preprocessing step already trimmed glyphs.
+ * Don't trim them again! */
+ subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, !plan->accelerator);
+ }
+
+ if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ 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 *
+glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
+{
+ hb_font_t *font = hb_font_create (plan->source);
+ 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 (), true)))
+ return nullptr;
+
+ for (auto _ : plan->user_axes_location)
+ {
+ hb_variation_t var;
+ var.tag = _.first;
+ var.value = _.second;
+ vars.push (var);
+ }
+
+#ifndef HB_NO_VAR
+ hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
+#endif
+ return font;
+}
+
+
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYF_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/loca.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/loca.hh
new file mode 100644
index 0000000000..4481cba8ed
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/loca.hh
@@ -0,0 +1,43 @@
+#ifndef OT_GLYF_LOCA_HH
+#define OT_GLYF_LOCA_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+
+
+/*
+ * loca -- Index to Location
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/loca
+ */
+#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
+
+struct loca
+{
+ friend struct glyf;
+ friend struct glyf_accelerator_t;
+
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
+
+ bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (true);
+ }
+
+ protected:
+ UnsizedArrayOf<HBUINT8>
+ dataZ; /* Location data. */
+ public:
+ DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+ * check the size externally, allow Null() object of it by
+ * defining it _MIN instead. */
+};
+
+
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_LOCA_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh
new file mode 100644
index 0000000000..e35a4dafde
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh
@@ -0,0 +1,174 @@
+#ifndef OT_GLYF_PATH_BUILDER_HH
+#define OT_GLYF_PATH_BUILDER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct path_builder_t
+{
+ hb_font_t *font;
+ hb_draw_session_t *draw_session;
+
+ struct optional_point_t
+ {
+ optional_point_t () {}
+ optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {}
+ operator bool () const { return has_data; }
+
+ bool has_data = false;
+ float x = 0.;
+ float y = 0.;
+
+ 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, 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 = 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
+ *
+ * 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)
+ {
+ if (is_on_curve)
+ {
+ first_oncurve = p;
+ draw_session->move_to (p.x, p.y);
+ }
+ else
+ {
+ if (first_offcurve)
+ {
+ optional_point_t mid = first_offcurve.lerp (p, .5f);
+ first_oncurve = mid;
+ last_offcurve = p;
+ draw_session->move_to (mid.x, mid.y);
+ }
+ else
+ first_offcurve = p;
+ }
+ }
+ else
+ {
+ if (last_offcurve)
+ {
+ if (is_on_curve)
+ {
+ 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
+ {
+ 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
+ {
+ if (is_on_curve)
+ draw_session->line_to (p.x, p.y);
+ else
+ last_offcurve = p;
+ }
+ }
+
+ if (point.is_end_point)
+ {
+ if (first_offcurve && last_offcurve)
+ {
+ optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve = optional_point_t ();
+ /* now check the rest */
+ }
+
+ if (first_offcurve && first_oncurve)
+ draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else if (last_offcurve && first_oncurve)
+ {
+ 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)
+ {
+ float x = first_offcurve.x, y = first_offcurve.y;
+ draw_session->move_to (x, y);
+ draw_session->quadratic_to (x, y, x, y);
+ }
+
+ /* Getting ready for the next contour */
+ first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
+ draw_session->close_path ();
+ }
+ }
+ void points_end () {}
+
+ bool is_consuming_contour_points () { return true; }
+ contour_point_t *get_phantoms_sink () { return nullptr; }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_PATH_BUILDER_HH */
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/classdef-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh
new file mode 100644
index 0000000000..c2e24a7067
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh
@@ -0,0 +1,216 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "graph.hh"
+#include "../hb-ot-layout-common.hh"
+
+#ifndef GRAPH_CLASSDEF_GRAPH_HH
+#define GRAPH_CLASSDEF_GRAPH_HH
+
+namespace graph {
+
+struct ClassDefFormat1 : public OT::ClassDefFormat1_3<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ constexpr unsigned min_size = OT::ClassDefFormat1_3<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+ return vertex_len >= min_size + classValue.get_size () - classValue.len.get_size ();
+ }
+};
+
+struct ClassDefFormat2 : public OT::ClassDefFormat2_4<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ constexpr unsigned min_size = OT::ClassDefFormat2_4<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+ return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
+ }
+};
+
+struct ClassDef : public OT::ClassDef
+{
+ template<typename It>
+ static bool add_class_def (gsubgpos_graph_context_t& c,
+ unsigned parent_id,
+ unsigned link_position,
+ It glyph_and_class,
+ unsigned max_size)
+ {
+ unsigned class_def_prime_id = c.graph.new_node (nullptr, nullptr);
+ auto& class_def_prime_vertex = c.graph.vertices_[class_def_prime_id];
+ if (!make_class_def (c, glyph_and_class, class_def_prime_id, max_size))
+ return false;
+
+ auto* class_def_link = c.graph.vertices_[parent_id].obj.real_links.push ();
+ class_def_link->width = SmallTypes::size;
+ class_def_link->objidx = class_def_prime_id;
+ class_def_link->position = link_position;
+ class_def_prime_vertex.parents.push (parent_id);
+
+ return true;
+ }
+
+ template<typename It>
+ static bool make_class_def (gsubgpos_graph_context_t& c,
+ It glyph_and_class,
+ unsigned dest_obj,
+ unsigned max_size)
+ {
+ char* buffer = (char*) hb_calloc (1, max_size);
+ hb_serialize_context_t serializer (buffer, max_size);
+ OT::ClassDef_serialize (&serializer, glyph_and_class);
+ serializer.end_serialize ();
+ if (serializer.in_error ())
+ {
+ hb_free (buffer);
+ return false;
+ }
+
+ hb_bytes_t class_def_copy = serializer.copy_bytes ();
+ c.add_buffer ((char *) class_def_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
+
+ auto& obj = c.graph.vertices_[dest_obj].obj;
+ obj.head = (char *) class_def_copy.arrayZ;
+ obj.tail = obj.head + class_def_copy.length;
+
+ hb_free (buffer);
+ return true;
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::ClassDef::min_size) return false;
+ switch (u.format)
+ {
+ case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
+ case 2: return ((ClassDefFormat2*)this)->sanitize (vertex);
+#ifndef HB_NO_BEYOND_64K
+ // Not currently supported
+ case 3:
+ case 4:
+#endif
+ default: return false;
+ }
+ }
+};
+
+
+struct class_def_size_estimator_t
+{
+ template<typename It>
+ class_def_size_estimator_t (It glyph_and_class)
+ : gids_consecutive (true), num_ranges_per_class (), glyphs_per_class ()
+ {
+ unsigned last_gid = (unsigned) -1;
+ for (auto p : + glyph_and_class)
+ {
+ unsigned gid = p.first;
+ unsigned klass = p.second;
+
+ if (last_gid != (unsigned) -1 && gid != last_gid + 1)
+ gids_consecutive = false;
+ last_gid = gid;
+
+ hb_set_t* glyphs;
+ if (glyphs_per_class.has (klass, &glyphs) && glyphs) {
+ glyphs->add (gid);
+ continue;
+ }
+
+ hb_set_t new_glyphs;
+ new_glyphs.add (gid);
+ glyphs_per_class.set (klass, std::move (new_glyphs));
+ }
+
+ if (in_error ()) return;
+
+ for (unsigned klass : glyphs_per_class.keys ())
+ {
+ if (!klass) continue; // class 0 doesn't get encoded.
+
+ const hb_set_t& glyphs = glyphs_per_class.get (klass);
+ hb_codepoint_t start = HB_SET_VALUE_INVALID;
+ hb_codepoint_t end = HB_SET_VALUE_INVALID;
+
+ unsigned count = 0;
+ while (glyphs.next_range (&start, &end))
+ count++;
+
+ num_ranges_per_class.set (klass, count);
+ }
+ }
+
+ // Incremental increase in the Coverage and ClassDef table size
+ // (worst case) if all glyphs associated with 'klass' were added.
+ unsigned incremental_coverage_size (unsigned klass) const
+ {
+ // Coverage takes 2 bytes per glyph worst case,
+ return 2 * glyphs_per_class.get (klass).get_population ();
+ }
+
+ // Incremental increase in the Coverage and ClassDef table size
+ // (worst case) if all glyphs associated with 'klass' were added.
+ unsigned incremental_class_def_size (unsigned klass) const
+ {
+ // ClassDef takes 6 bytes per range
+ unsigned class_def_2_size = 6 * num_ranges_per_class.get (klass);
+ if (gids_consecutive)
+ {
+ // ClassDef1 takes 2 bytes per glyph, but only can be used
+ // when gids are consecutive.
+ return hb_min (2 * glyphs_per_class.get (klass).get_population (), class_def_2_size);
+ }
+
+ return class_def_2_size;
+ }
+
+ bool in_error ()
+ {
+ if (num_ranges_per_class.in_error ()) return true;
+ if (glyphs_per_class.in_error ()) return true;
+
+ for (const hb_set_t& s : glyphs_per_class.values ())
+ {
+ if (s.in_error ()) return true;
+ }
+ return false;
+ }
+
+ private:
+ bool gids_consecutive;
+ hb_hashmap_t<unsigned, unsigned> num_ranges_per_class;
+ hb_hashmap_t<unsigned, hb_set_t> glyphs_per_class;
+};
+
+
+}
+
+#endif // GRAPH_CLASSDEF_GRAPH_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh
new file mode 100644
index 0000000000..49d0936315
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh
@@ -0,0 +1,152 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "graph.hh"
+#include "../OT/Layout/Common/Coverage.hh"
+
+#ifndef GRAPH_COVERAGE_GRAPH_HH
+#define GRAPH_COVERAGE_GRAPH_HH
+
+namespace graph {
+
+struct CoverageFormat1 : public OT::Layout::Common::CoverageFormat1_3<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+ return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size ();
+ }
+};
+
+struct CoverageFormat2 : public OT::Layout::Common::CoverageFormat2_4<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+ return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
+ }
+};
+
+struct Coverage : public OT::Layout::Common::Coverage
+{
+ static Coverage* clone_coverage (gsubgpos_graph_context_t& c,
+ unsigned coverage_id,
+ unsigned new_parent_id,
+ unsigned link_position,
+ unsigned start, unsigned end)
+
+ {
+ unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
+ auto& coverage_v = c.graph.vertices_[coverage_id];
+ Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
+ if (!coverage_table || !coverage_table->sanitize (coverage_v))
+ return nullptr;
+
+ auto new_coverage =
+ + hb_zip (coverage_table->iter (), hb_range ())
+ | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
+ return p.second >= start && p.second < end;
+ })
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ return add_coverage (c, new_parent_id, link_position, new_coverage, coverage_size);
+ }
+
+ template<typename It>
+ static Coverage* add_coverage (gsubgpos_graph_context_t& c,
+ unsigned parent_id,
+ unsigned link_position,
+ It glyphs,
+ unsigned max_size)
+ {
+ unsigned coverage_prime_id = c.graph.new_node (nullptr, nullptr);
+ auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id];
+ if (!make_coverage (c, glyphs, coverage_prime_id, max_size))
+ return nullptr;
+
+ auto* coverage_link = c.graph.vertices_[parent_id].obj.real_links.push ();
+ coverage_link->width = SmallTypes::size;
+ coverage_link->objidx = coverage_prime_id;
+ coverage_link->position = link_position;
+ coverage_prime_vertex.parents.push (parent_id);
+
+ return (Coverage*) coverage_prime_vertex.obj.head;
+ }
+
+ template<typename It>
+ static bool make_coverage (gsubgpos_graph_context_t& c,
+ It glyphs,
+ unsigned dest_obj,
+ unsigned max_size)
+ {
+ char* buffer = (char*) hb_calloc (1, max_size);
+ hb_serialize_context_t serializer (buffer, max_size);
+ OT::Layout::Common::Coverage_serialize (&serializer, glyphs);
+ serializer.end_serialize ();
+ if (serializer.in_error ())
+ {
+ hb_free (buffer);
+ return false;
+ }
+
+ hb_bytes_t coverage_copy = serializer.copy_bytes ();
+ c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
+
+ auto& obj = c.graph.vertices_[dest_obj].obj;
+ obj.head = (char *) coverage_copy.arrayZ;
+ obj.tail = obj.head + coverage_copy.length;
+
+ hb_free (buffer);
+ return true;
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::Layout::Common::Coverage::min_size) return false;
+ switch (u.format)
+ {
+ case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
+ case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
+#ifndef HB_NO_BEYOND_64K
+ // Not currently supported
+ case 3:
+ case 4:
+#endif
+ default: return false;
+ }
+ }
+};
+
+
+}
+
+#endif // GRAPH_COVERAGE_GRAPH_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh
new file mode 100644
index 0000000000..38ca5db096
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh
@@ -0,0 +1,1392 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "../hb-set.hh"
+#include "../hb-priority-queue.hh"
+#include "../hb-serialize.hh"
+
+#ifndef GRAPH_GRAPH_HH
+#define GRAPH_GRAPH_HH
+
+namespace graph {
+
+/**
+ * Represents a serialized table in the form of a graph.
+ * Provides methods for modifying and reordering the graph.
+ */
+struct graph_t
+{
+ struct vertex_t
+ {
+ hb_serialize_context_t::object_t obj;
+ int64_t distance = 0 ;
+ int64_t space = 0 ;
+ hb_vector_t<unsigned> parents;
+ unsigned start = 0;
+ unsigned end = 0;
+ unsigned priority = 0;
+
+
+ bool link_positions_valid (unsigned num_objects, bool removed_nil)
+ {
+ hb_set_t assigned_bytes;
+ for (const auto& l : obj.real_links)
+ {
+ if (l.objidx >= num_objects
+ || (removed_nil && !l.objidx))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Invalid object index.");
+ return false;
+ }
+
+ unsigned start = l.position;
+ unsigned end = start + l.width - 1;
+
+ if (unlikely (l.width < 2 || l.width > 4))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Invalid link width.");
+ return false;
+ }
+
+ if (unlikely (end >= table_size ()))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Link position is out of bounds.");
+ return false;
+ }
+
+ if (unlikely (assigned_bytes.intersects (start, end)))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Found offsets whose positions overlap.");
+ return false;
+ }
+
+ assigned_bytes.add_range (start, end);
+ }
+
+ return !assigned_bytes.in_error ();
+ }
+
+ void normalize ()
+ {
+ obj.real_links.qsort ();
+ for (auto& l : obj.real_links)
+ {
+ for (unsigned i = 0; i < l.width; i++)
+ {
+ obj.head[l.position + i] = 0;
+ }
+ }
+ }
+
+ bool equals (const vertex_t& other,
+ const graph_t& graph,
+ const graph_t& other_graph,
+ unsigned depth) const
+ {
+ if (!(as_bytes () == other.as_bytes ()))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "vertex [%lu] bytes != [%lu] bytes, depth = %u",
+ (unsigned long) table_size (),
+ (unsigned long) other.table_size (),
+ depth);
+
+ auto a = as_bytes ();
+ auto b = other.as_bytes ();
+ while (a || b)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " 0x%x %s 0x%x", (unsigned) *a, (*a == *b) ? "==" : "!=", (unsigned) *b);
+ a++;
+ b++;
+ }
+ return false;
+ }
+
+ return links_equal (obj.real_links, other.obj.real_links, graph, other_graph, depth);
+ }
+
+ hb_bytes_t as_bytes () const
+ {
+ return hb_bytes_t (obj.head, table_size ());
+ }
+
+ friend void swap (vertex_t& a, vertex_t& b)
+ {
+ hb_swap (a.obj, b.obj);
+ hb_swap (a.distance, b.distance);
+ hb_swap (a.space, b.space);
+ hb_swap (a.parents, b.parents);
+ hb_swap (a.start, b.start);
+ hb_swap (a.end, b.end);
+ hb_swap (a.priority, b.priority);
+ }
+
+ hb_hashmap_t<unsigned, unsigned>
+ position_to_index_map () const
+ {
+ hb_hashmap_t<unsigned, unsigned> result;
+
+ for (const auto& l : obj.real_links) {
+ result.set (l.position, l.objidx);
+ }
+
+ return result;
+ }
+
+ bool is_shared () const
+ {
+ return parents.length > 1;
+ }
+
+ unsigned incoming_edges () const
+ {
+ return parents.length;
+ }
+
+ void remove_parent (unsigned parent_index)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ {
+ if (parents[i] != parent_index) continue;
+ parents.remove_unordered (i);
+ break;
+ }
+ }
+
+ void remove_real_link (unsigned child_index, const void* offset)
+ {
+ for (unsigned i = 0; i < obj.real_links.length; i++)
+ {
+ auto& link = obj.real_links.arrayZ[i];
+ if (link.objidx != child_index)
+ continue;
+
+ if ((obj.head + link.position) != offset)
+ continue;
+
+ obj.real_links.remove_unordered (i);
+ return;
+ }
+ }
+
+ void remap_parents (const hb_vector_t<unsigned>& id_map)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ parents[i] = id_map[parents[i]];
+ }
+
+ void remap_parent (unsigned old_index, unsigned new_index)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ {
+ if (parents[i] == old_index)
+ parents[i] = new_index;
+ }
+ }
+
+ bool is_leaf () const
+ {
+ return !obj.real_links.length && !obj.virtual_links.length;
+ }
+
+ bool raise_priority ()
+ {
+ if (has_max_priority ()) return false;
+ priority++;
+ return true;
+ }
+
+ bool has_max_priority () const {
+ return priority >= 3;
+ }
+
+ size_t table_size () const {
+ return obj.tail - obj.head;
+ }
+
+ int64_t modified_distance (unsigned order) const
+ {
+ // TODO(garretrieger): once priority is high enough, should try
+ // setting distance = 0 which will force to sort immediately after
+ // it's parent where possible.
+
+ int64_t modified_distance =
+ hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF);
+ if (has_max_priority ()) {
+ modified_distance = 0;
+ }
+ return (modified_distance << 18) | (0x003FFFF & order);
+ }
+
+ int64_t distance_modifier () const
+ {
+ if (!priority) return 0;
+ int64_t table_size = obj.tail - obj.head;
+
+ if (priority == 1)
+ return -table_size / 2;
+
+ return -table_size;
+ }
+
+ private:
+ bool links_equal (const hb_vector_t<hb_serialize_context_t::object_t::link_t>& this_links,
+ const hb_vector_t<hb_serialize_context_t::object_t::link_t>& other_links,
+ const graph_t& graph,
+ const graph_t& other_graph,
+ unsigned depth) const
+ {
+ auto a = this_links.iter ();
+ auto b = other_links.iter ();
+
+ while (a && b)
+ {
+ const auto& link_a = *a;
+ const auto& link_b = *b;
+
+ if (link_a.width != link_b.width ||
+ link_a.is_signed != link_b.is_signed ||
+ link_a.whence != link_b.whence ||
+ link_a.position != link_b.position ||
+ link_a.bias != link_b.bias)
+ return false;
+
+ if (!graph.vertices_[link_a.objidx].equals (
+ other_graph.vertices_[link_b.objidx], graph, other_graph, depth + 1))
+ return false;
+
+ a++;
+ b++;
+ }
+
+ if (bool (a) != bool (b))
+ return false;
+
+ return true;
+ }
+ };
+
+ template <typename T>
+ struct vertex_and_table_t
+ {
+ vertex_and_table_t () : index (0), vertex (nullptr), table (nullptr)
+ {}
+
+ unsigned index;
+ vertex_t* vertex;
+ T* table;
+
+ operator bool () {
+ return table && vertex;
+ }
+ };
+
+ /*
+ * A topological sorting of an object graph. Ordered
+ * in reverse serialization order (first object in the
+ * serialization is at the end of the list). This matches
+ * the 'packed' object stack used internally in the
+ * serializer
+ */
+ template<typename T>
+ graph_t (const T& objects)
+ : parents_invalid (true),
+ distance_invalid (true),
+ positions_invalid (true),
+ successful (true),
+ buffers ()
+ {
+ num_roots_for_space_.push (1);
+ bool removed_nil = false;
+ vertices_.alloc (objects.length);
+ vertices_scratch_.alloc (objects.length);
+ for (unsigned i = 0; i < objects.length; i++)
+ {
+ // If this graph came from a serialization buffer object 0 is the
+ // nil object. We don't need it for our purposes here so drop it.
+ if (i == 0 && !objects[i])
+ {
+ removed_nil = true;
+ continue;
+ }
+
+ vertex_t* v = vertices_.push ();
+ if (check_success (!vertices_.in_error ()))
+ v->obj = *objects[i];
+
+ check_success (v->link_positions_valid (objects.length, removed_nil));
+
+ if (!removed_nil) continue;
+ // Fix indices to account for removed nil object.
+ for (auto& l : v->obj.all_links_writer ()) {
+ l.objidx--;
+ }
+ }
+ }
+
+ ~graph_t ()
+ {
+ vertices_.fini ();
+ for (char* b : buffers)
+ hb_free (b);
+ }
+
+ bool operator== (const graph_t& other) const
+ {
+ return root ().equals (other.root (), *this, other, 0);
+ }
+
+ // Sorts links of all objects in a consistent manner and zeroes all offsets.
+ void normalize ()
+ {
+ for (auto& v : vertices_.writer ())
+ v.normalize ();
+ }
+
+ bool in_error () const
+ {
+ return !successful ||
+ vertices_.in_error () ||
+ num_roots_for_space_.in_error ();
+ }
+
+ const vertex_t& root () const
+ {
+ return vertices_[root_idx ()];
+ }
+
+ unsigned root_idx () const
+ {
+ // Object graphs are in reverse order, the first object is at the end
+ // of the vector. Since the graph is topologically sorted it's safe to
+ // assume the first object has no incoming edges.
+ return vertices_.length - 1;
+ }
+
+ const hb_serialize_context_t::object_t& object (unsigned i) const
+ {
+ return vertices_[i].obj;
+ }
+
+ void add_buffer (char* buffer)
+ {
+ buffers.push (buffer);
+ }
+
+ /*
+ * Adds a 16 bit link from parent_id to child_id
+ */
+ template<typename T>
+ void add_link (T* offset,
+ unsigned parent_id,
+ unsigned child_id)
+ {
+ auto& v = vertices_[parent_id];
+ auto* link = v.obj.real_links.push ();
+ link->width = 2;
+ link->objidx = child_id;
+ link->position = (char*) offset - (char*) v.obj.head;
+ vertices_[child_id].parents.push (parent_id);
+ }
+
+ /*
+ * Generates a new topological sorting of graph ordered by the shortest
+ * distance to each node if positions are marked as invalid.
+ */
+ void sort_shortest_distance_if_needed ()
+ {
+ if (!positions_invalid) return;
+ sort_shortest_distance ();
+ }
+
+
+ /*
+ * Generates a new topological sorting of graph ordered by the shortest
+ * distance to each node.
+ */
+ void sort_shortest_distance ()
+ {
+ positions_invalid = true;
+
+ if (vertices_.length <= 1) {
+ // Graph of 1 or less doesn't need sorting.
+ return;
+ }
+
+ update_distances ();
+
+ hb_priority_queue_t queue;
+ hb_vector_t<vertex_t> &sorted_graph = vertices_scratch_;
+ if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
+ hb_vector_t<unsigned> id_map;
+ if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
+
+ hb_vector_t<unsigned> removed_edges;
+ if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
+ update_parents ();
+
+ queue.insert (root ().modified_distance (0), root_idx ());
+ int new_id = root_idx ();
+ unsigned order = 1;
+ while (!queue.in_error () && !queue.is_empty ())
+ {
+ unsigned next_id = queue.pop_minimum().second;
+
+ hb_swap (sorted_graph[new_id], vertices_[next_id]);
+ const vertex_t& next = sorted_graph[new_id];
+
+ if (unlikely (!check_success(new_id >= 0))) {
+ // We are out of ids. Which means we've visited a node more than once.
+ // This graph contains a cycle which is not allowed.
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Invalid graph. Contains cycle.");
+ return;
+ }
+
+ id_map[next_id] = new_id--;
+
+ for (const auto& link : next.obj.all_links ()) {
+ removed_edges[link.objidx]++;
+ if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
+ // Add the order that the links were encountered to the priority.
+ // This ensures that ties between priorities objects are broken in a consistent
+ // way. More specifically this is set up so that if a set of objects have the same
+ // distance they'll be added to the topological order in the order that they are
+ // referenced from the parent object.
+ queue.insert (vertices_[link.objidx].modified_distance (order++),
+ link.objidx);
+ }
+ }
+
+ check_success (!queue.in_error ());
+ check_success (!sorted_graph.in_error ());
+
+ remap_all_obj_indices (id_map, &sorted_graph);
+ hb_swap (vertices_, sorted_graph);
+
+ if (!check_success (new_id == -1))
+ print_orphaned_nodes ();
+ }
+
+ /*
+ * Finds the set of nodes (placed into roots) that should be assigned unique spaces.
+ * More specifically this looks for the top most 24 bit or 32 bit links in the graph.
+ * Some special casing is done that is specific to the layout of GSUB/GPOS tables.
+ */
+ void find_space_roots (hb_set_t& visited, hb_set_t& roots)
+ {
+ int root_index = (int) root_idx ();
+ for (int i = root_index; i >= 0; i--)
+ {
+ if (visited.has (i)) continue;
+
+ // Only real links can form 32 bit spaces
+ for (auto& l : vertices_[i].obj.real_links)
+ {
+ if (l.is_signed || l.width < 3)
+ continue;
+
+ if (i == root_index && l.width == 3)
+ // Ignore 24bit links from the root node, this skips past the single 24bit
+ // pointer to the lookup list.
+ continue;
+
+ if (l.width == 3)
+ {
+ // A 24bit offset forms a root, unless there is 32bit offsets somewhere
+ // in it's subgraph, then those become the roots instead. This is to make sure
+ // that extension subtables beneath a 24bit lookup become the spaces instead
+ // of the offset to the lookup.
+ hb_set_t sub_roots;
+ find_32bit_roots (l.objidx, sub_roots);
+ if (sub_roots) {
+ for (unsigned sub_root_idx : sub_roots) {
+ roots.add (sub_root_idx);
+ find_subgraph (sub_root_idx, visited);
+ }
+ continue;
+ }
+ }
+
+ roots.add (l.objidx);
+ find_subgraph (l.objidx, visited);
+ }
+ }
+ }
+
+ template <typename T, typename ...Ts>
+ vertex_and_table_t<T> as_table (unsigned parent, const void* offset, Ts... ds)
+ {
+ return as_table_from_index<T> (index_for_offset (parent, offset), std::forward<Ts>(ds)...);
+ }
+
+ template <typename T, typename ...Ts>
+ vertex_and_table_t<T> as_mutable_table (unsigned parent, const void* offset, Ts... ds)
+ {
+ return as_table_from_index<T> (mutable_index_for_offset (parent, offset), std::forward<Ts>(ds)...);
+ }
+
+ template <typename T, typename ...Ts>
+ vertex_and_table_t<T> as_table_from_index (unsigned index, Ts... ds)
+ {
+ if (index >= vertices_.length)
+ return vertex_and_table_t<T> ();
+
+ vertex_and_table_t<T> r;
+ r.vertex = &vertices_[index];
+ r.table = (T*) r.vertex->obj.head;
+ r.index = index;
+ if (!r.table)
+ return vertex_and_table_t<T> ();
+
+ if (!r.table->sanitize (*(r.vertex), std::forward<Ts>(ds)...))
+ return vertex_and_table_t<T> ();
+
+ return r;
+ }
+
+ // Finds the object id of the object pointed to by the offset at 'offset'
+ // within object[node_idx].
+ unsigned index_for_offset (unsigned node_idx, const void* offset) const
+ {
+ const auto& node = object (node_idx);
+ if (offset < node.head || offset >= node.tail) return -1;
+
+ unsigned length = node.real_links.length;
+ for (unsigned i = 0; i < length; i++)
+ {
+ // Use direct access for increased performance, this is a hot method.
+ const auto& link = node.real_links.arrayZ[i];
+ if (offset != node.head + link.position)
+ continue;
+ return link.objidx;
+ }
+
+ return -1;
+ }
+
+ // Finds the object id of the object pointed to by the offset at 'offset'
+ // within object[node_idx]. Ensures that the returned object is safe to mutate.
+ // That is, if the original child object is shared by parents other than node_idx
+ // it will be duplicated and the duplicate will be returned instead.
+ unsigned mutable_index_for_offset (unsigned node_idx, const void* offset)
+ {
+ unsigned child_idx = index_for_offset (node_idx, offset);
+ auto& child = vertices_[child_idx];
+ for (unsigned p : child.parents)
+ {
+ if (p != node_idx) {
+ return duplicate (node_idx, child_idx);
+ }
+ }
+
+ return child_idx;
+ }
+
+
+ /*
+ * Assign unique space numbers to each connected subgraph of 24 bit and/or 32 bit offset(s).
+ * Currently, this is implemented specifically tailored to the structure of a GPOS/GSUB
+ * (including with 24bit offsets) table.
+ */
+ bool assign_spaces ()
+ {
+ update_parents ();
+
+ hb_set_t visited;
+ hb_set_t roots;
+ find_space_roots (visited, roots);
+
+ // Mark everything not in the subgraphs of the roots as visited. This prevents
+ // subgraphs from being connected via nodes not in those subgraphs.
+ visited.invert ();
+
+ if (!roots) return false;
+
+ while (roots)
+ {
+ uint32_t next = HB_SET_VALUE_INVALID;
+ if (unlikely (!check_success (!roots.in_error ()))) break;
+ if (!roots.next (&next)) break;
+
+ hb_set_t connected_roots;
+ find_connected_nodes (next, roots, visited, connected_roots);
+ if (unlikely (!check_success (!connected_roots.in_error ()))) break;
+
+ isolate_subgraph (connected_roots);
+ if (unlikely (!check_success (!connected_roots.in_error ()))) break;
+
+ unsigned next_space = this->next_space ();
+ num_roots_for_space_.push (0);
+ for (unsigned root : connected_roots)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space);
+ vertices_[root].space = next_space;
+ num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1;
+ distance_invalid = true;
+ positions_invalid = true;
+ }
+
+ // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space
+ // into the 32 bit space as needed, instead of using isolation.
+ }
+
+
+
+ return true;
+ }
+
+ /*
+ * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph
+ * that originate from outside of the subgraph will be removed by duplicating the linked to
+ * object.
+ *
+ * Indices stored in roots will be updated if any of the roots are duplicated to new indices.
+ */
+ bool isolate_subgraph (hb_set_t& roots)
+ {
+ update_parents ();
+ hb_map_t subgraph;
+
+ // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these
+ // set the subgraph incoming edge count to match all of root_idx's incoming edges
+ hb_set_t parents;
+ for (unsigned root_idx : roots)
+ {
+ subgraph.set (root_idx, wide_parents (root_idx, parents));
+ find_subgraph (root_idx, subgraph);
+ }
+
+ unsigned original_root_idx = root_idx ();
+ hb_map_t index_map;
+ bool made_changes = false;
+ for (auto entry : subgraph.iter ())
+ {
+ const auto& node = vertices_[entry.first];
+ unsigned subgraph_incoming_edges = entry.second;
+
+ if (subgraph_incoming_edges < node.incoming_edges ())
+ {
+ // Only de-dup objects with incoming links from outside the subgraph.
+ made_changes = true;
+ duplicate_subgraph (entry.first, index_map);
+ }
+ }
+
+ if (in_error ())
+ return false;
+
+ if (!made_changes)
+ return false;
+
+ if (original_root_idx != root_idx ()
+ && parents.has (original_root_idx))
+ {
+ // If the root idx has changed since parents was determined, update root idx in parents
+ parents.add (root_idx ());
+ parents.del (original_root_idx);
+ }
+
+ auto new_subgraph =
+ + subgraph.keys ()
+ | hb_map([&] (uint32_t node_idx) {
+ const uint32_t *v;
+ if (index_map.has (node_idx, &v)) return *v;
+ return node_idx;
+ })
+ ;
+
+ remap_obj_indices (index_map, new_subgraph);
+ remap_obj_indices (index_map, parents.iter (), true);
+
+ // Update roots set with new indices as needed.
+ uint32_t next = HB_SET_VALUE_INVALID;
+ while (roots.next (&next))
+ {
+ const uint32_t *v;
+ if (index_map.has (next, &v))
+ {
+ roots.del (next);
+ roots.add (*v);
+ }
+ }
+
+ return true;
+ }
+
+ void find_subgraph (unsigned node_idx, hb_map_t& subgraph)
+ {
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ {
+ const uint32_t *v;
+ if (subgraph.has (link.objidx, &v))
+ {
+ subgraph.set (link.objidx, *v + 1);
+ continue;
+ }
+ subgraph.set (link.objidx, 1);
+ find_subgraph (link.objidx, subgraph);
+ }
+ }
+
+ void find_subgraph (unsigned node_idx, hb_set_t& subgraph)
+ {
+ if (subgraph.has (node_idx)) return;
+ subgraph.add (node_idx);
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ find_subgraph (link.objidx, subgraph);
+ }
+
+ size_t find_subgraph_size (unsigned node_idx, hb_set_t& subgraph, unsigned max_depth = -1)
+ {
+ if (subgraph.has (node_idx)) return 0;
+ subgraph.add (node_idx);
+
+ const auto& o = vertices_[node_idx].obj;
+ size_t size = o.tail - o.head;
+ if (max_depth == 0)
+ return size;
+
+ for (const auto& link : o.all_links ())
+ size += find_subgraph_size (link.objidx, subgraph, max_depth - 1);
+ return size;
+ }
+
+ /*
+ * Finds the topmost children of 32bit offsets in the subgraph starting
+ * at node_idx. Found indices are placed into 'found'.
+ */
+ void find_32bit_roots (unsigned node_idx, hb_set_t& found)
+ {
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ {
+ if (!link.is_signed && link.width == 4) {
+ found.add (link.objidx);
+ continue;
+ }
+ find_32bit_roots (link.objidx, found);
+ }
+ }
+
+ /*
+ * Moves the child of old_parent_idx pointed to by old_offset to a new
+ * vertex at the new_offset.
+ */
+ template<typename O>
+ void move_child (unsigned old_parent_idx,
+ const O* old_offset,
+ unsigned new_parent_idx,
+ const O* new_offset)
+ {
+ distance_invalid = true;
+ positions_invalid = true;
+
+ auto& old_v = vertices_[old_parent_idx];
+ auto& new_v = vertices_[new_parent_idx];
+
+ unsigned child_id = index_for_offset (old_parent_idx,
+ old_offset);
+
+ auto* new_link = new_v.obj.real_links.push ();
+ new_link->width = O::static_size;
+ new_link->objidx = child_id;
+ new_link->position = (const char*) new_offset - (const char*) new_v.obj.head;
+
+ auto& child = vertices_[child_id];
+ child.parents.push (new_parent_idx);
+
+ old_v.remove_real_link (child_id, old_offset);
+ child.remove_parent (old_parent_idx);
+ }
+
+ /*
+ * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
+ * links. index_map is updated with mappings from old id to new id. If a duplication has already
+ * been performed for a given index, then it will be skipped.
+ */
+ void duplicate_subgraph (unsigned node_idx, hb_map_t& index_map)
+ {
+ if (index_map.has (node_idx))
+ return;
+
+ 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);
+ }
+ }
+
+ /*
+ * Creates a copy of node_idx and returns it's new index.
+ */
+ unsigned duplicate (unsigned node_idx)
+ {
+ positions_invalid = true;
+ distance_invalid = true;
+
+ auto* clone = vertices_.push ();
+ auto& child = vertices_[node_idx];
+ if (vertices_.in_error ()) {
+ return -1;
+ }
+
+ clone->obj.head = child.obj.head;
+ clone->obj.tail = child.obj.tail;
+ clone->distance = child.distance;
+ clone->space = child.space;
+ clone->parents.reset ();
+
+ unsigned clone_idx = vertices_.length - 2;
+ for (const auto& l : child.obj.real_links)
+ {
+ clone->obj.real_links.push (l);
+ vertices_[l.objidx].parents.push (clone_idx);
+ }
+ for (const auto& l : child.obj.virtual_links)
+ {
+ clone->obj.virtual_links.push (l);
+ vertices_[l.objidx].parents.push (clone_idx);
+ }
+
+ check_success (!clone->obj.real_links.in_error ());
+ check_success (!clone->obj.virtual_links.in_error ());
+
+ // The last object is the root of the graph, so swap back the root to the end.
+ // The root's obj idx does change, however since it's root nothing else refers to it.
+ // all other obj idx's will be unaffected.
+ hb_swap (vertices_[vertices_.length - 2], *clone);
+
+ // Since the root moved, update the parents arrays of all children on the root.
+ for (const auto& l : root ().obj.all_links ())
+ vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
+
+ return clone_idx;
+ }
+
+ /*
+ * Creates a copy of child and re-assigns the link from
+ * parent to the clone. The copy is a shallow copy, objects
+ * linked from child are not duplicated.
+ */
+ unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx)
+ {
+ unsigned new_idx = duplicate (parent_idx, child_idx);
+ if (new_idx == (unsigned) -1) return child_idx;
+ return new_idx;
+ }
+
+
+ /*
+ * Creates a copy of child and re-assigns the link from
+ * parent to the clone. The copy is a shallow copy, objects
+ * linked from child are not duplicated.
+ */
+ unsigned duplicate (unsigned parent_idx, unsigned child_idx)
+ {
+ update_parents ();
+
+ unsigned links_to_child = 0;
+ for (const auto& l : vertices_[parent_idx].obj.all_links ())
+ {
+ if (l.objidx == child_idx) links_to_child++;
+ }
+
+ if (vertices_[child_idx].incoming_edges () <= links_to_child)
+ {
+ // Can't duplicate this node, doing so would orphan the original one as all remaining links
+ // to child are from parent.
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %u => %u",
+ parent_idx, child_idx);
+ return -1;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %u => %u",
+ parent_idx, child_idx);
+
+ unsigned clone_idx = duplicate (child_idx);
+ if (clone_idx == (unsigned) -1) return false;
+ // duplicate shifts the root node idx, so if parent_idx was root update it.
+ if (parent_idx == clone_idx) parent_idx++;
+
+ auto& parent = vertices_[parent_idx];
+ for (auto& l : parent.obj.all_links_writer ())
+ {
+ if (l.objidx != child_idx)
+ continue;
+
+ reassign_link (l, parent_idx, clone_idx);
+ }
+
+ return clone_idx;
+ }
+
+
+ /*
+ * Adds a new node to the graph, not connected to anything.
+ */
+ unsigned new_node (char* head, char* tail)
+ {
+ positions_invalid = true;
+ distance_invalid = true;
+
+ auto* clone = vertices_.push ();
+ if (vertices_.in_error ()) {
+ return -1;
+ }
+
+ clone->obj.head = head;
+ clone->obj.tail = tail;
+ clone->distance = 0;
+ clone->space = 0;
+
+ unsigned clone_idx = vertices_.length - 2;
+
+ // The last object is the root of the graph, so swap back the root to the end.
+ // The root's obj idx does change, however since it's root nothing else refers to it.
+ // all other obj idx's will be unaffected.
+ hb_swap (vertices_[vertices_.length - 2], *clone);
+
+ // Since the root moved, update the parents arrays of all children on the root.
+ for (const auto& l : root ().obj.all_links ())
+ vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
+
+ return clone_idx;
+ }
+
+ /*
+ * Raises the sorting priority of all children.
+ */
+ bool raise_childrens_priority (unsigned parent_idx)
+ {
+ 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
+ // to update distances or edge counts.
+ auto& parent = vertices_[parent_idx].obj;
+ bool made_change = false;
+ for (auto& l : parent.all_links_writer ())
+ made_change |= vertices_[l.objidx].raise_priority ();
+ return made_change;
+ }
+
+ bool is_fully_connected ()
+ {
+ update_parents();
+
+ if (root().parents)
+ // Root cannot have parents.
+ return false;
+
+ for (unsigned i = 0; i < root_idx (); i++)
+ {
+ if (!vertices_[i].parents)
+ return false;
+ }
+ return true;
+ }
+
+#if 0
+ /*
+ * Saves the current graph to a packed binary format which the repacker fuzzer takes
+ * as a seed.
+ */
+ void save_fuzzer_seed (hb_tag_t tag) const
+ {
+ FILE* f = fopen ("./repacker_fuzzer_seed", "w");
+ fwrite ((void*) &tag, sizeof (tag), 1, f);
+
+ uint16_t num_objects = vertices_.length;
+ fwrite ((void*) &num_objects, sizeof (num_objects), 1, f);
+
+ for (const auto& v : vertices_)
+ {
+ uint16_t blob_size = v.table_size ();
+ fwrite ((void*) &blob_size, sizeof (blob_size), 1, f);
+ fwrite ((const void*) v.obj.head, blob_size, 1, f);
+ }
+
+ uint16_t link_count = 0;
+ for (const auto& v : vertices_)
+ link_count += v.obj.real_links.length;
+
+ fwrite ((void*) &link_count, sizeof (link_count), 1, f);
+
+ typedef struct
+ {
+ uint16_t parent;
+ uint16_t child;
+ uint16_t position;
+ uint8_t width;
+ } link_t;
+
+ for (unsigned i = 0; i < vertices_.length; i++)
+ {
+ for (const auto& l : vertices_[i].obj.real_links)
+ {
+ link_t link {
+ (uint16_t) i, (uint16_t) l.objidx,
+ (uint16_t) l.position, (uint8_t) l.width
+ };
+ fwrite ((void*) &link, sizeof (link), 1, f);
+ }
+ }
+
+ fclose (f);
+ }
+#endif
+
+ void print_orphaned_nodes ()
+ {
+ if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
+ parents_invalid = true;
+ update_parents();
+
+ if (root().parents) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Root node has incoming edges.");
+ }
+
+ for (unsigned i = 0; i < root_idx (); i++)
+ {
+ const auto& v = vertices_[i];
+ if (!v.parents)
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i);
+ }
+ }
+
+ unsigned num_roots_for_space (unsigned space) const
+ {
+ return num_roots_for_space_[space];
+ }
+
+ unsigned next_space () const
+ {
+ return num_roots_for_space_.length;
+ }
+
+ void move_to_new_space (const hb_set_t& indices)
+ {
+ num_roots_for_space_.push (0);
+ unsigned new_space = num_roots_for_space_.length - 1;
+
+ for (unsigned index : indices) {
+ auto& node = vertices_[index];
+ num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1;
+ num_roots_for_space_[new_space] = num_roots_for_space_[new_space] + 1;
+ node.space = new_space;
+ distance_invalid = true;
+ positions_invalid = true;
+ }
+ }
+
+ unsigned space_for (unsigned index, unsigned* root = nullptr) const
+ {
+ const auto& node = vertices_[index];
+ if (node.space)
+ {
+ if (root != nullptr)
+ *root = index;
+ return node.space;
+ }
+
+ if (!node.parents)
+ {
+ if (root)
+ *root = index;
+ return 0;
+ }
+
+ return space_for (node.parents[0], root);
+ }
+
+ void err_other_error () { this->successful = false; }
+
+ size_t total_size_in_bytes () const {
+ size_t total_size = 0;
+ for (unsigned i = 0; i < vertices_.length; i++) {
+ size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
+ total_size += size;
+ }
+ return total_size;
+ }
+
+
+ private:
+
+ /*
+ * Returns the numbers of incoming edges that are 24 or 32 bits wide.
+ */
+ unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
+ {
+ unsigned count = 0;
+ hb_set_t visited;
+ for (unsigned p : vertices_[node_idx].parents)
+ {
+ if (visited.has (p)) continue;
+ visited.add (p);
+
+ // Only real links can be wide
+ for (const auto& l : vertices_[p].obj.real_links)
+ {
+ if (l.objidx == node_idx
+ && (l.width == 3 || l.width == 4)
+ && !l.is_signed)
+ {
+ count++;
+ parents.add (p);
+ }
+ }
+ }
+ return count;
+ }
+
+ bool check_success (bool success)
+ { return this->successful && (success || ((void) err_other_error (), false)); }
+
+ public:
+ /*
+ * Creates a map from objid to # of incoming edges.
+ */
+ void update_parents ()
+ {
+ if (!parents_invalid) return;
+
+ for (unsigned i = 0; i < vertices_.length; i++)
+ vertices_[i].parents.reset ();
+
+ for (unsigned p = 0; p < vertices_.length; p++)
+ {
+ for (auto& l : vertices_[p].obj.all_links ())
+ {
+ vertices_[l.objidx].parents.push (p);
+ }
+ }
+
+ for (unsigned i = 0; i < vertices_.length; i++)
+ // parents arrays must be accurate or downstream operations like cycle detection
+ // and sorting won't work correctly.
+ check_success (!vertices_[i].parents.in_error ());
+
+ parents_invalid = false;
+ }
+
+ /*
+ * compute the serialized start and end positions for each vertex.
+ */
+ void update_positions ()
+ {
+ if (!positions_invalid) return;
+
+ unsigned current_pos = 0;
+ for (int i = root_idx (); i >= 0; i--)
+ {
+ auto& v = vertices_[i];
+ v.start = current_pos;
+ current_pos += v.obj.tail - v.obj.head;
+ v.end = current_pos;
+ }
+
+ positions_invalid = false;
+ }
+
+ /*
+ * Finds the distance to each object in the graph
+ * from the initial node.
+ */
+ void update_distances ()
+ {
+ if (!distance_invalid) return;
+
+ // Uses Dijkstra's algorithm to find all of the shortest distances.
+ // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
+ //
+ // Implementation Note:
+ // Since our priority queue doesn't support fast priority decreases
+ // we instead just add new entries into the queue when a priority changes.
+ // Redundant ones are filtered out later on by the visited set.
+ // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
+ // for practical performance this is faster then using a more advanced queue
+ // (such as a fibonacci queue) with a fast decrease priority.
+ for (unsigned i = 0; i < vertices_.length; i++)
+ {
+ if (i == vertices_.length - 1)
+ vertices_[i].distance = 0;
+ else
+ vertices_[i].distance = hb_int_max (int64_t);
+ }
+
+ hb_priority_queue_t queue;
+ queue.insert (0, vertices_.length - 1);
+
+ hb_vector_t<bool> visited;
+ visited.resize (vertices_.length);
+
+ while (!queue.in_error () && !queue.is_empty ())
+ {
+ unsigned next_idx = queue.pop_minimum ().second;
+ if (visited[next_idx]) continue;
+ const auto& next = vertices_[next_idx];
+ int64_t next_distance = vertices_[next_idx].distance;
+ visited[next_idx] = true;
+
+ for (const auto& link : next.obj.all_links ())
+ {
+ if (visited[link.objidx]) continue;
+
+ const auto& child = vertices_[link.objidx].obj;
+ unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
+ int64_t child_weight = (child.tail - child.head) +
+ ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
+ int64_t child_distance = next_distance + child_weight;
+
+ if (child_distance < vertices_[link.objidx].distance)
+ {
+ vertices_[link.objidx].distance = child_distance;
+ queue.insert (child_distance, link.objidx);
+ }
+ }
+ }
+
+ check_success (!queue.in_error ());
+ if (!check_success (queue.is_empty ()))
+ {
+ print_orphaned_nodes ();
+ return;
+ }
+
+ distance_invalid = false;
+ }
+
+ private:
+ /*
+ * Updates a link in the graph to point to a different object. Corrects the
+ * parents vector on the previous and new child nodes.
+ */
+ void reassign_link (hb_serialize_context_t::object_t::link_t& link,
+ unsigned parent_idx,
+ unsigned new_idx)
+ {
+ unsigned old_idx = link.objidx;
+ link.objidx = new_idx;
+ vertices_[old_idx].remove_parent (parent_idx);
+ vertices_[new_idx].parents.push (parent_idx);
+ }
+
+ /*
+ * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts.
+ */
+ template<typename Iterator, hb_requires (hb_is_iterator (Iterator))>
+ void remap_obj_indices (const hb_map_t& id_map,
+ Iterator subgraph,
+ bool only_wide = false)
+ {
+ if (!id_map) return;
+ for (unsigned i : subgraph)
+ {
+ for (auto& link : vertices_[i].obj.all_links_writer ())
+ {
+ const uint32_t *v;
+ if (!id_map.has (link.objidx, &v)) continue;
+ if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
+
+ reassign_link (link, i, *v);
+ }
+ }
+ }
+
+ /*
+ * Updates all objidx's in all links using the provided mapping.
+ */
+ void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
+ hb_vector_t<vertex_t>* sorted_graph) const
+ {
+ for (unsigned i = 0; i < sorted_graph->length; i++)
+ {
+ (*sorted_graph)[i].remap_parents (id_map);
+ for (auto& link : (*sorted_graph)[i].obj.all_links_writer ())
+ {
+ link.objidx = id_map[link.objidx];
+ }
+ }
+ }
+
+ /*
+ * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped.
+ * For this search the graph is treated as being undirected.
+ *
+ * Connected targets will be added to connected and removed from targets. All visited nodes
+ * will be added to visited.
+ */
+ void find_connected_nodes (unsigned start_idx,
+ hb_set_t& targets,
+ hb_set_t& visited,
+ hb_set_t& connected)
+ {
+ if (unlikely (!check_success (!visited.in_error ()))) return;
+ if (visited.has (start_idx)) return;
+ visited.add (start_idx);
+
+ if (targets.has (start_idx))
+ {
+ targets.del (start_idx);
+ connected.add (start_idx);
+ }
+
+ const auto& v = vertices_[start_idx];
+
+ // Graph is treated as undirected so search children and parents of start_idx
+ for (const auto& l : v.obj.all_links ())
+ find_connected_nodes (l.objidx, targets, visited, connected);
+
+ for (unsigned p : v.parents)
+ find_connected_nodes (p, targets, visited, connected);
+ }
+
+ public:
+ // TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
+ hb_vector_t<vertex_t> vertices_;
+ hb_vector_t<vertex_t> vertices_scratch_;
+ private:
+ bool parents_invalid;
+ bool distance_invalid;
+ bool positions_invalid;
+ bool successful;
+ hb_vector_t<unsigned> num_roots_for_space_;
+ hb_vector_t<char*> buffers;
+};
+
+}
+
+#endif // GRAPH_GRAPH_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/test-array.cc b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc
index 6c888138e7..b2044426d4 100644
--- a/src/3rdparty/harfbuzz-ng/src/test-array.cc
+++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc
@@ -1,5 +1,5 @@
/*
- * Copyright © 2020 Google, Inc.
+ * Copyright © 2022 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,53 +24,47 @@
* Google Author(s): Garret Rieger
*/
-#include "hb.hh"
-#include "hb-array.hh"
+#include "gsubgpos-graph.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);
-}
+namespace graph {
-static void
-test_reverse_range ()
+gsubgpos_graph_context_t::gsubgpos_graph_context_t (hb_tag_t table_tag_,
+ graph_t& graph_)
+ : table_tag (table_tag_),
+ graph (graph_),
+ lookup_list_index (0),
+ lookups ()
{
- int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- hb_array_t<int> a (values, 9);
- a.reverse(2, 6);
+ if (table_tag_ != HB_OT_TAG_GPOS
+ && table_tag_ != HB_OT_TAG_GSUB)
+ return;
- int expected_values[] = {1, 2, 6, 5, 4, 3, 7, 8, 9};
- hb_array_t<int> expected (expected_values, 9);
- assert (a == expected);
+ GSTAR* gstar = graph::GSTAR::graph_to_gstar (graph_);
+ if (gstar) {
+ gstar->find_lookups (graph, lookups);
+ lookup_list_index = gstar->get_lookup_list_index (graph_);
+ }
}
-static void
-test_reverse_invalid ()
+unsigned gsubgpos_graph_context_t::create_node (unsigned size)
{
- int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- hb_array_t<int> a (values, 9);
+ char* buffer = (char*) hb_calloc (1, size);
+ if (!buffer)
+ return -1;
- a.reverse(4, 3);
- a.reverse(2, 3);
- a.reverse(5, 5);
- a.reverse(12, 15);
+ add_buffer (buffer);
- int expected_values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- hb_array_t<int> expected (expected_values, 9);
- assert (a == expected);
+ return graph.new_node (buffer, buffer + size);
+}
+
+unsigned gsubgpos_graph_context_t::num_non_ext_subtables () {
+ unsigned count = 0;
+ for (auto l : lookups.values ())
+ {
+ if (l->is_extension (table_tag)) continue;
+ count += l->number_of_subtables ();
+ }
+ return count;
}
-int
-main (int argc, char **argv)
-{
- test_reverse ();
- test_reverse_range ();
- test_reverse_invalid ();
}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-unicode-ranges.cc b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh
index 33cac6b715..9fe9662e64 100644
--- a/src/3rdparty/harfbuzz-ng/src/test-unicode-ranges.cc
+++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2018 Google, Inc.
+ * Copyright © 2022 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,43 +24,38 @@
* Google Author(s): Garret Rieger
*/
-#include "hb.hh"
-#include "hb-ot-os2-unicode-ranges.hh"
+#include "graph.hh"
+#include "../hb-ot-layout-gsubgpos.hh"
-static void
-test (hb_codepoint_t cp, unsigned int bit)
-{
- if (OT::_hb_ot_os2_get_unicode_range_bit (cp) != bit)
- {
- 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();
- }
-}
+#ifndef GRAPH_GSUBGPOS_CONTEXT_HH
+#define GRAPH_GSUBGPOS_CONTEXT_HH
-static void
-test_get_unicode_range_bit ()
+namespace graph {
+
+struct Lookup;
+
+struct gsubgpos_graph_context_t
{
- test (0x0000, 0);
- test (0x0042, 0);
- test (0x007F, 0);
- test (0x0080, 1);
+ hb_tag_t table_tag;
+ graph_t& graph;
+ unsigned lookup_list_index;
+ hb_hashmap_t<unsigned, graph::Lookup*> lookups;
- test (0x30A0, 50);
- test (0x30B1, 50);
- test (0x30FF, 50);
- test (0x10FFFD, 90);
+ HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
+ graph_t& graph_);
- test (0x30000, -1);
- test (0x110000, -1);
-}
+ HB_INTERNAL unsigned create_node (unsigned size);
+
+ void add_buffer (char* buffer)
+ {
+ graph.add_buffer (buffer);
+ }
+
+ private:
+ HB_INTERNAL unsigned num_non_ext_subtables ();
+};
-int
-main ()
-{
- test_get_unicode_range_bit ();
- return 0;
}
+
+#endif // GRAPH_GSUBGPOS_CONTEXT
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh
new file mode 100644
index 0000000000..c170638409
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh
@@ -0,0 +1,414 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "graph.hh"
+#include "../hb-ot-layout-gsubgpos.hh"
+#include "../OT/Layout/GSUB/ExtensionSubst.hh"
+#include "gsubgpos-context.hh"
+#include "pairpos-graph.hh"
+#include "markbasepos-graph.hh"
+
+#ifndef GRAPH_GSUBGPOS_GRAPH_HH
+#define GRAPH_GSUBGPOS_GRAPH_HH
+
+namespace graph {
+
+struct Lookup;
+
+template<typename T>
+struct ExtensionFormat1 : public OT::ExtensionFormat1<T>
+{
+ void reset(unsigned type)
+ {
+ this->format = 1;
+ this->extensionLookupType = type;
+ this->extensionOffset = 0;
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ return vertex_len >= OT::ExtensionFormat1<T>::static_size;
+ }
+
+ unsigned get_lookup_type () const
+ {
+ return this->extensionLookupType;
+ }
+
+ unsigned get_subtable_index (graph_t& graph, unsigned this_index) const
+ {
+ return graph.index_for_offset (this_index, &this->extensionOffset);
+ }
+};
+
+struct Lookup : public OT::Lookup
+{
+ unsigned number_of_subtables () const
+ {
+ return subTable.len;
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::Lookup::min_size) return false;
+ return vertex_len >= this->get_size ();
+ }
+
+ bool is_extension (hb_tag_t table_tag) const
+ {
+ return lookupType == extension_type (table_tag);
+ }
+
+ bool make_extension (gsubgpos_graph_context_t& c,
+ unsigned this_index)
+ {
+ unsigned type = lookupType;
+ unsigned ext_type = extension_type (c.table_tag);
+ if (!ext_type || is_extension (c.table_tag))
+ {
+ // NOOP
+ return true;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Promoting lookup type %u (obj %u) to extension.",
+ type,
+ this_index);
+
+ for (unsigned i = 0; i < subTable.len; i++)
+ {
+ unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
+ if (!make_subtable_extension (c,
+ this_index,
+ subtable_index))
+ return false;
+ }
+
+ lookupType = ext_type;
+ return true;
+ }
+
+ bool split_subtables_if_needed (gsubgpos_graph_context_t& c,
+ unsigned this_index)
+ {
+ unsigned type = lookupType;
+ bool is_ext = is_extension (c.table_tag);
+
+ if (c.table_tag != HB_OT_TAG_GPOS)
+ return true;
+
+ if (!is_ext &&
+ type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair &&
+ type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::MarkBase)
+ return true;
+
+ hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>> all_new_subtables;
+ for (unsigned i = 0; i < subTable.len; i++)
+ {
+ unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
+ unsigned parent_index = this_index;
+ if (is_ext) {
+ unsigned ext_subtable_index = subtable_index;
+ parent_index = ext_subtable_index;
+ ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
+ (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
+ c.graph.object (ext_subtable_index).head;
+ if (!extension || !extension->sanitize (c.graph.vertices_[ext_subtable_index]))
+ continue;
+
+ subtable_index = extension->get_subtable_index (c.graph, ext_subtable_index);
+ type = extension->get_lookup_type ();
+ if (type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair
+ && type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::MarkBase)
+ continue;
+ }
+
+ hb_vector_t<unsigned> new_sub_tables;
+ switch (type)
+ {
+ case 2:
+ new_sub_tables = split_subtable<PairPos> (c, parent_index, subtable_index); break;
+ case 4:
+ new_sub_tables = split_subtable<MarkBasePos> (c, parent_index, subtable_index); break;
+ default:
+ break;
+ }
+ if (new_sub_tables.in_error ()) return false;
+ if (!new_sub_tables) continue;
+ hb_pair_t<unsigned, hb_vector_t<unsigned>>* entry = all_new_subtables.push ();
+ entry->first = i;
+ entry->second = std::move (new_sub_tables);
+ }
+
+ if (all_new_subtables) {
+ add_sub_tables (c, this_index, type, all_new_subtables);
+ }
+
+ return true;
+ }
+
+ template<typename T>
+ hb_vector_t<unsigned> split_subtable (gsubgpos_graph_context_t& c,
+ unsigned parent_idx,
+ unsigned objidx)
+ {
+ T* sub_table = (T*) c.graph.object (objidx).head;
+ if (!sub_table || !sub_table->sanitize (c.graph.vertices_[objidx]))
+ return hb_vector_t<unsigned> ();
+
+ return sub_table->split_subtables (c, parent_idx, objidx);
+ }
+
+ void add_sub_tables (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned type,
+ hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids)
+ {
+ bool is_ext = is_extension (c.table_tag);
+ auto& v = c.graph.vertices_[this_index];
+ fix_existing_subtable_links (c, this_index, subtable_ids);
+
+ unsigned new_subtable_count = 0;
+ for (const auto& p : subtable_ids)
+ new_subtable_count += p.second.length;
+
+ size_t new_size = v.table_size ()
+ + new_subtable_count * OT::Offset16::static_size;
+ char* buffer = (char*) hb_calloc (1, new_size);
+ c.add_buffer (buffer);
+ hb_memcpy (buffer, v.obj.head, v.table_size());
+
+ v.obj.head = buffer;
+ v.obj.tail = buffer + new_size;
+
+ Lookup* new_lookup = (Lookup*) buffer;
+
+ unsigned shift = 0;
+ new_lookup->subTable.len = subTable.len + new_subtable_count;
+ for (const auto& p : subtable_ids)
+ {
+ unsigned offset_index = p.first + shift + 1;
+ shift += p.second.length;
+
+ for (unsigned subtable_id : p.second)
+ {
+ if (is_ext)
+ {
+ unsigned ext_id = create_extension_subtable (c, subtable_id, type);
+ c.graph.vertices_[subtable_id].parents.push (ext_id);
+ subtable_id = ext_id;
+ }
+
+ auto* link = v.obj.real_links.push ();
+ link->width = 2;
+ link->objidx = subtable_id;
+ link->position = (char*) &new_lookup->subTable[offset_index++] -
+ (char*) new_lookup;
+ c.graph.vertices_[subtable_id].parents.push (this_index);
+ }
+ }
+
+ // Repacker sort order depends on link order, which we've messed up so resort it.
+ v.obj.real_links.qsort ();
+
+ // The head location of the lookup has changed, invalidating the lookups map entry
+ // in the context. Update the map.
+ c.lookups.set (this_index, new_lookup);
+ }
+
+ void fix_existing_subtable_links (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids)
+ {
+ auto& v = c.graph.vertices_[this_index];
+ Lookup* lookup = (Lookup*) v.obj.head;
+
+ unsigned shift = 0;
+ for (const auto& p : subtable_ids)
+ {
+ unsigned insert_index = p.first + shift;
+ unsigned pos_offset = p.second.length * OT::Offset16::static_size;
+ unsigned insert_offset = (char*) &lookup->subTable[insert_index] - (char*) lookup;
+ shift += p.second.length;
+
+ for (auto& l : v.obj.all_links_writer ())
+ {
+ if (l.position > insert_offset) l.position += pos_offset;
+ }
+ }
+ }
+
+ unsigned create_extension_subtable (gsubgpos_graph_context_t& c,
+ unsigned subtable_index,
+ unsigned type)
+ {
+ unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
+
+ unsigned ext_index = c.create_node (extension_size);
+ if (ext_index == (unsigned) -1)
+ return -1;
+
+ auto& ext_vertex = c.graph.vertices_[ext_index];
+ ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
+ (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) ext_vertex.obj.head;
+ extension->reset (type);
+
+ // Make extension point at the subtable.
+ auto* l = ext_vertex.obj.real_links.push ();
+
+ l->width = 4;
+ l->objidx = subtable_index;
+ l->position = 4;
+
+ return ext_index;
+ }
+
+ bool make_subtable_extension (gsubgpos_graph_context_t& c,
+ unsigned lookup_index,
+ unsigned subtable_index)
+ {
+ unsigned type = lookupType;
+
+ unsigned ext_index = create_extension_subtable(c, subtable_index, type);
+ if (ext_index == (unsigned) -1)
+ return false;
+
+ auto& lookup_vertex = c.graph.vertices_[lookup_index];
+ for (auto& l : lookup_vertex.obj.real_links.writer ())
+ {
+ if (l.objidx == subtable_index)
+ // Change lookup to point at the extension.
+ l.objidx = ext_index;
+ }
+
+ // Make extension point at the subtable.
+ auto& ext_vertex = c.graph.vertices_[ext_index];
+ auto& subtable_vertex = c.graph.vertices_[subtable_index];
+ ext_vertex.parents.push (lookup_index);
+ subtable_vertex.remap_parent (lookup_index, ext_index);
+
+ return true;
+ }
+
+ private:
+ unsigned extension_type (hb_tag_t table_tag) const
+ {
+ switch (table_tag)
+ {
+ case HB_OT_TAG_GPOS: return 9;
+ case HB_OT_TAG_GSUB: return 7;
+ default: return 0;
+ }
+ }
+};
+
+template <typename T>
+struct LookupList : public OT::LookupList<T>
+{
+ bool sanitize (const graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::LookupList<T>::min_size) return false;
+ return vertex_len >= OT::LookupList<T>::item_size * this->len;
+ }
+};
+
+struct GSTAR : public OT::GSUBGPOS
+{
+ static GSTAR* graph_to_gstar (graph_t& graph)
+ {
+ const auto& r = graph.root ();
+
+ GSTAR* gstar = (GSTAR*) r.obj.head;
+ if (!gstar || !gstar->sanitize (r))
+ return nullptr;
+
+ return gstar;
+ }
+
+ const void* get_lookup_list_field_offset () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.get_lookup_list_offset ();
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.get_lookup_list_offset ();
+#endif
+ default: return 0;
+ }
+ }
+
+ bool sanitize (const graph_t::vertex_t& vertex)
+ {
+ int64_t len = vertex.obj.tail - vertex.obj.head;
+ if (len < OT::GSUBGPOS::min_size) return false;
+ return len >= get_size ();
+ }
+
+ void find_lookups (graph_t& graph,
+ hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */)
+ {
+ switch (u.version.major) {
+ case 1: find_lookups<SmallTypes> (graph, lookups); break;
+#ifndef HB_NO_BEYOND_64K
+ case 2: find_lookups<MediumTypes> (graph, lookups); break;
+#endif
+ }
+ }
+
+ unsigned get_lookup_list_index (graph_t& graph)
+ {
+ return graph.index_for_offset (graph.root_idx (),
+ get_lookup_list_field_offset());
+ }
+
+ template<typename Types>
+ void find_lookups (graph_t& graph,
+ hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */)
+ {
+ unsigned lookup_list_idx = get_lookup_list_index (graph);
+ const LookupList<Types>* lookupList =
+ (const LookupList<Types>*) graph.object (lookup_list_idx).head;
+ if (!lookupList || !lookupList->sanitize (graph.vertices_[lookup_list_idx]))
+ return;
+
+ for (unsigned i = 0; i < lookupList->len; i++)
+ {
+ unsigned lookup_idx = graph.index_for_offset (lookup_list_idx, &(lookupList->arrayZ[i]));
+ Lookup* lookup = (Lookup*) graph.object (lookup_idx).head;
+ if (!lookup || !lookup->sanitize (graph.vertices_[lookup_idx])) continue;
+ lookups.set (lookup_idx, lookup);
+ }
+ }
+};
+
+
+
+
+}
+
+#endif /* GRAPH_GSUBGPOS_GRAPH_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh
new file mode 100644
index 0000000000..84ef5f71b9
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh
@@ -0,0 +1,510 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef GRAPH_MARKBASEPOS_GRAPH_HH
+#define GRAPH_MARKBASEPOS_GRAPH_HH
+
+#include "split-helpers.hh"
+#include "coverage-graph.hh"
+#include "../OT/Layout/GPOS/MarkBasePos.hh"
+#include "../OT/Layout/GPOS/PosLookupSubTable.hh"
+
+namespace graph {
+
+struct AnchorMatrix : public OT::Layout::GPOS_impl::AnchorMatrix
+{
+ bool sanitize (graph_t::vertex_t& vertex, unsigned class_count) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < AnchorMatrix::min_size) return false;
+
+ return vertex_len >= AnchorMatrix::min_size +
+ OT::Offset16::static_size * class_count * this->rows;
+ }
+
+ bool shrink (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned old_class_count,
+ unsigned new_class_count)
+ {
+ if (new_class_count >= old_class_count) return false;
+ auto& o = c.graph.vertices_[this_index].obj;
+ unsigned base_count = rows;
+ o.tail = o.head +
+ AnchorMatrix::min_size +
+ OT::Offset16::static_size * base_count * new_class_count;
+
+ // Reposition links into the new indexing scheme.
+ for (auto& link : o.real_links.writer ())
+ {
+ unsigned index = (link.position - 2) / 2;
+ unsigned base = index / old_class_count;
+ unsigned klass = index % old_class_count;
+ if (klass >= new_class_count)
+ // should have already been removed
+ return false;
+
+ unsigned new_index = base * new_class_count + klass;
+
+ link.position = (char*) &(this->matrixZ[new_index]) - (char*) this;
+ }
+
+ return true;
+ }
+
+ unsigned clone (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned start,
+ unsigned end,
+ unsigned class_count)
+ {
+ unsigned base_count = rows;
+ unsigned new_class_count = end - start;
+ unsigned size = AnchorMatrix::min_size +
+ OT::Offset16::static_size * new_class_count * rows;
+ unsigned prime_id = c.create_node (size);
+ if (prime_id == (unsigned) -1) return -1;
+ AnchorMatrix* prime = (AnchorMatrix*) c.graph.object (prime_id).head;
+ prime->rows = base_count;
+
+ auto& o = c.graph.vertices_[this_index].obj;
+ int num_links = o.real_links.length;
+ for (int i = 0; i < num_links; i++)
+ {
+ const auto& link = o.real_links[i];
+ unsigned old_index = (link.position - 2) / OT::Offset16::static_size;
+ unsigned klass = old_index % class_count;
+ if (klass < start || klass >= end) continue;
+
+ unsigned base = old_index / class_count;
+ unsigned new_klass = klass - start;
+ unsigned new_index = base * new_class_count + new_klass;
+
+
+ unsigned child_idx = link.objidx;
+ c.graph.add_link (&(prime->matrixZ[new_index]),
+ prime_id,
+ child_idx);
+
+ auto& child = c.graph.vertices_[child_idx];
+ child.remove_parent (this_index);
+
+ o.real_links.remove_unordered (i);
+ num_links--;
+ i--;
+ }
+
+ return prime_id;
+ }
+};
+
+struct MarkArray : public OT::Layout::GPOS_impl::MarkArray
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ unsigned min_size = MarkArray::min_size;
+ if (vertex_len < min_size) return false;
+
+ return vertex_len >= get_size ();
+ }
+
+ bool shrink (gsubgpos_graph_context_t& c,
+ const hb_hashmap_t<unsigned, unsigned>& mark_array_links,
+ unsigned this_index,
+ unsigned new_class_count)
+ {
+ auto& o = c.graph.vertices_[this_index].obj;
+ for (const auto& link : o.real_links)
+ c.graph.vertices_[link.objidx].remove_parent (this_index);
+ o.real_links.reset ();
+
+ unsigned new_index = 0;
+ for (const auto& record : this->iter ())
+ {
+ unsigned klass = record.klass;
+ if (klass >= new_class_count) continue;
+
+ (*this)[new_index].klass = klass;
+ unsigned position = (char*) &record.markAnchor - (char*) this;
+ unsigned* objidx;
+ if (!mark_array_links.has (position, &objidx))
+ {
+ new_index++;
+ continue;
+ }
+
+ c.graph.add_link (&(*this)[new_index].markAnchor, this_index, *objidx);
+ new_index++;
+ }
+
+ this->len = new_index;
+ o.tail = o.head + MarkArray::min_size +
+ OT::Layout::GPOS_impl::MarkRecord::static_size * new_index;
+ return true;
+ }
+
+ unsigned clone (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ const hb_hashmap_t<unsigned, unsigned>& pos_to_index,
+ hb_set_t& marks,
+ unsigned start_class)
+ {
+ unsigned size = MarkArray::min_size +
+ OT::Layout::GPOS_impl::MarkRecord::static_size *
+ marks.get_population ();
+ unsigned prime_id = c.create_node (size);
+ if (prime_id == (unsigned) -1) return -1;
+ MarkArray* prime = (MarkArray*) c.graph.object (prime_id).head;
+ prime->len = marks.get_population ();
+
+
+ unsigned i = 0;
+ for (hb_codepoint_t mark : marks)
+ {
+ (*prime)[i].klass = (*this)[mark].klass - start_class;
+ unsigned offset_pos = (char*) &((*this)[mark].markAnchor) - (char*) this;
+ unsigned* anchor_index;
+ if (pos_to_index.has (offset_pos, &anchor_index))
+ c.graph.move_child (this_index,
+ &((*this)[mark].markAnchor),
+ prime_id,
+ &((*prime)[i].markAnchor));
+
+ i++;
+ }
+
+ return prime_id;
+ }
+};
+
+struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ return vertex_len >= MarkBasePosFormat1::static_size;
+ }
+
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+ unsigned parent_index,
+ unsigned this_index)
+ {
+ hb_set_t visited;
+
+ const unsigned base_coverage_id = c.graph.index_for_offset (this_index, &baseCoverage);
+ const unsigned base_size =
+ OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size +
+ MarkArray::min_size +
+ AnchorMatrix::min_size +
+ c.graph.vertices_[base_coverage_id].table_size ();
+
+ hb_vector_t<class_info_t> class_to_info = get_class_info (c, this_index);
+
+ unsigned class_count = classCount;
+ auto base_array = c.graph.as_table<AnchorMatrix> (this_index,
+ &baseArray,
+ class_count);
+ if (!base_array) return hb_vector_t<unsigned> ();
+ unsigned base_count = base_array.table->rows;
+
+ unsigned partial_coverage_size = 4;
+ unsigned accumulated = base_size;
+ hb_vector_t<unsigned> split_points;
+
+ for (unsigned klass = 0; klass < class_count; klass++)
+ {
+ class_info_t& info = class_to_info[klass];
+ partial_coverage_size += OT::HBUINT16::static_size * info.marks.get_population ();
+ unsigned accumulated_delta =
+ OT::Layout::GPOS_impl::MarkRecord::static_size * info.marks.get_population () +
+ OT::Offset16::static_size * base_count;
+
+ for (unsigned objidx : info.child_indices)
+ accumulated_delta += c.graph.find_subgraph_size (objidx, visited);
+
+ accumulated += accumulated_delta;
+ unsigned total = accumulated + partial_coverage_size;
+
+ if (total >= (1 << 16))
+ {
+ split_points.push (klass);
+ accumulated = base_size + accumulated_delta;
+ partial_coverage_size = 4 + OT::HBUINT16::static_size * info.marks.get_population ();
+ visited.clear (); // node sharing isn't allowed between splits.
+ }
+ }
+
+
+ const unsigned mark_array_id = c.graph.index_for_offset (this_index, &markArray);
+ split_context_t split_context {
+ c,
+ this,
+ c.graph.duplicate_if_shared (parent_index, this_index),
+ std::move (class_to_info),
+ c.graph.vertices_[mark_array_id].position_to_index_map (),
+ };
+
+ return actuate_subtable_split<split_context_t> (split_context, split_points);
+ }
+
+ private:
+
+ struct class_info_t {
+ hb_set_t marks;
+ hb_vector_t<unsigned> child_indices;
+ };
+
+ struct split_context_t {
+ gsubgpos_graph_context_t& c;
+ MarkBasePosFormat1* thiz;
+ unsigned this_index;
+ hb_vector_t<class_info_t> class_to_info;
+ hb_hashmap_t<unsigned, unsigned> mark_array_links;
+
+ hb_set_t marks_for (unsigned start, unsigned end)
+ {
+ hb_set_t marks;
+ for (unsigned klass = start; klass < end; klass++)
+ {
+ + class_to_info[klass].marks.iter ()
+ | hb_sink (marks)
+ ;
+ }
+ return marks;
+ }
+
+ unsigned original_count ()
+ {
+ return thiz->classCount;
+ }
+
+ unsigned clone_range (unsigned start, unsigned end)
+ {
+ return thiz->clone_range (*this, this->this_index, start, end);
+ }
+
+ bool shrink (unsigned count)
+ {
+ return thiz->shrink (*this, this->this_index, count);
+ }
+ };
+
+ hb_vector_t<class_info_t> get_class_info (gsubgpos_graph_context_t& c,
+ unsigned this_index)
+ {
+ hb_vector_t<class_info_t> class_to_info;
+
+ unsigned class_count= classCount;
+ class_to_info.resize (class_count);
+
+ auto mark_array = c.graph.as_table<MarkArray> (this_index, &markArray);
+ if (!mark_array) return hb_vector_t<class_info_t> ();
+ unsigned mark_count = mark_array.table->len;
+ for (unsigned mark = 0; mark < mark_count; mark++)
+ {
+ unsigned klass = (*mark_array.table)[mark].get_class ();
+ class_to_info[klass].marks.add (mark);
+ }
+
+ for (const auto& link : mark_array.vertex->obj.real_links)
+ {
+ unsigned mark = (link.position - 2) /
+ OT::Layout::GPOS_impl::MarkRecord::static_size;
+ unsigned klass = (*mark_array.table)[mark].get_class ();
+ class_to_info[klass].child_indices.push (link.objidx);
+ }
+
+ unsigned base_array_id =
+ c.graph.index_for_offset (this_index, &baseArray);
+ auto& base_array_v = c.graph.vertices_[base_array_id];
+
+ for (const auto& link : base_array_v.obj.real_links)
+ {
+ unsigned index = (link.position - 2) / OT::Offset16::static_size;
+ unsigned klass = index % class_count;
+ class_to_info[klass].child_indices.push (link.objidx);
+ }
+
+ return class_to_info;
+ }
+
+ bool shrink (split_context_t& sc,
+ unsigned this_index,
+ unsigned count)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Shrinking MarkBasePosFormat1 (%u) to [0, %u).",
+ this_index,
+ count);
+
+ unsigned old_count = classCount;
+ if (count >= old_count)
+ return true;
+
+ classCount = count;
+
+ auto mark_coverage = sc.c.graph.as_mutable_table<Coverage> (this_index,
+ &markCoverage);
+ if (!mark_coverage) return false;
+ hb_set_t marks = sc.marks_for (0, count);
+ auto new_coverage =
+ + hb_enumerate (mark_coverage.table->iter ())
+ | hb_filter (marks, hb_first)
+ | hb_map_retains_sorting (hb_second)
+ ;
+ if (!Coverage::make_coverage (sc.c, + new_coverage,
+ mark_coverage.index,
+ 4 + 2 * marks.get_population ()))
+ return false;
+
+
+ auto base_array = sc.c.graph.as_mutable_table<AnchorMatrix> (this_index,
+ &baseArray,
+ old_count);
+ if (!base_array || !base_array.table->shrink (sc.c,
+ base_array.index,
+ old_count,
+ count))
+ return false;
+
+ auto mark_array = sc.c.graph.as_mutable_table<MarkArray> (this_index,
+ &markArray);
+ if (!mark_array || !mark_array.table->shrink (sc.c,
+ sc.mark_array_links,
+ mark_array.index,
+ count))
+ return false;
+
+ return true;
+ }
+
+ // Create a new MarkBasePos that has all of the data for classes from [start, end).
+ unsigned clone_range (split_context_t& sc,
+ unsigned this_index,
+ unsigned start, unsigned end) const
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Cloning MarkBasePosFormat1 (%u) range [%u, %u).", this_index, start, end);
+
+ graph_t& graph = sc.c.graph;
+ unsigned prime_size = OT::Layout::GPOS_impl::MarkBasePosFormat1_2<SmallTypes>::static_size;
+
+ unsigned prime_id = sc.c.create_node (prime_size);
+ if (prime_id == (unsigned) -1) return -1;
+
+ MarkBasePosFormat1* prime = (MarkBasePosFormat1*) graph.object (prime_id).head;
+ prime->format = this->format;
+ unsigned new_class_count = end - start;
+ prime->classCount = new_class_count;
+
+ unsigned base_coverage_id =
+ graph.index_for_offset (sc.this_index, &baseCoverage);
+ graph.add_link (&(prime->baseCoverage), prime_id, base_coverage_id);
+ graph.duplicate (prime_id, base_coverage_id);
+
+ auto mark_coverage = sc.c.graph.as_table<Coverage> (this_index,
+ &markCoverage);
+ if (!mark_coverage) return false;
+ hb_set_t marks = sc.marks_for (start, end);
+ auto new_coverage =
+ + hb_enumerate (mark_coverage.table->iter ())
+ | hb_filter (marks, hb_first)
+ | hb_map_retains_sorting (hb_second)
+ ;
+ if (!Coverage::add_coverage (sc.c,
+ prime_id,
+ 2,
+ + new_coverage,
+ marks.get_population () * 2 + 4))
+ return -1;
+
+ auto mark_array =
+ graph.as_table <MarkArray> (sc.this_index, &markArray);
+ if (!mark_array) return -1;
+ unsigned new_mark_array =
+ mark_array.table->clone (sc.c,
+ mark_array.index,
+ sc.mark_array_links,
+ marks,
+ start);
+ graph.add_link (&(prime->markArray), prime_id, new_mark_array);
+
+ unsigned class_count = classCount;
+ auto base_array =
+ graph.as_table<AnchorMatrix> (sc.this_index, &baseArray, class_count);
+ if (!base_array) return -1;
+ unsigned new_base_array =
+ base_array.table->clone (sc.c,
+ base_array.index,
+ start, end, this->classCount);
+ graph.add_link (&(prime->baseArray), prime_id, new_base_array);
+
+ return prime_id;
+ }
+};
+
+
+struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
+{
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+ unsigned parent_index,
+ unsigned this_index)
+ {
+ switch (u.format) {
+ case 1:
+ return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
+#ifndef HB_NO_BEYOND_64K
+ case 2: HB_FALLTHROUGH;
+ // Don't split 24bit PairPos's.
+#endif
+ default:
+ return hb_vector_t<unsigned> ();
+ }
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < u.format.get_size ()) return false;
+
+ switch (u.format) {
+ case 1:
+ return ((MarkBasePosFormat1*)(&u.format1))->sanitize (vertex);
+#ifndef HB_NO_BEYOND_64K
+ case 2: HB_FALLTHROUGH;
+#endif
+ default:
+ // We don't handle format 3 and 4 here.
+ return false;
+ }
+ }
+};
+
+
+}
+
+#endif // GRAPH_MARKBASEPOS_GRAPH_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh
new file mode 100644
index 0000000000..1c13eb24f9
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh
@@ -0,0 +1,647 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef GRAPH_PAIRPOS_GRAPH_HH
+#define GRAPH_PAIRPOS_GRAPH_HH
+
+#include "split-helpers.hh"
+#include "coverage-graph.hh"
+#include "classdef-graph.hh"
+#include "../OT/Layout/GPOS/PairPos.hh"
+#include "../OT/Layout/GPOS/PosLookupSubTable.hh"
+
+namespace graph {
+
+struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ unsigned min_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+
+ return vertex_len >=
+ min_size + pairSet.get_size () - pairSet.len.get_size();
+ }
+
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+ unsigned parent_index,
+ unsigned this_index)
+ {
+ hb_set_t visited;
+
+ const unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
+ const unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
+ const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size;
+
+ unsigned partial_coverage_size = 4;
+ unsigned accumulated = base_size;
+ hb_vector_t<unsigned> split_points;
+ for (unsigned i = 0; i < pairSet.len; i++)
+ {
+ unsigned pair_set_index = pair_set_graph_index (c, this_index, i);
+ unsigned accumulated_delta =
+ c.graph.find_subgraph_size (pair_set_index, visited) +
+ SmallTypes::size; // for PairSet offset.
+ partial_coverage_size += OT::HBUINT16::static_size;
+
+ accumulated += accumulated_delta;
+ unsigned total = accumulated + hb_min (partial_coverage_size, coverage_size);
+
+ if (total >= (1 << 16))
+ {
+ split_points.push (i);
+ accumulated = base_size + accumulated_delta;
+ partial_coverage_size = 6;
+ visited.clear (); // node sharing isn't allowed between splits.
+ }
+ }
+
+ split_context_t split_context {
+ c,
+ this,
+ c.graph.duplicate_if_shared (parent_index, this_index),
+ };
+
+ return actuate_subtable_split<split_context_t> (split_context, split_points);
+ }
+
+ private:
+
+ struct split_context_t {
+ gsubgpos_graph_context_t& c;
+ PairPosFormat1* thiz;
+ unsigned this_index;
+
+ unsigned original_count ()
+ {
+ return thiz->pairSet.len;
+ }
+
+ unsigned clone_range (unsigned start, unsigned end)
+ {
+ return thiz->clone_range (this->c, this->this_index, start, end);
+ }
+
+ bool shrink (unsigned count)
+ {
+ return thiz->shrink (this->c, this->this_index, count);
+ }
+ };
+
+ bool shrink (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned count)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Shrinking PairPosFormat1 (%u) to [0, %u).",
+ this_index,
+ count);
+ unsigned old_count = pairSet.len;
+ if (count >= old_count)
+ return true;
+
+ pairSet.len = count;
+ c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
+
+ auto coverage = c.graph.as_mutable_table<Coverage> (this_index, &this->coverage);
+ if (!coverage) return false;
+
+ unsigned coverage_size = coverage.vertex->table_size ();
+ auto new_coverage =
+ + hb_zip (coverage.table->iter (), hb_range ())
+ | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
+ return p.second < count;
+ })
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ return Coverage::make_coverage (c, new_coverage, coverage.index, coverage_size);
+ }
+
+ // Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
+ // Returns object id of the new object.
+ unsigned clone_range (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned start, unsigned end) const
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Cloning PairPosFormat1 (%u) range [%u, %u).", this_index, start, end);
+
+ unsigned num_pair_sets = end - start;
+ unsigned prime_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size
+ + num_pair_sets * SmallTypes::size;
+
+ unsigned pair_pos_prime_id = c.create_node (prime_size);
+ if (pair_pos_prime_id == (unsigned) -1) return -1;
+
+ PairPosFormat1* pair_pos_prime = (PairPosFormat1*) c.graph.object (pair_pos_prime_id).head;
+ pair_pos_prime->format = this->format;
+ pair_pos_prime->valueFormat[0] = this->valueFormat[0];
+ pair_pos_prime->valueFormat[1] = this->valueFormat[1];
+ pair_pos_prime->pairSet.len = num_pair_sets;
+
+ for (unsigned i = start; i < end; i++)
+ {
+ c.graph.move_child<> (this_index,
+ &pairSet[i],
+ pair_pos_prime_id,
+ &pair_pos_prime->pairSet[i - start]);
+ }
+
+ unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
+ if (!Coverage::clone_coverage (c,
+ coverage_id,
+ pair_pos_prime_id,
+ 2,
+ start, end))
+ return -1;
+
+ return pair_pos_prime_id;
+ }
+
+
+
+ unsigned pair_set_graph_index (gsubgpos_graph_context_t& c, unsigned this_index, unsigned i) const
+ {
+ return c.graph.index_for_offset (this_index, &pairSet[i]);
+ }
+};
+
+struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ size_t vertex_len = vertex.table_size ();
+ unsigned min_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+
+ const unsigned class1_count = class1Count;
+ return vertex_len >=
+ min_size + class1_count * get_class1_record_size ();
+ }
+
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+ unsigned parent_index,
+ unsigned this_index)
+ {
+ const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size;
+ const unsigned class_def_2_size = size_of (c, this_index, &classDef2);
+ const Coverage* coverage = get_coverage (c, this_index);
+ const ClassDef* class_def_1 = get_class_def_1 (c, this_index);
+ auto gid_and_class =
+ + coverage->iter ()
+ | hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
+ return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1->get_class (gid));
+ })
+ ;
+ class_def_size_estimator_t estimator (gid_and_class);
+
+ const unsigned class1_count = class1Count;
+ const unsigned class2_count = class2Count;
+ const unsigned class1_record_size = get_class1_record_size ();
+
+ const unsigned value_1_len = valueFormat1.get_len ();
+ const unsigned value_2_len = valueFormat2.get_len ();
+ const unsigned total_value_len = value_1_len + value_2_len;
+
+ unsigned accumulated = base_size;
+ unsigned coverage_size = 4;
+ unsigned class_def_1_size = 4;
+ unsigned max_coverage_size = coverage_size;
+ unsigned max_class_def_1_size = class_def_1_size;
+
+ hb_vector_t<unsigned> split_points;
+
+ hb_hashmap_t<unsigned, unsigned> device_tables = get_all_device_tables (c, this_index);
+ hb_vector_t<unsigned> format1_device_table_indices = valueFormat1.get_device_table_indices ();
+ hb_vector_t<unsigned> format2_device_table_indices = valueFormat2.get_device_table_indices ();
+ bool has_device_tables = bool(format1_device_table_indices) || bool(format2_device_table_indices);
+
+ hb_set_t visited;
+ for (unsigned i = 0; i < class1_count; i++)
+ {
+ unsigned accumulated_delta = class1_record_size;
+ coverage_size += estimator.incremental_coverage_size (i);
+ class_def_1_size += estimator.incremental_class_def_size (i);
+ max_coverage_size = hb_max (max_coverage_size, coverage_size);
+ max_class_def_1_size = hb_max (max_class_def_1_size, class_def_1_size);
+
+ if (has_device_tables) {
+ for (unsigned j = 0; j < class2_count; j++)
+ {
+ unsigned value1_index = total_value_len * (class2_count * i + j);
+ unsigned value2_index = value1_index + value_1_len;
+ accumulated_delta += size_of_value_record_children (c,
+ device_tables,
+ format1_device_table_indices,
+ value1_index,
+ visited);
+ accumulated_delta += size_of_value_record_children (c,
+ device_tables,
+ format2_device_table_indices,
+ value2_index,
+ visited);
+ }
+ }
+
+ accumulated += accumulated_delta;
+ unsigned total = accumulated
+ + coverage_size + class_def_1_size + class_def_2_size
+ // The largest object will pack last and can exceed the size limit.
+ - hb_max (hb_max (coverage_size, class_def_1_size), class_def_2_size);
+ if (total >= (1 << 16))
+ {
+ split_points.push (i);
+ // split does not include i, so add the size for i when we reset the size counters.
+ accumulated = base_size + accumulated_delta;
+ coverage_size = 4 + estimator.incremental_coverage_size (i);
+ class_def_1_size = 4 + estimator.incremental_class_def_size (i);
+ visited.clear (); // node sharing isn't allowed between splits.
+ }
+ }
+
+ split_context_t split_context {
+ c,
+ this,
+ c.graph.duplicate_if_shared (parent_index, this_index),
+ class1_record_size,
+ total_value_len,
+ value_1_len,
+ value_2_len,
+ max_coverage_size,
+ max_class_def_1_size,
+ device_tables,
+ format1_device_table_indices,
+ format2_device_table_indices
+ };
+
+ return actuate_subtable_split<split_context_t> (split_context, split_points);
+ }
+ private:
+
+ struct split_context_t
+ {
+ gsubgpos_graph_context_t& c;
+ PairPosFormat2* thiz;
+ unsigned this_index;
+ unsigned class1_record_size;
+ unsigned value_record_len;
+ unsigned value1_record_len;
+ unsigned value2_record_len;
+ unsigned max_coverage_size;
+ unsigned max_class_def_size;
+
+ const hb_hashmap_t<unsigned, unsigned>& device_tables;
+ const hb_vector_t<unsigned>& format1_device_table_indices;
+ const hb_vector_t<unsigned>& format2_device_table_indices;
+
+ unsigned original_count ()
+ {
+ return thiz->class1Count;
+ }
+
+ unsigned clone_range (unsigned start, unsigned end)
+ {
+ return thiz->clone_range (*this, start, end);
+ }
+
+ bool shrink (unsigned count)
+ {
+ return thiz->shrink (*this, count);
+ }
+ };
+
+ size_t get_class1_record_size () const
+ {
+ const size_t class2_count = class2Count;
+ return
+ class2_count * (valueFormat1.get_size () + valueFormat2.get_size ());
+ }
+
+ unsigned clone_range (split_context_t& split_context,
+ unsigned start, unsigned end) const
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Cloning PairPosFormat2 (%u) range [%u, %u).", split_context.this_index, start, end);
+
+ graph_t& graph = split_context.c.graph;
+
+ unsigned num_records = end - start;
+ unsigned prime_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size
+ + num_records * split_context.class1_record_size;
+
+ unsigned pair_pos_prime_id = split_context.c.create_node (prime_size);
+ if (pair_pos_prime_id == (unsigned) -1) return -1;
+
+ PairPosFormat2* pair_pos_prime =
+ (PairPosFormat2*) graph.object (pair_pos_prime_id).head;
+ pair_pos_prime->format = this->format;
+ pair_pos_prime->valueFormat1 = this->valueFormat1;
+ pair_pos_prime->valueFormat2 = this->valueFormat2;
+ pair_pos_prime->class1Count = num_records;
+ pair_pos_prime->class2Count = this->class2Count;
+ clone_class1_records (split_context,
+ pair_pos_prime_id,
+ start,
+ end);
+
+ unsigned coverage_id =
+ graph.index_for_offset (split_context.this_index, &coverage);
+ unsigned class_def_1_id =
+ graph.index_for_offset (split_context.this_index, &classDef1);
+ auto& coverage_v = graph.vertices_[coverage_id];
+ auto& class_def_1_v = graph.vertices_[class_def_1_id];
+ Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
+ ClassDef* class_def_1_table = (ClassDef*) class_def_1_v.obj.head;
+ if (!coverage_table
+ || !coverage_table->sanitize (coverage_v)
+ || !class_def_1_table
+ || !class_def_1_table->sanitize (class_def_1_v))
+ return -1;
+
+ auto klass_map =
+ + coverage_table->iter ()
+ | hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
+ return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1_table->get_class (gid));
+ })
+ | hb_filter ([&] (hb_codepoint_t klass) {
+ return klass >= start && klass < end;
+ }, hb_second)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, hb_codepoint_t> gid_and_class) {
+ // Classes must be from 0...N so subtract start
+ return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid_and_class.first, gid_and_class.second - start);
+ })
+ ;
+
+ if (!Coverage::add_coverage (split_context.c,
+ pair_pos_prime_id,
+ 2,
+ + klass_map | hb_map_retains_sorting (hb_first),
+ split_context.max_coverage_size))
+ return -1;
+
+ // classDef1
+ if (!ClassDef::add_class_def (split_context.c,
+ pair_pos_prime_id,
+ 8,
+ + klass_map,
+ split_context.max_class_def_size))
+ return -1;
+
+ // classDef2
+ unsigned class_def_2_id =
+ graph.index_for_offset (split_context.this_index, &classDef2);
+ auto* class_def_link = graph.vertices_[pair_pos_prime_id].obj.real_links.push ();
+ class_def_link->width = SmallTypes::size;
+ class_def_link->objidx = class_def_2_id;
+ class_def_link->position = 10;
+ graph.vertices_[class_def_2_id].parents.push (pair_pos_prime_id);
+ graph.duplicate (pair_pos_prime_id, class_def_2_id);
+
+ return pair_pos_prime_id;
+ }
+
+ void clone_class1_records (split_context_t& split_context,
+ unsigned pair_pos_prime_id,
+ unsigned start, unsigned end) const
+ {
+ PairPosFormat2* pair_pos_prime =
+ (PairPosFormat2*) split_context.c.graph.object (pair_pos_prime_id).head;
+
+ char* start_addr = ((char*)&values[0]) + start * split_context.class1_record_size;
+ unsigned num_records = end - start;
+ hb_memcpy (&pair_pos_prime->values[0],
+ start_addr,
+ num_records * split_context.class1_record_size);
+
+ if (!split_context.format1_device_table_indices
+ && !split_context.format2_device_table_indices)
+ // No device tables to move over.
+ return;
+
+ unsigned class2_count = class2Count;
+ for (unsigned i = start; i < end; i++)
+ {
+ for (unsigned j = 0; j < class2_count; j++)
+ {
+ unsigned value1_index = split_context.value_record_len * (class2_count * i + j);
+ unsigned value2_index = value1_index + split_context.value1_record_len;
+
+ unsigned new_value1_index = split_context.value_record_len * (class2_count * (i - start) + j);
+ unsigned new_value2_index = new_value1_index + split_context.value1_record_len;
+
+ transfer_device_tables (split_context,
+ pair_pos_prime_id,
+ split_context.format1_device_table_indices,
+ value1_index,
+ new_value1_index);
+
+ transfer_device_tables (split_context,
+ pair_pos_prime_id,
+ split_context.format2_device_table_indices,
+ value2_index,
+ new_value2_index);
+ }
+ }
+ }
+
+ void transfer_device_tables (split_context_t& split_context,
+ unsigned pair_pos_prime_id,
+ const hb_vector_t<unsigned>& device_table_indices,
+ unsigned old_value_record_index,
+ unsigned new_value_record_index) const
+ {
+ PairPosFormat2* pair_pos_prime =
+ (PairPosFormat2*) split_context.c.graph.object (pair_pos_prime_id).head;
+
+ for (unsigned i : device_table_indices)
+ {
+ OT::Offset16* record = (OT::Offset16*) &values[old_value_record_index + i];
+ unsigned record_position = ((char*) record) - ((char*) this);
+ if (!split_context.device_tables.has (record_position)) continue;
+
+ split_context.c.graph.move_child (
+ split_context.this_index,
+ record,
+ pair_pos_prime_id,
+ (OT::Offset16*) &pair_pos_prime->values[new_value_record_index + i]);
+ }
+ }
+
+ bool shrink (split_context_t& split_context,
+ unsigned count)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Shrinking PairPosFormat2 (%u) to [0, %u).",
+ split_context.this_index,
+ count);
+ unsigned old_count = class1Count;
+ if (count >= old_count)
+ return true;
+
+ graph_t& graph = split_context.c.graph;
+ class1Count = count;
+ graph.vertices_[split_context.this_index].obj.tail -=
+ (old_count - count) * split_context.class1_record_size;
+
+ auto coverage =
+ graph.as_mutable_table<Coverage> (split_context.this_index, &this->coverage);
+ if (!coverage) return false;
+
+ auto class_def_1 =
+ graph.as_mutable_table<ClassDef> (split_context.this_index, &classDef1);
+ if (!class_def_1) return false;
+
+ auto klass_map =
+ + coverage.table->iter ()
+ | hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
+ return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1.table->get_class (gid));
+ })
+ | hb_filter ([&] (hb_codepoint_t klass) {
+ return klass < count;
+ }, hb_second)
+ ;
+
+ auto new_coverage = + klass_map | hb_map_retains_sorting (hb_first);
+ if (!Coverage::make_coverage (split_context.c,
+ + new_coverage,
+ coverage.index,
+ // existing ranges my not be kept, worst case size is a format 1
+ // coverage table.
+ 4 + new_coverage.len() * 2))
+ return false;
+
+ return ClassDef::make_class_def (split_context.c,
+ + klass_map,
+ class_def_1.index,
+ class_def_1.vertex->table_size ());
+ }
+
+ hb_hashmap_t<unsigned, unsigned>
+ get_all_device_tables (gsubgpos_graph_context_t& c,
+ unsigned this_index) const
+ {
+ const auto& v = c.graph.vertices_[this_index];
+ return v.position_to_index_map ();
+ }
+
+ const Coverage* get_coverage (gsubgpos_graph_context_t& c,
+ unsigned this_index) const
+ {
+ unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
+ auto& coverage_v = c.graph.vertices_[coverage_id];
+
+ Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
+ if (!coverage_table || !coverage_table->sanitize (coverage_v))
+ return &Null(Coverage);
+ return coverage_table;
+ }
+
+ const ClassDef* get_class_def_1 (gsubgpos_graph_context_t& c,
+ unsigned this_index) const
+ {
+ unsigned class_def_1_id = c.graph.index_for_offset (this_index, &classDef1);
+ auto& class_def_1_v = c.graph.vertices_[class_def_1_id];
+
+ ClassDef* class_def_1_table = (ClassDef*) class_def_1_v.obj.head;
+ if (!class_def_1_table || !class_def_1_table->sanitize (class_def_1_v))
+ return &Null(ClassDef);
+ return class_def_1_table;
+ }
+
+ unsigned size_of_value_record_children (gsubgpos_graph_context_t& c,
+ const hb_hashmap_t<unsigned, unsigned>& device_tables,
+ const hb_vector_t<unsigned> device_table_indices,
+ unsigned value_record_index,
+ hb_set_t& visited)
+ {
+ unsigned size = 0;
+ for (unsigned i : device_table_indices)
+ {
+ OT::Layout::GPOS_impl::Value* record = &values[value_record_index + i];
+ unsigned record_position = ((char*) record) - ((char*) this);
+ unsigned* obj_idx;
+ if (!device_tables.has (record_position, &obj_idx)) continue;
+ size += c.graph.find_subgraph_size (*obj_idx, visited);
+ }
+ return size;
+ }
+
+ unsigned size_of (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ const void* offset) const
+ {
+ const unsigned id = c.graph.index_for_offset (this_index, offset);
+ return c.graph.vertices_[id].table_size ();
+ }
+};
+
+struct PairPos : public OT::Layout::GPOS_impl::PairPos
+{
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
+ unsigned parent_index,
+ unsigned this_index)
+ {
+ switch (u.format) {
+ case 1:
+ return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
+ case 2:
+ return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index);
+#ifndef HB_NO_BEYOND_64K
+ case 3: HB_FALLTHROUGH;
+ case 4: HB_FALLTHROUGH;
+ // Don't split 24bit PairPos's.
+#endif
+ default:
+ return hb_vector_t<unsigned> ();
+ }
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < u.format.get_size ()) return false;
+
+ switch (u.format) {
+ case 1:
+ return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
+ case 2:
+ return ((PairPosFormat2*)(&u.format2))->sanitize (vertex);
+#ifndef HB_NO_BEYOND_64K
+ case 3: HB_FALLTHROUGH;
+ case 4: HB_FALLTHROUGH;
+#endif
+ default:
+ // We don't handle format 3 and 4 here.
+ return false;
+ }
+ }
+};
+
+}
+
+#endif // GRAPH_PAIRPOS_GRAPH_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh
new file mode 100644
index 0000000000..040fd1de5f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh
@@ -0,0 +1,270 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef GRAPH_SERIALIZE_HH
+#define GRAPH_SERIALIZE_HH
+
+namespace graph {
+
+struct overflow_record_t
+{
+ unsigned parent;
+ unsigned child;
+
+ bool operator != (const overflow_record_t o) const
+ { return !(*this == o); }
+
+ inline bool operator == (const overflow_record_t& o) const
+ {
+ return parent == o.parent &&
+ child == o.child;
+ }
+
+ inline uint32_t hash () const
+ {
+ uint32_t current = 0;
+ current = current * 31 + hb_hash (parent);
+ current = current * 31 + hb_hash (child);
+ return current;
+ }
+};
+
+inline
+int64_t compute_offset (
+ const graph_t& graph,
+ unsigned parent_idx,
+ const hb_serialize_context_t::object_t::link_t& link)
+{
+ const auto& parent = graph.vertices_[parent_idx];
+ const auto& child = graph.vertices_[link.objidx];
+ int64_t offset = 0;
+ switch ((hb_serialize_context_t::whence_t) link.whence) {
+ case hb_serialize_context_t::whence_t::Head:
+ offset = child.start - parent.start; break;
+ case hb_serialize_context_t::whence_t::Tail:
+ offset = child.start - parent.end; break;
+ case hb_serialize_context_t::whence_t::Absolute:
+ offset = child.start; break;
+ }
+
+ assert (offset >= link.bias);
+ offset -= link.bias;
+ return offset;
+}
+
+inline
+bool is_valid_offset (int64_t offset,
+ const hb_serialize_context_t::object_t::link_t& link)
+{
+ if (unlikely (!link.width))
+ // Virtual links can't overflow.
+ return link.is_signed || offset >= 0;
+
+ if (link.is_signed)
+ {
+ if (link.width == 4)
+ return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
+ else
+ return offset >= -(1 << 15) && offset < (1 << 15);
+ }
+ else
+ {
+ if (link.width == 4)
+ return offset >= 0 && offset < ((int64_t) 1 << 32);
+ else if (link.width == 3)
+ return offset >= 0 && offset < ((int32_t) 1 << 24);
+ else
+ return offset >= 0 && offset < (1 << 16);
+ }
+}
+
+/*
+ * Will any offsets overflow on graph when it's serialized?
+ */
+inline bool
+will_overflow (graph_t& graph,
+ hb_vector_t<overflow_record_t>* overflows = nullptr)
+{
+ if (overflows) overflows->resize (0);
+ graph.update_positions ();
+
+ hb_hashmap_t<overflow_record_t*, bool> record_set;
+ const auto& vertices = graph.vertices_;
+ for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--)
+ {
+ // Don't need to check virtual links for overflow
+ for (const auto& link : vertices[parent_idx].obj.real_links)
+ {
+ int64_t offset = compute_offset (graph, parent_idx, link);
+ if (is_valid_offset (offset, link))
+ continue;
+
+ if (!overflows) return true;
+
+ overflow_record_t r;
+ r.parent = parent_idx;
+ r.child = link.objidx;
+ if (record_set.has(&r)) continue; // don't keep duplicate overflows.
+
+ overflows->push (r);
+ record_set.set(&r, true);
+ }
+ }
+
+ if (!overflows) return false;
+ return overflows->length;
+}
+
+inline
+void print_overflows (graph_t& graph,
+ const hb_vector_t<overflow_record_t>& overflows)
+{
+ if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
+
+ graph.update_parents ();
+ int limit = 10;
+ for (const auto& o : overflows)
+ {
+ if (!limit--) break;
+ const auto& parent = graph.vertices_[o.parent];
+ const auto& child = graph.vertices_[o.child];
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " overflow from "
+ "%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,
+ graph.space_for (o.parent),
+ o.child,
+ child.incoming_edges (),
+ child.obj.real_links.length + child.obj.virtual_links.length,
+ graph.space_for (o.child));
+ }
+ if (overflows.length > 10) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %u more overflows.", overflows.length - 10);
+ }
+}
+
+template <typename O> inline void
+serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
+ char* head,
+ hb_serialize_context_t* c)
+{
+ OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
+ *offset = 0;
+ c->add_link (*offset,
+ // serializer has an extra nil object at the start of the
+ // object array. So all id's are +1 of what our id's are.
+ link.objidx + 1,
+ (hb_serialize_context_t::whence_t) link.whence,
+ link.bias);
+}
+
+inline
+void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
+ char* head,
+ hb_serialize_context_t* c)
+{
+ switch (link.width)
+ {
+ case 0:
+ // Virtual links aren't serialized.
+ return;
+ case 4:
+ if (link.is_signed)
+ {
+ serialize_link_of_type<OT::HBINT32> (link, head, c);
+ } else {
+ serialize_link_of_type<OT::HBUINT32> (link, head, c);
+ }
+ return;
+ case 2:
+ if (link.is_signed)
+ {
+ serialize_link_of_type<OT::HBINT16> (link, head, c);
+ } else {
+ serialize_link_of_type<OT::HBUINT16> (link, head, c);
+ }
+ return;
+ case 3:
+ serialize_link_of_type<OT::HBUINT24> (link, head, c);
+ return;
+ default:
+ // Unexpected link width.
+ assert (0);
+ }
+}
+
+/*
+ * serialize graph into the provided serialization buffer.
+ */
+inline hb_blob_t* serialize (const graph_t& graph)
+{
+ hb_vector_t<char> buffer;
+ size_t size = graph.total_size_in_bytes ();
+ if (!buffer.alloc (size)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
+ return nullptr;
+ }
+ hb_serialize_context_t c((void *) buffer, size);
+
+ c.start_serialize<void> ();
+ const auto& vertices = graph.vertices_;
+ for (unsigned i = 0; i < vertices.length; i++) {
+ c.push ();
+
+ size_t size = vertices[i].obj.tail - vertices[i].obj.head;
+ char* start = c.allocate_size <char> (size);
+ if (!start) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space.");
+ return nullptr;
+ }
+
+ hb_memcpy (start, vertices[i].obj.head, size);
+
+ // Only real links needs to be serialized.
+ for (const auto& link : vertices[i].obj.real_links)
+ serialize_link (link, start, &c);
+
+ // All duplications are already encoded in the graph, so don't
+ // enable sharing during packing.
+ c.pop_pack (false);
+ }
+ c.end_serialize ();
+
+ if (c.in_error ()) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d",
+ c.errors);
+ return nullptr;
+ }
+
+ return c.copy_blob ();
+}
+
+} // namespace graph
+
+#endif // GRAPH_SERIALIZE_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/split-helpers.hh b/src/3rdparty/harfbuzz-ng/src/graph/split-helpers.hh
new file mode 100644
index 0000000000..61fd7c2d2f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/graph/split-helpers.hh
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef GRAPH_SPLIT_HELPERS_HH
+#define GRAPH_SPLIT_HELPERS_HH
+
+namespace graph {
+
+template<typename Context>
+HB_INTERNAL
+hb_vector_t<unsigned> actuate_subtable_split (Context& split_context,
+ const hb_vector_t<unsigned>& split_points)
+{
+ hb_vector_t<unsigned> new_objects;
+ if (!split_points)
+ return new_objects;
+
+ for (unsigned i = 0; i < split_points.length; i++)
+ {
+ unsigned start = split_points[i];
+ unsigned end = (i < split_points.length - 1)
+ ? split_points[i + 1]
+ : split_context.original_count ();
+ unsigned id = split_context.clone_range (start, end);
+
+ if (id == (unsigned) -1)
+ {
+ new_objects.reset ();
+ new_objects.allocated = -1; // mark error
+ return new_objects;
+ }
+ new_objects.push (id);
+ }
+
+ if (!split_context.shrink (split_points[0]))
+ {
+ new_objects.reset ();
+ new_objects.allocated = -1; // mark error
+ }
+
+ return new_objects;
+}
+
+}
+
+#endif // GRAPH_SPLIT_HELPERS_HH
diff --git a/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc
new file mode 100644
index 0000000000..55854ff5c2
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "gsubgpos-context.hh"
+#include "classdef-graph.hh"
+
+typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> gid_and_class_t;
+typedef hb_vector_t<gid_and_class_t> gid_and_class_list_t;
+
+
+static bool incremental_size_is (const gid_and_class_list_t& list, unsigned klass,
+ unsigned cov_expected, unsigned class_def_expected)
+{
+ graph::class_def_size_estimator_t estimator (list.iter ());
+
+ unsigned result = estimator.incremental_coverage_size (klass);
+ if (result != cov_expected)
+ {
+ printf ("FAIL: coverage expected size %u but was %u\n", cov_expected, result);
+ return false;
+ }
+
+ result = estimator.incremental_class_def_size (klass);
+ if (result != class_def_expected)
+ {
+ printf ("FAIL: class def expected size %u but was %u\n", class_def_expected, result);
+ return false;
+ }
+
+ return true;
+}
+
+static void test_class_and_coverage_size_estimates ()
+{
+ gid_and_class_list_t empty = {
+ };
+ assert (incremental_size_is (empty, 0, 0, 0));
+ assert (incremental_size_is (empty, 1, 0, 0));
+
+ gid_and_class_list_t class_zero = {
+ {5, 0},
+ };
+ assert (incremental_size_is (class_zero, 0, 2, 0));
+
+ gid_and_class_list_t consecutive = {
+ {4, 0},
+ {5, 0},
+ {6, 1},
+ {7, 1},
+ {8, 2},
+ {9, 2},
+ {10, 2},
+ {11, 2},
+ };
+ assert (incremental_size_is (consecutive, 0, 4, 0));
+ assert (incremental_size_is (consecutive, 1, 4, 4));
+ assert (incremental_size_is (consecutive, 2, 8, 6));
+
+ gid_and_class_list_t non_consecutive = {
+ {4, 0},
+ {5, 0},
+
+ {6, 1},
+ {7, 1},
+
+ {9, 2},
+ {10, 2},
+ {11, 2},
+ {12, 2},
+ };
+ assert (incremental_size_is (non_consecutive, 0, 4, 0));
+ assert (incremental_size_is (non_consecutive, 1, 4, 6));
+ assert (incremental_size_is (non_consecutive, 2, 8, 6));
+
+ gid_and_class_list_t multiple_ranges = {
+ {4, 0},
+ {5, 0},
+
+ {6, 1},
+ {7, 1},
+
+ {9, 1},
+
+ {11, 1},
+ {12, 1},
+ {13, 1},
+ };
+ assert (incremental_size_is (multiple_ranges, 0, 4, 0));
+ assert (incremental_size_is (multiple_ranges, 1, 2 * 6, 3 * 6));
+}
+
+int
+main (int argc, char **argv)
+{
+ test_class_and_coverage_size_estimates ();
+}
diff --git a/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc b/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc
new file mode 100644
index 0000000000..c0e23b3eb8
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc
@@ -0,0 +1,62 @@
+#include "graph/gsubgpos-context.cc"
+#include "hb-aat-layout.cc"
+#include "hb-aat-map.cc"
+#include "hb-blob.cc"
+#include "hb-buffer-serialize.cc"
+#include "hb-buffer-verify.cc"
+#include "hb-buffer.cc"
+#include "hb-common.cc"
+#include "hb-draw.cc"
+#include "hb-face-builder.cc"
+#include "hb-face.cc"
+#include "hb-fallback-shape.cc"
+#include "hb-font.cc"
+#include "hb-map.cc"
+#include "hb-number.cc"
+#include "hb-ot-cff1-table.cc"
+#include "hb-ot-cff2-table.cc"
+#include "hb-ot-color.cc"
+#include "hb-ot-face.cc"
+#include "hb-ot-font.cc"
+#include "hb-ot-layout.cc"
+#include "hb-ot-map.cc"
+#include "hb-ot-math.cc"
+#include "hb-ot-meta.cc"
+#include "hb-ot-metrics.cc"
+#include "hb-ot-name.cc"
+#include "hb-ot-shape-fallback.cc"
+#include "hb-ot-shape-normalize.cc"
+#include "hb-ot-shape.cc"
+#include "hb-ot-shaper-arabic.cc"
+#include "hb-ot-shaper-default.cc"
+#include "hb-ot-shaper-hangul.cc"
+#include "hb-ot-shaper-hebrew.cc"
+#include "hb-ot-shaper-indic-table.cc"
+#include "hb-ot-shaper-indic.cc"
+#include "hb-ot-shaper-khmer.cc"
+#include "hb-ot-shaper-myanmar.cc"
+#include "hb-ot-shaper-syllabic.cc"
+#include "hb-ot-shaper-thai.cc"
+#include "hb-ot-shaper-use.cc"
+#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"
+#include "hb-shaper.cc"
+#include "hb-static.cc"
+#include "hb-style.cc"
+#include "hb-subset-cff-common.cc"
+#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"
+#include "hb-ucd.cc"
+#include "hb-unicode.cc"
diff --git a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
index b6a5957c42..d7e8a93f39 100644
--- a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
+++ b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
@@ -5,10 +5,17 @@
#include "hb-buffer-verify.cc"
#include "hb-buffer.cc"
#include "hb-common.cc"
+#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"
+#include "hb-ft.cc"
+#include "hb-gdi.cc"
+#include "hb-glib.cc"
+#include "hb-graphite2.cc"
#include "hb-map.cc"
#include "hb-number.cc"
#include "hb-ot-cff1-table.cc"
@@ -22,23 +29,26 @@
#include "hb-ot-meta.cc"
#include "hb-ot-metrics.cc"
#include "hb-ot-name.cc"
-#include "hb-ot-shape-complex-arabic.cc"
-#include "hb-ot-shape-complex-default.cc"
-#include "hb-ot-shape-complex-hangul.cc"
-#include "hb-ot-shape-complex-hebrew.cc"
-#include "hb-ot-shape-complex-indic-table.cc"
-#include "hb-ot-shape-complex-indic.cc"
-#include "hb-ot-shape-complex-khmer.cc"
-#include "hb-ot-shape-complex-myanmar.cc"
-#include "hb-ot-shape-complex-syllabic.cc"
-#include "hb-ot-shape-complex-thai.cc"
-#include "hb-ot-shape-complex-use.cc"
-#include "hb-ot-shape-complex-vowel-constraints.cc"
#include "hb-ot-shape-fallback.cc"
#include "hb-ot-shape-normalize.cc"
#include "hb-ot-shape.cc"
+#include "hb-ot-shaper-arabic.cc"
+#include "hb-ot-shaper-default.cc"
+#include "hb-ot-shaper-hangul.cc"
+#include "hb-ot-shaper-hebrew.cc"
+#include "hb-ot-shaper-indic-table.cc"
+#include "hb-ot-shaper-indic.cc"
+#include "hb-ot-shaper-khmer.cc"
+#include "hb-ot-shaper-myanmar.cc"
+#include "hb-ot-shaper-syllabic.cc"
+#include "hb-ot-shaper-thai.cc"
+#include "hb-ot-shaper-use.cc"
+#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"
@@ -47,10 +57,4 @@
#include "hb-style.cc"
#include "hb-ucd.cc"
#include "hb-unicode.cc"
-#include "hb-glib.cc"
-#include "hb-ft.cc"
-#include "hb-graphite2.cc"
#include "hb-uniscribe.cc"
-#include "hb-gdi.cc"
-#include "hb-directwrite.cc"
-#include "hb-coretext.cc"
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh
index b52844e75d..bf12d2e699 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-bsln-table.hh
@@ -42,7 +42,7 @@ struct BaselineTableFormat0Part
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -78,7 +78,7 @@ struct BaselineTableFormat2Part
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
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 1db0f1df92..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
*/
@@ -415,18 +453,7 @@ struct Lookup
public:
DEFINE_SIZE_UNION (2, format);
};
-/* Lookup 0 has unbounded size (dependant on num_glyphs). So we need to defined
- * special NULL objects for Lookup<> objects, but since it's template our macros
- * don't work. So we have to hand-code them here. UGLY. */
-} /* Close namespace. */
-/* Ugly hand-coded null objects for template Lookup<> :(. */
-extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
-template <typename T>
-struct Null<AAT::Lookup<T>> {
- static AAT::Lookup<T> const & get_null ()
- { return *reinterpret_cast<const AAT::Lookup<T> *> (_hb_Null_AAT_Lookup); }
-};
-namespace AAT {
+DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
enum { DELETED_GLYPH = 0xFFFF };
@@ -681,6 +708,13 @@ struct ObsoleteTypes
const void *base,
const T *array)
{
+ /* https://github.com/harfbuzz/harfbuzz/issues/3483 */
+ /* If offset is less than base, return an offset that would
+ * result in an address half a 32bit address-space away,
+ * to make sure sanitize fails even on 32bit builds. */
+ if (unlikely (offset < unsigned ((const char *) array - (const char *) base)))
+ return INT_MAX / T::static_size;
+
/* https://github.com/harfbuzz/harfbuzz/issues/2816 */
return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size;
}
@@ -744,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);
@@ -849,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-feat-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-feat-table.hh
index 573f0cf9f6..815a1fd2aa 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-feat-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-feat-table.hh
@@ -62,7 +62,7 @@ struct SettingName
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh
index 0bf9bd2912..8fd3990f88 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-just-table.hh
@@ -48,7 +48,7 @@ struct ActionSubrecordHeader
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
HBUINT16 actionClass; /* The JustClass value associated with this
@@ -65,14 +65,14 @@ struct DecompositionAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
ActionSubrecordHeader
header;
- HBFixed lowerLimit; /* If the distance factor is less than this value,
+ F16DOT16 lowerLimit; /* If the distance factor is less than this value,
* then the ligature is decomposed. */
- HBFixed upperLimit; /* If the distance factor is greater than this value,
+ F16DOT16 upperLimit; /* If the distance factor is greater than this value,
* then the ligature is decomposed. */
HBUINT16 order; /* Numerical order in which this ligature will
* be decomposed; you may want infrequent ligatures
@@ -112,13 +112,13 @@ struct ConditionalAddGlyphAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
ActionSubrecordHeader
header;
- HBFixed substThreshold; /* Distance growth factor (in ems) at which
+ F16DOT16 substThreshold; /* Distance growth factor (in ems) at which
* this glyph is replaced and the growth factor
* recalculated. */
HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is
@@ -137,7 +137,7 @@ struct DuctileGlyphAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -146,13 +146,13 @@ struct DuctileGlyphAction
HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
* This would normally be 0x64756374 ('duct'),
* but you may use any axis the font contains. */
- HBFixed minimumLimit; /* The lowest value for the ductility axis that
+ F16DOT16 minimumLimit; /* The lowest value for the ductility axis that
* still yields an acceptable appearance. Normally
* this will be 1.0. */
- HBFixed noStretchValue; /* This is the default value that corresponds to
+ F16DOT16 noStretchValue; /* This is the default value that corresponds to
* no change in appearance. Normally, this will
* be 1.0. */
- HBFixed maximumLimit; /* The highest value for the ductility axis that
+ F16DOT16 maximumLimit; /* The highest value for the ductility axis that
* still yields an acceptable appearance. */
public:
DEFINE_SIZE_STATIC (22);
@@ -163,7 +163,7 @@ struct RepeatedAddGlyphAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -271,14 +271,14 @@ struct JustWidthDeltaEntry
};
protected:
- HBFixed beforeGrowLimit;/* The ratio by which the advance width of the
+ F16DOT16 beforeGrowLimit;/* The ratio by which the advance width of the
* glyph is permitted to grow on the left or top side. */
- HBFixed beforeShrinkLimit;
+ F16DOT16 beforeShrinkLimit;
/* The ratio by which the advance width of the
* glyph is permitted to shrink on the left or top side. */
- HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph
+ F16DOT16 afterGrowLimit; /* The ratio by which the advance width of the glyph
* is permitted to shrink on the left or top side. */
- HBFixed afterShrinkLimit;
+ F16DOT16 afterShrinkLimit;
/* The ratio by which the advance width of the glyph
* is at most permitted to shrink on the right or
* bottom side. */
@@ -294,7 +294,7 @@ struct WidthDeltaPair
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
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 0354b47d5a..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
@@ -287,7 +287,7 @@ struct KerxSubTableFormat1
* in the 'kern' table example. */
if (v == -0x8000)
{
- o.attach_type() = ATTACH_TYPE_NONE;
+ o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_NONE;
o.attach_chain() = 0;
o.y_offset = 0;
}
@@ -310,7 +310,7 @@ struct KerxSubTableFormat1
/* CoreText doesn't do crossStream kerning in vertical. We do. */
if (v == -0x8000)
{
- o.attach_type() = ATTACH_TYPE_NONE;
+ o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_NONE;
o.attach_chain() = 0;
o.x_offset = 0;
}
@@ -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);
}
@@ -567,7 +567,7 @@ struct KerxSubTableFormat4
}
break;
}
- o.attach_type() = ATTACH_TYPE_MARK;
+ o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_MARK;
o.attach_chain() = (int) mark - (int) buffer->idx;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
}
@@ -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);
}
@@ -751,7 +751,7 @@ struct KerxSubTableHeader
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
public:
@@ -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 &&
@@ -901,7 +903,7 @@ struct KerxTable
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++)
{
- pos[i].attach_type() = ATTACH_TYPE_CURSIVE;
+ pos[i].attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_CURSIVE;
pos[i].attach_chain() = HB_DIRECTION_IS_FORWARD (c->buffer->props.direction) ? -1 : +1;
/* We intentionally don't set HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT,
* since there needs to be a non-zero attachment for post-positioning to
@@ -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 b77c1f4d44..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
@@ -123,7 +123,7 @@ struct RearrangementSubtable
bool reverse_l = 3 == (m >> 4);
bool reverse_r = 3 == (m & 0x0F);
- if (end - start >= l + r)
+ if (end - start >= l + r && end-start <= HB_MAX_CONTEXT_LENGTH)
{
buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len));
buffer->merge_clusters (start, end);
@@ -131,14 +131,14 @@ struct RearrangementSubtable
hb_glyph_info_t *info = buffer->info;
hb_glyph_info_t buf[4];
- memcpy (buf, info + start, l * sizeof (buf[0]));
- memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
+ hb_memcpy (buf, info + start, l * sizeof (buf[0]));
+ hb_memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
if (l != r)
memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0]));
- memcpy (info + start, buf + 2, r * sizeof (buf[0]));
- memcpy (info + end - l, buf, l * sizeof (buf[0]));
+ hb_memcpy (info + start, buf + 2, r * sizeof (buf[0]));
+ hb_memcpy (info + end - l, buf, l * sizeof (buf[0]));
if (reverse_l)
{
buf[0] = info[end - 1];
@@ -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;
@@ -980,13 +999,21 @@ struct Chain
setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS;
goto retry;
}
+#ifndef HB_NO_AAT
+ else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE && setting &&
+ /* TODO: Rudimentary language matching. */
+ hb_language_matches (map->face->table.ltag->get_language (setting - 1), map->props.language))
+ {
+ flags &= feature.disableFlags;
+ flags |= feature.enableFlags;
+ }
+#endif
}
}
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;
@@ -994,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) !=
@@ -1034,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)
@@ -1045,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;
@@ -1111,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-opbd-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-opbd-table.hh
index b1a1512821..51b650fc33 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-opbd-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-opbd-table.hh
@@ -42,7 +42,7 @@ struct OpticalBounds
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
FWORD leftSide;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh
index 68bcb2396f..2ba9355b06 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh
@@ -62,7 +62,7 @@ struct TrackTableEntry
}
protected:
- HBFixed track; /* Track value for this record. */
+ F16DOT16 track; /* Track value for this record. */
NameID trackNameID; /* The 'name' table index for this track.
* (a short word or phrase like "loose"
* or "very tight") */
@@ -82,7 +82,7 @@ struct TrackData
const void *base) const
{
unsigned int sizes = nSizes;
- hb_array_t<const HBFixed> size_table ((base+sizeTable).arrayZ, sizes);
+ hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
float s0 = size_table[idx].to_float ();
float s1 = size_table[idx + 1].to_float ();
@@ -120,7 +120,7 @@ struct TrackData
if (!sizes) return 0.;
if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
- hb_array_t<const HBFixed> size_table ((base+sizeTable).arrayZ, sizes);
+ hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
unsigned int size_index;
for (size_index = 0; size_index < sizes - 1; size_index++)
if (size_table[size_index].to_float () >= ptem)
@@ -141,7 +141,7 @@ struct TrackData
protected:
HBUINT16 nTracks; /* Number of separate tracks included in this table. */
HBUINT16 nSizes; /* Number of point sizes included in this table. */
- NNOffset32To<UnsizedArrayOf<HBFixed>>
+ NNOffset32To<UnsizedArrayOf<F16DOT16>>
sizeTable; /* Offset from start of the tracking table to
* Array[nSizes] of size values.. */
UnsizedArrayOf<TrackTableEntry>
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
index caff204d67..c9147ff73b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
@@ -131,6 +131,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
{HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS, (hb_aat_layout_feature_selector_t) 4},
{HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
{HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
+ {HB_TAG ('r','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF},
{HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF},
{HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
{HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
@@ -229,7 +230,7 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
*
* <note>Note: does not examine the `GSUB` table.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.3.0
*/
@@ -243,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;
}
@@ -262,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;
}
@@ -288,7 +297,7 @@ is_deleted_glyph (const hb_glyph_info_t *info)
void
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
{
- hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
+ buffer->delete_glyphs_inplace (is_deleted_glyph);
}
/**
@@ -300,7 +309,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
*
* <note>Note: does not examine the `GPOS` table.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.3.0
*/
@@ -333,7 +342,7 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
* Tests whether the specified face includes any tracking information
* in the `trak` table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.3.0
*/
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 5a0fa70544..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
{
- 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
@@ -52,10 +51,11 @@ struct hb_aat_map_builder_t
public:
HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_,
- const hb_segment_properties_t *props_ HB_UNUSED) :
- face (face_) {}
+ const hb_segment_properties_t props_) :
+ 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);
@@ -77,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) :
@@ -85,11 +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 c40a55cd1f..e98645e3e3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
@@ -59,7 +59,7 @@
static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
- static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \
+ static inline constexpr unsigned operator ~ (T r) { return (~(unsigned) r); } \
static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
@@ -109,15 +109,16 @@ struct BEInt<Type, 2>
struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
constexpr operator Type () const
{
-#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
defined(__BYTE_ORDER) && \
(__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
/* Spoon-feed the compiler a big-endian integer with alignment 1.
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- return __builtin_bswap16 (((packed_uint16_t *) this)->v);
+ return __builtin_bswap16 (((packed_uint16_t *) v)->v);
#else /* __BYTE_ORDER == __BIG_ENDIAN */
- return ((packed_uint16_t *) this)->v;
+ return ((packed_uint16_t *) v)->v;
#endif
#else
return (v[0] << 8)
@@ -150,10 +151,27 @@ struct BEInt<Type, 4>
uint8_t ((V >> 16) & 0xFF),
uint8_t ((V >> 8) & 0xFF),
uint8_t ((V ) & 0xFF)} {}
- constexpr operator Type () const { return (v[0] << 24)
- + (v[1] << 16)
- + (v[2] << 8)
- + (v[3] ); }
+
+ struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+ constexpr operator Type () const {
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+ defined(__BYTE_ORDER) && \
+ (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
+ /* Spoon-feed the compiler a big-endian integer with alignment 1.
+ * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ return __builtin_bswap32 (((packed_uint32_t *) v)->v);
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+ return ((packed_uint32_t *) v)->v;
+#endif
+#else
+ return (v[0] << 24)
+ + (v[1] << 16)
+ + (v[2] << 8)
+ + (v[3] );
+#endif
+ }
private: uint8_t v[4];
};
@@ -211,31 +229,15 @@ struct
}
HB_FUNCOBJ (hb_bool);
-template <typename T>
-static inline
-T hb_coerce (const T v) { return v; }
-template <typename T, typename V,
- hb_enable_if (!hb_is_same (hb_decay<T>, hb_decay<V>) && std::is_pointer<V>::value)>
-static inline
-T hb_coerce (const V v) { return *v; }
-
struct
{
private:
template <typename T> constexpr auto
- impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
+ impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
template <typename T> constexpr auto
- impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
-
- template <typename T,
- hb_enable_if (std::is_integral<T>::value)> constexpr auto
- impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
- (
- /* Knuth's multiplicative method: */
- (uint32_t) v * 2654435761u
- )
+ impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
public:
@@ -482,6 +484,17 @@ struct
}
HB_FUNCOBJ (hb_equal);
+struct
+{
+ template <typename T> void
+ operator () (T& a, T& b) const
+ {
+ using std::swap; // allow ADL
+ swap (a, b);
+ }
+}
+HB_FUNCOBJ (hb_swap);
+
template <typename T1, typename T2>
struct hb_pair_t
@@ -494,7 +507,7 @@ struct hb_pair_t
hb_enable_if (std::is_default_constructible<U1>::value &&
std::is_default_constructible<U2>::value)>
hb_pair_t () : first (), second () {}
- hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
+ hb_pair_t (T1 a, T2 b) : first (std::forward<T1> (a)), second (std::forward<T2> (b)) {}
template <typename Q1, typename Q2,
hb_enable_if (hb_is_convertible (T1, Q1) &&
@@ -511,10 +524,28 @@ struct hb_pair_t
bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
bool operator <= (const pair_t& o) const { return !(*this > o); }
+ static int cmp (const void *pa, const void *pb)
+ {
+ pair_t *a = (pair_t *) pa;
+ pair_t *b = (pair_t *) pb;
+
+ if (a->first < b->first) return -1;
+ if (a->first > b->first) return +1;
+ if (a->second < b->second) return -1;
+ if (a->second > b->second) return +1;
+ return 0;
+ }
+
+ friend void swap (hb_pair_t& a, hb_pair_t& b)
+ {
+ hb_swap (a.first, b.first);
+ hb_swap (a.second, b.second);
+ }
+
+
T1 first;
T2 second;
};
-#define hb_pair_t(T1,T2) hb_pair_t<T1, T2>
template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
@@ -540,14 +571,14 @@ struct
{
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a <= b ? std::forward<T> (a) : std::forward<T2> (b))
+ (a <= b ? a : b)
}
HB_FUNCOBJ (hb_min);
struct
{
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a >= b ? std::forward<T> (a) : std::forward<T2> (b))
+ (a >= b ? a : b)
}
HB_FUNCOBJ (hb_max);
struct
@@ -558,17 +589,6 @@ struct
}
HB_FUNCOBJ (hb_clamp);
-struct
-{
- template <typename T> void
- operator () (T& a, T& b) const
- {
- using std::swap; // allow ADL
- swap (a, b);
- }
-}
-HB_FUNCOBJ (hb_swap);
-
/*
* Bithacks.
*/
@@ -837,14 +857,14 @@ hb_in_range (T u, T lo, T hi)
return (T)(u - lo) <= (T)(hi - lo);
}
template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
+hb_in_ranges (T u, T lo1, T hi1)
{
- return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
+ return hb_in_range (u, lo1, hi1);
}
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
+template <typename T, typename ...Ts> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
{
- return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
+ return hb_in_range<T> (u, lo1, hi1) || hb_in_ranges<T> (u, ds...);
}
@@ -852,10 +872,18 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
* Overflow checking.
*/
-/* Consider __builtin_mul_overflow use here also */
static inline bool
-hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
+hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
{
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || (defined(__clang__) && (__clang_major__ >= 8))
+ unsigned stack_result;
+ if (!result)
+ result = &stack_result;
+ return __builtin_mul_overflow (count, size, result);
+#endif
+
+ if (result)
+ *result = count * size;
return (size > 0) && (count >= ((unsigned int) -1) / size);
}
@@ -956,7 +984,7 @@ void hb_qsort(void *base, size_t nel, size_t width,
[void *arg]);
*/
-#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
+#define SORT_R_SWAP(a,b,tmp) ((void) ((tmp) = (a)), (void) ((a) = (b)), (b) = (tmp))
/* swap a and b */
/* a and b must not be equal! */
@@ -1147,9 +1175,12 @@ hb_qsort (void *base, size_t nel, size_t width,
}
-template <typename T, typename T2, typename T3> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
+template <typename T, typename T2, typename T3 = int> static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2 = nullptr)
{
+ static_assert (hb_is_trivially_copy_assignable (T), "");
+ static_assert (hb_is_trivially_copy_assignable (T3), "");
+
for (unsigned int i = 1; i < len; i++)
{
unsigned int j = i;
@@ -1172,12 +1203,6 @@ hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *)
}
}
-template <typename T> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
-{
- hb_stable_sort (array, len, compar, (int *) nullptr);
-}
-
static inline hb_bool_t
hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
{
@@ -1305,47 +1330,4 @@ struct
HB_FUNCOBJ (hb_dec);
-/* Compiler-assisted vectorization. */
-
-/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
- * basically a fixed-size bitset. */
-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) { memset (this, v, sizeof (*this)); }
-
- template <typename Op>
- hb_vector_size_t process (const Op& op) const
- {
- hb_vector_size_t r;
- for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
- r.v[i] = op (v[i]);
- return r;
- }
- template <typename Op>
- hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
- {
- hb_vector_size_t r;
- for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
- r.v[i] = op (v[i], o.v[i]);
- return r;
- }
- hb_vector_size_t operator | (const hb_vector_size_t &o) const
- { return process (hb_bitwise_or, o); }
- hb_vector_size_t operator & (const hb_vector_size_t &o) const
- { return process (hb_bitwise_and, o); }
- hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
- { return process (hb_bitwise_xor, o); }
- hb_vector_size_t operator ~ () const
- { return process (hb_bitwise_neg); }
-
- private:
- static_assert (0 == byte_size % sizeof (elt_t), "");
- elt_t v[byte_size / sizeof (elt_t)];
-};
-
-
#endif /* HB_ALGS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-array.hh
index 1d1476d7cd..e82c081535 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-array.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-array.hh
@@ -56,7 +56,6 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
hb_array_t& operator= (const hb_array_t&) = default;
hb_array_t& operator= (hb_array_t&&) = default;
- constexpr hb_array_t (std::nullptr_t) : hb_array_t () {}
constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
template <unsigned int length_>
constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {}
@@ -101,10 +100,17 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
/* Ouch. The operator== compares the contents of the array. For range-based for loops,
* it's best if we can just compare arrayZ, though comparing contents is still fast,
* but also would require that Type has operator==. As such, we optimize this operator
- * for range-based for loop and just compare arrayZ. No need to compare length, as we
- * assume we're only compared to .end(). */
+ * for range-based for loop and just compare arrayZ and length.
+ *
+ * The above comment is outdated now because we implemented separate begin/end to
+ * objects that were using hb_array_t for range-based loop before. */
bool operator != (const hb_array_t& o) const
- { return arrayZ != o.arrayZ; }
+ { return this->arrayZ != o.arrayZ || this->length != o.length; }
+
+ /* Faster range-based for loop without bounds-check. */
+ Type *begin () const { return arrayZ; }
+ Type *end () const { return arrayZ + length; }
+
/* Extra operators.
*/
@@ -114,11 +120,11 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
HB_INTERNAL bool operator == (const hb_array_t &o) const;
- uint32_t hash () const {
+ uint32_t hash () const
+ {
uint32_t current = 0;
- for (unsigned int i = 0; i < this->length; i++) {
- current = current * 31 + hb_hash (this->arrayZ[i]);
- }
+ for (auto &v : *this)
+ current = current * 31 + hb_hash (v);
return current;
}
@@ -186,23 +192,18 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
{
+ //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), "");
if (likely (length))
hb_qsort (arrayZ, length, this->get_item_size (), cmp_);
return hb_sorted_array_t<Type> (*this);
}
hb_sorted_array_t<Type> qsort ()
{
+ //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), "");
if (likely (length))
hb_qsort (arrayZ, length, this->get_item_size (), Type::cmp);
return hb_sorted_array_t<Type> (*this);
}
- void qsort (unsigned int start, unsigned int end)
- {
- end = hb_min (end, length);
- assert (start <= end);
- if (likely (start < end))
- hb_qsort (arrayZ + start, end - start, this->get_item_size (), Type::cmp);
- }
/*
* Other methods.
@@ -221,11 +222,8 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
if (end < start + 2)
return;
- for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--) {
- Type temp = arrayZ[rhs];
- arrayZ[rhs] = arrayZ[lhs];
- arrayZ[lhs] = temp;
- }
+ for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--)
+ hb_swap (arrayZ[rhs], arrayZ[lhs]);
}
hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
@@ -267,17 +265,31 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
void fini ()
{ hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
- template <typename hb_serialize_context_t>
+ template <typename hb_serialize_context_t,
+ typename U = Type,
+ hb_enable_if (!(sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>)))>
hb_array_t copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
auto* out = c->start_embed (arrayZ);
- if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ());
+ if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ());
for (unsigned i = 0; i < length; i++)
out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */
return_trace (hb_array_t (out, length));
}
+ template <typename hb_serialize_context_t,
+ typename U = Type,
+ hb_enable_if (sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>))>
+ hb_array_t copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ auto* out = c->start_embed (arrayZ);
+ if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ());
+ hb_memcpy (out, arrayZ, get_size ());
+ return_trace (hb_array_t (out, length));
+ }
+
template <typename hb_sanitize_context_t>
bool sanitize (hb_sanitize_context_t *c) const
{ return c->check_array (arrayZ, length); }
@@ -292,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>
@@ -300,8 +315,8 @@ hb_array (T (&array_)[length_])
template <typename Type>
struct hb_sorted_array_t :
- hb_iter_t<hb_sorted_array_t<Type>, Type&>,
- hb_array_t<Type>
+ hb_array_t<Type>,
+ hb_iter_t<hb_sorted_array_t<Type>, Type&>
{
typedef hb_iter_t<hb_sorted_array_t, Type&> iter_base_t;
HB_ITER_USING (iter_base_t);
@@ -314,7 +329,6 @@ struct hb_sorted_array_t :
hb_sorted_array_t& operator= (const hb_sorted_array_t&) = default;
hb_sorted_array_t& operator= (hb_sorted_array_t&&) = default;
- constexpr hb_sorted_array_t (std::nullptr_t) : hb_sorted_array_t () {}
constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
template <unsigned int length_>
constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
@@ -322,17 +336,24 @@ struct hb_sorted_array_t :
template <typename U,
hb_enable_if (hb_is_cr_convertible(U, Type))>
constexpr hb_sorted_array_t (const hb_array_t<U> &o) :
- hb_iter_t<hb_sorted_array_t, Type&> (),
- hb_array_t<Type> (o) {}
+ hb_array_t<Type> (o),
+ hb_iter_t<hb_sorted_array_t, Type&> () {}
template <typename U,
hb_enable_if (hb_is_cr_convertible(U, Type))>
hb_sorted_array_t& operator = (const hb_array_t<U> &o)
{ hb_array_t<Type> (*this) = o; return *this; }
/* Iterator implementation. */
+
+ /* See comment in hb_array_of::operator != */
bool operator != (const hb_sorted_array_t& o) const
{ return this->arrayZ != o.arrayZ || this->length != o.length; }
+ /* Faster range-based for loop without bounds-check. */
+ Type *begin () const { return this->arrayZ; }
+ Type *end () const { return this->arrayZ + this->length; }
+
+
hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
{ return hb_sorted_array_t (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
@@ -384,15 +405,16 @@ struct hb_sorted_array_t :
}
return false;
}
- template <typename T>
- bool bsearch_impl (const T &x, unsigned *pos) const
+ template <typename T, typename ...Ts>
+ bool bsearch_impl (const T &x, unsigned *pos, Ts... ds) const
{
return hb_bsearch_impl (pos,
x,
this->arrayZ,
this->length,
sizeof (Type),
- _hb_cmp_method<T, Type>);
+ _hb_cmp_method<T, Type, Ts...>,
+ std::forward<Ts> (ds)...);
}
};
template <typename T> inline hb_sorted_array_t<T>
@@ -403,7 +425,7 @@ hb_sorted_array (T (&array_)[length_])
{ return hb_sorted_array_t<T> (array_); }
template <typename T>
-bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
+inline bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
{
if (o.length != this->length) return false;
for (unsigned int i = 0; i < this->length; i++) {
@@ -411,22 +433,55 @@ bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
}
return true;
}
+template <>
+inline bool hb_array_t<const char>::operator == (const hb_array_t<const char> &o) const
+{
+ if (o.length != this->length) return false;
+ return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
+}
+template <>
+inline bool hb_array_t<const unsigned char>::operator == (const hb_array_t<const unsigned char> &o) const
+{
+ if (o.length != this->length) return false;
+ return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
+}
+
-/* TODO Specialize operator== for hb_bytes_t and hb_ubytes_t. */
+/* Specialize hash() for byte arrays. */
template <>
-inline uint32_t hb_array_t<const char>::hash () const {
+inline uint32_t hb_array_t<const char>::hash () const
+{
uint32_t current = 0;
- for (unsigned int i = 0; i < this->length; i++)
- current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
+ unsigned i = 0;
+
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
+ struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+ for (; i + 4 <= this->length; i += 4)
+ current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v);
+#endif
+
+ for (; i < this->length; i++)
+ current = current * 31 + hb_hash (this->arrayZ[i]);
return current;
}
template <>
-inline uint32_t hb_array_t<const unsigned char>::hash () const {
+inline uint32_t hb_array_t<const unsigned char>::hash () const
+{
uint32_t current = 0;
- for (unsigned int i = 0; i < this->length; i++)
- current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
+ unsigned i = 0;
+
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__))
+ struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+ for (; i + 4 <= this->length; i += 4)
+ current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v);
+#endif
+
+ for (; i < this->length; i++)
+ current = current * 31 + hb_hash (this->arrayZ[i]);
return current;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
index e640d1b586..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,6 +111,24 @@ _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
+#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
+#define _hb_compiler_memory_r_barrier() do {} while (0)
+#endif
+#endif
+
+
+
#ifndef _hb_memory_r_barrier
#define _hb_memory_r_barrier() _hb_memory_barrier ()
#endif
@@ -132,24 +150,47 @@ _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;
constexpr hb_atomic_int_t (int v) : v (v) {}
+ hb_atomic_int_t& operator = (int v_) { set_relaxed (v_); return *this; }
+ operator int () const { return get_relaxed (); }
+
void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
- void set (int v_) { hb_atomic_int_impl_set (&v, v_); }
+ void set_release (int v_) { hb_atomic_int_impl_set (&v, v_); }
int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
- int get () const { return hb_atomic_int_impl_get (&v); }
+ int get_acquire () const { return hb_atomic_int_impl_get (&v); }
int inc () { return hb_atomic_int_impl_add (&v, 1); }
int dec () { return hb_atomic_int_impl_add (&v, -1); }
@@ -167,11 +208,11 @@ struct hb_atomic_ptr_t
void init (T* v_ = nullptr) { set_relaxed (v_); }
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
- T *get () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
+ T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
- T * operator -> () const { return get (); }
- template <typename C> operator C * () const { return get (); }
+ T * operator -> () const { return get_acquire (); }
+ template <typename C> operator C * () const { return get_acquire (); }
T *v = nullptr;
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
index a9e1278de7..8e8c988716 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
@@ -39,6 +39,12 @@ struct hb_bimap_t
back_map.reset ();
}
+ void resize (unsigned pop)
+ {
+ forw_map.resize (pop);
+ back_map.resize (pop);
+ }
+
bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
@@ -48,17 +54,18 @@ struct hb_bimap_t
if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
forw_map.set (lhs, rhs);
- if (in_error ()) return;
+ if (unlikely (in_error ())) return;
back_map.set (rhs, lhs);
- if (in_error ()) forw_map.del (lhs);
+ if (unlikely (in_error ())) forw_map.del (lhs);
}
hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); }
hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
- bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); }
+ bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); }
+
void del (hb_codepoint_t lhs)
{
@@ -72,7 +79,7 @@ struct hb_bimap_t
back_map.clear ();
}
- bool is_empty () const { return get_population () == 0; }
+ bool is_empty () const { return forw_map.is_empty (); }
unsigned int get_population () const { return forw_map.get_population (); }
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
index 9759836654..9b027ac590 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
@@ -30,25 +30,89 @@
#include "hb.hh"
+
+/* Compiler-assisted vectorization. */
+
+/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
+ * 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 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
+ {
+ hb_vector_size_t r;
+ for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+ r.v[i] = op (v[i]);
+ return r;
+ }
+ template <typename Op>
+ hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
+ {
+ hb_vector_size_t r;
+ for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+ r.v[i] = op (v[i], o.v[i]);
+ return r;
+ }
+ hb_vector_size_t operator | (const hb_vector_size_t &o) const
+ { return process (hb_bitwise_or, o); }
+ hb_vector_size_t operator & (const hb_vector_size_t &o) const
+ { return process (hb_bitwise_and, o); }
+ hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
+ { return process (hb_bitwise_xor, o); }
+ hb_vector_size_t operator ~ () const
+ { return process (hb_bitwise_neg); }
+
+ hb_array_t<const elt_t> iter () const
+ { return hb_array (v); }
+
+ private:
+ static_assert (0 == byte_size % sizeof (elt_t), "");
+ elt_t v[byte_size / sizeof (elt_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
{
- for (unsigned int i = 0; i < len (); i++)
- if (v[i])
- return false;
- return true;
+ return
+ + hb_iter (v)
+ | hb_none
+ ;
+ }
+ uint32_t hash () const
+ {
+ return
+ + hb_iter (v)
+ | hb_reduce ([] (uint32_t h, const elt_t &_) { return h * 31 + hb_hash (_); }, (uint32_t) 0u)
+ ;
}
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
- void set (hb_codepoint_t g, bool v) { if (v) add (g); else del (g); }
+ void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
void add_range (hb_codepoint_t a, hb_codepoint_t b)
@@ -62,7 +126,7 @@ struct hb_bit_page_t
*la |= ~(mask (a) - 1);
la++;
- memset (la, 0xff, (char *) lb - (char *) la);
+ hb_memset (la, 0xff, (char *) lb - (char *) la);
*lb |= ((mask (b) << 1) - 1);
}
@@ -78,7 +142,7 @@ struct hb_bit_page_t
*la &= mask (a) - 1;
la++;
- memset (la, 0, (char *) lb - (char *) la);
+ hb_memset (la, 0, (char *) lb - (char *) la);
*lb &= ~((mask (b) << 1) - 1);
}
@@ -94,13 +158,13 @@ struct hb_bit_page_t
hb_codepoint_t *p,
unsigned int size) const
{
- unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_v = start_value / ELT_BITS;
unsigned int start_bit = start_value & ELT_MASK;
unsigned int count = 0;
for (unsigned i = start_v; i < len () && count < size; i++)
{
elt_t bits = v[i];
- uint32_t v_base = base | (i << ELT_BITS_LOG_2);
+ uint32_t v_base = base | (i * ELT_BITS);
for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
{
if ((elt_t(1) << j) & bits) {
@@ -125,13 +189,13 @@ struct hb_bit_page_t
unsigned int size,
hb_codepoint_t *next_value) const
{
- unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_v = start_value / ELT_BITS;
unsigned int start_bit = start_value & ELT_MASK;
unsigned int count = 0;
for (unsigned i = start_v; i < len () && count < size; i++)
{
elt_t bits = v[i];
- uint32_t v_offset = i << ELT_BITS_LOG_2;
+ uint32_t v_offset = i * ELT_BITS;
for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
{
if ((elt_t(1) << j) & bits)
@@ -154,7 +218,10 @@ struct hb_bit_page_t
bool is_equal (const hb_bit_page_t &other) const
{
- return 0 == hb_memcmp (&v, &other.v, sizeof (v));
+ for (unsigned i = 0; i < len (); i++)
+ if (v[i] != other.v[i])
+ return false;
+ return true;
}
bool is_subset (const hb_bit_page_t &larger_page) const
{
@@ -166,10 +233,10 @@ struct hb_bit_page_t
unsigned int get_population () const
{
- unsigned int pop = 0;
- for (unsigned int i = 0; i < len (); i++)
- pop += hb_popcount (v[i]);
- return pop;
+ return
+ + hb_iter (v)
+ | hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u)
+ ;
}
bool next (hb_codepoint_t *codepoint) const
@@ -243,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); }
@@ -255,8 +322,6 @@ struct hb_bit_page_t
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
- static constexpr unsigned ELT_BITS_LOG_2 = 6;
- static_assert (1 << ELT_BITS_LOG_2 == ELT_BITS, "");
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
static constexpr unsigned BITS = sizeof (vector_t) * 8;
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 4a4ce34053..1eb1b1c209 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh
@@ -38,10 +38,10 @@ struct hb_bit_set_invertible_t
bool inverted = false;
hb_bit_set_invertible_t () = default;
- hb_bit_set_invertible_t (hb_bit_set_invertible_t& o) = default;
- hb_bit_set_invertible_t (hb_bit_set_invertible_t&& o) = default;
+ hb_bit_set_invertible_t (const hb_bit_set_invertible_t& o) = default;
+ hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other) : hb_bit_set_invertible_t () { hb_swap (*this, other); }
hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default;
- hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& o) = default;
+ hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other) { hb_swap (*this, other); return *this; }
friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b)
{
if (likely (!a.s.successful || !b.s.successful))
@@ -56,6 +56,7 @@ struct hb_bit_set_invertible_t
bool in_error () const { return s.in_error (); }
explicit operator bool () const { return !is_empty (); }
+ void alloc (unsigned sz) { s.alloc (sz); }
void reset ()
{
s.reset ();
@@ -73,12 +74,19 @@ struct hb_bit_set_invertible_t
inverted = !inverted;
}
+ bool is_inverted () const
+ {
+ return inverted;
+ }
+
bool is_empty () const
{
hb_codepoint_t v = INVALID;
next (&v);
return v == INVALID;
}
+ uint32_t hash () const { return s.hash () ^ (uint32_t) inverted; }
+
hb_codepoint_t get_min () const
{
hb_codepoint_t v = INVALID;
@@ -97,7 +105,7 @@ struct hb_bit_set_invertible_t
void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
- { return unlikely (inverted) ? (s.del_range (a, b), true) : s.add_range (a, b); }
+ { return unlikely (inverted) ? ((void) s.del_range (a, b), true) : s.add_range (a, b); }
template <typename T>
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
@@ -120,10 +128,8 @@ struct hb_bit_set_invertible_t
bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
/* Has interface. */
- static constexpr bool SENTINEL = false;
- typedef bool value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ bool operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k]; }
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
index fcaff9f3be..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; }
@@ -78,25 +78,36 @@ struct hb_bit_set_t
bool successful = true; /* Allocations successful */
mutable unsigned int population = 0;
- mutable unsigned int last_page_lookup = 0;
+ mutable hb_atomic_int_t last_page_lookup = 0;
hb_sorted_vector_t<page_map_t> page_map;
hb_vector_t<page_t> pages;
void err () { if (successful) successful = false; } /* TODO Remove */
bool in_error () const { return !successful; }
- bool resize (unsigned int count)
+ bool resize (unsigned int count, bool clear = true, bool exact_size = false)
{
if (unlikely (!successful)) return false;
- if (unlikely (!pages.resize (count) || !page_map.resize (count)))
+
+ 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;
}
return true;
}
+ void alloc (unsigned sz)
+ {
+ sz >>= (page_t::PAGE_BITS_LOG_2 - 1);
+ pages.alloc (sz);
+ page_map.alloc (sz);
+ }
+
void reset ()
{
successful = true;
@@ -119,6 +130,14 @@ struct hb_bit_set_t
}
explicit operator bool () const { return !is_empty (); }
+ uint32_t hash () const
+ {
+ uint32_t h = 0;
+ for (auto &map : page_map)
+ h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]);
+ return h;
+ }
+
private:
void dirty () { population = UINT_MAX; }
public:
@@ -315,10 +334,8 @@ struct hb_bit_set_t
}
/* Has interface. */
- static constexpr bool SENTINEL = false;
- typedef bool value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ bool operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k]; }
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
@@ -333,23 +350,22 @@ 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)))
+ if (unlikely (!resize (count, false, exact_size)))
return;
population = other.population;
- /* TODO switch to vector operator =. */
- hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size);
- hb_memcpy ((void *) page_map, (const void *) other.page_map, count * page_map.item_size);
+ page_map = other.page_map;
+ pages = other.pages;
}
bool is_equal (const hb_bit_set_t &other) const
{
if (has_population () && other.has_population () &&
- get_population () != other.get_population ())
+ population != other.population)
return false;
unsigned int na = pages.length;
@@ -377,7 +393,7 @@ struct hb_bit_set_t
bool is_subset (const hb_bit_set_t &larger_set) const
{
if (has_population () && larger_set.has_population () &&
- get_population () != larger_set.get_population ())
+ population > larger_set.population)
return false;
uint32_t spi = 0;
@@ -410,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;
@@ -451,12 +467,10 @@ struct hb_bit_set_t
}
public:
- template <typename Op>
- void process (const Op& op, const hb_bit_set_t &other)
+ void process_ (hb_bit_page_t::vector_t (*op) (const hb_bit_page_t::vector_t &, const hb_bit_page_t::vector_t &),
+ bool passthru_left, bool passthru_right,
+ const hb_bit_set_t &other)
{
- const bool passthru_left = op (1, 0);
- const bool passthru_right = op (0, 1);
-
if (unlikely (!successful)) return;
dirty ();
@@ -528,21 +542,21 @@ struct hb_bit_set_t
b = nb;
for (; a && b; )
{
- if (page_map[a - 1].major == other.page_map[b - 1].major)
+ if (page_map.arrayZ[a - 1].major == other.page_map.arrayZ[b - 1].major)
{
a--;
b--;
count--;
- page_map[count] = page_map[a];
+ page_map.arrayZ[count] = page_map.arrayZ[a];
page_at (count).v = op (page_at (a).v, other.page_at (b).v);
}
- else if (page_map[a - 1].major > other.page_map[b - 1].major)
+ else if (page_map.arrayZ[a - 1].major > other.page_map.arrayZ[b - 1].major)
{
a--;
if (passthru_left)
{
count--;
- page_map[count] = page_map[a];
+ page_map.arrayZ[count] = page_map.arrayZ[a];
}
}
else
@@ -551,8 +565,8 @@ struct hb_bit_set_t
if (passthru_right)
{
count--;
- page_map[count].major = other.page_map[b].major;
- page_map[count].index = next_page++;
+ page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
+ page_map.arrayZ[count].index = next_page++;
page_at (count).v = other.page_at (b).v;
}
}
@@ -562,20 +576,29 @@ struct hb_bit_set_t
{
a--;
count--;
- page_map[count] = page_map [a];
+ page_map.arrayZ[count] = page_map.arrayZ[a];
}
if (passthru_right)
while (b)
{
b--;
count--;
- page_map[count].major = other.page_map[b].major;
- page_map[count].index = next_page++;
+ page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
+ page_map.arrayZ[count].index = next_page++;
page_at (count).v = other.page_at (b).v;
}
assert (!count);
resize (newCount);
}
+ template <typename Op>
+ static hb_bit_page_t::vector_t
+ op_ (const hb_bit_page_t::vector_t &a, const hb_bit_page_t::vector_t &b)
+ { return Op{} (a, b); }
+ template <typename Op>
+ void process (const Op& op, const hb_bit_set_t &other)
+ {
+ process_ (op_<Op>, op (1, 0), op (0, 1), other);
+ }
void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); }
void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); }
@@ -584,8 +607,6 @@ struct hb_bit_set_t
bool next (hb_codepoint_t *codepoint) const
{
- // TODO: this should be merged with prev() as both implementations
- // are very similar.
if (unlikely (*codepoint == INVALID)) {
*codepoint = get_min ();
return *codepoint != INVALID;
@@ -619,7 +640,7 @@ struct hb_bit_set_t
for (; i < page_map.length; i++)
{
- const page_map_t &current = page_map.arrayZ[i];
+ const page_map_t &current = page_map_array[i];
hb_codepoint_t m = pages_array[current.index].get_min ();
if (m != INVALID)
{
@@ -642,21 +663,21 @@ struct hb_bit_set_t
page_map_t map = {get_major (*codepoint), 0};
unsigned int i;
page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST);
- if (i < page_map.length && page_map[i].major == map.major)
+ if (i < page_map.length && page_map.arrayZ[i].major == map.major)
{
- if (pages[page_map[i].index].previous (codepoint))
+ if (pages[page_map.arrayZ[i].index].previous (codepoint))
{
- *codepoint += page_map[i].major * page_t::PAGE_BITS;
+ *codepoint += page_map.arrayZ[i].major * page_t::PAGE_BITS;
return true;
}
}
i--;
for (; (int) i >= 0; i--)
{
- hb_codepoint_t m = pages[page_map[i].index].get_max ();
+ hb_codepoint_t m = pages.arrayZ[page_map.arrayZ[i].index].get_max ();
if (m != INVALID)
{
- *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+ *codepoint = page_map.arrayZ[i].major * page_t::PAGE_BITS + m;
return true;
}
}
@@ -874,8 +895,20 @@ struct hb_bit_set_t
page_t *page_for (hb_codepoint_t g, bool insert = false)
{
- page_map_t map = {get_major (g), pages.length};
- unsigned int i;
+ unsigned major = get_major (g);
+
+ /* The extra page_map length is necessary; can't just rely on vector here,
+ * since the next check would be tricked because a null page also has
+ * major==0, which we can't distinguish from an actualy major==0 page... */
+ unsigned i = last_page_lookup;
+ if (likely (i < page_map.length))
+ {
+ auto &cached_page = page_map.arrayZ[i];
+ if (cached_page.major == major)
+ return &pages.arrayZ[cached_page.index];
+ }
+
+ page_map_t map = {major, pages.length};
if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST))
{
if (!insert)
@@ -884,24 +917,48 @@ struct hb_bit_set_t
if (unlikely (!resize (pages.length + 1)))
return nullptr;
- pages[map.index].init0 ();
- memmove (page_map + i + 1,
- page_map + i,
+ pages.arrayZ[map.index].init0 ();
+ memmove (page_map.arrayZ + i + 1,
+ page_map.arrayZ + i,
(page_map.length - 1 - i) * page_map.item_size);
page_map[i] = map;
}
- return &pages[page_map[i].index];
+
+ last_page_lookup = i;
+ return &pages.arrayZ[page_map.arrayZ[i].index];
}
const page_t *page_for (hb_codepoint_t g) const
{
- page_map_t key = {get_major (g)};
- const page_map_t *found = page_map.bsearch (key);
- if (found)
- return &pages[found->index];
- return nullptr;
+ unsigned major = get_major (g);
+
+ /* The extra page_map length is necessary; can't just rely on vector here,
+ * since the next check would be tricked because a null page also has
+ * major==0, which we can't distinguish from an actualy major==0 page... */
+ unsigned i = last_page_lookup;
+ if (likely (i < page_map.length))
+ {
+ auto &cached_page = page_map.arrayZ[i];
+ if (cached_page.major == major)
+ return &pages.arrayZ[cached_page.index];
+ }
+
+ page_map_t key = {major};
+ if (!page_map.bfind (key, &i))
+ return nullptr;
+
+ last_page_lookup = i;
+ return &pages.arrayZ[page_map[i].index];
+ }
+ page_t &page_at (unsigned int i)
+ {
+ assert (i < page_map.length);
+ return pages.arrayZ[page_map.arrayZ[i].index];
+ }
+ const page_t &page_at (unsigned int i) const
+ {
+ assert (i < page_map.length);
+ return pages.arrayZ[page_map.arrayZ[i].index];
}
- page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
- const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; }
unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; }
hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; }
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
index 65e44c7f6a..265effba03 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc
@@ -99,7 +99,7 @@ hb_blob_create (const char *data,
* is zero. This is in contrast to hb_blob_create(), which returns the singleton
* empty blob (as returned by hb_blob_get_empty()) if @length is zero.
*
- * Return value: New blob, or %NULL if failed. Destroy with hb_blob_destroy().
+ * Return value: New blob, or `NULL` if failed. Destroy with hb_blob_destroy().
*
* Since: 2.8.2
**/
@@ -263,8 +263,6 @@ hb_blob_destroy (hb_blob_t *blob)
{
if (!hb_object_destroy (blob)) return;
- blob->fini_shallow ();
-
hb_free (blob);
}
@@ -278,7 +276,7 @@ hb_blob_destroy (hb_blob_t *blob)
*
* Attaches a user-data key/data pair to the specified blob.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -305,7 +303,7 @@ hb_blob_set_user_data (hb_blob_t *blob,
* Since: 0.9.2
**/
void *
-hb_blob_get_user_data (hb_blob_t *blob,
+hb_blob_get_user_data (const hb_blob_t *blob,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (blob, key);
@@ -335,7 +333,7 @@ hb_blob_make_immutable (hb_blob_t *blob)
*
* Tests whether a blob is immutable.
*
- * Return value: %true if @blob is immutable, %false otherwise
+ * Return value: `true` if @blob is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -369,7 +367,7 @@ hb_blob_get_length (hb_blob_t *blob)
*
* Fetches the data from a blob.
*
- * Returns: (transfer none) (array length=length): the byte data of @blob.
+ * Returns: (nullable) (transfer none) (array length=length): the byte data of @blob.
*
* Since: 0.9.2
**/
@@ -394,7 +392,7 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
* fails.
*
* Returns: (transfer none) (array length=length): Writable blob data,
- * or %NULL if failed.
+ * or `NULL` if failed.
*
* Since: 0.9.2
**/
@@ -497,7 +495,7 @@ hb_blob_t::try_make_writable ()
DEBUG_MSG_FUNC (BLOB, this, "dupped successfully -> %p\n", this->data);
- memcpy (new_data, this->data, this->length);
+ hb_memcpy (new_data, this->data, this->length);
this->destroy_user_data ();
this->mode = HB_MEMORY_MODE_WRITABLE;
this->data = new_data;
@@ -572,7 +570,7 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
strncpy (rsrc_name, file_name, name_len);
strncpy (rsrc_name + name_len, _PATH_RSRCFORKSPEC,
- sizeof (_PATH_RSRCFORKSPEC) - 1);
+ sizeof (_PATH_RSRCFORKSPEC));
int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0);
hb_free (rsrc_name);
@@ -620,7 +618,7 @@ hb_blob_create_from_file (const char *file_name)
* specified binary font file.
*
* Returns: An #hb_blob_t pointer with the content of the file,
- * or %NULL if failed.
+ * or `NULL` if failed.
*
* Since: 2.8.2
**/
@@ -678,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);
@@ -699,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);
@@ -712,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-blob.h b/src/3rdparty/harfbuzz-ng/src/hb-blob.h
index 203f9e19dd..4eb42314da 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-blob.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.h
@@ -135,7 +135,7 @@ hb_blob_set_user_data (hb_blob_t *blob,
HB_EXTERN void *
-hb_blob_get_user_data (hb_blob_t *blob,
+hb_blob_get_user_data (const hb_blob_t *blob,
hb_user_data_key_t *key);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.hh b/src/3rdparty/harfbuzz-ng/src/hb-blob.hh
index a3683a681e..b1b3b94d3d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-blob.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.hh
@@ -38,7 +38,7 @@
struct hb_blob_t
{
- void fini_shallow () { destroy_user_data (); }
+ ~hb_blob_t () { destroy_user_data (); }
void destroy_user_data ()
{
@@ -61,12 +61,12 @@ struct hb_blob_t
public:
hb_object_header_t header;
- const char *data;
- unsigned int length;
- hb_memory_mode_t mode;
+ const char *data = nullptr;
+ unsigned int length = 0;
+ hb_memory_mode_t mode = (hb_memory_mode_t) 0;
- void *user_data;
- hb_destroy_func_t destroy;
+ void *user_data = nullptr;
+ hb_destroy_func_t destroy = nullptr;
};
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 e80cfea6e7..004a9fb8b7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-json.hh
@@ -32,35 +32,38 @@
#include "hb.hh"
-#line 36 "hb-buffer-deserialize-json.hh"
+#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, 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, 9u, 123u, 0u, 0u, 0
+ 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, 50, 49,
- 59, 117, 59, 117, 117, 1, 50, 49,
- 117, 85, 115, 0
+ 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, 2083,
- 2133, 2193, 2311, 2371, 2489, 2607, 2609, 2660,
- 2710, 2828, 2914, 3030
+ 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
};
static const char _deserialize_json_indicies[] = {
@@ -82,28 +85,28 @@ static const char _deserialize_json_indicies[] = {
3, 3, 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, 7, 1, 1, 8, 1,
+ 5, 1, 6, 7, 1, 8, 9, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 9, 1, 10, 11,
- 1, 12, 1, 12, 12, 12, 12, 12,
+ 1, 1, 1, 1, 10, 1, 11, 12,
+ 1, 13, 1, 13, 13, 13, 13, 13,
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, 13, 1, 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, 13, 13,
- 13, 13, 13, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 14, 1, 14, 14,
+ 14, 14, 14, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 13, 1, 1,
+ 1, 1, 1, 1, 1, 14, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 14, 1, 1, 15, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 1,
- 17, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 1, 19, 19, 19, 19, 19,
+ 1, 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, 20, 20, 20, 20,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 19, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 20, 1,
+ 1, 1, 20, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 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,
@@ -113,11 +116,11 @@ 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, 1, 1, 21,
- 1, 22, 22, 22, 22, 22, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 22,
+ 1, 23, 23, 23, 23, 23, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 22, 1, 1, 1, 1, 1, 1, 1,
+ 23, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 3, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -128,85 +131,94 @@ 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, 23, 1, 19,
- 19, 19, 19, 19, 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, 19, 1,
+ 1, 1, 1, 1, 1, 1, 25, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 20, 1, 1, 1, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18,
+ 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, 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, 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, 21, 1, 24, 1, 24,
- 24, 24, 24, 24, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 24, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 25, 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, 1, 26, 1,
- 1, 27, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 1, 29, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 1, 31,
- 31, 31, 31, 31, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 31, 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, 32, 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,
+ 36, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 33, 1, 31, 31, 31,
- 31, 31, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 31, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 32, 1, 1, 1, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 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, 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, 33, 1, 34, 1, 35, 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, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 36, 1, 36, 36, 36, 36, 36, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 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, 36, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 39, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 37, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 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, 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,
@@ -215,43 +227,42 @@ 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,
- 41, 1, 39, 39, 39, 39, 39, 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, 39, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 40, 1, 1,
- 1, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 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, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 41, 1,
- 43, 44, 1, 45, 1, 45, 45, 45,
- 45, 45, 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, 45, 1, 47, 48,
+ 1, 49, 1, 49, 49, 49, 49, 49,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 46, 1,
- 46, 46, 46, 46, 46, 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, 46,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 47, 1, 1, 48,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 1, 50, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 1, 52, 52, 52,
- 52, 52, 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, 52, 1, 1, 1,
+ 1, 1, 1, 1, 1, 50, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 53, 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, 1, 1, 1, 1, 1, 1, 1,
@@ -259,42 +270,43 @@ 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, 54, 1, 52, 52, 52, 52, 52,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 52, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 53, 1,
- 1, 1, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 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,
+ 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, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 54,
- 1, 55, 1, 55, 55, 55, 55, 55,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 55, 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, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 56, 1, 56, 56,
- 56, 56, 56, 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, 56, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 57, 1, 1, 58, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 1,
- 60, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 1, 62, 62, 62, 62, 62,
+ 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,
- 1, 1, 62, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 63, 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, 1,
@@ -302,48 +314,42 @@ 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, 1, 1, 64,
- 1, 62, 62, 62, 62, 62, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 62, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 63, 1, 1, 1,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 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, 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, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 64, 1, 65,
- 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,
+ 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, 66, 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, 67, 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, 68, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 1, 71, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 72, 70, 73, 73, 73, 73, 73, 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, 73, 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, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -352,86 +358,126 @@ 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, 1, 75, 1,
- 70, 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, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 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, 78, 1, 78, 78, 78, 78,
+ 78, 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, 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, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 70, 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, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 77,
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, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 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,
- 78, 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, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 77, 1, 1,
- 1, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 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, 1, 1, 78, 1,
- 80, 1, 80, 80, 80, 80, 80, 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, 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, 81, 1, 81, 81, 81,
- 81, 81, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 81, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 82, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 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, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 77, 1, 1, 1, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
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, 1, 1, 1, 93, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 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, 1, 1, 78, 1, 85, 85, 85,
- 85, 85, 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, 85, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 86, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 87, 1, 0, 0, 0, 0, 0,
+ 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,
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,
@@ -442,46 +488,49 @@ 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, 2, 1, 1,
- 0
+ 1, 1, 2, 1, 1, 0
};
static const char _deserialize_json_trans_targs[] = {
- 1, 0, 2, 2, 3, 4, 18, 24,
- 37, 45, 5, 12, 6, 7, 8, 9,
- 11, 9, 11, 10, 2, 49, 10, 49,
- 13, 14, 15, 16, 17, 16, 17, 10,
- 2, 49, 19, 20, 21, 22, 23, 10,
- 2, 49, 23, 25, 31, 26, 27, 28,
- 29, 30, 29, 30, 10, 2, 49, 32,
- 33, 34, 35, 36, 35, 36, 10, 2,
- 49, 38, 39, 40, 43, 44, 40, 41,
- 42, 10, 2, 49, 10, 2, 49, 44,
- 46, 47, 43, 48, 48, 49, 50, 51
+ 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, 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, 2, 14, 14, 0, 15,
- 0, 16, 16, 17, 18, 18, 19, 15,
- 0, 0, 20, 20, 21, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 0, 0, 3, 3, 4, 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 = 49;
+static const int deserialize_json_first_final = 56;
static const int deserialize_json_error = 0;
static const int deserialize_json_en_main = 1;
-#line 108 "hb-buffer-deserialize-json.rl"
+#line 111 "hb-buffer-deserialize-json.rl"
static hb_bool_t
@@ -499,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 512 "hb-buffer-deserialize-json.hh"
+#line 552 "hb-buffer-deserialize-json.hh"
{
cs = deserialize_json_start;
}
-#line 517 "hb-buffer-deserialize-json.hh"
+#line 555 "hb-buffer-deserialize-json.hh"
{
int _slen;
int _trans;
@@ -541,8 +588,8 @@ _resume:
case 1:
#line 38 "hb-buffer-deserialize-json.rl"
{
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
+ hb_memset (&info, 0, sizeof (info));
+ hb_memset (&pos , 0, sizeof (pos ));
}
break;
case 5:
@@ -561,25 +608,25 @@ _resume:
tok = p;
}
break;
- case 15:
+ case 17:
#line 55 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 21:
+ case 23:
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 16:
+ case 18:
#line 58 "hb-buffer-deserialize-json.rl"
{
/* TODO Unescape \" and \\ if found. */
if (!hb_font_glyph_from_string (font,
- tok, p - tok,
+ tok+1, p - tok - 2, /* Skip "" */
&info.codepoint))
return false;
}
break;
- case 18:
+ case 20:
#line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
break;
@@ -604,6 +651,10 @@ _resume:
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
break;
case 14:
+#line 72 "hb-buffer-deserialize-json.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+ break;
+ case 16:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
@@ -611,7 +662,7 @@ _resume:
#line 55 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 20:
+ case 22:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
@@ -619,12 +670,12 @@ _resume:
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 17:
+ case 19:
#line 58 "hb-buffer-deserialize-json.rl"
{
/* TODO Unescape \" and \\ if found. */
if (!hb_font_glyph_from_string (font,
- tok, p - tok,
+ tok+1, p - tok - 2, /* Skip "" */
&info.codepoint))
return false;
}
@@ -637,7 +688,7 @@ _resume:
*end_ptr = p;
}
break;
- case 19:
+ case 21:
#line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
#line 43 "hb-buffer-deserialize-json.rl"
@@ -709,7 +760,19 @@ _resume:
*end_ptr = p;
}
break;
-#line 713 "hb-buffer-deserialize-json.hh"
+ case 15:
+#line 72 "hb-buffer-deserialize-json.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-json.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+#line 733 "hb-buffer-deserialize-json.hh"
}
_again:
@@ -721,7 +784,7 @@ _again:
_out: {}
}
-#line 136 "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 06a605e225..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text.hh
+++ /dev/null
@@ -1,853 +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 36 "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, 45u, 57u,
- 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u,
- 43u, 124u, 45u, 57u, 48u, 57u, 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, 0
-};
-
-static const char _deserialize_text_key_spans[] = {
- 0, 83, 1, 1, 55, 77, 10, 13,
- 10, 10, 13, 10, 1, 13, 10, 14,
- 82, 13, 10, 116, 116, 0, 77, 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,
- 247, 258, 269, 283, 294, 296, 310, 321,
- 336, 419, 433, 444, 561, 678, 679, 757,
- 874, 991, 1108, 1225, 1342, 1459, 1576, 1693,
- 1810, 1927, 2044, 2161, 2278
-};
-
-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, 1, 1, 11, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 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,
- 1, 23, 1, 1, 24, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 1, 26,
- 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 1, 22, 1, 1, 1, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 1, 28, 28, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 28, 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,
- 1, 1, 28, 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, 1, 1, 1,
- 1, 1, 28, 1, 29, 1, 1, 30,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 1, 32, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 1, 34, 34, 34,
- 34, 34, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 34, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 1, 1,
- 1, 36, 37, 1, 1, 35, 35, 35,
- 35, 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, 35, 35, 35,
- 35, 35, 35, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 38, 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, 1, 1, 1, 1, 40,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 41, 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, 42, 42,
- 42, 42, 42, 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, 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, 44, 1, 42, 42, 42, 42, 42,
- 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, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 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, 44, 1,
- 47, 47, 47, 47, 47, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 47,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 48, 1, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 49, 46, 46, 50,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 51, 52, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 53, 46, 54, 54, 54,
- 54, 54, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 54, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 55,
- 1, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 56, 28, 28, 57, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 58, 59, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 60, 28, 61, 61, 61, 61, 61, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 61, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 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, 63, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 64, 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, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 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, 1, 1, 1,
- 1, 1, 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, 67, 67, 67, 67,
- 67, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 67, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 48, 1,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 49, 46, 46, 50, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 51,
- 52, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 53,
- 46, 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, 69, 1, 1, 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, 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, 71, 1, 72, 72,
- 72, 72, 72, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 72, 1, 1,
- 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, 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, 72, 72, 72, 72, 72,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 72, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 73, 1, 1,
- 1, 1, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 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,
- 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, 69, 1, 1, 1, 1, 76,
- 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 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, 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, 71, 1, 77, 77, 77,
- 77, 77, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 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, 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, 77, 77, 77, 77, 77, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 77, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 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, 61,
- 61, 61, 61, 61, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 61, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 62, 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, 63, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 64, 1, 0
-};
-
-static const char _deserialize_text_trans_targs[] = {
- 1, 0, 2, 25, 3, 4, 19, 5,
- 23, 24, 8, 27, 36, 27, 36, 30,
- 33, 11, 12, 15, 12, 15, 13, 14,
- 31, 32, 31, 32, 26, 18, 34, 35,
- 34, 35, 20, 19, 6, 21, 22, 20,
- 21, 22, 20, 21, 22, 24, 26, 26,
- 7, 9, 10, 16, 21, 29, 26, 7,
- 9, 10, 16, 21, 29, 28, 17, 21,
- 29, 28, 29, 29, 28, 7, 10, 29,
- 28, 7, 21, 29, 33, 28, 21, 29
-};
-
-static const char _deserialize_text_trans_actions[] = {
- 0, 0, 0, 0, 1, 0, 2, 0,
- 2, 2, 3, 4, 4, 5, 5, 4,
- 4, 3, 3, 3, 0, 0, 6, 3,
- 4, 4, 5, 5, 5, 3, 4, 4,
- 5, 5, 7, 8, 9, 7, 7, 0,
- 0, 0, 10, 10, 10, 8, 12, 13,
- 14, 14, 14, 15, 11, 11, 17, 18,
- 18, 18, 0, 16, 16, 19, 20, 19,
- 19, 0, 0, 13, 10, 21, 21, 10,
- 22, 23, 22, 22, 5, 24, 24, 24
-};
-
-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, 7, 0, 0, 0, 10,
- 10, 11, 16, 19, 0, 11, 10, 22,
- 22, 10, 24, 24, 19
-};
-
-static const int deserialize_text_start = 1;
-static const int deserialize_text_first_final = 19;
-static const int deserialize_text_error = 0;
-
-static const int deserialize_text_en_main = 1;
-
-
-#line 114 "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 428 "hb-buffer-deserialize-text.hh"
- {
- cs = deserialize_text_start;
- }
-
-#line 433 "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"
- {
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
-}
- break;
- case 3:
-#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 21:
-#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 23:
-#line 70 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.y_offset )) return false; }
- break;
- case 20:
-#line 71 "hb-buffer-deserialize-text.rl"
- { if (!parse_int (tok, p, &pos.x_advance)) return false; }
- break;
- case 15:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- memset (&info, 0, sizeof (info));
- memset (&pos , 0, sizeof (pos ));
-}
-#line 51 "hb-buffer-deserialize-text.rl"
- {
- tok = p;
-}
- break;
- case 4:
-#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 22:
-#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 19:
-#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 24:
-#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 12:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- memset (&info, 0, sizeof (info));
- 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"
- {
- memset (&info, 0, sizeof (info));
- 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"
- {
- memset (&info, 0, sizeof (info));
- 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"
- {
- memset (&info, 0, sizeof (info));
- 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 722 "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 22:
-#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 19:
-#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 24:
-#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 11:
-#line 38 "hb-buffer-deserialize-text.rl"
- {
- memset (&info, 0, sizeof (info));
- 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 839 "hb-buffer-deserialize-text.hh"
- }
- }
-
- _out: {}
- }
-
-#line 138 "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 6539b89640..16f189519b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc
@@ -31,7 +31,7 @@
#include "hb-buffer.hh"
-static const char *serialize_formats[] = {
+static const char *_hb_buffer_serialize_formats[] = {
"text",
"json",
nullptr
@@ -50,13 +50,13 @@ static const char *serialize_formats[] = {
const char **
hb_buffer_serialize_list_formats ()
{
- return serialize_formats;
+ return _hb_buffer_serialize_formats;
}
/**
* hb_buffer_serialize_format_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
+ * @len: length of @str, or -1 if string is `NULL` terminated
*
* Parses a string into an #hb_buffer_serialize_format_t. Does not check if
* @str is a valid buffer serialization format, use
@@ -78,11 +78,11 @@ hb_buffer_serialize_format_from_string (const char *str, int len)
* hb_buffer_serialize_format_to_string:
* @format: an #hb_buffer_serialize_format_t to convert.
*
- * Converts @format to the string corresponding it, or %NULL if it is not a valid
+ * Converts @format to the string corresponding it, or `NULL` if it is not a valid
* #hb_buffer_serialize_format_t.
*
* Return value: (transfer none):
- * A %NULL terminated string corresponding to @format. Should not be freed.
+ * A `NULL` terminated string corresponding to @format. Should not be freed.
*
* Since: 0.9.7
**/
@@ -91,8 +91,8 @@ hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
{
switch ((unsigned) format)
{
- case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0];
- case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1];
+ case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return _hb_buffer_serialize_formats[0];
+ case HB_BUFFER_SERIALIZE_FORMAT_JSON: return _hb_buffer_serialize_formats[1];
default:
case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr;
}
@@ -183,7 +183,7 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
unsigned int l = p - b;
if (buf_size > l)
{
- memcpy (buf, b, l);
+ hb_memcpy (buf, b, l);
buf += l;
buf_size -= l;
*buf_consumed += l;
@@ -241,7 +241,7 @@ _hb_buffer_serialize_unicode_json (hb_buffer_t *buffer,
unsigned int l = p - b;
if (buf_size > l)
{
- memcpy (buf, b, l);
+ hb_memcpy (buf, b, l);
buf += l;
buf_size -= l;
*buf_consumed += l;
@@ -329,7 +329,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
unsigned int l = p - b;
if (buf_size > l)
{
- memcpy (buf, b, l);
+ hb_memcpy (buf, b, l);
buf += l;
buf_size -= l;
*buf_consumed += l;
@@ -381,7 +381,7 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
unsigned int l = p - b;
if (buf_size > l)
{
- memcpy (buf, b, l);
+ hb_memcpy (buf, b, l);
buf += l;
buf_size -= l;
*buf_consumed += l;
@@ -400,9 +400,9 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf.
* @font: (nullable): the #hb_font_t used to shape this buffer, needed to
- * read glyph names and extents. If %NULL, and empty font will be used.
+ * read glyph names and extents. If `NULL`, an empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
@@ -514,7 +514,7 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
@@ -637,9 +637,9 @@ _hb_buffer_serialize_invalid (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf.
* @font: (nullable): the #hb_font_t used to shape this buffer, needed to
- * read glyph names and extents. If %NULL, and empty font will be used.
+ * read glyph names and extents. If `NULL`, an empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
@@ -721,13 +721,14 @@ 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:
* @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len): string to deserialize
- * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
+ * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated
* @end_ptr: (out) (optional): output pointer to the character after last
* consumed one.
* @font: (nullable): font for getting glyph IDs
@@ -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,
@@ -800,7 +802,7 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
* hb_buffer_deserialize_unicode:
* @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len): string to deserialize
- * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
+ * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated
* @end_ptr: (out) (optional): output pointer to the character after last
* consumed one.
* @format: the #hb_buffer_serialize_format_t of the input @buf
@@ -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 dea2c11c35..f111b2d8dc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
@@ -102,9 +102,9 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
/* Check that breaking up shaping at safe-to-break is indeed safe. */
hb_buffer_t *fragment = hb_buffer_create_similar (buffer);
- hb_buffer_set_flags (fragment, hb_buffer_get_flags (fragment) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (fragment, (hb_buffer_flags_t (hb_buffer_get_flags (fragment) & ~HB_BUFFER_FLAG_VERIFY)));
hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
- hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (reconstruction, (hb_buffer_flags_t (hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY)));
unsigned int num_glyphs;
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
@@ -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);
@@ -169,6 +169,12 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
hb_buffer_destroy (fragment);
return false;
}
+ else if (!fragment->successful || fragment->shaping_failed)
+ {
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+ return true;
+ }
hb_buffer_append (reconstruction, fragment, 0, -1);
start = end;
@@ -180,7 +186,7 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
bool ret = true;
hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
- if (diff)
+ if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
{
buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed.");
ret = false;
@@ -238,10 +244,10 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
hb_buffer_t *fragments[2] {hb_buffer_create_similar (buffer),
hb_buffer_create_similar (buffer)};
- hb_buffer_set_flags (fragments[0], hb_buffer_get_flags (fragments[0]) & ~HB_BUFFER_FLAG_VERIFY);
- hb_buffer_set_flags (fragments[1], hb_buffer_get_flags (fragments[1]) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (fragments[0], (hb_buffer_flags_t (hb_buffer_get_flags (fragments[0]) & ~HB_BUFFER_FLAG_VERIFY)));
+ hb_buffer_set_flags (fragments[1], (hb_buffer_flags_t (hb_buffer_get_flags (fragments[1]) & ~HB_BUFFER_FLAG_VERIFY)));
hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
- hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (reconstruction, (hb_buffer_flags_t (hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY)));
hb_segment_properties_t props;
hb_buffer_get_segment_properties (buffer, &props);
hb_buffer_set_segment_properties (fragments[0], &props);
@@ -286,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);
@@ -307,7 +313,6 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
bool ret = true;
hb_buffer_diff_flags_t diff;
-
/*
* Shape the two fragment streams.
*/
@@ -317,12 +322,22 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
ret = false;
goto out;
}
+ else if (!fragments[0]->successful || fragments[0]->shaping_failed)
+ {
+ ret = true;
+ goto out;
+ }
if (!hb_shape_full (font, fragments[1], features, num_features, shapers))
{
buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
ret = false;
goto out;
}
+ else if (!fragments[1]->successful || fragments[1]->shaping_failed)
+ {
+ ret = true;
+ goto out;
+ }
if (!forward)
{
@@ -366,7 +381,7 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
* Diff results.
*/
diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
- if (diff)
+ if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH)
{
buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed.");
ret = false;
@@ -402,6 +417,7 @@ hb_buffer_t::verify (hb_buffer_t *text_buffer,
ret = false;
if (!ret)
{
+#ifndef HB_NO_BUFFER_SERIALIZE
unsigned len = text_buffer->len;
hb_vector_t<char> bytes;
if (likely (bytes.resize (len * 10 + 16)))
@@ -414,6 +430,7 @@ hb_buffer_t::verify (hb_buffer_t *text_buffer,
HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS);
buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ);
}
+#endif
}
return ret;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
index 6a9ee3ccc8..f557ceee56 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
@@ -51,7 +51,7 @@
* Checks the equality of two #hb_segment_properties_t's.
*
* Return value:
- * %true if all properties of @a equal those of @b, %false otherwise.
+ * `true` if all properties of @a equal those of @b, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -81,8 +81,8 @@ hb_segment_properties_equal (const hb_segment_properties_t *a,
unsigned int
hb_segment_properties_hash (const hb_segment_properties_t *p)
{
- return (unsigned int) p->direction ^
- (unsigned int) p->script ^
+ return ((unsigned int) p->direction * 31 +
+ (unsigned int) p->script) * 31 +
(intptr_t) (p->language);
}
@@ -172,12 +172,13 @@ hb_buffer_t::enlarge (unsigned int size)
while (size >= new_allocated)
new_allocated += (new_allocated >> 1) + 32;
- static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
- if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
+ unsigned new_bytes;
+ if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]), &new_bytes)))
goto done;
- new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0]));
- new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0]));
+ static_assert (sizeof (info[0]) == sizeof (pos[0]), "");
+ new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_bytes);
+ new_info = (hb_glyph_info_t *) hb_realloc (info, new_bytes);
done:
if (unlikely (!new_pos || !new_info))
@@ -208,7 +209,7 @@ hb_buffer_t::make_room_for (unsigned int num_in,
assert (have_output);
out_info = (hb_glyph_info_t *) pos;
- memcpy (out_info, info, out_len * sizeof (out_info[0]));
+ hb_memcpy (out_info, info, out_len * sizeof (out_info[0]));
}
return true;
@@ -229,7 +230,7 @@ hb_buffer_t::shift_forward (unsigned int count)
* Ideally, we should at least set Default_Ignorable bits on
* these, as well as consistent cluster values. But the former
* is layering violation... */
- memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
+ hb_memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
}
len += count;
idx += count;
@@ -289,6 +290,7 @@ hb_buffer_t::clear ()
props = default_props;
successful = true;
+ shaping_failed = false;
have_output = false;
have_positions = false;
@@ -297,8 +299,8 @@ hb_buffer_t::clear ()
out_len = 0;
out_info = info;
- memset (context, 0, sizeof context);
- memset (context_len, 0, sizeof context_len);
+ hb_memset (context, 0, sizeof context);
+ hb_memset (context_len, 0, sizeof context_len);
deallocate_var_all ();
serial = 0;
@@ -310,16 +312,16 @@ hb_buffer_t::enter ()
{
deallocate_var_all ();
serial = 0;
+ shaping_failed = false;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
- if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR)))
+ unsigned mul;
+ if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR, &mul)))
{
- max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR,
- (unsigned) HB_BUFFER_MAX_LEN_MIN);
+ max_len = hb_max (mul, (unsigned) HB_BUFFER_MAX_LEN_MIN);
}
- if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR)))
+ if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR, &mul)))
{
- max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR,
- (unsigned) HB_BUFFER_MAX_OPS_MIN);
+ max_ops = hb_max (mul, (unsigned) HB_BUFFER_MAX_OPS_MIN);
}
}
void
@@ -329,6 +331,7 @@ hb_buffer_t::leave ()
max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
deallocate_var_all ();
serial = 0;
+ // Intentionally not reseting shaping_failed, such that it can be inspected.
}
@@ -342,7 +345,7 @@ hb_buffer_t::add (hb_codepoint_t codepoint,
glyph = &info[len];
- memset (glyph, 0, sizeof (*glyph));
+ hb_memset (glyph, 0, sizeof (*glyph));
glyph->codepoint = codepoint;
glyph->mask = 0;
glyph->cluster = cluster;
@@ -384,9 +387,11 @@ hb_buffer_t::clear_positions ()
hb_memset (pos, 0, sizeof (pos[0]) * len);
}
-void
+bool
hb_buffer_t::sync ()
{
+ bool ret = false;
+
assert (have_output);
assert (idx <= len);
@@ -400,12 +405,39 @@ hb_buffer_t::sync ()
info = out_info;
}
len = out_len;
+ ret = true;
reset:
have_output = false;
out_len = 0;
out_info = info;
idx = 0;
+
+ return ret;
+}
+
+int
+hb_buffer_t::sync_so_far ()
+{
+ bool had_output = have_output;
+ unsigned out_i = out_len;
+ unsigned i = idx;
+ unsigned old_idx = idx;
+
+ if (sync ())
+ idx = out_i;
+ else
+ idx = i;
+
+ if (had_output)
+ {
+ have_output = true;
+ out_len = idx;
+ }
+
+ assert (idx <= len);
+
+ return idx - old_idx;
}
bool
@@ -490,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);
@@ -542,7 +576,8 @@ hb_buffer_t::delete_glyph ()
/* The logic here is duplicated in hb_ot_hide_default_ignorables(). */
unsigned int cluster = info[idx].cluster;
- if (idx + 1 < len && cluster == info[idx + 1].cluster)
+ if ((idx + 1 < len && cluster == info[idx + 1].cluster) ||
+ (out_len && cluster == out_info[out_len - 1].cluster))
{
/* Cluster survives; do nothing. */
goto done;
@@ -573,6 +608,53 @@ done:
}
void
+hb_buffer_t::delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info))
+{
+ /* Merge clusters and delete filtered glyphs.
+ * NOTE! We can't use out-buffer as we have positioning data. */
+ unsigned int j = 0;
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (filter (&info[i]))
+ {
+ /* Merge clusters.
+ * Same logic as delete_glyph(), but for in-place removal. */
+
+ unsigned int cluster = info[i].cluster;
+ if (i + 1 < count && cluster == info[i + 1].cluster)
+ continue; /* Cluster survives; do nothing. */
+
+ if (j)
+ {
+ /* Merge cluster backward. */
+ if (cluster < info[j - 1].cluster)
+ {
+ unsigned int mask = info[i].mask;
+ unsigned int old_cluster = info[j - 1].cluster;
+ for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
+ set_cluster (info[k - 1], cluster, mask);
+ }
+ continue;
+ }
+
+ if (i + 1 < count)
+ merge_clusters (i, i + 2); /* Merge cluster forward. */
+
+ continue;
+ }
+
+ if (j != i)
+ {
+ info[j] = info[i];
+ pos[j] = pos[i];
+ }
+ j++;
+ }
+ len = j;
+}
+
+void
hb_buffer_t::guess_segment_properties ()
{
assert_unicode ();
@@ -623,6 +705,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
HB_SEGMENT_PROPERTIES_DEFAULT,
false, /* successful */
+ true, /* shaping_failed */
false, /* have_output */
true /* have_positions */
@@ -631,16 +714,16 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
/**
- * hb_buffer_create: (Xconstructor)
+ * hb_buffer_create:
*
* Creates a new #hb_buffer_t with all properties to defaults.
*
* Return value: (transfer full):
* A newly allocated #hb_buffer_t with a reference count of 1. The initial
* reference count should be released with hb_buffer_destroy() when you are done
- * using the #hb_buffer_t. This function never returns %NULL. If memory cannot
+ * using the #hb_buffer_t. This function never returns `NULL`. If memory cannot
* be allocated, a special #hb_buffer_t object will be returned on which
- * hb_buffer_allocation_successful() returns %false.
+ * hb_buffer_allocation_successful() returns `false`.
*
* Since: 0.9.2
**/
@@ -770,7 +853,7 @@ hb_buffer_destroy (hb_buffer_t *buffer)
*
* Attaches a user-data key/data pair to the specified buffer.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -797,7 +880,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
* Since: 0.9.2
**/
void *
-hb_buffer_get_user_data (hb_buffer_t *buffer,
+hb_buffer_get_user_data (const hb_buffer_t *buffer,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (buffer, key);
@@ -812,6 +895,32 @@ hb_buffer_get_user_data (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
@@ -834,7 +943,7 @@ hb_buffer_set_content_type (hb_buffer_t *buffer,
* Since: 0.9.5
**/
hb_buffer_content_type_t
-hb_buffer_get_content_type (hb_buffer_t *buffer)
+hb_buffer_get_content_type (const hb_buffer_t *buffer)
{
return buffer->content_type;
}
@@ -876,7 +985,7 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
+hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer)
{
return buffer->unicode;
}
@@ -899,7 +1008,6 @@ hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
void
hb_buffer_set_direction (hb_buffer_t *buffer,
hb_direction_t direction)
-
{
if (unlikely (hb_object_is_immutable (buffer)))
return;
@@ -919,7 +1027,7 @@ hb_buffer_set_direction (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_direction_t
-hb_buffer_get_direction (hb_buffer_t *buffer)
+hb_buffer_get_direction (const hb_buffer_t *buffer)
{
return buffer->props.direction;
}
@@ -963,7 +1071,7 @@ hb_buffer_set_script (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer)
+hb_buffer_get_script (const hb_buffer_t *buffer)
{
return buffer->props.script;
}
@@ -1007,7 +1115,7 @@ hb_buffer_set_language (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer)
+hb_buffer_get_language (const hb_buffer_t *buffer)
{
return buffer->props.language;
}
@@ -1043,7 +1151,7 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer,
* Since: 0.9.7
**/
void
-hb_buffer_get_segment_properties (hb_buffer_t *buffer,
+hb_buffer_get_segment_properties (const hb_buffer_t *buffer,
hb_segment_properties_t *props)
{
*props = buffer->props;
@@ -1081,7 +1189,7 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
* Since: 0.9.7
**/
hb_buffer_flags_t
-hb_buffer_get_flags (hb_buffer_t *buffer)
+hb_buffer_get_flags (const hb_buffer_t *buffer)
{
return buffer->flags;
}
@@ -1120,7 +1228,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer,
* Since: 0.9.42
**/
hb_buffer_cluster_level_t
-hb_buffer_get_cluster_level (hb_buffer_t *buffer)
+hb_buffer_get_cluster_level (const hb_buffer_t *buffer)
{
return buffer->cluster_level;
}
@@ -1161,7 +1269,7 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
* Since: 0.9.31
**/
hb_codepoint_t
-hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer)
+hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer)
{
return buffer->replacement;
}
@@ -1201,7 +1309,7 @@ hb_buffer_set_invisible_glyph (hb_buffer_t *buffer,
* Since: 2.0.0
**/
hb_codepoint_t
-hb_buffer_get_invisible_glyph (hb_buffer_t *buffer)
+hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer)
{
return buffer->invisible;
}
@@ -1241,7 +1349,7 @@ hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
* Since: 3.1.0
**/
hb_codepoint_t
-hb_buffer_get_not_found_glyph (hb_buffer_t *buffer)
+hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer)
{
return buffer->not_found;
}
@@ -1273,7 +1381,7 @@ hb_buffer_clear_contents (hb_buffer_t *buffer)
* Pre allocates memory for @buffer to fit at least @size number of items.
*
* Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise
+ * `true` if @buffer memory allocation succeeded, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1290,7 +1398,7 @@ hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
* Check if allocating memory for the buffer succeeded.
*
* Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise.
+ * `true` if @buffer memory allocation succeeded, `false` otherwise.
*
* Since: 0.9.2
**/
@@ -1335,7 +1443,7 @@ hb_buffer_add (hb_buffer_t *buffer,
* end.
*
* Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise.
+ * `true` if @buffer memory allocation succeeded, `false` otherwise.
*
* Since: 0.9.2
**/
@@ -1351,9 +1459,9 @@ hb_buffer_set_length (hb_buffer_t *buffer,
/* Wipe the new space */
if (length > buffer->len) {
- memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
+ hb_memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
if (buffer->have_positions)
- memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
+ hb_memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
}
buffer->len = length;
@@ -1381,7 +1489,7 @@ hb_buffer_set_length (hb_buffer_t *buffer,
* Since: 0.9.2
**/
unsigned int
-hb_buffer_get_length (hb_buffer_t *buffer)
+hb_buffer_get_length (const hb_buffer_t *buffer)
{
return buffer->len;
}
@@ -1421,7 +1529,7 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
* If buffer did not have positions before, the positions will be
* initialized to zeros, unless this function is called from
* within a buffer message callback (see hb_buffer_set_message_func()),
- * in which case %NULL is returned.
+ * in which case `NULL` is returned.
*
* Return value: (transfer none) (array length=length):
* The @buffer glyph position array.
@@ -1456,7 +1564,7 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
* and cleared of position data when hb_buffer_clear_contents() is called.
*
* Return value:
- * %true if the @buffer has position array, %false otherwise.
+ * `true` if the @buffer has position array, `false` otherwise.
*
* Since: 2.7.3
**/
@@ -1640,10 +1748,10 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
* @buffer: An #hb_buffer_t
* @text: (array length=text_length) (element-type uint8_t): An array of UTF-8
* characters to append.
- * @text_length: The length of the @text, or -1 if it is %NULL terminated.
+ * @text_length: The length of the @text, or -1 if it is `NULL` terminated.
* @item_offset: The offset of the first character to add to the @buffer.
* @item_length: The number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated).
+ * end of @text (assuming it is `NULL` terminated).
*
* See hb_buffer_add_codepoints().
*
@@ -1666,10 +1774,10 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer,
* hb_buffer_add_utf16:
* @buffer: An #hb_buffer_t
* @text: (array length=text_length): An array of UTF-16 characters to append
- * @text_length: The length of the @text, or -1 if it is %NULL terminated
+ * @text_length: The length of the @text, or -1 if it is `NULL` terminated
* @item_offset: The offset of the first character to add to the @buffer
* @item_length: The number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated)
+ * end of @text (assuming it is `NULL` terminated)
*
* See hb_buffer_add_codepoints().
*
@@ -1692,10 +1800,10 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer,
* hb_buffer_add_utf32:
* @buffer: An #hb_buffer_t
* @text: (array length=text_length): An array of UTF-32 characters to append
- * @text_length: The length of the @text, or -1 if it is %NULL terminated
+ * @text_length: The length of the @text, or -1 if it is `NULL` terminated
* @item_offset: The offset of the first character to add to the @buffer
* @item_length: The number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated)
+ * end of @text (assuming it is `NULL` terminated)
*
* See hb_buffer_add_codepoints().
*
@@ -1719,10 +1827,10 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
* @buffer: An #hb_buffer_t
* @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
* characters to append
- * @text_length: the length of the @text, or -1 if it is %NULL terminated
+ * @text_length: the length of the @text, or -1 if it is `NULL` terminated
* @item_offset: the offset of the first character to add to the @buffer
* @item_length: the number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated)
+ * end of @text (assuming it is `NULL` terminated)
*
* Similar to hb_buffer_add_codepoints(), but allows only access to first 256
* Unicode code points that can fit in 8-bit strings.
@@ -1745,10 +1853,10 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer,
* hb_buffer_add_codepoints:
* @buffer: a #hb_buffer_t to append characters to.
* @text: (array length=text_length): an array of Unicode code points to append.
- * @text_length: the length of the @text, or -1 if it is %NULL terminated.
+ * @text_length: the length of the @text, or -1 if it is `NULL` terminated.
* @item_offset: the offset of the first code point to add to the @buffer.
* @item_length: the number of code points to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated).
+ * end of @text (assuming it is `NULL` terminated).
*
* Appends characters from @text array to @buffer. The @item_offset is the
* position of the first character from @text that will be appended, and
@@ -1761,7 +1869,9 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer,
* marks at stat of run.
*
* This function does not check the validity of @text, it is up to the caller
- * to ensure it contains a valid Unicode code points.
+ * to ensure it contains a valid Unicode scalar values. In contrast,
+ * hb_buffer_add_utf32() can be used that takes similar input but performs
+ * sanity-check on the input.
*
* Since: 0.9.31
**/
@@ -1824,9 +1934,9 @@ hb_buffer_append (hb_buffer_t *buffer,
hb_segment_properties_overlay (&buffer->props, &source->props);
- memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
+ hb_memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
if (buffer->have_positions)
- memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
+ hb_memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE)
{
@@ -2014,7 +2124,7 @@ hb_buffer_diff (hb_buffer_t *buffer,
result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH;
if (buf_info->cluster != ref_info->cluster)
result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH;
- if ((buf_info->mask & ~ref_info->mask & HB_GLYPH_FLAG_DEFINED))
+ if ((buf_info->mask ^ ref_info->mask) & HB_GLYPH_FLAG_DEFINED)
result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH;
if (contains && ref_info->codepoint == dottedcircle_glyph)
result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
@@ -2069,6 +2179,13 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
hb_buffer_message_func_t func,
void *user_data, hb_destroy_func_t destroy)
{
+ if (unlikely (hb_object_is_immutable (buffer)))
+ {
+ if (destroy)
+ destroy (user_data);
+ return;
+ }
+
if (buffer->message_destroy)
buffer->message_destroy (buffer->message_data);
@@ -2085,8 +2202,16 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
bool
hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
{
+ assert (!have_output || (out_info == info && out_len == idx));
+
+ message_depth++;
+
char buf[100];
vsnprintf (buf, sizeof (buf), fmt, ap);
- return (bool) this->message_func (this, font, buf, this->message_data);
+ bool ret = (bool) this->message_func (this, font, buf, this->message_data);
+
+ message_depth--;
+
+ return ret;
}
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
index 14aaa5e1f5..bff78543c8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h
@@ -142,6 +142,15 @@ typedef struct hb_glyph_info_t {
* shaping, otherwise the buffer flag will not be
* reliably produced.
* Since: 4.0.0
+ * @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL: In scripts that use elongation (Arabic,
+ Mongolian, Syriac, etc.), this flag signifies
+ that it is safe to insert a U+0640 TATWEEL
+ character before this cluster for elongation.
+ This flag does not determine the
+ script-specific elongation places, but only
+ when it is safe to do the elongation without
+ interrupting text shaping.
+ Since: 5.1.0
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*
* Flags for #hb_glyph_info_t.
@@ -149,10 +158,11 @@ typedef struct hb_glyph_info_t {
* Since: 1.5.0
*/
typedef enum { /*< flags >*/
- HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
- HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
+ HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
+ HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
+ HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL = 0x00000004,
- HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */
+ HB_GLYPH_FLAG_DEFINED = 0x00000007 /* OR of all defined flags */
} hb_glyph_flags_t;
HB_EXTERN hb_glyph_flags_t
@@ -266,7 +276,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
hb_bool_t replace);
HB_EXTERN void *
-hb_buffer_get_user_data (hb_buffer_t *buffer,
+hb_buffer_get_user_data (const hb_buffer_t *buffer,
hb_user_data_key_t *key);
@@ -289,7 +299,7 @@ hb_buffer_set_content_type (hb_buffer_t *buffer,
hb_buffer_content_type_t content_type);
HB_EXTERN hb_buffer_content_type_t
-hb_buffer_get_content_type (hb_buffer_t *buffer);
+hb_buffer_get_content_type (const hb_buffer_t *buffer);
HB_EXTERN void
@@ -297,21 +307,21 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
hb_unicode_funcs_t *unicode_funcs);
HB_EXTERN hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t *buffer);
+hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_direction (hb_buffer_t *buffer,
hb_direction_t direction);
HB_EXTERN hb_direction_t
-hb_buffer_get_direction (hb_buffer_t *buffer);
+hb_buffer_get_direction (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_script (hb_buffer_t *buffer,
hb_script_t script);
HB_EXTERN hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer);
+hb_buffer_get_script (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_language (hb_buffer_t *buffer,
@@ -319,14 +329,14 @@ hb_buffer_set_language (hb_buffer_t *buffer,
HB_EXTERN hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer);
+hb_buffer_get_language (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_segment_properties (hb_buffer_t *buffer,
const hb_segment_properties_t *props);
HB_EXTERN void
-hb_buffer_get_segment_properties (hb_buffer_t *buffer,
+hb_buffer_get_segment_properties (const hb_buffer_t *buffer,
hb_segment_properties_t *props);
HB_EXTERN void
@@ -373,6 +383,11 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
* glyph-flag should be produced by the shaper. By default
* it will not be produced since it incurs a cost. Since: 4.0.0
+ * @HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL:
+ * flag indicating that the @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL
+ * glyph-flag should be produced by the shaper. By default
+ * it will not be produced. Since: 5.1.0
+ * @HB_BUFFER_FLAG_DEFINED: All currently defined flags: Since: 4.4.0
*
* Flags for #hb_buffer_t.
*
@@ -386,7 +401,10 @@ typedef enum { /*< flags >*/
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u,
HB_BUFFER_FLAG_VERIFY = 0x00000020u,
- HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u
+ HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u,
+ HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL = 0x00000080u,
+
+ HB_BUFFER_FLAG_DEFINED = 0x000000FFu
} hb_buffer_flags_t;
HB_EXTERN void
@@ -394,7 +412,7 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
hb_buffer_flags_t flags);
HB_EXTERN hb_buffer_flags_t
-hb_buffer_get_flags (hb_buffer_t *buffer);
+hb_buffer_get_flags (const hb_buffer_t *buffer);
/**
* hb_buffer_cluster_level_t:
@@ -436,7 +454,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer,
hb_buffer_cluster_level_t cluster_level);
HB_EXTERN hb_buffer_cluster_level_t
-hb_buffer_get_cluster_level (hb_buffer_t *buffer);
+hb_buffer_get_cluster_level (const hb_buffer_t *buffer);
/**
* HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT:
@@ -453,21 +471,21 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
hb_codepoint_t replacement);
HB_EXTERN hb_codepoint_t
-hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer);
+hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_invisible_glyph (hb_buffer_t *buffer,
hb_codepoint_t invisible);
HB_EXTERN hb_codepoint_t
-hb_buffer_get_invisible_glyph (hb_buffer_t *buffer);
+hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
hb_codepoint_t not_found);
HB_EXTERN hb_codepoint_t
-hb_buffer_get_not_found_glyph (hb_buffer_t *buffer);
+hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer);
/*
@@ -549,7 +567,7 @@ hb_buffer_set_length (hb_buffer_t *buffer,
unsigned int length);
HB_EXTERN unsigned int
-hb_buffer_get_length (hb_buffer_t *buffer);
+hb_buffer_get_length (const hb_buffer_t *buffer);
/* Getting glyphs out of the buffer */
@@ -583,6 +601,7 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
* @HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS: serialize glyph flags. Since: 1.5.0
* @HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES: do not serialize glyph advances,
* glyph offsets will reflect absolute glyph positions. Since: 1.8.0
+ * @HB_BUFFER_SERIALIZE_FLAG_DEFINED: All currently defined flags. Since: 4.4.0
*
* Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs().
*
@@ -595,7 +614,9 @@ typedef enum { /*< flags >*/
HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u,
HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u,
HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS = 0x00000010u,
- HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u
+ HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u,
+
+ HB_BUFFER_SERIALIZE_FLAG_DEFINED = 0x0000003Fu
} hb_buffer_serialize_flags_t;
/**
@@ -742,23 +763,23 @@ hb_buffer_diff (hb_buffer_t *buffer,
/*
- * Debugging.
+ * Tracing.
*/
/**
* hb_buffer_message_func_t:
* @buffer: An #hb_buffer_t to work upon
* @font: The #hb_font_t the @buffer is shaped with
- * @message: %NULL-terminated message passed to the function
+ * @message: `NULL`-terminated message passed to the function
* @user_data: User data pointer passed by the caller
*
* A callback method for #hb_buffer_t. The method gets called with the
* #hb_buffer_t it was set on, the #hb_font_t the buffer is shaped with and a
* message describing what step of the shaping process will be performed.
- * Returning %false from this method will skip this shaping step and move to
+ * Returning `false` from this method will skip this shaping step and move to
* the next one.
*
- * Return value: %true to perform the shaping step, %false to skip it.
+ * Return value: `true` to perform the shaping step, `false` to skip it.
*
* Since: 1.1.3
*/
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
index bc6992905e..5a43cabcb7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh
@@ -32,31 +32,13 @@
#include "hb.hh"
#include "hb-unicode.hh"
+#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)), "");
+HB_MARK_AS_FLAG_T (hb_glyph_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
@@ -69,12 +51,13 @@ enum hb_buffer_scratch_flags_t {
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u,
HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u,
+ HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE = 0x00000040u,
- /* Reserved for complex shapers' internal use. */
- HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
- HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u,
- HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u,
- HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u,
+ /* Reserved for shapers' internal use. */
+ HB_BUFFER_SCRATCH_FLAG_SHAPER0 = 0x01000000u,
+ HB_BUFFER_SCRATCH_FLAG_SHAPER1 = 0x02000000u,
+ HB_BUFFER_SCRATCH_FLAG_SHAPER2 = 0x04000000u,
+ HB_BUFFER_SCRATCH_FLAG_SHAPER3 = 0x08000000u,
};
HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
@@ -106,6 +89,7 @@ struct hb_buffer_t
hb_segment_properties_t props; /* Script, language, direction */
bool successful; /* Allocations successful */
+ bool shaping_failed; /* Shaping failure */
bool have_output; /* Whether we have an output buffer going on */
bool have_positions; /* Whether we have positions */
@@ -130,9 +114,7 @@ struct hb_buffer_t
* Managed by enter / leave
*/
-#ifndef HB_NDEBUG
uint8_t allocated_var_bits;
-#endif
uint8_t serial;
hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
unsigned int max_len; /* Maximum allowed len. */
@@ -161,38 +143,40 @@ struct hb_buffer_t
void allocate_var (unsigned int start, unsigned int count)
{
-#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
unsigned int bits = (1u<<end) - (1u<<start);
assert (0 == (allocated_var_bits & bits));
allocated_var_bits |= bits;
-#endif
+ }
+ bool try_allocate_var (unsigned int start, unsigned int count)
+ {
+ unsigned int end = start + count;
+ assert (end <= 8);
+ unsigned int bits = (1u<<end) - (1u<<start);
+ if (allocated_var_bits & bits)
+ return false;
+ allocated_var_bits |= bits;
+ return true;
}
void deallocate_var (unsigned int start, unsigned int count)
{
-#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
unsigned int bits = (1u<<end) - (1u<<start);
assert (bits == (allocated_var_bits & bits));
allocated_var_bits &= ~bits;
-#endif
}
void assert_var (unsigned int start, unsigned int count)
{
-#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
- unsigned int bits = (1u<<end) - (1u<<start);
+ HB_UNUSED unsigned int bits = (1u<<end) - (1u<<start);
assert (bits == (allocated_var_bits & bits));
-#endif
}
void deallocate_var_all ()
{
-#ifndef HB_NDEBUG
allocated_var_bits = 0;
-#endif
}
hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
@@ -204,6 +188,14 @@ struct hb_buffer_t
hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; }
hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
+ hb_set_digest_t digest () const
+ {
+ hb_set_digest_t d;
+ d.init ();
+ d.add_array (&info[0].codepoint, len, sizeof (info[0]));
+ return d;
+ }
+
HB_INTERNAL void similar (const hb_buffer_t &src);
HB_INTERNAL void reset ();
HB_INTERNAL void clear ();
@@ -285,7 +277,8 @@ struct hb_buffer_t
HB_INTERNAL void guess_segment_properties ();
- HB_INTERNAL void sync ();
+ HB_INTERNAL bool sync ();
+ HB_INTERNAL int sync_so_far ();
HB_INTERNAL void clear_output ();
HB_INTERNAL void clear_positions ();
@@ -398,6 +391,8 @@ struct hb_buffer_t
HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
/* Merge clusters for deleting current glyph, and skip it. */
HB_INTERNAL void delete_glyph ();
+ HB_INTERNAL void delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info));
+
/* Adds glyph flags in mask to infos with clusters between start and end.
@@ -458,6 +453,17 @@ struct hb_buffer_t
start, end,
true);
}
+ void safe_to_insert_tatweel (unsigned int start = 0, unsigned int end = -1)
+ {
+ if ((flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL) == 0)
+ {
+ unsafe_to_break (start, end);
+ return;
+ }
+ _set_glyph_flags (HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL,
+ start, end,
+ true);
+ }
void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
{
if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
@@ -549,18 +555,14 @@ struct hb_buffer_t
#ifdef HB_NO_BUFFER_MESSAGE
return true;
#else
- if (!messaging ())
+ if (likely (!messaging ()))
return true;
- message_depth++;
-
va_list ap;
va_start (ap, fmt);
bool ret = message_impl (font, fmt, ap);
va_end (ap);
- message_depth--;
-
return ret;
#endif
}
@@ -579,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)
@@ -619,9 +659,10 @@ DECLARE_NULL_INSTANCE (hb_buffer_t);
#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
sizeof (b->info[0].var))
-#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ())
-#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
-#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ())
+#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ())
+#define HB_BUFFER_TRY_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, try_allocate_var, var ())
+#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
+#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ())
#endif /* HB_BUFFER_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh
index e617b75de9..2e98187b50 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh
@@ -32,27 +32,39 @@
/* Implements a lockfree cache for int->int functions. */
-template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
+template <unsigned int key_bits=16,
+ unsigned int value_bits=8 + 32 - key_bits,
+ unsigned int cache_bits=8,
+ bool thread_safe=true>
struct hb_cache_t
{
+ using item_t = typename std::conditional<thread_safe,
+ 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
+ >::type;
+
static_assert ((key_bits >= cache_bits), "");
- static_assert ((key_bits + value_bits - cache_bits <= 8 * sizeof (hb_atomic_int_t)), "");
- static_assert (sizeof (hb_atomic_int_t) == sizeof (unsigned int), "");
+ static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), "");
+
+ hb_cache_t () { init (); }
void init () { clear (); }
- void fini () {}
void clear ()
{
for (unsigned i = 0; i < ARRAY_LENGTH (values); i++)
- values[i].set_relaxed (-1);
+ values[i] = -1;
}
bool get (unsigned int key, unsigned int *value) const
{
unsigned int k = key & ((1u<<cache_bits)-1);
- unsigned int v = values[k].get_relaxed ();
- if ((key_bits + value_bits - cache_bits == 8 * sizeof (hb_atomic_int_t) && v == (unsigned int) -1) ||
+ unsigned int v = values[k];
+ if ((key_bits + value_bits - cache_bits == 8 * sizeof (item_t) && v == (unsigned int) -1) ||
(v >> value_bits) != (key >> cache_bits))
return false;
*value = v & ((1u<<value_bits)-1);
@@ -65,16 +77,13 @@ struct hb_cache_t
return false; /* Overflows */
unsigned int k = key & ((1u<<cache_bits)-1);
unsigned int v = ((key>>cache_bits)<<value_bits) | value;
- values[k].set_relaxed (v);
+ values[k] = v;
return true;
}
private:
- hb_atomic_int_t values[1u<<cache_bits];
+ item_t values[1u<<cache_bits];
};
-typedef hb_cache_t<21, 16, 8> hb_cmap_cache_t;
-typedef hb_cache_t<16, 24, 8> hb_advance_cache_t;
-
#endif /* HB_CACHE_HH */
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 641de0eff2..949bfebf9b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh
@@ -248,6 +248,9 @@ struct number_t
/* byte string */
struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
{
+ hb_ubytes_t as_ubytes (unsigned l) const
+ { return hb_ubytes_t ((const unsigned char *) this, l); }
+
// encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
template <typename T, typename V>
static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value)
@@ -274,128 +277,91 @@ struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
/* Defining null_size allows a Null object may be created. Should be safe because:
* A descendent struct Dict uses a Null pointer to indicate a missing table,
* checked before access.
- * byte_str_t, a wrapper struct pairing a byte pointer along with its length, always
- * checks the length before access. A Null pointer is used as the initial pointer
- * along with zero length by the default ctor.
*/
DEFINE_SIZE_MIN(0);
};
-/* Holder of a section of byte string within a CFFIndex entry */
-struct byte_str_t : hb_ubytes_t
-{
- byte_str_t ()
- : hb_ubytes_t () {}
- byte_str_t (const UnsizedByteStr& s, unsigned int l)
- : hb_ubytes_t ((const unsigned char*)&s, l) {}
- byte_str_t (const unsigned char *s, unsigned int l)
- : hb_ubytes_t (s, l) {}
- byte_str_t (const hb_ubytes_t &ub) /* conversion from hb_ubytes_t */
- : hb_ubytes_t (ub) {}
-
- /* sub-string */
- byte_str_t sub_str (unsigned int offset, unsigned int len_) const
- { return byte_str_t (hb_ubytes_t::sub_array (offset, len_)); }
-
- bool check_limit (unsigned int offset, unsigned int count) const
- { return (offset + count <= length); }
-};
-
/* A byte string associated with the current offset and an error condition */
struct byte_str_ref_t
{
- byte_str_ref_t () { init (); }
-
- void init ()
- {
- str = byte_str_t ();
- offset = 0;
- error = false;
- }
+ byte_str_ref_t ()
+ : str () {}
- void fini () {}
+ byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0)
+ : str (str_) { set_offset (offset_); }
- byte_str_ref_t (const byte_str_t &str_, unsigned int offset_ = 0)
- : str (str_), offset (offset_), error (false) {}
-
- void reset (const byte_str_t &str_, unsigned int offset_ = 0)
+ void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0)
{
str = str_;
- offset = offset_;
- error = false;
+ set_offset (offset_);
}
const unsigned char& operator [] (int i) {
- if (unlikely ((unsigned int) (offset + i) >= str.length))
+ if (unlikely ((unsigned int) (get_offset () + i) >= str.length))
{
set_error ();
return Null (unsigned char);
}
- return str[offset + i];
+ return str.arrayZ[get_offset () + i];
}
- /* Conversion to byte_str_t */
- operator byte_str_t () const { return str.sub_str (offset, str.length - offset); }
+ unsigned char head_unchecked () const { return str.arrayZ[get_offset ()]; }
+
+ /* Conversion to hb_ubytes_t */
+ operator hb_ubytes_t () const { return str.sub_array (get_offset ()); }
- byte_str_t sub_str (unsigned int offset_, unsigned int len_) const
- { return str.sub_str (offset_, len_); }
+ hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const
+ { return str.sub_array (offset_, len_); }
bool avail (unsigned int count=1) const
- { return (!in_error () && str.check_limit (offset, count)); }
+ { return get_offset () + count <= str.length; }
void inc (unsigned int count=1)
{
- if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
- {
- offset += count;
- }
- else
- {
- offset = str.length;
- set_error ();
- }
+ /* Automatically puts us in error if count is out-of-range. */
+ set_offset (get_offset () + count);
}
- void set_error () { error = true; }
- bool in_error () const { return error; }
+ /* We (ab)use ubytes backwards_length as a cursor (called offset),
+ * as well as to store error condition. */
+
+ unsigned get_offset () const { return str.backwards_length; }
+ void set_offset (unsigned offset) { str.backwards_length = offset; }
- byte_str_t str;
- unsigned int offset; /* beginning of the sub-string within str */
+ void set_error () { str.backwards_length = str.length + 1; }
+ bool in_error () const { return str.backwards_length > str.length; }
+
+ unsigned total_size () const { return str.length; }
protected:
- bool error;
+ hb_ubytes_t str;
};
-typedef hb_vector_t<byte_str_t> byte_str_array_t;
+using byte_str_array_t = hb_vector_t<hb_ubytes_t>;
/* stack */
template <typename ELEM, int LIMIT>
struct cff_stack_t
{
- void init ()
- {
- error = false;
- count = 0;
- elements.init ();
- elements.resize (kSizeLimit);
- }
- void fini () { elements.fini (); }
-
ELEM& operator [] (unsigned int i)
{
- if (unlikely (i >= count)) set_error ();
+ if (unlikely (i >= count))
+ {
+ set_error ();
+ return Crap (ELEM);
+ }
return elements[i];
}
void push (const ELEM &v)
{
- if (likely (count < elements.length))
+ if (likely (count < LIMIT))
elements[count++] = v;
else
set_error ();
}
ELEM &push ()
{
- if (likely (count < elements.length))
+ if (likely (count < LIMIT))
return elements[count++];
else
{
@@ -424,7 +390,7 @@ struct cff_stack_t
const ELEM& peek ()
{
- if (unlikely (count < 0))
+ if (unlikely (count == 0))
{
set_error ();
return Null (ELEM);
@@ -434,7 +400,7 @@ struct cff_stack_t
void unpop ()
{
- if (likely (count < elements.length))
+ if (likely (count < LIMIT))
count++;
else
set_error ();
@@ -442,18 +408,19 @@ struct cff_stack_t
void clear () { count = 0; }
- bool in_error () const { return (error || elements.in_error ()); }
+ bool in_error () const { return (error); }
void set_error () { error = true; }
unsigned int get_count () const { return count; }
bool is_empty () const { return !count; }
- static constexpr unsigned kSizeLimit = LIMIT;
+ hb_array_t<const ELEM> sub_array (unsigned start, unsigned length) const
+ { return hb_array_t<const ELEM> (elements).sub_array (start, length); }
- protected:
- bool error;
- unsigned int count;
- hb_vector_t<ELEM> elements;
+ private:
+ bool error = false;
+ unsigned int count = 0;
+ ELEM elements[LIMIT];
};
/* argument stack */
@@ -508,9 +475,6 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
return true;
}
- hb_array_t<const ARG> get_subarray (unsigned int start) const
- { return S::elements.sub_array (start); }
-
private:
typedef cff_stack_t<ARG, 513> S;
};
@@ -518,8 +482,15 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
/* an operator prefixed by its operands in a byte string */
struct op_str_t
{
- op_code_t op;
- byte_str_t str;
+ /* This used to have a hb_ubytes_t. Using a pointer and length
+ * in a particular order, saves 8 bytes in this struct and more
+ * in our parsed_cs_op_t subclass. */
+
+ const unsigned char *ptr = nullptr;
+
+ op_code_t op = OpCode_Invalid;
+
+ uint8_t length = 0;
};
/* base of OP_SERIALIZER */
@@ -530,9 +501,11 @@ struct op_serializer_t
{
TRACE_SERIALIZE (this);
- HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+ unsigned char *d = c->allocate_size<unsigned char> (opstr.length);
if (unlikely (!d)) return_trace (false);
- memcpy (d, &opstr.str[0], opstr.str.length);
+ /* Faster than hb_memcpy for small strings. */
+ for (unsigned i = 0; i < opstr.length; i++)
+ d[i] = opstr.ptr[i];
return_trace (true);
}
};
@@ -547,32 +520,30 @@ struct parsed_values_t
}
void fini () { values.fini (); }
- void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ())
+ void alloc (unsigned n)
{
- VAL *val = values.push ();
- val->op = op;
- val->str = str_ref.str.sub_str (opStart, str_ref.offset - opStart);
- opStart = str_ref.offset;
+ values.alloc (n, true);
}
- 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;
- val->str = str_ref.sub_str ( opStart, str_ref.offset - opStart);
- opStart = str_ref.offset;
+ 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 ();
}
bool has_op (op_code_t op) const
{
- for (unsigned int i = 0; i < get_count (); i++)
- if (get_value (i).op == op) return true;
+ for (const auto& v : values)
+ if (v.op == op) return true;
return false;
}
unsigned get_count () const { return values.length; }
- const VAL &get_value (unsigned int i) const { return values[i]; }
- const VAL &operator [] (unsigned int i) const { return get_value (i); }
+ const VAL &operator [] (unsigned int i) const { return values[i]; }
unsigned int opStart;
hb_vector_t<VAL> values;
@@ -581,32 +552,29 @@ struct parsed_values_t
template <typename ARG=number_t>
struct interp_env_t
{
- void init (const byte_str_t &str_)
+ interp_env_t () {}
+ interp_env_t (const hb_ubytes_t &str_)
{
str_ref.reset (str_);
- argStack.init ();
- error = false;
}
- void fini () { argStack.fini (); }
-
bool in_error () const
- { return error || str_ref.in_error () || argStack.in_error (); }
+ { return str_ref.in_error () || argStack.in_error (); }
- void set_error () { error = true; }
+ void set_error () { str_ref.set_error (); }
op_code_t fetch_op ()
{
op_code_t op = OpCode_Invalid;
if (unlikely (!str_ref.avail ()))
return OpCode_Invalid;
- op = (op_code_t)(unsigned char)str_ref[0];
+ op = (op_code_t) str_ref.head_unchecked ();
+ str_ref.inc ();
if (op == OpCode_escape) {
if (unlikely (!str_ref.avail ()))
return OpCode_Invalid;
- op = Make_OpCode_ESC(str_ref[1]);
+ op = Make_OpCode_ESC (str_ref.head_unchecked ());
str_ref.inc ();
}
- str_ref.inc ();
return op;
}
@@ -621,11 +589,9 @@ struct interp_env_t
str_ref;
arg_stack_t<ARG>
argStack;
- protected:
- bool error;
};
-typedef interp_env_t<> num_interp_env_t;
+using num_interp_env_t = interp_env_t<>;
template <typename ARG=number_t>
struct opset_t
@@ -668,11 +634,8 @@ struct opset_t
template <typename ENV>
struct interpreter_t
{
- ~interpreter_t() { fini (); }
-
- void fini () { env.fini (); }
-
- ENV env;
+ interpreter_t (ENV& env_) : env (env_) {}
+ ENV& env;
};
} /* namespace CFF */
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 ef299369b5..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
@@ -79,10 +79,10 @@ struct biased_subrs_t
unsigned int get_count () const { return subrs ? subrs->count : 0; }
unsigned int get_bias () const { return bias; }
- byte_str_t operator [] (unsigned int index) const
+ hb_ubytes_t operator [] (unsigned int index) const
{
if (unlikely (!subrs || index >= subrs->count))
- return Null (byte_str_t);
+ return hb_ubytes_t ();
else
return (*subrs)[index];
}
@@ -112,10 +112,9 @@ struct point_t
template <typename ARG, typename SUBRS>
struct cs_interp_env_t : interp_env_t<ARG>
{
- void init (const byte_str_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_)
+ cs_interp_env_t (const hb_ubytes_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_) :
+ interp_env_t<ARG> (str)
{
- interp_env_t<ARG>::init (str);
-
context.init (str, CSType_CharString);
seen_moveto = true;
seen_hintmask = false;
@@ -123,15 +122,11 @@ struct cs_interp_env_t : interp_env_t<ARG>
vstem_count = 0;
hintmask_size = 0;
pt.set_int (0, 0);
- callStack.init ();
globalSubrs.init (globalSubrs_);
localSubrs.init (localSubrs_);
}
- void fini ()
+ ~cs_interp_env_t ()
{
- interp_env_t<ARG>::fini ();
-
- callStack.fini ();
globalSubrs.fini ();
localSubrs.fini ();
}
@@ -880,11 +875,19 @@ struct path_procs_t
template <typename ENV, typename OPSET, typename PARAM>
struct cs_interpreter_t : interpreter_t<ENV>
{
+ cs_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
+
bool interpret (PARAM& param)
{
SUPER::env.set_endchar (false);
+ unsigned max_ops = HB_CFF_MAX_OPS;
for (;;) {
+ if (unlikely (!--max_ops))
+ {
+ SUPER::env.set_error ();
+ break;
+ }
OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
if (unlikely (SUPER::env.in_error ()))
return false;
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 a520ca3bce..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;
@@ -179,6 +177,8 @@ struct top_dict_opset_t : dict_opset_t
template <typename OPSET, typename PARAM, typename ENV=num_interp_env_t>
struct dict_interpreter_t : interpreter_t<ENV>
{
+ dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
+
bool interpret (PARAM& param)
{
param.init ();
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 1c8762c172..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,17 +38,16 @@ 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>
- void init (const byte_str_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)
{
- SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
processed_width = false;
has_width = false;
arg_start = 0;
in_seac = false;
}
- void fini () { SUPER::fini (); }
-
void set_width (bool has_width_)
{
if (likely (!processed_width && (SUPER::argStack.get_count () > 0)))
@@ -154,7 +153,7 @@ struct cff1_cs_opset_t : cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM
};
template <typename OPSET, typename PARAM>
-struct cff1_cs_interpreter_t : cs_interpreter_t<cff1_cs_interp_env_t, OPSET, PARAM> {};
+using cff1_cs_interpreter_t = cs_interpreter_t<cff1_cs_interp_env_t, OPSET, PARAM>;
} /* namespace CFF */
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 766183760e..915b10cf39 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh
@@ -40,20 +40,22 @@ struct blend_arg_t : number_t
void set_real (double v) { reset_blends (); number_t::set_real (v); }
void set_blends (unsigned int numValues_, unsigned int valueIndex_,
- unsigned int numBlends, hb_array_t<const blend_arg_t> blends_)
+ hb_array_t<const blend_arg_t> blends_)
{
numValues = numValues_;
valueIndex = valueIndex_;
- deltas.resize (numBlends);
+ unsigned numBlends = blends_.length;
+ if (unlikely (!deltas.resize_exact (numBlends)))
+ return;
for (unsigned int i = 0; i < numBlends; i++)
- deltas[i] = blends_[i];
+ deltas.arrayZ[i] = blends_.arrayZ[i];
}
bool blending () const { return deltas.length > 0; }
void reset_blends ()
{
numValues = valueIndex = 0;
- deltas.resize (0);
+ deltas.shrink (0);
}
unsigned int numValues;
@@ -61,17 +63,16 @@ struct blend_arg_t : number_t
hb_vector_t<number_t> deltas;
};
-typedef interp_env_t<blend_arg_t> BlendInterpEnv;
typedef biased_subrs_t<CFF2Subrs> cff2_biased_subrs_t;
-struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
+template <typename ELEM>
+struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
{
template <typename ACC>
- void init (const byte_str_t &str, ACC &acc, unsigned int fd,
- const int *coords_=nullptr, unsigned int num_coords_=0)
+ cff2_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)
{
- SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
-
coords = coords_;
num_coords = num_coords_;
varStore = acc.varStore;
@@ -100,18 +101,14 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
return OpCode_return;
}
- const blend_arg_t& eval_arg (unsigned int i)
+ const ELEM& eval_arg (unsigned int i)
{
- blend_arg_t &arg = argStack[i];
- blend_arg (arg);
- return arg;
+ return SUPER::argStack[i];
}
- const blend_arg_t& pop_arg ()
+ const ELEM& pop_arg ()
{
- blend_arg_t &arg = argStack.pop ();
- blend_arg (arg);
- return arg;
+ return SUPER::argStack.pop ();
}
void process_blend ()
@@ -121,8 +118,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
region_count = varStore->varStore.get_region_index_count (get_ivs ());
if (do_blend)
{
- if (unlikely (!scalars.resize (region_count)))
- set_error ();
+ if (unlikely (!scalars.resize_exact (region_count)))
+ SUPER::set_error ();
else
varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
&scalars[0], region_count);
@@ -133,10 +130,10 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
void process_vsindex ()
{
- unsigned int index = argStack.pop_uint ();
+ unsigned int index = SUPER::argStack.pop_uint ();
if (unlikely (seen_vsindex () || seen_blend))
{
- set_error ();
+ SUPER::set_error ();
}
else
{
@@ -151,24 +148,23 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
void set_ivs (unsigned int ivs_) { ivs = ivs_; }
bool seen_vsindex () const { return seen_vsindex_; }
- protected:
- void blend_arg (blend_arg_t &arg)
+ double blend_deltas (hb_array_t<const ELEM> deltas) const
{
- if (do_blend && arg.blending ())
+ double v = 0;
+ if (do_blend)
{
- if (likely (scalars.length == arg.deltas.length))
+ if (likely (scalars.length == deltas.length))
{
- double v = arg.to_real ();
- for (unsigned int i = 0; i < scalars.length; i++)
- {
- v += (double)scalars[i] * arg.deltas[i].to_real ();
- }
- arg.set_real (v);
- arg.deltas.resize (0);
+ unsigned count = scalars.length;
+ for (unsigned i = 0; i < count; i++)
+ v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
}
}
+ return v;
}
+ bool have_coords () const { return num_coords; }
+
protected:
const int *coords;
unsigned int num_coords;
@@ -180,22 +176,24 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
bool seen_vsindex_;
bool seen_blend;
- typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
+ typedef cs_interp_env_t<ELEM, CFF2Subrs> SUPER;
};
-template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM>>
-struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
+template <typename OPSET, typename PARAM, typename ELEM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t<ELEM>, PARAM>>
+struct cff2_cs_opset_t : cs_opset_t<ELEM, OPSET, cff2_cs_interp_env_t<ELEM>, PARAM, PATH>
{
- static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
+ static void process_op (op_code_t op, cff2_cs_interp_env_t<ELEM> &env, PARAM& param)
{
switch (op) {
case OpCode_callsubr:
case OpCode_callgsubr:
/* a subroutine number shouldn't be a blended value */
+#if 0
if (unlikely (env.argStack.peek ().blending ()))
{
env.set_error ();
break;
}
+#endif
SUPER::process_op (op, env, param);
break;
@@ -204,11 +202,13 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
break;
case OpCode_vsindexcs:
+#if 0
if (unlikely (env.argStack.peek ().blending ()))
{
env.set_error ();
break;
}
+#endif
OPSET::process_vsindex (env, param);
break;
@@ -217,7 +217,29 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
}
}
- static void process_blend (cff2_cs_interp_env_t &env, PARAM& param)
+ template <typename T = ELEM,
+ hb_enable_if (hb_is_same (T, blend_arg_t))>
+ static void process_arg_blend (cff2_cs_interp_env_t<ELEM> &env,
+ ELEM &arg,
+ const hb_array_t<const ELEM> blends,
+ unsigned n, unsigned i)
+ {
+ 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))>
+ static void process_arg_blend (cff2_cs_interp_env_t<ELEM> &env,
+ ELEM &arg,
+ const hb_array_t<const ELEM> blends,
+ unsigned n, unsigned i)
+ {
+ arg.set_real (arg.to_real () + env.blend_deltas (blends));
+ }
+
+ static void process_blend (cff2_cs_interp_env_t<ELEM> &env, PARAM& param)
{
unsigned int n, k;
@@ -234,26 +256,26 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
}
for (unsigned int i = 0; i < n; i++)
{
- const hb_array_t<const blend_arg_t> blends = env.argStack.get_subarray (start + n + (i * k));
- env.argStack[start + i].set_blends (n, i, k, blends);
+ const hb_array_t<const ELEM> blends = env.argStack.sub_array (start + n + (i * k), k);
+ process_arg_blend (env, 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_vsindex (cff2_cs_interp_env_t &env, PARAM& param)
+ static void process_vsindex (cff2_cs_interp_env_t<ELEM> &env, PARAM& param)
{
env.process_vsindex ();
env.clear_args ();
}
private:
- typedef cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH> SUPER;
+ typedef cs_opset_t<ELEM, OPSET, cff2_cs_interp_env_t<ELEM>, PARAM, PATH> SUPER;
};
-template <typename OPSET, typename PARAM>
-struct cff2_cs_interpreter_t : cs_interpreter_t<cff2_cs_interp_env_t, OPSET, PARAM> {};
+template <typename OPSET, typename PARAM, typename ELEM>
+using cff2_cs_interpreter_t = cs_interpreter_t<cff2_cs_interp_env_t<ELEM>, OPSET, PARAM>;
} /* namespace CFF */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-common.cc
index 41229b9183..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
@@ -99,7 +73,7 @@ _hb_options_init ()
}
/* This is idempotent and threadsafe. */
- _hb_options.set_relaxed (u.i);
+ _hb_options = u.i;
}
@@ -108,7 +82,7 @@ _hb_options_init ()
/**
* hb_tag_from_string:
* @str: (array length=len) (element-type uint8_t): String to convert
- * @len: Length of @str, or -1 if it is %NULL-terminated
+ * @len: Length of @str, or -1 if it is `NULL`-terminated
*
* Converts a string into an #hb_tag_t. Valid tags
* are four characters. Shorter input strings will be
@@ -160,7 +134,7 @@ hb_tag_to_string (hb_tag_t tag, char *buf)
/* hb_direction_t */
-const char direction_strings[][4] = {
+static const char direction_strings[][4] = {
"ltr",
"rtl",
"ttb",
@@ -170,7 +144,7 @@ const char direction_strings[][4] = {
/**
* hb_direction_from_string:
* @str: (array length=len) (element-type uint8_t): String to convert
- * @len: Length of @str, or -1 if it is %NULL-terminated
+ * @len: Length of @str, or -1 if it is `NULL`-terminated
*
* Converts a string to an #hb_direction_t.
*
@@ -285,7 +259,7 @@ struct hb_language_item_t {
lang = (hb_language_t) hb_malloc(len);
if (likely (lang))
{
- memcpy((unsigned char *) lang, s, len);
+ hb_memcpy((unsigned char *) lang, s, len);
for (unsigned char *p = (unsigned char *) lang; *p; p++)
*p = canon_map[*p];
}
@@ -357,7 +331,7 @@ retry:
* hb_language_from_string:
* @str: (array length=len) (element-type uint8_t): a string representing
* a BCP 47 language tag
- * @len: length of the @str, or -1 if it is %NULL-terminated.
+ * @len: length of the @str, or -1 if it is `NULL`-terminated.
*
* Converts @str representing a BCP 47 language tag to the corresponding
* #hb_language_t.
@@ -379,7 +353,7 @@ hb_language_from_string (const char *str, int len)
/* NUL-terminate it. */
char strbuf[64];
len = hb_min (len, (int) sizeof (strbuf) - 1);
- memcpy (strbuf, str, len);
+ hb_memcpy (strbuf, str, len);
strbuf[len] = '\0';
item = lang_find_or_insert (strbuf);
}
@@ -396,7 +370,7 @@ hb_language_from_string (const char *str, int len)
* Converts an #hb_language_t to a string.
*
* Return value: (transfer none):
- * A %NULL-terminated string representing the @language. Must not be freed by
+ * A `NULL`-terminated string representing the @language. Must not be freed by
* the caller.
*
* Since: 0.9.2
@@ -441,6 +415,38 @@ hb_language_get_default ()
return language;
}
+/**
+ * hb_language_matches:
+ * @language: The #hb_language_t to work on
+ * @specific: Another #hb_language_t
+ *
+ * Check whether a second language tag is the same or a more
+ * specific version of the provided language tag. For example,
+ * "fa_IR.utf8" is a more specific tag for "fa" or for "fa_IR".
+ *
+ * Return value: `true` if languages match, `false` otherwise.
+ *
+ * Since: 5.0.0
+ **/
+hb_bool_t
+hb_language_matches (hb_language_t language,
+ hb_language_t specific)
+{
+ if (language == specific) return true;
+ if (!language || !specific) return false;
+
+ const char *l = language->s;
+ const char *s = specific->s;
+ unsigned ll = strlen (l);
+ unsigned sl = strlen (s);
+
+ if (ll > sl)
+ return false;
+
+ return strncmp (l, s, ll) == 0 &&
+ (s[ll] == '\0' || s[ll] == '-');
+}
+
/* hb_script_t */
@@ -498,7 +504,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
* hb_script_from_string:
* @str: (array length=len) (element-type uint8_t): a string representing an
* ISO 15924 tag.
- * @len: length of the @str, or -1 if it is %NULL-terminated.
+ * @len: length of the @str, or -1 if it is `NULL`-terminated.
*
* Converts a string @str representing an ISO 15924 script tag to a
* corresponding #hb_script_t. Shorthand for hb_tag_from_string() then
@@ -693,8 +699,8 @@ hb_version_string ()
* Tests the library version against a minimum value,
* as three integer components.
*
- * Return value: %true if the library is equal to or greater than
- * the test value, %false otherwise
+ * Return value: `true` if the library is equal to or greater than
+ * the test value, `false` otherwise
*
* Since: 0.9.30
**/
@@ -881,7 +887,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
/**
* hb_feature_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
+ * @len: length of @str, or -1 if string is `NULL` terminated
* @feature: (out): the #hb_feature_t to initialize with the parsed values
*
* Parses a string into a #hb_feature_t.
@@ -923,7 +929,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
* </informaltable>
*
* Return value:
- * %true if @str is successfully parsed, %false otherwise
+ * `true` if @str is successfully parsed, `false` otherwise
*
* Since: 0.9.5
**/
@@ -944,7 +950,7 @@ hb_feature_from_string (const char *str, int len,
}
if (feature)
- memset (feature, 0, sizeof (*feature));
+ hb_memset (feature, 0, sizeof (*feature));
return false;
}
@@ -954,7 +960,7 @@ hb_feature_from_string (const char *str, int len,
* @buf: (array length=size) (out): output string
* @size: the allocated size of @buf
*
- * Converts a #hb_feature_t into a %NULL-terminated string in the format
+ * Converts a #hb_feature_t into a `NULL`-terminated string in the format
* understood by hb_feature_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
@@ -993,7 +999,7 @@ hb_feature_to_string (hb_feature_t *feature,
}
assert (len < ARRAY_LENGTH (s));
len = hb_min (len, size - 1);
- memcpy (buf, s, len);
+ hb_memcpy (buf, s, len);
buf[len] = '\0';
}
@@ -1022,7 +1028,7 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation
/**
* hb_variation_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
+ * @len: length of @str, or -1 if string is `NULL` terminated
* @variation: (out): the #hb_variation_t to initialize with the parsed values
*
* Parses a string into a #hb_variation_t.
@@ -1035,7 +1041,7 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation
* number. For example `wght=500`, or `slnt=-7.5`.
*
* Return value:
- * %true if @str is successfully parsed, %false otherwise
+ * `true` if @str is successfully parsed, `false` otherwise
*
* Since: 1.4.2
*/
@@ -1056,7 +1062,7 @@ hb_variation_from_string (const char *str, int len,
}
if (variation)
- memset (variation, 0, sizeof (*variation));
+ hb_memset (variation, 0, sizeof (*variation));
return false;
}
@@ -1104,10 +1110,10 @@ get_C_locale ()
/**
* hb_variation_to_string:
* @variation: an #hb_variation_t to convert
- * @buf: (array length=size) (out): output string
+ * @buf: (array length=size) (out caller-allocates): output string
* @size: the allocated size of @buf
*
- * Converts an #hb_variation_t into a %NULL-terminated string in the format
+ * Converts an #hb_variation_t into a `NULL`-terminated string in the format
* understood by hb_variation_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
@@ -1134,7 +1140,7 @@ hb_variation_to_string (hb_variation_t *variation,
assert (len < ARRAY_LENGTH (s));
len = hb_min (len, size - 1);
- memcpy (buf, s, len);
+ hb_memcpy (buf, s, len);
buf[len] = '\0';
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h
index 7b897a6c51..a5da4e76a3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-common.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h
@@ -326,6 +326,9 @@ hb_language_to_string (hb_language_t language);
HB_EXTERN hb_language_t
hb_language_get_default (void);
+HB_EXTERN hb_bool_t
+hb_language_matches (hb_language_t language,
+ hb_language_t specific);
/**
* hb_script_t:
@@ -492,6 +495,8 @@ hb_language_get_default (void);
* @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
* @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
* @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0
+ * @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0
+ * @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0
* @HB_SCRIPT_INVALID: No script set
*
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
@@ -713,6 +718,12 @@ typedef enum
*/
HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'),
+ /*
+ * Since 5.2.0
+ */
+ HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/
+ HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/
+
/* No script set. */
HB_SCRIPT_INVALID = HB_TAG_NONE,
@@ -886,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 4b46dea938..047518b87d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-config.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-config.hh
@@ -35,6 +35,11 @@
#include "config.h"
#endif
+#ifndef HB_EXPERIMENTAL_API
+#define HB_NO_BEYOND_64K
+#define HB_NO_CUBIC_GLYF
+#define HB_NO_VAR_COMPOSITES
+#endif
#ifdef HB_TINY
#define HB_LEAN
@@ -64,9 +69,11 @@
#define HB_NO_FACE_COLLECT_UNICODES
#define HB_NO_GETENV
#define HB_NO_HINTING
+#define HB_NO_LANGUAGE_LONG
#define HB_NO_LANGUAGE_PRIVATE_SUBTAG
#define HB_NO_LAYOUT_FEATURE_PARAMS
#define HB_NO_LAYOUT_COLLECT_GLYPHS
+#define HB_NO_LAYOUT_RARELY_USED
#define HB_NO_LAYOUT_UNUSED
#define HB_NO_MATH
#define HB_NO_META
@@ -74,11 +81,13 @@
#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
#define HB_NO_VAR
#endif
@@ -97,12 +106,22 @@
/* Closure of options. */
+#ifdef HB_NO_BORING_EXPANSION
+#define HB_NO_BEYOND_64K
+#define HB_NO_AVAR2
+#endif
+
#ifdef HB_DISABLE_DEPRECATED
#define HB_IF_NOT_DEPRECATED(x)
#else
#define HB_IF_NOT_DEPRECATED(x) x
#endif
+#ifdef HB_NO_SHAPER
+#define HB_NO_OT_SHAPE
+#define HB_NO_AAT_SHAPE
+#endif
+
#ifdef HB_NO_AAT
#define HB_NO_OT_NAME_LANGUAGE_AAT
#define HB_NO_AAT_SHAPE
@@ -145,10 +164,11 @@
#endif
#ifdef HB_NO_OT_SHAPE_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
+#define HB_NO_OT_SHAPER_ARABIC_FALLBACK
+#define HB_NO_OT_SHAPER_HEBREW_FALLBACK
+#define HB_NO_OT_SHAPER_THAI_FALLBACK
+#define HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS
+#define HB_NO_OT_SHAPER_MYANMAR_ZAWGYI
#endif
#ifdef NDEBUG
@@ -163,5 +183,9 @@
#endif
#endif
+#ifdef HB_OPTIMIZE_SIZE
+#define HB_NO_OT_LAYOUT_LOOKUP_CACHE
+#endif
+
#endif /* HB_CONFIG_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
index 6ccc1b0a2b..a87cb5cd02 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
@@ -332,7 +332,7 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
return nullptr;
}
- if (font->coords)
+ if (font->num_coords)
{
CFMutableDictionaryRef variations =
CFDictionaryCreateMutable (kCFAllocatorDefault,
@@ -347,10 +347,13 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
hb_ot_var_axis_info_t info;
unsigned int c = 1;
hb_ot_var_get_axis_infos (font->face, i, &c, &info);
- CFDictionarySetValue (variations,
- CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag),
- CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &font->design_coords[i])
- );
+ float v = hb_clamp (font->design_coords[i], info.min_value, info.max_value);
+
+ CFNumberRef tag_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag);
+ CFNumberRef value_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &v);
+ CFDictionarySetValue (variations, tag_number, value_number);
+ CFRelease (tag_number);
+ CFRelease (value_number);
}
CFDictionaryRef attributes =
@@ -379,37 +382,6 @@ _hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
CFRelease ((CTFontRef) data);
}
-static const hb_coretext_font_data_t *
-hb_coretext_font_data_sync (hb_font_t *font)
-{
-retry:
- const hb_coretext_font_data_t *data = font->data.coretext;
- if (unlikely (!data)) return nullptr;
-
- if (fabs (CTFontGetSize ((CTFontRef) data) - (CGFloat) font->ptem) > (CGFloat) .5)
- {
- /* XXX-MT-bug
- * Note that evaluating condition above can be dangerous if another thread
- * got here first and destructed data. That's, as always, bad use pattern.
- * If you modify the font (change font size), other threads must not be
- * using it at the same time. However, since this check is delayed to
- * when one actually tries to shape something, this is a XXX race condition
- * (and the only one we have that I know of) right now. Ie. you modify the
- * font size in one thread, then (supposedly safely) try to use it from two
- * or more threads and BOOM! I'm not sure how to fix this. We want RCU.
- */
-
- /* Drop and recreate. */
- /* If someone dropped it in the mean time, throw it away and don't touch it.
- * Otherwise, destruct it. */
- if (likely (font->data.coretext.cmpexch (const_cast<hb_coretext_font_data_t *> (data), nullptr)))
- _hb_coretext_shaper_font_data_destroy (const_cast<hb_coretext_font_data_t *> (data));
- else
- goto retry;
- }
- return font->data.coretext;
-}
-
/**
* hb_coretext_font_create:
* @ct_font: The CTFontRef to work upon
@@ -455,8 +427,8 @@ hb_coretext_font_create (CTFontRef ct_font)
CTFontRef
hb_coretext_font_get_ct_font (hb_font_t *font)
{
- const hb_coretext_font_data_t *data = hb_coretext_font_data_sync (font);
- return data ? (CTFontRef) data : nullptr;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
+ return ct_font ? (CTFontRef) ct_font : nullptr;
}
@@ -516,7 +488,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
{
hb_face_t *face = font->face;
CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
- CTFontRef ct_font = (CTFontRef) hb_coretext_font_data_sync (font);
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
@@ -539,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;
/*
@@ -679,7 +650,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
} else {
active_feature_t *feature = active_features.lsearch (event->feature);
if (feature)
- active_features.remove (feature - active_features.arrayZ);
+ active_features.remove_ordered (feature - active_features.arrayZ);
}
}
}
@@ -1106,7 +1077,8 @@ resize_and_retry:
advance = positions[j + 1].x - positions[j].x;
else /* last glyph */
advance = run_advance - (positions[j].x - positions[0].x);
- info->mask = round (advance * x_mult);
+ /* int cast necessary to pass through negative values. */
+ info->mask = (int) round (advance * x_mult);
info->var1.i32 = x_offset;
info->var2.i32 = round (positions[j].y * y_mult);
info++;
@@ -1122,7 +1094,8 @@ resize_and_retry:
advance = positions[j + 1].y - positions[j].y;
else /* last glyph */
advance = run_advance - (positions[j].y - positions[0].y);
- info->mask = round (advance * y_mult);
+ /* int cast necessary to pass through negative values. */
+ info->mask = (int) round (advance * y_mult);
info->var1.i32 = round (positions[j].x * x_mult);
info->var2.i32 = y_offset;
info++;
@@ -1151,7 +1124,7 @@ resize_and_retry:
pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32;
- info++, pos++;
+ info++; pos++;
}
else
for (unsigned int i = 0; i < count; i++)
@@ -1160,7 +1133,7 @@ resize_and_retry:
pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32;
- info++, pos++;
+ info++; pos++;
}
/* Fix up clusters so that we never return out-of-order indices;
@@ -1173,7 +1146,8 @@ resize_and_retry:
* This does *not* mean we'll form the same clusters as Uniscribe
* or the native OT backend, only that the cluster indices will be
* monotonic in the output buffer. */
- if (count > 1 && (status_or & kCTRunStatusNonMonotonic))
+ if (count > 1 && (status_or & kCTRunStatusNonMonotonic) &&
+ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
{
hb_glyph_info_t *info = buffer->info;
if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
@@ -1197,6 +1171,10 @@ resize_and_retry:
}
}
+ /* TODO: Sometimes the above positioning code generates negative
+ * advance values. Fix them up. Example, with NotoNastaliqUrdu
+ * font and sequence ابهد. */
+
buffer->clear_glyph_flags ();
buffer->unsafe_to_break ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cplusplus.hh b/src/3rdparty/harfbuzz-ng/src/hb-cplusplus.hh
new file mode 100644
index 0000000000..531ef1b7c8
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-cplusplus.hh
@@ -0,0 +1,223 @@
+/*
+ * 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_CPLUSPLUS_HH
+#define HB_CPLUSPLUS_HH
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+HB_END_DECLS
+
+#ifdef __cplusplus
+
+#include <functional>
+#include <utility>
+
+#if 0
+#if !(__cplusplus >= 201103L)
+#error "HarfBuzz C++ helpers require C++11"
+#endif
+#endif
+
+namespace hb {
+
+
+template <typename T>
+struct vtable;
+
+template <typename T>
+struct shared_ptr
+{
+ using element_type = T;
+
+ using v = vtable<T>;
+
+ explicit shared_ptr (T *p = nullptr) : p (p) {}
+ shared_ptr (const shared_ptr &o) : p (v::reference (o.p)) {}
+ shared_ptr (shared_ptr &&o) : p (o.p) { o.p = nullptr; }
+ shared_ptr& operator = (const shared_ptr &o) { if (p != o.p) { destroy (); p = o.p; reference (); } return *this; }
+ shared_ptr& operator = (shared_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
+ ~shared_ptr () { v::destroy (p); p = nullptr; }
+
+ T* get() const { return p; }
+
+ void swap (shared_ptr &o) { std::swap (p, o.p); }
+ friend void swap (shared_ptr &a, shared_ptr &b) { std::swap (a.p, b.p); }
+
+ operator T * () const { return p; }
+ T& operator * () const { return *get (); }
+ T* operator -> () const { return get (); }
+ operator bool () const { return p; }
+ bool operator == (const shared_ptr &o) const { return p == o.p; }
+ bool operator != (const shared_ptr &o) const { return p != o.p; }
+
+ static T* get_empty() { return v::get_empty (); }
+ T* reference() { return v::reference (p); }
+ void destroy() { v::destroy (p); }
+ void set_user_data (hb_user_data_key_t *key,
+ void *value,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace) { v::set_user_data (p, key, value, destroy, replace); }
+ void * get_user_data (hb_user_data_key_t *key) { return v::get_user_data (p, key); }
+
+ private:
+ T *p;
+};
+
+template<typename T> struct is_shared_ptr : std::false_type {};
+template<typename T> struct is_shared_ptr<shared_ptr<T>> : std::true_type {};
+
+template <typename T>
+struct unique_ptr
+{
+ using element_type = T;
+
+ using v = vtable<T>;
+
+ explicit unique_ptr (T *p = nullptr) : p (p) {}
+ unique_ptr (const unique_ptr &o) = delete;
+ unique_ptr (unique_ptr &&o) : p (o.p) { o.p = nullptr; }
+ unique_ptr& operator = (const unique_ptr &o) = delete;
+ unique_ptr& operator = (unique_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
+ ~unique_ptr () { v::destroy (p); p = nullptr; }
+
+ T* get() const { return p; }
+ T* release () { T* v = p; p = nullptr; return v; }
+
+ void swap (unique_ptr &o) { std::swap (p, o.p); }
+ friend void swap (unique_ptr &a, unique_ptr &b) { std::swap (a.p, b.p); }
+
+ operator T * () const { return p; }
+ T& operator * () const { return *get (); }
+ T* operator -> () const { return get (); }
+ operator bool () { return p; }
+
+ private:
+ T *p;
+};
+
+template<typename T> struct is_unique_ptr : std::false_type {};
+template<typename T> struct is_unique_ptr<unique_ptr<T>> : std::true_type {};
+
+template <typename T,
+ T * (*_get_empty) (void),
+ T * (*_reference) (T *),
+ void (*_destroy) (T *),
+ hb_bool_t (*_set_user_data) (T *,
+ hb_user_data_key_t *,
+ void *,
+ hb_destroy_func_t,
+ hb_bool_t),
+ void * (*_get_user_data) (const T *,
+ hb_user_data_key_t *)>
+struct vtable_t
+{
+ static constexpr auto get_empty = _get_empty;
+ static constexpr auto reference = _reference;
+ static constexpr auto destroy = _destroy;
+ static constexpr auto set_user_data = _set_user_data;
+ static constexpr auto get_user_data = _get_user_data;
+};
+
+#define HB_DEFINE_VTABLE(name) \
+ template<> \
+ struct vtable<hb_##name##_t> \
+ : vtable_t<hb_##name##_t, \
+ &hb_##name##_get_empty, \
+ &hb_##name##_reference, \
+ &hb_##name##_destroy, \
+ &hb_##name##_set_user_data, \
+ &hb_##name##_get_user_data> {}
+
+HB_DEFINE_VTABLE (buffer);
+HB_DEFINE_VTABLE (blob);
+HB_DEFINE_VTABLE (face);
+HB_DEFINE_VTABLE (font);
+HB_DEFINE_VTABLE (font_funcs);
+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
+
+
+#ifdef HB_SUBSET_H
+
+#define HB_DEFINE_VTABLE(name) \
+ template<> \
+ struct vtable<hb_##name##_t> \
+ : vtable_t<hb_##name##_t, \
+ nullptr, \
+ &hb_##name##_reference, \
+ &hb_##name##_destroy, \
+ &hb_##name##_set_user_data, \
+ &hb_##name##_get_user_data> {}
+
+
+HB_DEFINE_VTABLE (subset_input);
+HB_DEFINE_VTABLE (subset_plan);
+
+#undef HB_DEFINE_VTABLE
+
+#endif
+
+
+} // namespace hb
+
+/* Workaround for GCC < 7, see:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480
+ * https://stackoverflow.com/a/25594741 */
+namespace std {
+
+
+template<typename T>
+struct hash<hb::shared_ptr<T>>
+{
+ std::size_t operator()(const hb::shared_ptr<T>& v) const noexcept
+ {
+ std::size_t h = std::hash<decltype (v.get ())>{}(v.get ());
+ return h;
+ }
+};
+
+template<typename T>
+struct hash<hb::unique_ptr<T>>
+{
+ std::size_t operator()(const hb::unique_ptr<T>& v) const noexcept
+ {
+ std::size_t h = std::hash<decltype (v.get ())>{}(v.get ());
+ return h;
+ }
+};
+
+
+} // namespace std
+
+#endif /* __cplusplus */
+
+#endif /* HB_CPLUSPLUS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
index 3ac7440e80..efab374646 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh
@@ -67,12 +67,12 @@ hb_options ()
#endif
/* Make a local copy, so we can access bitfield threadsafely. */
hb_options_union_t u;
- u.i = _hb_options.get_relaxed ();
+ u.i = _hb_options;
if (unlikely (!u.i))
{
_hb_options_init ();
- u.i = _hb_options.get_relaxed ();
+ u.i = _hb_options;
}
return u.opts;
@@ -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,10 +454,15 @@ 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
+#ifndef HB_BUFFER_MESSAGE_MORE
+#define HB_BUFFER_MESSAGE_MORE (HB_DEBUG+1)
+#endif
+
+
#endif /* HB_DEBUG_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h
index a130d77f77..edacfd064c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h
@@ -93,7 +93,7 @@ HB_BEGIN_DECLS
* This method should retrieve the glyph ID for a specified Unicode code point
* font, with an optional variation selector.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
* Deprecated: 1.2.3
*
**/
@@ -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 f177ff31c0..42764a244b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
@@ -43,6 +43,14 @@
* Functions for using HarfBuzz with DirectWrite fonts.
**/
+/* Declare object creator for dynamic support of DWRITE */
+typedef HRESULT (WINAPI *t_DWriteCreateFactory)(
+ DWRITE_FACTORY_TYPE factoryType,
+ REFIID iid,
+ IUnknown **factory
+);
+
+
/*
* DirectWrite font stream helpers
*/
@@ -137,6 +145,7 @@ public:
struct hb_directwrite_face_data_t
{
+ HMODULE dwrite_dll;
IDWriteFactory *dwriteFactory;
IDWriteFontFile *fontFile;
DWriteFontFileStream *fontFileStream;
@@ -158,12 +167,33 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
return nullptr; \
} HB_STMT_END
+ data->dwrite_dll = LoadLibrary (TEXT ("DWRITE"));
+ if (unlikely (!data->dwrite_dll))
+ FAIL ("Cannot find DWrite.DLL");
+
+ t_DWriteCreateFactory p_DWriteCreateFactory;
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
+
+ p_DWriteCreateFactory = (t_DWriteCreateFactory)
+ GetProcAddress (data->dwrite_dll, "DWriteCreateFactory");
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+ if (unlikely (!p_DWriteCreateFactory))
+ FAIL ("Cannot find DWriteCreateFactory().");
+
HRESULT hr;
// TODO: factory and fontFileLoader should be cached separately
IDWriteFactory* dwriteFactory;
- hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
- (IUnknown**) &dwriteFactory);
+ hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
+ (IUnknown**) &dwriteFactory);
if (unlikely (hr != S_OK))
FAIL ("Failed to run DWriteCreateFactory().");
@@ -221,14 +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);
- if (data)
- delete data;
+ delete data->fontFileLoader;
+ delete data->fontFileStream;
+ hb_blob_destroy (data->faceBlob);
+ if (data->dwrite_dll)
+ FreeLibrary (data->dwrite_dll);
+ delete data;
}
@@ -241,17 +269,12 @@ struct hb_directwrite_font_data_t {};
hb_directwrite_font_data_t *
_hb_directwrite_shaper_font_data_create (hb_font_t *font)
{
- hb_directwrite_font_data_t *data = new hb_directwrite_font_data_t;
- if (unlikely (!data))
- return nullptr;
-
- return data;
+ return (hb_directwrite_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
{
- delete data;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-draw.cc b/src/3rdparty/harfbuzz-ng/src/hb-draw.cc
index b31019b07e..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
@@ -56,12 +58,14 @@ hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
+#define HB_ONE_THIRD 0.33333333f
dfuncs->emit_cubic_to (draw_data, *st,
- (st->current_x + 2.f * control_x) / 3.f,
- (st->current_y + 2.f * control_y) / 3.f,
- (to_x + 2.f * control_x) / 3.f,
- (to_y + 2.f * control_y) / 3.f,
+ (st->current_x + 2.f * control_x) * HB_ONE_THIRD,
+ (st->current_y + 2.f * control_y) * HB_ONE_THIRD,
+ (to_x + 2.f * control_x) * HB_ONE_THIRD,
+ (to_y + 2.f * control_y) * HB_ONE_THIRD,
to_x, to_y);
+#undef HB_ONE_THIRD
}
static void
@@ -78,6 +82,56 @@ hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UN
void *user_data HB_UNUSED) {}
+static bool
+_hb_draw_funcs_set_preamble (hb_draw_funcs_t *dfuncs,
+ bool func_is_null,
+ void **user_data,
+ hb_destroy_func_t *destroy)
+{
+ if (hb_object_is_immutable (dfuncs))
+ {
+ 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_draw_funcs_set_middle (hb_draw_funcs_t *dfuncs,
+ void *user_data,
+ hb_destroy_func_t destroy)
+{
+ if (user_data && !dfuncs->user_data)
+ {
+ dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data));
+ if (unlikely (!dfuncs->user_data))
+ goto fail;
+ }
+ if (destroy && !dfuncs->destroy)
+ {
+ dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy));
+ if (unlikely (!dfuncs->destroy))
+ goto fail;
+ }
+
+ return true;
+
+fail:
+ if (destroy)
+ (destroy) (user_data);
+ return false;
+}
+
#define HB_DRAW_FUNC_IMPLEMENT(name) \
\
void \
@@ -86,35 +140,38 @@ hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \
void *user_data, \
hb_destroy_func_t destroy) \
{ \
- if (hb_object_is_immutable (dfuncs)) \
- return; \
- \
- if (dfuncs->destroy.name) \
- dfuncs->destroy.name (dfuncs->user_data.name); \
+ if (!_hb_draw_funcs_set_preamble (dfuncs, !func, &user_data, &destroy))\
+ return; \
\
- if (func) { \
- dfuncs->func.name = func; \
- dfuncs->user_data.name = user_data; \
- dfuncs->destroy.name = destroy; \
- } else { \
- dfuncs->func.name = hb_draw_##name##_nil; \
- dfuncs->user_data.name = nullptr; \
- dfuncs->destroy.name = nullptr; \
- } \
+ if (dfuncs->destroy && dfuncs->destroy->name) \
+ dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \
+ \
+ if (!_hb_draw_funcs_set_middle (dfuncs, user_data, destroy)) \
+ return; \
+ \
+ if (func) \
+ dfuncs->func.name = func; \
+ else \
+ dfuncs->func.name = hb_draw_##name##_nil; \
+ \
+ if (dfuncs->user_data) \
+ dfuncs->user_data->name = user_data; \
+ if (dfuncs->destroy) \
+ dfuncs->destroy->name = destroy; \
}
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
/**
- * hb_draw_funcs_create: (Xconstructor)
+ * hb_draw_funcs_create:
*
* Creates a new draw callbacks object.
*
* Return value: (transfer full):
* A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
* reference count should be released with hb_draw_funcs_destroy when you are
- * done using the #hb_draw_funcs_t. This function never returns %NULL. If
+ * done using the #hb_draw_funcs_t. This function never returns `NULL`. If
* memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
* be returned.
*
@@ -143,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.
@@ -177,16 +250,64 @@ hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
{
if (!hb_object_destroy (dfuncs)) return;
+ if (dfuncs->destroy)
+ {
#define HB_DRAW_FUNC_IMPLEMENT(name) \
- if (dfuncs->destroy.name) dfuncs->destroy.name (dfuncs->user_data.name);
- HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+ if (dfuncs->destroy->name) dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name);
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
+ }
+ hb_free (dfuncs->destroy);
+ hb_free (dfuncs->user_data);
hb_free (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
*
@@ -209,7 +330,7 @@ hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
*
* Checks whether @dfuncs is immutable.
*
- * Return value: %true if @dfuncs is immutable, %false otherwise
+ * Return value: `true` if @dfuncs is immutable, `false` otherwise
*
* Since: 4.0.0
**/
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-draw.hh b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh
index 28bc9218e1..768f51a875 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-draw.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh
@@ -54,31 +54,31 @@ struct hb_draw_funcs_t
#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
- } user_data;
+ } *user_data;
struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
- } destroy;
+ } *destroy;
void emit_move_to (void *draw_data, hb_draw_state_t &st,
float to_x, float to_y)
{ func.move_to (this, draw_data, &st,
to_x, to_y,
- user_data.move_to); }
+ !user_data ? nullptr : user_data->move_to); }
void emit_line_to (void *draw_data, hb_draw_state_t &st,
float to_x, float to_y)
{ func.line_to (this, draw_data, &st,
to_x, to_y,
- user_data.line_to); }
+ !user_data ? nullptr : user_data->line_to); }
void emit_quadratic_to (void *draw_data, hb_draw_state_t &st,
float control_x, float control_y,
float to_x, float to_y)
{ func.quadratic_to (this, draw_data, &st,
control_x, control_y,
to_x, to_y,
- user_data.quadratic_to); }
+ !user_data ? nullptr : user_data->quadratic_to); }
void emit_cubic_to (void *draw_data, hb_draw_state_t &st,
float control1_x, float control1_y,
float control2_x, float control2_y,
@@ -87,10 +87,10 @@ struct hb_draw_funcs_t
control1_x, control1_y,
control2_x, control2_y,
to_x, to_y,
- user_data.cubic_to); }
+ !user_data ? nullptr : user_data->cubic_to); }
void emit_close_path (void *draw_data, hb_draw_state_t &st)
{ func.close_path (this, draw_data, &st,
- user_data.close_path); }
+ !user_data ? nullptr : user_data->close_path); }
void move_to (void *draw_data, hb_draw_state_t &st,
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 5365598636..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"
/**
@@ -132,7 +131,7 @@ hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
face->user_data = user_data;
face->destroy = destroy;
- face->num_glyphs.set_relaxed (-1);
+ face->num_glyphs = -1;
face->data.init0 (face);
face->table.init0 (face);
@@ -190,7 +189,7 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
}
/**
- * hb_face_create: (Xconstructor)
+ * hb_face_create:
* @blob: #hb_blob_t to work upon
* @index: The index of the face within @blob
*
@@ -288,6 +287,7 @@ hb_face_destroy (hb_face_t *face)
{
if (!hb_object_destroy (face)) return;
+#ifndef HB_NO_SHAPER
for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
{
hb_face_t::plan_node_t *next = node->next;
@@ -295,6 +295,7 @@ hb_face_destroy (hb_face_t *face)
hb_free (node);
node = next;
}
+#endif
face->data.fini ();
face->table.fini ();
@@ -315,7 +316,7 @@ hb_face_destroy (hb_face_t *face)
*
* Attaches a user-data key/data pair to the given face object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -371,7 +372,7 @@ hb_face_make_immutable (hb_face_t *face)
*
* Tests whether the given face object is immutable.
*
- * Return value: %true is @face is immutable, %false otherwise
+ * Return value: `true` is @face is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -470,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
@@ -479,14 +482,17 @@ hb_face_set_upem (hb_face_t *face,
if (hb_object_is_immutable (face))
return;
- face->upem.set_relaxed (upem);
+ face->upem = upem;
}
/**
* 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
*
@@ -505,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
@@ -514,7 +522,7 @@ hb_face_set_glyph_count (hb_face_t *face,
if (hb_object_is_immutable (face))
return;
- face->num_glyphs.set_relaxed (glyph_count);
+ face->num_glyphs = glyph_count;
}
/**
@@ -579,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.
@@ -593,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.
@@ -612,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.
@@ -627,163 +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 hb_face_builder_data_t
-{
- hb_hashmap_t<hb_tag_t, hb_blob_t *> tables;
-};
-
-static int compare_entries (const void* pa, const void* pb)
-{
- const auto& a = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pa;
- const auto& b = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pb;
-
- /* Order by blob size first (smallest to largest) and then table tag */
-
- if (a.second->length != b.second->length)
- return a.second->length < b.second->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 (hb_blob_t* b : data->tables.values())
- hb_blob_destroy (b);
-
- 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 (hb_blob_t* b : data->tables.values())
- face_length += hb_ceil_to_4 (hb_blob_get_length (b));
-
- 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, hb_blob_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());
-
- 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]);
-}
-
-
-/**
- * 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 (tag == HB_MAP_VALUE_INVALID)
- return false;
-
- if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
- return false;
-
- hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
-
- hb_blob_t* previous = data->tables.get (tag);
- if (!data->tables.set (tag, hb_blob_reference (blob)))
- {
- hb_blob_destroy (blob);
- return false;
- }
-
- hb_blob_destroy (previous);
- return true;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.h b/src/3rdparty/harfbuzz-ng/src/hb-face.h
index 6ef2f8b886..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);
@@ -171,6 +177,10 @@ hb_face_builder_add_table (hb_face_t *face,
hb_tag_t tag,
hb_blob_t *blob);
+HB_EXTERN void
+hb_face_builder_sort_tables (hb_face_t *face,
+ const hb_tag_t *tags);
+
HB_END_DECLS
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.hh b/src/3rdparty/harfbuzz-ng/src/hb-face.hh
index 765f272858..1bf0606e52 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-face.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-face.hh
@@ -65,7 +65,9 @@ struct hb_face_t
hb_shape_plan_t *shape_plan;
plan_node_t *next;
};
+#ifndef HB_NO_SHAPER
hb_atomic_ptr_t<plan_node_t> shape_plans;
+#endif
hb_blob_t *reference_table (hb_tag_t tag) const
{
@@ -83,7 +85,7 @@ struct hb_face_t
unsigned int get_upem () const
{
- unsigned int ret = upem.get_relaxed ();
+ unsigned int ret = upem;
if (unlikely (!ret))
{
return load_upem ();
@@ -93,7 +95,7 @@ struct hb_face_t
unsigned int get_num_glyphs () const
{
- unsigned int ret = num_glyphs.get_relaxed ();
+ unsigned int ret = num_glyphs;
if (unlikely (ret == UINT_MAX))
return load_num_glyphs ();
return ret;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc
index f8524ecc8e..c54ad8764b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc
@@ -75,16 +75,6 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *features HB_UNUSED,
unsigned int num_features HB_UNUSED)
{
- /* TODO
- *
- * - Apply fallback kern.
- * - Handle Variation Selectors?
- * - Apply normalization?
- *
- * This will make the fallback shaper into a dumb "TrueType"
- * shaper which many people unfortunately still request.
- */
-
hb_codepoint_t space;
bool has_space = (bool) font->get_nominal_glyph (' ', &space);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-font.cc
index db05f017a5..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"
@@ -71,7 +72,7 @@ hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return false;
}
@@ -96,7 +97,7 @@ hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return false;
}
@@ -409,7 +410,7 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return false;
}
@@ -503,22 +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;
-} hb_font_get_glyph_shape_default_adaptor_t;
+ float slant;
+} hb_font_draw_glyph_default_adaptor_t;
static void
hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
@@ -527,12 +540,13 @@ 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;
adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
- x_scale * to_x, y_scale * to_y);
+ x_scale * to_x + slant * to_y, y_scale * to_y);
}
static void
@@ -541,15 +555,16 @@ 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;
- st->current_x *= x_scale;
- st->current_y *= y_scale;
+ st->current_x = st->current_x * x_scale + st->current_y * slant;
+ st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
- x_scale * to_x, y_scale * to_y);
+ x_scale * to_x + slant * to_y, y_scale * to_y);
}
static void
@@ -559,16 +574,17 @@ 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;
- st->current_x *= x_scale;
- st->current_y *= y_scale;
+ st->current_x = st->current_x * x_scale + st->current_y * slant;
+ st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
- x_scale * control_x, y_scale * control_y,
- x_scale * to_x, y_scale * to_y);
+ x_scale * control_x + slant * control_y, y_scale * control_y,
+ x_scale * to_x + slant * to_y, y_scale * to_y);
}
static void
@@ -579,17 +595,18 @@ 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;
- st->current_x *= x_scale;
- st->current_y *= y_scale;
+ st->current_x = st->current_x * x_scale + st->current_y * slant;
+ st->current_y = st->current_y * y_scale;
adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
- x_scale * control1_x, y_scale * control1_y,
- x_scale * control2_x, y_scale * control2_y,
- x_scale * to_x, y_scale * to_y);
+ x_scale * control1_x + slant * control1_y, y_scale * control1_y,
+ x_scale * control2_x + slant * control2_y, y_scale * control2_y,
+ x_scale * to_x + slant * to_y, y_scale * to_y);
}
static void
@@ -597,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);
}
@@ -613,42 +630,59 @@ 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,
- (float) font->x_scale / (float) font->parent->x_scale,
- (float) font->y_scale / (float) font->parent->y_scale
+ font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
+ font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f,
+ font->parent->y_scale ? (font->slant - font->parent->slant) *
+ (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,
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
+ nullptr,
+ 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
}
@@ -658,19 +692,11 @@ DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
static const hb_font_funcs_t _hb_font_funcs_default = {
HB_OBJECT_HEADER_STATIC,
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
+ nullptr,
+ 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
}
@@ -679,7 +705,7 @@ static const hb_font_funcs_t _hb_font_funcs_default = {
/**
- * hb_font_funcs_create: (Xconstructor)
+ * hb_font_funcs_create:
*
* Creates a new #hb_font_funcs_t structure of font functions.
*
@@ -746,10 +772,16 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
{
if (!hb_object_destroy (ffuncs)) return;
-#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
- ffuncs->destroy.name (ffuncs->user_data.name);
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+ if (ffuncs->destroy)
+ {
+#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
+ }
+
+ hb_free (ffuncs->destroy);
+ hb_free (ffuncs->user_data);
hb_free (ffuncs);
}
@@ -764,7 +796,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
*
* Attaches a user-data key/data pair to the specified font-functions structure.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -791,8 +823,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
* Since: 0.9.2
**/
void *
-hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
- hb_user_data_key_t *key)
+hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key)
{
return hb_object_get_user_data (ffuncs, key);
}
@@ -821,7 +853,7 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
*
* Tests whether a font-functions structure is immutable.
*
- * Return value: %true if @ffuncs is immutable, %false otherwise
+ * Return value: `true` if @ffuncs is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -832,33 +864,82 @@ hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
}
-#define HB_FONT_FUNC_IMPLEMENT(name) \
+static bool
+_hb_font_funcs_set_preamble (hb_font_funcs_t *ffuncs,
+ bool func_is_null,
+ void **user_data,
+ hb_destroy_func_t *destroy)
+{
+ if (hb_object_is_immutable (ffuncs))
+ {
+ 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_font_funcs_set_middle (hb_font_funcs_t *ffuncs,
+ void *user_data,
+ hb_destroy_func_t destroy)
+{
+ if (user_data && !ffuncs->user_data)
+ {
+ ffuncs->user_data = (decltype (ffuncs->user_data)) hb_calloc (1, sizeof (*ffuncs->user_data));
+ if (unlikely (!ffuncs->user_data))
+ goto fail;
+ }
+ if (destroy && !ffuncs->destroy)
+ {
+ ffuncs->destroy = (decltype (ffuncs->destroy)) hb_calloc (1, sizeof (*ffuncs->destroy));
+ if (unlikely (!ffuncs->destroy))
+ goto fail;
+ }
+
+ return true;
+
+fail:
+ if (destroy)
+ (destroy) (user_data);
+ return false;
+}
+
+#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) \
{ \
- if (hb_object_is_immutable (ffuncs)) \
- { \
- if (destroy) \
- destroy (user_data); \
- return; \
- } \
+ if (!_hb_font_funcs_set_preamble (ffuncs, !func, &user_data, &destroy))\
+ return; \
\
- if (ffuncs->destroy.name) \
- ffuncs->destroy.name (ffuncs->user_data.name); \
+ if (ffuncs->destroy && ffuncs->destroy->name) \
+ ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name); \
+ \
+ if (!_hb_font_funcs_set_middle (ffuncs, user_data, destroy)) \
+ return; \
\
- if (func) { \
+ if (func) \
ffuncs->get.f.name = func; \
- ffuncs->user_data.name = user_data; \
- ffuncs->destroy.name = destroy; \
- } else { \
- ffuncs->get.f.name = hb_font_get_##name##_default; \
- ffuncs->user_data.name = nullptr; \
- ffuncs->destroy.name = nullptr; \
- } \
+ else \
+ ffuncs->get.f.name = hb_font_##get_##name##_default; \
+ \
+ if (ffuncs->user_data) \
+ ffuncs->user_data->name = user_data; \
+ if (ffuncs->destroy) \
+ ffuncs->destroy->name = destroy; \
}
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -887,7 +968,7 @@ hb_font_t::has_func (unsigned int i)
* Fetches the extents for a specified font, for horizontal
* text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.1.3
**/
@@ -906,7 +987,7 @@ hb_font_get_h_extents (hb_font_t *font,
* Fetches the extents for a specified font, for vertical
* text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.1.3
**/
@@ -930,7 +1011,7 @@ hb_font_get_v_extents (hb_font_t *font,
* If @variation_selector is 0, calls hb_font_get_nominal_glyph();
* otherwise calls hb_font_get_variation_glyph().
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -958,7 +1039,7 @@ hb_font_get_glyph (hb_font_t *font,
* for code points modified by variation selectors. For variation-selector
* support, user hb_font_get_variation_glyph() or use hb_font_get_glyph().
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.2.3
**/
@@ -980,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
*
@@ -1010,7 +1092,7 @@ hb_font_get_nominal_glyphs (hb_font_t *font,
* by the specified variation-selector code point, in the specified
* font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.2.3
**/
@@ -1120,7 +1202,7 @@ hb_font_get_glyph_v_advances (hb_font_t* font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for horizontal text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1143,7 +1225,7 @@ hb_font_get_glyph_h_origin (hb_font_t *font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for vertical text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1216,7 +1298,7 @@ hb_font_get_glyph_v_kerning (hb_font_t *font,
* Fetches the #hb_glyph_extents_t data for a glyph ID
* in the specified font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1239,7 +1321,7 @@ hb_font_get_glyph_extents (hb_font_t *font,
* Fetches the (x,y) coordinates of a specified contour-point index
* in the specified glyph, within the specified font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1262,7 +1344,10 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
*
* Fetches the glyph-name string for a glyph ID in the specified @font.
*
- * Return value: %true if data found, %false otherwise
+ * 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
**/
@@ -1286,7 +1371,7 @@ hb_font_get_glyph_name (hb_font_t *font,
*
* <note>Note: @len == -1 means the name string is null-terminated.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1307,17 +1392,71 @@ hb_font_get_glyph_from_name (hb_font_t *font,
* @draw_data: User data to pass to draw callbacks
*
* Fetches the glyph shape that corresponds to a glyph in the specified @font.
- * The shape is returned by way of calls to the callsbacks of the @dfuncs
+ * The shape is returned by way of calls to the callbacks of the @dfuncs
* 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 */
@@ -1521,7 +1660,7 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1550,7 +1689,7 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1578,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
@@ -1601,7 +1743,7 @@ hb_font_glyph_to_string (hb_font_t *font,
*
* <note>Note: @len == -1 means the string is null-terminated.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1623,13 +1765,23 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
{
HB_OBJECT_HEADER_STATIC,
+ 0, /* serial */
+ 0, /* serial_coords */
+
nullptr, /* parent */
const_cast<hb_face_t *> (&_hb_Null_hb_face_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 */
1<<16, /* y_mult */
@@ -1637,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 */
@@ -1654,6 +1807,7 @@ _hb_font_create (hb_face_t *face)
if (unlikely (!face))
face = hb_face_get_empty ();
+
if (!(font = hb_object_create<hb_font_t> ()))
return hb_font_get_empty ();
@@ -1662,14 +1816,17 @@ _hb_font_create (hb_face_t *face)
font->face = hb_face_reference (face);
font->klass = hb_font_funcs_get_empty ();
font->data.init0 (font);
- font->x_scale = font->y_scale = hb_face_get_upem (face);
+ 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;
}
/**
- * hb_font_create: (Xconstructor)
+ * hb_font_create:
* @face: a face.
*
* Constructs a new font object from the specified face.
@@ -1715,6 +1872,8 @@ _hb_font_adopt_var_coords (hb_font_t *font,
font->coords = coords;
font->design_coords = design_coords;
font->num_coords = coords_length;
+
+ font->mults_changed (); // Easiest to call this to drop cached data
}
/**
@@ -1743,8 +1902,10 @@ 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->mults_changed ();
font->x_ppem = parent->x_ppem;
font->y_ppem = parent->y_ppem;
font->ptem = parent->ptem;
@@ -1756,8 +1917,8 @@ hb_font_create_sub_font (hb_font_t *parent)
float *design_coords = (float *) hb_calloc (num_coords, sizeof (parent->design_coords[0]));
if (likely (coords && design_coords))
{
- memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
- memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0]));
+ hb_memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
+ hb_memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0]));
_hb_font_adopt_var_coords (font, coords, design_coords, num_coords);
}
else
@@ -1767,6 +1928,8 @@ hb_font_create_sub_font (hb_font_t *parent)
}
}
+ font->mults_changed ();
+
return font;
}
@@ -1841,7 +2004,7 @@ hb_font_destroy (hb_font_t *font)
*
* Attaches a user-data key/data pair to the specified font object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1852,6 +2015,9 @@ hb_font_set_user_data (hb_font_t *font,
hb_destroy_func_t destroy /* May be NULL. */,
hb_bool_t replace)
{
+ if (!hb_object_is_immutable (font))
+ font->serial++;
+
return hb_object_set_user_data (font, key, data, destroy, replace);
}
@@ -1868,7 +2034,7 @@ hb_font_set_user_data (hb_font_t *font,
* Since: 0.9.2
**/
void *
-hb_font_get_user_data (hb_font_t *font,
+hb_font_get_user_data (const hb_font_t *font,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (font, key);
@@ -1900,7 +2066,7 @@ hb_font_make_immutable (hb_font_t *font)
*
* Tests whether a font object is immutable.
*
- * Return value: %true if @font is immutable, %false otherwise
+ * Return value: `true` if @font is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1911,6 +2077,45 @@ hb_font_is_immutable (hb_font_t *font)
}
/**
+ * hb_font_get_serial:
+ * @font: #hb_font_t to work upon
+ *
+ * Returns the internal serial number of the font. The serial
+ * number is increased every time a setting on the font is
+ * changed, using a setter function.
+ *
+ * Return value: serial number
+ *
+ * Since: 4.4.0
+ **/
+unsigned int
+hb_font_get_serial (hb_font_t *font)
+{
+ return font->serial;
+}
+
+/**
+ * hb_font_changed:
+ * @font: #hb_font_t to work upon
+ *
+ * Notifies the @font that underlying font data has changed.
+ * This has the effect of increasing the serial as returned
+ * by hb_font_get_serial(), which invalidates internal caches.
+ *
+ * Since: 4.4.0
+ **/
+void
+hb_font_changed (hb_font_t *font)
+{
+ if (hb_object_is_immutable (font))
+ return;
+
+ font->serial++;
+
+ font->mults_changed ();
+}
+
+/**
* hb_font_set_parent:
* @font: #hb_font_t to work upon
* @parent: The parent font object to assign
@@ -1926,6 +2131,11 @@ hb_font_set_parent (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (parent == font->parent)
+ return;
+
+ font->serial++;
+
if (!parent)
parent = hb_font_get_empty ();
@@ -1968,6 +2178,11 @@ hb_font_set_face (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (face == font->face)
+ return;
+
+ font->serial++;
+
if (unlikely (!face))
face = hb_face_get_empty ();
@@ -2022,6 +2237,8 @@ hb_font_set_funcs (hb_font_t *font,
return;
}
+ font->serial++;
+
if (font->destroy)
font->destroy (font->user_data);
@@ -2059,6 +2276,8 @@ hb_font_set_funcs_data (hb_font_t *font,
return;
}
+ font->serial++;
+
if (font->destroy)
font->destroy (font->user_data);
@@ -2075,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
@@ -2085,6 +2329,11 @@ hb_font_set_scale (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (font->x_scale == x_scale && font->y_scale == y_scale)
+ return;
+
+ font->serial++;
+
font->x_scale = x_scale;
font->y_scale = y_scale;
font->mults_changed ();
@@ -2115,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
**/
@@ -2127,6 +2380,11 @@ hb_font_set_ppem (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
+ return;
+
+ font->serial++;
+
font->x_ppem = x_ppem;
font->y_ppem = y_ppem;
}
@@ -2169,6 +2427,11 @@ hb_font_set_ptem (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (font->ptem == ptem)
+ return;
+
+ font->serial++;
+
font->ptem = ptem;
}
@@ -2190,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.
@@ -2201,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>
@@ -2216,6 +2548,11 @@ hb_font_set_synthetic_slant (hb_font_t *font, float slant)
if (hb_object_is_immutable (font))
return;
+ if (font->slant == slant)
+ return;
+
+ font->serial++;
+
font->slant = slant;
font->mults_changed ();
}
@@ -2263,7 +2600,9 @@ hb_font_set_variations (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
- if (!variations_length)
+ font->serial_coords = ++font->serial;
+
+ if (!variations_length && font->instance_index == HB_FONT_NO_VAR_NAMED_INSTANCE)
{
hb_font_set_var_coords_normalized (font, nullptr, 0);
return;
@@ -2283,19 +2622,30 @@ hb_font_set_variations (hb_font_t *font,
return;
}
+ /* 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++)
{
const auto tag = variations[i].tag;
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);
}
@@ -2322,6 +2672,8 @@ hb_font_set_var_coords_design (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
@@ -2333,7 +2685,7 @@ hb_font_set_var_coords_design (hb_font_t *font,
}
if (coords_length)
- memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0]));
+ hb_memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0]));
hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
@@ -2344,26 +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;
- unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
-
- float *coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
- if (unlikely (coords_length && !coords))
+ if (font->instance_index == instance_index)
return;
- 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);
+ font->serial_coords = ++font->serial;
+
+ font->instance_index = instance_index;
+ hb_font_set_variations (font, nullptr, 0);
+}
+
+/**
+ * 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;
}
/**
@@ -2391,6 +2757,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;
@@ -2405,8 +2773,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
if (coords_length)
{
- memcpy (copy, coords, coords_length * sizeof (coords[0]));
- memcpy (unmapped, coords, coords_length * sizeof (coords[0]));
+ hb_memcpy (copy, coords, coords_length * sizeof (coords[0]));
+ hb_memcpy (unmapped, coords, coords_length * sizeof (coords[0]));
}
/* Best effort design coords simulation */
@@ -2596,15 +2964,27 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
return;
}
+ /* Since we pass it to two destroying functions. */
+ trampoline_reference (&trampoline->closure);
+
hb_font_funcs_set_nominal_glyph_func (ffuncs,
hb_font_get_nominal_glyph_trampoline,
trampoline,
trampoline_destroy);
- trampoline_reference (&trampoline->closure);
hb_font_funcs_set_variation_glyph_func (ffuncs,
hb_font_get_variation_glyph_trampoline,
trampoline,
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 9548857535..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
*/
@@ -86,8 +78,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
HB_EXTERN void *
-hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
- hb_user_data_key_t *key);
+hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key);
HB_EXTERN void
@@ -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 */
/**
@@ -198,7 +172,7 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
* This method should retrieve the nominal glyph ID for a specified Unicode code
* point. Glyph IDs must be returned in a #hb_codepoint_t output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data,
@@ -221,7 +195,7 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo
* followed by a specified Variation Selector code point. Glyph IDs must be
* returned in a #hb_codepoint_t output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data,
@@ -362,7 +336,7 @@ typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
* origin for a glyph. Each coordinate must be returned in an #hb_position_t
* output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
@@ -434,7 +408,7 @@ typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
* This method should retrieve the extents for a specified glyph. Extents must be
* returned in an #hb_glyph_extents output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
@@ -458,7 +432,7 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo
* specified contour point in a glyph. Each coordinate must be returned as
* an #hb_position_t output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data,
@@ -481,7 +455,7 @@ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, vo
* This method should retrieve the glyph name that corresponds to a
* glyph ID. The name should be returned in a string output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data,
@@ -503,7 +477,7 @@ typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_
* This method should retrieve the glyph ID that corresponds to a glyph-name
* string.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data,
@@ -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 */
@@ -993,7 +1053,7 @@ hb_font_set_user_data (hb_font_t *font,
HB_EXTERN void *
-hb_font_get_user_data (hb_font_t *font,
+hb_font_get_user_data (const hb_font_t *font,
hb_user_data_key_t *key);
HB_EXTERN void
@@ -1002,6 +1062,12 @@ hb_font_make_immutable (hb_font_t *font);
HB_EXTERN hb_bool_t
hb_font_is_immutable (hb_font_t *font);
+HB_EXTERN unsigned int
+hb_font_get_serial (hb_font_t *font);
+
+HB_EXTERN void
+hb_font_changed (hb_font_t *font);
+
HB_EXTERN void
hb_font_set_parent (hb_font_t *font,
hb_font_t *parent);
@@ -1064,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
@@ -1092,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 70311b4a85..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,26 +66,26 @@ 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;
+ } *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;
+ } *destroy;
/* 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
]) ();
@@ -104,14 +105,26 @@ DECLARE_NULL_INSTANCE (hb_font_funcs_t);
struct hb_font_t
{
hb_object_header_t header;
+ unsigned int serial;
+ unsigned int serial_coords;
hb_font_t *parent;
hb_face_t *face;
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;
int64_t y_mult;
@@ -121,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;
@@ -137,12 +151,12 @@ struct hb_font_t
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
- hb_position_t em_scalef_x (float v) { return em_scalef (v, x_scale); }
- hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
- float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
- float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
- float em_fscalef_x (float v) { return em_fscalef (v, x_scale); }
- float em_fscalef_y (float v) { return em_fscalef (v, y_scale); }
+ hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); }
+ hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
+ float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); }
+ float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); }
+ float em_fscalef_x (float v) { return em_fmultf (v, x_multf); }
+ float em_fscalef_y (float v) { return em_fmultf (v, y_multf); }
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
{ return em_mult (v, dir_mult (direction)); }
@@ -175,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 */
@@ -182,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 () \
{ \
@@ -202,17 +252,17 @@ struct hb_font_t
hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return klass->get.f.font_h_extents (this, user_data,
extents,
- klass->user_data.font_h_extents);
+ !klass->user_data ? nullptr : klass->user_data->font_h_extents);
}
hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return klass->get.f.font_v_extents (this, user_data,
extents,
- klass->user_data.font_v_extents);
+ !klass->user_data ? nullptr : klass->user_data->font_v_extents);
}
bool has_glyph (hb_codepoint_t unicode)
@@ -228,7 +278,7 @@ struct hb_font_t
*glyph = not_found;
return klass->get.f.nominal_glyph (this, user_data,
unicode, glyph,
- klass->user_data.nominal_glyph);
+ !klass->user_data ? nullptr : klass->user_data->nominal_glyph);
}
unsigned int get_nominal_glyphs (unsigned int count,
const hb_codepoint_t *first_unicode,
@@ -240,7 +290,7 @@ struct hb_font_t
count,
first_unicode, unicode_stride,
first_glyph, glyph_stride,
- klass->user_data.nominal_glyphs);
+ !klass->user_data ? nullptr : klass->user_data->nominal_glyphs);
}
hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
@@ -250,21 +300,21 @@ struct hb_font_t
*glyph = not_found;
return klass->get.f.variation_glyph (this, user_data,
unicode, variation_selector, glyph,
- klass->user_data.variation_glyph);
+ !klass->user_data ? nullptr : klass->user_data->variation_glyph);
}
hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
{
return klass->get.f.glyph_h_advance (this, user_data,
glyph,
- klass->user_data.glyph_h_advance);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
}
hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
{
return klass->get.f.glyph_v_advance (this, user_data,
glyph,
- klass->user_data.glyph_v_advance);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
}
void get_glyph_h_advances (unsigned int count,
@@ -277,7 +327,7 @@ struct hb_font_t
count,
first_glyph, glyph_stride,
first_advance, advance_stride,
- klass->user_data.glyph_h_advances);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
}
void get_glyph_v_advances (unsigned int count,
@@ -290,7 +340,7 @@ struct hb_font_t
count,
first_glyph, glyph_stride,
first_advance, advance_stride,
- klass->user_data.glyph_v_advances);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
}
hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
@@ -299,7 +349,7 @@ struct hb_font_t
*x = *y = 0;
return klass->get.f.glyph_h_origin (this, user_data,
glyph, x, y,
- klass->user_data.glyph_h_origin);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
}
hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
@@ -308,7 +358,7 @@ struct hb_font_t
*x = *y = 0;
return klass->get.f.glyph_v_origin (this, user_data,
glyph, x, y,
- klass->user_data.glyph_v_origin);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
}
hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
@@ -319,7 +369,7 @@ struct hb_font_t
#else
return klass->get.f.glyph_h_kerning (this, user_data,
left_glyph, right_glyph,
- klass->user_data.glyph_h_kerning);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning);
#endif
}
@@ -331,18 +381,18 @@ struct hb_font_t
#else
return klass->get.f.glyph_v_kerning (this, user_data,
top_glyph, bottom_glyph,
- klass->user_data.glyph_v_kerning);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning);
#endif
}
hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
hb_glyph_extents_t *extents)
{
- memset (extents, 0, sizeof (*extents));
+ hb_memset (extents, 0, sizeof (*extents));
return klass->get.f.glyph_extents (this, user_data,
glyph,
extents,
- klass->user_data.glyph_extents);
+ !klass->user_data ? nullptr : klass->user_data->glyph_extents);
}
hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
@@ -352,7 +402,7 @@ struct hb_font_t
return klass->get.f.glyph_contour_point (this, user_data,
glyph, point_index,
x, y,
- klass->user_data.glyph_contour_point);
+ !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
}
hb_bool_t get_glyph_name (hb_codepoint_t glyph,
@@ -362,7 +412,7 @@ struct hb_font_t
return klass->get.f.glyph_name (this, user_data,
glyph,
name, size,
- klass->user_data.glyph_name);
+ !klass->user_data ? nullptr : klass->user_data->glyph_name);
}
hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
@@ -373,18 +423,29 @@ struct hb_font_t
return klass->get.f.glyph_from_name (this, user_data,
name, len,
glyph,
- klass->user_data.glyph_from_name);
+ !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.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 */
@@ -444,7 +505,6 @@ struct hb_font_t
{
*x = get_glyph_h_advance (glyph) / 2;
- /* TODO cache this somehow?! */
hb_font_extents_t extents;
get_h_extents_with_fallback (&extents);
*y = extents.ascender;
@@ -628,20 +688,31 @@ struct hb_font_t
void mults_changed ()
{
- signed upem = face->get_upem ();
- x_mult = ((int64_t) x_scale << 16) / upem;
- y_mult = ((int64_t) y_scale << 16) / upem;
+ 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 ();
}
hb_position_t em_mult (int16_t v, int64_t mult)
{ return (hb_position_t) ((v * mult + 32768) >> 16); }
- hb_position_t em_scalef (float v, int scale)
- { return (hb_position_t) roundf (em_fscalef (v, scale)); }
- float em_fscalef (float v, int scale)
- { return v * scale / face->get_upem (); }
- float em_fscale (int16_t v, int scale)
- { return (float) v * scale / face->get_upem (); }
+ hb_position_t em_multf (float v, float mult)
+ { return (hb_position_t) roundf (em_fmultf (v, mult)); }
+ float em_fmultf (float v, float mult)
+ { return v * mult; }
+ float em_fmult (int16_t v, float mult)
+ { return (float) v * mult; }
};
DECLARE_NULL_INSTANCE (hb_font_t);
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 0cfbb22e31..4bc10e0620 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc
@@ -33,15 +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
/**
@@ -78,16 +85,19 @@
*/
+using hb_ft_advance_cache_t = hb_cache_t<16, 8, 8, false>;
+
struct hb_ft_font_t
{
- mutable hb_mutex_t lock;
- FT_Face ft_face;
int load_flags;
bool symbol; /* Whether selected cmap is symbol cmap. */
bool unref; /* Whether to destroy ft_face when done. */
+ bool transform; /* Whether to apply FT_Face's transform. */
- mutable int cached_x_scale;
- mutable hb_advance_cache_t advance_cache;
+ mutable hb_mutex_t lock; /* Protects members below. */
+ FT_Face ft_face;
+ mutable unsigned cached_serial;
+ mutable hb_ft_advance_cache_t advance_cache;
};
static hb_ft_font_t *
@@ -103,7 +113,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
- ft_font->cached_x_scale = 0;
+ ft_font->cached_serial = (unsigned) -1;
ft_font->advance_cache.init ();
return ft_font;
@@ -120,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);
@@ -130,6 +138,85 @@ _hb_ft_font_destroy (void *data)
hb_free (ft_font);
}
+
+/* hb_font changed, update FT_Face. */
+static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face)
+{
+ hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
+
+ float x_mult = 1.f, y_mult = 1.f;
+
+ if (font->x_scale < 0) x_mult = -x_mult;
+ if (font->y_scale < 0) y_mult = -y_mult;
+
+ if (FT_Set_Char_Size (ft_face,
+ abs (font->x_scale), abs (font->y_scale),
+ 0, 0
+#if 0
+ font->x_ppem * 72 * 64 / font->x_scale,
+ font->y_ppem * 72 * 64 / font->y_scale
+#endif
+ ) && ft_face->num_fixed_sizes)
+ {
+#ifdef HAVE_FT_GET_TRANSFORM
+ /* Bitmap font, eg. bitmap color emoji. */
+ /* 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);
+
+ /* This contains the sign that was previously in x_mult/y_mult. */
+ x_mult = (float) font->x_scale / x_scale;
+ y_mult = (float) font->y_scale / y_scale;
+#endif
+ }
+ else
+ { /* Shrug */ }
+
+
+ if (x_mult != 1.f || y_mult != 1.f)
+ {
+ FT_Matrix matrix = { (int) roundf (x_mult * (1<<16)), 0,
+ 0, (int) roundf (y_mult * (1<<16))};
+ FT_Set_Transform (ft_face, &matrix, nullptr);
+ ft_font->transform = true;
+ }
+
+#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
+ unsigned int num_coords;
+ const float *coords = hb_font_get_var_coords_design (font, &num_coords);
+ if (num_coords)
+ {
+ FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
+ if (ft_coords)
+ {
+ for (unsigned int i = 0; i < num_coords; i++)
+ ft_coords[i] = coords[i] * 65536.f;
+ FT_Set_Var_Design_Coordinates (ft_face, num_coords, ft_coords);
+ hb_free (ft_coords);
+ }
+ }
+#endif
+}
+
+/* Check if hb_font changed, update FT_Face. */
+static inline bool
+_hb_ft_hb_font_check_changed (hb_font_t *font,
+ const hb_ft_font_t *ft_font)
+{
+ if (font->serial != ft_font->cached_serial)
+ {
+ _hb_ft_hb_font_changed (font, ft_font->ft_face);
+ ft_font->advance_cache.clear ();
+ ft_font->cached_serial = font->serial;
+ return true;
+ }
+ return false;
+}
+
+
/**
* hb_ft_font_set_load_flags:
* @font: #hb_font_t to work upon
@@ -140,6 +227,9 @@ _hb_ft_font_destroy (void *data)
* 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
@@ -165,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
**/
@@ -181,13 +274,16 @@ hb_ft_font_get_load_flags (hb_font_t *font)
}
/**
- * hb_ft_font_get_face:
+ * hb_ft_font_get_face: (skip)
* @font: #hb_font_t to work upon
*
* Fetches the FT_Face associated with the specified #hb_font_t
* font object.
*
- * Return value: (nullable): the FT_Face found or %NULL
+ * 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
**/
@@ -203,13 +299,18 @@ hb_ft_font_get_face (hb_font_t *font)
}
/**
- * hb_ft_font_lock_face:
+ * 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.
*
- * Return value: (nullable): the FT_Face associated with @font or %NULL
+ * 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
**/
FT_Face
@@ -226,7 +327,7 @@ hb_ft_font_lock_face (hb_font_t *font)
}
/**
- * hb_ft_font_unlock_face:
+ * hb_ft_font_unlock_face: (skip)
* @font: #hb_font_t to work upon
*
* Releases an FT_Face previously obtained with hb_ft_font_lock_face().
@@ -246,7 +347,7 @@ hb_ft_font_unlock_face (hb_font_t *font)
static hb_bool_t
-hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
+hb_ft_get_nominal_glyph (hb_font_t *font,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
@@ -258,14 +359,29 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
if (unlikely (!g))
{
- if (unlikely (ft_font->symbol) && unicode <= 0x00FFu)
+ if (unlikely (ft_font->symbol))
{
- /* For symbol-encoded OpenType fonts, we duplicate the
- * U+F000..F0FF range at U+0000..U+00FF. That's what
- * Windows seems to do, and that's hinted about at:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
- * under "Non-Standard (Symbol) Fonts". */
- g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
+ switch ((unsigned) font->face->table.OS2->get_font_page ()) {
+ case OT::OS2::font_page_t::FONT_PAGE_NONE:
+ if (unicode <= 0x00FFu)
+ /* For symbol-encoded OpenType fonts, we duplicate the
+ * U+F000..F0FF range at U+0000..U+00FF. That's what
+ * Windows seems to do, and that's hinted about at:
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
+ * under "Non-Standard (Symbol) Fonts". */
+ g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
+ break;
+#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK
+ case OT::OS2::font_page_t::FONT_PAGE_SIMP_ARABIC:
+ g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_simp_map (unicode));
+ break;
+ case OT::OS2::font_page_t::FONT_PAGE_TRAD_ARABIC:
+ g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_trad_map (unicode));
+ break;
+#endif
+ default:
+ break;
+ }
if (!g)
return false;
}
@@ -332,15 +448,23 @@ 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;
- int mult = font->x_scale < 0 ? -1 : +1;
-
- if (font->x_scale != ft_font->cached_x_scale)
+ float x_mult;
+#ifdef HAVE_FT_GET_TRANSFORM
+ if (ft_font->transform)
{
- ft_font->advance_cache.clear ();
- ft_font->cached_x_scale = font->x_scale;
+ 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
+ {
+ x_mult = font->x_scale < 0 ? -1 : +1;
}
for (unsigned int i = 0; i < count; i++)
@@ -354,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 = (v * 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
@@ -373,17 +513,31 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Fixed v;
+ float y_mult;
+#ifdef HAVE_FT_GET_TRANSFORM
+ if (ft_font->transform)
+ {
+ 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
+ {
+ y_mult = font->y_scale < 0 ? -1 : +1;
+ }
if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
return 0;
- if (font->y_scale < 0)
- v = -v;
+ v = (int) (y_mult * v);
/* 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
@@ -399,6 +553,23 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
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;
+ float x_mult, y_mult;
+#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
+ {
+ x_mult = font->x_scale < 0 ? -1 : +1;
+ y_mult = font->y_scale < 0 ? -1 : +1;
+ }
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
@@ -408,10 +579,8 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
*x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX;
*y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
- if (font->x_scale < 0)
- *x = -*x;
- if (font->y_scale < 0)
- *y = -*y;
+ *x = (hb_position_t) (x_mult * *x);
+ *y = (hb_position_t) (y_mult * *y);
return true;
}
@@ -426,6 +595,7 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ hb_lock_t lock (ft_font->lock);
FT_Vector kerningv;
FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
@@ -446,24 +616,63 @@ hb_ft_get_glyph_extents (hb_font_t *font,
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;
+ 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
+ {
+ x_mult = font->x_scale < 0 ? -1 : +1;
+ y_mult = font->y_scale < 0 ? -1 : +1;
+ }
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
- extents->x_bearing = ft_face->glyph->metrics.horiBearingX;
- extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
- extents->width = ft_face->glyph->metrics.width;
- extents->height = -ft_face->glyph->metrics.height;
- if (font->x_scale < 0)
+ /* 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)
{
- extents->x_bearing = -extents->x_bearing;
- extents->width = -extents->width;
+ x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
+ x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
}
- if (font->y_scale < 0)
+
+ 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)
{
- extents->y_bearing = -extents->y_bearing;
- extents->height = -extents->height;
+ /* 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;
}
@@ -556,15 +765,39 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
- metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
- metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
- metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
- if (font->y_scale < 0)
+ float y_mult;
+#ifdef HAVE_FT_GET_TRANSFORM
+ if (ft_font->transform)
{
- metrics->ascender = -metrics->ascender;
- metrics->descender = -metrics->descender;
- metrics->line_gap = -metrics->line_gap;
+ 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
+ {
+ y_mult = font->y_scale < 0 ? -1 : +1;
+ }
+
+ if (ft_face->units_per_EM != 0)
+ {
+ metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
+ metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
+ metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
+ }
+ else
+ {
+ /* Bitmap-only font, eg. color bitmap font. */
+ metrics->ascender = ft_face->size->metrics.ascender;
+ metrics->descender = ft_face->size->metrics.descender;
+ metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender);
+ }
+
+ 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);
+
return true;
}
@@ -572,16 +805,18 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
static int
_hb_ft_move_to (const FT_Vector *to,
- hb_draw_session_t *drawing)
+ void *arg)
{
+ hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
drawing->move_to (to->x, to->y);
return FT_Err_Ok;
}
static int
_hb_ft_line_to (const FT_Vector *to,
- hb_draw_session_t *drawing)
+ void *arg)
{
+ hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
drawing->line_to (to->x, to->y);
return FT_Err_Ok;
}
@@ -589,8 +824,9 @@ _hb_ft_line_to (const FT_Vector *to,
static int
_hb_ft_conic_to (const FT_Vector *control,
const FT_Vector *to,
- hb_draw_session_t *drawing)
+ void *arg)
{
+ hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
drawing->quadratic_to (control->x, control->y,
to->x, to->y);
return FT_Err_Ok;
@@ -600,8 +836,9 @@ static int
_hb_ft_cubic_to (const FT_Vector *control1,
const FT_Vector *control2,
const FT_Vector *to,
- hb_draw_session_t *drawing)
+ void *arg)
{
+ hb_draw_session_t *drawing = (hb_draw_session_t *) arg;
drawing->cubic_to (control1->x, control1->y,
control2->x, control2->y,
to->x, to->y);
@@ -609,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);
@@ -627,22 +864,139 @@ hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
return;
const FT_Outline_Funcs outline_funcs = {
- (FT_Outline_MoveToFunc) _hb_ft_move_to,
- (FT_Outline_LineToFunc) _hb_ft_line_to,
- (FT_Outline_ConicToFunc) _hb_ft_conic_to,
- (FT_Outline_CubicToFunc) _hb_ft_cubic_to,
+ _hb_ft_move_to,
+ _hb_ft_line_to,
+ _hb_ft_conic_to,
+ _hb_ft_cubic_to,
0, /* shift */
0, /* delta */
};
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 ();
@@ -676,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);
@@ -751,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()
@@ -795,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
@@ -815,8 +1183,9 @@ hb_ft_face_create_referenced (FT_Face ft_face)
}
static void
-hb_ft_face_finalize (FT_Face ft_face)
+hb_ft_face_finalize (void *arg)
{
+ FT_Face ft_face = (FT_Face) arg;
hb_face_destroy ((hb_face_t *) ft_face->generic.data);
}
@@ -826,6 +1195,10 @@ hb_ft_face_finalize (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 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
@@ -848,7 +1221,7 @@ hb_ft_face_create_cached (FT_Face ft_face)
ft_face->generic.finalizer (ft_face);
ft_face->generic.data = hb_ft_face_create (ft_face, nullptr);
- ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
+ ft_face->generic.finalizer = hb_ft_face_finalize;
}
return hb_face_reference ((hb_face_t *) ft_face->generic.data);
@@ -961,6 +1334,34 @@ hb_ft_font_changed (hb_font_t *font)
#endif
}
#endif
+
+ ft_font->advance_cache.clear ();
+ ft_font->cached_serial = font->serial;
+}
+
+/**
+ * hb_ft_hb_font_changed:
+ * @font: #hb_font_t to work upon
+ *
+ * Refreshes the state of the underlying FT_Face of @font when the hb_font_t
+ * @font has changed.
+ * This function should be called after changing the size or
+ * variation-axis settings on the @font.
+ * This call is fast if nothing has changed on @font.
+ *
+ * Return value: true if changed, false otherwise
+ *
+ * Since: 4.4.0
+ **/
+hb_bool_t
+hb_ft_hb_font_changed (hb_font_t *font)
+{
+ if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+ return false;
+
+ hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
+
+ return _hb_ft_hb_font_check_changed (font, ft_font);
}
/**
@@ -1029,8 +1430,9 @@ get_ft_library ()
}
static void
-_release_blob (FT_Face ft_face)
+_release_blob (void *arg)
{
+ FT_Face ft_face = (FT_Face) arg;
hb_blob_destroy ((hb_blob_t *) ft_face->generic.data);
}
@@ -1047,10 +1449,14 @@ _release_blob (FT_Face ft_face)
* 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>
*
@@ -1081,42 +1487,14 @@ hb_ft_font_set_funcs (hb_font_t *font)
if (FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL))
FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
- FT_Set_Char_Size (ft_face,
- abs (font->x_scale), abs (font->y_scale),
- 0, 0);
-#if 0
- font->x_ppem * 72 * 64 / font->x_scale,
- font->y_ppem * 72 * 64 / font->y_scale);
-#endif
- if (font->x_scale < 0 || font->y_scale < 0)
- {
- FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
- 0, font->y_scale < 0 ? -1 : +1};
- FT_Set_Transform (ft_face, &matrix, nullptr);
- }
-
-#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
- unsigned int num_coords;
- const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
- if (num_coords)
- {
- FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
- if (ft_coords)
- {
- for (unsigned int i = 0; i < num_coords; i++)
- ft_coords[i] = coords[i] * 4;
- FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
- hb_free (ft_coords);
- }
- }
-#endif
ft_face->generic.data = blob;
- ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
+ ft_face->generic.finalizer = _release_blob;
_hb_ft_font_set_funcs (font, ft_face, true);
hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
-}
+ _hb_ft_hb_font_changed (font, ft_face);
+}
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ft.h b/src/3rdparty/harfbuzz-ng/src/hb-ft.h
index bf07115ab9..6a8a7abe8c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ft.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ft.h
@@ -122,10 +122,17 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
HB_EXTERN int
hb_ft_font_get_load_flags (hb_font_t *font);
-/* Call when size or variations settings on underlying FT_Face change. */
+/* Call when size or variations settings on underlying FT_Face changed,
+ * and you want to update the hb_font_t from it. */
HB_EXTERN void
hb_ft_font_changed (hb_font_t *font);
+/* Call when size or variations settings on underlying hb_font_t may have
+ * changed, and you want to update the FT_Face from it. This call is fast
+ * if nothing changed on hb_font_t. Returns true if changed. */
+HB_EXTERN hb_bool_t
+hb_ft_hb_font_changed (hb_font_t *font);
+
/* Makes an hb_font_t use FreeType internally to implement font functions.
* Note: this internally creates an FT_Face. Use it when you create your
* hb_face_t using hb_face_create(). */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-glib.cc b/src/3rdparty/harfbuzz-ng/src/hb-glib.cc
index 8ddc7ebad8..1da81696e7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-glib.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-glib.cc
@@ -129,32 +129,9 @@ hb_glib_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
{
#if GLIB_CHECK_VERSION(2,29,12)
return g_unichar_compose (a, b, ab);
+#else
+ return false;
#endif
-
- /* We don't ifdef-out the fallback code such that compiler always
- * sees it and makes sure it's compilable. */
-
- gchar utf8[12];
- gchar *normalized;
- int len;
- hb_bool_t ret;
-
- len = g_unichar_to_utf8 (a, utf8);
- len += g_unichar_to_utf8 (b, utf8 + len);
- normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFC);
- len = g_utf8_strlen (normalized, -1);
- if (unlikely (!len))
- return false;
-
- if (len == 1) {
- *ab = g_utf8_get_char (normalized);
- ret = true;
- } else {
- ret = false;
- }
-
- g_free (normalized);
- return ret;
}
static hb_bool_t
@@ -166,55 +143,9 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
{
#if GLIB_CHECK_VERSION(2,29,12)
return g_unichar_decompose (ab, a, b);
+#else
+ return false;
#endif
-
- /* We don't ifdef-out the fallback code such that compiler always
- * sees it and makes sure it's compilable. */
-
- gchar utf8[6];
- gchar *normalized;
- int len;
- hb_bool_t ret;
-
- len = g_unichar_to_utf8 (ab, utf8);
- normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFD);
- len = g_utf8_strlen (normalized, -1);
- if (unlikely (!len))
- return false;
-
- if (len == 1) {
- *a = g_utf8_get_char (normalized);
- *b = 0;
- ret = *a != ab;
- } else if (len == 2) {
- *a = g_utf8_get_char (normalized);
- *b = g_utf8_get_char (g_utf8_next_char (normalized));
- /* Here's the ugly part: if ab decomposes to a single character and
- * that character decomposes again, we have to detect that and undo
- * the second part :-(. */
- gchar *recomposed = g_utf8_normalize (normalized, -1, G_NORMALIZE_NFC);
- hb_codepoint_t c = g_utf8_get_char (recomposed);
- if (c != ab && c != *a) {
- *a = c;
- *b = 0;
- }
- g_free (recomposed);
- ret = true;
- } else {
- /* If decomposed to more than two characters, take the last one,
- * and recompose the rest to get the first component. */
- gchar *end = g_utf8_offset_to_pointer (normalized, len - 1);
- gchar *recomposed;
- *b = g_utf8_get_char (end);
- recomposed = g_utf8_normalize (normalized, end - normalized, G_NORMALIZE_NFC);
- /* We expect that recomposed has exactly one character now. */
- *a = g_utf8_get_char (recomposed);
- g_free (recomposed);
- ret = true;
- }
-
- g_free (normalized);
- return ret;
}
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.cc b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
index 63dc18b466..9e068f8d84 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
@@ -158,7 +158,7 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
}
/**
- * hb_graphite2_face_get_gr_face:
+ * hb_graphite2_face_get_gr_face: (skip)
* @face: @hb_face_t to query
*
* Fetches the Graphite2 gr_face corresponding to the specified
@@ -195,10 +195,10 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED
#ifndef HB_DISABLE_DEPRECATED
/**
- * hb_graphite2_font_get_gr_font:
+ * hb_graphite2_font_get_gr_font: (skip)
* @font: An #hb_font_t
*
- * Always returns %NULL. Use hb_graphite2_face_get_gr_face() instead.
+ * Always returns `NULL`. Use hb_graphite2_face_get_gr_face() instead.
*
* Return value: (nullable): Graphite2 font associated with @font.
*
@@ -223,7 +223,7 @@ struct hb_graphite2_cluster_t {
unsigned int base_glyph;
unsigned int num_glyphs;
unsigned int cluster;
- unsigned int advance;
+ int advance;
};
hb_bool_t
@@ -318,7 +318,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
#undef ALLOCATE_ARRAY
- memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
+ hb_memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
hb_codepoint_t *pg = gids;
clusters[0].cluster = buffer->info[0].cluster;
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 43a3098f65..b123b2f27c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh
@@ -43,17 +43,12 @@
* is writable, then the iterator returns lvalues, otherwise it
* returns rvalues.
*
- * TODO Document more.
- *
- * If iterator implementation implements operator!=, then can be
+ * If iterator implementation implements operator!=, then it can be
* used in range-based for loop. That already happens if the iterator
* is random-access. Otherwise, the range-based for loop incurs
* one traversal to find end(), which can be avoided if written
* as a while-style for loop, or if iterator implements a faster
- * __end__() method.
- * TODO When opting in for C++17, address this by changing return
- * type of .end()?
- */
+ * __end__() method. */
/*
* Base classes for iterators.
@@ -75,20 +70,17 @@ struct hb_iter_t
iter_t* thiz () { return static_cast< iter_t *> (this); }
public:
- /* TODO:
- * Port operators below to use hb_enable_if to sniff which method implements
- * an operator and use it, and remove hb_iter_fallback_mixin_t completely. */
-
/* Operators. */
iter_t iter () const { return *thiz(); }
iter_t operator + () const { return *thiz(); }
- iter_t begin () const { return *thiz(); }
- iter_t end () const { return thiz()->__end__ (); }
+ iter_t _begin () const { return *thiz(); }
+ iter_t begin () const { return _begin (); }
+ iter_t _end () const { return thiz()->__end__ (); }
+ iter_t end () const { return _end (); }
explicit operator bool () const { return thiz()->__more__ (); }
unsigned len () const { return thiz()->__len__ (); }
/* The following can only be enabled if item_t is reference type. Otherwise
- * it will be returning pointer to temporary rvalue.
- * TODO Use a wrapper return type to fix for non-reference type. */
+ * it will be returning pointer to temporary rvalue. */
template <typename T = item_t,
hb_enable_if (std::is_reference<T>::value)>
hb_remove_reference<item_t>* operator -> () const { return std::addressof (**thiz()); }
@@ -128,7 +120,9 @@ struct hb_iter_t
#define HB_ITER_USING(Name) \
using item_t = typename Name::item_t; \
+ using Name::_begin; \
using Name::begin; \
+ using Name::_end; \
using Name::end; \
using Name::get_item_size; \
using Name::is_iterator; \
@@ -178,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);
@@ -263,6 +263,8 @@ struct hb_is_iterator_of
};
#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
+#define hb_is_sorted_iterator_of(Iter, Item) (hb_is_iterator_of<Iter, Item>::value && Iter::is_sorted_iterator)
+#define hb_is_sorted_iterator(Iter) hb_is_sorted_iterator_of (Iter, typename Iter::item_t)
/* hb_is_iterable() */
@@ -385,7 +387,7 @@ struct hb_map_iter_t :
void __forward__ (unsigned n) { it += n; }
void __prev__ () { --it; }
void __rewind__ (unsigned n) { it -= n; }
- hb_map_iter_t __end__ () const { return hb_map_iter_t (it.end (), f); }
+ hb_map_iter_t __end__ () const { return hb_map_iter_t (it._end (), f); }
bool operator != (const hb_map_iter_t& o) const
{ return it != o.it; }
@@ -448,7 +450,7 @@ struct hb_filter_iter_t :
bool __more__ () const { return bool (it); }
void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
void __prev__ () { do --it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
- hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it.end (), p, f); }
+ hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it._end (), p, f); }
bool operator != (const hb_filter_iter_t& o) const
{ return it != o.it; }
@@ -561,7 +563,7 @@ struct hb_zip_iter_t :
void __forward__ (unsigned n) { a += n; b += n; }
void __prev__ () { --a; --b; }
void __rewind__ (unsigned n) { a -= n; b -= n; }
- hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a.end (), b.end ()); }
+ hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a._end (), b._end ()); }
/* Note, we should stop if ANY of the iters reaches end. As such two compare
* unequal if both items are unequal, NOT if either is unequal. */
bool operator != (const hb_zip_iter_t& o) const
@@ -645,7 +647,7 @@ struct hb_concat_iter_t :
}
}
- hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); }
+ hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a._end (), b._end ()); }
bool operator != (const hb_concat_iter_t& o) const
{
return a != o.a
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 e52a6a4124..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"
/*
@@ -136,6 +135,13 @@ static inline Type& StructAfter(TObject &X)
/*
* Lazy loaders.
+ *
+ * The lazy-loaders are thread-safe pointer-like objects that create their
+ * instead on-demand. They also support access to a "data" object that is
+ * necessary for creating their instance. The data object, if specified,
+ * is accessed via pointer math, located at a location before the position
+ * of the loader itself. This avoids having to store a pointer to data
+ * for every lazy-loader. Multiple lazy-loaders can access the same data.
*/
template <typename Data, unsigned int WheresData>
@@ -176,12 +182,12 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
void init0 () {} /* Init, when memory is already set to 0. No-op for us. */
void init () { instance.set_relaxed (nullptr); }
- void fini () { do_destroy (instance.get ()); }
+ void fini () { do_destroy (instance.get_acquire ()); init (); }
void free_instance ()
{
retry:
- Stored *p = instance.get ();
+ Stored *p = instance.get_acquire ();
if (unlikely (p && !cmpexch (p, nullptr)))
goto retry;
do_destroy (p);
@@ -203,7 +209,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
Stored * get_stored () const
{
retry:
- Stored *p = this->instance.get ();
+ Stored *p = this->instance.get_acquire ();
if (unlikely (!p))
{
if (unlikely (this->is_inert ()))
@@ -228,7 +234,8 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
bool cmpexch (Stored *current, Stored *value) const
{
- /* This *must* be called when there are no other threads accessing. */
+ /* This function can only be safely called directly if no
+ * other thread is accessing. */
return this->instance.cmpexch (current, value);
}
@@ -261,7 +268,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
hb_free (p);
}
-// private:
+ private:
/* Must only have one pointer. */
hb_atomic_ptr_t<Stored *> instance;
};
@@ -283,7 +290,7 @@ struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
{
auto c = hb_sanitize_context_t ();
if (core)
- c.set_num_glyphs (0); // So we don't recurse ad infinitum...
+ c.set_num_glyphs (0); // So we don't recurse ad infinitum, or doesn't need num_glyphs
return c.reference_table<T> (face);
}
static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
@@ -297,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 9f1ac42846..0014570e8e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-map.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-map.cc
@@ -40,7 +40,7 @@
/**
- * hb_map_create: (Xconstructor)
+ * hb_map_create:
*
* Creates a new, initially empty map.
*
@@ -56,8 +56,6 @@ hb_map_create ()
if (!(map = hb_object_create<hb_map_t> ()))
return hb_map_get_empty ();
- map->init_shallow ();
-
return map;
}
@@ -107,8 +105,6 @@ hb_map_destroy (hb_map_t *map)
{
if (!hb_object_destroy (map)) return;
- map->fini_shallow ();
-
hb_free (map);
}
@@ -122,7 +118,7 @@ hb_map_destroy (hb_map_t *map)
*
* Attaches a user-data key/data pair to the specified map.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 1.7.7
**/
@@ -149,7 +145,7 @@ hb_map_set_user_data (hb_map_t *map,
* Since: 1.7.7
**/
void *
-hb_map_get_user_data (hb_map_t *map,
+hb_map_get_user_data (const hb_map_t *map,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (map, key);
@@ -162,7 +158,7 @@ hb_map_get_user_data (hb_map_t *map,
*
* Tests whether memory allocation for a set was successful.
*
- * Return value: %true if allocation succeeded, %false otherwise
+ * Return value: `true` if allocation succeeded, `false` otherwise
*
* Since: 1.7.7
**/
@@ -172,6 +168,26 @@ hb_map_allocation_successful (const hb_map_t *map)
return map->successful;
}
+/**
+ * hb_map_copy:
+ * @map: A map
+ *
+ * Allocate a copy of @map.
+ *
+ * Return value: (transfer full): Newly-allocated map.
+ *
+ * Since: 4.4.0
+ **/
+hb_map_t *
+hb_map_copy (const hb_map_t *map)
+{
+ hb_map_t *copy = hb_map_create ();
+ if (unlikely (copy->in_error ()))
+ return hb_map_get_empty ();
+
+ *copy = *map;
+ return copy;
+}
/**
* hb_map_set:
@@ -232,7 +248,7 @@ hb_map_del (hb_map_t *map,
*
* Tests whether @key is an element of @map.
*
- * Return value: %true if @key is found in @map, %false otherwise
+ * Return value: `true` if @key is found in @map, `false` otherwise
*
* Since: 1.7.7
**/
@@ -264,7 +280,7 @@ hb_map_clear (hb_map_t *map)
*
* Tests whether @map is empty (contains no elements).
*
- * Return value: %true if @map is empty
+ * Return value: `true` if @map is empty
*
* Since: 1.7.7
**/
@@ -289,3 +305,115 @@ hb_map_get_population (const hb_map_t *map)
{
return map->get_population ();
}
+
+/**
+ * hb_map_is_equal:
+ * @map: A map
+ * @other: Another map
+ *
+ * Tests whether @map and @other are equal (contain the same
+ * elements).
+ *
+ * Return value: `true` if the two maps are equal, `false` otherwise.
+ *
+ * Since: 4.3.0
+ **/
+hb_bool_t
+hb_map_is_equal (const hb_map_t *map,
+ const hb_map_t *other)
+{
+ return map->is_equal (*other);
+}
+
+/**
+ * hb_map_hash:
+ * @map: A map
+ *
+ * Creates a hash representing @map.
+ *
+ * Return value:
+ * A hash of @map.
+ *
+ * Since: 4.4.0
+ **/
+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 6a45a7bdd5..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
@@ -74,7 +75,7 @@ hb_map_set_user_data (hb_map_t *map,
hb_bool_t replace);
HB_EXTERN void *
-hb_map_get_user_data (hb_map_t *map,
+hb_map_get_user_data (const hb_map_t *map,
hb_user_data_key_t *key);
@@ -82,6 +83,9 @@ hb_map_get_user_data (hb_map_t *map,
HB_EXTERN hb_bool_t
hb_map_allocation_successful (const hb_map_t *map);
+HB_EXTERN hb_map_t *
+hb_map_copy (const hb_map_t *map);
+
HB_EXTERN void
hb_map_clear (hb_map_t *map);
@@ -91,6 +95,13 @@ hb_map_is_empty (const hb_map_t *map);
HB_EXTERN unsigned int
hb_map_get_population (const hb_map_t *map);
+HB_EXTERN hb_bool_t
+hb_map_is_equal (const hb_map_t *map,
+ const hb_map_t *other);
+
+HB_EXTERN unsigned int
+hb_map_hash (const hb_map_t *map);
+
HB_EXTERN void
hb_map_set (hb_map_t *map,
hb_codepoint_t key,
@@ -108,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 9341637eac..615d1825ed 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-map.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-map.hh
@@ -29,24 +29,25 @@
#include "hb.hh"
+#include "hb-set.hh"
+
/*
* hb_hashmap_t
*/
+extern HB_INTERNAL const hb_codepoint_t minus_1;
+
template <typename K, typename V,
- typename k_invalid_t = K,
- typename v_invalid_t = V,
- k_invalid_t kINVALID = std::is_pointer<K>::value ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1,
- v_invalid_t vINVALID = std::is_pointer<V>::value ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1>
+ bool minus_one = false>
struct hb_hashmap_t
{
hb_hashmap_t () { init (); }
~hb_hashmap_t () { fini (); }
- hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { hb_copy (o, *this); }
+ hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (o.population); hb_copy (o, *this); }
hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
- hb_hashmap_t& operator= (const hb_hashmap_t& o) { hb_copy (o, *this); return *this; }
+ hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); resize (o.population); hb_copy (o, *this); return *this; }
hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; }
hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t ()
@@ -58,49 +59,54 @@ struct hb_hashmap_t
hb_requires (hb_is_iterable (Iterable))>
hb_hashmap_t (const Iterable &o) : hb_hashmap_t ()
{
- hb_copy (o, *this);
+ auto iter = hb_iter (o);
+ if (iter.is_random_access_iterator)
+ resize (hb_len (iter));
+ hb_copy (iter, *this);
}
struct item_t
{
K key;
+ uint32_t hash : 30;
+ uint32_t is_used_ : 1;
+ uint32_t is_tombstone_ : 1;
V value;
- uint32_t hash;
- void clear ()
+ item_t () : key (),
+ hash (0),
+ is_used_ (false), is_tombstone_ (false),
+ value () {}
+
+ bool is_used () const { return is_used_; }
+ void set_used (bool is_used) { is_used_ = is_used; }
+ bool is_tombstone () const { return is_tombstone_; }
+ void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; }
+ bool is_real () const { return is_used_ && !is_tombstone_; }
+
+ template <bool v = minus_one,
+ hb_enable_if (v == false)>
+ static inline const V& default_value () { return Null(V); };
+ template <bool v = minus_one,
+ hb_enable_if (v == true)>
+ static inline const V& default_value ()
{
- new (std::addressof (key)) K ();
- key = hb_coerce<K> (kINVALID);
- new (std::addressof (value)) V ();
- value = hb_coerce<V> (vINVALID);
- hash = 0;
- }
+ static_assert (hb_is_same (V, hb_codepoint_t), "");
+ return minus_1;
+ };
- bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); }
- bool operator == (const item_t &o) { return *this == o.key; }
- bool is_unused () const
- {
- const K inv = hb_coerce<K> (kINVALID);
- return key == inv;
- }
- bool is_tombstone () const
- {
- const K kinv = hb_coerce<K> (kINVALID);
- const V vinv = hb_coerce<V> (vINVALID);
- return key != kinv && value == vinv;
- }
- bool is_real () const
- {
- const K kinv = hb_coerce<K> (kINVALID);
- const V vinv = hb_coerce<V> (vINVALID);
- return key != kinv && value != vinv;
- }
+ bool operator == (const K &o) const { return hb_deref (key) == hb_deref (o); }
+ bool operator == (const item_t &o) const { return *this == o.key; }
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
+ hb_pair_t<const K &, const V &> get_pair_ref() const { return hb_pair_t<const K &, const V &> (key, value); }
+
+ uint32_t total_hash () const
+ { return (hash * 31) + hb_hash (value); }
};
hb_object_header_t header;
- bool successful; /* Allocations successful */
- unsigned int population; /* Not including tombstones. */
+ unsigned int successful : 1; /* Allocations successful */
+ unsigned int population : 31; /* Not including tombstones. */
unsigned int occupancy; /* Including tombstones. */
unsigned int mask;
unsigned int prime;
@@ -110,27 +116,29 @@ struct hb_hashmap_t
{
if (unlikely (!a.successful || !b.successful))
return;
- hb_swap (a.population, b.population);
+ unsigned tmp = a.population;
+ a.population = b.population;
+ b.population = tmp;
+ //hb_swap (a.population, b.population);
hb_swap (a.occupancy, b.occupancy);
hb_swap (a.mask, b.mask);
hb_swap (a.prime, b.prime);
hb_swap (a.items, b.items);
}
- void init_shallow ()
+ void init ()
{
+ hb_object_init (this);
+
successful = true;
population = occupancy = 0;
mask = 0;
prime = 0;
items = nullptr;
}
- void init ()
- {
- hb_object_init (this);
- init_shallow ();
- }
- void fini_shallow ()
+ void fini ()
{
+ hb_object_fini (this);
+
if (likely (items)) {
unsigned size = mask + 1;
for (unsigned i = 0; i < size; i++)
@@ -140,11 +148,6 @@ struct hb_hashmap_t
}
population = occupancy = 0;
}
- void fini ()
- {
- hb_object_fini (this);
- fini_shallow ();
- }
void reset ()
{
@@ -154,11 +157,13 @@ struct hb_hashmap_t
bool in_error () const { return !successful; }
- bool resize ()
+ bool resize (unsigned new_population = 0)
{
if (unlikely (!successful)) return false;
- unsigned int power = hb_bit_storage (population * 2 + 8);
+ if (new_population != 0 && (new_population + new_population / 2) < mask) return true;
+
+ unsigned int power = hb_bit_storage (hb_max ((unsigned) population, new_population) * 2 + 8);
unsigned int new_size = 1u << power;
item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t));
if (unlikely (!new_items))
@@ -167,9 +172,9 @@ struct hb_hashmap_t
return false;
}
for (auto &_ : hb_iter (new_items, new_size))
- _.clear ();
+ new (&_) item_t ();
- unsigned int old_size = mask + 1;
+ unsigned int old_size = size ();
item_t *old_items = items;
/* Switch to new, empty, array. */
@@ -179,55 +184,102 @@ struct hb_hashmap_t
items = new_items;
/* Insert back old items. */
- if (old_items)
- for (unsigned int i = 0; i < old_size; i++)
+ for (unsigned int i = 0; i < old_size; i++)
+ {
+ if (old_items[i].is_real ())
{
- if (old_items[i].is_real ())
- {
- set_with_hash (old_items[i].key,
- old_items[i].hash,
- std::move (old_items[i].value));
- }
- old_items[i].~item_t ();
+ set_with_hash (std::move (old_items[i].key),
+ old_items[i].hash,
+ std::move (old_items[i].value));
}
+ old_items[i].~item_t ();
+ }
hb_free (old_items);
return true;
}
- bool set (K key, const V& value) { return set_with_hash (key, hb_hash (key), value); }
- bool set (K key, V&& value) { return set_with_hash (key, hb_hash (key), std::move (value)); }
+ template <typename KK, typename VV>
+ bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool is_delete=false)
+ {
+ if (unlikely (!successful)) return false;
+ if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
+ item_t &item = item_for_hash (key, hash);
+
+ if (is_delete && !(item == key))
+ return true; /* Trying to delete non-existent key. */
+
+ if (item.is_used ())
+ {
+ occupancy--;
+ if (!item.is_tombstone ())
+ population--;
+ }
+
+ item.key = std::forward<KK> (key);
+ item.value = std::forward<VV> (value);
+ item.hash = hash;
+ item.set_used (true);
+ item.set_tombstone (is_delete);
+
+ occupancy++;
+ if (!is_delete)
+ population++;
+
+ return true;
+ }
+
+ template <typename VV>
+ bool set (const K &key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
+ template <typename VV>
+ bool set (K &&key, VV&& value) { return set_with_hash (std::move (key), hb_hash (key), std::forward<VV> (value)); }
- V get (K key) const
+ const V& get_with_hash (const K &key, uint32_t hash) const
+ {
+ if (unlikely (!items)) return item_t::default_value ();
+ auto &item = item_for_hash (key, hash);
+ return item.is_real () && item == key ? item.value : item_t::default_value ();
+ }
+ const V& get (const K &key) const
{
- if (unlikely (!items)) return hb_coerce<V> (vINVALID);
- unsigned int i = bucket_for (key);
- return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID);
+ if (unlikely (!items)) return item_t::default_value ();
+ return get_with_hash (key, hb_hash (key));
}
- void del (K key) { set (key, hb_coerce<V> (vINVALID)); }
+ void del (const K &key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
/* Has interface. */
- typedef V value_t;
- value_t operator [] (K k) const { return get (k); }
- bool has (K k, V *vp = nullptr) const
+ const V& operator [] (K k) const { return get (k); }
+ template <typename VV=V>
+ bool has (K key, VV **vp = nullptr) const
{
- V v = (*this)[k];
- if (vp) *vp = v;
- const V vinv = hb_coerce<V> (vINVALID);
- return v != vinv;
+ if (unlikely (!items))
+ return false;
+ auto &item = item_for_hash (key, hb_hash (key));
+ if (item.is_real () && item == key)
+ {
+ if (vp) *vp = std::addressof (item.value);
+ return true;
+ }
+ else
+ return false;
}
/* Projection. */
V operator () (K k) const { return get (k); }
+ unsigned size () const { return mask ? mask + 1 : 0; }
+
void clear ()
{
if (unlikely (!successful)) return;
- if (items)
- for (auto &_ : hb_iter (items, mask + 1))
- _.clear ();
+ for (auto &_ : hb_iter (items, size ()))
+ {
+ /* Reconstruct items. */
+ _.~item_t ();
+ new (&_) item_t ();
+ }
population = occupancy = 0;
}
@@ -235,88 +287,135 @@ struct hb_hashmap_t
bool is_empty () const { return population == 0; }
explicit operator bool () const { return !is_empty (); }
+ uint32_t hash () const
+ {
+ return
+ + iter_items ()
+ | hb_reduce ([] (uint32_t h, const item_t &_) { return h ^ _.total_hash (); }, (uint32_t) 0u)
+ ;
+ }
+
+ bool is_equal (const hb_hashmap_t &other) const
+ {
+ if (population != other.population) return false;
+
+ for (auto pair : iter ())
+ if (other.get (pair.first) != pair.second)
+ return false;
+
+ return true;
+ }
+ bool operator == (const hb_hashmap_t &other) const { return is_equal (other); }
+ bool operator != (const hb_hashmap_t &other) const { return !is_equal (other); }
+
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
*/
- auto iter () const HB_AUTO_RETURN
+
+ auto iter_items () const HB_AUTO_RETURN
(
- + hb_array (items, mask ? mask + 1 : 0)
+ + hb_iter (items, size ())
| hb_filter (&item_t::is_real)
+ )
+ auto iter_ref () const HB_AUTO_RETURN
+ (
+ + iter_items ()
+ | hb_map (&item_t::get_pair_ref)
+ )
+ auto iter () const HB_AUTO_RETURN
+ (
+ + iter_items ()
| hb_map (&item_t::get_pair)
)
- auto keys () const HB_AUTO_RETURN
+ auto keys_ref () const HB_AUTO_RETURN
(
- + hb_array (items, mask ? mask + 1 : 0)
- | hb_filter (&item_t::is_real)
+ + iter_items ()
| hb_map (&item_t::key)
+ )
+ auto keys () const HB_AUTO_RETURN
+ (
+ + keys_ref ()
| hb_map (hb_ridentity)
)
- auto values () const HB_AUTO_RETURN
+ auto values_ref () const HB_AUTO_RETURN
(
- + hb_array (items, mask ? mask + 1 : 0)
- | hb_filter (&item_t::is_real)
+ + iter_items ()
| hb_map (&item_t::value)
+ )
+ auto values () const HB_AUTO_RETURN
+ (
+ + values_ref ()
| hb_map (hb_ridentity)
)
- /* Sink interface. */
- hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
- { set (v.first, v.second); return *this; }
-
- protected:
-
- template <typename VV>
- bool set_with_hash (K key, uint32_t hash, VV&& value)
+ /* C iterator. */
+ bool next (int *idx,
+ K *key,
+ V *value) const
{
- if (unlikely (!successful)) return false;
- const K kinv = hb_coerce<K> (kINVALID);
- if (unlikely (key == kinv)) return true;
- if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
- unsigned int i = bucket_for_hash (key, hash);
+ unsigned i = (unsigned) (*idx + 1);
- const V vinv = hb_coerce<V> (vINVALID);
- if (value == vinv && items[i].key != key)
- return true; /* Trying to delete non-existent key. */
+ unsigned count = size ();
+ while (i < count && !items[i].is_real ())
+ i++;
- if (!items[i].is_unused ())
+ if (i >= count)
{
- occupancy--;
- if (!items[i].is_tombstone ())
- population--;
+ *idx = -1;
+ return false;
}
- items[i].key = key;
- items[i].value = value;
- items[i].hash = hash;
-
- occupancy++;
- if (!items[i].is_tombstone ())
- population++;
+ *key = items[i].key;
+ *value = items[i].value;
+ *idx = (signed) i;
return true;
}
- unsigned int bucket_for (K key) const
- {
- return bucket_for_hash (key, hb_hash (key));
- }
-
- unsigned int bucket_for_hash (K key, uint32_t hash) const
+ /* Sink interface. */
+ hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
+ { set (v.first, v.second); return *this; }
+ hb_hashmap_t& operator << (const hb_pair_t<K, V&&>& v)
+ { set (v.first, std::move (v.second)); return *this; }
+ hb_hashmap_t& operator << (const hb_pair_t<K&&, V>& v)
+ { set (std::move (v.first), v.second); return *this; }
+ hb_hashmap_t& operator << (const hb_pair_t<K&&, V&&>& v)
+ { set (std::move (v.first), std::move (v.second)); return *this; }
+
+ item_t& item_for_hash (const K &key, uint32_t hash) const
{
+ hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
unsigned int i = hash % prime;
unsigned int step = 0;
unsigned int tombstone = (unsigned) -1;
- while (!items[i].is_unused ())
+ while (items[i].is_used ())
{
if (items[i].hash == hash && items[i] == key)
- return i;
+ return items[i];
if (tombstone == (unsigned) -1 && items[i].is_tombstone ())
tombstone = i;
i = (i + ++step) & mask;
}
- return tombstone == (unsigned) -1 ? i : tombstone;
+ return items[tombstone == (unsigned) -1 ? i : tombstone];
}
static unsigned int prime_for (unsigned int shift)
@@ -377,21 +476,16 @@ struct hb_hashmap_t
struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_codepoint_t,
- hb_codepoint_t,
- hb_codepoint_t,
- HB_MAP_VALUE_INVALID,
- HB_MAP_VALUE_INVALID>
+ true>
{
using hashmap = hb_hashmap_t<hb_codepoint_t,
hb_codepoint_t,
- hb_codepoint_t,
- hb_codepoint_t,
- HB_MAP_VALUE_INVALID,
- HB_MAP_VALUE_INVALID>;
+ true>;
- hb_map_t () = default;
~hb_map_t () = default;
- hb_map_t (hb_map_t&) = default;
+ hb_map_t () : hashmap () {}
+ hb_map_t (const hb_map_t &o) : hashmap ((hashmap &) o) {}
+ hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {}
hb_map_t& operator= (const hb_map_t&) = default;
hb_map_t& operator= (hb_map_t&&) = default;
hb_map_t (std::initializer_list<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> lst) : hashmap (lst) {}
@@ -400,4 +494,5 @@ struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_map_t (const Iterable &o) : hashmap (o) {}
};
+
#endif /* HB_MAP_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh
index 3fea5d995e..31aa7fa6f1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh
@@ -112,8 +112,7 @@ template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_ident
template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (hb_prioritize));
-/* TODO Add feature-parity to std::decay. */
-template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
+template <typename T> using hb_decay = typename std::decay<T>::type;
#define hb_is_convertible(From,To) std::is_convertible<From, To>::value
@@ -133,6 +132,18 @@ struct
template <typename T> constexpr auto
operator () (T *v) const HB_AUTO_RETURN (*v)
+
+ template <typename T> constexpr auto
+ operator () (const hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v)
+
+ template <typename T> constexpr auto
+ operator () (hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v)
+
+ template <typename T> constexpr auto
+ operator () (const hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v)
+
+ template <typename T> constexpr auto
+ operator () (hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v)
}
HB_FUNCOBJ (hb_deref);
@@ -188,6 +199,19 @@ template <> struct hb_int_max<signed long long> : hb_integral_constant<signed l
template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigned long long, ULLONG_MAX> {};
#define hb_int_max(T) hb_int_max<T>::value
+#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
+#define hb_is_trivially_copyable(T) __has_trivial_copy(T)
+#define hb_is_trivially_copy_assignable(T) __has_trivial_assign(T)
+#define hb_is_trivially_constructible(T) __has_trivial_constructor(T)
+#define hb_is_trivially_copy_constructible(T) __has_trivial_copy_constructor(T)
+#define hb_is_trivially_destructible(T) __has_trivial_destructor(T)
+#else
+#define hb_is_trivially_copyable(T) std::is_trivially_copyable<T>::value
+#define hb_is_trivially_copy_assignable(T) std::is_trivially_copy_assignable<T>::value
+#define hb_is_trivially_constructible(T) std::is_trivially_constructible<T>::value
+#define hb_is_trivially_copy_constructible(T) std::is_trivially_copy_constructible<T>::value
+#define hb_is_trivially_destructible(T) std::is_trivially_destructible<T>::value
+#endif
/* Class traits. */
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 d40fdeaa82..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;
@@ -166,7 +169,7 @@ hb_ms_setup_features (const hb_feature_t *features,
{
auto *feature = active_features.lsearch (event->feature);
if (feature)
- active_features.remove (feature - active_features.arrayZ);
+ active_features.remove_ordered (feature - active_features.arrayZ);
}
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh
new file mode 100644
index 0000000000..b4a8cc62a3
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh
@@ -0,0 +1,92 @@
+/*
+ * 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_MULTIMAP_HH
+#define HB_MULTIMAP_HH
+
+#include "hb.hh"
+#include "hb-map.hh"
+#include "hb-vector.hh"
+
+
+/*
+ * hb_multimap_t
+ */
+
+struct hb_multimap_t
+{
+ void add (hb_codepoint_t k, hb_codepoint_t v)
+ {
+ hb_codepoint_t *i;
+ if (multiples_indices.has (k, &i))
+ {
+ multiples_values[*i].push (v);
+ return;
+ }
+
+ hb_codepoint_t *old_v;
+ if (singulars.has (k, &old_v))
+ {
+ hb_codepoint_t old = *old_v;
+ singulars.del (k);
+
+ multiples_indices.set (k, multiples_values.length);
+ auto *vec = multiples_values.push ();
+
+ vec->push (old);
+ vec->push (v);
+
+ return;
+ }
+
+ singulars.set (k, v);
+ }
+
+ hb_array_t<const hb_codepoint_t> get (hb_codepoint_t k) const
+ {
+ const hb_codepoint_t *v;
+ if (singulars.has (k, &v))
+ return hb_array (v, 1);
+
+ hb_codepoint_t *i;
+ if (multiples_indices.has (k, &i))
+ return multiples_values[*i].as_array ();
+
+ return hb_array_t<const hb_codepoint_t> ();
+ }
+
+ bool in_error () const
+ {
+ return singulars.in_error () || multiples_indices.in_error () || multiples_values.in_error ();
+ }
+
+ protected:
+ hb_map_t singulars;
+ hb_map_t multiples_indices;
+ hb_vector_t<hb_vector_t<hb_codepoint_t>> multiples_values;
+};
+
+
+
+#endif /* HB_MULTIMAP_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh b/src/3rdparty/harfbuzz-ng/src/hb-mutex.hh
index 6914b22450..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); }
@@ -108,10 +111,11 @@ struct hb_mutex_t
struct hb_lock_t
{
- hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); }
- ~hb_lock_t () { mutex.unlock (); }
+ hb_lock_t (hb_mutex_t &mutex_) : mutex (&mutex_) { mutex->lock (); }
+ hb_lock_t (hb_mutex_t *mutex_) : mutex (mutex_) { if (mutex) mutex->lock (); }
+ ~hb_lock_t () { if (mutex) mutex->unlock (); }
private:
- hb_mutex_t &mutex;
+ hb_mutex_t *mutex;
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-null.hh b/src/3rdparty/harfbuzz-ng/src/hb-null.hh
index db38a4dfd2..0d7f4da79e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-null.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-null.hh
@@ -37,7 +37,25 @@
/* Global nul-content Null pool. Enlarge as necessary. */
-#define HB_NULL_POOL_SIZE 384
+#define HB_NULL_POOL_SIZE 448
+
+template <typename T, typename>
+struct _hb_has_min_size : hb_false_type {};
+template <typename T>
+struct _hb_has_min_size<T, hb_void_t<decltype (T::min_size)>>
+ : hb_true_type {};
+template <typename T>
+using hb_has_min_size = _hb_has_min_size<T, void>;
+#define hb_has_min_size(T) hb_has_min_size<T>::value
+
+template <typename T, typename>
+struct _hb_has_null_size : hb_false_type {};
+template <typename T>
+struct _hb_has_null_size<T, hb_void_t<decltype (T::null_size)>>
+ : hb_true_type {};
+template <typename T>
+using hb_has_null_size = _hb_has_null_size<T, void>;
+#define hb_has_null_size(T) hb_has_null_size<T>::value
/* Use SFINAE to sniff whether T has min_size; in which case return the larger
* of sizeof(T) and T::null_size, otherwise return sizeof(T).
@@ -108,7 +126,7 @@ struct NullHelper
/* Specializations for arbitrary-content Null objects expressed in bytes. */
#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
} /* Close namespace. */ \
- extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
+ extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[hb_null_size (Namespace::Type)]; \
template <> \
struct Null<Namespace::Type> { \
static Namespace::Type const & get_null () { \
@@ -117,8 +135,19 @@ struct NullHelper
}; \
namespace Namespace { \
static_assert (true, "") /* Require semicolon after. */
+#define DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1(Namespace, Type, Size) \
+ } /* Close namespace. */ \
+ extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Size]; \
+ template <typename Spec> \
+ struct Null<Namespace::Type<Spec>> { \
+ static Namespace::Type<Spec> const & get_null () { \
+ return *reinterpret_cast<const Namespace::Type<Spec> *> (_hb_Null_##Namespace##_##Type); \
+ } \
+ }; \
+ namespace Namespace { \
+ static_assert (true, "") /* Require semicolon after. */
#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
- const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
+ const unsigned char _hb_Null_##Namespace##_##Type[sizeof (_hb_Null_##Namespace##_##Type)]
/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
#define DECLARE_NULL_INSTANCE(Type) \
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-number-parser.hh b/src/3rdparty/harfbuzz-ng/src/hb-number-parser.hh
index 1a9dbba6dd..ec68c3a728 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-number-parser.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-number-parser.hh
@@ -31,7 +31,7 @@
#include "hb.hh"
-#line 35 "hb-number-parser.hh"
+#line 32 "hb-number-parser.hh"
static const unsigned char _double_parser_trans_keys[] = {
0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u,
46u, 101u, 0
@@ -135,12 +135,12 @@ strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
int cs;
-#line 139 "hb-number-parser.hh"
+#line 132 "hb-number-parser.hh"
{
cs = double_parser_start;
}
-#line 144 "hb-number-parser.hh"
+#line 135 "hb-number-parser.hh"
{
int _slen;
int _trans;
@@ -198,7 +198,7 @@ _resume:
exp_overflow = true;
}
break;
-#line 202 "hb-number-parser.hh"
+#line 187 "hb-number-parser.hh"
}
_again:
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 4b5bc32ade..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>
@@ -80,7 +80,7 @@ struct hb_lockable_set_t
if (item)
{
item_t old = *item;
- *item = items[items.length - 1];
+ *item = std::move (items.tail ());
items.pop ();
l.unlock ();
old.fini ();
@@ -123,7 +123,7 @@ struct hb_lockable_set_t
l.lock ();
while (items.length)
{
- item_t old = items[items.length - 1];
+ item_t old = items.tail ();
items.pop ();
l.unlock ();
old.fini ();
@@ -144,14 +144,14 @@ struct hb_reference_count_t
{
mutable hb_atomic_int_t ref_count;
- void init (int v = 1) { ref_count.set_relaxed (v); }
- int get_relaxed () const { return ref_count.get_relaxed (); }
+ void init (int v = 1) { ref_count = v; }
+ int get_relaxed () const { return ref_count; }
int inc () const { return ref_count.inc (); }
int dec () const { return ref_count.dec (); }
- void fini () { ref_count.set_relaxed (-0x0000DEAD); }
+ void fini () { ref_count = -0x0000DEAD; }
- bool is_inert () const { return !ref_count.get_relaxed (); }
- bool is_valid () const { return ref_count.get_relaxed () > 0; }
+ bool is_inert () const { return !ref_count; }
+ bool is_valid () const { return ref_count > 0; }
};
@@ -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 (); }
+
+ bool set (hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+ {
+ if (!key)
+ return false;
- HB_INTERNAL void *get (hb_user_data_key_t *key);
+ 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);
- void fini () { items.fini (lock); lock.fini (); }
+ 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;
+ }
};
@@ -214,23 +234,26 @@ static inline void hb_object_trace (const Type *obj, const char *function)
obj ? obj->header.ref_count.get_relaxed () : 0);
}
-template <typename Type>
-static inline Type *hb_object_create ()
+template <typename Type, typename ...Ts>
+static inline Type *hb_object_create (Ts... ds)
{
Type *obj = (Type *) hb_calloc (1, sizeof (Type));
if (unlikely (!obj))
return obj;
+ new (obj) Type (std::forward<Ts> (ds)...);
+
hb_object_init (obj);
hb_object_trace (obj, HB_FUNC);
+
return obj;
}
template <typename Type>
static inline void hb_object_init (Type *obj)
{
obj->header.ref_count.init ();
- obj->header.writable.set_relaxed (true);
+ obj->header.writable = true;
obj->header.user_data.init ();
}
template <typename Type>
@@ -241,12 +264,12 @@ static inline bool hb_object_is_valid (const Type *obj)
template <typename Type>
static inline bool hb_object_is_immutable (const Type *obj)
{
- return !obj->header.writable.get_relaxed ();
+ return !obj->header.writable;
}
template <typename Type>
static inline void hb_object_make_immutable (const Type *obj)
{
- obj->header.writable.set_relaxed (false);
+ obj->header.writable = false;
}
template <typename Type>
static inline Type *hb_object_reference (Type *obj)
@@ -269,18 +292,22 @@ static inline bool hb_object_destroy (Type *obj)
return false;
hb_object_fini (obj);
+
+ if (!std::is_trivially_destructible<Type>::value)
+ obj->~Type ();
+
return true;
}
template <typename Type>
static inline void hb_object_fini (Type *obj)
{
obj->header.ref_count.fini (); /* Do this before user_data */
- hb_user_data_array_t *user_data = obj->header.user_data.get ();
+ hb_user_data_array_t *user_data = obj->header.user_data.get_acquire ();
if (user_data)
{
user_data->fini ();
hb_free (user_data);
- user_data = nullptr;
+ obj->header.user_data.set_relaxed (nullptr);
}
}
template <typename Type>
@@ -295,7 +322,7 @@ static inline bool hb_object_set_user_data (Type *obj,
assert (hb_object_is_valid (obj));
retry:
- hb_user_data_array_t *user_data = obj->header.user_data.get ();
+ hb_user_data_array_t *user_data = obj->header.user_data.get_acquire ();
if (unlikely (!user_data))
{
user_data = (hb_user_data_array_t *) hb_calloc (sizeof (hb_user_data_array_t), 1);
@@ -320,7 +347,7 @@ static inline void *hb_object_get_user_data (Type *obj,
if (unlikely (!obj || obj->header.is_inert ()))
return nullptr;
assert (hb_object_is_valid (obj));
- hb_user_data_array_t *user_data = obj->header.user_data.get ();
+ hb_user_data_array_t *user_data = obj->header.user_data.get_acquire ();
if (!user_data)
return nullptr;
return user_data->get (key);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh
index 6eee5827c1..13570a46e0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh
@@ -90,7 +90,7 @@ typedef struct OpenTypeOffsetTable
{
if (table_count)
{
- + tables.sub_array (start_offset, table_count)
+ + tables.as_array ().sub_array (start_offset, table_count)
| hb_map (&TableRecord::tag)
| hb_sink (hb_array (table_tags, *table_count))
;
@@ -158,7 +158,7 @@ typedef struct OpenTypeOffsetTable
return_trace (false);
if (likely (len))
- memcpy (start, blob->data, len);
+ hb_memcpy (start, blob->data, len);
/* 4-byte alignment. */
c->align (4);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
index 7e524177f6..4c9bfebcec 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
@@ -33,6 +33,7 @@
#include "hb-blob.hh"
#include "hb-face.hh"
#include "hb-machinery.hh"
+#include "hb-meta.hh"
#include "hb-subset.hh"
@@ -104,7 +105,7 @@ struct IntType
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
BEInt<Type, Size> v;
@@ -140,27 +141,29 @@ typedef HBINT32 FWORD32;
/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
typedef HBUINT16 UFWORD;
-/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
-struct F2DOT14 : HBINT16
+template <typename Type, unsigned fraction_bits>
+struct HBFixed : Type
{
- F2DOT14& operator = (uint16_t i ) { HBINT16::operator= (i); return *this; }
- // 16384 means 1<<14
- float to_float () const { return ((int32_t) v) / 16384.f; }
- void set_float (float f) { v = roundf (f * 16384.f); }
+ static constexpr float shift = (float) (1 << fraction_bits);
+ static_assert (Type::static_size * 8 > fraction_bits, "");
+
+ 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:
- DEFINE_SIZE_STATIC (2);
+ DEFINE_SIZE_STATIC (Type::static_size);
};
+/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
+using F2DOT14 = HBFixed<HBINT16, 14>;
+using F4DOT12 = HBFixed<HBINT16, 12>;
+using F6DOT10 = HBFixed<HBINT16, 10>;
+
/* 32-bit signed fixed-point number (16.16). */
-struct HBFixed : HBINT32
-{
- HBFixed& operator = (uint32_t i) { HBINT32::operator= (i); return *this; }
- // 65536 means 1<<16
- float to_float () const { return ((int32_t) v) / 65536.f; }
- void set_float (float f) { v = roundf (f * 65536.f); }
- public:
- DEFINE_SIZE_STATIC (4);
-};
+using F16DOT16 = HBFixed<HBINT32, 16>;
/* Date represented in number of seconds since 12:00 midnight, January 1,
* 1904. The value is represented as a signed 64-bit integer. */
@@ -169,7 +172,7 @@ struct LONGDATETIME
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
HBINT32 major;
@@ -195,6 +198,10 @@ struct HBGlyphID16 : HBUINT16
{
HBGlyphID16& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
};
+struct HBGlyphID24 : HBUINT24
+{
+ HBGlyphID24& operator = (uint32_t i) { HBUINT24::operator= (i); return *this; }
+};
/* Script/language-system/feature index */
struct Index : HBUINT16 {
@@ -207,6 +214,12 @@ typedef Index NameID;
struct VarIdx : HBUINT32 {
static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu;
+ static_assert (NO_VARIATION == HB_OT_LAYOUT_NO_VARIATIONS_INDEX, "");
+ static uint32_t add (uint32_t i, unsigned short v)
+ {
+ if (i == NO_VARIATION) return i;
+ return i + v;
+ }
VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
};
DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx);
@@ -299,6 +312,10 @@ struct _hb_has_null<Type, true>
template <typename Type, typename OffsetType, bool has_null=true>
struct OffsetTo : Offset<OffsetType, has_null>
{
+ // Make sure Type is not unbounded; works only for types that are fully defined at OffsetTo time.
+ static_assert (has_null == false ||
+ (hb_has_null_size (Type) || !hb_has_min_size (Type)), "");
+
HB_DELETE_COPY_ASSIGN (OffsetTo);
OffsetTo () = default;
@@ -449,14 +466,16 @@ struct UnsizedArrayOf
{
unsigned int i = (unsigned int) i_;
const Type *p = &arrayZ[i];
- if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) arrayZ)) return Null (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return *p;
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
Type *p = &arrayZ[i];
- if (unlikely (p < arrayZ)) return Crap (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) arrayZ)) return Crap (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return *p;
}
@@ -485,10 +504,10 @@ struct UnsizedArrayOf
void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
{ as_array (len).qsort (start, end); }
- bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+ bool serialize (hb_serialize_context_t *c, unsigned int items_len, bool clear = true)
{
TRACE_SERIALIZE (this);
- if (unlikely (!c->extend (this, items_len))) return_trace (false);
+ if (unlikely (!c->extend_size (this, get_size (items_len), clear))) return_trace (false);
return_trace (true);
}
template <typename Iterator,
@@ -496,8 +515,8 @@ struct UnsizedArrayOf
bool serialize (hb_serialize_context_t *c, Iterator items)
{
TRACE_SERIALIZE (this);
- unsigned count = items.len ();
- if (unlikely (!serialize (c, count))) return_trace (false);
+ unsigned count = hb_len (items);
+ if (unlikely (!serialize (c, count, false))) return_trace (false);
/* TODO Umm. Just exhaust the iterator instead? Being extra
* cautious right now.. */
for (unsigned i = 0; i < count; i++, ++items)
@@ -518,7 +537,7 @@ struct UnsizedArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
return_trace (false);
@@ -549,14 +568,16 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_
{
unsigned int i = (unsigned int) i_;
const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
- if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Null (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return this+*p;
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
- if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Crap (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return this+*p;
}
@@ -607,12 +628,14 @@ struct ArrayOf
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= len)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= len)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
@@ -634,14 +657,9 @@ struct ArrayOf
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
- hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
- { return as_array ().sub_array (start_offset, count); }
- hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
- { return as_array ().sub_array (start_offset, count); }
- hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
- { return as_array ().sub_array (start_offset, count); }
- hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
- { return as_array ().sub_array (start_offset, count); }
+ /* Faster range-based for loop. */
+ const Type *begin () const { return arrayZ; }
+ const Type *end () const { return arrayZ + len; }
template <typename T>
Type &lsearch (const T &x, Type &not_found = Crap (Type))
@@ -655,15 +673,15 @@ struct ArrayOf
unsigned int to_store = (unsigned int) -1) const
{ return as_array ().lfind (x, i, not_found, to_store); }
- void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
- { as_array ().qsort (start, end); }
+ void qsort ()
+ { as_array ().qsort (); }
- HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len)
+ HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len, bool clear = true)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
- if (unlikely (!c->extend (this))) return_trace (false);
+ if (unlikely (!c->extend_size (this, get_size (), clear))) return_trace (false);
return_trace (true);
}
template <typename Iterator,
@@ -671,8 +689,8 @@ struct ArrayOf
HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items)
{
TRACE_SERIALIZE (this);
- unsigned count = items.len ();
- if (unlikely (!serialize (c, count))) return_trace (false);
+ unsigned count = hb_len (items);
+ if (unlikely (!serialize (c, count, false))) return_trace (false);
/* TODO Umm. Just exhaust the iterator instead? Being extra
* cautious right now.. */
for (unsigned i = 0; i < count; i++, ++items)
@@ -707,7 +725,7 @@ struct ArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -728,6 +746,7 @@ struct ArrayOf
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
template <typename Type> using Array16Of = ArrayOf<Type, HBUINT16>;
+template <typename Type> using Array24Of = ArrayOf<Type, HBUINT24>;
template <typename Type> using Array32Of = ArrayOf<Type, HBUINT32>;
using PString = ArrayOf<HBUINT8, HBUINT8>;
@@ -737,26 +756,28 @@ template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUI
template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
/* Array of offsets relative to the beginning of the array itself. */
-template <typename Type>
-struct List16OfOffset16To : Array16OfOffset16To<Type>
+template <typename Type, typename OffsetType>
+struct List16OfOffsetTo : ArrayOf<OffsetTo<Type, OffsetType>, HBUINT16>
{
const Type& operator [] (int i_) const
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= this->len)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return this+this->arrayZ[i];
}
const Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= this->len)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return this+this->arrayZ[i];
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- struct List16OfOffset16To<Type> *out = c->serializer->embed (*this);
+ struct List16OfOffsetTo *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
unsigned int count = this->len;
for (unsigned int i = 0; i < count; i++)
@@ -768,10 +789,13 @@ struct List16OfOffset16To : Array16OfOffset16To<Type>
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
{
TRACE_SANITIZE (this);
- return_trace (Array16OfOffset16To<Type>::sanitize (c, this, std::forward<Ts> (ds)...));
+ return_trace ((Array16Of<OffsetTo<Type, OffsetType>>::sanitize (c, this, std::forward<Ts> (ds)...)));
}
};
+template <typename Type>
+using List16OfOffset16To = List16OfOffsetTo<Type, HBUINT16>;
+
/* An array starting at second element. */
template <typename Type, typename LenType=HBUINT16>
struct HeadlessArrayOf
@@ -784,12 +808,14 @@ struct HeadlessArrayOf
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= lenP1 || !i)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i-1];
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= lenP1 || !i)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i-1];
}
unsigned int get_size () const
@@ -808,21 +834,25 @@ struct HeadlessArrayOf
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
- bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+ /* Faster range-based for loop. */
+ const Type *begin () const { return arrayZ; }
+ const Type *end () const { return arrayZ + get_length (); }
+
+ HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned int items_len, bool clear = true)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
- if (unlikely (!c->extend (this))) return_trace (false);
+ if (unlikely (!c->extend_size (this, get_size (), clear))) return_trace (false);
return_trace (true);
}
template <typename Iterator,
hb_requires (hb_is_source_of (Iterator, Type))>
- bool serialize (hb_serialize_context_t *c, Iterator items)
+ HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items)
{
TRACE_SERIALIZE (this);
- unsigned count = items.len ();
- if (unlikely (!serialize (c, count))) return_trace (false);
+ unsigned count = hb_len (items);
+ if (unlikely (!serialize (c, count, false))) return_trace (false);
/* TODO Umm. Just exhaust the iterator instead? Being extra
* cautious right now.. */
for (unsigned i = 0; i < count; i++, ++items)
@@ -835,7 +865,7 @@ struct HeadlessArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -868,12 +898,14 @@ struct ArrayOfM1
{
unsigned int i = (unsigned int) i_;
if (unlikely (i > lenM1)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i > lenM1)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
unsigned int get_size () const
@@ -884,7 +916,7 @@ struct ArrayOfM1
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = lenM1 + 1;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -922,14 +954,9 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
- hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
- { return as_array ().sub_array (start_offset, count); }
- hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
- { return as_array ().sub_array (start_offset, count); }
- hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
- { return as_array ().sub_array (start_offset, count); }
- hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
- { return as_array ().sub_array (start_offset, count); }
+ /* Faster range-based for loop. */
+ const Type *begin () const { return this->arrayZ; }
+ const Type *end () const { return this->arrayZ + this->len; }
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
{
@@ -960,6 +987,7 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
};
template <typename Type> using SortedArray16Of = SortedArrayOf<Type, HBUINT16>;
+template <typename Type> using SortedArray24Of = SortedArrayOf<Type, HBUINT24>;
template <typename Type> using SortedArray32Of = SortedArrayOf<Type, HBUINT32>;
/*
@@ -1052,12 +1080,14 @@ struct VarSizedBinSearchArrayOf
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= get_length ())) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= get_length ())) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
}
unsigned int get_length () const
@@ -1070,7 +1100,7 @@ struct VarSizedBinSearchArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
if (unlikely (!(*this)[i].sanitize (c, std::forward<Ts> (ds)...)))
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh
index c102c15173..f22824fc69 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh
@@ -46,161 +46,45 @@ template<typename Type>
static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset)
{ return offset ? StructAtOffset<Type> (P, offset) : Null (Type); }
-inline unsigned int calcOffSize (unsigned int dataSize)
-{
- unsigned int size = 1;
- unsigned int offset = dataSize + 1;
- while (offset & ~0xFF)
- {
- size++;
- offset >>= 8;
- }
- /* format does not support size > 4; caller should handle it as an error */
- return size;
-}
-
struct code_pair_t
{
hb_codepoint_t code;
hb_codepoint_t glyph;
};
-typedef hb_vector_t<unsigned char> str_buff_t;
-struct str_buff_vec_t : hb_vector_t<str_buff_t>
-{
- unsigned int total_size () const
- {
- unsigned int size = 0;
- for (unsigned int i = 0; i < length; i++)
- size += (*this)[i].length;
- return size;
- }
-
- private:
- typedef hb_vector_t<str_buff_t> SUPER;
-};
+using str_buff_t = hb_vector_t<unsigned char>;
+using str_buff_vec_t = hb_vector_t<str_buff_t>;
/* CFF INDEX */
template <typename COUNT>
struct CFFIndex
{
- static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
- { return offSize * (count + 1); }
-
unsigned int offset_array_size () const
- { return calculate_offset_array_size (offSize, count); }
+ { return offSize * (count + 1); }
CFFIndex *copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
unsigned int size = get_size ();
- CFFIndex *out = c->allocate_size<CFFIndex> (size);
+ CFFIndex *out = c->allocate_size<CFFIndex> (size, false);
if (likely (out))
- memcpy (out, this, size);
+ hb_memcpy (out, this, size);
return_trace (out);
}
- bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
- {
- TRACE_SERIALIZE (this);
- unsigned int size = src.get_size ();
- CFFIndex *dest = c->allocate_size<CFFIndex> (size);
- if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
- return_trace (true);
- }
-
- bool serialize (hb_serialize_context_t *c,
- unsigned int offSize_,
- const byte_str_array_t &byteArray)
- {
- TRACE_SERIALIZE (this);
- if (byteArray.length == 0)
- {
- COUNT *dest = c->allocate_min<COUNT> ();
- if (unlikely (!dest)) return_trace (false);
- *dest = 0;
- }
- else
- {
- /* serialize CFFIndex header */
- if (unlikely (!c->extend_min (this))) return_trace (false);
- this->count = byteArray.length;
- this->offSize = offSize_;
- if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
- return_trace (false);
-
- /* serialize indices */
- unsigned int offset = 1;
- unsigned int i = 0;
- for (; i < byteArray.length; i++)
- {
- set_offset_at (i, offset);
- offset += byteArray[i].get_size ();
- }
- set_offset_at (i, offset);
-
- /* serialize data */
- for (unsigned int i = 0; i < byteArray.length; i++)
- {
- const byte_str_t &bs = byteArray[i];
- unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
- if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &bs[0], bs.length);
- }
- }
- return_trace (true);
- }
-
- bool serialize (hb_serialize_context_t *c,
- unsigned int offSize_,
- const str_buff_vec_t &buffArray)
- {
- byte_str_array_t byteArray;
- byteArray.init ();
- byteArray.resize (buffArray.length);
- for (unsigned int i = 0; i < byteArray.length; i++)
- byteArray[i] = byte_str_t (buffArray[i].arrayZ, buffArray[i].length);
- bool result = this->serialize (c, offSize_, byteArray);
- byteArray.fini ();
- return result;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
bool serialize (hb_serialize_context_t *c,
- Iterator it)
+ const Iterable &iterable)
{
TRACE_SERIALIZE (this);
- if (it.len () == 0)
- {
- COUNT *dest = c->allocate_min<COUNT> ();
- if (unlikely (!dest)) return_trace (false);
- *dest = 0;
- }
- else
- {
- serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; }));
- for (const auto &_ : +it)
- _.copy (c);
- }
+ auto it = hb_iter (iterable);
+ serialize_header(c, + it | hb_map (hb_iter) | hb_map (hb_len));
+ for (const auto &_ : +it)
+ hb_iter (_).copy (c);
return_trace (true);
}
- bool serialize (hb_serialize_context_t *c,
- const byte_str_array_t &byteArray)
- { return serialize (c, + hb_iter (byteArray)); }
-
- bool serialize (hb_serialize_context_t *c,
- const str_buff_vec_t &buffArray)
- {
- auto it =
- + hb_iter (buffArray)
- | hb_map ([] (const str_buff_t &_) { return byte_str_t (_.arrayZ, _.length); })
- ;
- return serialize (c, it);
- }
-
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool serialize_header (hb_serialize_context_t *c,
@@ -209,13 +93,15 @@ struct CFFIndex
TRACE_SERIALIZE (this);
unsigned total = + it | hb_reduce (hb_add, 0);
- unsigned off_size = calcOffSize (total);
+ unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
/* serialize CFFIndex header */
if (unlikely (!c->extend_min (this))) return_trace (false);
this->count = it.len ();
+ if (!this->count) return_trace (true);
+ if (unlikely (!c->extend (this->offSize))) return_trace (false);
this->offSize = off_size;
- if (unlikely (!c->allocate_size<HBUINT8> (off_size * (it.len () + 1))))
+ if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1), false)))
return_trace (false);
/* serialize indices */
@@ -223,16 +109,30 @@ struct CFFIndex
unsigned int i = 0;
for (unsigned _ : +it)
{
- CFFIndex<COUNT>::set_offset_at (i++, offset);
+ set_offset_at (i++, offset);
offset += _;
}
- CFFIndex<COUNT>::set_offset_at (i, offset);
+ set_offset_at (i, offset);
return_trace (true);
}
+ template <typename Iterable,
+ hb_requires (hb_is_iterable (Iterable))>
+ static unsigned total_size (const Iterable &iterable)
+ {
+ auto it = + hb_iter (iterable) | hb_map (hb_iter) | hb_map (hb_len);
+ if (!it) return 0;
+
+ unsigned total = + it | hb_reduce (hb_add, 0);
+ unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
+
+ return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
+ }
+
void set_offset_at (unsigned int index, unsigned int offset)
{
+ assert (index <= count);
HBUINT8 *p = offsets + offSize * index + offSize;
unsigned int size = offSize;
for (; size; size--)
@@ -243,85 +143,77 @@ struct CFFIndex
}
}
+ private:
unsigned int offset_at (unsigned int index) const
{
assert (index <= count);
- const HBUINT8 *p = offsets + offSize * index;
+
unsigned int size = offSize;
- unsigned int offset = 0;
- for (; size; size--)
- offset = (offset << 8) + *p++;
- return offset;
+ const HBUINT8 *p = offsets + size * index;
+ switch (size)
+ {
+ case 1: return * (HBUINT8 *) p;
+ case 2: return * (HBUINT16 *) p;
+ case 3: return * (HBUINT24 *) p;
+ case 4: return * (HBUINT32 *) p;
+ default: return 0;
+ }
}
unsigned int length_at (unsigned int index) const
{
- if (unlikely ((offset_at (index + 1) < offset_at (index)) ||
- (offset_at (index + 1) > offset_at (count))))
+ unsigned offset0 = offset_at (index);
+ unsigned offset1 = offset_at (index + 1);
+ if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
return 0;
- return offset_at (index + 1) - offset_at (index);
+ return offset1 - offset0;
}
const unsigned char *data_base () const
- { return (const unsigned char *) this + min_size + offset_array_size (); }
-
- unsigned int data_size () const { return HBINT8::static_size; }
+ { return (const unsigned char *) this + min_size + offSize.static_size + offset_array_size (); }
+ public:
- byte_str_t operator [] (unsigned int index) const
+ hb_ubytes_t operator [] (unsigned int index) const
{
- if (unlikely (index >= count)) return Null (byte_str_t);
- return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
+ if (unlikely (index >= count)) return hb_ubytes_t ();
+ _hb_compiler_memory_r_barrier ();
+ unsigned length = length_at (index);
+ if (unlikely (!length)) return hb_ubytes_t ();
+ return hb_ubytes_t (data_base () + offset_at (index) - 1, length);
}
unsigned int get_size () const
{
- if (this == &Null (CFFIndex)) return 0;
- if (count > 0)
- return min_size + offset_array_size () + (offset_at (count) - 1);
- return count.static_size; /* empty CFFIndex contains count only */
+ if (count)
+ return min_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1);
+ return min_size; /* empty CFFIndex contains count only */
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely ((c->check_struct (this) && count == 0) || /* empty INDEX */
- (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
- c->check_array (offsets, offSize, count + 1) &&
- c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1))));
- }
-
- protected:
- unsigned int max_offset () const
- {
- unsigned int max = 0;
- for (unsigned int i = 0; i < count + 1u; i++)
- {
- unsigned int off = offset_at (i);
- if (off > max) max = off;
- }
- return max;
+ return_trace (likely (c->check_struct (this) &&
+ (count == 0 || /* empty INDEX */
+ (count < count + 1u &&
+ c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 &&
+ c->check_array (offsets, offSize, count + 1u) &&
+ c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count) - 1)))));
}
public:
COUNT count; /* Number of object data. Note there are (count+1) offsets */
+ private:
HBUINT8 offSize; /* The byte size of each offset in the offsets array. */
HBUINT8 offsets[HB_VAR_ARRAY];
/* The array of (count + 1) offsets into objects array (1-base). */
/* HBUINT8 data[HB_VAR_ARRAY]; Object data */
public:
- DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
+ DEFINE_SIZE_MIN (COUNT::static_size);
};
template <typename COUNT, typename TYPE>
struct CFFIndexOf : CFFIndex<COUNT>
{
- const byte_str_t operator [] (unsigned int index) const
- {
- if (likely (index < CFFIndex<COUNT>::count))
- return byte_str_t (CFFIndex<COUNT>::data_base () + CFFIndex<COUNT>::offset_at (index) - 1, CFFIndex<COUNT>::length_at (index));
- return Null (byte_str_t);
- }
-
template <typename DATA, typename PARAM1, typename PARAM2>
bool serialize (hb_serialize_context_t *c,
unsigned int offSize_,
@@ -336,7 +228,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
if (unlikely (!c->extend_min (this))) return_trace (false);
this->count = dataArrayLen;
this->offSize = offSize_;
- if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
+ if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1), false)))
return_trace (false);
/* serialize indices */
@@ -344,10 +236,10 @@ struct CFFIndexOf : CFFIndex<COUNT>
unsigned int i = 0;
for (; i < dataArrayLen; i++)
{
- CFFIndex<COUNT>::set_offset_at (i, offset);
+ this->set_offset_at (i, offset);
offset += dataSizeArray[i];
}
- CFFIndex<COUNT>::set_offset_at (i, offset);
+ this->set_offset_at (i, offset);
/* serialize data */
for (unsigned int i = 0; i < dataArrayLen; i++)
@@ -380,13 +272,12 @@ struct Dict : UnsizedByteStr
template <typename T, typename V>
static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, V value, op_code_t intOp)
{
- // XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
- if (/*unlikely*/ (!serialize_int<T, V> (c, intOp, value)))
+ if (unlikely ((!serialize_int<T, V> (c, intOp, value))))
return false;
TRACE_SERIALIZE (this);
/* serialize the opcode */
- HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
+ HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op), false);
if (unlikely (!p)) return_trace (false);
if (Is_OpCode_ESC (op))
{
@@ -471,9 +362,8 @@ struct FDSelect0 {
TRACE_SANITIZE (this);
if (unlikely (!(c->check_struct (this))))
return_trace (false);
- for (unsigned int i = 0; i < c->get_num_glyphs (); i++)
- if (unlikely (!fds[i].sanitize (c)))
- return_trace (false);
+ if (unlikely (!c->check_array (fds, c->get_num_glyphs ())))
+ return_trace (false);
return_trace (true);
}
@@ -527,14 +417,20 @@ struct FDSelect3_4
return_trace (true);
}
- hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+ static int _cmp_range (const void *_key, const void *_item)
{
- unsigned int i;
- for (i = 1; i < nRanges (); i++)
- if (glyph < ranges[i].first)
- break;
+ hb_codepoint_t glyph = * (hb_codepoint_t *) _key;
+ FDSelect3_4_Range<GID_TYPE, FD_TYPE> *range = (FDSelect3_4_Range<GID_TYPE, FD_TYPE> *) _item;
+
+ if (glyph < range[0].first) return -1;
+ if (glyph < range[1].first) return 0;
+ return +1;
+ }
- return (hb_codepoint_t) ranges[i - 1].fd;
+ hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+ {
+ auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
+ return range ? range->fd : ranges[nRanges () - 1].fd;
}
GID_TYPE &nRanges () { return ranges.len; }
@@ -557,9 +453,9 @@ struct FDSelect
{
TRACE_SERIALIZE (this);
unsigned int size = src.get_size (num_glyphs);
- FDSelect *dest = c->allocate_size<FDSelect> (size);
+ FDSelect *dest = c->allocate_size<FDSelect> (size, false);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
+ hb_memcpy (dest, &src, size);
return_trace (true);
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
index df4554ac00..5040c74623 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc
@@ -311,10 +311,8 @@ struct bounds_t
struct cff1_extents_param_t
{
- void init (const OT::cff1::accelerator_t *_cff)
+ cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff)
{
- path_open = false;
- cff = _cff;
bounds.init ();
}
@@ -322,7 +320,7 @@ struct cff1_extents_param_t
void end_path () { path_open = false; }
bool is_path_open () const { return path_open; }
- bool path_open;
+ bool path_open = false;
bounds_t bounds;
const OT::cff1::accelerator_t *cff;
@@ -395,12 +393,11 @@ bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, boun
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
unsigned int fd = cff->fdSelect->get_fd (glyph);
- cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp;
- const byte_str_t str = (*cff->charStrings)[glyph];
- interp.env.init (str, *cff, fd);
- interp.env.set_in_seac (in_seac);
- cff1_extents_param_t param;
- param.init (cff);
+ const hb_ubytes_t str = (*cff->charStrings)[glyph];
+ cff1_cs_interp_env_t env (str, *cff, fd);
+ env.set_in_seac (in_seac);
+ cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp (env);
+ cff1_extents_param_t param (cff);
if (unlikely (!interp.interpret (param))) return false;
bounds = param.bounds;
return true;
@@ -425,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)
{
@@ -435,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;
}
@@ -541,10 +540,10 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
unsigned int fd = cff->fdSelect->get_fd (glyph);
- cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp;
- const byte_str_t str = (*cff->charStrings)[glyph];
- interp.env.init (str, *cff, fd);
- interp.env.set_in_seac (in_seac);
+ const hb_ubytes_t str = (*cff->charStrings)[glyph];
+ cff1_cs_interp_env_t env (str, *cff, fd);
+ env.set_in_seac (in_seac);
+ cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp (env);
cff1_path_param_t param (cff, font, draw_session, delta);
if (unlikely (!interp.interpret (param))) return false;
@@ -554,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
@@ -566,18 +574,13 @@ bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h
struct get_seac_param_t
{
- void init (const OT::cff1::accelerator_t *_cff)
- {
- cff = _cff;
- base = 0;
- accent = 0;
- }
+ get_seac_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) {}
bool has_seac () const { return base && accent; }
const OT::cff1::accelerator_t *cff;
- hb_codepoint_t base;
- hb_codepoint_t accent;
+ hb_codepoint_t base = 0;
+ hb_codepoint_t accent = 0;
};
struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
@@ -598,11 +601,10 @@ bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_code
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
unsigned int fd = fdSelect->get_fd (glyph);
- cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp;
- const byte_str_t str = (*charStrings)[glyph];
- interp.env.init (str, *this, fd);
- get_seac_param_t param;
- param.init (this);
+ const hb_ubytes_t str = (*charStrings)[glyph];
+ cff1_cs_interp_env_t env (str, *this, fd);
+ cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp (env);
+ get_seac_param_t param (this);
if (unlikely (!interp.interpret (param))) return false;
if (param.has_seac ())
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 542e3f4de3..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"
@@ -175,7 +176,7 @@ struct Encoding
unsigned int size = src.get_size ();
Encoding *dest = c->allocate_size<Encoding> (size);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
+ hb_memcpy (dest, &src, size);
return_trace (true);
}
@@ -318,14 +319,21 @@ struct Charset0 {
return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
}
- hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
{
+ if (unlikely (glyph >= num_glyphs)) return 0;
if (glyph == 0)
return 0;
else
return sids[glyph - 1];
}
+ void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ {
+ for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
+ mapping->set (gid, sids[gid - 1]);
+ }
+
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
if (sid == 0)
@@ -381,20 +389,38 @@ struct Charset1_2 {
return_trace (true);
}
- hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
{
+ if (unlikely (glyph >= num_glyphs)) return 0;
if (glyph == 0) return 0;
glyph--;
for (unsigned int i = 0;; i++)
{
if (glyph <= ranges[i].nLeft)
- return (hb_codepoint_t)ranges[i].first + glyph;
+ return (hb_codepoint_t) ranges[i].first + glyph;
glyph -= (ranges[i].nLeft + 1);
}
return 0;
}
+ void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ {
+ hb_codepoint_t gid = 1;
+ if (gid >= num_glyphs)
+ return;
+ for (unsigned i = 0;; i++)
+ {
+ hb_codepoint_t sid = ranges[i].first;
+ unsigned count = ranges[i].nLeft + 1;
+ for (unsigned j = 0; j < count; j++)
+ mapping->set (gid++, sid++);
+
+ if (gid >= num_glyphs)
+ break;
+ }
+ }
+
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
if (sid == 0) return 0;
@@ -446,7 +472,7 @@ struct Charset
unsigned int size = src.get_size (num_glyphs);
Charset *dest = c->allocate_size<Charset> (size);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
+ hb_memcpy (dest, &src, size);
return_trace (true);
}
@@ -521,16 +547,26 @@ struct Charset
hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
{
- if (unlikely (glyph >= num_glyphs)) return 0;
switch (format)
{
- case 0: return u.format0.get_sid (glyph);
- case 1: return u.format1.get_sid (glyph);
- case 2: return u.format2.get_sid (glyph);
+ case 0: return u.format0.get_sid (glyph, num_glyphs);
+ case 1: return u.format1.get_sid (glyph, num_glyphs);
+ case 2: return u.format2.get_sid (glyph, num_glyphs);
default:return 0;
}
}
+ void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ {
+ switch (format)
+ {
+ case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+ case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+ case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+ default:return;
+ }
+ }
+
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
switch (format)
@@ -582,7 +618,6 @@ struct CFF1StringIndex : CFF1Index
}
byte_str_array_t bytesArray;
- bytesArray.init ();
if (!bytesArray.resize (sidmap.get_population ()))
return_trace (false);
for (unsigned int i = 0; i < strings.count; i++)
@@ -593,7 +628,6 @@ struct CFF1StringIndex : CFF1Index
}
bool result = CFF1Index::serialize (c, bytesArray);
- bytesArray.fini ();
return_trace (result);
}
};
@@ -602,6 +636,8 @@ struct cff1_top_dict_interp_env_t : num_interp_env_t
{
cff1_top_dict_interp_env_t ()
: num_interp_env_t(), prev_offset(0), last_offset(0) {}
+ cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes)
+ : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {}
unsigned int prev_offset;
unsigned int last_offset;
@@ -776,7 +812,7 @@ struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
break;
default:
- env.last_offset = env.str_ref.offset;
+ env.last_offset = env.str_ref.get_offset ();
top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
/* Record this operand below if stack is empty, otherwise done */
if (!env.argStack.is_empty ()) return;
@@ -866,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:
@@ -879,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:
@@ -1024,11 +1057,10 @@ struct cff1
{ fini (); return; }
{ /* parse top dict */
- const byte_str_t topDictStr = (*topDictIndex)[0];
+ const hb_ubytes_t topDictStr = (*topDictIndex)[0];
if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
- cff1_top_dict_interpreter_t top_interp;
- top_interp.env.init (topDictStr);
- topDict.init ();
+ cff1_top_dict_interp_env_t env (topDictStr);
+ cff1_top_dict_interpreter_t top_interp (env);
if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
}
@@ -1098,20 +1130,21 @@ struct cff1
{
for (unsigned int i = 0; i < fdCount; i++)
{
- byte_str_t fontDictStr = (*fdArray)[i];
+ hb_ubytes_t fontDictStr = (*fdArray)[i];
if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
cff1_font_dict_values_t *font;
- cff1_font_dict_interpreter_t font_interp;
- font_interp.env.init (fontDictStr);
+ cff1_top_dict_interp_env_t env (fontDictStr);
+ cff1_font_dict_interpreter_t font_interp (env);
font = fontDicts.push ();
- if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; }
+ if (unlikely (fontDicts.in_error ())) { fini (); return; }
+
font->init ();
if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
PRIVDICTVAL *priv = &privateDicts[i];
- const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+ const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
- dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
- priv_interp.env.init (privDictStr);
+ num_interp_env_t env2 (privDictStr);
+ dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
priv->init ();
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
@@ -1126,10 +1159,10 @@ struct cff1
cff1_top_dict_values_t *font = &topDict;
PRIVDICTVAL *priv = &privateDicts[0];
- const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+ const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
- dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
- priv_interp.env.init (privDictStr);
+ num_interp_env_t env (privDictStr);
+ dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
priv->init ();
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
@@ -1194,6 +1227,19 @@ struct cff1
}
}
+ hb_map_t *create_glyph_to_sid_map () const
+ {
+ if (charset != &Null (Charset))
+ {
+ hb_map_t *mapping = hb_map_create ();
+ mapping->set (0, 0);
+ charset->collect_glyph_to_sid_map (mapping, num_glyphs);
+ return mapping;
+ }
+ else
+ return nullptr;
+ }
+
hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
{
if (charset != &Null (Charset))
@@ -1245,10 +1291,10 @@ struct cff1
}
protected:
- hb_blob_t *blob = nullptr;
hb_sanitize_context_t sc;
public:
+ hb_blob_t *blob = nullptr;
const Encoding *encoding = nullptr;
const Charset *charset = nullptr;
const CFF1NameIndex *nameIndex = nullptr;
@@ -1274,30 +1320,20 @@ struct cff1
{
SUPER::init (face);
+ glyph_names.set_relaxed (nullptr);
+
if (!is_valid ()) return;
if (is_CID ()) return;
- /* fill glyph_names */
- for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
- {
- hb_codepoint_t sid = glyph_to_sid (gid);
- gname_t gname;
- gname.sid = sid;
- if (sid < cff1_std_strings_length)
- gname.name = cff1_std_strings (sid);
- else
- {
- byte_str_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
- gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length);
- }
- if (unlikely (!gname.name.arrayZ)) { fini (); return; }
- glyph_names.push (gname);
- }
- glyph_names.qsort ();
}
~accelerator_t ()
{
- glyph_names.fini ();
+ hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed ();
+ if (names)
+ {
+ names->fini ();
+ hb_free (names);
+ }
SUPER::fini ();
}
@@ -1305,9 +1341,10 @@ struct cff1
bool get_glyph_name (hb_codepoint_t glyph,
char *buf, unsigned int buf_len) const
{
- if (!buf) return true;
+ if (unlikely (glyph >= num_glyphs)) return false;
if (unlikely (!is_valid ())) return false;
if (is_CID()) return false;
+ if (unlikely (!buf_len)) return true;
hb_codepoint_t sid = glyph_to_sid (glyph);
const char *str;
size_t str_len;
@@ -1319,7 +1356,7 @@ struct cff1
}
else
{
- byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
+ hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
str = (const char *)ubyte_str.arrayZ;
str_len = ubyte_str.length;
}
@@ -1333,11 +1370,53 @@ struct cff1
bool get_glyph_from_name (const char *name, int len,
hb_codepoint_t *glyph) const
{
+ if (unlikely (!is_valid ())) return false;
+ if (is_CID()) return false;
if (len < 0) len = strlen (name);
if (unlikely (!len)) return false;
+ retry:
+ hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire ();
+ if (unlikely (!names))
+ {
+ names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
+ if (likely (names))
+ {
+ names->init ();
+ /* TODO */
+
+ /* fill glyph names */
+ for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
+ {
+ hb_codepoint_t sid = glyph_to_sid (gid);
+ gname_t gname;
+ gname.sid = sid;
+ if (sid < cff1_std_strings_length)
+ gname.name = cff1_std_strings (sid);
+ else
+ {
+ hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
+ gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length);
+ }
+ if (unlikely (!gname.name.arrayZ))
+ gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */
+ names->push (gname);
+ }
+ names->qsort ();
+ }
+ if (unlikely (!glyph_names.cmpexch (nullptr, names)))
+ {
+ if (names)
+ {
+ names->fini ();
+ hb_free (names);
+ }
+ goto retry;
+ }
+ }
+
gname_t key = { hb_bytes_t (name, len), 0 };
- const gname_t *gname = glyph_names.bsearch (key);
+ const gname_t *gname = names ? names->bsearch (key) : nullptr;
if (!gname) return false;
hb_codepoint_t gid = sid_to_glyph (gname->sid);
if (!gid && gname->sid) return false;
@@ -1346,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;
@@ -1359,7 +1439,7 @@ struct cff1
{
const gname_t *a = (const gname_t *)a_;
const gname_t *b = (const gname_t *)b_;
- int minlen = hb_min (a->name.length, b->name.length);
+ unsigned minlen = hb_min (a->name.length, b->name.length);
int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
if (ret) return ret;
return a->name.length - b->name.length;
@@ -1368,7 +1448,7 @@ struct cff1
int cmp (const gname_t &a) const { return cmp (&a, this); }
};
- hb_sorted_vector_t<gname_t> glyph_names;
+ mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
};
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 817fe064ce..7955565551 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc
@@ -36,9 +36,8 @@ using namespace CFF;
struct cff2_extents_param_t
{
- void init ()
+ cff2_extents_param_t ()
{
- path_open = false;
min_x.set_int (INT_MAX);
min_y.set_int (INT_MAX);
max_x.set_int (INT_MIN);
@@ -57,22 +56,22 @@ struct cff2_extents_param_t
if (pt.y > max_y) max_y = pt.y;
}
- bool path_open;
+ bool path_open = false;
number_t min_x;
number_t min_y;
number_t max_x;
number_t max_y;
};
-struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, cff2_extents_param_t>
+struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t<number_t>, cff2_extents_param_t>
{
- static void moveto (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt)
+ static void moveto (cff2_cs_interp_env_t<number_t> &env, cff2_extents_param_t& param, const point_t &pt)
{
param.end_path ();
env.moveto (pt);
}
- static void line (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1)
+ static void line (cff2_cs_interp_env_t<number_t> &env, cff2_extents_param_t& param, const point_t &pt1)
{
if (!param.is_path_open ())
{
@@ -83,7 +82,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
param.update_bounds (env.get_pt ());
}
- static void curve (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+ static void curve (cff2_cs_interp_env_t<number_t> &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
{
if (!param.is_path_open ())
{
@@ -98,7 +97,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
}
};
-struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_extents_param_t, cff2_path_procs_extents_t> {};
+struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_extents_param_t, number_t, cff2_path_procs_extents_t> {};
bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
hb_codepoint_t glyph,
@@ -112,11 +111,10 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
unsigned int fd = fdSelect->get_fd (glyph);
- cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t> interp;
- const byte_str_t str = (*charStrings)[glyph];
- interp.env.init (str, *this, fd, font->coords, font->num_coords);
+ const hb_ubytes_t str = (*charStrings)[glyph];
+ cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords);
+ cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t, number_t> interp (env);
cff2_extents_param_t param;
- param.init ();
if (unlikely (!interp.interpret (param))) return false;
if (param.min_x >= param.max_x)
@@ -126,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)
{
@@ -136,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;
}
@@ -169,28 +178,28 @@ struct cff2_path_param_t
hb_font_t *font;
};
-struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t, cff2_path_param_t>
+struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t<number_t>, cff2_path_param_t>
{
- static void moveto (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt)
+ static void moveto (cff2_cs_interp_env_t<number_t> &env, cff2_path_param_t& param, const point_t &pt)
{
param.move_to (pt);
env.moveto (pt);
}
- static void line (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1)
+ static void line (cff2_cs_interp_env_t<number_t> &env, cff2_path_param_t& param, const point_t &pt1)
{
param.line_to (pt1);
env.moveto (pt1);
}
- static void curve (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+ static void curve (cff2_cs_interp_env_t<number_t> &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
{
param.cubic_to (pt1, pt2, pt3);
env.moveto (pt3);
}
};
-struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
+struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, number_t, cff2_path_procs_path_t> {};
bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
@@ -202,9 +211,9 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
unsigned int fd = fdSelect->get_fd (glyph);
- cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
- const byte_str_t str = (*charStrings)[glyph];
- interp.env.init (str, *this, fd, font->coords, font->num_coords);
+ const hb_ubytes_t str = (*charStrings)[glyph];
+ cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords);
+ cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t, number_t> interp (env);
cff2_path_param_t param (font, draw_session);
if (unlikely (!interp.interpret (param))) return false;
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 b77e7f53fa..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 {
@@ -56,7 +57,7 @@ struct CFF2FDSelect
unsigned int size = src.get_size (num_glyphs);
CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
+ hb_memcpy (dest, &src, size);
return_trace (true);
}
@@ -124,7 +125,7 @@ struct CFF2VariationStore
unsigned int size_ = varStore->get_size ();
CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
if (unlikely (!dest)) return_trace (false);
- memcpy (dest, varStore, size_);
+ hb_memcpy (dest, varStore, size_);
return_trace (true);
}
@@ -247,12 +248,8 @@ typedef cff2_private_dict_values_base_t<num_dict_val_t> cff2_private_dict_values
struct cff2_priv_dict_interp_env_t : num_interp_env_t
{
- void init (const byte_str_t &str)
- {
- num_interp_env_t::init (str);
- ivs = 0;
- seen_vsindex = false;
- }
+ cff2_priv_dict_interp_env_t (const hb_ubytes_t &str) :
+ num_interp_env_t (str) {}
void process_vsindex ()
{
@@ -267,8 +264,8 @@ struct cff2_priv_dict_interp_env_t : num_interp_env_t
void set_ivs (unsigned int ivs_) { ivs = ivs_; }
protected:
- unsigned int ivs;
- bool seen_vsindex;
+ unsigned int ivs = 0;
+ bool seen_vsindex = false;
};
struct cff2_private_dict_opset_t : dict_opset_t
@@ -286,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:
@@ -415,10 +409,10 @@ struct cff2
goto fail;
{ /* parse top dict */
- byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize);
+ hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize);
if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
- cff2_top_dict_interpreter_t top_interp;
- top_interp.env.init (topDictStr);
+ num_interp_env_t env (topDictStr);
+ cff2_top_dict_interpreter_t top_interp (env);
topDict.init ();
if (unlikely (!top_interp.interpret (topDict))) goto fail;
}
@@ -447,20 +441,20 @@ struct cff2
/* parse font dicts and gather private dicts */
for (unsigned int i = 0; i < fdCount; i++)
{
- const byte_str_t fontDictStr = (*fdArray)[i];
+ const hb_ubytes_t fontDictStr = (*fdArray)[i];
if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
cff2_font_dict_values_t *font;
- cff2_font_dict_interpreter_t font_interp;
- font_interp.env.init (fontDictStr);
+ num_interp_env_t env (fontDictStr);
+ cff2_font_dict_interpreter_t font_interp (env);
font = fontDicts.push ();
if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail;
font->init ();
if (unlikely (!font_interp.interpret (*font))) goto fail;
- const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
+ const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
- dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp;
- priv_interp.env.init(privDictStr);
+ cff2_priv_dict_interp_env_t env2 (privDictStr);
+ dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2);
privateDicts[i].init ();
if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
@@ -487,13 +481,18 @@ struct cff2
blob = nullptr;
}
+ hb_map_t *create_glyph_to_sid_map () const
+ {
+ return nullptr;
+ }
+
bool is_valid () const { return blob; }
protected:
- hb_blob_t *blob = nullptr;
hb_sanitize_context_t sc;
public:
+ hb_blob_t *blob = nullptr;
cff2_top_dict_values_t topDict;
const CFF2Subrs *globalSubrs = nullptr;
const CFF2VariationStore *varStore = nullptr;
@@ -515,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 a8747ee5a1..f5a03d2b00 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh
@@ -27,8 +27,11 @@
#ifndef HB_OT_CMAP_TABLE_HH
#define HB_OT_CMAP_TABLE_HH
+#include "hb-ot-os2-table.hh"
+#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
@@ -44,7 +47,7 @@ struct CmapSubtableFormat0
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -109,22 +112,26 @@ struct CmapSubtableFormat4
while (it) {
// Start a new range
- start_cp = (*it).first;
- prev_run_start_cp = (*it).first;
- run_start_cp = (*it).first;
- end_cp = (*it).first;
- last_gid = (*it).second;
- run_length = 1;
- prev_delta = 0;
-
- delta = (*it).second - (*it).first;
+ {
+ const auto& pair = *it;
+ start_cp = pair.first;
+ prev_run_start_cp = start_cp;
+ run_start_cp = start_cp;
+ end_cp = start_cp;
+ last_gid = pair.second;
+ run_length = 1;
+ prev_delta = 0;
+ }
+
+ delta = last_gid - start_cp;
mode = FIRST_SUB_RANGE;
it++;
while (it) {
// Process range
- hb_codepoint_t next_cp = (*it).first;
- hb_codepoint_t next_gid = (*it).second;
+ const auto& pair = *it;
+ hb_codepoint_t next_cp = pair.first;
+ hb_codepoint_t next_gid = pair.second;
if (next_cp != end_cp + 1) {
// Current range is over, stop processing.
break;
@@ -282,23 +289,22 @@ struct CmapSubtableFormat4
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_iterator (Iterator))>
HBUINT16* serialize_rangeoffset_glyid (hb_serialize_context_t *c,
- Iterator it,
+ Iterator it,
HBUINT16 *endCode,
HBUINT16 *startCode,
HBINT16 *idDelta,
unsigned segcount)
{
- hb_hashmap_t<hb_codepoint_t, hb_codepoint_t> cp_to_gid;
- + it | hb_sink (cp_to_gid);
+ hb_map_t cp_to_gid { it };
HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
for (unsigned i : + hb_range (segcount)
- | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
+ | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
{
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++)
@@ -323,22 +329,31 @@ struct CmapSubtableFormat4
{ return _.first <= 0xFFFF; })
;
- if (format4_iter.len () == 0) return;
+ if (!format4_iter) return;
unsigned table_initpos = c->length ();
if (unlikely (!c->extend_min (this))) return;
this->format = 4;
+ hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> cp_to_gid {
+ format4_iter
+ };
+
//serialize endCode[], startCode[], idDelta[]
HBUINT16* endCode = c->start_embed<HBUINT16> ();
- unsigned segcount = serialize_find_segcount (format4_iter);
- if (unlikely (!serialize_start_end_delta_arrays (c, format4_iter, segcount)))
+ unsigned segcount = serialize_find_segcount (cp_to_gid.iter());
+ if (unlikely (!serialize_start_end_delta_arrays (c, cp_to_gid.iter(), segcount)))
return;
HBUINT16 *startCode = endCode + segcount + 1;
HBINT16 *idDelta = ((HBINT16*)startCode) + segcount;
- HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
+ HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c,
+ cp_to_gid.iter (),
+ endCode,
+ startCode,
+ idDelta,
+ segcount);
if (unlikely (!c->check_success (idRangeOffset))) return;
this->length = c->length () - table_initpos;
@@ -401,7 +416,7 @@ struct CmapSubtableFormat4
2,
_hb_cmp_method<hb_codepoint_t, CustomRange, unsigned>,
this->segCount + 1);
- if (!found)
+ if (unlikely (!found))
return false;
unsigned int i = found - endCount;
@@ -421,7 +436,7 @@ struct CmapSubtableFormat4
gid += this->idDelta[i];
}
gid &= 0xFFFFu;
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -440,14 +455,14 @@ struct CmapSubtableFormat4
hb_codepoint_t start = this->startCount[i];
hb_codepoint_t end = this->endCount[i];
unsigned int rangeOffset = this->idRangeOffset[i];
+ out->add_range(start, end);
if (rangeOffset == 0)
{
for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
{
hb_codepoint_t gid = (codepoint + this->idDelta[i]) & 0xFFFFu;
if (unlikely (!gid))
- continue;
- out->add (codepoint);
+ out->del(codepoint);
}
}
else
@@ -456,11 +471,13 @@ struct CmapSubtableFormat4
{
unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
if (unlikely (index >= this->glyphIdArrayLength))
+ {
+ out->del_range (codepoint, end);
break;
+ }
hb_codepoint_t gid = this->glyphIdArray[index];
if (unlikely (!gid))
- continue;
- out->add (codepoint);
+ out->del(codepoint);
}
}
}
@@ -469,6 +486,8 @@ struct CmapSubtableFormat4
void collect_mapping (hb_set_t *unicodes, /* OUT */
hb_map_t *mapping /* OUT */) const
{
+ // TODO(grieger): optimize similar to collect_unicodes
+ // (ie. use add_range())
unsigned count = this->segCount;
if (count && this->startCount[count - 1] == 0xFFFFu)
count--; /* Skip sentinel segment. */
@@ -620,7 +639,7 @@ struct CmapSubtableTrimmed
{
/* Rely on our implicit array bound-checking. */
hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -674,7 +693,7 @@ struct CmapSubtableTrimmed
};
struct CmapSubtableFormat6 : CmapSubtableTrimmed<HBUINT16> {};
-struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32 > {};
+struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32> {};
template <typename T>
struct CmapSubtableLongSegmented
@@ -684,7 +703,7 @@ struct CmapSubtableLongSegmented
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint);
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -722,11 +741,19 @@ struct CmapSubtableLongSegmented
hb_map_t *mapping, /* OUT */
unsigned num_glyphs) const
{
+ hb_codepoint_t last_end = 0;
for (unsigned i = 0; i < this->groups.len; i++)
{
hb_codepoint_t start = this->groups[i].startCharCode;
hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
(hb_codepoint_t) HB_UNICODE_MAX);
+ if (unlikely (start > end || start < last_end)) {
+ // Range is not in order and is invalid, skip it.
+ continue;
+ }
+ last_end = end;
+
+
hb_codepoint_t gid = this->groups[i].glyphID;
if (!gid)
{
@@ -778,16 +805,16 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
void serialize (hb_serialize_context_t *c,
Iterator it)
{
- if (it.len () == 0) return;
+ if (!it) return;
unsigned table_initpos = c->length ();
if (unlikely (!c->extend_min (this))) return;
- hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
+ hb_codepoint_t startCharCode = (hb_codepoint_t) -1, endCharCode = (hb_codepoint_t) -1;
hb_codepoint_t glyphID = 0;
for (const auto& _ : +it)
{
- if (startCharCode == 0xFFFF)
+ if (startCharCode == (hb_codepoint_t) -1)
{
startCharCode = _.first;
endCharCode = _.first;
@@ -818,7 +845,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
this->format = 12;
this->reserved = 0;
this->length = c->length () - table_initpos;
- this->groups.len = (this->length - min_size)/CmapSubtableLongGroup::static_size;
+ this->groups.len = (this->length - min_size) / CmapSubtableLongGroup::static_size;
}
static size_t get_sub_table_size (const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
@@ -883,7 +910,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
hb_codepoint_t first = arrayZ[i].startUnicodeValue;
hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
(hb_codepoint_t) HB_UNICODE_MAX);
- out->add_range (first, hb_min (last, 0x10FFFFu));
+ out->add_range (first, last);
}
}
@@ -899,37 +926,75 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
if (unlikely (!c->copy<HBUINT32> (len))) return nullptr;
unsigned init_len = c->length ();
- hb_codepoint_t lastCode = HB_MAP_VALUE_INVALID;
- int count = -1;
-
- for (const UnicodeValueRange& _ : as_array ())
+ if (this->len > unicodes->get_population () * hb_bit_storage ((unsigned) this->len))
{
- for (const unsigned addcnt : hb_range ((unsigned) _.additionalCount + 1))
+ hb_codepoint_t start = HB_SET_VALUE_INVALID;
+ hb_codepoint_t end = HB_SET_VALUE_INVALID;
+
+ for (hb_codepoint_t u = HB_SET_VALUE_INVALID;
+ unicodes->next (&u);)
{
- unsigned curEntry = (unsigned) _.startUnicodeValue + addcnt;
- if (!unicodes->has (curEntry)) continue;
- count += 1;
- if (lastCode == HB_MAP_VALUE_INVALID)
- lastCode = curEntry;
- else if (lastCode + count != curEntry)
+ if (!as_array ().bsearch (u))
+ continue;
+ if (start == HB_SET_VALUE_INVALID)
{
+ start = u;
+ end = start - 1;
+ }
+ if (end + 1 != u || end - start == 255)
+ {
UnicodeValueRange rec;
- rec.startUnicodeValue = lastCode;
- rec.additionalCount = count - 1;
+ rec.startUnicodeValue = start;
+ rec.additionalCount = end - start;
c->copy<UnicodeValueRange> (rec);
-
- lastCode = curEntry;
- count = 0;
+ start = u;
}
+ end = u;
+ }
+ if (start != HB_SET_VALUE_INVALID)
+ {
+ UnicodeValueRange rec;
+ rec.startUnicodeValue = start;
+ rec.additionalCount = end - start;
+ c->copy<UnicodeValueRange> (rec);
}
- }
- if (lastCode != HB_MAP_VALUE_INVALID)
+ }
+ else
{
- UnicodeValueRange rec;
- rec.startUnicodeValue = lastCode;
- rec.additionalCount = count;
- c->copy<UnicodeValueRange> (rec);
+ hb_codepoint_t lastCode = HB_SET_VALUE_INVALID;
+ int count = -1;
+
+ for (const UnicodeValueRange& _ : *this)
+ {
+ hb_codepoint_t curEntry = (hb_codepoint_t) (_.startUnicodeValue - 1);
+ hb_codepoint_t end = curEntry + _.additionalCount + 2;
+
+ for (; unicodes->next (&curEntry) && curEntry < end;)
+ {
+ count += 1;
+ if (lastCode == HB_SET_VALUE_INVALID)
+ lastCode = curEntry;
+ else if (lastCode + count != curEntry)
+ {
+ UnicodeValueRange rec;
+ rec.startUnicodeValue = lastCode;
+ rec.additionalCount = count - 1;
+ c->copy<UnicodeValueRange> (rec);
+
+ lastCode = curEntry;
+ count = 0;
+ }
+ }
+ }
+
+ if (lastCode != HB_MAP_VALUE_INVALID)
+ {
+ UnicodeValueRange rec;
+ rec.startUnicodeValue = lastCode;
+ rec.additionalCount = count;
+ c->copy<UnicodeValueRange> (rec);
+ }
}
if (c->length () - init_len == 0)
@@ -1350,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;
}
}
@@ -1448,17 +1513,127 @@ struct EncodingRecord
DEFINE_SIZE_STATIC (8);
};
+struct cmap;
+
+struct SubtableUnicodesCache {
+
+ private:
+ hb_blob_ptr_t<cmap> base_blob;
+ const char* base;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> cached_unicodes;
+
+ public:
+
+ static SubtableUnicodesCache* create (hb_blob_ptr_t<cmap> source_table)
+ {
+ SubtableUnicodesCache* cache =
+ (SubtableUnicodesCache*) hb_malloc (sizeof(SubtableUnicodesCache));
+ new (cache) SubtableUnicodesCache (source_table);
+ return cache;
+ }
+
+ static void destroy (void* value) {
+ if (!value) return;
+
+ SubtableUnicodesCache* cache = (SubtableUnicodesCache*) value;
+ cache->~SubtableUnicodesCache ();
+ hb_free (cache);
+ }
+
+ SubtableUnicodesCache(const void* cmap_base)
+ : base_blob(),
+ base ((const char*) cmap_base),
+ cached_unicodes ()
+ {}
+
+ SubtableUnicodesCache(hb_blob_ptr_t<cmap> base_blob_)
+ : base_blob(base_blob_),
+ base ((const char *) base_blob.get()),
+ cached_unicodes ()
+ {}
+
+ ~SubtableUnicodesCache()
+ {
+ base_blob.destroy ();
+ }
+
+ bool same_base(const void* other) const
+ {
+ return other == (const void*) base;
+ }
+
+ const hb_set_t* set_for (const EncodingRecord* record,
+ SubtableUnicodesCache& mutable_cache) const
+ {
+ if (cached_unicodes.has ((unsigned) ((const char *) record - base)))
+ return cached_unicodes.get ((unsigned) ((const char *) record - base));
+
+ return mutable_cache.set_for (record);
+ }
+
+ const hb_set_t* set_for (const EncodingRecord* record)
+ {
+ if (!cached_unicodes.has ((unsigned) ((const char *) record - base)))
+ {
+ hb_set_t *s = hb_set_create ();
+ if (unlikely (s->in_error ()))
+ return hb_set_get_empty ();
+
+ (base+record->subtable).collect_unicodes (s);
+
+ if (unlikely (!cached_unicodes.set ((unsigned) ((const char *) record - base), hb::unique_ptr<hb_set_t> {s})))
+ return hb_set_get_empty ();
+
+ return s;
+ }
+ return cached_unicodes.get ((unsigned) ((const char *) record - base));
+ }
+
+};
+
+static inline uint_fast16_t
+_hb_symbol_pua_map (unsigned codepoint)
+{
+ if (codepoint <= 0x00FFu)
+ {
+ /* For symbol-encoded OpenType fonts, we duplicate the
+ * U+F000..F0FF range at U+0000..U+00FF. That's what
+ * Windows seems to do, and that's hinted about at:
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
+ * under "Non-Standard (Symbol) Fonts". */
+ return 0xF000u + codepoint;
+ }
+ return 0;
+}
+
struct cmap
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
+
+ static SubtableUnicodesCache* create_filled_cache(hb_blob_ptr_t<cmap> source_table) {
+ const cmap* cmap = source_table.get();
+ auto it =
+ + hb_iter (cmap->encodingRecord)
+ | hb_filter ([&](const EncodingRecord& _) {
+ return cmap::filter_encoding_records_for_subset (cmap, _);
+ })
+ ;
+
+ SubtableUnicodesCache* cache = SubtableUnicodesCache::create(source_table);
+ for (const EncodingRecord& _ : it)
+ cache->set_for(&_); // populate the cache for this encoding record.
+
+ return cache;
+ }
+
template<typename Iterator, typename EncodingRecIter,
hb_requires (hb_is_iterator (EncodingRecIter))>
bool serialize (hb_serialize_context_t *c,
Iterator it,
EncodingRecIter encodingrec_iter,
const void *base,
- const hb_subset_plan_t *plan,
+ hb_subset_plan_t *plan,
bool drop_format_4 = false)
{
if (unlikely (!c->extend_min ((*this)))) return false;
@@ -1467,6 +1642,14 @@ struct cmap
unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
auto snap = c->snapshot ();
+ SubtableUnicodesCache local_unicodes_cache (base);
+ const SubtableUnicodesCache* unicodes_cache = &local_unicodes_cache;
+
+ if (plan->accelerator &&
+ plan->accelerator->cmap_cache &&
+ plan->accelerator->cmap_cache->same_base (base))
+ unicodes_cache = plan->accelerator->cmap_cache;
+
for (const EncodingRecord& _ : encodingrec_iter)
{
if (c->in_error ())
@@ -1475,12 +1658,11 @@ struct cmap
unsigned format = (base+_.subtable).u.format;
if (format != 4 && format != 12 && format != 14) continue;
- hb_set_t unicodes_set;
- (base+_.subtable).collect_unicodes (&unicodes_set);
+ const hb_set_t* unicodes_set = unicodes_cache->set_for (&_, local_unicodes_cache);
if (!drop_format_4 && format == 4)
{
- c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
+ c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 4u, base, plan, &format4objidx);
if (c->in_error () && c->only_overflow ())
{
// cmap4 overflowed, reset and retry serialization without format 4 subtables.
@@ -1495,8 +1677,14 @@ struct cmap
else if (format == 12)
{
- if (_can_drop (_, unicodes_set, base, + it | hb_map (hb_first), encodingrec_iter)) continue;
- c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
+ if (_can_drop (_,
+ *unicodes_set,
+ base,
+ *unicodes_cache,
+ local_unicodes_cache,
+ + it | hb_map (hb_first), encodingrec_iter))
+ continue;
+ c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx);
}
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
}
@@ -1514,6 +1702,8 @@ struct cmap
bool _can_drop (const EncodingRecord& cmap12,
const hb_set_t& cmap12_unicodes,
const void* base,
+ const SubtableUnicodesCache& unicodes_cache,
+ SubtableUnicodesCache& local_unicodes_cache,
Iterator subset_unicodes,
EncodingRecordIterator encoding_records)
{
@@ -1544,11 +1734,10 @@ struct cmap
|| (base+_.subtable).get_language() != target_language)
continue;
- hb_set_t sibling_unicodes;
- (base+_.subtable).collect_unicodes (&sibling_unicodes);
+ const hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_, local_unicodes_cache);
auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes);
- auto sibling = + subset_unicodes | hb_filter (sibling_unicodes);
+ auto sibling = + subset_unicodes | hb_filter (*sibling_unicodes);
for (; cmap12 && sibling; cmap12++, sibling++)
{
unsigned a = *cmap12;
@@ -1582,17 +1771,9 @@ struct cmap
auto encodingrec_iter =
+ hb_iter (encodingRecord)
- | hb_filter ([&] (const EncodingRecord& _)
- {
- if ((_.platformID == 0 && _.encodingID == 3) ||
- (_.platformID == 0 && _.encodingID == 4) ||
- (_.platformID == 3 && _.encodingID == 1) ||
- (_.platformID == 3 && _.encodingID == 10) ||
- (this + _.subtable).u.format == 14)
- return true;
-
- return false;
- })
+ | hb_filter ([&](const EncodingRecord& _) {
+ return cmap::filter_encoding_records_for_subset (this, _);
+ })
;
if (unlikely (!encodingrec_iter.len ())) return_trace (false);
@@ -1616,18 +1797,16 @@ struct cmap
if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
auto it =
- + hb_iter (c->plan->unicodes)
- | hb_map ([&] (hb_codepoint_t _)
- {
- hb_codepoint_t new_gid = HB_MAP_VALUE_INVALID;
- c->plan->new_gid_for_codepoint (_, &new_gid);
- return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, new_gid);
- })
+ + c->plan->unicode_to_new_gid_list.iter ()
| hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
{ return (_.second != HB_MAP_VALUE_INVALID); })
;
- return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan));
+ return_trace (cmap_prime->serialize (c->serializer,
+ it,
+ encodingrec_iter,
+ this,
+ c->plan));
}
const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
@@ -1663,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);
@@ -1677,7 +1858,24 @@ struct cmap
this->get_glyph_data = subtable;
if (unlikely (symbol))
- this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable>;
+ {
+ switch ((unsigned) face->table.OS2->get_font_page ()) {
+ case OS2::font_page_t::FONT_PAGE_NONE:
+ this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_symbol_pua_map>;
+ break;
+#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK
+ case OS2::font_page_t::FONT_PAGE_SIMP_ARABIC:
+ this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_arabic_pua_simp_map>;
+ break;
+ case OS2::font_page_t::FONT_PAGE_TRAD_ARABIC:
+ this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_arabic_pua_trad_map>;
+ break;
+#endif
+ default:
+ this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
+ break;
+ }
+ }
else
{
switch (subtable->u.format) {
@@ -1700,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);
@@ -1730,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,
@@ -1741,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
@@ -1759,6 +1975,7 @@ struct cmap
typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph);
+ typedef uint_fast16_t (*hb_pua_remap_func_t) (unsigned);
template <typename Type>
HB_INTERNAL static bool get_glyph_from (const void *obj,
@@ -1769,7 +1986,7 @@ struct cmap
return typed_obj->get_glyph (codepoint, glyph);
}
- template <typename Type>
+ template <typename Type, hb_pua_remap_func_t remap>
HB_INTERNAL static bool get_glyph_from_symbol (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph)
@@ -1778,15 +1995,8 @@ struct cmap
if (likely (typed_obj->get_glyph (codepoint, glyph)))
return true;
- if (codepoint <= 0x00FFu)
- {
- /* For symbol-encoded OpenType fonts, we duplicate the
- * U+F000..F0FF range at U+0000..U+00FF. That's what
- * Windows seems to do, and that's hinted about at:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
- * under "Non-Standard (Symbol) Fonts". */
- return typed_obj->get_glyph (0xF000u + codepoint, glyph);
- }
+ if (hb_codepoint_t c = remap (codepoint))
+ return typed_obj->get_glyph (c, glyph);
return false;
}
@@ -1852,6 +2062,19 @@ struct cmap
encodingRecord.sanitize (c, this));
}
+ private:
+
+ static bool filter_encoding_records_for_subset(const cmap* cmap,
+ const EncodingRecord& _)
+ {
+ return
+ (_.platformID == 0 && _.encodingID == 3) ||
+ (_.platformID == 0 && _.encodingID == 4) ||
+ (_.platformID == 3 && _.encodingID == 1) ||
+ (_.platformID == 3 && _.encodingID == 10) ||
+ (cmap + _.subtable).u.format == 14;
+ }
+
protected:
HBUINT16 version; /* Table version number (0). */
SortedArray16Of<EncodingRecord>
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc
index 16077765bd..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"
/**
@@ -61,7 +61,7 @@
*
* Tests whether a face includes a `CPAL` color-palette table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.1.0
*/
@@ -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,16 +194,53 @@ 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
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.1.0
*/
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);
}
/**
@@ -239,7 +280,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
*
* Tests whether a face includes any `SVG` glyph images.
*
- * Return value: %true if data found, %false otherwise.
+ * Return value: `true` if data found, `false` otherwise.
*
* Since: 2.1.0
*/
@@ -279,7 +320,7 @@ hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
*
* Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables).
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.1.0
*/
@@ -295,8 +336,8 @@ hb_ot_color_has_png (hb_face_t *face)
* @glyph: a glyph index
*
* Fetches the PNG image for a glyph. This function takes a font object, not a face object,
- * as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font
- * object. If UPEM is unset, the blob returned will be the largest PNG available.
+ * as input. To get an optimally sized PNG blob, the PPEM values must be set on the @font
+ * object. If PPEM is unset, the blob returned will be the largest PNG available.
*
* If the glyph has no PNG image, the singleton empty blob is returned.
*
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-color.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-color.h
index c23ce4de44..22ee497e38 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-color.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-color.h
@@ -102,6 +102,10 @@ hb_ot_color_has_layers (hb_face_t *face);
*
* Pairs of glyph and color index.
*
+ * A color index of 0xFFFF does not refer to a palette
+ * color, but indicates that the foreground color should
+ * be used.
+ *
* Since: 2.1.0
**/
typedef struct hb_ot_color_layer_t {
@@ -116,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-table-list.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-face-table-list.hh
index c05034b3bb..c9da36c1bb 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-face-table-list.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-face-table-list.hh
@@ -56,9 +56,9 @@ HB_OT_CORE_TABLE (OT, maxp)
#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
HB_OT_ACCELERATOR (OT, cmap)
#endif
-HB_OT_TABLE (OT, hhea)
+HB_OT_CORE_TABLE (OT, hhea)
HB_OT_ACCELERATOR (OT, hmtx)
-HB_OT_TABLE (OT, OS2)
+HB_OT_CORE_TABLE (OT, OS2)
#if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS) || !defined(HB_NO_STYLE)
HB_OT_ACCELERATOR (OT, post)
#endif
@@ -66,7 +66,7 @@ HB_OT_ACCELERATOR (OT, post)
HB_OT_ACCELERATOR (OT, name)
#endif
#ifndef HB_NO_STYLE
-HB_OT_TABLE (OT, STAT)
+HB_OT_CORE_TABLE (OT, STAT)
#endif
#ifndef HB_NO_META
HB_OT_ACCELERATOR (OT, meta)
@@ -74,9 +74,9 @@ HB_OT_ACCELERATOR (OT, meta)
/* Vertical layout. */
#ifndef HB_NO_VERTICAL
-HB_OT_TABLE (OT, vhea)
+HB_OT_CORE_TABLE (OT, vhea)
HB_OT_ACCELERATOR (OT, vmtx)
-HB_OT_TABLE (OT, VORG)
+HB_OT_CORE_TABLE (OT, VORG)
#endif
/* TrueType outlines. */
@@ -91,15 +91,15 @@ HB_OT_ACCELERATOR (OT, cff2)
/* OpenType variations. */
#ifndef HB_NO_VAR
-HB_OT_TABLE (OT, fvar)
-HB_OT_TABLE (OT, avar)
+HB_OT_CORE_TABLE (OT, fvar)
+HB_OT_CORE_TABLE (OT, avar)
HB_OT_ACCELERATOR (OT, gvar)
-HB_OT_TABLE (OT, MVAR)
+HB_OT_CORE_TABLE (OT, MVAR)
#endif
/* Legacy kern. */
#ifndef HB_NO_OT_KERN
-HB_OT_TABLE (OT, kern)
+HB_OT_CORE_TABLE (OT, kern)
#endif
/* OpenType shaping. */
@@ -107,12 +107,12 @@ HB_OT_TABLE (OT, kern)
HB_OT_ACCELERATOR (OT, GDEF)
HB_OT_ACCELERATOR (OT, GSUB)
HB_OT_ACCELERATOR (OT, GPOS)
-//HB_OT_TABLE (OT, JSTF)
+//HB_OT_CORE_TABLE (OT, JSTF)
#endif
/* OpenType baseline. */
#ifndef HB_NO_BASE
-HB_OT_TABLE (OT, BASE)
+HB_OT_CORE_TABLE (OT, BASE)
#endif
/* AAT shaping. */
@@ -129,8 +129,8 @@ HB_OT_TABLE (AAT, feat)
/* OpenType color fonts. */
#ifndef HB_NO_COLOR
-HB_OT_TABLE (OT, COLR)
-HB_OT_TABLE (OT, CPAL)
+HB_OT_CORE_TABLE (OT, COLR)
+HB_OT_CORE_TABLE (OT, CPAL)
HB_OT_ACCELERATOR (OT, CBDT)
HB_OT_ACCELERATOR (OT, sbix)
HB_OT_ACCELERATOR (OT, SVG)
@@ -138,7 +138,7 @@ HB_OT_ACCELERATOR (OT, SVG)
/* OpenType math. */
#ifndef HB_NO_MATH
-HB_OT_TABLE (OT, MATH)
+HB_OT_CORE_TABLE (OT, MATH)
#endif
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 0f44ee4d5f..19ae02e28b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
@@ -30,21 +30,24 @@
#include "hb-ot.h"
+#include "hb-cache.hh"
#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"
#include "hb-ot-cff1-table.hh"
#include "hb-ot-cff2-table.hh"
#include "hb-ot-hmtx-table.hh"
-#include "hb-ot-os2-table.hh"
#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 "OT/Color/CBDT/CBDT.hh"
+#include "OT/Color/COLR/COLR.hh"
+#include "OT/Color/sbix/sbix.hh"
+#include "OT/Color/svg/svg.hh"
/**
@@ -58,6 +61,71 @@
* 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;
+};
+
+static hb_ot_font_t *
+_hb_ot_font_create (hb_font_t *font)
+{
+ hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
+ if (unlikely (!ot_font))
+ return nullptr;
+
+ 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;
+}
+
+static void
+_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 ();
+ hb_free (cache);
+
+ hb_free (ot_font);
+}
static hb_bool_t
hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
@@ -66,8 +134,9 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
- return ot_face->cmap->get_nominal_glyph (unicode, glyph);
+ 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, ot_font->cmap_cache);
}
static unsigned int
@@ -80,10 +149,12 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
unsigned int glyph_stride,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ 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_glyphs (count,
first_unicode, unicode_stride,
- first_glyph, glyph_stride);
+ first_glyph, glyph_stride,
+ ot_font->cmap_cache);
}
static hb_bool_t
@@ -94,8 +165,11 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
- return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
+ 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,
+ ot_font->cmap_cache);
}
static void
@@ -107,14 +181,97 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+
+ 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;
- for (unsigned int i = 0; i < count; i++)
+ 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;
+ OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
+
+ bool use_cache = font->num_coords;
+#else
+ OT::VariationStore::cache_t *varStore_cache = nullptr;
+ bool use_cache = false;
+#endif
+
+ hb_ot_font_advance_cache_t *cache = nullptr;
+ if (use_cache)
+ {
+ retry:
+ cache = ot_font->advance_cache.get_acquire ();
+ if (unlikely (!cache))
+ {
+ cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
+ if (unlikely (!cache))
+ {
+ use_cache = false;
+ goto out;
+ }
+
+ cache->init ();
+ if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
+ {
+ hb_free (cache);
+ goto retry;
+ }
+ ot_font->cached_coords_serial.set_release (font->serial_coords);
+ }
+ }
+ out:
+
+ if (!use_cache)
+ {
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->em_scale_x (hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
+ else
+ { /* Use cache. */
+ if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords)
+ {
+ ot_font->advance_cache->init ();
+ ot_font->cached_coords_serial.set_release (font->serial_coords);
+ }
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ hb_position_t v;
+ unsigned cv;
+ if (ot_font->advance_cache->get (*first_glyph, &cv))
+ v = cv;
+ else
+ {
+ v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
+ ot_font->advance_cache->set (*first_glyph, v);
+ }
+ *first_advance = font->em_scale_x (v);
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
+
+#ifndef HB_NO_VAR
+ OT::VariationStore::destroy_cache (varStore_cache);
+#endif
+
+ if (font->x_strength && !font->embolden_in_place)
{
- *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font));
- first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
- first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ /* 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);
+ }
}
}
@@ -128,16 +285,33 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ 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::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+ hb_position_t *orig_first_advance = first_advance;
+
if (vmtx.has_data ())
+ {
+#ifndef HB_NO_VAR
+ const OT::VVAR &VVAR = *vmtx.var_table;
+ const OT::VariationStore &varStore = &VVAR + VVAR.varStore;
+ OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
+#else
+ OT::VariationStore::cache_t *varStore_cache = nullptr;
+#endif
+
for (unsigned int i = 0; i < count; i++)
{
- *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
+ *first_advance = font->em_scale_y (-(int) vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
+
+#ifndef HB_NO_VAR
+ OT::VariationStore::destroy_cache (varStore_cache);
+#endif
+ }
else
{
hb_font_extents_t font_extents;
@@ -151,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
@@ -163,24 +349,36 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
hb_position_t *y,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ 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;
*x = font->get_glyph_h_advance (glyph) / 2;
const OT::VORG &VORG = *ot_face->VORG;
if (VORG.has_data ())
{
- *y = font->em_scale_y (VORG.get_y_origin (glyph));
+ float delta = 0;
+
+#ifndef HB_NO_VAR
+ const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+ const OT::VVAR &VVAR = *vmtx.var_table;
+ if (font->num_coords)
+ VVAR.get_vorg_delta_unscaled (glyph,
+ font->coords, font->num_coords,
+ &delta);
+#endif
+
+ *y = font->em_scalef_y (VORG.get_y_origin (glyph) + delta);
return true;
}
hb_glyph_extents_t extents = {0};
if (ot_face->glyf->get_extents (font, glyph, &extents))
{
- if (ot_face->vmtx->has_data ())
+ const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+ int tsb = 0;
+ if (vmtx.get_leading_bearing_with_var_unscaled (font, glyph, &tsb))
{
- const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
- hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
*y = extents.y_bearing + font->em_scale_y (tsb);
return true;
}
@@ -208,21 +406,22 @@ hb_ot_get_glyph_extents (hb_font_t *font,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ 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;
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
+ if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
+#endif
+#if !defined(HB_NO_COLOR)
+ if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
#endif
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
#endif
-#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
- if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
-#endif
- // TODO Hook up side-bearings variations.
return false;
}
@@ -234,7 +433,9 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
char *name, unsigned int size,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ 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;
+
if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
@@ -248,7 +449,9 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ 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;
+
if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
@@ -263,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
@@ -283,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)
{
- 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;
+ 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)) return;
- if (font->face->table.cff2->get_path (font, glyph, draw_session)) return;
+ 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)
+{
+#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->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
@@ -321,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);
@@ -364,23 +623,28 @@ _hb_ot_get_font_funcs ()
void
hb_ot_font_set_funcs (hb_font_t *font)
{
+ hb_ot_font_t *ot_font = _hb_ot_font_create (font);
+ if (unlikely (!ot_font))
+ return;
+
hb_font_set_funcs (font,
_hb_ot_get_font_funcs (),
- &font->face->table,
- nullptr);
+ ot_font,
+ _hb_ot_font_destroy);
}
#ifndef HB_NO_VAR
-int
-_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
+bool
+_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical,
+ int *lsb)
{
- return font->face->table.glyf->get_side_bearing_var (font, glyph, is_vertical);
+ return font->face->table.glyf->get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
}
unsigned
-_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
+_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
{
- return font->face->table.glyf->get_advance_var (font, glyph, is_vertical);
+ return font->face->table.glyf->get_advance_with_var_unscaled (font, glyph, is_vertical);
}
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh
index b4ac688344..c32ff7636d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh
@@ -30,1332 +30,6 @@
#ifndef HB_OT_GLYF_TABLE_HH
#define HB_OT_GLYF_TABLE_HH
-#include "hb-open-type.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-hmtx-table.hh"
-#include "hb-ot-var-gvar-table.hh"
-#include "hb-draw.hh"
-
-namespace OT {
-
-
-/*
- * loca -- Index to Location
- * https://docs.microsoft.com/en-us/typography/opentype/spec/loca
- */
-#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
-
-#ifndef HB_MAX_COMPOSITE_OPERATIONS
-#define HB_MAX_COMPOSITE_OPERATIONS 100000
-#endif
-
-
-struct loca
-{
- friend struct glyf;
-
- static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
-
- bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
- {
- TRACE_SANITIZE (this);
- return_trace (true);
- }
-
- protected:
- UnsizedArrayOf<HBUINT8>
- dataZ; /* Location data. */
- public:
- DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
- * check the size externally, allow Null() object of it by
- * defining it _MIN instead. */
-};
-
-
-/*
- * glyf -- TrueType Glyph Data
- * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
- */
-#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
-
-
-struct glyf
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
-
- bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
- {
- TRACE_SANITIZE (this);
- /* Runtime checks as eager sanitizing each glyph is costy */
- return_trace (true);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_source_of (Iterator, unsigned int))>
- static bool
- _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
- {
- unsigned num_offsets = padded_offsets.len () + 1;
- unsigned entry_size = use_short_loca ? 2 : 4;
- char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
-
- if (unlikely (!loca_prime_data)) return false;
-
- DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
- entry_size, num_offsets, entry_size * num_offsets);
-
- if (use_short_loca)
- _write_loca (padded_offsets, 1, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
- else
- _write_loca (padded_offsets, 0, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
-
- hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
- entry_size * num_offsets,
- HB_MEMORY_MODE_WRITABLE,
- loca_prime_data,
- hb_free);
-
- bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
- && _add_head_and_set_loca_version (plan, use_short_loca);
-
- hb_blob_destroy (loca_blob);
- return result;
- }
-
- template<typename IteratorIn, typename IteratorOut,
- hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
- hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
- static void
- _write_loca (IteratorIn it, unsigned right_shift, IteratorOut dest)
- {
- unsigned int offset = 0;
- dest << 0;
- + it
- | hb_map ([=, &offset] (unsigned int padded_size)
- {
- offset += padded_size;
- DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
- return offset >> right_shift;
- })
- | hb_sink (dest)
- ;
- }
-
- /* requires source of SubsetGlyph complains the identifier isn't declared */
- template <typename Iterator>
- bool serialize (hb_serialize_context_t *c,
- Iterator it,
- bool use_short_loca,
- const hb_subset_plan_t *plan)
- {
- TRACE_SERIALIZE (this);
- unsigned init_len = c->length ();
- for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
-
- /* As a special case when all glyph in the font are empty, add a zero byte
- * to the table, so that OTS doesn’t reject it, and to make the table work
- * on Windows as well.
- * See https://github.com/khaledhosny/ots/issues/52 */
- if (init_len == c->length ())
- {
- HBUINT8 empty_byte;
- empty_byte = 0;
- c->copy (empty_byte);
- }
- return_trace (true);
- }
-
- /* Byte region(s) per glyph to output
- unpadded, hints removed if so requested
- If we fail to process a glyph we produce an empty (0-length) glyph */
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
-
- glyf *glyf_prime = c->serializer->start_embed <glyf> ();
- if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
-
- hb_vector_t<SubsetGlyph> glyphs;
- _populate_subset_glyphs (c->plan, &glyphs);
-
- auto padded_offsets =
- + hb_iter (glyphs)
- | hb_map (&SubsetGlyph::padded_size)
- ;
-
- unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
- bool use_short_loca = max_offset < 0x1FFFF;
-
-
- glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
- if (!use_short_loca) {
- padded_offsets =
- + hb_iter (glyphs)
- | hb_map (&SubsetGlyph::length)
- ;
- }
-
-
- if (unlikely (c->serializer->in_error ())) return_trace (false);
- return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
- padded_offsets,
- use_short_loca)));
- }
-
- template <typename SubsetGlyph>
- void
- _populate_subset_glyphs (const hb_subset_plan_t *plan,
- hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const
- {
- OT::glyf::accelerator_t glyf (plan->source);
-
- + hb_range (plan->num_output_glyphs ())
- | hb_map ([&] (hb_codepoint_t new_gid)
- {
- SubsetGlyph subset_glyph = {0};
- subset_glyph.new_gid = new_gid;
-
- /* should never fail: all old gids should be mapped */
- if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
- return subset_glyph;
-
- if (new_gid == 0 &&
- !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
- subset_glyph.source_glyph = Glyph ();
- else
- subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
- if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- subset_glyph.drop_hints_bytes ();
- else
- subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
- return subset_glyph;
- })
- | hb_sink (glyphs)
- ;
- }
-
- static bool
- _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
- {
- hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
- hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
- hb_blob_destroy (head_blob);
-
- if (unlikely (!head_prime_blob))
- return false;
-
- head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
- head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
- bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
-
- hb_blob_destroy (head_prime_blob);
- return success;
- }
-
- struct CompositeGlyphChain
- {
- protected:
- enum composite_glyph_flag_t
- {
- ARG_1_AND_2_ARE_WORDS = 0x0001,
- ARGS_ARE_XY_VALUES = 0x0002,
- ROUND_XY_TO_GRID = 0x0004,
- WE_HAVE_A_SCALE = 0x0008,
- MORE_COMPONENTS = 0x0020,
- WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
- WE_HAVE_A_TWO_BY_TWO = 0x0080,
- WE_HAVE_INSTRUCTIONS = 0x0100,
- USE_MY_METRICS = 0x0200,
- OVERLAP_COMPOUND = 0x0400,
- SCALED_COMPONENT_OFFSET = 0x0800,
- UNSCALED_COMPONENT_OFFSET = 0x1000
- };
-
- public:
- unsigned int get_size () const
- {
- unsigned int size = min_size;
- /* arg1 and 2 are int16 */
- if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
- /* arg1 and 2 are int8 */
- else size += 2;
-
- /* One x 16 bit (scale) */
- if (flags & WE_HAVE_A_SCALE) size += 2;
- /* Two x 16 bit (xscale, yscale) */
- else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
- /* Four x 16 bit (xscale, scale01, scale10, yscale) */
- else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
-
- return size;
- }
-
- void set_glyph_index (hb_codepoint_t new_gid) { glyphIndex = new_gid; }
- hb_codepoint_t get_glyph_index () const { return glyphIndex; }
-
- void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
- void set_overlaps_flag ()
- {
- flags = (uint16_t) flags | OVERLAP_COMPOUND;
- }
-
- bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
-
- bool has_more () const { return flags & MORE_COMPONENTS; }
- bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
- bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
- void get_anchor_points (unsigned int &point1, unsigned int &point2) const
- {
- const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex);
- if (flags & ARG_1_AND_2_ARE_WORDS)
- {
- point1 = ((const HBUINT16 *) p)[0];
- point2 = ((const HBUINT16 *) p)[1];
- }
- else
- {
- point1 = p[0];
- point2 = p[1];
- }
- }
-
- void transform_points (contour_point_vector_t &points) const
- {
- float matrix[4];
- contour_point_t trans;
- if (get_transformation (matrix, trans))
- {
- if (scaled_offsets ())
- {
- points.translate (trans);
- points.transform (matrix);
- }
- else
- {
- points.transform (matrix);
- points.translate (trans);
- }
- }
- }
-
- protected:
- bool scaled_offsets () const
- { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
-
- bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
- {
- matrix[0] = matrix[3] = 1.f;
- matrix[1] = matrix[2] = 0.f;
-
- int tx, ty;
- const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex);
- if (flags & ARG_1_AND_2_ARE_WORDS)
- {
- tx = *(const HBINT16 *) p;
- p += HBINT16::static_size;
- ty = *(const HBINT16 *) p;
- p += HBINT16::static_size;
- }
- else
- {
- tx = *p++;
- ty = *p++;
- }
- if (is_anchored ()) tx = ty = 0;
-
- trans.init ((float) tx, (float) ty);
-
- {
- const F2DOT14 *points = (const F2DOT14 *) p;
- if (flags & WE_HAVE_A_SCALE)
- {
- matrix[0] = matrix[3] = points[0].to_float ();
- return true;
- }
- else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
- {
- matrix[0] = points[0].to_float ();
- matrix[3] = points[1].to_float ();
- return true;
- }
- else if (flags & WE_HAVE_A_TWO_BY_TWO)
- {
- matrix[0] = points[0].to_float ();
- matrix[1] = points[1].to_float ();
- matrix[2] = points[2].to_float ();
- matrix[3] = points[3].to_float ();
- return true;
- }
- }
- return tx || ty;
- }
-
- protected:
- HBUINT16 flags;
- HBGlyphID16 glyphIndex;
- public:
- DEFINE_SIZE_MIN (4);
- };
-
- struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphChain &>
- {
- typedef const CompositeGlyphChain *__item_t__;
- composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
- glyph (glyph_), current (nullptr), current_size (0)
- {
- set_next (current_);
- }
-
- composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
-
- const CompositeGlyphChain &__item__ () const { return *current; }
- bool __more__ () const { return current; }
- void __next__ ()
- {
- if (!current->has_more ()) { current = nullptr; return; }
-
- set_next (&StructAtOffset<CompositeGlyphChain> (current, current_size));
- }
- bool operator != (const composite_iter_t& o) const
- { return glyph != o.glyph || current != o.current; }
-
-
- void set_next (const CompositeGlyphChain *composite)
- {
- if (!glyph.check_range (composite, CompositeGlyphChain::min_size))
- {
- current = nullptr;
- current_size = 0;
- return;
- }
- unsigned size = composite->get_size ();
- if (!glyph.check_range (composite, size))
- {
- current = nullptr;
- current_size = 0;
- return;
- }
-
- current = composite;
- current_size = size;
- }
-
- private:
- hb_bytes_t glyph;
- __item_t__ current;
- unsigned current_size;
- };
-
- enum phantom_point_index_t
- {
- PHANTOM_LEFT = 0,
- PHANTOM_RIGHT = 1,
- PHANTOM_TOP = 2,
- PHANTOM_BOTTOM = 3,
- PHANTOM_COUNT = 4
- };
-
- struct accelerator_t;
-
- struct Glyph
- {
- enum simple_glyph_flag_t
- {
- FLAG_ON_CURVE = 0x01,
- FLAG_X_SHORT = 0x02,
- FLAG_Y_SHORT = 0x04,
- FLAG_REPEAT = 0x08,
- FLAG_X_SAME = 0x10,
- FLAG_Y_SAME = 0x20,
- FLAG_OVERLAP_SIMPLE = 0x40,
- FLAG_RESERVED2 = 0x80
- };
-
- private:
- struct GlyphHeader
- {
- bool has_data () const { return numberOfContours; }
-
- bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
- hb_codepoint_t gid, hb_glyph_extents_t *extents) const
- {
- /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
- /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
- extents->x_bearing = font->em_scale_x (glyf_accelerator.hmtx->get_side_bearing (gid));
- 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));
-
- return true;
- }
-
- HBINT16 numberOfContours;
- /* If the number of contours is
- * greater than or equal to zero,
- * this is a simple glyph; if negative,
- * this is a composite glyph. */
- FWORD xMin; /* Minimum x for coordinate data. */
- FWORD yMin; /* Minimum y for coordinate data. */
- FWORD xMax; /* Maximum x for coordinate data. */
- FWORD yMax; /* Maximum y for coordinate data. */
- public:
- DEFINE_SIZE_STATIC (10);
- };
-
- struct SimpleGlyph
- {
- const GlyphHeader &header;
- hb_bytes_t bytes;
- SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
- header (header_), bytes (bytes_) {}
-
- unsigned int instruction_len_offset () const
- { return GlyphHeader::static_size + 2 * header.numberOfContours; }
-
- unsigned int length (unsigned int instruction_len) const
- { return instruction_len_offset () + 2 + instruction_len; }
-
- unsigned int instructions_length () const
- {
- unsigned int instruction_length_offset = instruction_len_offset ();
- if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
-
- const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
- /* Out of bounds of the current glyph */
- if (unlikely (length (instructionLength) > bytes.length)) return 0;
- return instructionLength;
- }
-
- const Glyph trim_padding () const
- {
- /* based on FontTools _g_l_y_f.py::trim */
- const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
- const uint8_t *glyph_end = glyph + bytes.length;
- /* simple glyph w/contours, possibly trimmable */
- glyph += instruction_len_offset ();
-
- if (unlikely (glyph + 2 >= glyph_end)) return Glyph ();
- unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
- unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
-
- glyph += 2 + num_instructions;
-
- unsigned int coord_bytes = 0;
- unsigned int coords_with_flags = 0;
- while (glyph < glyph_end)
- {
- uint8_t flag = *glyph;
- glyph++;
-
- unsigned int repeat = 1;
- if (flag & FLAG_REPEAT)
- {
- if (unlikely (glyph >= glyph_end)) return Glyph ();
- repeat = *glyph + 1;
- glyph++;
- }
-
- unsigned int xBytes, yBytes;
- xBytes = yBytes = 0;
- if (flag & FLAG_X_SHORT) xBytes = 1;
- else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
-
- if (flag & FLAG_Y_SHORT) yBytes = 1;
- else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
-
- coord_bytes += (xBytes + yBytes) * repeat;
- coords_with_flags += repeat;
- if (coords_with_flags >= num_coordinates) break;
- }
-
- if (unlikely (coords_with_flags != num_coordinates)) return Glyph ();
- return Glyph (bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph)));
- }
-
- /* zero instruction length */
- void drop_hints ()
- {
- GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
- (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
- }
-
- void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
- {
- unsigned int instructions_len = instructions_length ();
- unsigned int glyph_length = length (instructions_len);
- dest_start = bytes.sub_array (0, glyph_length - instructions_len);
- dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
- }
-
- void set_overlaps_flag ()
- {
- if (unlikely (!header.numberOfContours)) return;
-
- unsigned flags_offset = length (instructions_length ());
- if (unlikely (flags_offset + 1 > bytes.length)) return;
-
- HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
- first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
- }
-
- static bool read_points (const HBUINT8 *&p /* IN/OUT */,
- contour_point_vector_t &points_ /* IN/OUT */,
- const hb_bytes_t &bytes,
- void (* setter) (contour_point_t &_, float v),
- const simple_glyph_flag_t short_flag,
- const simple_glyph_flag_t same_flag)
- {
- float v = 0;
- for (unsigned i = 0; i < points_.length; i++)
- {
- uint8_t flag = points_[i].flag;
- if (flag & short_flag)
- {
- if (unlikely (!bytes.check_range (p))) return false;
- if (flag & same_flag)
- v += *p++;
- else
- v -= *p++;
- }
- else
- {
- if (!(flag & same_flag))
- {
- if (unlikely (!bytes.check_range ((const HBUINT16 *) p))) return false;
- v += *(const HBINT16 *) p;
- p += HBINT16::static_size;
- }
- }
- setter (points_[i], v);
- }
- return true;
- }
-
- bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
- bool phantom_only = false) const
- {
- const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
- int num_contours = header.numberOfContours;
- if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
- unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
-
- points_.resize (num_points);
- for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
- if (phantom_only) return true;
-
- for (int i = 0; i < num_contours; i++)
- points_[endPtsOfContours[i]].is_end_point = true;
-
- /* Skip instructions */
- const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
- endPtsOfContours[num_contours]);
-
- /* Read flags */
- for (unsigned int i = 0; i < num_points; i++)
- {
- if (unlikely (!bytes.check_range (p))) return false;
- uint8_t flag = *p++;
- points_[i].flag = flag;
- if (flag & FLAG_REPEAT)
- {
- if (unlikely (!bytes.check_range (p))) return false;
- unsigned int repeat_count = *p++;
- while ((repeat_count-- > 0) && (++i < num_points))
- points_[i].flag = flag;
- }
- }
-
- /* Read x & y coordinates */
- return read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.x = v; },
- FLAG_X_SHORT, FLAG_X_SAME)
- && read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.y = v; },
- FLAG_Y_SHORT, FLAG_Y_SAME);
- }
- };
-
- struct CompositeGlyph
- {
- const GlyphHeader &header;
- hb_bytes_t bytes;
- CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
- header (header_), bytes (bytes_) {}
-
- composite_iter_t get_iterator () const
- { return composite_iter_t (bytes, &StructAfter<CompositeGlyphChain, GlyphHeader> (header)); }
-
- unsigned int instructions_length (hb_bytes_t bytes) const
- {
- unsigned int start = bytes.length;
- unsigned int end = bytes.length;
- const CompositeGlyphChain *last = nullptr;
- for (auto &item : get_iterator ())
- last = &item;
- if (unlikely (!last)) return 0;
-
- if (last->has_instructions ())
- start = (char *) last - &bytes + last->get_size ();
- if (unlikely (start > end)) return 0;
- return end - start;
- }
-
- /* Trimming for composites not implemented.
- * If removing hints it falls out of that. */
- const Glyph trim_padding () const { return Glyph (bytes); }
-
- void drop_hints ()
- {
- for (const auto &_ : get_iterator ())
- const_cast<CompositeGlyphChain &> (_).drop_instructions_flag ();
- }
-
- /* Chop instructions off the end */
- void drop_hints_bytes (hb_bytes_t &dest_start) const
- { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
-
- void set_overlaps_flag ()
- {
- const_cast<CompositeGlyphChain &> (StructAfter<CompositeGlyphChain, GlyphHeader> (header))
- .set_overlaps_flag ();
- }
- };
-
- enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
-
- public:
- composite_iter_t get_composite_iterator () const
- {
- if (type != COMPOSITE) return composite_iter_t ();
- return CompositeGlyph (*header, bytes).get_iterator ();
- }
-
- const Glyph trim_padding () const
- {
- switch (type) {
- case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
- case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
- default: return bytes;
- }
- }
-
- void drop_hints ()
- {
- switch (type) {
- case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
- case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
- default: return;
- }
- }
-
- void set_overlaps_flag ()
- {
- switch (type) {
- case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
- case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
- default: return;
- }
- }
-
- void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
- {
- switch (type) {
- case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
- case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
- default: return;
- }
- }
-
- /* Note: Recursively calls itself.
- * all_points includes phantom points
- */
- bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
- contour_point_vector_t &all_points /* OUT */,
- bool phantom_only = false,
- unsigned int depth = 0) const
- {
- if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
- contour_point_vector_t points;
-
- switch (type) {
- case COMPOSITE:
- {
- /* pseudo component points for each component in composite glyph */
- unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ());
- if (unlikely (!points.resize (num_points))) return false;
- for (unsigned i = 0; i < points.length; i++)
- points[i].init ();
- break;
- }
- case SIMPLE:
- if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
- return false;
- break;
- }
-
- /* Init phantom points */
- if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
- hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
- {
- for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
- int h_delta = (int) header->xMin -
- glyf_accelerator.hmtx->get_side_bearing (gid);
- int v_orig = (int) header->yMax +
-#ifndef HB_NO_VERTICAL
- glyf_accelerator.vmtx->get_side_bearing (gid)
-#else
- 0
-#endif
- ;
- unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid);
- unsigned v_adv =
-#ifndef HB_NO_VERTICAL
- glyf_accelerator.vmtx->get_advance (gid)
-#else
- - font->face->get_upem ()
-#endif
- ;
- phantoms[PHANTOM_LEFT].x = h_delta;
- phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
- phantoms[PHANTOM_TOP].y = v_orig;
- phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
- }
-
-#ifndef HB_NO_VAR
- glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
-#endif
-
- switch (type) {
- case SIMPLE:
- all_points.extend (points.as_array ());
- break;
- case COMPOSITE:
- {
- unsigned int comp_index = 0;
- for (auto &item : get_composite_iterator ())
- {
- contour_point_vector_t comp_points;
- if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_glyph_index ())
- .get_points (font, glyf_accelerator, comp_points,
- phantom_only, depth + 1)
- || comp_points.length < PHANTOM_COUNT))
- return false;
-
- /* Copy phantom points from component if USE_MY_METRICS flag set */
- if (item.is_use_my_metrics ())
- for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
- phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
-
- /* Apply component transformation & translation */
- item.transform_points (comp_points);
-
- /* Apply translation from gvar */
- comp_points.translate (points[comp_index]);
-
- if (item.is_anchored ())
- {
- unsigned int p1, p2;
- item.get_anchor_points (p1, p2);
- if (likely (p1 < all_points.length && p2 < comp_points.length))
- {
- contour_point_t delta;
- delta.init (all_points[p1].x - comp_points[p2].x,
- all_points[p1].y - comp_points[p2].y);
-
- comp_points.translate (delta);
- }
- }
-
- all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
-
- comp_index++;
- }
-
- all_points.extend (phantoms);
- } break;
- default:
- all_points.extend (phantoms);
- }
-
- if (depth == 0) /* Apply at top level */
- {
- /* Undocumented rasterizer behavior:
- * Shift points horizontally by the updated left side bearing
- */
- contour_point_t delta;
- delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
- if (delta.x) all_points.translate (delta);
- }
-
- return true;
- }
-
- bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
- hb_glyph_extents_t *extents) const
- {
- if (type == EMPTY) return true; /* Empty glyph; zero extents. */
- return header->get_extents (font, glyf_accelerator, gid, extents);
- }
-
- hb_bytes_t get_bytes () const { return bytes; }
-
- Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
- hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_),
- header (bytes.as<GlyphHeader> ())
- {
- int num_contours = header->numberOfContours;
- if (unlikely (num_contours == 0)) type = EMPTY;
- else if (num_contours > 0) type = SIMPLE;
- else type = COMPOSITE; /* negative numbers */
- }
-
- protected:
- hb_bytes_t bytes;
- hb_codepoint_t gid;
- const GlyphHeader *header;
- unsigned type;
- };
-
- struct accelerator_t
- {
- accelerator_t (hb_face_t *face)
- {
- short_offset = false;
- num_glyphs = 0;
- loca_table = nullptr;
- glyf_table = nullptr;
-#ifndef HB_NO_VAR
- gvar = nullptr;
-#endif
- hmtx = nullptr;
-#ifndef HB_NO_VERTICAL
- vmtx = nullptr;
-#endif
- const OT::head &head = *face->table.head;
- if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
- /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
- return;
- short_offset = 0 == head.indexToLocFormat;
-
- loca_table = face->table.loca.get_blob (); // Needs no destruct!
- glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
-#ifndef HB_NO_VAR
- gvar = face->table.gvar;
-#endif
- hmtx = face->table.hmtx;
-#ifndef HB_NO_VERTICAL
- vmtx = face->table.vmtx;
-#endif
-
- num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
- num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
- }
- ~accelerator_t ()
- {
- glyf_table.destroy ();
- }
-
- protected:
- template<typename T>
- bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
- {
- if (gid >= num_glyphs) return false;
-
- /* Making this allocfree is not that easy
- https://github.com/harfbuzz/harfbuzz/issues/2095
- mostly because of gvar handling in VF fonts,
- perhaps a separate path for non-VF fonts can be considered */
- contour_point_vector_t all_points;
-
- bool phantom_only = !consumer.is_consuming_contour_points ();
- if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, phantom_only)))
- return false;
-
- if (consumer.is_consuming_contour_points ())
- {
- for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
- consumer.consume_point (all_points[point_index]);
- consumer.points_end ();
- }
-
- /* Where to write phantoms, nullptr if not requested */
- contour_point_t *phantoms = consumer.get_phantoms_sink ();
- if (phantoms)
- for (unsigned i = 0; i < PHANTOM_COUNT; ++i)
- phantoms[i] = all_points[all_points.length - PHANTOM_COUNT + i];
-
- return true;
- }
-
-#ifndef HB_NO_VAR
- struct points_aggregator_t
- {
- hb_font_t *font;
- hb_glyph_extents_t *extents;
- contour_point_t *phantoms;
-
- struct contour_bounds_t
- {
- contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
-
- void add (const contour_point_t &p)
- {
- min_x = hb_min (min_x, p.x);
- min_y = hb_min (min_y, p.y);
- max_x = hb_max (max_x, p.x);
- max_y = hb_max (max_y, p.y);
- }
-
- bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
-
- void get_extents (hb_font_t *font, hb_glyph_extents_t *extents)
- {
- if (unlikely (empty ()))
- {
- extents->width = 0;
- extents->x_bearing = 0;
- extents->height = 0;
- extents->y_bearing = 0;
- return;
- }
- extents->x_bearing = font->em_scalef_x (min_x);
- extents->width = font->em_scalef_x (max_x) - extents->x_bearing;
- extents->y_bearing = font->em_scalef_y (max_y);
- extents->height = font->em_scalef_y (min_y) - extents->y_bearing;
- }
-
- protected:
- float min_x, min_y, max_x, max_y;
- } bounds;
-
- points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_)
- {
- font = font_;
- extents = extents_;
- phantoms = phantoms_;
- if (extents) bounds = contour_bounds_t ();
- }
-
- void consume_point (const contour_point_t &point) { bounds.add (point); }
- void points_end () { bounds.get_extents (font, extents); }
-
- bool is_consuming_contour_points () { return extents; }
- contour_point_t *get_phantoms_sink () { return phantoms; }
- };
-
- public:
- unsigned
- get_advance_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
- {
- if (unlikely (gid >= num_glyphs)) return 0;
-
- bool success = false;
-
- contour_point_t phantoms[PHANTOM_COUNT];
- if (likely (font->num_coords == gvar->get_axis_count ()))
- success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
-
- if (unlikely (!success))
- return
-#ifndef HB_NO_VERTICAL
- is_vertical ? vmtx->get_advance (gid) :
-#endif
- hmtx->get_advance (gid);
-
- float result = is_vertical
- ? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y
- : phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x;
- return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
- }
-
- int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
- {
- if (unlikely (gid >= num_glyphs)) return 0;
-
- hb_glyph_extents_t extents;
-
- contour_point_t phantoms[PHANTOM_COUNT];
- if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms))))
- return
-#ifndef HB_NO_VERTICAL
- is_vertical ? vmtx->get_side_bearing (gid) :
-#endif
- hmtx->get_side_bearing (gid);
-
- return is_vertical
- ? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
- : floorf (phantoms[PHANTOM_LEFT].x);
- }
-#endif
-
- public:
- bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
- {
- if (unlikely (gid >= num_glyphs)) return false;
-
-#ifndef HB_NO_VAR
- if (font->num_coords && font->num_coords == gvar->get_axis_count ())
- return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
-#endif
- return glyph_for_gid (gid).get_extents (font, *this, extents);
- }
-
- const Glyph
- glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
- {
- if (unlikely (gid >= num_glyphs)) return Glyph ();
-
- unsigned int start_offset, end_offset;
-
- if (short_offset)
- {
- const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
- start_offset = 2 * offsets[gid];
- end_offset = 2 * offsets[gid + 1];
- }
- else
- {
- const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
- start_offset = offsets[gid];
- end_offset = offsets[gid + 1];
- }
-
- if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
- return Glyph ();
-
- Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
- end_offset - start_offset), gid);
- return needs_padding_removal ? glyph.trim_padding () : glyph;
- }
-
- unsigned
- add_gid_and_children (hb_codepoint_t gid,
- hb_set_t *gids_to_retain,
- unsigned depth = 0,
- unsigned operation_count = 0) const
- {
- if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
- if (unlikely (operation_count++ > HB_MAX_COMPOSITE_OPERATIONS)) return operation_count;
- /* Check if is already visited */
- if (gids_to_retain->has (gid)) return operation_count;
-
- gids_to_retain->add (gid);
-
- auto it = glyph_for_gid (gid).get_composite_iterator ();
- while (it)
- {
- auto item = *(it++);
- operation_count =
- add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
- }
-
- return operation_count;
- }
-
- struct path_builder_t
- {
- hb_font_t *font;
- hb_draw_session_t *draw_session;
-
- struct optional_point_t
- {
- optional_point_t () { has_data = false; }
- optional_point_t (float x_, float y_) { x = x_; y = y_; has_data = true; }
-
- bool has_data;
- float x;
- float y;
-
- optional_point_t lerp (optional_point_t p, float t)
- { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
- } first_oncurve, first_offcurve, last_offcurve;
-
- path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
- {
- font = font_;
- draw_session = &draw_session_;
- first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
- }
-
- /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
- See also:
- * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
- * https://stackoverflow.com/a/20772557 */
- void consume_point (const contour_point_t &point)
- {
- bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
- optional_point_t p (point.x, point.y);
- if (!first_oncurve.has_data)
- {
- if (is_on_curve)
- {
- first_oncurve = p;
- draw_session->move_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
- }
- else
- {
- if (first_offcurve.has_data)
- {
- optional_point_t mid = first_offcurve.lerp (p, .5f);
- first_oncurve = mid;
- last_offcurve = p;
- draw_session->move_to (font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
- }
- else
- first_offcurve = p;
- }
- }
- else
- {
- if (last_offcurve.has_data)
- {
- if (is_on_curve)
- {
- draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
- font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
- last_offcurve = optional_point_t ();
- }
- else
- {
- optional_point_t mid = last_offcurve.lerp (p, .5f);
- draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
- font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
- last_offcurve = p;
- }
- }
- else
- {
- if (is_on_curve)
- draw_session->line_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
- else
- last_offcurve = p;
- }
- }
-
- if (point.is_end_point)
- {
- if (first_offcurve.has_data && last_offcurve.has_data)
- {
- optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
- draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
- font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
- last_offcurve = optional_point_t ();
- /* now check the rest */
- }
-
- if (first_offcurve.has_data && first_oncurve.has_data)
- draw_session->quadratic_to (font->em_fscalef_x (first_offcurve.x), font->em_fscalef_y (first_offcurve.y),
- font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
- else if (last_offcurve.has_data && first_oncurve.has_data)
- draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
- font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
- else if (first_oncurve.has_data)
- draw_session->line_to (font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
- else if (first_offcurve.has_data)
- {
- float x = font->em_fscalef_x (first_offcurve.x), y = font->em_fscalef_x (first_offcurve.y);
- draw_session->move_to (x, y);
- draw_session->quadratic_to (x, y, x, y);
- }
-
- /* Getting ready for the next contour */
- first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
- draw_session->close_path ();
- }
- }
- void points_end () {}
-
- bool is_consuming_contour_points () { return true; }
- contour_point_t *get_phantoms_sink () { return nullptr; }
- };
-
- bool
- get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
- { return get_points (font, gid, path_builder_t (font, draw_session)); }
-
-#ifndef HB_NO_VAR
- const gvar_accelerator_t *gvar;
-#endif
- const hmtx_accelerator_t *hmtx;
-#ifndef HB_NO_VERTICAL
- const vmtx_accelerator_t *vmtx;
-#endif
-
- private:
- bool short_offset;
- unsigned int num_glyphs;
- hb_blob_ptr_t<loca> loca_table;
- hb_blob_ptr_t<glyf> glyf_table;
- };
-
- struct SubsetGlyph
- {
- hb_codepoint_t new_gid;
- hb_codepoint_t old_gid;
- Glyph source_glyph;
- hb_bytes_t dest_start; /* region of source_glyph to copy first */
- hb_bytes_t dest_end; /* region of source_glyph to copy second */
-
- bool serialize (hb_serialize_context_t *c,
- bool use_short_loca,
- const hb_subset_plan_t *plan) const
- {
- TRACE_SERIALIZE (this);
-
- hb_bytes_t dest_glyph = dest_start.copy (c);
- dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
- unsigned int pad_length = use_short_loca ? padding () : 0;
- DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
-
- HBUINT8 pad;
- pad = 0;
- while (pad_length > 0)
- {
- c->embed (pad);
- pad_length--;
- }
-
- if (unlikely (!dest_glyph.length)) return_trace (true);
-
- /* update components gids */
- for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
- {
- hb_codepoint_t new_gid;
- if (plan->new_gid_for_old_gid (_.get_glyph_index (), &new_gid))
- const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
- }
-
- if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- Glyph (dest_glyph).drop_hints ();
-
- if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
- Glyph (dest_glyph).set_overlaps_flag ();
-
- return_trace (true);
- }
-
- void drop_hints_bytes ()
- { source_glyph.drop_hints_bytes (dest_start, dest_end); }
-
- unsigned int length () const { return dest_start.length + dest_end.length; }
- /* pad to 2 to ensure 2-byte loca will be ok */
- unsigned int padding () const { return length () % 2; }
- unsigned int padded_size () const { return length () + padding (); }
- };
-
- protected:
- UnsizedArrayOf<HBUINT8>
- dataZ; /* Glyphs data. */
- public:
- DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
- * check the size externally, allow Null() object of it by
- * defining it _MIN instead. */
-};
-
-struct glyf_accelerator_t : glyf::accelerator_t {
- glyf_accelerator_t (hb_face_t *face) : glyf::accelerator_t (face) {}
-};
-
-
-} /* namespace OT */
-
+#include "OT/glyf/glyf.hh"
#endif /* HB_OT_GLYF_TABLE_HH */
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 d5e1fc91d2..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"
/*
@@ -43,11 +44,11 @@
#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
-HB_INTERNAL int
-_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+HB_INTERNAL bool
+_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical, int *lsb);
HB_INTERNAL unsigned
-_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
namespace OT {
@@ -62,7 +63,7 @@ struct LongMetric
};
-template <typename T, typename H>
+template <typename T/*Data table type*/, typename H/*Header table type*/, typename V/*Var table type*/>
struct hmtxvmtx
{
bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
@@ -73,11 +74,15 @@ struct hmtxvmtx
return_trace (true);
}
+ 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);
@@ -89,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;
@@ -130,14 +184,15 @@ struct hmtxvmtx
accelerator_t _mtx (c->plan->source);
unsigned num_long_metrics;
+ 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;
+
num_long_metrics = plan->num_output_glyphs ();
- hb_codepoint_t old_gid = 0;
- unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0;
+ unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx);
while (num_long_metrics > 1 &&
- last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0))
+ last_advance == get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 2, _mtx))
{
num_long_metrics--;
}
@@ -145,12 +200,18 @@ struct hmtxvmtx
auto it =
+ hb_range (c->plan->num_output_glyphs ())
- | hb_map ([c, &_mtx] (unsigned _)
+ | hb_map ([c, &_mtx, mtx_map] (unsigned _)
{
- hb_codepoint_t old_gid;
- if (!c->plan->old_gid_for_new_gid (_, &old_gid))
- return hb_pair (0u, 0);
- return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
+ if (!mtx_map->has (_))
+ {
+ hb_codepoint_t old_gid;
+ if (!c->plan->old_gid_for_new_gid (_, &old_gid))
+ return hb_pair (0u, 0);
+ int lsb = 0;
+ (void) _mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb);
+ return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
+ }
+ return mtx_map->get (_);
})
;
@@ -160,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);
@@ -173,7 +235,7 @@ struct hmtxvmtx
accelerator_t (hb_face_t *face)
{
table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
- var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
+ var_table = hb_sanitize_context_t ().reference_table<V> (face, T::variationsTag);
default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face);
@@ -221,36 +283,46 @@ struct hmtxvmtx
bool has_data () const { return (bool) num_bearings; }
- int get_side_bearing (hb_codepoint_t glyph) const
+ bool get_leading_bearing_without_var_unscaled (hb_codepoint_t glyph,
+ int *lsb) const
{
if (glyph < num_long_metrics)
- return table->longMetricZ[glyph].sb;
+ {
+ *lsb = table->longMetricZ[glyph].sb;
+ return true;
+ }
if (unlikely (glyph >= num_bearings))
- return 0;
+ return false;
const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
- return bearings[glyph - num_long_metrics];
+ *lsb = bearings[glyph - num_long_metrics];
+ return true;
}
- int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const
+ bool get_leading_bearing_with_var_unscaled (hb_font_t *font,
+ hb_codepoint_t glyph,
+ int *lsb) const
{
- int side_bearing = get_side_bearing (glyph);
+ if (!font->num_coords)
+ return get_leading_bearing_without_var_unscaled (glyph, lsb);
#ifndef HB_NO_VAR
- if (unlikely (glyph >= num_bearings) || !font->num_coords)
- return side_bearing;
-
- if (var_table.get_length ())
- return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
+ float delta;
+ if (var_table->get_lsb_delta_unscaled (glyph, font->coords, font->num_coords, &delta) &&
+ get_leading_bearing_without_var_unscaled (glyph, lsb))
+ {
+ *lsb += roundf (delta);
+ return true;
+ }
- return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+ return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx, lsb);
#else
- return side_bearing;
+ return false;
#endif
}
- unsigned int get_advance (hb_codepoint_t glyph) const
+ unsigned int get_advance_without_var_unscaled (hb_codepoint_t glyph) const
{
/* OpenType case. */
if (glyph < num_bearings)
@@ -262,7 +334,7 @@ struct hmtxvmtx
if (unlikely (!num_advances))
return default_advance;
-#ifdef HB_NO_BORING_EXPANSION
+#ifdef HB_NO_BEYOND_64K
return 0;
#endif
@@ -272,10 +344,8 @@ struct hmtxvmtx
/* num_bearings <= glyph < num_glyphs;
* num_bearings <= num_advances */
- /* TODO Optimize */
-
if (num_bearings == num_advances)
- return get_advance (num_bearings - 1);
+ return get_advance_without_var_unscaled (num_bearings - 1);
const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics];
@@ -283,19 +353,22 @@ struct hmtxvmtx
return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)];
}
- unsigned int get_advance (hb_codepoint_t glyph,
- hb_font_t *font) const
+ unsigned get_advance_with_var_unscaled (hb_codepoint_t glyph,
+ hb_font_t *font,
+ VariationStore::cache_t *store_cache = nullptr) const
{
- unsigned int advance = get_advance (glyph);
+ unsigned int advance = get_advance_without_var_unscaled (glyph);
#ifndef HB_NO_VAR
if (unlikely (glyph >= num_bearings) || !font->num_coords)
return advance;
if (var_table.get_length ())
- return advance + roundf (var_table->get_advance_var (glyph, font)); // TODO Optimize?!
+ return advance + roundf (var_table->get_advance_delta_unscaled (glyph,
+ font->coords, font->num_coords,
+ store_cache));
- return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+ return _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
#else
return advance;
#endif
@@ -310,11 +383,27 @@ struct hmtxvmtx
unsigned int default_advance;
- private:
+ public:
hb_blob_ptr_t<hmtxvmtx> table;
- hb_blob_ptr_t<HVARVVAR> var_table;
+ hb_blob_ptr_t<V> var_table;
};
+ /* 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<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map,
+ unsigned new_gid,
+ const accelerator_t &_mtx) const
+ {
+ 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;
+ }
+ return mtx_map->get (new_gid).first;
+ }
+
protected:
UnsizedArrayOf<LongMetric>
longMetricZ; /* Paired advance width and leading
@@ -345,12 +434,12 @@ struct hmtxvmtx
DEFINE_SIZE_ARRAY (0, longMetricZ);
};
-struct hmtx : hmtxvmtx<hmtx, hhea> {
+struct hmtx : hmtxvmtx<hmtx, hhea, HVAR> {
static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
static constexpr bool is_horizontal = true;
};
-struct vmtx : hmtxvmtx<vmtx, vhea> {
+struct vmtx : hmtxvmtx<vmtx, vhea, VVAR> {
static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
static constexpr bool is_horizontal = false;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh
index 1b9dfcd3f5..8179e5acd5 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh
@@ -49,7 +49,7 @@ struct BaseCoordFormat1
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
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 f2a58028e3..b53f2e9276 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh
@@ -35,74 +35,47 @@
#include "hb-set.hh"
#include "hb-bimap.hh"
+#include "OT/Layout/Common/Coverage.hh"
+#include "OT/Layout/types.hh"
-#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_pause() is
- * called in a collect_features call of any shaper.
- */
-#define HB_CLOSURE_MAX_STAGES 32
-#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_FEATURES
-#define HB_MAX_FEATURES 750
-#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
+// TODO(garretrieger): cleanup these after migration.
+using OT::Layout::Common::Coverage;
+using OT::Layout::Common::RangeRecord;
+using OT::Layout::SmallTypes;
+using OT::Layout::MediumTypes;
namespace OT {
-
-#define NOT_COVERED ((unsigned int) -1)
-
-
template<typename Iterator>
-static inline void Coverage_serialize (hb_serialize_context_t *c,
+static inline bool ClassDef_serialize (hb_serialize_context_t *c,
Iterator it);
-template<typename Iterator>
-static inline void ClassDef_serialize (hb_serialize_context_t *c,
- Iterator it);
-
-static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
- const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID16> &glyphs,
- const hb_set_t &klasses,
- bool use_class_zero,
- hb_map_t *klass_map /*INOUT*/);
+static bool ClassDef_remap_and_serialize (
+ hb_serialize_context_t *c,
+ const hb_set_t &klasses,
+ bool use_class_zero,
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_map_t *klass_map /*IN/OUT*/);
+struct hb_collect_feature_substitutes_with_var_context_t
+{
+ const hb_map_t *axes_index_tag_map;
+ const hb_hashmap_t<hb_tag_t, int> *axes_location;
+ hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map;
+ hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
+
+ // not stored in subset_plan
+ hb_set_t *feature_indices;
+ bool apply;
+ unsigned cur_record_idx;
+ hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map;
+};
struct hb_prune_langsys_context_t
{
hb_prune_langsys_context_t (const void *table_,
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
const hb_map_t *duplicate_feature_map_,
hb_set_t *new_collected_feature_indexes_)
:table (table_),
@@ -122,7 +95,7 @@ struct hb_prune_langsys_context_t
public:
const void *table;
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
const hb_map_t *duplicate_feature_map;
hb_set_t *new_feature_indexes;
@@ -162,26 +135,42 @@ struct hb_subset_layout_context_t :
hb_subset_context_t *subset_context;
const hb_tag_t table_tag;
const hb_map_t *lookup_index_map;
- const hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
+ const hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
const hb_map_t *feature_index_map;
+ const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
+ hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map;
+
unsigned cur_script_index;
+ unsigned cur_feature_var_record_idx;
hb_subset_layout_context_t (hb_subset_context_t *c_,
- hb_tag_t tag_,
- hb_map_t *lookup_map_,
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
- hb_map_t *feature_index_map_) :
+ hb_tag_t tag_) :
subset_context (c_),
table_tag (tag_),
- lookup_index_map (lookup_map_),
- script_langsys_map (script_langsys_map_),
- feature_index_map (feature_index_map_),
cur_script_index (0xFFFFu),
+ cur_feature_var_record_idx (0u),
script_count (0),
langsys_count (0),
feature_index_count (0),
lookup_index_count (0)
- {}
+ {
+ 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;
+ }
+ 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;
+ }
+ }
private:
unsigned script_count;
@@ -190,6 +179,7 @@ struct hb_subset_layout_context_t :
unsigned lookup_index_count;
};
+struct VariationStore;
struct hb_collect_variation_indices_context_t :
hb_dispatch_context_t<hb_collect_variation_indices_context_t>
{
@@ -198,15 +188,27 @@ struct hb_collect_variation_indices_context_t :
static return_t default_return_value () { return hb_empty_t (); }
hb_set_t *layout_variation_indices;
+ hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map;
+ hb_font_t *font;
+ const VariationStore *var_store;
const hb_set_t *glyph_set;
const hb_map_t *gpos_lookups;
+ float *store_cache;
hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_,
+ hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map_,
+ hb_font_t *font_,
+ const VariationStore *var_store_,
const hb_set_t *glyph_set_,
- const hb_map_t *gpos_lookups_) :
+ const hb_map_t *gpos_lookups_,
+ float *store_cache_) :
layout_variation_indices (layout_variation_indices_),
+ varidx_delta_map (varidx_delta_map_),
+ font (font_),
+ var_store (var_store_),
glyph_set (glyph_set_),
- gpos_lookups (gpos_lookups_) {}
+ gpos_lookups (gpos_lookups_),
+ store_cache (store_cache_) {}
};
template<typename OutputArray>
@@ -315,6 +317,31 @@ struct subset_record_array_t
const void *base;
};
+template<typename OutputArray, typename Arg>
+struct subset_record_array_arg_t
+{
+ subset_record_array_arg_t (hb_subset_layout_context_t *c_, OutputArray* out_,
+ const void *base_,
+ Arg &&arg_) : subset_layout_context (c_),
+ out (out_), base (base_), arg (arg_) {}
+
+ template <typename T>
+ void
+ operator () (T&& record)
+ {
+ auto snap = subset_layout_context->subset_context->serializer->snapshot ();
+ bool ret = record.subset (subset_layout_context, base, arg);
+ if (!ret) subset_layout_context->subset_context->serializer->revert (snap);
+ else out->len++;
+ }
+
+ private:
+ hb_subset_layout_context_t *subset_layout_context;
+ OutputArray *out;
+ const void *base;
+ Arg &&arg;
+};
+
/*
* Helper to subset a RecordList/record array. Subsets each Record in the array and
* discards the record if the subset operation returns false.
@@ -326,6 +353,13 @@ struct
operator () (hb_subset_layout_context_t *c, OutputArray* out,
const void *base) const
{ return subset_record_array_t<OutputArray> (c, out, base); }
+
+ /* Variant with one extra argument passed to subset */
+ template<typename OutputArray, typename Arg>
+ subset_record_array_arg_t<OutputArray, Arg>
+ operator () (hb_subset_layout_context_t *c, OutputArray* out,
+ const void *base, Arg &&arg) const
+ { return subset_record_array_arg_t<OutputArray, Arg> (c, out, base, arg); }
}
HB_FUNCOBJ (subset_record_array);
@@ -377,166 +411,6 @@ HB_FUNCOBJ (serialize_math_record_array);
* Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
*/
-struct Record_sanitize_closure_t {
- hb_tag_t tag;
- const void *list_base;
-};
-
-template <typename Type>
-struct Record
-{
- int cmp (hb_tag_t a) const { return tag.cmp (a); }
-
- bool subset (hb_subset_layout_context_t *c, const void *base) const
- {
- TRACE_SUBSET (this);
- auto *out = c->subset_context->serializer->embed (this);
- if (unlikely (!out)) return_trace (false);
- bool ret = out->offset.serialize_subset (c->subset_context, offset, base, c, &tag);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- const Record_sanitize_closure_t closure = {tag, base};
- return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
- }
-
- Tag tag; /* 4-byte Tag identifier */
- Offset16To<Type>
- offset; /* Offset from beginning of object holding
- * the Record */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-
-template <typename Type>
-struct RecordArrayOf : SortedArray16Of<Record<Type>>
-{
- const Offset16To<Type>& get_offset (unsigned int i) const
- { return (*this)[i].offset; }
- Offset16To<Type>& get_offset (unsigned int i)
- { return (*this)[i].offset; }
- const Tag& get_tag (unsigned int i) const
- { return (*this)[i].tag; }
- unsigned int get_tags (unsigned int start_offset,
- unsigned int *record_count /* IN/OUT */,
- hb_tag_t *record_tags /* OUT */) const
- {
- if (record_count)
- {
- + this->sub_array (start_offset, record_count)
- | hb_map (&Record<Type>::tag)
- | hb_sink (hb_array (record_tags, *record_count))
- ;
- }
- return this->len;
- }
- bool find_index (hb_tag_t tag, unsigned int *index) const
- {
- return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
- }
-};
-
-template <typename Type>
-struct RecordListOf : RecordArrayOf<Type>
-{
- const Type& operator [] (unsigned int i) const
- { return this+this->get_offset (i); }
-
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- + this->iter ()
- | hb_apply (subset_record_array (l, out, this))
- ;
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (RecordArrayOf<Type>::sanitize (c, this));
- }
-};
-
-struct Feature;
-
-struct RecordListOfFeature : RecordListOf<Feature>
-{
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- unsigned count = this->len;
- + hb_zip (*this, hb_range (count))
- | hb_filter (l->feature_index_map, hb_second)
- | hb_map (hb_first)
- | hb_apply (subset_record_array (l, out, this))
- ;
- return_trace (true);
- }
-};
-
-struct Script;
-struct RecordListOfScript : RecordListOf<Script>
-{
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- unsigned count = this->len;
- for (auto _ : + hb_zip (*this, hb_range (count)))
- {
- auto snap = c->serializer->snapshot ();
- l->cur_script_index = _.second;
- bool ret = _.first.subset (l, this);
- if (!ret) c->serializer->revert (snap);
- else out->len++;
- }
-
- return_trace (true);
- }
-};
-
-struct RangeRecord
-{
- int cmp (hb_codepoint_t g) const
- { return g < first ? -1 : g <= last ? 0 : +1; }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- { return glyphs->intersects (first, last); }
-
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- { return glyphs->add_range (first, last); }
-
- HBGlyphID16 first; /* First GlyphID in the range */
- HBGlyphID16 last; /* Last GlyphID in the range */
- HBUINT16 value; /* Value */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
-
-
struct IndexArray : Array16Of<Index>
{
bool intersects (const hb_map_t *indexes) const
@@ -568,7 +442,7 @@ struct IndexArray : Array16Of<Index>
{
if (_count)
{
- + this->sub_array (start_offset, _count)
+ + this->as_array ().sub_array (start_offset, _count)
| hb_sink (hb_array (_indexes, *_count))
;
}
@@ -582,249 +456,6 @@ struct IndexArray : Array16Of<Index>
};
-struct LangSys
-{
- unsigned int get_feature_count () const
- { return featureIndex.len; }
- hb_tag_t get_feature_index (unsigned int i) const
- { return featureIndex[i]; }
- unsigned int get_feature_indexes (unsigned int start_offset,
- unsigned int *feature_count /* IN/OUT */,
- unsigned int *feature_indexes /* OUT */) const
- { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
- void add_feature_indexes_to (hb_set_t *feature_indexes) const
- { featureIndex.add_indexes_to (feature_indexes); }
-
- bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
- unsigned int get_required_feature_index () const
- {
- if (reqFeatureIndex == 0xFFFFu)
- return Index::NOT_FOUND_INDEX;
- return reqFeatureIndex;
- }
-
- LangSys* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- return_trace (c->embed (*this));
- }
-
- bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
- {
- if (reqFeatureIndex != o.reqFeatureIndex)
- return false;
-
- auto iter =
- + hb_iter (featureIndex)
- | hb_filter (feature_index_map)
- | hb_map (feature_index_map)
- ;
-
- auto o_iter =
- + hb_iter (o.featureIndex)
- | hb_filter (feature_index_map)
- | hb_map (feature_index_map)
- ;
-
- for (; iter && o_iter; iter++, o_iter++)
- {
- unsigned a = *iter;
- unsigned b = *o_iter;
- if (a != b) return false;
- }
-
- if (iter || o_iter) return false;
-
- return true;
- }
-
- void collect_features (hb_prune_langsys_context_t *c) const
- {
- if (!has_required_feature () && !get_feature_count ()) return;
- if (has_required_feature () &&
- c->duplicate_feature_map->has (reqFeatureIndex))
- c->new_feature_indexes->add (get_required_feature_index ());
-
- + hb_iter (featureIndex)
- | hb_filter (c->duplicate_feature_map)
- | hb_sink (c->new_feature_indexes)
- ;
- }
-
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l,
- const Tag *tag = nullptr) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex) ? l->feature_index_map->get (reqFeatureIndex) : 0xFFFFu;
-
- if (!l->visitFeatureIndex (featureIndex.len))
- return_trace (false);
-
- auto it =
- + hb_iter (featureIndex)
- | hb_filter (l->feature_index_map)
- | hb_map (l->feature_index_map)
- ;
-
- bool ret = bool (it);
- out->featureIndex.serialize (c->serializer, l, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c,
- const Record_sanitize_closure_t * = nullptr) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && featureIndex.sanitize (c));
- }
-
- Offset16 lookupOrderZ; /* = Null (reserved for an offset to a
- * reordering table) */
- HBUINT16 reqFeatureIndex;/* Index of a feature required for this
- * language system--if no required features
- * = 0xFFFFu */
- IndexArray featureIndex; /* Array of indices into the FeatureList */
- public:
- DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
-};
-DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
-
-struct Script
-{
- unsigned int get_lang_sys_count () const
- { return langSys.len; }
- const Tag& get_lang_sys_tag (unsigned int i) const
- { return langSys.get_tag (i); }
- unsigned int get_lang_sys_tags (unsigned int start_offset,
- unsigned int *lang_sys_count /* IN/OUT */,
- hb_tag_t *lang_sys_tags /* OUT */) const
- { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
- const LangSys& get_lang_sys (unsigned int i) const
- {
- if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
- return this+langSys[i].offset;
- }
- bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
- { return langSys.find_index (tag, index); }
-
- bool has_default_lang_sys () const { return defaultLangSys != 0; }
- const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
-
- void prune_langsys (hb_prune_langsys_context_t *c,
- unsigned script_index) const
- {
- if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
- if (!c->visitScript ()) return;
-
- if (!c->script_langsys_map->has (script_index))
- {
- hb_set_t* empty_set = hb_set_create ();
- if (unlikely (!c->script_langsys_map->set (script_index, empty_set)))
- {
- hb_set_destroy (empty_set);
- return;
- }
- }
-
- unsigned langsys_count = get_lang_sys_count ();
- if (has_default_lang_sys ())
- {
- //only collect features from non-redundant langsys
- const LangSys& d = get_default_lang_sys ();
- if (c->visitLangsys (d.get_feature_count ())) {
- d.collect_features (c);
- }
-
- for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
- {
- const LangSys& l = this+_.first.offset;
- if (!c->visitLangsys (l.get_feature_count ())) continue;
- if (l.compare (d, c->duplicate_feature_map)) continue;
-
- l.collect_features (c);
- c->script_langsys_map->get (script_index)->add (_.second);
- }
- }
- else
- {
- for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
- {
- const LangSys& l = this+_.first.offset;
- if (!c->visitLangsys (l.get_feature_count ())) continue;
- l.collect_features (c);
- c->script_langsys_map->get (script_index)->add (_.second);
- }
- }
- }
-
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l,
- const Tag *tag) const
- {
- TRACE_SUBSET (this);
- if (!l->visitScript ()) return_trace (false);
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- bool defaultLang = false;
- if (has_default_lang_sys ())
- {
- c->serializer->push ();
- const LangSys& ls = this+defaultLangSys;
- bool ret = ls.subset (c, l);
- if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
- {
- c->serializer->pop_discard ();
- out->defaultLangSys = 0;
- }
- else
- {
- c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
- defaultLang = true;
- }
- }
-
- const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
- if (active_langsys)
- {
- unsigned count = langSys.len;
- + hb_zip (langSys, hb_range (count))
- | hb_filter (active_langsys, hb_second)
- | hb_map (hb_first)
- | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
- | hb_apply (subset_record_array (l, &(out->langSys), this))
- ;
- }
-
- return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
- }
-
- bool sanitize (hb_sanitize_context_t *c,
- const Record_sanitize_closure_t * = nullptr) const
- {
- TRACE_SANITIZE (this);
- return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
- }
-
- protected:
- Offset16To<LangSys>
- defaultLangSys; /* Offset to DefaultLangSys table--from
- * beginning of Script table--may be Null */
- RecordArrayOf<LangSys>
- langSys; /* Array of LangSysRecords--listed
- * alphabetically by LangSysTag */
- public:
- DEFINE_SIZE_ARRAY_SIZED (4, langSys);
-};
-
-typedef RecordListOfScript ScriptList;
-
-
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
struct FeatureParamsSize
{
@@ -991,7 +622,7 @@ struct FeatureParamsCharacterVariants
{
if (char_count)
{
- + characters.sub_array (start_offset, char_count)
+ + characters.as_array ().sub_array (start_offset, char_count)
| hb_sink (hb_array (chars, *char_count))
;
}
@@ -1107,6 +738,11 @@ struct FeatureParams
DEFINE_SIZE_MIN (0);
};
+struct Record_sanitize_closure_t {
+ hb_tag_t tag;
+ const void *list_base;
+};
+
struct Feature
{
unsigned int get_lookup_count () const
@@ -1202,9 +838,395 @@ struct Feature
DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
};
+template <typename Type>
+struct Record
+{
+ int cmp (hb_tag_t a) const { return tag.cmp (a); }
+
+ bool subset (hb_subset_layout_context_t *c, const void *base, const void *f_sub = nullptr) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->subset_context->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ if (!f_sub)
+ return_trace (out->offset.serialize_subset (c->subset_context, offset, base, c, &tag));
+
+ const Feature& f = *reinterpret_cast<const Feature *> (f_sub);
+ auto *s = c->subset_context->serializer;
+ s->push ();
+
+ out->offset = 0;
+ bool ret = f.subset (c->subset_context, c, &tag);
+ if (ret)
+ s->add_link (out->offset, s->pop_pack ());
+ else
+ s->pop_discard ();
+
+ return_trace (ret);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ const Record_sanitize_closure_t closure = {tag, base};
+ return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
+ }
+
+ Tag tag; /* 4-byte Tag identifier */
+ Offset16To<Type>
+ offset; /* Offset from beginning of object holding
+ * the Record */
+ public:
+ DEFINE_SIZE_STATIC (6);
+};
+
+template <typename Type>
+struct RecordArrayOf : SortedArray16Of<Record<Type>>
+{
+ const Offset16To<Type>& get_offset (unsigned int i) const
+ { return (*this)[i].offset; }
+ Offset16To<Type>& get_offset (unsigned int i)
+ { return (*this)[i].offset; }
+ const Tag& get_tag (unsigned int i) const
+ { return (*this)[i].tag; }
+ unsigned int get_tags (unsigned int start_offset,
+ unsigned int *record_count /* IN/OUT */,
+ hb_tag_t *record_tags /* OUT */) const
+ {
+ if (record_count)
+ {
+ + this->as_array ().sub_array (start_offset, record_count)
+ | hb_map (&Record<Type>::tag)
+ | hb_sink (hb_array (record_tags, *record_count))
+ ;
+ }
+ return this->len;
+ }
+ bool find_index (hb_tag_t tag, unsigned int *index) const
+ {
+ return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+ }
+};
+
+template <typename Type>
+struct RecordListOf : RecordArrayOf<Type>
+{
+ const Type& operator [] (unsigned int i) const
+ { return this+this->get_offset (i); }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ + this->iter ()
+ | hb_apply (subset_record_array (l, out, this))
+ ;
+ return_trace (true);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (RecordArrayOf<Type>::sanitize (c, this));
+ }
+};
+
+struct RecordListOfFeature : RecordListOf<Feature>
+{
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ + hb_enumerate (*this)
+ | hb_filter (l->feature_index_map, hb_first)
+ | hb_apply ([l, out, this] (const hb_pair_t<unsigned, const Record<Feature>&>& _)
+ {
+ const Feature *f_sub = nullptr;
+ const Feature **f = nullptr;
+ if (l->feature_substitutes_map->has (_.first, &f))
+ f_sub = *f;
+
+ subset_record_array (l, out, this, f_sub) (_.second);
+ })
+ ;
+
+ return_trace (true);
+ }
+};
+
typedef RecordListOf<Feature> FeatureList;
+struct LangSys
+{
+ unsigned int get_feature_count () const
+ { return featureIndex.len; }
+ hb_tag_t get_feature_index (unsigned int i) const
+ { return featureIndex[i]; }
+ unsigned int get_feature_indexes (unsigned int start_offset,
+ unsigned int *feature_count /* IN/OUT */,
+ unsigned int *feature_indexes /* OUT */) const
+ { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
+ void add_feature_indexes_to (hb_set_t *feature_indexes) const
+ { featureIndex.add_indexes_to (feature_indexes); }
+
+ bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
+ unsigned int get_required_feature_index () const
+ {
+ if (reqFeatureIndex == 0xFFFFu)
+ return Index::NOT_FOUND_INDEX;
+ return reqFeatureIndex;
+ }
+
+ LangSys* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed (*this));
+ }
+
+ bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
+ {
+ if (reqFeatureIndex != o.reqFeatureIndex)
+ return false;
+
+ auto iter =
+ + hb_iter (featureIndex)
+ | hb_filter (feature_index_map)
+ | hb_map (feature_index_map)
+ ;
+
+ auto o_iter =
+ + hb_iter (o.featureIndex)
+ | hb_filter (feature_index_map)
+ | hb_map (feature_index_map)
+ ;
+
+ for (; iter && o_iter; iter++, o_iter++)
+ {
+ unsigned a = *iter;
+ unsigned b = *o_iter;
+ if (a != b) return false;
+ }
+
+ if (iter || o_iter) return false;
+
+ return true;
+ }
+
+ void collect_features (hb_prune_langsys_context_t *c) const
+ {
+ if (!has_required_feature () && !get_feature_count ()) return;
+ if (has_required_feature () &&
+ c->duplicate_feature_map->has (reqFeatureIndex))
+ c->new_feature_indexes->add (get_required_feature_index ());
+
+ + hb_iter (featureIndex)
+ | hb_filter (c->duplicate_feature_map)
+ | hb_sink (c->new_feature_indexes)
+ ;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l,
+ const Tag *tag = nullptr) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ const uint32_t *v;
+ out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
+
+ if (!l->visitFeatureIndex (featureIndex.len))
+ return_trace (false);
+
+ auto it =
+ + hb_iter (featureIndex)
+ | hb_filter (l->feature_index_map)
+ | hb_map (l->feature_index_map)
+ ;
+
+ bool ret = bool (it);
+ out->featureIndex.serialize (c->serializer, l, it);
+ return_trace (ret);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c,
+ const Record_sanitize_closure_t * = nullptr) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && featureIndex.sanitize (c));
+ }
+
+ Offset16 lookupOrderZ; /* = Null (reserved for an offset to a
+ * reordering table) */
+ HBUINT16 reqFeatureIndex;/* Index of a feature required for this
+ * language system--if no required features
+ * = 0xFFFFu */
+ IndexArray featureIndex; /* Array of indices into the FeatureList */
+ public:
+ DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
+
+struct Script
+{
+ unsigned int get_lang_sys_count () const
+ { return langSys.len; }
+ const Tag& get_lang_sys_tag (unsigned int i) const
+ { return langSys.get_tag (i); }
+ unsigned int get_lang_sys_tags (unsigned int start_offset,
+ unsigned int *lang_sys_count /* IN/OUT */,
+ hb_tag_t *lang_sys_tags /* OUT */) const
+ { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
+ const LangSys& get_lang_sys (unsigned int i) const
+ {
+ if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
+ return this+langSys[i].offset;
+ }
+ bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
+ { return langSys.find_index (tag, index); }
+
+ bool has_default_lang_sys () const { return defaultLangSys != 0; }
+ const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
+
+ void prune_langsys (hb_prune_langsys_context_t *c,
+ unsigned script_index) const
+ {
+ if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
+ if (!c->visitScript ()) return;
+
+ if (!c->script_langsys_map->has (script_index))
+ {
+ if (unlikely (!c->script_langsys_map->set (script_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
+ return;
+ }
+
+ if (has_default_lang_sys ())
+ {
+ //only collect features from non-redundant langsys
+ const LangSys& d = get_default_lang_sys ();
+ if (c->visitLangsys (d.get_feature_count ())) {
+ d.collect_features (c);
+ }
+
+ for (auto _ : + hb_enumerate (langSys))
+ {
+ const LangSys& l = this+_.second.offset;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
+ if (l.compare (d, c->duplicate_feature_map)) continue;
+
+ l.collect_features (c);
+ c->script_langsys_map->get (script_index)->add (_.first);
+ }
+ }
+ else
+ {
+ for (auto _ : + hb_enumerate (langSys))
+ {
+ const LangSys& l = this+_.second.offset;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
+ l.collect_features (c);
+ c->script_langsys_map->get (script_index)->add (_.first);
+ }
+ }
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l,
+ const Tag *tag) const
+ {
+ TRACE_SUBSET (this);
+ if (!l->visitScript ()) return_trace (false);
+ if (tag && !c->plan->layout_scripts.has (*tag))
+ return false;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ bool defaultLang = false;
+ if (has_default_lang_sys ())
+ {
+ c->serializer->push ();
+ const LangSys& ls = this+defaultLangSys;
+ bool ret = ls.subset (c, l);
+ if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
+ {
+ c->serializer->pop_discard ();
+ out->defaultLangSys = 0;
+ }
+ else
+ {
+ c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
+ defaultLang = true;
+ }
+ }
+
+ const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
+ if (active_langsys)
+ {
+ + hb_enumerate (langSys)
+ | hb_filter (active_langsys, hb_first)
+ | hb_map (hb_second)
+ | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
+ | hb_apply (subset_record_array (l, &(out->langSys), this))
+ ;
+ }
+
+ return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c,
+ const Record_sanitize_closure_t * = nullptr) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
+ }
+
+ protected:
+ Offset16To<LangSys>
+ defaultLangSys; /* Offset to DefaultLangSys table--from
+ * beginning of Script table--may be Null */
+ RecordArrayOf<LangSys>
+ langSys; /* Array of LangSysRecords--listed
+ * alphabetically by LangSysTag */
+ public:
+ DEFINE_SIZE_ARRAY_SIZED (4, langSys);
+};
+
+struct RecordListOfScript : RecordListOf<Script>
+{
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ for (auto _ : + hb_enumerate (*this))
+ {
+ auto snap = c->serializer->snapshot ();
+ l->cur_script_index = _.first;
+ bool ret = _.second.subset (l, this);
+ if (!ret) c->serializer->revert (snap);
+ else out->len++;
+ }
+
+ return_trace (true);
+ }
+};
+
+typedef RecordListOfScript ScriptList;
+
+
+
struct LookupFlag : HBUINT16
{
enum Flags {
@@ -1325,7 +1347,13 @@ struct Lookup
outMarkFilteringSet = markFilteringSet;
}
- return_trace (out->subTable.len);
+ // Always keep the lookup even if it's empty. The rest of layout subsetting depends on lookup
+ // indices being consistent with those computed during planning. So if an empty lookup is
+ // discarded during the subset phase it will invalidate all subsequent lookup indices.
+ // 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_trace (true);
}
template <typename TSubTable>
@@ -1346,7 +1374,7 @@ struct Lookup
if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
return_trace (false);
- if (unlikely (get_type () == TSubTable::Extension && subtables && !c->get_edit_count ()))
+ if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
{
/* The spec says all subtables of an Extension lookup should
* have the same type, which shall not be the Extension type
@@ -1366,7 +1394,7 @@ struct Lookup
return_trace (true);
}
- private:
+ protected:
HBUINT16 lookupType; /* Different enumerations for GSUB and GPOS */
HBUINT16 lookupFlag; /* Lookup qualifiers */
Array16Of<Offset16>
@@ -1378,10 +1406,11 @@ struct Lookup
DEFINE_SIZE_ARRAY (6, subTable);
};
-typedef List16OfOffset16To<Lookup> LookupList;
+template <typename Types>
+using LookupList = List16OfOffsetTo<Lookup, typename Types::HBUINT>;
-template <typename TLookup>
-struct LookupOffsetList : List16OfOffset16To<TLookup>
+template <typename TLookup, typename OffsetType>
+struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
{
bool subset (hb_subset_context_t *c,
hb_subset_layout_context_t *l) const
@@ -1390,10 +1419,9 @@ struct LookupOffsetList : List16OfOffset16To<TLookup>
auto *out = c->serializer->start_embed (this);
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
- unsigned count = this->len;
- + hb_zip (*this, hb_range (count))
- | hb_filter (l->lookup_index_map, hb_second)
- | hb_map (hb_first)
+ + hb_enumerate (*this)
+ | hb_filter (l->lookup_index_map, hb_first)
+ | hb_map (hb_second)
| hb_apply (subset_offset_array (c, *out, this))
;
return_trace (true);
@@ -1411,464 +1439,15 @@ struct LookupOffsetList : List16OfOffset16To<TLookup>
* Coverage Table
*/
-struct CoverageFormat1
-{
- friend struct Coverage;
-
- private:
- unsigned int get_coverage (hb_codepoint_t glyph_id) const
- {
- unsigned int i;
- glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
- return i;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c, Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- return_trace (glyphArray.serialize (c, glyphs));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (glyphArray.sanitize (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- /* TODO Speed up, using hb_set_next() and bsearch()? */
- for (const auto& g : glyphArray.as_array ())
- if (glyphs->has (g))
- return true;
- return false;
- }
- bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
- { return glyphs->has (glyphArray[index]); }
-
- void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
- {
- unsigned count = glyphArray.len;
- for (unsigned i = 0; i < count; i++)
- if (glyphs->has (glyphArray[i]))
- intersect_glyphs->add (glyphArray[i]);
- }
-
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- { return glyphs->add_sorted_array (glyphArray.as_array ()); }
-
- public:
- /* Older compilers need this to be public. */
- struct iter_t
- {
- void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }
- void fini () {}
- bool more () const { return i < c->glyphArray.len; }
- void next () { i++; }
- hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
- bool operator != (const iter_t& o) const
- { return i != o.i || c != o.c; }
-
- private:
- const struct CoverageFormat1 *c;
- unsigned int i;
- };
- private:
-
- protected:
- HBUINT16 coverageFormat; /* Format identifier--format = 1 */
- SortedArray16Of<HBGlyphID16>
- glyphArray; /* Array of GlyphIDs--in numerical order */
- public:
- DEFINE_SIZE_ARRAY (4, glyphArray);
-};
-
-struct CoverageFormat2
-{
- friend struct Coverage;
-
- private:
- unsigned int get_coverage (hb_codepoint_t glyph_id) const
- {
- const RangeRecord &range = rangeRecord.bsearch (glyph_id);
- return likely (range.first <= range.last)
- ? (unsigned int) range.value + (glyph_id - range.first)
- : NOT_COVERED;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c, Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
-
- if (unlikely (!glyphs))
- {
- rangeRecord.len = 0;
- return_trace (true);
- }
-
- /* TODO(iter) Write more efficiently? */
-
- unsigned num_ranges = 0;
- hb_codepoint_t last = (hb_codepoint_t) -2;
- for (auto g: glyphs)
- {
- if (last + 1 != g)
- num_ranges++;
- last = g;
- }
-
- if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
-
- unsigned count = 0;
- unsigned range = (unsigned) -1;
- last = (hb_codepoint_t) -2;
- for (auto g: glyphs)
- {
- if (last + 1 != g)
- {
- range++;
- rangeRecord[range].first = g;
- rangeRecord[range].value = count;
- }
- rangeRecord[range].last = g;
- last = g;
- count++;
- }
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (rangeRecord.sanitize (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- /* TODO Speed up, using hb_set_next() and bsearch()? */
- /* TODO(iter) Rewrite as dagger. */
- for (const auto& range : rangeRecord.as_array ())
- if (range.intersects (glyphs))
- return true;
- return false;
- }
- bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
- {
- /* TODO(iter) Rewrite as dagger. */
- for (const auto& range : rangeRecord.as_array ())
- {
- if (range.value <= index &&
- index < (unsigned int) range.value + (range.last - range.first) &&
- range.intersects (glyphs))
- return true;
- else if (index < range.value)
- return false;
- }
- return false;
- }
-
- void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
- {
- for (const auto& range : rangeRecord.as_array ())
- {
- if (!range.intersects (glyphs)) continue;
- for (hb_codepoint_t g = range.first; g <= range.last; g++)
- if (glyphs->has (g)) intersect_glyphs->add (g);
- }
- }
-
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- {
- unsigned int count = rangeRecord.len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
- return false;
- return true;
- }
-
- public:
- /* Older compilers need this to be public. */
- struct iter_t
- {
- void init (const CoverageFormat2 &c_)
- {
- c = &c_;
- coverage = 0;
- i = 0;
- j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
- if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
- {
- /* Broken table. Skip. */
- i = c->rangeRecord.len;
- }
- }
- void fini () {}
- bool more () const { return i < c->rangeRecord.len; }
- void next ()
- {
- if (j >= c->rangeRecord[i].last)
- {
- i++;
- if (more ())
- {
- unsigned int old = coverage;
- j = c->rangeRecord[i].first;
- coverage = c->rangeRecord[i].value;
- if (unlikely (coverage != old + 1))
- {
- /* Broken table. Skip. Important to avoid DoS.
- * Also, our callers depend on coverage being
- * consecutive and monotonically increasing,
- * ie. iota(). */
- i = c->rangeRecord.len;
- return;
- }
- }
- return;
- }
- coverage++;
- j++;
- }
- hb_codepoint_t get_glyph () const { return j; }
- bool operator != (const iter_t& o) const
- { return i != o.i || j != o.j || c != o.c; }
-
- private:
- const struct CoverageFormat2 *c;
- unsigned int i, coverage;
- hb_codepoint_t j;
- };
- private:
-
- protected:
- HBUINT16 coverageFormat; /* Format identifier--format = 2 */
- SortedArray16Of<RangeRecord>
- rangeRecord; /* Array of glyph ranges--ordered by
- * Start GlyphID. rangeCount entries
- * long */
- public:
- DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct Coverage
-{
- /* Has interface. */
- static constexpr unsigned SENTINEL = NOT_COVERED;
- typedef unsigned int value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
- /* Predicate. */
- bool operator () (hb_codepoint_t k) const { return has (k); }
-
- unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
- unsigned int get_coverage (hb_codepoint_t glyph_id) const
- {
- switch (u.format) {
- case 1: return u.format1.get_coverage (glyph_id);
- case 2: return u.format2.get_coverage (glyph_id);
- default:return NOT_COVERED;
- }
- }
-
- template <typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c, Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
-
- unsigned count = 0;
- unsigned num_ranges = 0;
- hb_codepoint_t last = (hb_codepoint_t) -2;
- for (auto g: glyphs)
- {
- if (last + 1 != g)
- num_ranges++;
- last = g;
- count++;
- }
- u.format = count <= num_ranges * 3 ? 1 : 2;
-
- switch (u.format)
- {
- case 1: return_trace (u.format1.serialize (c, glyphs));
- case 2: return_trace (u.format2.serialize (c, glyphs));
- default:return_trace (false);
- }
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + iter ()
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- bool ret = bool (it);
- Coverage_serialize (c->serializer, it);
- return_trace (ret);
- }
-
- 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));
- default:return_trace (true);
- }
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- switch (u.format)
- {
- case 1: return u.format1.intersects (glyphs);
- case 2: return u.format2.intersects (glyphs);
- default:return false;
- }
- }
- bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
- {
- switch (u.format)
- {
- case 1: return u.format1.intersects_coverage (glyphs, index);
- case 2: return u.format2.intersects_coverage (glyphs, index);
- default:return false;
- }
- }
-
- /* Might return false if array looks unsorted.
- * Used for faster rejection of corrupt data. */
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- {
- switch (u.format)
- {
- case 1: return u.format1.collect_coverage (glyphs);
- case 2: return u.format2.collect_coverage (glyphs);
- default:return false;
- }
- }
-
- void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
- {
- switch (u.format)
- {
- case 1: return u.format1.intersected_coverage_glyphs (glyphs, intersect_glyphs);
- case 2: return u.format2.intersected_coverage_glyphs (glyphs, intersect_glyphs);
- default:return ;
- }
- }
- struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
- {
- static constexpr bool is_sorted_iterator = true;
- iter_t (const Coverage &c_ = Null (Coverage))
- {
- memset (this, 0, sizeof (*this));
- format = c_.u.format;
- switch (format)
- {
- case 1: u.format1.init (c_.u.format1); return;
- case 2: u.format2.init (c_.u.format2); return;
- default: return;
- }
- }
- bool __more__ () const
- {
- switch (format)
- {
- case 1: return u.format1.more ();
- case 2: return u.format2.more ();
- default:return false;
- }
- }
- void __next__ ()
- {
- switch (format)
- {
- case 1: u.format1.next (); break;
- case 2: u.format2.next (); break;
- default: break;
- }
- }
- typedef hb_codepoint_t __item_t__;
- __item_t__ __item__ () const { return get_glyph (); }
-
- hb_codepoint_t get_glyph () const
- {
- switch (format)
- {
- case 1: return u.format1.get_glyph ();
- case 2: return u.format2.get_glyph ();
- default:return 0;
- }
- }
- bool operator != (const iter_t& o) const
- {
- if (format != o.format) return true;
- switch (format)
- {
- case 1: return u.format1 != o.u.format1;
- case 2: return u.format2 != o.u.format2;
- default:return false;
- }
- }
-
- private:
- unsigned int format;
- union {
- CoverageFormat2::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
- CoverageFormat1::iter_t format1;
- } u;
- };
- iter_t iter () const { return iter_t (*this); }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- CoverageFormat1 format1;
- CoverageFormat2 format2;
- } u;
- public:
- DEFINE_SIZE_UNION (2, format);
-};
-
-template<typename Iterator>
-static inline void
-Coverage_serialize (hb_serialize_context_t *c,
- Iterator it)
-{ c->start_embed<Coverage> ()->serialize (c, it); }
-
-static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
- const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID16> &glyphs,
+static bool ClassDef_remap_and_serialize (hb_serialize_context_t *c,
const hb_set_t &klasses,
bool use_class_zero,
- hb_map_t *klass_map /*INOUT*/)
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_map_t *klass_map /*IN/OUT*/)
{
if (!klass_map)
- {
- ClassDef_serialize (c, hb_zip (glyphs.iter (), + glyphs.iter ()
- | hb_map (gid_klass_map)));
- return;
- }
+ return ClassDef_serialize (c, glyph_and_klass.iter ());
/* any glyph not assigned a class value falls into Class zero (0),
* if any glyph assigned to class 0, remapping must start with 0->0*/
@@ -1876,31 +1455,30 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
klass_map->set (0, 0);
unsigned idx = klass_map->has (0) ? 1 : 0;
- for (const unsigned k: klasses.iter ())
+ for (const unsigned k: klasses)
{
if (klass_map->has (k)) continue;
klass_map->set (k, idx);
idx++;
}
- auto it =
- + glyphs.iter ()
- | hb_map_retains_sorting ([&] (const HBGlyphID16& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
- {
- unsigned new_klass = klass_map->get (gid_klass_map[gid]);
- return hb_pair ((hb_codepoint_t)gid, new_klass);
- })
- ;
- c->propagate_error (glyphs, klasses);
- ClassDef_serialize (c, it);
+ for (unsigned i = 0; i < glyph_and_klass.length; i++)
+ {
+ hb_codepoint_t klass = glyph_and_klass[i].second;
+ glyph_and_klass[i].second = klass_map->get (klass);
+ }
+
+ c->propagate_error (glyph_and_klass, klasses);
+ return ClassDef_serialize (c, glyph_and_klass.iter ());
}
/*
* Class Definition Table
*/
-struct ClassDefFormat1
+template <typename Types>
+struct ClassDefFormat1_3
{
friend struct ClassDef;
@@ -1910,8 +1488,13 @@ struct ClassDefFormat1
return classValue[(unsigned int) (glyph_id - startGlyph)];
}
+ unsigned get_population () const
+ {
+ return classValue.len;
+ }
+
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c,
Iterator it)
{
@@ -1934,7 +1517,7 @@ struct ClassDefFormat1
startGlyph = glyph_min;
if (unlikely (!classValue.serialize (c, glyph_count))) return_trace (false);
- for (const hb_pair_t<hb_codepoint_t, unsigned> gid_klass_pair : + it)
+ for (const hb_pair_t<hb_codepoint_t, uint32_t> gid_klass_pair : + it)
{
unsigned idx = gid_klass_pair.first - glyph_min;
classValue[idx] = gid_klass_pair.second;
@@ -1949,36 +1532,38 @@ struct ClassDefFormat1
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
+ const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
- hb_sorted_vector_t<HBGlyphID16> glyphs;
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
- hb_map_t gid_org_klass_map;
hb_codepoint_t start = startGlyph;
hb_codepoint_t end = start + classValue.len;
- for (const hb_codepoint_t gid : + hb_range (start, end)
- | hb_filter (glyphset))
+ for (const hb_codepoint_t gid : + hb_range (start, end))
{
+ hb_codepoint_t new_gid = glyph_map[gid];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
if (glyph_filter && !glyph_filter->has(gid)) continue;
unsigned klass = classValue[gid - start];
if (!klass) continue;
- glyphs.push (glyph_map[gid]);
- gid_org_klass_map.set (glyph_map[gid], klass);
+ glyph_and_klass.push (hb_pair (new_gid, klass));
orig_klasses.add (klass);
}
unsigned glyph_count = glyph_filter
- ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
- : glyphset.get_population ();
- use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
- ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
- glyphs, orig_klasses, use_class_zero, klass_map);
- return_trace (keep_empty_table || (bool) glyphs);
+ ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter))
+ : glyph_map.get_population ();
+ use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+ if (!ClassDef_remap_and_serialize (c->serializer,
+ orig_klasses,
+ use_class_zero,
+ glyph_and_klass,
+ klass_map))
+ return_trace (false);
+ return_trace (keep_empty_table || (bool) glyph_and_klass);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -1987,6 +1572,8 @@ struct ClassDefFormat1
return_trace (c->check_struct (this) && classValue.sanitize (c));
}
+ unsigned cost () const { return 1; }
+
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{
@@ -2021,11 +1608,10 @@ struct ClassDefFormat1
bool intersects (const hb_set_t *glyphs) const
{
- /* TODO Speed up, using hb_set_next()? */
hb_codepoint_t start = startGlyph;
hb_codepoint_t end = startGlyph + classValue.len;
for (hb_codepoint_t iter = startGlyph - 1;
- hb_set_next (glyphs, &iter) && iter < end;)
+ glyphs->next (&iter) && iter < end;)
if (classValue[iter - start]) return true;
return false;
}
@@ -2036,18 +1622,17 @@ struct ClassDefFormat1
{
/* Match if there's any glyph that is not listed! */
hb_codepoint_t g = HB_SET_VALUE_INVALID;
- if (!hb_set_next (glyphs, &g)) return false;
+ if (!glyphs->next (&g)) return false;
if (g < startGlyph) return true;
g = startGlyph + count - 1;
- if (hb_set_next (glyphs, &g)) return true;
+ if (glyphs->next (&g)) return true;
/* Fall through. */
}
/* TODO Speed up, using set overlap first? */
/* TODO(iter) Rewrite as dagger. */
- HBUINT16 k {klass};
const HBUINT16 *arr = classValue.arrayZ;
for (unsigned int i = 0; i < count; i++)
- if (arr[i] == k && glyphs->has (startGlyph + i))
+ if (arr[i] == klass && glyphs->has (startGlyph + i))
return true;
return false;
}
@@ -2057,17 +1642,32 @@ struct ClassDefFormat1
unsigned count = classValue.len;
if (klass == 0)
{
- hb_codepoint_t endGlyph = startGlyph + count -1;
- for (hb_codepoint_t g : glyphs->iter ())
- if (g < startGlyph || g > endGlyph)
- intersect_glyphs->add (g);
+ unsigned start_glyph = startGlyph;
+ for (uint32_t g = HB_SET_VALUE_INVALID;
+ glyphs->next (&g) && g < start_glyph;)
+ intersect_glyphs->add (g);
+
+ for (uint32_t g = startGlyph + count - 1;
+ glyphs-> next (&g);)
+ intersect_glyphs->add (g);
return;
}
for (unsigned i = 0; i < count; i++)
if (classValue[i] == klass && glyphs->has (startGlyph + i))
- intersect_glyphs->add (startGlyph + i);
+ intersect_glyphs->add (startGlyph + i);
+
+#if 0
+ /* The following implementation is faster asymptotically, but slower
+ * in practice. */
+ unsigned start_glyph = startGlyph;
+ unsigned end_glyph = start_glyph + count;
+ for (unsigned g = startGlyph - 1;
+ glyphs->next (&g) && g < end_glyph;)
+ if (classValue.arrayZ[g - start_glyph] == klass)
+ intersect_glyphs->add (g);
+#endif
}
void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
@@ -2088,14 +1688,16 @@ struct ClassDefFormat1
protected:
HBUINT16 classFormat; /* Format identifier--format = 1 */
- HBGlyphID16 startGlyph; /* First GlyphID of the classValueArray */
- Array16Of<HBUINT16>
+ typename Types::HBGlyphID
+ startGlyph; /* First GlyphID of the classValueArray */
+ typename Types::template ArrayOf<HBUINT16>
classValue; /* Array of Class Values--one per GlyphID */
public:
- DEFINE_SIZE_ARRAY (6, classValue);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, classValue);
};
-struct ClassDefFormat2
+template <typename Types>
+struct ClassDefFormat2_4
{
friend struct ClassDef;
@@ -2105,8 +1707,16 @@ struct ClassDefFormat2
return rangeRecord.bsearch (glyph_id).value;
}
+ unsigned get_population () const
+ {
+ typename Types::large_int ret = 0;
+ for (const auto &r : rangeRecord)
+ ret += r.get_population ();
+ return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
+ }
+
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c,
Iterator it)
{
@@ -2124,12 +1734,12 @@ struct ClassDefFormat2
hb_codepoint_t prev_gid = (*it).first;
unsigned prev_klass = (*it).second;
- RangeRecord range_rec;
+ RangeRecord<Types> range_rec;
range_rec.first = prev_gid;
range_rec.last = prev_gid;
range_rec.value = prev_klass;
- RangeRecord *record = c->copy (range_rec);
+ auto *record = c->copy (range_rec);
if (unlikely (!record)) return_trace (false);
for (const auto gid_klass_pair : + (++it))
@@ -2167,37 +1777,59 @@ struct ClassDefFormat2
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
+ 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<HBGlyphID16> glyphs;
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
- hb_map_t gid_org_klass_map;
- unsigned count = rangeRecord.len;
- for (unsigned i = 0; i < count; i++)
+ if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2
+ < get_population ())
{
- unsigned klass = rangeRecord[i].value;
- if (!klass) continue;
- hb_codepoint_t start = rangeRecord[i].first;
- hb_codepoint_t end = rangeRecord[i].last + 1;
- for (hb_codepoint_t g = start; g < end; g++)
+ for (hb_codepoint_t g : glyph_set)
{
- if (!glyphset.has (g)) continue;
- if (glyph_filter && !glyph_filter->has (g)) continue;
- glyphs.push (glyph_map[g]);
- gid_org_klass_map.set (glyph_map[g], klass);
+ unsigned klass = get_class (g);
+ if (!klass) continue;
+ hb_codepoint_t new_gid = glyph_map[g];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
+ if (glyph_filter && !glyph_filter->has (g)) continue;
+ glyph_and_klass.push (hb_pair (new_gid, klass));
orig_klasses.add (klass);
}
}
+ else
+ {
+ unsigned num_source_glyphs = c->plan->source->get_num_glyphs ();
+ for (auto &range : rangeRecord)
+ {
+ unsigned klass = range.value;
+ if (!klass) continue;
+ hb_codepoint_t start = range.first;
+ hb_codepoint_t end = hb_min (range.last + 1, num_source_glyphs);
+ for (hb_codepoint_t g = start; g < end; g++)
+ {
+ hb_codepoint_t new_gid = glyph_map[g];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
+ if (glyph_filter && !glyph_filter->has (g)) continue;
+
+ glyph_and_klass.push (hb_pair (new_gid, klass));
+ orig_klasses.add (klass);
+ }
+ }
+ }
+ const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
unsigned glyph_count = glyph_filter
? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
- : glyphset.get_population ();
- use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
- ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
- glyphs, orig_klasses, use_class_zero, klass_map);
- return_trace (keep_empty_table || (bool) glyphs);
+ : glyph_map.get_population ();
+ use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+ if (!ClassDef_remap_and_serialize (c->serializer,
+ orig_klasses,
+ use_class_zero,
+ glyph_and_klass,
+ klass_map))
+ return_trace (false);
+ return_trace (keep_empty_table || (bool) glyph_and_klass);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2206,13 +1838,14 @@ struct ClassDefFormat2
return_trace (rangeRecord.sanitize (c));
}
+ unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
+
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{
- unsigned int count = rangeRecord.len;
- for (unsigned int i = 0; i < count; i++)
- if (rangeRecord[i].value)
- if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
+ for (auto &range : rangeRecord)
+ if (range.value)
+ if (unlikely (!range.collect_coverage (glyphs)))
return false;
return true;
}
@@ -2220,11 +1853,10 @@ struct ClassDefFormat2
template <typename set_t>
bool collect_class (set_t *glyphs, unsigned int klass) const
{
- unsigned int count = rangeRecord.len;
- for (unsigned int i = 0; i < count; i++)
+ for (auto &range : rangeRecord)
{
- if (rangeRecord[i].value == klass)
- if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
+ if (range.value == klass)
+ if (unlikely (!range.collect_coverage (glyphs)))
return false;
}
return true;
@@ -2232,90 +1864,87 @@ struct ClassDefFormat2
bool intersects (const hb_set_t *glyphs) const
{
- /* TODO Speed up, using hb_set_next() and bsearch()? */
- unsigned int count = rangeRecord.len;
- for (unsigned int i = 0; i < count; i++)
+ if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
{
- const auto& range = rangeRecord[i];
- if (range.intersects (glyphs) && range.value)
- return true;
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
+ if (get_class (g))
+ return true;
+ return false;
}
- return false;
+
+ return hb_any (+ hb_iter (rangeRecord)
+ | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs) && range.value; }));
}
bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const
{
- unsigned int count = rangeRecord.len;
if (klass == 0)
{
/* Match if there's any glyph that is not listed! */
hb_codepoint_t g = HB_SET_VALUE_INVALID;
- for (unsigned int i = 0; i < count; i++)
+ for (auto &range : rangeRecord)
{
- if (!hb_set_next (glyphs, &g))
+ if (!glyphs->next (&g))
break;
- if (g < rangeRecord[i].first)
+ if (g < range.first)
return true;
- g = rangeRecord[i].last;
+ g = range.last;
}
- if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+ if (g != HB_SET_VALUE_INVALID && glyphs->next (&g))
return true;
/* Fall through. */
}
- /* TODO Speed up, using set overlap first? */
- /* TODO(iter) Rewrite as dagger. */
- HBUINT16 k {klass};
- const RangeRecord *arr = rangeRecord.arrayZ;
- for (unsigned int i = 0; i < count; i++)
- if (arr[i].value == k && arr[i].intersects (glyphs))
+ for (const auto &range : rangeRecord)
+ if (range.value == klass && range.intersects (*glyphs))
return true;
return false;
}
void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
{
- unsigned count = rangeRecord.len;
if (klass == 0)
{
hb_codepoint_t g = HB_SET_VALUE_INVALID;
- for (unsigned int i = 0; i < count; i++)
+ for (auto &range : rangeRecord)
{
- if (!hb_set_next (glyphs, &g))
- break;
- while (g != HB_SET_VALUE_INVALID && g < rangeRecord[i].first)
- {
- intersect_glyphs->add (g);
- hb_set_next (glyphs, &g);
+ if (!glyphs->next (&g))
+ goto done;
+ while (g < range.first)
+ {
+ intersect_glyphs->add (g);
+ if (!glyphs->next (&g))
+ goto done;
}
- g = rangeRecord[i].last;
+ g = range.last;
}
- while (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
- intersect_glyphs->add (g);
+ while (glyphs->next (&g))
+ intersect_glyphs->add (g);
+ done:
return;
}
- hb_codepoint_t g = HB_SET_VALUE_INVALID;
- for (unsigned int i = 0; i < count; i++)
+ unsigned count = rangeRecord.len;
+ if (count > glyphs->get_population () * hb_bit_storage (count) * 8)
{
- if (rangeRecord[i].value != klass) continue;
-
- if (g != HB_SET_VALUE_INVALID)
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID;
+ glyphs->next (&g);)
{
- if (g >= rangeRecord[i].first &&
- g <= rangeRecord[i].last)
- intersect_glyphs->add (g);
- if (g > rangeRecord[i].last)
- continue;
+ unsigned i;
+ if (rangeRecord.as_array ().bfind (g, &i) &&
+ rangeRecord.arrayZ[i].value == klass)
+ intersect_glyphs->add (g);
}
+ return;
+ }
- g = rangeRecord[i].first - 1;
- while (hb_set_next (glyphs, &g))
- {
- if (g >= rangeRecord[i].first && g <= rangeRecord[i].last)
- intersect_glyphs->add (g);
- else if (g > rangeRecord[i].last)
- break;
- }
+ for (auto &range : rangeRecord)
+ {
+ if (range.value != klass) continue;
+
+ unsigned end = range.last + 1;
+ for (hb_codepoint_t g = range.first - 1;
+ glyphs->next (&g) && g < end;)
+ intersect_glyphs->add (g);
}
}
@@ -2323,43 +1952,40 @@ struct ClassDefFormat2
{
if (glyphs->is_empty ()) return;
- unsigned count = rangeRecord.len;
hb_codepoint_t g = HB_SET_VALUE_INVALID;
- for (unsigned int i = 0; i < count; i++)
+ for (auto &range : rangeRecord)
{
- if (!hb_set_next (glyphs, &g))
+ if (!glyphs->next (&g))
break;
- if (g < rangeRecord[i].first)
+ if (g < range.first)
{
intersect_classes->add (0);
break;
}
- g = rangeRecord[i].last;
+ g = range.last;
}
- if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+ if (g != HB_SET_VALUE_INVALID && glyphs->next (&g))
intersect_classes->add (0);
- for (const RangeRecord& record : rangeRecord.iter ())
- if (record.intersects (glyphs))
- intersect_classes->add (record.value);
+ for (const auto& range : rangeRecord)
+ if (range.intersects (*glyphs))
+ intersect_classes->add (range.value);
}
protected:
HBUINT16 classFormat; /* Format identifier--format = 2 */
- SortedArray16Of<RangeRecord>
+ typename Types::template SortedArrayOf<RangeRecord<Types>>
rangeRecord; /* Array of glyph ranges--ordered by
* Start GlyphID */
public:
- DEFINE_SIZE_ARRAY (4, rangeRecord);
+ DEFINE_SIZE_ARRAY (2 + Types::size, rangeRecord);
};
struct ClassDef
{
/* Has interface. */
- static constexpr unsigned SENTINEL = 0;
- typedef unsigned int value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ unsigned operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k]; }
/* Projection. */
hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); }
@@ -2369,12 +1995,29 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.get_class (glyph_id);
case 2: return u.format2.get_class (glyph_id);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.get_class (glyph_id);
+ case 4: return u.format4.get_class (glyph_id);
+#endif
default:return 0;
}
}
+ unsigned get_population () const
+ {
+ switch (u.format) {
+ case 1: return u.format1.get_population ();
+ case 2: return u.format2.get_population ();
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.get_population ();
+ case 4: return u.format4.get_population ();
+#endif
+ default:return NOT_COVERED;
+ }
+ }
+
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero)
{
TRACE_SERIALIZE (this);
@@ -2383,10 +2026,11 @@ struct ClassDef
auto it = + it_with_class_zero | hb_filter (hb_second);
unsigned format = 2;
+ hb_codepoint_t glyph_max = 0;
if (likely (it))
{
hb_codepoint_t glyph_min = (*it).first;
- hb_codepoint_t glyph_max = glyph_min;
+ glyph_max = glyph_min;
unsigned num_glyphs = 0;
unsigned num_ranges = 1;
@@ -2411,12 +2055,22 @@ struct ClassDef
if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3)
format = 1;
}
+
+#ifndef HB_NO_BEYOND_64K
+ if (glyph_max > 0xFFFFu)
+ format += 2;
+#endif
+
u.format = format;
switch (u.format)
{
case 1: return_trace (u.format1.serialize (c, it));
case 2: return_trace (u.format2.serialize (c, it));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.serialize (c, it));
+ case 4: return_trace (u.format4.serialize (c, it));
+#endif
default:return_trace (false);
}
}
@@ -2431,6 +2085,10 @@ struct ClassDef
switch (u.format) {
case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+ case 4: return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+#endif
default:return_trace (false);
}
}
@@ -2442,10 +2100,27 @@ struct ClassDef
switch (u.format) {
case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.sanitize (c));
+ case 4: return_trace (u.format4.sanitize (c));
+#endif
default:return_trace (true);
}
}
+ unsigned cost () const
+ {
+ switch (u.format) {
+ case 1: return u.format1.cost ();
+ case 2: return u.format2.cost ();
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.cost ();
+ case 4: return u.format4.cost ();
+#endif
+ default:return 0u;
+ }
+ }
+
/* Might return false if array looks unsorted.
* Used for faster rejection of corrupt data. */
template <typename set_t>
@@ -2454,6 +2129,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.collect_coverage (glyphs);
case 2: return u.format2.collect_coverage (glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.collect_coverage (glyphs);
+ case 4: return u.format4.collect_coverage (glyphs);
+#endif
default:return false;
}
}
@@ -2466,6 +2145,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.collect_class (glyphs, klass);
case 2: return u.format2.collect_class (glyphs, klass);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.collect_class (glyphs, klass);
+ case 4: return u.format4.collect_class (glyphs, klass);
+#endif
default:return false;
}
}
@@ -2475,6 +2158,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersects (glyphs);
case 2: return u.format2.intersects (glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersects (glyphs);
+ case 4: return u.format4.intersects (glyphs);
+#endif
default:return false;
}
}
@@ -2483,6 +2170,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersects_class (glyphs, klass);
case 2: return u.format2.intersects_class (glyphs, klass);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersects_class (glyphs, klass);
+ case 4: return u.format4.intersects_class (glyphs, klass);
+#endif
default:return false;
}
}
@@ -2492,6 +2183,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+ case 4: return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+#endif
default:return;
}
}
@@ -2501,6 +2196,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersected_classes (glyphs, intersect_classes);
case 2: return u.format2.intersected_classes (glyphs, intersect_classes);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersected_classes (glyphs, intersect_classes);
+ case 4: return u.format4.intersected_classes (glyphs, intersect_classes);
+#endif
default:return;
}
}
@@ -2508,18 +2207,22 @@ struct ClassDef
protected:
union {
- HBUINT16 format; /* Format identifier */
- ClassDefFormat1 format1;
- ClassDefFormat2 format2;
+ HBUINT16 format; /* Format identifier */
+ ClassDefFormat1_3<SmallTypes> format1;
+ ClassDefFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BEYOND_64K
+ ClassDefFormat1_3<MediumTypes>format3;
+ ClassDefFormat2_4<MediumTypes>format4;
+#endif
} u;
public:
DEFINE_SIZE_UNION (2, format);
};
template<typename Iterator>
-static inline void ClassDef_serialize (hb_serialize_context_t *c,
+static inline bool ClassDef_serialize (hb_serialize_context_t *c,
Iterator it)
-{ c->start_embed<ClassDef> ()->serialize (c, it); }
+{ return (c->start_embed<ClassDef> ()->serialize (c, it)); }
/*
@@ -2530,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))
@@ -2567,14 +2270,27 @@ struct VarRegionAxis
DEFINE_SIZE_STATIC (6);
};
+#define REGION_CACHE_ITEM_CACHE_INVALID 2.f
+
struct VarRegionList
{
+ using cache_t = float;
+
float evaluate (unsigned int region_index,
- const int *coords, unsigned int coord_len) const
+ const int *coords, unsigned int coord_len,
+ cache_t *cache = nullptr) const
{
if (unlikely (region_index >= regionCount))
return 0.;
+ float *cached_value = nullptr;
+ if (cache)
+ {
+ cached_value = &(cache[region_index]);
+ if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
+ return *cached_value;
+ }
+
const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
float v = 1.;
@@ -2584,9 +2300,16 @@ struct VarRegionList
int coord = i < coord_len ? coords[i] : 0;
float factor = axes[i].evaluate (coord);
if (factor == 0.f)
+ {
+ if (cache)
+ *cached_value = 0.;
return 0.;
+ }
v *= factor;
}
+
+ if (cache)
+ *cached_value = v;
return v;
}
@@ -2610,7 +2333,7 @@ struct VarRegionList
{
unsigned int backward = region_map.backward (r);
if (backward >= region_count) return_trace (false);
- memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
+ hb_memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
}
return_trace (true);
@@ -2630,11 +2353,14 @@ struct VarRegionList
struct VarData
{
+ unsigned int get_item_count () const
+ { return itemCount; }
+
unsigned int get_region_index_count () const
{ return regionIndices.len; }
unsigned int get_row_size () const
- { return shortCount + regionIndices.len; }
+ { return (wordCount () + regionIndices.len) * (longWords () ? 2 : 1); }
unsigned int get_size () const
{ return min_size
@@ -2644,30 +2370,40 @@ struct VarData
float get_delta (unsigned int inner,
const int *coords, unsigned int coord_count,
- const VarRegionList &regions) const
+ const VarRegionList &regions,
+ VarRegionList::cache_t *cache = nullptr) const
{
if (unlikely (inner >= itemCount))
return 0.;
unsigned int count = regionIndices.len;
- unsigned int scount = shortCount;
+ bool is_long = longWords ();
+ unsigned word_count = wordCount ();
+ unsigned int scount = is_long ? count : word_count;
+ unsigned int lcount = is_long ? word_count : 0;
const HBUINT8 *bytes = get_delta_bytes ();
- const HBUINT8 *row = bytes + inner * (scount + count);
+ const HBUINT8 *row = bytes + inner * get_row_size ();
float delta = 0.;
unsigned int i = 0;
- const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
+ const HBINT32 *lcursor = reinterpret_cast<const HBINT32 *> (row);
+ for (; i < lcount; i++)
+ {
+ float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
+ delta += scalar * *lcursor++;
+ }
+ const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (lcursor);
for (; i < scount; i++)
{
- float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+ float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
delta += scalar * *scursor++;
}
const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
for (; i < count; i++)
{
- float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+ float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
delta += scalar * *bcursor++;
}
@@ -2691,7 +2427,7 @@ struct VarData
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
regionIndices.sanitize (c) &&
- shortCount <= regionIndices.len &&
+ wordCount () <= regionIndices.len &&
c->check_range (get_delta_bytes (),
itemCount,
get_row_size ()));
@@ -2706,55 +2442,96 @@ struct VarData
if (unlikely (!c->extend_min (this))) return_trace (false);
itemCount = inner_map.get_next_value ();
- /* Optimize short count */
- unsigned short ri_count = src->regionIndices.len;
- enum delta_size_t { kZero=0, kByte, kShort };
+ /* Optimize word count */
+ unsigned ri_count = src->regionIndices.len;
+ enum delta_size_t { kZero=0, kNonWord, kWord };
hb_vector_t<delta_size_t> delta_sz;
- hb_vector_t<unsigned int> ri_map; /* maps old index to new index */
+ hb_vector_t<unsigned int> ri_map; /* maps new index to old index */
delta_sz.resize (ri_count);
ri_map.resize (ri_count);
- unsigned int new_short_count = 0;
+ unsigned int new_word_count = 0;
unsigned int r;
+
+ const HBUINT8 *src_delta_bytes = src->get_delta_bytes ();
+ unsigned src_row_size = src->get_row_size ();
+ unsigned src_word_count = src->wordCount ();
+ bool src_long_words = src->longWords ();
+
+ bool has_long = false;
+ if (src_long_words)
+ {
+ for (r = 0; r < src_word_count; r++)
+ {
+ for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
+ {
+ unsigned int old = inner_map.backward (i);
+ int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size);
+ if (delta < -65536 || 65535 < delta)
+ {
+ has_long = true;
+ break;
+ }
+ }
+ }
+ }
+
+ signed min_threshold = has_long ? -65536 : -128;
+ signed max_threshold = has_long ? +65535 : +127;
for (r = 0; r < ri_count; r++)
{
+ bool short_circuit = src_long_words == has_long && src_word_count <= r;
+
delta_sz[r] = kZero;
for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
{
unsigned int old = inner_map.backward (i);
- int16_t delta = src->get_item_delta (old, r);
- if (delta < -128 || 127 < delta)
+ int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size);
+ if (delta < min_threshold || max_threshold < delta)
{
- delta_sz[r] = kShort;
- new_short_count++;
+ delta_sz[r] = kWord;
+ new_word_count++;
break;
}
else if (delta != 0)
- delta_sz[r] = kByte;
+ {
+ delta_sz[r] = kNonWord;
+ if (short_circuit)
+ break;
+ }
}
}
- unsigned int short_index = 0;
- unsigned int byte_index = new_short_count;
+
+ unsigned int word_index = 0;
+ unsigned int non_word_index = new_word_count;
unsigned int new_ri_count = 0;
for (r = 0; r < ri_count; r++)
if (delta_sz[r])
{
- ri_map[r] = (delta_sz[r] == kShort)? short_index++ : byte_index++;
+ unsigned new_r = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
+ ri_map[new_r] = r;
new_ri_count++;
}
- shortCount = new_short_count;
+ wordSizeCount = new_word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0);
+
regionIndices.len = new_ri_count;
if (unlikely (!c->extend (this))) return_trace (false);
- for (r = 0; r < ri_count; r++)
- if (delta_sz[r]) regionIndices[ri_map[r]] = region_map[src->regionIndices[r]];
+ for (r = 0; r < new_ri_count; r++)
+ regionIndices[r] = region_map[src->regionIndices[ri_map[r]]];
- for (unsigned int i = 0; i < itemCount; i++)
+ HBUINT8 *delta_bytes = get_delta_bytes ();
+ unsigned row_size = get_row_size ();
+ unsigned count = itemCount;
+ for (unsigned int i = 0; i < count; i++)
{
- unsigned int old = inner_map.backward (i);
- for (unsigned int r = 0; r < ri_count; r++)
- if (delta_sz[r]) set_item_delta (i, ri_map[r], src->get_item_delta (old, r));
+ unsigned int old = inner_map.backward (i);
+ for (unsigned int r = 0; r < new_ri_count; r++)
+ set_item_delta_fast (i, r,
+ src->get_item_delta_fast (old, ri_map[r],
+ src_delta_bytes, src_row_size),
+ delta_bytes, row_size);
}
return_trace (true);
@@ -2762,12 +2539,15 @@ struct VarData
void collect_region_refs (hb_set_t &region_indices, const hb_inc_bimap_t &inner_map) const
{
+ const HBUINT8 *delta_bytes = get_delta_bytes ();
+ unsigned row_size = get_row_size ();
+
for (unsigned int r = 0; r < regionIndices.len; r++)
{
- unsigned int region = regionIndices[r];
+ unsigned int region = regionIndices.arrayZ[r];
if (region_indices.has (region)) continue;
for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
- if (get_item_delta (inner_map.backward (i), r) != 0)
+ if (get_item_delta_fast (inner_map.backward (i), r, delta_bytes, row_size) != 0)
{
region_indices.add (region);
break;
@@ -2782,28 +2562,70 @@ struct VarData
HBUINT8 *get_delta_bytes ()
{ return &StructAfter<HBUINT8> (regionIndices); }
- int16_t get_item_delta (unsigned int item, unsigned int region) const
+ int32_t get_item_delta_fast (unsigned int item, unsigned int region,
+ const HBUINT8 *delta_bytes, unsigned row_size) const
{
- if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0;
- const HBINT8 *p = (const HBINT8 *)get_delta_bytes () + item * get_row_size ();
- if (region < shortCount)
- return ((const HBINT16 *)p)[region];
+ if (unlikely (item >= itemCount || region >= regionIndices.len)) return 0;
+
+ const HBINT8 *p = (const HBINT8 *) delta_bytes + item * row_size;
+ unsigned word_count = wordCount ();
+ bool is_long = longWords ();
+ if (is_long)
+ {
+ if (region < word_count)
+ return ((const HBINT32 *) p)[region];
+ else
+ return ((const HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count];
+ }
else
- return (p + HBINT16::static_size * shortCount)[region - shortCount];
+ {
+ if (region < word_count)
+ return ((const HBINT16 *) p)[region];
+ else
+ return (p + HBINT16::static_size * word_count)[region - word_count];
+ }
+ }
+ int32_t get_item_delta (unsigned int item, unsigned int region) const
+ {
+ return get_item_delta_fast (item, region,
+ get_delta_bytes (),
+ get_row_size ());
}
- void set_item_delta (unsigned int item, unsigned int region, int16_t delta)
+ void set_item_delta_fast (unsigned int item, unsigned int region, int32_t delta,
+ HBUINT8 *delta_bytes, unsigned row_size)
{
- HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size ();
- if (region < shortCount)
- ((HBINT16 *)p)[region] = delta;
+ HBINT8 *p = (HBINT8 *) delta_bytes + item * row_size;
+ unsigned word_count = wordCount ();
+ bool is_long = longWords ();
+ if (is_long)
+ {
+ if (region < word_count)
+ ((HBINT32 *) p)[region] = delta;
+ else
+ ((HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count] = delta;
+ }
else
- (p + HBINT16::static_size * shortCount)[region - shortCount] = delta;
+ {
+ if (region < word_count)
+ ((HBINT16 *) p)[region] = delta;
+ else
+ (p + HBINT16::static_size * word_count)[region - word_count] = delta;
+ }
}
+ void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
+ {
+ set_item_delta_fast (item, region, delta,
+ get_delta_bytes (),
+ get_row_size ());
+ }
+
+ bool longWords () const { return wordSizeCount & 0x8000u /* LONG_WORDS */; }
+ unsigned wordCount () const { return wordSizeCount & 0x7FFFu /* WORD_DELTA_COUNT_MASK */; }
protected:
HBUINT16 itemCount;
- HBUINT16 shortCount;
+ HBUINT16 wordSizeCount;
Array16Of<HBUINT16> regionIndices;
/*UnsizedArrayOf<HBUINT8>bytesX;*/
public:
@@ -2812,9 +2634,31 @@ struct VarData
struct VariationStore
{
+ using cache_t = VarRegionList::cache_t;
+
+ cache_t *create_cache () const
+ {
+#ifdef HB_NO_VAR
+ return nullptr;
+#endif
+ auto &r = this+regions;
+ unsigned count = r.regionCount;
+
+ float *cache = (float *) hb_malloc (sizeof (float) * count);
+ if (unlikely (!cache)) return nullptr;
+
+ for (unsigned i = 0; i < count; i++)
+ cache[i] = REGION_CACHE_ITEM_CACHE_INVALID;
+
+ return cache;
+ }
+
+ static void destroy_cache (cache_t *cache) { hb_free (cache); }
+
private:
float get_delta (unsigned int outer, unsigned int inner,
- const int *coords, unsigned int coord_count) const
+ const int *coords, unsigned int coord_count,
+ VarRegionList::cache_t *cache = nullptr) const
{
#ifdef HB_NO_VAR
return 0.f;
@@ -2825,16 +2669,26 @@ struct VariationStore
return (this+dataSets[outer]).get_delta (inner,
coords, coord_count,
- this+regions);
+ this+regions,
+ cache);
}
public:
float get_delta (unsigned int index,
- const int *coords, unsigned int coord_count) const
+ const int *coords, unsigned int coord_count,
+ VarRegionList::cache_t *cache = nullptr) const
{
unsigned int outer = index >> 16;
unsigned int inner = index & 0xFFFF;
- return get_delta (outer, inner, coords, coord_count);
+ return get_delta (outer, inner, coords, coord_count, cache);
+ }
+ float get_delta (unsigned int index,
+ hb_array_t<int> coords,
+ VarRegionList::cache_t *cache = nullptr) const
+ {
+ return get_delta (index,
+ coords.arrayZ, coords.length,
+ cache);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2852,9 +2706,13 @@ struct VariationStore
bool serialize (hb_serialize_context_t *c,
const VariationStore *src,
- const hb_array_t <hb_inc_bimap_t> &inner_maps)
+ const hb_array_t <const hb_inc_bimap_t> &inner_maps)
{
TRACE_SERIALIZE (this);
+#ifdef HB_NO_VAR
+ return_trace (false);
+#endif
+
if (unlikely (!c->extend_min (this))) return_trace (false);
unsigned int set_count = 0;
@@ -2903,29 +2761,40 @@ struct VariationStore
return_trace (true);
}
- bool subset (hb_subset_context_t *c) const
+ VariationStore *copy (hb_serialize_context_t *c) const
{
- TRACE_SUBSET (this);
+ TRACE_SERIALIZE (this);
+ auto *out = c->start_embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
- VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> ();
- if (unlikely (!varstore_prime)) return_trace (false);
+ 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];
- const hb_set_t *variation_indices = c->plan->layout_variation_indices;
- if (variation_indices->is_empty ()) return_trace (false);
+ unsigned itemCount = data.get_item_count ();
+ for (unsigned j = 0; j < itemCount; j++)
+ map->add (j);
+ }
- hb_vector_t<hb_inc_bimap_t> inner_maps;
- inner_maps.resize ((unsigned) dataSets.len);
+ if (unlikely (!out->serialize (c, this, inner_maps))) return_trace (nullptr);
- for (unsigned idx : c->plan->layout_variation_indices->iter ())
- {
- uint16_t major = idx >> 16;
- uint16_t minor = idx & 0xFFFF;
+ return_trace (out);
+ }
- if (major >= inner_maps.length)
- return_trace (false);
- inner_maps[major].add (minor);
- }
- varstore_prime->serialize (c->serializer, this, inner_maps.as_array ());
+ bool subset (hb_subset_context_t *c, const hb_array_t<const hb_inc_bimap_t> &inner_maps) const
+ {
+ TRACE_SUBSET (this);
+#ifdef HB_NO_VAR
+ return_trace (false);
+#endif
+
+ VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> ();
+ if (unlikely (!varstore_prime)) return_trace (false);
+
+ varstore_prime->serialize (c->serializer, this, inner_maps);
return_trace (
!c->serializer->in_error()
@@ -2933,7 +2802,12 @@ struct VariationStore
}
unsigned int get_region_index_count (unsigned int major) const
- { return (this+dataSets[major]).get_region_index_count (); }
+ {
+#ifdef HB_NO_VAR
+ return 0;
+#endif
+ return (this+dataSets[major]).get_region_index_count ();
+ }
void get_region_scalars (unsigned int major,
const int *coords, unsigned int coord_count,
@@ -2951,7 +2825,13 @@ struct VariationStore
&scalars[0], num_scalars);
}
- unsigned int get_sub_table_count () const { return dataSets.len; }
+ unsigned int get_sub_table_count () const
+ {
+#ifdef HB_NO_VAR
+ return 0;
+#endif
+ return dataSets.len;
+ }
protected:
HBUINT16 format;
@@ -2961,9 +2841,18 @@ struct VariationStore
DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
};
+#undef REGION_CACHE_ITEM_CACHE_INVALID
+
/*
* Feature Variations
*/
+enum Cond_with_Var_flag_t
+{
+ KEEP_COND_WITH_VAR = 0,
+ DROP_COND_WITH_VAR = 1,
+ DROP_RECORD_WITH_VAR = 2,
+ MEM_ERR_WITH_VAR = 3,
+};
struct ConditionFormat1
{
@@ -2974,14 +2863,56 @@ struct ConditionFormat1
TRACE_SUBSET (this);
auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (false);
- return_trace (true);
+
+ const hb_map_t *index_map = &c->plan->axes_index_map;
+ if (index_map->is_empty ()) return_trace (true);
+
+ if (!index_map->has (axisIndex))
+ return_trace (false);
+
+ return_trace (c->serializer->check_assign (out->axisIndex, index_map->get (axisIndex),
+ HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
private:
+ Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
+ hb_map_t *condition_map /* OUT */) const
+ {
+ //invalid axis index, drop the entire record
+ if (!c->axes_index_tag_map->has (axisIndex))
+ return DROP_RECORD_WITH_VAR;
+
+ hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
+
+ //axis not pinned, keep the condition
+ if (!c->axes_location->has (axis_tag))
+ {
+ // add axisIndex->value into the hashmap so we can check if the record is
+ // unique with variations
+ int16_t min_val = filterRangeMinValue.to_int ();
+ int16_t max_val = filterRangeMaxValue.to_int ();
+ hb_codepoint_t val = (max_val << 16) + min_val;
+
+ condition_map->set (axisIndex, val);
+ return KEEP_COND_WITH_VAR;
+ }
+
+ //axis pinned, check if condition is met
+ //TODO: add check for axis Ranges
+ int v = c->axes_location->get (axis_tag);
+
+ //condition not met, drop the entire record
+ if (v < filterRangeMinValue.to_int () || v > filterRangeMaxValue.to_int ())
+ return DROP_RECORD_WITH_VAR;
+
+ //axis pinned and condition met, drop the condition
+ return DROP_COND_WITH_VAR;
+ }
+
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
@@ -3009,11 +2940,20 @@ struct Condition
}
}
+ Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
+ hb_map_t *condition_map /* OUT */) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.keep_with_variations (c, condition_map);
+ default:return KEEP_COND_WITH_VAR;
+ }
+ }
+
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 ());
@@ -3050,15 +2990,65 @@ struct ConditionSet
return true;
}
- bool subset (hb_subset_context_t *c) const
+ Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+ {
+ hb_map_t *condition_map = hb_map_create ();
+ if (unlikely (!condition_map)) return MEM_ERR_WITH_VAR;
+ hb::shared_ptr<hb_map_t> p {condition_map};
+
+ hb_set_t *cond_set = hb_set_create ();
+ if (unlikely (!cond_set)) return MEM_ERR_WITH_VAR;
+ hb::shared_ptr<hb_set_t> s {cond_set};
+
+ unsigned num_kept_cond = 0, cond_idx = 0;
+ for (const auto& offset : conditions)
+ {
+ Cond_with_Var_flag_t ret = (this+offset).keep_with_variations (c, condition_map);
+ // one condition is not met, drop the entire record
+ if (ret == DROP_RECORD_WITH_VAR)
+ return DROP_RECORD_WITH_VAR;
+
+ // axis not pinned, keep this condition
+ if (ret == KEEP_COND_WITH_VAR)
+ {
+ cond_set->add (cond_idx);
+ num_kept_cond++;
+ }
+ cond_idx++;
+ }
+
+ // all conditions met
+ if (num_kept_cond == 0) return DROP_COND_WITH_VAR;
+
+ //check if condition_set is unique with variations
+ if (c->conditionset_map->has (p))
+ //duplicate found, drop the entire record
+ return DROP_RECORD_WITH_VAR;
+
+ c->conditionset_map->set (p, 1);
+ c->record_cond_idx_map->set (c->cur_record_idx, s);
+
+ return KEEP_COND_WITH_VAR;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (this);
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
- + conditions.iter ()
- | hb_apply (subset_offset_array (c, out->conditions, this))
- ;
+ hb_set_t *retained_cond_set = nullptr;
+ if (l->feature_record_cond_idx_map != nullptr)
+ retained_cond_set = l->feature_record_cond_idx_map->get (l->cur_feature_var_record_idx);
+
+ unsigned int count = conditions.len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (retained_cond_set != nullptr && !retained_cond_set->has (i))
+ continue;
+ subset_offset_array (c, out->conditions, this) (conditions[i]);
+ }
return_trace (bool (out->conditions));
}
@@ -3092,10 +3082,19 @@ struct FeatureTableSubstitutionRecord
feature_indexes->add (featureIndex);
}
+ void collect_feature_substitutes_with_variations (hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
+ const hb_set_t *feature_indices,
+ const void *base) const
+ {
+ if (feature_indices->has (featureIndex))
+ feature_substitutes_map->set (featureIndex, &(base+feature));
+ }
+
bool subset (hb_subset_layout_context_t *c, const void *base) const
{
TRACE_SUBSET (this);
- if (!c->feature_index_map->has (featureIndex)) {
+ if (!c->feature_index_map->has (featureIndex) ||
+ c->feature_substitutes_map->has (featureIndex)) {
// Feature that is being substituted is not being retained, so we don't
// need this.
return_trace (false);
@@ -3137,10 +3136,16 @@ struct FeatureTableSubstitution
}
void collect_lookups (const hb_set_t *feature_indexes,
+ const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
hb_set_t *lookup_indexes /* OUT */) const
{
+ hb_iter (substitutions)
| hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
+ | hb_filter ([feature_substitutes_map] (const FeatureTableSubstitutionRecord& record)
+ {
+ if (feature_substitutes_map == nullptr) return true;
+ return !feature_substitutes_map->has (record.featureIndex);
+ })
| hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
{ r.collect_lookups (this, lookup_indexes); })
;
@@ -3162,6 +3167,12 @@ struct FeatureTableSubstitution
return false;
}
+ void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+ {
+ for (const FeatureTableSubstitutionRecord& record : substitutions)
+ record.collect_feature_substitutes_with_variations (c->feature_substitutes_map, c->feature_indices, this);
+ }
+
bool subset (hb_subset_context_t *c,
hb_subset_layout_context_t *l) const
{
@@ -3201,9 +3212,10 @@ struct FeatureVariationRecord
void collect_lookups (const void *base,
const hb_set_t *feature_indexes,
+ const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
hb_set_t *lookup_indexes /* OUT */) const
{
- return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
+ return (base+substitutions).collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
}
void closure_features (const void *base,
@@ -3218,13 +3230,25 @@ struct FeatureVariationRecord
return (base+substitutions).intersects_features (feature_index_map);
}
+ void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
+ const void *base) const
+ {
+ // ret == 1, all conditions met
+ if ((base+conditions).keep_with_variations (c) == DROP_COND_WITH_VAR &&
+ c->apply)
+ {
+ (base+substitutions).collect_feature_substitutes_with_variations (c);
+ c->apply = false; // set variations only once
+ }
+ }
+
bool subset (hb_subset_layout_context_t *c, const void *base) const
{
TRACE_SUBSET (this);
auto *out = c->subset_context->serializer->embed (this);
if (unlikely (!out)) return_trace (false);
- out->conditions.serialize_subset (c->subset_context, conditions, base);
+ out->conditions.serialize_subset (c->subset_context, conditions, base, c);
out->substitutions.serialize_subset (c->subset_context, substitutions, base, c);
return_trace (true);
@@ -3274,6 +3298,16 @@ struct FeatureVariations
return (this+record.substitutions).find_substitute (feature_index);
}
+ void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+ {
+ unsigned int count = varRecords.len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ c->cur_record_idx = i;
+ varRecords[i].collect_feature_substitutes_with_variations (c, this);
+ }
+ }
+
FeatureVariations* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
@@ -3281,17 +3315,25 @@ struct FeatureVariations
}
void collect_lookups (const hb_set_t *feature_indexes,
+ const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
hb_set_t *lookup_indexes /* OUT */) const
{
for (const FeatureVariationRecord& r : varRecords)
- r.collect_lookups (this, feature_indexes, lookup_indexes);
+ r.collect_lookups (this, feature_indexes, feature_substitutes_map, lookup_indexes);
}
void closure_features (const hb_map_t *lookup_indexes,
+ const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
hb_set_t *feature_indexes /* OUT */) const
{
- for (const FeatureVariationRecord& record : varRecords)
- record.closure_features (this, lookup_indexes, feature_indexes);
+ unsigned int count = varRecords.len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (feature_record_cond_idx_map != nullptr &&
+ !feature_record_cond_idx_map->has (i))
+ continue;
+ varRecords[i].closure_features (this, lookup_indexes, feature_indexes);
+ }
}
bool subset (hb_subset_context_t *c,
@@ -3313,7 +3355,13 @@ struct FeatureVariations
}
unsigned count = (unsigned) (keep_up_to + 1);
- for (unsigned i = 0; i < count; i++) {
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (l->feature_record_cond_idx_map != nullptr &&
+ !l->feature_record_cond_idx_map->has (i))
+ continue;
+
+ l->cur_feature_var_record_idx = i;
subset_record_array (l, &(out->varRecords), this) (varRecords[i]);
}
return_trace (bool (out->varRecords));
@@ -3428,34 +3476,45 @@ struct VariationDevice
private:
- hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
- { return font->em_scalef_x (get_delta (font, store)); }
+ hb_position_t get_x_delta (hb_font_t *font,
+ const VariationStore &store,
+ VariationStore::cache_t *store_cache = nullptr) const
+ { return font->em_scalef_x (get_delta (font, store, store_cache)); }
- hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
- { return font->em_scalef_y (get_delta (font, store)); }
+ hb_position_t get_y_delta (hb_font_t *font,
+ const VariationStore &store,
+ VariationStore::cache_t *store_cache = nullptr) const
+ { return font->em_scalef_y (get_delta (font, store, store_cache)); }
- VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const
+ VariationDevice* copy (hb_serialize_context_t *c,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
{
TRACE_SERIALIZE (this);
- auto snap = c->snapshot ();
+ if (!layout_variation_idx_delta_map) return_trace (nullptr);
+
+ hb_pair_t<unsigned, int> *v;
+ if (!layout_variation_idx_delta_map->has (varIdx, &v))
+ return_trace (nullptr);
+
+ c->start_zerocopy (this->static_size);
auto *out = c->embed (this);
if (unlikely (!out)) return_trace (nullptr);
- if (!layout_variation_idx_map || layout_variation_idx_map->is_empty ()) return_trace (out);
- /* TODO Just get() and bail if NO_VARIATION. Needs to setup the map to return that. */
- if (!layout_variation_idx_map->has (varIdx))
- {
- c->revert (snap);
- return_trace (nullptr);
- }
- unsigned new_idx = layout_variation_idx_map->get (varIdx);
+ unsigned new_idx = hb_first (*v);
out->varIdx = new_idx;
return_trace (out);
}
- void record_variation_index (hb_set_t *layout_variation_indices) const
+ void collect_variation_index (hb_collect_variation_indices_context_t *c) const
{
- layout_variation_indices->add (varIdx);
+ c->layout_variation_indices->add (varIdx);
+ int delta = 0;
+ if (c->font && c->var_store)
+ delta = roundf (get_delta (c->font, *c->var_store, c->store_cache));
+
+ /* set new varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX here, will remap
+ * varidx later*/
+ c->varidx_delta_map->set (varIdx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -3466,9 +3525,11 @@ struct VariationDevice
private:
- float get_delta (hb_font_t *font, const VariationStore &store) const
+ float get_delta (hb_font_t *font,
+ const VariationStore &store,
+ VariationStore::cache_t *store_cache = nullptr) const
{
- return store.get_delta (varIdx, font->coords, font->num_coords);
+ return store.get_delta (varIdx, font->coords, font->num_coords, (VariationStore::cache_t *) store_cache);
}
protected:
@@ -3491,7 +3552,9 @@ struct DeviceHeader
struct Device
{
- hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+ hb_position_t get_x_delta (hb_font_t *font,
+ const VariationStore &store=Null (VariationStore),
+ VariationStore::cache_t *store_cache = nullptr) const
{
switch (u.b.format)
{
@@ -3501,13 +3564,15 @@ struct Device
#endif
#ifndef HB_NO_VAR
case 0x8000:
- return u.variation.get_x_delta (font, store);
+ return u.variation.get_x_delta (font, store, store_cache);
#endif
default:
return 0;
}
}
- hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+ hb_position_t get_y_delta (hb_font_t *font,
+ const VariationStore &store=Null (VariationStore),
+ VariationStore::cache_t *store_cache = nullptr) const
{
switch (u.b.format)
{
@@ -3517,7 +3582,7 @@ struct Device
#endif
#ifndef HB_NO_VAR
case 0x8000:
- return u.variation.get_y_delta (font, store);
+ return u.variation.get_y_delta (font, store, store_cache);
#endif
default:
return 0;
@@ -3542,7 +3607,8 @@ struct Device
}
}
- Device* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map=nullptr) const
+ Device* copy (hb_serialize_context_t *c,
+ const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map=nullptr) const
{
TRACE_SERIALIZE (this);
switch (u.b.format) {
@@ -3554,14 +3620,14 @@ struct Device
#endif
#ifndef HB_NO_VAR
case 0x8000:
- return_trace (reinterpret_cast<Device *> (u.variation.copy (c, layout_variation_idx_map)));
+ return_trace (reinterpret_cast<Device *> (u.variation.copy (c, layout_variation_idx_delta_map)));
#endif
default:
return_trace (nullptr);
}
}
- void collect_variation_indices (hb_set_t *layout_variation_indices) const
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{
switch (u.b.format) {
#ifndef HB_NO_HINTING
@@ -3572,7 +3638,7 @@ struct Device
#endif
#ifndef HB_NO_VAR
case 0x8000:
- u.variation.record_variation_index (layout_variation_indices);
+ u.variation.collect_variation_index (c);
return;
#endif
default:
@@ -3580,6 +3646,18 @@ struct Device
}
}
+ unsigned get_variation_index () const
+ {
+ switch (u.b.format) {
+#ifndef HB_NO_VAR
+ case 0x8000:
+ return u.variation.varIdx;
+#endif
+ default:
+ return HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
+ }
+ }
+
protected:
union {
DeviceHeader b;
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 a76d644c4b..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,696 +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.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->embed (this);
- if (unlikely (!out)) 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_map));
- }
-
- void collect_variation_indices (hb_set_t *layout_variation_indices) const
- { (this+deviceTable).collect_variation_indices (layout_variation_indices); }
-
- 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_set_t *layout_variation_indices) const
- {
- switch (u.format) {
- case 1:
- case 2:
- return;
- case 3:
- u.format3.collect_variation_indices (layout_variation_indices);
- 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.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->layout_variation_indices);
- }
-
- 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
- */
-
-
-struct GDEF
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
-
- enum GlyphClasses {
- UnclassifiedGlyph = 0,
- BaseGlyph = 1,
- LigatureGlyph = 2,
- MarkGlyph = 3,
- ComponentGlyph = 4
- };
-
- bool has_data () const { return version.to_int (); }
- bool has_glyph_classes () const { return glyphClassDef != 0; }
- unsigned int get_glyph_class (hb_codepoint_t glyph) const
- { return (this+glyphClassDef).get_class (glyph); }
- void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
- { (this+glyphClassDef).collect_class (glyphs, klass); }
-
- bool has_mark_attachment_types () const { return markAttachClassDef != 0; }
- unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
- { return (this+markAttachClassDef).get_class (glyph); }
-
- bool has_attach_points () const { return attachList != 0; }
- 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 (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
-
- bool has_lig_carets () const { return ligCaretList != 0; }
- 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 (this+ligCaretList).get_lig_carets (font,
- direction, glyph_id, get_var_store(),
- start_offset, caret_count, caret_array); }
-
- bool has_mark_sets () const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
- bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
- { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
-
- bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; }
- const VariationStore &get_var_store () const
- { return version.to_int () >= 0x00010003u ? this+varStore : Null (VariationStore); }
-
- /* 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 0;
- 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;
- };
-
- unsigned int get_size () const
- {
- return min_size +
- (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
- (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- { (this+ligCaretList).collect_variation_indices (c); }
-
- void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
- hb_map_t *layout_variation_idx_map /* OUT */) const
- {
- if (version.to_int () < 0x00010003u || !varStore) 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 >= (this+varStore).get_sub_table_count ()) break;
- if (major != last_major)
- {
- new_minor = 0;
- ++new_major;
- }
-
- unsigned new_idx = (new_major << 16) + new_minor;
- layout_variation_idx_map->set (idx, new_idx);
- ++new_minor;
- last_major = major;
- }
- }
-
- 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 = true;
- if (version.to_int () >= 0x00010002u)
- {
- subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
- if (!subset_markglyphsetsdef &&
- version.to_int () == 0x00010002u)
- out->version.minor = 0;
- }
-
- bool subset_varstore = true;
- if (version.to_int () >= 0x00010003u)
- {
- subset_varstore = out->varStore.serialize_subset (c, varStore, this);
- if (!subset_varstore && version.to_int () == 0x00010003u)
- out->version.minor = 2;
- }
-
- return_trace (subset_glyphclassdef || subset_attachlist ||
- subset_ligcaretlist || subset_markattachclassdef ||
- (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||
- (out->version.to_int () >= 0x00010003u && subset_varstore));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (version.sanitize (c) &&
- likely (version.major == 1) &&
- 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)));
- }
-
- protected:
- FixedVersion<>version; /* Version of the GDEF table--currently
- * 0x00010003u */
- Offset16To<ClassDef>
- glyphClassDef; /* Offset to class definition table
- * for glyph type--from beginning of
- * GDEF header (may be Null) */
- Offset16To<AttachList>
- attachList; /* Offset to list of glyphs with
- * attachment points--from beginning
- * of GDEF header (may be Null) */
- Offset16To<LigCaretList>
- ligCaretList; /* Offset to list of positioning points
- * for ligature carets--from beginning
- * of GDEF header (may be Null) */
- Offset16To<ClassDef>
- markAttachClassDef; /* Offset to class definition table for
- * mark attachment type--from beginning
- * of GDEF header (may be Null) */
- Offset16To<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 (12);
-};
-
-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 2f9186a2a7..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
@@ -29,3090 +29,14 @@
#ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
#define HB_OT_LAYOUT_GPOS_TABLE_HH
-#include "hb-ot-layout-gsubgpos.hh"
-
+#include "OT/Layout/GPOS/GPOS.hh"
namespace OT {
+namespace Layout {
+namespace GPOS_impl {
-struct MarkArray;
-static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
- const MarkArray &mark_array,
- const hb_set_t &glyphset,
- hb_map_t* klass_mapping /* INOUT */);
-
-/* buffer **position** var allocations */
-#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
-#define attach_type() var.u8[2] /* attachment type */
-/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
-
-enum attach_type_t {
- ATTACH_TYPE_NONE = 0X00,
-
- /* Each attachment should be either a mark or a cursive; can't be both. */
- ATTACH_TYPE_MARK = 0X01,
- ATTACH_TYPE_CURSIVE = 0X02,
-};
-
-
-/* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
-
-typedef HBUINT16 Value;
-
-typedef UnsizedArrayOf<Value> ValueRecord;
-
-struct ValueFormat : HBUINT16
-{
- enum Flags {
- xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
- yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
- xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
- yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
- xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
- yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
- xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
- yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
- ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
- reserved = 0xF000u, /* For future use */
-
- devices = 0x00F0u /* Mask for having any Device table */
- };
-
-/* All fields are options. Only those available advance the value pointer. */
-#if 0
- HBINT16 xPlacement; /* Horizontal adjustment for
- * placement--in design units */
- HBINT16 yPlacement; /* Vertical adjustment for
- * placement--in design units */
- HBINT16 xAdvance; /* Horizontal adjustment for
- * advance--in design units (only used
- * for horizontal writing) */
- HBINT16 yAdvance; /* Vertical adjustment for advance--in
- * design units (only used for vertical
- * writing) */
- Offset16To<Device> xPlaDevice; /* Offset to Device table for
- * horizontal placement--measured from
- * beginning of PosTable (may be NULL) */
- Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
- * placement--measured from beginning
- * of PosTable (may be NULL) */
- Offset16To<Device> xAdvDevice; /* Offset to Device table for
- * horizontal advance--measured from
- * beginning of PosTable (may be NULL) */
- Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
- * advance--measured from beginning of
- * PosTable (may be NULL) */
-#endif
-
- IntType& operator = (uint16_t i) { v = i; return *this; }
-
- unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
- unsigned int get_size () const { return get_len () * Value::static_size; }
-
- bool apply_value (hb_ot_apply_context_t *c,
- const void *base,
- const Value *values,
- hb_glyph_position_t &glyph_pos) const
- {
- bool ret = false;
- unsigned int format = *this;
- if (!format) return ret;
-
- hb_font_t *font = c->font;
- bool horizontal =
-#ifndef HB_NO_VERTICAL
- HB_DIRECTION_IS_HORIZONTAL (c->direction)
-#else
- true
-#endif
- ;
-
- if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
- if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
- if (format & xAdvance) {
- if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
- values++;
- }
- /* y_advance values grow downward but font-space grows upward, hence negation */
- if (format & yAdvance) {
- if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
- values++;
- }
-
- if (!has_device ()) return ret;
-
- bool use_x_device = font->x_ppem || font->num_coords;
- bool use_y_device = font->y_ppem || font->num_coords;
-
- if (!use_x_device && !use_y_device) return ret;
-
- const VariationStore &store = c->var_store;
-
- /* pixel -> fractional pixel */
- if (format & xPlaDevice) {
- if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store);
- values++;
- }
- if (format & yPlaDevice) {
- if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store);
- values++;
- }
- if (format & xAdvDevice) {
- if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store);
- values++;
- }
- if (format & yAdvDevice) {
- /* y_advance values grow downward but font-space grows upward, hence negation */
- if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store);
- values++;
- }
- return ret;
- }
-
- unsigned int get_effective_format (const Value *values) const
- {
- unsigned int format = *this;
- for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
- if (format & flag) should_drop (*values++, (Flags) flag, &format);
- }
-
- return format;
- }
-
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- unsigned int get_effective_format (Iterator it) const {
- unsigned int new_format = 0;
-
- for (const hb_array_t<const Value>& values : it)
- new_format = new_format | get_effective_format (&values);
-
- return new_format;
- }
-
- void copy_values (hb_serialize_context_t *c,
- unsigned int new_format,
- const void *base,
- const Value *values,
- const hb_map_t *layout_variation_idx_map) const
- {
- unsigned int format = *this;
- if (!format) return;
-
- if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++);
- if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++);
- if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++);
- if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++);
-
- if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
- if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
- if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
- if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
- }
-
- void copy_value (hb_serialize_context_t *c,
- unsigned int new_format,
- Flags flag,
- Value value) const
- {
- // Filter by new format.
- if (!(new_format & flag)) return;
- c->copy (value);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const void *base,
- const hb_array_t<const Value>& values) const
- {
- unsigned format = *this;
- unsigned i = 0;
- if (format & xPlacement) i++;
- if (format & yPlacement) i++;
- if (format & xAdvance) i++;
- if (format & yAdvance) i++;
- if (format & xPlaDevice)
- {
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
-
- if (format & ValueFormat::yPlaDevice)
- {
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
-
- if (format & ValueFormat::xAdvDevice)
- {
-
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
-
- if (format & ValueFormat::yAdvDevice)
- {
-
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
- }
-
- private:
- bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
- {
- unsigned int format = *this;
-
- if (format & xPlacement) values++;
- if (format & yPlacement) values++;
- if (format & xAdvance) values++;
- if (format & yAdvance) values++;
-
- if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
- if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
- if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
- if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
-
- return true;
- }
-
- static inline Offset16To<Device>& get_device (Value* value)
- {
- return *static_cast<Offset16To<Device> *> (value);
- }
- static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
- {
- if (worked) *worked |= bool (*value);
- return *static_cast<const Offset16To<Device> *> (value);
- }
-
- bool copy_device (hb_serialize_context_t *c, const void *base,
- const Value *src_value, const hb_map_t *layout_variation_idx_map) const
- {
- Value *dst_value = c->copy (*src_value);
-
- if (!dst_value) return false;
- if (*dst_value == 0) return true;
-
- *dst_value = 0;
- c->push ();
- if ((base + get_device (src_value)).copy (c, layout_variation_idx_map))
- {
- c->add_link (*dst_value, c->pop_pack ());
- return true;
- }
- else
- {
- c->pop_discard ();
- return false;
- }
- }
-
- static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
- {
- if (worked) *worked |= bool (*value);
- return *reinterpret_cast<const HBINT16 *> (value);
- }
-
- public:
-
- bool has_device () const
- {
- unsigned int format = *this;
- return (format & devices) != 0;
- }
-
- bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
- }
-
- bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
- {
- TRACE_SANITIZE (this);
- unsigned int len = get_len ();
-
- if (!c->check_range (values, count, get_size ())) return_trace (false);
-
- if (!has_device ()) return_trace (true);
-
- for (unsigned int i = 0; i < count; i++) {
- if (!sanitize_value_devices (c, base, values))
- return_trace (false);
- values += len;
- }
-
- return_trace (true);
- }
-
- /* Just sanitize referenced Device tables. Doesn't check the values themselves. */
- bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
- {
- TRACE_SANITIZE (this);
-
- if (!has_device ()) return_trace (true);
-
- for (unsigned int i = 0; i < count; i++) {
- if (!sanitize_value_devices (c, base, values))
- return_trace (false);
- values += stride;
- }
-
- return_trace (true);
- }
-
- private:
-
- void should_drop (Value value, Flags flag, unsigned int* format) const
- {
- if (value) return;
- *format = *format & ~flag;
- }
-
-};
-
-template<typename Iterator, typename SrcLookup>
-static void SinglePos_serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- const hb_map_t *layout_variation_idx_map);
-
-
-struct AnchorFormat1
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
- float *x, float *y) const
- {
- hb_font_t *font = c->font;
- *x = font->em_fscale_x (xCoordinate);
- *y = font->em_fscale_y (yCoordinate);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- AnchorFormat1* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- AnchorFormat1* out = c->embed<AnchorFormat1> (this);
- if (!out) return_trace (out);
- out->format = 1;
- return_trace (out);
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- FWORD xCoordinate; /* Horizontal value--in design units */
- FWORD yCoordinate; /* Vertical value--in design units */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-
-struct AnchorFormat2
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
- float *x, float *y) const
- {
- hb_font_t *font = c->font;
-
-#ifdef HB_NO_HINTING
- *x = font->em_fscale_x (xCoordinate);
- *y = font->em_fscale_y (yCoordinate);
- return;
-#endif
-
- unsigned int x_ppem = font->x_ppem;
- unsigned int y_ppem = font->y_ppem;
- hb_position_t cx = 0, cy = 0;
- bool ret;
-
- ret = (x_ppem || y_ppem) &&
- font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
- *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
- *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- AnchorFormat2* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- return_trace (c->embed<AnchorFormat2> (this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- FWORD xCoordinate; /* Horizontal value--in design units */
- FWORD yCoordinate; /* Vertical value--in design units */
- HBUINT16 anchorPoint; /* Index to glyph contour point */
- public:
- DEFINE_SIZE_STATIC (8);
-};
-
-struct AnchorFormat3
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
- float *x, float *y) const
- {
- hb_font_t *font = c->font;
- *x = font->em_fscale_x (xCoordinate);
- *y = font->em_fscale_y (yCoordinate);
-
- if (font->x_ppem || font->num_coords)
- *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
- if (font->y_ppem || font->num_coords)
- *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
- }
-
- AnchorFormat3* copy (hb_serialize_context_t *c,
- const hb_map_t *layout_variation_idx_map) const
- {
- TRACE_SERIALIZE (this);
- if (!layout_variation_idx_map) return_trace (nullptr);
-
- auto *out = c->embed<AnchorFormat3> (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- out->xDeviceTable.serialize_copy (c, xDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
- out->yDeviceTable.serialize_copy (c, yDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
- return_trace (out);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- (this+xDeviceTable).collect_variation_indices (c->layout_variation_indices);
- (this+yDeviceTable).collect_variation_indices (c->layout_variation_indices);
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 3 */
- FWORD xCoordinate; /* Horizontal value--in design units */
- FWORD yCoordinate; /* Vertical value--in design units */
- Offset16To<Device>
- xDeviceTable; /* Offset to Device table for X
- * coordinate-- from beginning of
- * Anchor table (may be NULL) */
- Offset16To<Device>
- yDeviceTable; /* Offset to Device table for Y
- * coordinate-- from beginning of
- * Anchor table (may be NULL) */
- public:
- DEFINE_SIZE_STATIC (10);
-};
-
-struct Anchor
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
- float *x, float *y) const
- {
- *x = *y = 0;
- switch (u.format) {
- case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
- case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
- case 3: u.format3.get_anchor (c, glyph_id, x, y); 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);
- }
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- switch (u.format) {
- case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
- case 2:
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- {
- // AnchorFormat 2 just containins extra hinting information, so
- // if hints are being dropped convert to format 1.
- return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
- }
- return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
- case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer,
- c->plan->layout_variation_idx_map))));
- default:return_trace (false);
- }
- }
-
- 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;
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- AnchorFormat1 format1;
- AnchorFormat2 format2;
- AnchorFormat3 format3;
- } u;
- public:
- DEFINE_SIZE_UNION (2, format);
-};
-
-
-struct AnchorMatrix
-{
- const Anchor& get_anchor (unsigned int row, unsigned int col,
- unsigned int cols, bool *found) const
- {
- *found = false;
- if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
- *found = !matrixZ[row * cols + col].is_null ();
- return this+matrixZ[row * cols + col];
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- Iterator index_iter) const
- {
- for (unsigned i : index_iter)
- (this+matrixZ[i]).collect_variation_indices (c);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool subset (hb_subset_context_t *c,
- unsigned num_rows,
- Iterator index_iter) const
- {
- TRACE_SUBSET (this);
-
- auto *out = c->serializer->start_embed (this);
-
- if (!index_iter) return_trace (false);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- out->rows = num_rows;
- for (const unsigned i : index_iter)
- {
- auto *offset = c->serializer->embed (matrixZ[i]);
- if (!offset) return_trace (false);
- offset->serialize_subset (c, matrixZ[i], this);
- }
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
- {
- TRACE_SANITIZE (this);
- if (!c->check_struct (this)) return_trace (false);
- if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
- unsigned int count = rows * cols;
- if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
- for (unsigned int i = 0; i < count; i++)
- if (!matrixZ[i].sanitize (c, this)) return_trace (false);
- return_trace (true);
- }
-
- HBUINT16 rows; /* Number of rows */
- UnsizedArrayOf<Offset16To<Anchor>>
- matrixZ; /* Matrix of offsets to Anchor tables--
- * from beginning of AnchorMatrix table */
- public:
- DEFINE_SIZE_ARRAY (2, matrixZ);
-};
-
-
-struct MarkRecord
-{
- friend struct MarkArray;
-
- unsigned get_class () const { return (unsigned) klass; }
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
- }
-
- MarkRecord *subset (hb_subset_context_t *c,
- const void *src_base,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- out->klass = klass_mapping->get (klass);
- out->markAnchor.serialize_subset (c, markAnchor, src_base);
- return_trace (out);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const void *src_base) const
- {
- (src_base+markAnchor).collect_variation_indices (c);
- }
-
- protected:
- HBUINT16 klass; /* Class defined for this mark */
- Offset16To<Anchor>
- markAnchor; /* Offset to Anchor table--from
- * beginning of MarkArray table */
- public:
- DEFINE_SIZE_STATIC (4);
-};
-
-struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
-{
- bool apply (hb_ot_apply_context_t *c,
- unsigned int mark_index, unsigned int glyph_index,
- const AnchorMatrix &anchors, unsigned int class_count,
- unsigned int glyph_pos) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
- unsigned int mark_class = record.klass;
-
- const Anchor& mark_anchor = this + record.markAnchor;
- bool found;
- const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
- /* If this subtable doesn't have an anchor for this base and this class,
- * return false such that the subsequent subtables have a chance at it. */
- if (unlikely (!found)) return_trace (false);
-
- float mark_x, mark_y, base_x, base_y;
-
- buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
- mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
- glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
-
- hb_glyph_position_t &o = buffer->cur_pos();
- o.x_offset = roundf (base_x - mark_x);
- o.y_offset = roundf (base_y - mark_y);
- o.attach_type() = ATTACH_TYPE_MARK;
- o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
- buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
-
- buffer->idx++;
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool subset (hb_subset_context_t *c,
- Iterator coverage,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
-
- auto* out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- auto mark_iter =
- + hb_zip (coverage, this->iter ())
- | hb_filter (glyphset, hb_first)
- | hb_map (hb_second)
- ;
-
- unsigned new_length = 0;
- for (const auto& mark_record : mark_iter) {
- if (unlikely (!mark_record.subset (c, this, klass_mapping)))
- return_trace (false);
- new_length++;
- }
-
- if (unlikely (!c->serializer->check_assign (out->len, new_length,
- HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
- return_trace (false);
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (Array16Of<MarkRecord>::sanitize (c, this));
- }
-};
-
-
-/* Lookups */
-
-struct SinglePosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if (!valueFormat.has_device ()) return;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (c->glyph_set)
- ;
-
- if (!it) return;
- valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- ValueFormat get_value_format () const { return valueFormat; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- valueFormat.apply_value (c, this, values, buffer->cur_pos());
-
- buffer->idx++;
- return_trace (true);
- }
-
- template<typename Iterator,
- typename SrcLookup,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- ValueFormat newFormat,
- const hb_map_t *layout_variation_idx_map)
- {
- if (unlikely (!c->extend_min (this))) return;
- if (unlikely (!c->check_assign (valueFormat,
- newFormat,
- HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
-
- for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
- {
- src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map);
- // Only serialize the first entry in the iterator, the rest are assumed to
- // be the same.
- break;
- }
-
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
-
- coverage.serialize_serialize (c, glyphs);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
- ;
-
- bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- coverage.sanitize (c, this) &&
- valueFormat.sanitize_value (c, this, values));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat; /* Defines the types of data in the
- * ValueRecord */
- ValueRecord values; /* Defines positioning
- * value(s)--applied to all glyphs in
- * the Coverage table */
- public:
- DEFINE_SIZE_ARRAY (6, values);
-};
-
-struct SinglePosFormat2
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if (!valueFormat.has_device ()) return;
-
- auto it =
- + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
- | hb_filter (c->glyph_set, hb_first)
- ;
-
- if (!it) return;
-
- unsigned sub_length = valueFormat.get_len ();
- const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
-
- for (unsigned i : + it
- | hb_map (hb_second))
- valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
-
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- ValueFormat get_value_format () const { return valueFormat; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- if (likely (index >= valueCount)) return_trace (false);
-
- valueFormat.apply_value (c, this,
- &values[index * valueFormat.get_len ()],
- buffer->cur_pos());
-
- buffer->idx++;
- return_trace (true);
- }
-
- template<typename Iterator,
- typename SrcLookup,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- ValueFormat newFormat,
- const hb_map_t *layout_variation_idx_map)
- {
- auto out = c->extend_min (this);
- if (unlikely (!out)) return;
- if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
- if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
-
- + it
- | hb_map (hb_second)
- | hb_apply ([&] (hb_array_t<const Value> _)
- { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); })
- ;
-
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
-
- coverage.serialize_serialize (c, glyphs);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- unsigned sub_length = valueFormat.get_len ();
- auto values_array = values.as_array (valueCount * sub_length);
-
- auto it =
- + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
- | hb_filter (glyphset, hb_first)
- | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
- {
- return hb_pair (glyph_map[_.first],
- values_array.sub_array (_.second * sub_length,
- sub_length));
- })
- ;
-
- bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- coverage.sanitize (c, this) &&
- valueFormat.sanitize_values (c, this, values, valueCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat; /* Defines the types of data in the
- * ValueRecord */
- HBUINT16 valueCount; /* Number of ValueRecords */
- ValueRecord values; /* Array of ValueRecords--positioning
- * values applied to glyphs */
- public:
- DEFINE_SIZE_ARRAY (8, values);
-};
-
-struct SinglePos
-{
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- unsigned get_format (Iterator glyph_val_iter_pairs)
- {
- hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
-
- for (const auto iter : glyph_val_iter_pairs)
- for (const auto _ : hb_zip (iter.second, first_val_iter))
- if (_.first != _.second)
- return 2;
-
- return 1;
- }
-
-
- template<typename Iterator,
- typename SrcLookup,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- const SrcLookup* src,
- Iterator glyph_val_iter_pairs,
- const hb_map_t *layout_variation_idx_map)
- {
- if (unlikely (!c->extend_min (u.format))) return;
- unsigned format = 2;
- ValueFormat new_format = src->get_value_format ();
-
- if (glyph_val_iter_pairs)
- {
- format = get_format (glyph_val_iter_pairs);
- new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second));
- }
-
- u.format = format;
- switch (u.format) {
- case 1: u.format1.serialize (c,
- src,
- glyph_val_iter_pairs,
- new_format,
- layout_variation_idx_map);
- return;
- case 2: u.format2.serialize (c,
- src,
- glyph_val_iter_pairs,
- new_format,
- layout_variation_idx_map);
- return;
- default:return;
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- SinglePosFormat1 format1;
- SinglePosFormat2 format2;
- } u;
-};
-
-template<typename Iterator, typename SrcLookup>
-static void
-SinglePos_serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- const hb_map_t *layout_variation_idx_map)
-{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); }
-
-
-struct PairValueRecord
-{
- friend struct PairSet;
-
- int cmp (hb_codepoint_t k) const
- { return secondGlyph.cmp (k); }
-
- struct context_t
- {
- const void *base;
- const ValueFormat *valueFormats;
- const ValueFormat *newFormats;
- unsigned len1; /* valueFormats[0].get_len() */
- const hb_map_t *glyph_map;
- const hb_map_t *layout_variation_idx_map;
- };
-
- bool subset (hb_subset_context_t *c,
- context_t *closure) const
- {
- TRACE_SERIALIZE (this);
- auto *s = c->serializer;
- auto *out = s->start_embed (*this);
- if (unlikely (!s->extend_min (out))) return_trace (false);
-
- out->secondGlyph = (*closure->glyph_map)[secondGlyph];
-
- closure->valueFormats[0].copy_values (s,
- closure->newFormats[0],
- closure->base, &values[0],
- closure->layout_variation_idx_map);
- closure->valueFormats[1].copy_values (s,
- closure->newFormats[1],
- closure->base,
- &values[closure->len1],
- closure->layout_variation_idx_map);
-
- return_trace (true);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const ValueFormat *valueFormats,
- const void *base) const
- {
- unsigned record1_len = valueFormats[0].get_len ();
- unsigned record2_len = valueFormats[1].get_len ();
- const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
-
- if (valueFormats[0].has_device ())
- valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
-
- if (valueFormats[1].has_device ())
- valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
- }
-
- bool intersects (const hb_set_t& glyphset) const
- {
- return glyphset.has(secondGlyph);
- }
-
- const Value* get_values_1 () const
- {
- return &values[0];
- }
-
- const Value* get_values_2 (ValueFormat format1) const
- {
- return &values[format1.get_len ()];
- }
-
- protected:
- HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the
- * pair--first glyph is listed in the
- * Coverage table */
- ValueRecord values; /* Positioning data for the first glyph
- * followed by for second glyph */
- public:
- DEFINE_SIZE_ARRAY (2, values);
-};
-
-struct PairSet
-{
- friend struct PairPosFormat1;
-
- 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);
-
- const PairValueRecord *record = &firstPairValueRecord;
- unsigned int count = len;
- for (unsigned int i = 0; i < count; i++)
- {
- if (glyphs->has (record->secondGlyph))
- return true;
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
- return false;
- }
-
- 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);
-
- const PairValueRecord *record = &firstPairValueRecord;
- c->input->add_array (&record->secondGlyph, len, record_size);
- }
-
- 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);
-
- const PairValueRecord *record = &firstPairValueRecord;
- unsigned count = len;
- for (unsigned i = 0; i < count; i++)
- {
- if (c->glyph_set->has (record->secondGlyph))
- { record->collect_variation_indices (c, valueFormats, this); }
-
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
- }
-
- bool apply (hb_ot_apply_context_t *c,
- const ValueFormat *valueFormats,
- unsigned int pos) const
- {
- TRACE_APPLY (this);
- 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);
-
- const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
- &firstPairValueRecord,
- len,
- record_size);
- if (record)
- {
- bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
- bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
- if (applied_first || applied_second)
- buffer->unsafe_to_break (buffer->idx, pos + 1);
- if (len2)
- pos++;
- buffer->idx = pos;
- return_trace (true);
- }
- buffer->unsafe_to_concat (buffer->idx, pos + 1);
- return_trace (false);
- }
-
- bool subset (hb_subset_context_t *c,
- const ValueFormat valueFormats[2],
- const ValueFormat newFormats[2]) const
- {
- TRACE_SUBSET (this);
- auto snap = c->serializer->snapshot ();
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->len = 0;
-
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- unsigned len1 = valueFormats[0].get_len ();
- unsigned len2 = valueFormats[1].get_len ();
- unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
-
- PairValueRecord::context_t context =
- {
- this,
- valueFormats,
- newFormats,
- len1,
- &glyph_map,
- c->plan->layout_variation_idx_map
- };
-
- const PairValueRecord *record = &firstPairValueRecord;
- unsigned count = len, num = 0;
- for (unsigned i = 0; i < count; i++)
- {
- if (glyphset.has (record->secondGlyph)
- && record->subset (c, &context)) num++;
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
-
- out->len = num;
- if (!num) c->serializer->revert (snap);
- return_trace (num);
- }
-
- struct sanitize_closure_t
- {
- const ValueFormat *valueFormats;
- unsigned int len1; /* valueFormats[0].get_len() */
- unsigned int stride; /* 1 + len1 + len2 */
- };
-
- bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
- {
- TRACE_SANITIZE (this);
- if (!(c->check_struct (this)
- && c->check_range (&firstPairValueRecord,
- len,
- HBUINT16::static_size,
- closure->stride))) return_trace (false);
-
- unsigned int count = len;
- const PairValueRecord *record = &firstPairValueRecord;
- return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
- closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
- }
-
- protected:
- HBUINT16 len; /* Number of PairValueRecords */
- PairValueRecord firstPairValueRecord;
- /* Array of PairValueRecords--ordered
- * by GlyphID of the second glyph */
- public:
- DEFINE_SIZE_MIN (2);
-};
-
-struct PairPosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return
- + hb_zip (this+coverage, pairSet)
- | hb_filter (*glyphs, hb_first)
- | hb_map (hb_second)
- | hb_map ([glyphs, this] (const Offset16To<PairSet> &_)
- { return (this+_).intersects (glyphs, valueFormat); })
- | hb_any
- ;
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
-
- auto it =
- + hb_zip (this+coverage, pairSet)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- if (!it) return;
- + it
- | hb_map (hb_add (this))
- | hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
- ;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- unsigned int count = pairSet.len;
- for (unsigned int i = 0; i < count; i++)
- (this+pairSet[i]).collect_glyphs (c, valueFormat);
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- unsigned unsafe_to;
- if (!skippy_iter.next (&unsafe_to))
- {
- buffer->unsafe_to_concat (buffer->idx, unsafe_to);
- return_trace (false);
- }
-
- return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
-
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
- out->valueFormat[0] = valueFormat[0];
- out->valueFormat[1] = valueFormat[1];
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- {
- hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
- out->valueFormat[0] = newFormats.first;
- out->valueFormat[1] = newFormats.second;
- }
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
-
- + hb_zip (this+coverage, pairSet)
- | hb_filter (glyphset, hb_first)
- | hb_filter ([this, c, out] (const Offset16To<PairSet>& _)
- {
- auto snap = c->serializer->snapshot ();
- auto *o = out->pairSet.serialize_append (c->serializer);
- if (unlikely (!o)) return false;
- bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
- if (!ret)
- {
- out->pairSet.pop ();
- c->serializer->revert (snap);
- }
- return ret;
- },
- 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));
- }
-
-
- 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 format1 = 0;
- unsigned format2 = 0;
- for (const Offset16To<PairSet>& _ :
- + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
- {
- const PairSet& set = (this + _);
- const PairValueRecord *record = &set.firstPairValueRecord;
-
- for (unsigned i = 0; i < set.len; i++)
- {
- if (record->intersects (glyphset))
- {
- format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
- format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
- }
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
- }
-
- return hb_pair (format1, format2);
- }
-
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
-
- if (!c->check_struct (this)) return_trace (false);
-
- unsigned int len1 = valueFormat[0].get_len ();
- unsigned int len2 = valueFormat[1].get_len ();
- PairSet::sanitize_closure_t closure =
- {
- valueFormat,
- len1,
- 1 + len1 + len2
- };
-
- return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat[2]; /* [0] Defines the types of data in
- * ValueRecord1--for the first glyph
- * in the pair--may be zero (0) */
- /* [1] Defines the types of data in
- * ValueRecord2--for the second glyph
- * in the pair--may be zero (0) */
- Array16OfOffset16To<PairSet>
- pairSet; /* Array of PairSet tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (10, pairSet);
-};
-
-struct PairPosFormat2
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+coverage).intersects (glyphs) &&
- (this+classDef2).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if (!intersects (c->glyph_set)) return;
- if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
-
- hb_set_t klass1_glyphs, klass2_glyphs;
- if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
- if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
-
- hb_set_t class1_set, class2_set;
- for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
- {
- if (!klass1_glyphs.has (cp)) class1_set.add (0);
- else
- {
- unsigned klass1 = (this+classDef1).get (cp);
- class1_set.add (klass1);
- }
- }
-
- class2_set.add (0);
- for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
- {
- unsigned klass2 = (this+classDef2).get (cp);
- class2_set.add (klass2);
- }
-
- if (class1_set.is_empty ()
- || class2_set.is_empty ()
- || (class2_set.get_population() == 1 && class2_set.has(0)))
- return;
-
- unsigned len1 = valueFormat1.get_len ();
- unsigned len2 = valueFormat2.get_len ();
- const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
- for (const unsigned class1_idx : class1_set.iter ())
- {
- for (const unsigned class2_idx : class2_set.iter ())
- {
- unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
- if (valueFormat1.has_device ())
- valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
-
- if (valueFormat2.has_device ())
- valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
- }
- }
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- unsigned unsafe_to;
- if (!skippy_iter.next (&unsafe_to))
- {
- buffer->unsafe_to_concat (buffer->idx, unsafe_to);
- return_trace (false);
- }
-
- unsigned int len1 = valueFormat1.get_len ();
- unsigned int len2 = valueFormat2.get_len ();
- unsigned int record_len = len1 + len2;
-
- unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
- unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
- if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
- {
- buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
- return_trace (false);
- }
-
- const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-
- bool applied_first = false, applied_second = false;
-
-
- /* Isolate simple kerning and apply it half to each side.
- * Results in better cursor positinoing / underline drawing.
- *
- * Disabled, because causes issues... :-(
- * https://github.com/harfbuzz/harfbuzz/issues/3408
- * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978
- */
-#ifndef HB_SPLIT_KERN
- if (0)
-#endif
- {
- if (!len2)
- {
- const hb_direction_t dir = buffer->props.direction;
- const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
- const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
- unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
- if (backward)
- mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
- /* Add Devices. */
- mask |= mask << 4;
-
- if (valueFormat1 & ~mask)
- goto bail;
-
- /* Is simple kern. Apply value on an empty position slot,
- * then split it between sides. */
-
- hb_glyph_position_t pos{};
- if (valueFormat1.apply_value (c, this, v, pos))
- {
- hb_position_t *src = &pos.x_advance;
- hb_position_t *dst1 = &buffer->cur_pos().x_advance;
- hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
- unsigned i = horizontal ? 0 : 1;
-
- hb_position_t kern = src[i];
- hb_position_t kern1 = kern >> 1;
- hb_position_t kern2 = kern - kern1;
-
- if (!backward)
- {
- dst1[i] += kern1;
- dst2[i] += kern2;
- dst2[i + 2] += kern2;
- }
- else
- {
- dst1[i] += kern1;
- dst1[i + 2] += src[i + 2] - kern2;
- dst2[i] += kern2;
- }
-
- applied_first = applied_second = kern != 0;
- goto success;
- }
- goto boring;
- }
- }
- bail:
-
-
- applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
- applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
-
- success:
- if (applied_first || applied_second)
- buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
- else
- boring:
- buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
-
-
- buffer->idx = skippy_iter.idx;
- if (len2)
- buffer->idx++;
-
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass1_map;
- out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
- out->class1Count = klass1_map.get_population ();
-
- hb_map_t klass2_map;
- out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
- out->class2Count = klass2_map.get_population ();
-
- unsigned len1 = valueFormat1.get_len ();
- unsigned len2 = valueFormat2.get_len ();
-
- hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- newFormats = compute_effective_value_formats (klass1_map, klass2_map);
-
- out->valueFormat1 = newFormats.first;
- out->valueFormat2 = newFormats.second;
-
- for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
- {
- 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, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map);
- valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
- }
- }
-
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- out->coverage.serialize_serialize (c->serializer, it);
- return_trace (out->class1Count && out->class2Count && bool (it));
- }
-
-
- hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
- const hb_map_t& klass2_map) const
- {
- unsigned len1 = valueFormat1.get_len ();
- unsigned len2 = valueFormat2.get_len ();
-
- unsigned format1 = 0;
- unsigned format2 = 0;
-
- for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
- {
- for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
- {
- unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
- format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
- format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
- }
- }
-
- return hb_pair (format1, format2);
- }
-
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!(c->check_struct (this)
- && coverage.sanitize (c, this)
- && classDef1.sanitize (c, this)
- && classDef2.sanitize (c, this))) return_trace (false);
-
- unsigned int len1 = valueFormat1.get_len ();
- unsigned int len2 = valueFormat2.get_len ();
- unsigned int stride = 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,
- count,
- record_size) &&
- valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
- valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat1; /* ValueRecord definition--for the
- * first glyph of the pair--may be zero
- * (0) */
- ValueFormat valueFormat2; /* ValueRecord definition--for the
- * second glyph of the pair--may be
- * zero (0) */
- Offset16To<ClassDef>
- classDef1; /* Offset to ClassDef table--from
- * beginning of PairPos subtable--for
- * the first glyph of the pair */
- Offset16To<ClassDef>
- classDef2; /* Offset to ClassDef table--from
- * beginning of PairPos subtable--for
- * the second glyph of the pair */
- HBUINT16 class1Count; /* Number of classes in ClassDef1
- * table--includes Class0 */
- HBUINT16 class2Count; /* Number of classes in ClassDef2
- * table--includes Class0 */
- ValueRecord values; /* Matrix of value pairs:
- * class1-major, class2-minor,
- * Each entry has value1 and value2 */
- public:
- DEFINE_SIZE_ARRAY (16, values);
-};
-
-struct PairPos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- PairPosFormat1 format1;
- PairPosFormat2 format2;
- } u;
-};
-
-
-struct EntryExitRecord
-{
- friend struct CursivePosFormat1;
-
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const void *src_base) const
- {
- (src_base+entryAnchor).collect_variation_indices (c);
- (src_base+exitAnchor).collect_variation_indices (c);
- }
-
- EntryExitRecord* subset (hb_subset_context_t *c,
- const void *src_base) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
- out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
- return_trace (out);
- }
-
- protected:
- Offset16To<Anchor>
- entryAnchor; /* Offset to EntryAnchor table--from
- * beginning of CursivePos
- * subtable--may be NULL */
- Offset16To<Anchor>
- exitAnchor; /* Offset to ExitAnchor table--from
- * beginning of CursivePos
- * subtable--may be NULL */
- public:
- DEFINE_SIZE_STATIC (4);
-};
-
-static void
-reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent);
-
-struct CursivePosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+coverage, entryExitRecord)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
- ;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
-
- const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
- if (!this_record.entryAnchor) return_trace (false);
-
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
- if (!prev_record.exitAnchor)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- unsigned int i = skippy_iter.idx;
- unsigned int j = buffer->idx;
-
- buffer->unsafe_to_break (i, j);
- float entry_x, entry_y, exit_x, exit_y;
- (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
- (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
-
- hb_glyph_position_t *pos = buffer->pos;
-
- hb_position_t d;
- /* Main-direction adjustment */
- switch (c->direction) {
- case HB_DIRECTION_LTR:
- pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
-
- d = roundf (entry_x) + pos[j].x_offset;
- pos[j].x_advance -= d;
- pos[j].x_offset -= d;
- break;
- case HB_DIRECTION_RTL:
- d = roundf (exit_x) + pos[i].x_offset;
- pos[i].x_advance -= d;
- pos[i].x_offset -= d;
-
- pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
- break;
- case HB_DIRECTION_TTB:
- pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
-
- d = roundf (entry_y) + pos[j].y_offset;
- pos[j].y_advance -= d;
- pos[j].y_offset -= d;
- break;
- case HB_DIRECTION_BTT:
- d = roundf (exit_y) + pos[i].y_offset;
- pos[i].y_advance -= d;
- pos[i].y_offset -= d;
-
- pos[j].y_advance = roundf (entry_y);
- break;
- case HB_DIRECTION_INVALID:
- default:
- break;
- }
-
- /* Cross-direction adjustment */
-
- /* We attach child to parent (think graph theory and rooted trees whereas
- * the root stays on baseline and each node aligns itself against its
- * parent.
- *
- * Optimize things for the case of RightToLeft, as that's most common in
- * Arabic. */
- unsigned int child = i;
- unsigned int parent = j;
- hb_position_t x_offset = entry_x - exit_x;
- hb_position_t y_offset = entry_y - exit_y;
- if (!(c->lookup_props & LookupFlag::RightToLeft))
- {
- unsigned int k = child;
- child = parent;
- parent = k;
- x_offset = -x_offset;
- y_offset = -y_offset;
- }
-
- /* If child was already connected to someone else, walk through its old
- * chain and reverse the link direction, such that the whole tree of its
- * previous connection now attaches to new parent. Watch out for case
- * where new parent is on the path from old chain...
- */
- reverse_cursive_minor_offset (pos, child, c->direction, parent);
-
- pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
- pos[child].attach_chain() = (int) parent - (int) child;
- buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
- if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
- pos[child].y_offset = y_offset;
- else
- pos[child].x_offset = x_offset;
-
- /* If parent was attached to child, separate them.
- * https://github.com/harfbuzz/harfbuzz/issues/2469
- */
- if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
- pos[parent].attach_chain() = 0;
-
- buffer->idx++;
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_subset_context_t *c,
- Iterator it,
- const void *src_base)
- {
- if (unlikely (!c->serializer->extend_min ((*this)))) return;
- this->format = 1;
- this->entryExitRecord.len = it.len ();
-
- for (const EntryExitRecord& entry_record : + it
- | hb_map (hb_second))
- entry_record.subset (c, src_base);
-
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
-
- coverage.serialize_serialize (c->serializer, glyphs);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
-
- auto it =
- + hb_zip (this+coverage, entryExitRecord)
- | hb_filter (glyphset, hb_first)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
- { return hb_pair (glyph_map[p.first], p.second);})
- ;
-
- bool ret = bool (it);
- out->serialize (c, it, this);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- Array16Of<EntryExitRecord>
- entryExitRecord; /* Array of EntryExit records--in
- * Coverage Index order */
- public:
- DEFINE_SIZE_ARRAY (6, entryExitRecord);
-};
-
-struct CursivePos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- CursivePosFormat1 format1;
- } u;
-};
-
-
-typedef AnchorMatrix BaseArray; /* base-major--
- * in order of BaseCoverage Index--,
- * mark-minor--
- * ordered by class--zero-based. */
-
-static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
- const MarkArray &mark_array,
- const hb_set_t &glyphset,
- hb_map_t* klass_mapping /* INOUT */)
-{
- hb_set_t orig_classes;
-
- + hb_zip (mark_coverage, mark_array)
- | hb_filter (glyphset, hb_first)
- | hb_map (hb_second)
- | hb_map (&MarkRecord::get_class)
- | hb_sink (orig_classes)
- ;
-
- unsigned idx = 0;
- for (auto klass : orig_classes.iter ())
- {
- if (klass_mapping->has (klass)) continue;
- klass_mapping->set (klass, idx);
- idx++;
- }
-}
-
-struct MarkBasePosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+markCoverage).intersects (glyphs) &&
- (this+baseCoverage).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
- ;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
-
- unsigned basecount = (this+baseArray).rows;
- auto base_iter =
- + hb_zip (this+baseCoverage, hb_range (basecount))
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- hb_sorted_vector_t<unsigned> base_indexes;
- for (const unsigned row : base_iter)
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (base_indexes)
- ;
- }
- (this+baseArray).collect_variation_indices (c, base_indexes.iter ());
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+markCoverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- 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 */
- 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))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- /* We only want to attach to the first of a MultipleSubst sequence.
- * https://github.com/harfbuzz/harfbuzz/issues/740
- * Reject others...
- * ...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_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);
-
- /* 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); }
-
- unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
- if (base_index == NOT_COVERED)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
-
- if (!klass_mapping.get_population ()) return_trace (false);
- out->classCount = klass_mapping.get_population ();
-
- auto mark_iter =
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (glyphset, hb_first)
- ;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + mark_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- out->markArray.serialize_subset (c, markArray, this,
- (this+markCoverage).iter (),
- &klass_mapping);
-
- unsigned basecount = (this+baseArray).rows;
- auto base_iter =
- + hb_zip (this+baseCoverage, hb_range (basecount))
- | hb_filter (glyphset, hb_first)
- ;
-
- new_coverage.reset ();
- + base_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- hb_sorted_vector_t<unsigned> base_indexes;
- for (const unsigned row : + base_iter
- | hb_map (hb_second))
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (base_indexes)
- ;
- }
-
- out->baseArray.serialize_subset (c, baseArray, this,
- base_iter.len (),
- base_indexes.iter ());
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- markCoverage.sanitize (c, this) &&
- baseCoverage.sanitize (c, this) &&
- markArray.sanitize (c, this) &&
- baseArray.sanitize (c, this, (unsigned int) classCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- markCoverage; /* Offset to MarkCoverage table--from
- * beginning of MarkBasePos subtable */
- Offset16To<Coverage>
- baseCoverage; /* Offset to BaseCoverage table--from
- * beginning of MarkBasePos subtable */
- HBUINT16 classCount; /* Number of classes defined for marks */
- Offset16To<MarkArray>
- markArray; /* Offset to MarkArray table--from
- * beginning of MarkBasePos subtable */
- Offset16To<BaseArray>
- baseArray; /* Offset to BaseArray table--from
- * beginning of MarkBasePos subtable */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-struct MarkBasePos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkBasePosFormat1 format1;
- } u;
-};
-
-
-typedef AnchorMatrix LigatureAttach; /* component-major--
- * in order of writing direction--,
- * mark-minor--
- * ordered by class--zero-based. */
-
-/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
-struct LigatureArray : List16OfOffset16To<LigatureAttach>
-{
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool subset (hb_subset_context_t *c,
- Iterator coverage,
- unsigned class_count,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
-
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- for (const auto _ : + hb_zip (coverage, *this)
- | hb_filter (glyphset, hb_first))
- {
- auto *matrix = out->serialize_append (c->serializer);
- if (unlikely (!matrix)) return_trace (false);
-
- const LigatureAttach& src = (this + _.second);
- auto indexes =
- + hb_range (src.rows * class_count)
- | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
- ;
- matrix->serialize_subset (c,
- _.second,
- this,
- src.rows,
- indexes);
- }
- return_trace (this->len);
- }
-};
-
-struct MarkLigPosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+markCoverage).intersects (glyphs) &&
- (this+ligatureCoverage).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
- ;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
-
- unsigned ligcount = (this+ligatureArray).len;
- auto lig_iter =
- + hb_zip (this+ligatureCoverage, hb_range (ligcount))
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- const LigatureArray& lig_array = this+ligatureArray;
- for (const unsigned i : lig_iter)
- {
- hb_sorted_vector_t<unsigned> lig_indexes;
- unsigned row_count = lig_array[i].rows;
- for (unsigned row : + hb_range (row_count))
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (lig_indexes)
- ;
- }
-
- lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
- }
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+markCoverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- 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 */
- 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))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
- //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
-
- unsigned int j = skippy_iter.idx;
- unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
- if (lig_index == NOT_COVERED)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- const LigatureArray& lig_array = this+ligatureArray;
- const LigatureAttach& lig_attach = lig_array[lig_index];
-
- /* Find component to attach to */
- unsigned int comp_count = lig_attach.rows;
- if (unlikely (!comp_count))
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- /* We must now check whether the ligature ID of the current mark glyph
- * is identical to the ligature ID of the found ligature. If yes, we
- * can directly use the component index. If not, we attach the mark
- * glyph to the last component of the ligature. */
- unsigned int comp_index;
- unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
- unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
- unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
- if (lig_id && lig_id == mark_id && mark_comp > 0)
- comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
- else
- comp_index = comp_count - 1;
-
- return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
-
- if (!klass_mapping.get_population ()) return_trace (false);
- out->classCount = klass_mapping.get_population ();
-
- auto mark_iter =
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (glyphset, hb_first)
- ;
-
- auto new_mark_coverage =
- + mark_iter
- | hb_map_retains_sorting (hb_first)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
- return_trace (false);
-
- out->markArray.serialize_subset (c, markArray, this,
- (this+markCoverage).iter (),
- &klass_mapping);
-
- auto new_ligature_coverage =
- + hb_iter (this + ligatureCoverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
- return_trace (false);
-
- out->ligatureArray.serialize_subset (c, ligatureArray, this,
- hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- markCoverage.sanitize (c, this) &&
- ligatureCoverage.sanitize (c, this) &&
- markArray.sanitize (c, this) &&
- ligatureArray.sanitize (c, this, (unsigned int) classCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- markCoverage; /* Offset to Mark Coverage table--from
- * beginning of MarkLigPos subtable */
- Offset16To<Coverage>
- ligatureCoverage; /* Offset to Ligature Coverage
- * table--from beginning of MarkLigPos
- * subtable */
- HBUINT16 classCount; /* Number of defined mark classes */
- Offset16To<MarkArray>
- markArray; /* Offset to MarkArray table--from
- * beginning of MarkLigPos subtable */
- Offset16To<LigatureArray>
- ligatureArray; /* Offset to LigatureArray table--from
- * beginning of MarkLigPos subtable */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-
-struct MarkLigPos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkLigPosFormat1 format1;
- } u;
-};
-
-
-typedef AnchorMatrix Mark2Array; /* mark2-major--
- * in order of Mark2Coverage Index--,
- * mark1-minor--
- * ordered by class--zero-based. */
-
-struct MarkMarkPosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+mark1Coverage).intersects (glyphs) &&
- (this+mark2Coverage).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+mark1Coverage, this+mark1Array)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
- ;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
-
- unsigned mark2_count = (this+mark2Array).rows;
- auto mark2_iter =
- + hb_zip (this+mark2Coverage, hb_range (mark2_count))
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- hb_sorted_vector_t<unsigned> mark2_indexes;
- for (const unsigned row : mark2_iter)
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (mark2_indexes)
- ;
- }
- (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+mark1Coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint);
- if (likely (mark1_index == NOT_COVERED)) return_trace (false);
-
- /* now we search backwards for a suitable mark glyph until a non-mark glyph */
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- unsigned int j = skippy_iter.idx;
-
- unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
- unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
- unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
- unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
-
- if (likely (id1 == id2))
- {
- if (id1 == 0) /* Marks belonging to the same base. */
- goto good;
- else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
- goto good;
- }
- else
- {
- /* If ligature ids don't match, it may be the case that one of the marks
- * itself is a ligature. In which case match. */
- if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
- goto good;
- }
-
- /* Didn't match. */
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
-
- good:
- unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
- if (mark2_index == NOT_COVERED)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
-
- if (!klass_mapping.get_population ()) return_trace (false);
- out->classCount = klass_mapping.get_population ();
-
- auto mark1_iter =
- + hb_zip (this+mark1Coverage, this+mark1Array)
- | hb_filter (glyphset, hb_first)
- ;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + mark1_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- out->mark1Array.serialize_subset (c, mark1Array, this,
- (this+mark1Coverage).iter (),
- &klass_mapping);
-
- unsigned mark2count = (this+mark2Array).rows;
- auto mark2_iter =
- + hb_zip (this+mark2Coverage, hb_range (mark2count))
- | hb_filter (glyphset, hb_first)
- ;
-
- new_coverage.reset ();
- + mark2_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- hb_sorted_vector_t<unsigned> mark2_indexes;
- for (const unsigned row : + mark2_iter
- | hb_map (hb_second))
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (mark2_indexes)
- ;
- }
-
- out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- mark1Coverage.sanitize (c, this) &&
- mark2Coverage.sanitize (c, this) &&
- mark1Array.sanitize (c, this) &&
- mark2Array.sanitize (c, this, (unsigned int) classCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- mark1Coverage; /* Offset to Combining Mark1 Coverage
- * table--from beginning of MarkMarkPos
- * subtable */
- Offset16To<Coverage>
- mark2Coverage; /* Offset to Combining Mark2 Coverage
- * table--from beginning of MarkMarkPos
- * subtable */
- HBUINT16 classCount; /* Number of defined mark classes */
- Offset16To<MarkArray>
- mark1Array; /* Offset to Mark1Array table--from
- * beginning of MarkMarkPos subtable */
- Offset16To<Mark2Array>
- mark2Array; /* Offset to Mark2Array table--from
- * beginning of MarkMarkPos subtable */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-struct MarkMarkPos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkMarkPosFormat1 format1;
- } u;
-};
-
-
-struct ContextPos : Context {};
-
-struct ChainContextPos : ChainContext {};
-
-struct ExtensionPos : Extension<ExtensionPos>
-{
- typedef struct PosLookupSubTable SubTable;
-};
-
-
-
-/*
- * PosLookup
- */
-
-
-struct PosLookupSubTable
-{
- friend struct Lookup;
- friend struct PosLookup;
-
- enum Type {
- Single = 1,
- Pair = 2,
- Cursive = 3,
- MarkBase = 4,
- MarkLig = 5,
- MarkMark = 6,
- Context = 7,
- ChainContext = 8,
- Extension = 9
- };
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, lookup_type);
- switch (lookup_type) {
- case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
- case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
- case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
- case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
- case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
- case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
- case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
- case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
- case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
- default: return_trace (c->default_return_value ());
- }
- }
-
- bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c, lookup_type);
- }
-
- protected:
- union {
- SinglePos single;
- PairPos pair;
- CursivePos cursive;
- MarkBasePos markBase;
- MarkLigPos markLig;
- MarkMarkPos markMark;
- ContextPos context;
- ChainContextPos chainContext;
- ExtensionPos extension;
- } u;
- public:
- DEFINE_SIZE_MIN (0);
-};
-
-
-struct PosLookup : Lookup
-{
- typedef struct PosLookupSubTable SubTable;
-
- const SubTable& get_subtable (unsigned int i) const
- { return Lookup::get_subtable<SubTable> (i); }
-
- bool is_reverse () const
- {
- return false;
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- return_trace (dispatch (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c);
- }
-
- hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
- { return dispatch (c); }
-
- hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
- {
- if (c->is_lookup_visited (this_index))
- return hb_closure_lookups_context_t::default_return_value ();
-
- c->set_lookup_visited (this_index);
- if (!intersects (c->glyphs))
- {
- c->set_lookup_inactive (this_index);
- return hb_closure_lookups_context_t::default_return_value ();
- }
- c->set_recurse_func (dispatch_closure_lookups_recurse_func);
-
- hb_closure_lookups_context_t::return_t ret = dispatch (c);
- return ret;
- }
-
- template <typename set_t>
- void collect_coverage (set_t *glyphs) const
- {
- hb_collect_coverage_context_t<set_t> c (glyphs);
- dispatch (&c);
- }
-
- static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
- template <typename context_t>
- static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
-
- HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index);
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
-
- bool subset (hb_subset_context_t *c) const
- { return Lookup::subset<SubTable> (c); }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return Lookup::sanitize<SubTable> (c); }
-};
-
-/*
- * GPOS -- Glyph Positioning
- * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
- */
-
-struct GPOS : GSUBGPOS
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
-
- const PosLookup& get_lookup (unsigned int i) const
- { return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
-
- static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
- static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
- static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
-
- bool subset (hb_subset_context_t *c) const
- {
- hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
- return GSUBGPOS::subset<PosLookup> (&l);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return GSUBGPOS::sanitize<PosLookup> (c); }
-
- HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
- hb_face_t *face) const;
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
- {
- if (!c->gpos_lookups->has (i)) continue;
- const PosLookup &l = get_lookup (i);
- l.dispatch (c);
- }
- }
-
- void closure_lookups (hb_face_t *face,
- const hb_set_t *glyphs,
- hb_set_t *lookup_indexes /* IN/OUT */) const
- { GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); }
-
- typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
-};
-
-
-static void
-reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
-{
- int chain = pos[i].attach_chain(), type = pos[i].attach_type();
- if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
- return;
-
- pos[i].attach_chain() = 0;
-
- unsigned int j = (int) i + chain;
-
- /* Stop if we see new parent in the chain. */
- if (j == new_parent)
- return;
-
- reverse_cursive_minor_offset (pos, j, direction, new_parent);
-
- if (HB_DIRECTION_IS_HORIZONTAL (direction))
- pos[j].y_offset = -pos[i].y_offset;
- else
- pos[j].x_offset = -pos[i].x_offset;
-
- pos[j].attach_chain() = -chain;
- pos[j].attach_type() = type;
-}
-static void
-propagate_attachment_offsets (hb_glyph_position_t *pos,
- unsigned int len,
- unsigned int i,
- hb_direction_t direction)
-{
- /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
- * offset of glyph they are attached to. */
- int chain = pos[i].attach_chain(), type = pos[i].attach_type();
- if (likely (!chain))
- return;
-
- pos[i].attach_chain() = 0;
-
- unsigned int j = (int) i + chain;
-
- if (unlikely (j >= len))
- return;
-
- propagate_attachment_offsets (pos, len, j, direction);
-
- assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
-
- if (type & ATTACH_TYPE_CURSIVE)
- {
- if (HB_DIRECTION_IS_HORIZONTAL (direction))
- pos[i].y_offset += pos[j].y_offset;
- else
- pos[i].x_offset += pos[j].x_offset;
- }
- else /*if (type & ATTACH_TYPE_MARK)*/
- {
- pos[i].x_offset += pos[j].x_offset;
- pos[i].y_offset += pos[j].y_offset;
-
- assert (j < i);
- if (HB_DIRECTION_IS_FORWARD (direction))
- for (unsigned int k = j; k < i; k++) {
- pos[i].x_offset -= pos[k].x_advance;
- pos[i].y_offset -= pos[k].y_advance;
- }
- else
- for (unsigned int k = j + 1; k < i + 1; k++) {
- pos[i].x_offset += pos[k].x_advance;
- pos[i].y_offset += pos[k].y_advance;
- }
- }
-}
-
-void
-GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
-{
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
-}
-
-void
-GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
-{
- //_hb_buffer_assert_gsubgpos_vars (buffer);
-}
-
-void
-GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
-{
- _hb_buffer_assert_gsubgpos_vars (buffer);
-
- unsigned int len;
- hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
- hb_direction_t direction = buffer->props.direction;
-
- /* Handle attachments */
- if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
- for (unsigned i = 0; i < len; i++)
- propagate_attachment_offsets (pos, len, i, direction);
-
- if (unlikely (font->slant))
- {
- for (unsigned i = 0; i < len; i++)
- if (unlikely (pos[i].y_offset))
- pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset);
- }
-}
-
-
-struct GPOS_accelerator_t : GPOS::accelerator_t {
- GPOS_accelerator_t (hb_face_t *face) : GPOS::accelerator_t (face) {}
-};
-
-
+// TODO(garretrieger): Move into new layout directory.
/* Out-of-class implementation for methods recursing */
-
#ifndef HB_NO_OT_LAYOUT
template <typename context_t>
/*static*/ typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
@@ -3121,27 +45,36 @@ template <typename context_t>
return l.dispatch (c);
}
-/*static*/ inline hb_closure_lookups_context_t::return_t PosLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
+template <>
+inline hb_closure_lookups_context_t::return_t
+PosLookup::dispatch_recurse_func<hb_closure_lookups_context_t> (hb_closure_lookups_context_t *c, unsigned this_index)
{
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (this_index);
return l.closure_lookups (c, this_index);
}
-/*static*/ bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
+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;
}
#endif
-
+} /* namespace GPOS_impl */
+} /* namespace Layout */
} /* namespace OT */
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 bef381430b..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
@@ -32,9 +32,8 @@
#include "OT/Layout/GSUB/GSUB.hh"
namespace OT {
-
-using Layout::GSUB::SubstLookup;
-using Layout::GSUB::ExtensionSubst;
+namespace Layout {
+namespace GSUB_impl {
// TODO(garretrieger): Move into the new layout directory.
/* Out-of-class implementation for methods recursing */
@@ -59,27 +58,36 @@ template <typename context_t>
return l.dispatch (c);
}
-/*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
+template <>
+inline hb_closure_lookups_context_t::return_t
+SubstLookup::dispatch_recurse_func<hb_closure_lookups_context_t> (hb_closure_lookups_context_t *c, unsigned this_index)
{
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index);
return l.closure_lookups (c, this_index);
}
-/*static*/ bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
+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;
}
#endif
-
+} /* namespace GSUB_impl */
+} /* namespace Layout */
} /* namespace OT */
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 56e8c5b006..10cc105de4 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh
@@ -100,8 +100,8 @@ struct hb_closure_context_t :
bool is_lookup_done (unsigned int lookup_index)
{
- if (done_lookups_glyph_count->in_error () ||
- done_lookups_glyph_set->in_error ())
+ if (unlikely (done_lookups_glyph_count->in_error () ||
+ done_lookups_glyph_set->in_error ()))
return true;
/* Have we visited this lookup with the current set of glyphs? */
@@ -109,17 +109,13 @@ struct hb_closure_context_t :
{
done_lookups_glyph_count->set (lookup_index, glyphs->get_population ());
- if (!done_lookups_glyph_set->get (lookup_index))
+ if (!done_lookups_glyph_set->has (lookup_index))
{
- hb_set_t* empty_set = hb_set_create ();
- if (unlikely (!done_lookups_glyph_set->set (lookup_index, empty_set)))
- {
- hb_set_destroy (empty_set);
+ if (unlikely (!done_lookups_glyph_set->set (lookup_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
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);
@@ -154,7 +150,7 @@ struct hb_closure_context_t :
bool pop_cur_done_glyphs ()
{
- if (active_glyphs_stack.length < 1)
+ if (!active_glyphs_stack)
return false;
active_glyphs_stack.pop ();
@@ -165,21 +161,19 @@ struct hb_closure_context_t :
hb_set_t *glyphs;
hb_set_t output[1];
hb_vector_t<hb_set_t> active_glyphs_stack;
- recurse_func_t recurse_func;
+ recurse_func_t recurse_func = nullptr;
unsigned int nesting_level_left;
hb_closure_context_t (hb_face_t *face_,
hb_set_t *glyphs_,
hb_map_t *done_lookups_glyph_count_,
- hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set_,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set_,
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
face (face_),
glyphs (glyphs_),
- recurse_func (nullptr),
nesting_level_left (nesting_level_left_),
done_lookups_glyph_count (done_lookups_glyph_count_),
- done_lookups_glyph_set (done_lookups_glyph_set_),
- lookup_count (0)
+ done_lookups_glyph_set (done_lookups_glyph_set_)
{}
~hb_closure_context_t () { flush (); }
@@ -197,8 +191,8 @@ struct hb_closure_context_t :
private:
hb_map_t *done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set;
- unsigned int lookup_count;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set;
+ unsigned int lookup_count = 0;
};
@@ -400,7 +394,6 @@ struct hb_collect_coverage_context_t :
set_t *set;
};
-
struct hb_ot_apply_context_t :
hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
{
@@ -416,7 +409,7 @@ struct hb_ot_apply_context_t :
match_func (nullptr),
match_data (nullptr) {}
- typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+ typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
@@ -434,15 +427,15 @@ struct hb_ot_apply_context_t :
MATCH_MAYBE
};
- may_match_t may_match (const hb_glyph_info_t &info,
- const HBUINT16 *glyph_data) const
+ may_match_t may_match (hb_glyph_info_t &info,
+ hb_codepoint_t glyph_data) const
{
if (!(info.mask & mask) ||
(syllable && syllable != info.syllable ()))
return MATCH_NO;
if (match_func)
- return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
+ return match_func (info, glyph_data, match_data) ? MATCH_YES : MATCH_NO;
return MATCH_MAYBE;
}
@@ -483,7 +476,10 @@ struct hb_ot_apply_context_t :
void init (hb_ot_apply_context_t *c_, bool context_match = false)
{
c = c_;
- match_glyph_data = nullptr;
+ match_glyph_data16 = nullptr;
+#ifndef HB_NO_BEYOND_64K
+ match_glyph_data24 = nullptr;
+#endif
matcher.set_match_func (nullptr, nullptr);
matcher.set_lookup_props (c->lookup_props);
/* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
@@ -498,12 +494,24 @@ struct hb_ot_apply_context_t :
matcher.set_lookup_props (lookup_props);
}
void set_match_func (matcher_t::match_func_t match_func_,
- const void *match_data_,
- const HBUINT16 glyph_data[])
+ const void *match_data_)
{
matcher.set_match_func (match_func_, match_data_);
- match_glyph_data = glyph_data;
}
+ void set_glyph_data (const HBUINT16 glyph_data[])
+ {
+ match_glyph_data16 = glyph_data;
+#ifndef HB_NO_BEYOND_64K
+ match_glyph_data24 = nullptr;
+#endif
+ }
+#ifndef HB_NO_BEYOND_64K
+ void set_glyph_data (const HBUINT24 glyph_data[])
+ {
+ match_glyph_data16 = nullptr;
+ match_glyph_data24 = glyph_data;
+ }
+#endif
void reset (unsigned int start_index_,
unsigned int num_items_)
@@ -517,40 +525,64 @@ struct hb_ot_apply_context_t :
void reject ()
{
num_items++;
- if (match_glyph_data) match_glyph_data--;
+ backup_glyph_data ();
}
matcher_t::may_skip_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);
- while (idx + num_items < end)
+ /* The alternate condition below is faster at string boundaries,
+ * but produces subpar "unsafe-to-concat" values. */
+ signed stop = (signed) end - (signed) num_items;
+ if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT)
+ stop = (signed) end - 1;
+ while ((signed) idx < stop)
{
idx++;
- const 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, match_glyph_data);
- if (match == matcher_t::MATCH_YES ||
- (match == matcher_t::MATCH_MAYBE &&
- skip == matcher_t::SKIP_NO))
+ switch (match (c->buffer->info[idx]))
{
- num_items--;
- if (match_glyph_data) match_glyph_data++;
- return true;
- }
-
- if (skip == matcher_t::SKIP_NO)
- {
- 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)
@@ -560,30 +592,30 @@ struct hb_ot_apply_context_t :
bool prev (unsigned *unsafe_from = nullptr)
{
assert (num_items > 0);
- while (idx > num_items - 1)
+ /* The alternate condition below is faster at string boundaries,
+ * but produces subpar "unsafe-to-concat" values. */
+ unsigned stop = num_items - 1;
+ if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT)
+ stop = 1 - 1;
+ while (idx > stop)
{
idx--;
- const 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, match_glyph_data);
- if (match == matcher_t::MATCH_YES ||
- (match == matcher_t::MATCH_MAYBE &&
- skip == matcher_t::SKIP_NO))
- {
- num_items--;
- if (match_glyph_data) match_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)
@@ -591,11 +623,43 @@ struct hb_ot_apply_context_t :
return false;
}
+ hb_codepoint_t
+ get_glyph_data ()
+ {
+ if (match_glyph_data16) return *match_glyph_data16;
+#ifndef HB_NO_BEYOND_64K
+ else
+ if (match_glyph_data24) return *match_glyph_data24;
+#endif
+ return 0;
+ }
+ void
+ advance_glyph_data ()
+ {
+ if (match_glyph_data16) match_glyph_data16++;
+#ifndef HB_NO_BEYOND_64K
+ else
+ if (match_glyph_data24) match_glyph_data24++;
+#endif
+ }
+ void
+ backup_glyph_data ()
+ {
+ if (match_glyph_data16) match_glyph_data16--;
+#ifndef HB_NO_BEYOND_64K
+ else
+ if (match_glyph_data24) match_glyph_data24--;
+#endif
+ }
+
unsigned int idx;
protected:
hb_ot_apply_context_t *c;
matcher_t matcher;
- const HBUINT16 *match_glyph_data;
+ const HBUINT16 *match_glyph_data16;
+#ifndef HB_NO_BEYOND_64K
+ const HBUINT24 *match_glyph_data24;
+#endif
unsigned int num_items;
unsigned int end;
@@ -611,7 +675,10 @@ struct hb_ot_apply_context_t :
return_t recurse (unsigned int sub_lookup_index)
{
if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
+ {
+ buffer->shaping_failed = true;
return default_return_value ();
+ }
nesting_level_left--;
bool ret = recurse_func (this, sub_lookup_index);
@@ -621,35 +688,38 @@ struct hb_ot_apply_context_t :
skipping_iterator_t iter_input, iter_context;
+ unsigned int table_index; /* GSUB/GPOS */
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
- recurse_func_t recurse_func;
+ recurse_func_t recurse_func = nullptr;
const GDEF &gdef;
const VariationStore &var_store;
+ VariationStore::cache_t *var_store_cache;
+ hb_set_digest_t digest;
hb_direction_t direction;
- hb_mask_t lookup_mask;
- unsigned int table_index; /* GSUB/GPOS */
- unsigned int lookup_index;
- unsigned int lookup_props;
- unsigned int nesting_level_left;
+ hb_mask_t lookup_mask = 1;
+ unsigned int lookup_index = (unsigned) -1;
+ unsigned int lookup_props = 0;
+ unsigned int nesting_level_left = HB_MAX_NESTING_LEVEL;
bool has_glyph_classes;
- bool auto_zwnj;
- bool auto_zwj;
- bool per_syllable;
- bool random;
-
- uint32_t random_state;
+ bool auto_zwnj = true;
+ bool auto_zwj = true;
+ bool per_syllable = false;
+ bool random = false;
+ 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_) :
- iter_input (), iter_context (),
+ table_index (table_index_),
font (font_), face (font->face), buffer (buffer_),
- recurse_func (nullptr),
gdef (
#ifndef HB_NO_OT_LAYOUT
*face->table.GDEF->table
@@ -658,18 +728,24 @@ struct hb_ot_apply_context_t :
#endif
),
var_store (gdef.get_var_store ()),
+ var_store_cache (
+#ifndef HB_NO_VAR
+ table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr
+#else
+ nullptr
+#endif
+ ),
+ digest (buffer_->digest ()),
direction (buffer_->props.direction),
- lookup_mask (1),
- table_index (table_index_),
- lookup_index ((unsigned int) -1),
- lookup_props (0),
- nesting_level_left (HB_MAX_NESTING_LEVEL),
- has_glyph_classes (gdef.has_glyph_classes ()),
- auto_zwnj (true),
- auto_zwj (true),
- per_syllable (false),
- random (false),
- random_state (1) { init_iters (); }
+ has_glyph_classes (gdef.has_glyph_classes ())
+ { init_iters (); }
+
+ ~hb_ot_apply_context_t ()
+ {
+#ifndef HB_NO_VAR
+ VariationStore::destroy_cache (var_store_cache);
+#endif
+ }
void init_iters ()
{
@@ -677,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 (); }
@@ -734,8 +810,13 @@ struct hb_ot_apply_context_t :
void _set_glyph_class (hb_codepoint_t glyph_index,
unsigned int class_guess = 0,
bool ligature = false,
- bool component = false) const
+ bool component = false)
{
+ digest.add (glyph_index);
+
+ if (new_syllables != (unsigned) -1)
+ buffer->cur().syllable() = new_syllables;
+
unsigned int props = _hb_glyph_info_get_glyph_props (&buffer->cur());
props |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
if (ligature)
@@ -765,24 +846,24 @@ struct hb_ot_apply_context_t :
_hb_glyph_info_set_glyph_props (&buffer->cur(), props);
}
- void replace_glyph (hb_codepoint_t glyph_index) const
+ void replace_glyph (hb_codepoint_t glyph_index)
{
_set_glyph_class (glyph_index);
(void) buffer->replace_glyph (glyph_index);
}
- void replace_glyph_inplace (hb_codepoint_t glyph_index) const
+ void replace_glyph_inplace (hb_codepoint_t glyph_index)
{
_set_glyph_class (glyph_index);
buffer->cur().codepoint = glyph_index;
}
void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
- unsigned int class_guess) const
+ unsigned int class_guess)
{
_set_glyph_class (glyph_index, class_guess, true);
(void) buffer->replace_glyph (glyph_index);
}
void output_glyph_for_component (hb_codepoint_t glyph_index,
- unsigned int class_guess) const
+ unsigned int class_guess)
{
_set_glyph_class (glyph_index, class_guess, false, true);
(void) buffer->output_glyph (glyph_index);
@@ -790,65 +871,155 @@ struct hb_ot_apply_context_t :
};
-struct hb_get_subtables_context_t :
- hb_dispatch_context_t<hb_get_subtables_context_t>
+struct hb_accelerate_subtables_context_t :
+ hb_dispatch_context_t<hb_accelerate_subtables_context_t>
{
template <typename Type>
- static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
+ static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c)
{
const Type *typed_obj = (const Type *) obj;
return typed_obj->apply (c);
}
- typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ template <typename T>
+ static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply (c, true) )
+ template <typename T>
+ static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
+ template <typename Type>
+ static inline bool apply_cached_to (const void *obj, hb_ot_apply_context_t *c)
+ {
+ const Type *typed_obj = (const Type *) obj;
+ return apply_cached_ (typed_obj, c, hb_prioritize);
+ }
+
+ template <typename T>
+ static inline auto cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) )
+ template <typename T>
+ static inline bool cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; }
+ template <typename Type>
+ static inline bool cache_func_to (const void *obj, hb_ot_apply_context_t *c, bool enter)
+ {
+ const Type *typed_obj = (const Type *) obj;
+ return cache_func_ (typed_obj, c, enter, hb_prioritize);
+ }
+#endif
+
+ typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c);
+ typedef bool (*hb_cache_func_t) (const void *obj, hb_ot_apply_context_t *c, bool enter);
struct hb_applicable_t
{
+ friend struct hb_accelerate_subtables_context_t;
+ friend struct hb_ot_layout_lookup_accelerator_t;
+
template <typename T>
- void init (const T &obj_, hb_apply_func_t apply_func_)
+ void init (const T &obj_,
+ hb_apply_func_t apply_func_
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ , hb_apply_func_t apply_cached_func_
+ , hb_cache_func_t cache_func_
+#endif
+ )
{
obj = &obj_;
apply_func = apply_func_;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ apply_cached_func = apply_cached_func_;
+ cache_func = cache_func_;
+#endif
digest.init ();
obj_.get_coverage ().collect_coverage (&digest);
}
- bool apply (OT::hb_ot_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c) const
{
return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
}
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ bool apply_cached (hb_ot_apply_context_t *c) const
+ {
+ return digest.may_have (c->buffer->cur().codepoint) && apply_cached_func (obj, c);
+ }
+ bool cache_enter (hb_ot_apply_context_t *c) const
+ {
+ return cache_func (obj, c, true);
+ }
+ void cache_leave (hb_ot_apply_context_t *c) const
+ {
+ cache_func (obj, c, false);
+ }
+#endif
private:
const void *obj;
hb_apply_func_t apply_func;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ hb_apply_func_t apply_cached_func;
+ hb_cache_func_t cache_func;
+#endif
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 () )
+ template <typename T>
+ auto cache_cost (const T &obj, hb_priority<0>) HB_AUTO_RETURN ( 0u )
+#endif
/* Dispatch interface. */
template <typename T>
return_t dispatch (const T &obj)
{
- hb_applicable_t *entry = array.push();
- entry->init (obj, apply_to<T>);
+ hb_applicable_t *entry = &array[i++];
+
+ entry->init (obj,
+ apply_to<T>
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ , apply_cached_to<T>
+ , cache_func_to<T>
+#endif
+ );
+
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ /* Cache handling
+ *
+ * We allow one subtable from each lookup to use a cache. The assumption
+ * being that multiple subtables of the same lookup cannot use a cache
+ * because the resources they would use will collide. As such, we ask
+ * each subtable to tell us how much it costs (which a cache would avoid),
+ * and we allocate the cache opportunity to the costliest subtable.
+ */
+ unsigned cost = cache_cost (obj, hb_prioritize);
+ if (cost > cache_user_cost)
+ {
+ cache_user_idx = i - 1;
+ cache_user_cost = cost;
+ }
+#endif
+
return hb_empty_t ();
}
static return_t default_return_value () { return hb_empty_t (); }
- hb_get_subtables_context_t (array_t &array_) :
- array (array_) {}
-
- array_t &array;
-};
+ hb_accelerate_subtables_context_t (hb_applicable_t *array_) :
+ array (array_) {}
+ hb_applicable_t *array;
+ unsigned i = 0;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ unsigned cache_user_idx = (unsigned) -1;
+ unsigned cache_user_cost = 0;
+#endif
+};
-typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs);
-typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data, void *cache);
+typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache);
+typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, unsigned value, const void *data);
+typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
struct ContextClosureFuncs
{
@@ -863,100 +1034,150 @@ struct ContextApplyFuncs
{
match_func_t match;
};
+struct ChainContextApplyFuncs
+{
+ match_func_t match[3];
+};
-static inline bool intersects_glyph (const hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED, void *cache HB_UNUSED)
{
return glyphs->has (value);
}
-static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data, void *cache)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
- return class_def.intersects_class (glyphs, value);
+ hb_map_t *map = (hb_map_t *) cache;
+
+ hb_codepoint_t *cached_v;
+ if (map->has (value, &cached_v))
+ return *cached_v;
+
+ bool v = class_def.intersects_class (glyphs, value);
+ map->set (value, v);
+
+ return v;
}
-static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data, void *cache HB_UNUSED)
{
- const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
+ Offset16To<Coverage> coverage;
+ coverage = value;
return (data+coverage).intersects (glyphs);
}
-static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache)
{
unsigned g = reinterpret_cast<const HBUINT16 *>(data)[value];
intersected_glyphs->add (g);
}
-static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+
+using intersected_class_cache_t = hb_hashmap_t<unsigned, hb_set_t>;
+
+static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
- class_def.intersected_class_glyphs (glyphs, value, intersected_glyphs);
+
+ intersected_class_cache_t *map = (intersected_class_cache_t *) cache;
+
+ hb_set_t *cached_v;
+ if (map->has (value, &cached_v))
+ {
+ intersected_glyphs->union_ (*cached_v);
+ return;
+ }
+
+ hb_set_t v;
+ class_def.intersected_class_glyphs (glyphs, value, &v);
+
+ intersected_glyphs->union_ (v);
+
+ map->set (value, std::move (v));
}
-static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs)
+
+static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache)
{
Offset16To<Coverage> coverage;
coverage = value;
- (data+coverage).intersected_coverage_glyphs (glyphs, intersected_glyphs);
+ (data+coverage).intersect_set (*glyphs, *intersected_glyphs);
}
+template <typename HBUINT>
static inline bool array_is_subset_of (const hb_set_t *glyphs,
unsigned int count,
- const HBUINT16 values[],
+ const HBUINT values[],
intersects_func_t intersects_func,
- const void *intersects_data)
+ const void *intersects_data,
+ void *cache)
{
- for (const HBUINT16 &_ : + hb_iter (values, count))
- if (!intersects_func (glyphs, _, intersects_data)) return false;
+ for (const auto &_ : + hb_iter (values, count))
+ if (!intersects_func (glyphs, _, intersects_data, cache)) return false;
return true;
}
-static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+static inline void collect_glyph (hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED)
{
glyphs->add (value);
}
-static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline void collect_class (hb_set_t *glyphs, unsigned value, const void *data)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
class_def.collect_class (glyphs, value);
}
-static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline void collect_coverage (hb_set_t *glyphs, unsigned value, const void *data)
{
- const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
+ Offset16To<Coverage> coverage;
+ coverage = value;
(data+coverage).collect_coverage (glyphs);
}
+template <typename HBUINT>
static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
hb_set_t *glyphs,
unsigned int count,
- const HBUINT16 values[],
+ const HBUINT values[],
collect_glyphs_func_t collect_func,
const void *collect_data)
{
return
+ hb_iter (values, count)
- | hb_apply ([&] (const HBUINT16 &_) { collect_func (glyphs, _, collect_data); })
+ | hb_apply ([&] (const HBUINT &_) { collect_func (glyphs, _, collect_data); })
;
}
-static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
+static inline bool match_glyph (hb_glyph_info_t &info, unsigned value, const void *data HB_UNUSED)
{
- return glyph_id == value;
+ return info.codepoint == value;
}
-static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+static inline bool match_class (hb_glyph_info_t &info, unsigned value, const void *data)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
- return class_def.get_class (glyph_id) == value;
+ return class_def.get_class (info.codepoint) == value;
}
-static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, const void *data)
{
- const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
- return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
+ unsigned klass = info.syllable();
+ if (klass < 255)
+ return klass == value;
+ const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+ klass = class_def.get_class (info.codepoint);
+ if (likely (klass < 255))
+ info.syllable() = klass;
+ return klass == value;
+}
+static inline bool match_coverage (hb_glyph_info_t &info, unsigned value, const void *data)
+{
+ Offset16To<Coverage> coverage;
+ coverage = value;
+ return (data+coverage).get_coverage (info.codepoint) != NOT_COVERED;
}
+template <typename HBUINT>
static inline bool would_match_input (hb_would_apply_context_t *c,
unsigned int count, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
match_func_t match_func,
const void *match_data)
{
@@ -964,14 +1185,19 @@ static inline bool would_match_input (hb_would_apply_context_t *c,
return false;
for (unsigned int i = 1; i < count; i++)
- if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
+ {
+ hb_glyph_info_t info;
+ info.codepoint = c->glyphs[i];
+ if (likely (!match_func (info, input[i - 1], match_data)))
return false;
+ }
return true;
}
+template <typename HBUINT>
static inline bool match_input (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
match_func_t match_func,
const void *match_data,
unsigned int *end_position,
@@ -986,7 +1212,8 @@ static inline bool match_input (hb_ot_apply_context_t *c,
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, count - 1);
- skippy_iter.set_match_func (match_func, match_data, input);
+ skippy_iter.set_match_func (match_func, match_data);
+ skippy_iter.set_glyph_data (input);
/*
* This is perhaps the trickiest part of OpenType... Remarks:
@@ -1207,9 +1434,10 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
return_trace (true);
}
+template <typename HBUINT>
static inline bool match_backtrack (hb_ot_apply_context_t *c,
unsigned int count,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
match_func_t match_func,
const void *match_data,
unsigned int *match_start)
@@ -1218,7 +1446,8 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
skippy_iter.reset (c->buffer->backtrack_len (), count);
- skippy_iter.set_match_func (match_func, match_data, backtrack);
+ skippy_iter.set_match_func (match_func, match_data);
+ skippy_iter.set_glyph_data (backtrack);
for (unsigned int i = 0; i < count; i++)
{
@@ -1234,9 +1463,10 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
return_trace (true);
}
+template <typename HBUINT>
static inline bool match_lookahead (hb_ot_apply_context_t *c,
unsigned int count,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
match_func_t match_func,
const void *match_data,
unsigned int start_index,
@@ -1246,7 +1476,8 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
skippy_iter.reset (start_index - 1, count);
- skippy_iter.set_match_func (match_func, match_data, lookahead);
+ skippy_iter.set_match_func (match_func, match_data);
+ skippy_iter.set_glyph_data (lookahead);
for (unsigned int i = 0; i < count; i++)
{
@@ -1310,27 +1541,30 @@ static unsigned serialize_lookuprecord_array (hb_serialize_context_t *c,
enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 };
+template <typename HBUINT>
static void context_closure_recurse_lookups (hb_closure_context_t *c,
- unsigned inputCount, const HBUINT16 input[],
+ unsigned inputCount, const HBUINT input[],
unsigned lookupCount,
const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */,
unsigned value,
ContextFormat context_format,
const void *data,
- intersected_glyphs_func_t intersected_glyphs_func)
+ 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_is_empty (covered_seq_indicies) || !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) {
@@ -1338,7 +1572,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
pos_glyphs.add (value);
break;
case ContextFormat::ClassBasedContext:
- intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs);
+ intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs, cache);
break;
case ContextFormat::CoverageBasedContext:
pos_glyphs.set (c->parent_active_glyphs ());
@@ -1355,13 +1589,13 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
input_value = input[seqIndex - 1];
}
- intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs);
+ intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs, cache);
}
}
- covered_seq_indicies->add (seqIndex);
+ covered_seq_indicies.add (seqIndex);
if (has_pos_glyphs) {
- c->push_cur_active_glyphs () = pos_glyphs;
+ c->push_cur_active_glyphs () = std::move (pos_glyphs);
} else {
c->push_cur_active_glyphs ().set (*c->glyphs);
}
@@ -1370,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>
@@ -1427,9 +1659,28 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
if (unlikely (buffer->max_ops <= 0))
break;
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ if (buffer->have_output)
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "recursing to lookup %u at %u",
+ (unsigned) lookupRecord[i].lookupListIndex,
+ buffer->idx);
+ }
+
if (!c->recurse (lookupRecord[i].lookupListIndex))
continue;
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ if (buffer->have_output)
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "recursed to lookup %u",
+ (unsigned) lookupRecord[i].lookupListIndex);
+ }
+
unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
int delta = new_len - orig_len;
@@ -1516,6 +1767,8 @@ struct ContextClosureLookupContext
ContextClosureFuncs funcs;
ContextFormat context_format;
const void *intersects_data;
+ void *intersects_cache;
+ void *intersected_glyphs_cache;
};
struct ContextCollectGlyphsLookupContext
@@ -1530,19 +1783,23 @@ struct ContextApplyLookupContext
const void *match_data;
};
+template <typename HBUINT>
static inline bool context_intersects (const hb_set_t *glyphs,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
ContextClosureLookupContext &lookup_context)
{
return array_is_subset_of (glyphs,
inputCount ? inputCount - 1 : 0, input,
- lookup_context.funcs.intersects, lookup_context.intersects_data);
+ lookup_context.funcs.intersects,
+ lookup_context.intersects_data,
+ lookup_context.intersects_cache);
}
+template <typename HBUINT>
static inline void context_closure_lookup (hb_closure_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */
@@ -1557,12 +1814,14 @@ static inline void context_closure_lookup (hb_closure_context_t *c,
value,
lookup_context.context_format,
lookup_context.intersects_data,
- lookup_context.funcs.intersected_glyphs);
+ lookup_context.funcs.intersected_glyphs,
+ lookup_context.intersected_glyphs_cache);
}
+template <typename HBUINT>
static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ContextCollectGlyphsLookupContext &lookup_context)
@@ -1574,23 +1833,26 @@ static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c
lookupCount, lookupRecord);
}
+template <typename HBUINT>
static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount HB_UNUSED,
const LookupRecord lookupRecord[] HB_UNUSED,
- ContextApplyLookupContext &lookup_context)
+ const ContextApplyLookupContext &lookup_context)
{
return would_match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data);
}
+
+template <typename HBUINT>
static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
- ContextApplyLookupContext &lookup_context)
+ const ContextApplyLookupContext &lookup_context)
{
unsigned match_end = 0;
unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
@@ -1613,6 +1875,7 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
}
}
+template <typename Types>
struct Rule
{
bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
@@ -1626,8 +1889,8 @@ struct Rule
{
if (unlikely (c->lookup_limit_exceeded ())) return;
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
context_closure_lookup (c,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
@@ -1640,16 +1903,16 @@ struct Rule
if (unlikely (c->lookup_limit_exceeded ())) return;
if (!intersects (c->glyphs, lookup_context)) return;
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
recurse_lookups (c, lookupCount, lookupRecord.arrayZ);
}
void collect_glyphs (hb_collect_glyphs_context_t *c,
ContextCollectGlyphsLookupContext &lookup_context) const
{
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
context_collect_glyphs_lookup (c,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
@@ -1657,10 +1920,10 @@ struct Rule
}
bool would_apply (hb_would_apply_context_t *c,
- ContextApplyLookupContext &lookup_context) const
+ const ContextApplyLookupContext &lookup_context) const
{
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
return context_would_apply_lookup (c,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
@@ -1668,11 +1931,11 @@ struct Rule
}
bool apply (hb_ot_apply_context_t *c,
- ContextApplyLookupContext &lookup_context) const
+ const ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
}
@@ -1685,7 +1948,7 @@ struct Rule
if (unlikely (!c->extend_min (out))) return_trace (false);
out->inputCount = inputCount;
- const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
+ const auto input = inputZ.as_array (inputCount - 1);
for (const auto org : input)
{
HBUINT16 d;
@@ -1693,8 +1956,8 @@ struct Rule
c->copy (d);
}
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (lookupCount), lookup_map);
return_trace (c->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
@@ -1706,7 +1969,7 @@ struct Rule
{
TRACE_SUBSET (this);
if (unlikely (!inputCount)) return_trace (false);
- const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
+ const auto input = inputZ.as_array (inputCount - 1);
const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map;
if (!hb_all (input, mapping)) return_trace (false);
@@ -1729,7 +1992,7 @@ struct Rule
* glyph sequence--includes the first
* glyph */
HBUINT16 lookupCount; /* Number of LookupRecords */
- UnsizedArrayOf<HBUINT16>
+ UnsizedArrayOf<typename Types::HBUINT>
inputZ; /* Array of match inputs--start with
* second glyph */
/*UnsizedArrayOf<LookupRecord>
@@ -1739,8 +2002,11 @@ struct Rule
DEFINE_SIZE_ARRAY (4, inputZ);
};
+template <typename Types>
struct RuleSet
{
+ using Rule = OT::Rule<Types>;
+
bool intersects (const hb_set_t *glyphs,
ContextClosureLookupContext &lookup_context) const
{
@@ -1785,7 +2051,7 @@ struct RuleSet
}
bool would_apply (hb_would_apply_context_t *c,
- ContextApplyLookupContext &lookup_context) const
+ const ContextApplyLookupContext &lookup_context) const
{
return
+ hb_iter (rule)
@@ -1796,7 +2062,7 @@ struct RuleSet
}
bool apply (hb_ot_apply_context_t *c,
- ContextApplyLookupContext &lookup_context) const
+ const ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
return_trace (
@@ -1853,8 +2119,11 @@ struct RuleSet
};
-struct ContextFormat1
+template <typename Types>
+struct ContextFormat1_4
{
+ using RuleSet = OT::RuleSet<Types>;
+
bool intersects (const hb_set_t *glyphs) const
{
struct ContextClosureLookupContext lookup_context = {
@@ -1878,9 +2147,8 @@ struct ContextFormat1
void closure (hb_closure_context_t *c) const
{
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
- cur_active_glyphs);
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs);
struct ContextClosureLookupContext lookup_context = {
{intersects_glyph, intersected_glyph},
@@ -1902,7 +2170,7 @@ struct ContextFormat1
void closure_lookups (hb_closure_lookups_context_t *c) const
{
struct ContextClosureLookupContext lookup_context = {
- {intersects_glyph, intersected_glyph},
+ {intersects_glyph, nullptr},
ContextFormat::SimpleContext,
nullptr
};
@@ -1969,7 +2237,7 @@ struct ContextFormat1
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)
@@ -1991,19 +2259,22 @@ struct ContextFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Array16OfOffset16To<RuleSet>
+ Array16Of<typename Types::template OffsetTo<RuleSet>>
ruleSet; /* Array of RuleSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, ruleSet);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
};
-struct ContextFormat2
+template <typename Types>
+struct ContextFormat2_5
{
+ using RuleSet = OT::RuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
if (!(this+coverage).intersects (glyphs))
@@ -2011,14 +2282,16 @@ struct ContextFormat2
const ClassDef &class_def = this+classDef;
+ hb_map_t cache;
struct ContextClosureLookupContext lookup_context = {
- {intersects_class, intersected_class_glyphs},
+ {intersects_class, nullptr},
ContextFormat::ClassBasedContext,
- &class_def
+ &class_def,
+ &cache
};
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -2044,23 +2317,27 @@ struct ContextFormat2
if (!(this+coverage).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
const ClassDef &class_def = this+classDef;
+ hb_map_t cache;
+ intersected_class_cache_t intersected_cache;
struct ContextClosureLookupContext lookup_context = {
{intersects_class, intersected_class_glyphs},
ContextFormat::ClassBasedContext,
- &class_def
+ &class_def,
+ &cache,
+ &intersected_cache
};
+ hb_enumerate (ruleSet)
| hb_filter ([&] (unsigned _)
{ return class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
- | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<RuleSet>&> _)
+ | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<RuleSet>&> _)
{
const RuleSet& rule_set = this+_.second;
rule_set.closure (c, _.first, lookup_context);
@@ -2077,10 +2354,12 @@ struct ContextFormat2
const ClassDef &class_def = this+classDef;
+ hb_map_t cache;
struct ContextClosureLookupContext lookup_context = {
- {intersects_class, intersected_class_glyphs},
+ {intersects_class, nullptr},
ContextFormat::ClassBasedContext,
- &class_def
+ &class_def,
+ &cache
};
+ hb_iter (ruleSet)
@@ -2125,19 +2404,54 @@ struct ContextFormat2
const Coverage &get_coverage () const { return this+coverage; }
- bool apply (hb_ot_apply_context_t *c) const
+ unsigned cache_cost () const
+ {
+ unsigned c = (this+classDef).cost () * ruleSet.len;
+ return c >= 4 ? c : 0;
+ }
+ bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+ {
+ if (enter)
+ {
+ if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+ return false;
+ auto &info = c->buffer->info;
+ unsigned count = c->buffer->len;
+ for (unsigned i = 0; i < count; i++)
+ info[i].syllable() = 255;
+ c->new_syllables = 255;
+ return true;
+ }
+ else
+ {
+ c->new_syllables = (unsigned) -1;
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+ return true;
+ }
+ }
+
+ bool apply (hb_ot_apply_context_t *c, bool cached = false) const
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
const ClassDef &class_def = this+classDef;
- index = class_def.get_class (c->buffer->cur().codepoint);
- const RuleSet &rule_set = this+ruleSet[index];
+
struct ContextApplyLookupContext lookup_context = {
- {match_class},
+ {cached ? match_class_cached : match_class},
&class_def
};
+
+ if (cached && c->buffer->cur().syllable() < 255)
+ index = c->buffer->cur().syllable ();
+ else
+ {
+ index = class_def.get_class (c->buffer->cur().codepoint);
+ if (cached && index < 255)
+ c->buffer->cur().syllable() = index;
+ }
+ const RuleSet &rule_set = this+ruleSet[index];
return_trace (rule_set.apply (c, lookup_context));
}
@@ -2155,14 +2469,15 @@ struct ContextFormat2
const hb_set_t* glyphset = c->plan->glyphset_gsub ();
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
(this+classDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
- const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+ 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();
for (const auto& _ : + hb_enumerate (ruleSet)
| hb_filter (klass_map, hb_first))
{
@@ -2174,8 +2489,10 @@ struct ContextFormat2
}
if (coverage_glyph_classes.has (_.first) &&
- o->serialize_subset (c, _.second, this, lookup_map, &klass_map))
+ o->serialize_subset (c, _.second, this, lookup_map, &klass_map)) {
non_zero_index = index;
+ snapshot = c->serializer->snapshot();
+ }
index++;
}
@@ -2189,6 +2506,7 @@ struct ContextFormat2
out->ruleSet.pop ();
index--;
}
+ c->serializer->revert (snapshot);
return_trace (bool (out->ruleSet));
}
@@ -2201,29 +2519,31 @@ struct ContextFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
classDef; /* Offset to glyph ClassDef table--from
* beginning of table */
- Array16OfOffset16To<RuleSet>
+ Array16Of<typename Types::template OffsetTo<RuleSet>>
ruleSet; /* Array of RuleSet tables
* ordered by class */
public:
- DEFINE_SIZE_ARRAY (8, ruleSet);
+ DEFINE_SIZE_ARRAY (4 + 2 * Types::size, ruleSet);
};
struct ContextFormat3
{
+ using RuleSet = OT::RuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
if (!(this+coverageZ[0]).intersects (glyphs))
return false;
struct ContextClosureLookupContext lookup_context = {
- {intersects_coverage, intersected_coverage_glyphs},
+ {intersects_coverage, nullptr},
ContextFormat::CoverageBasedContext,
this
};
@@ -2240,8 +2560,8 @@ struct ContextFormat3
if (!(this+coverageZ[0]).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
@@ -2333,8 +2653,8 @@ struct ContextFormat3
if (!o->serialize_subset (c, offset, this)) return_trace (false);
}
- const UnsizedArrayOf<LookupRecord>& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount));
- const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+ 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;
unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (lookupCount), lookup_map);
@@ -2374,22 +2694,30 @@ 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)...));
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BEYOND_64K
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- HBUINT16 format; /* Format identifier */
- ContextFormat1 format1;
- ContextFormat2 format2;
- ContextFormat3 format3;
+ HBUINT16 format; /* Format identifier */
+ ContextFormat1_4<SmallTypes> format1;
+ ContextFormat2_5<SmallTypes> format2;
+ ContextFormat3 format3;
+#ifndef HB_NO_BEYOND_64K
+ ContextFormat1_4<MediumTypes> format4;
+ ContextFormat2_5<MediumTypes> format5;
+#endif
} u;
};
@@ -2401,6 +2729,8 @@ struct ChainContextClosureLookupContext
ContextClosureFuncs funcs;
ContextFormat context_format;
const void *intersects_data[3];
+ void *intersects_cache[3];
+ void *intersected_glyphs_cache;
};
struct ChainContextCollectGlyphsLookupContext
@@ -2411,37 +2741,45 @@ struct ChainContextCollectGlyphsLookupContext
struct ChainContextApplyLookupContext
{
- ContextApplyFuncs funcs;
+ ChainContextApplyFuncs funcs;
const void *match_data[3];
};
+template <typename HBUINT>
static inline bool chain_context_intersects (const hb_set_t *glyphs,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
ChainContextClosureLookupContext &lookup_context)
{
return array_is_subset_of (glyphs,
backtrackCount, backtrack,
- lookup_context.funcs.intersects, lookup_context.intersects_data[0])
+ lookup_context.funcs.intersects,
+ lookup_context.intersects_data[0],
+ lookup_context.intersects_cache[0])
&& array_is_subset_of (glyphs,
inputCount ? inputCount - 1 : 0, input,
- lookup_context.funcs.intersects, lookup_context.intersects_data[1])
+ lookup_context.funcs.intersects,
+ lookup_context.intersects_data[1],
+ lookup_context.intersects_cache[1])
&& array_is_subset_of (glyphs,
lookaheadCount, lookahead,
- lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
+ lookup_context.funcs.intersects,
+ lookup_context.intersects_data[2],
+ lookup_context.intersects_cache[2]);
}
+template <typename HBUINT>
static inline void chain_context_closure_lookup (hb_closure_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
unsigned value,
@@ -2458,16 +2796,18 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c,
value,
lookup_context.context_format,
lookup_context.intersects_data[1],
- lookup_context.funcs.intersected_glyphs);
+ lookup_context.funcs.intersected_glyphs,
+ lookup_context.intersected_glyphs_cache);
}
+template <typename HBUINT>
static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ChainContextCollectGlyphsLookupContext &lookup_context)
@@ -2485,44 +2825,46 @@ static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_contex
lookupCount, lookupRecord);
}
+template <typename HBUINT>
static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[] HB_UNUSED,
+ const HBUINT backtrack[] HB_UNUSED,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[] HB_UNUSED,
+ const HBUINT lookahead[] HB_UNUSED,
unsigned int lookupCount HB_UNUSED,
const LookupRecord lookupRecord[] HB_UNUSED,
- ChainContextApplyLookupContext &lookup_context)
+ const ChainContextApplyLookupContext &lookup_context)
{
return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
&& would_match_input (c,
inputCount, input,
- lookup_context.funcs.match, lookup_context.match_data[1]);
+ lookup_context.funcs.match[1], lookup_context.match_data[1]);
}
+template <typename HBUINT>
static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
- ChainContextApplyLookupContext &lookup_context)
+ const ChainContextApplyLookupContext &lookup_context)
{
unsigned end_index = c->buffer->idx;
unsigned match_end = 0;
unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
if (!(match_input (c,
inputCount, input,
- lookup_context.funcs.match, lookup_context.match_data[1],
+ lookup_context.funcs.match[1], lookup_context.match_data[1],
&match_end, match_positions) && (end_index = match_end)
&& match_lookahead (c,
lookaheadCount, lookahead,
- lookup_context.funcs.match, lookup_context.match_data[2],
+ lookup_context.funcs.match[2], lookup_context.match_data[2],
match_end, &end_index)))
{
c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
@@ -2532,7 +2874,7 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
unsigned start_index = c->buffer->out_len;
if (!match_backtrack (c,
backtrackCount, backtrack,
- lookup_context.funcs.match, lookup_context.match_data[0],
+ lookup_context.funcs.match[0], lookup_context.match_data[0],
&start_index))
{
c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
@@ -2547,12 +2889,13 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
return true;
}
+template <typename Types>
struct ChainRule
{
bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
{
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
return chain_context_intersects (glyphs,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2565,9 +2908,9 @@ struct ChainRule
{
if (unlikely (c->lookup_limit_exceeded ())) return;
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
chain_context_closure_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2583,18 +2926,18 @@ struct ChainRule
if (unlikely (c->lookup_limit_exceeded ())) return;
if (!intersects (c->glyphs, lookup_context)) return;
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
recurse_lookups (c, lookup.len, lookup.arrayZ);
}
void collect_glyphs (hb_collect_glyphs_context_t *c,
ChainContextCollectGlyphsLookupContext &lookup_context) const
{
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
chain_context_collect_glyphs_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2604,11 +2947,11 @@ struct ChainRule
}
bool would_apply (hb_would_apply_context_t *c,
- ChainContextApplyLookupContext &lookup_context) const
+ const ChainContextApplyLookupContext &lookup_context) const
{
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return chain_context_would_apply_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2616,12 +2959,13 @@ struct ChainRule
lookup.arrayZ, lookup_context);
}
- bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+ bool apply (hb_ot_apply_context_t *c,
+ const ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return_trace (chain_context_apply_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2654,22 +2998,22 @@ struct ChainRule
serialize_array (c, backtrack.len, + backtrack.iter ()
| hb_map (mapping));
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (input_map) mapping = input_map;
serialize_array (c, input.lenP1, + input.iter ()
| hb_map (mapping));
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (lookahead_map) mapping = lookahead_map;
serialize_array (c, lookahead.len, + lookahead.iter ()
| hb_map (mapping));
- const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
- HBUINT16* lookupCount = c->embed (&(lookupRecord.len));
+ HBUINT16* lookupCount = c->embed (&(lookup.len));
if (!lookupCount) return_trace (false);
- unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (), lookup_map);
+ unsigned count = serialize_lookuprecord_array (c, lookup.as_array (), lookup_map);
return_trace (c->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
@@ -2681,8 +3025,8 @@ struct ChainRule
{
TRACE_SUBSET (this);
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!backtrack_map)
{
@@ -2711,23 +3055,23 @@ struct ChainRule
{
TRACE_SANITIZE (this);
if (!backtrack.sanitize (c)) return_trace (false);
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!input.sanitize (c)) return_trace (false);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!lookahead.sanitize (c)) return_trace (false);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return_trace (lookup.sanitize (c));
}
protected:
- Array16Of<HBUINT16>
+ Array16Of<typename Types::HBUINT>
backtrack; /* Array of backtracking values
* (to be matched before the input
* sequence) */
- HeadlessArrayOf<HBUINT16>
+ HeadlessArrayOf<typename Types::HBUINT>
inputX; /* Array of input values (start with
* second glyph) */
- Array16Of<HBUINT16>
+ Array16Of<typename Types::HBUINT>
lookaheadX; /* Array of lookahead values's (to be
* matched after the input sequence) */
Array16Of<LookupRecord>
@@ -2737,8 +3081,11 @@ struct ChainRule
DEFINE_SIZE_MIN (8);
};
+template <typename Types>
struct ChainRuleSet
{
+ using ChainRule = OT::ChainRule<Types>;
+
bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
{
return
@@ -2779,7 +3126,8 @@ struct ChainRuleSet
;
}
- bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+ bool would_apply (hb_would_apply_context_t *c,
+ const ChainContextApplyLookupContext &lookup_context) const
{
return
+ hb_iter (rule)
@@ -2789,7 +3137,8 @@ struct ChainRuleSet
;
}
- bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+ bool apply (hb_ot_apply_context_t *c,
+ const ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
return_trace (
@@ -2851,8 +3200,11 @@ struct ChainRuleSet
DEFINE_SIZE_ARRAY (2, rule);
};
-struct ChainContextFormat1
+template <typename Types>
+struct ChainContextFormat1_4
{
+ using ChainRuleSet = OT::ChainRuleSet<Types>;
+
bool intersects (const hb_set_t *glyphs) const
{
struct ChainContextClosureLookupContext lookup_context = {
@@ -2876,8 +3228,8 @@ struct ChainContextFormat1
void closure (hb_closure_context_t *c) const
{
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
struct ChainContextClosureLookupContext lookup_context = {
@@ -2900,7 +3252,7 @@ struct ChainContextFormat1
void closure_lookups (hb_closure_lookups_context_t *c) const
{
struct ChainContextClosureLookupContext lookup_context = {
- {intersects_glyph, intersected_glyph},
+ {intersects_glyph, nullptr},
ContextFormat::SimpleContext,
{nullptr, nullptr, nullptr}
};
@@ -2934,7 +3286,7 @@ struct ChainContextFormat1
{
const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
struct ChainContextApplyLookupContext lookup_context = {
- {match_glyph},
+ {{match_glyph, match_glyph, match_glyph}},
{nullptr, nullptr, nullptr}
};
return rule_set.would_apply (c, lookup_context);
@@ -2950,7 +3302,7 @@ struct ChainContextFormat1
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextApplyLookupContext lookup_context = {
- {match_glyph},
+ {{match_glyph, match_glyph, match_glyph}},
{nullptr, nullptr, nullptr}
};
return_trace (rule_set.apply (c, lookup_context));
@@ -2966,7 +3318,7 @@ struct ChainContextFormat1
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)
@@ -2988,18 +3340,21 @@ struct ChainContextFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Array16OfOffset16To<ChainRuleSet>
+ Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
ruleSet; /* Array of ChainRuleSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, ruleSet);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
};
-struct ChainContextFormat2
+template <typename Types>
+struct ChainContextFormat2_5
{
+ using ChainRuleSet = OT::ChainRuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
if (!(this+coverage).intersects (glyphs))
@@ -3009,16 +3364,18 @@ struct ChainContextFormat2
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+ hb_map_t caches[3] = {};
struct ChainContextClosureLookupContext lookup_context = {
- {intersects_class, intersected_class_glyphs},
+ {intersects_class, nullptr},
ContextFormat::ClassBasedContext,
{&backtrack_class_def,
&input_class_def,
- &lookahead_class_def}
+ &lookahead_class_def},
+ {&caches[0], &caches[1], &caches[2]}
};
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
input_class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -3043,8 +3400,8 @@ struct ChainContextFormat2
if (!(this+coverage).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
@@ -3052,19 +3409,23 @@ struct ChainContextFormat2
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+ hb_map_t caches[3] = {};
+ intersected_class_cache_t intersected_cache;
struct ChainContextClosureLookupContext lookup_context = {
{intersects_class, intersected_class_glyphs},
ContextFormat::ClassBasedContext,
{&backtrack_class_def,
&input_class_def,
- &lookahead_class_def}
+ &lookahead_class_def},
+ {&caches[0], &caches[1], &caches[2]},
+ &intersected_cache
};
+ hb_enumerate (ruleSet)
| hb_filter ([&] (unsigned _)
{ return input_class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
- | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<ChainRuleSet>&> _)
+ | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<ChainRuleSet>&> _)
{
const ChainRuleSet& chainrule_set = this+_.second;
chainrule_set.closure (c, _.first, lookup_context);
@@ -3083,12 +3444,14 @@ struct ChainContextFormat2
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+ hb_map_t caches[3] = {};
struct ChainContextClosureLookupContext lookup_context = {
- {intersects_class, intersected_class_glyphs},
+ {intersects_class, nullptr},
ContextFormat::ClassBasedContext,
{&backtrack_class_def,
&input_class_def,
- &lookahead_class_def}
+ &lookahead_class_def},
+ {&caches[0], &caches[1], &caches[2]}
};
+ hb_iter (ruleSet)
@@ -3134,7 +3497,7 @@ struct ChainContextFormat2
unsigned int index = input_class_def.get_class (c->glyphs[0]);
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextApplyLookupContext lookup_context = {
- {match_class},
+ {{match_class, match_class, match_class}},
{&backtrack_class_def,
&input_class_def,
&lookahead_class_def}
@@ -3144,7 +3507,33 @@ struct ChainContextFormat2
const Coverage &get_coverage () const { return this+coverage; }
- bool apply (hb_ot_apply_context_t *c) const
+ unsigned cache_cost () const
+ {
+ unsigned c = (this+lookaheadClassDef).cost () * ruleSet.len;
+ return c >= 4 ? c : 0;
+ }
+ bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+ {
+ if (enter)
+ {
+ if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+ return false;
+ auto &info = c->buffer->info;
+ unsigned count = c->buffer->len;
+ for (unsigned i = 0; i < count; i++)
+ info[i].syllable() = 255;
+ c->new_syllables = 255;
+ return true;
+ }
+ else
+ {
+ c->new_syllables = (unsigned) -1;
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+ return true;
+ }
+ }
+
+ bool apply (hb_ot_apply_context_t *c, bool cached = false) const
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@@ -3154,14 +3543,27 @@ struct ChainContextFormat2
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
- index = input_class_def.get_class (c->buffer->cur().codepoint);
- const ChainRuleSet &rule_set = this+ruleSet[index];
+ /* For ChainContextFormat2_5 we cache the LookaheadClassDef instead of InputClassDef.
+ * The reason is that most heavy fonts want to identify a glyph in context and apply
+ * a lookup to it. In this scenario, the length of the input sequence is one, whereas
+ * the lookahead / backtrack are typically longer. The one glyph in input sequence is
+ * looked-up below and no input glyph is looked up in individual rules, whereas the
+ * lookahead and backtrack glyphs are tried. Since we match lookahead before backtrack,
+ * we should cache lookahead. This decisions showed a 20% improvement in shaping of
+ * the Gulzar font.
+ */
+
struct ChainContextApplyLookupContext lookup_context = {
- {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,
&input_class_def,
&lookahead_class_def}
};
+
+ index = input_class_def.get_class (c->buffer->cur().codepoint);
+ const ChainRuleSet &rule_set = this+ruleSet[index];
return_trace (rule_set.apply (c, lookup_context));
}
@@ -3189,14 +3591,14 @@ struct ChainContextFormat2
const hb_set_t* glyphset = c->plan->glyphset_gsub ();
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
(this+inputClassDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
int non_zero_index = -1, index = 0;
bool ret = true;
- const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+ 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))
@@ -3244,40 +3646,42 @@ struct ChainContextFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
backtrackClassDef; /* Offset to glyph ClassDef table
* containing backtrack sequence
* data--from beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
inputClassDef; /* Offset to glyph ClassDef
* table containing input sequence
* data--from beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
lookaheadClassDef; /* Offset to glyph ClassDef table
* containing lookahead sequence
* data--from beginning of table */
- Array16OfOffset16To<ChainRuleSet>
+ Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
ruleSet; /* Array of ChainRuleSet tables
* ordered by class */
public:
- DEFINE_SIZE_ARRAY (12, ruleSet);
+ DEFINE_SIZE_ARRAY (4 + 4 * Types::size, ruleSet);
};
struct ChainContextFormat3
{
+ using RuleSet = OT::RuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!(this+input[0]).intersects (glyphs))
return false;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
struct ChainContextClosureLookupContext lookup_context = {
- {intersects_coverage, intersected_coverage_glyphs},
+ {intersects_coverage, nullptr},
ContextFormat::CoverageBasedContext,
{this, this, this}
};
@@ -3293,18 +3697,18 @@ struct ChainContextFormat3
void closure (hb_closure_context_t *c) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!(this+input[0]).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
struct ChainContextClosureLookupContext lookup_context = {
{intersects_coverage, intersected_coverage_glyphs},
ContextFormat::CoverageBasedContext,
@@ -3325,9 +3729,9 @@ struct ChainContextFormat3
if (!intersects (c->glyphs))
return;
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
recurse_lookups (c, lookup.len, lookup.arrayZ);
}
@@ -3335,12 +3739,13 @@ struct ChainContextFormat3
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
(this+input[0]).collect_coverage (c->input);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
+
struct ChainContextCollectGlyphsLookupContext lookup_context = {
{collect_coverage},
{this, this, this}
@@ -3355,11 +3760,11 @@ struct ChainContextFormat3
bool would_apply (hb_would_apply_context_t *c) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
struct ChainContextApplyLookupContext lookup_context = {
- {match_coverage},
+ {{match_coverage, match_coverage, match_coverage}},
{this, this, this}
};
return chain_context_would_apply_lookup (c,
@@ -3371,22 +3776,22 @@ struct ChainContextFormat3
const Coverage &get_coverage () const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
return this+input[0];
}
bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
struct ChainContextApplyLookupContext lookup_context = {
- {match_coverage},
+ {{match_coverage, match_coverage, match_coverage}},
{this, this, this}
};
return_trace (chain_context_apply_lookup (c,
@@ -3426,21 +3831,21 @@ struct ChainContextFormat3
if (!serialize_coverage_offsets (c, backtrack.iter (), this))
return_trace (false);
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!serialize_coverage_offsets (c, input.iter (), this))
return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!serialize_coverage_offsets (c, lookahead.iter (), this))
return_trace (false);
- const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
- const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+ 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;
- HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookupRecord.len);
+ HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookup.len);
if (!lookupCount) return_trace (false);
- unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (), lookup_map);
+ unsigned count = serialize_lookuprecord_array (c->serializer, lookup.as_array (), lookup_map);
return_trace (c->serializer->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
@@ -3448,12 +3853,12 @@ struct ChainContextFormat3
{
TRACE_SANITIZE (this);
if (!backtrack.sanitize (c, this)) return_trace (false);
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!input.sanitize (c, this)) return_trace (false);
if (!input.len) return_trace (false); /* To be consistent with Context. */
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!lookahead.sanitize (c, this)) return_trace (false);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return_trace (lookup.sanitize (c));
}
@@ -3483,22 +3888,30 @@ 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)...));
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BEYOND_64K
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- HBUINT16 format; /* Format identifier */
- ChainContextFormat1 format1;
- ChainContextFormat2 format2;
- ChainContextFormat3 format3;
+ HBUINT16 format; /* Format identifier */
+ ChainContextFormat1_4<SmallTypes> format1;
+ ChainContextFormat2_5<SmallTypes> format2;
+ ChainContextFormat3 format3;
+#ifndef HB_NO_BEYOND_64K
+ ChainContextFormat1_4<MediumTypes> format4;
+ ChainContextFormat2_5<MediumTypes> format5;
+#endif
} u;
};
@@ -3515,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)...));
}
@@ -3594,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 ());
@@ -3617,66 +4030,316 @@ struct Extension
struct hb_ot_layout_lookup_accelerator_t
{
template <typename TLookup>
- void init (const TLookup &lookup)
- {
- digest.init ();
- lookup.collect_coverage (&digest);
+ static hb_ot_layout_lookup_accelerator_t *create (const TLookup &lookup)
+ {
+ 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);
+
+ thiz->digest.init ();
+ for (auto& subtable : hb_iter (thiz->subtables, count))
+ thiz->digest.add (subtable.digest);
+
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ 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
- subtables.init ();
- OT::hb_get_subtables_context_t c_get_subtables (subtables);
- lookup.dispatch (&c_get_subtables);
+ 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) const
+ bool apply (hb_ot_apply_context_t *c, unsigned subtables_count, bool use_cache) const
{
- for (unsigned int i = 0; i < subtables.length; i++)
- if (subtables[i].apply (c))
- return true;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ if (use_cache)
+ {
+ return
+ + 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
+ ;
+ }
+ else
+#endif
+ {
+ return
+ + hb_iter (hb_iter (subtables, subtables_count))
+ | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply (c); })
+ | hb_any
+ ;
+ }
return false;
}
- private:
+ bool cache_enter (hb_ot_apply_context_t *c) const
+ {
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ return cache_user_idx != (unsigned) -1 &&
+ subtables[cache_user_idx].cache_enter (c);
+#else
+ return false;
+#endif
+ }
+ void cache_leave (hb_ot_apply_context_t *c) const
+ {
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ subtables[cache_user_idx].cache_leave (c);
+#endif
+ }
+
+
hb_set_digest_t digest;
- hb_get_subtables_context_t::array_t subtables;
+ private:
+#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>
+struct GSUBGPOSVersion1_2
+{
+ friend struct GSUBGPOS;
+
+ protected:
+ FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
+ * to 0x00010000u */
+ typename Types:: template OffsetTo<ScriptList>
+ scriptList; /* ScriptList table */
+ typename Types::template OffsetTo<FeatureList>
+ featureList; /* FeatureList table */
+ typename Types::template OffsetTo<LookupList<Types>>
+ lookupList; /* LookupList table */
+ Offset32To<FeatureVariations>
+ featureVars; /* Offset to Feature Variations
+ table--from beginning of table
+ * (may be NULL). Introduced
+ * in version 0x00010001. */
+ public:
+ DEFINE_SIZE_MIN (4 + 3 * Types::size);
+
+ unsigned int get_size () const
+ {
+ return min_size +
+ (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
+ }
+
+ const typename Types::template OffsetTo<LookupList<Types>>* get_lookup_list_offset () const
+ {
+ return &lookupList;
+ }
+
+ template <typename TLookup>
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList;
+ if (unlikely (!(scriptList.sanitize (c, this) &&
+ featureList.sanitize (c, this) &&
+ reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
+ return_trace (false);
+
+#ifndef HB_NO_VAR
+ if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
+ return_trace (false);
+#endif
+
+ return_trace (true);
+ }
+
+ template <typename TLookup>
+ bool subset (hb_subset_layout_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ 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)
+ .serialize_subset (c->subset_context,
+ reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList),
+ this,
+ c);
+
+ reinterpret_cast<typename Types::template OffsetTo<RecordListOfFeature> &> (out->featureList)
+ .serialize_subset (c->subset_context,
+ reinterpret_cast<const typename Types::template OffsetTo<RecordListOfFeature> &> (featureList),
+ this,
+ c);
+
+ out->scriptList.serialize_subset (c->subset_context,
+ scriptList,
+ this,
+ c);
+
+#ifndef HB_NO_VAR
+ if (version.to_int () >= 0x00010001u)
+ {
+ 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;
+ }
+ }
+#endif
+
+ return_trace (true);
+ }
};
struct GSUBGPOS
{
- bool has_data () const { return version.to_int (); }
+ 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;
+ }
+ }
+
+ template <typename TLookup>
+ 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<TLookup> (c));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return_trace (u.version2.sanitize<TLookup> (c));
+#endif
+ default: return_trace (true);
+ }
+ }
+
+ template <typename TLookup>
+ bool subset (hb_subset_layout_context_t *c) const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.subset<TLookup> (c);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.subset<TLookup> (c);
+#endif
+ default: return false;
+ }
+ }
+
+ const ScriptList &get_script_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.scriptList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.scriptList;
+#endif
+ default: return Null (ScriptList);
+ }
+ }
+ const FeatureList &get_feature_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.featureList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.featureList;
+#endif
+ default: return Null (FeatureList);
+ }
+ }
+ unsigned int get_lookup_count () const
+ {
+ switch (u.version.major) {
+ case 1: return (this+u.version1.lookupList).len;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return (this+u.version2.lookupList).len;
+#endif
+ default: return 0;
+ }
+ }
+ const Lookup& get_lookup (unsigned int i) const
+ {
+ switch (u.version.major) {
+ case 1: return (this+u.version1.lookupList)[i];
+#ifndef HB_NO_BEYOND_64K
+ case 2: return (this+u.version2.lookupList)[i];
+#endif
+ default: return Null (Lookup);
+ }
+ }
+ const FeatureVariations &get_feature_variations () const
+ {
+ switch (u.version.major) {
+ case 1: return (u.version.to_int () >= 0x00010001u ? this+u.version1.featureVars : Null (FeatureVariations));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.featureVars;
+#endif
+ default: return Null (FeatureVariations);
+ }
+ }
+
+ bool has_data () const { return u.version.to_int (); }
unsigned int get_script_count () const
- { return (this+scriptList).len; }
+ { return get_script_list ().len; }
const Tag& get_script_tag (unsigned int i) const
- { return (this+scriptList).get_tag (i); }
+ { return get_script_list ().get_tag (i); }
unsigned int get_script_tags (unsigned int start_offset,
unsigned int *script_count /* IN/OUT */,
hb_tag_t *script_tags /* OUT */) const
- { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
+ { return get_script_list ().get_tags (start_offset, script_count, script_tags); }
const Script& get_script (unsigned int i) const
- { return (this+scriptList)[i]; }
+ { return get_script_list ()[i]; }
bool find_script_index (hb_tag_t tag, unsigned int *index) const
- { return (this+scriptList).find_index (tag, index); }
+ { return get_script_list ().find_index (tag, index); }
unsigned int get_feature_count () const
- { return (this+featureList).len; }
+ { return get_feature_list ().len; }
hb_tag_t get_feature_tag (unsigned int i) const
- { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
+ { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : get_feature_list ().get_tag (i); }
unsigned int get_feature_tags (unsigned int start_offset,
unsigned int *feature_count /* IN/OUT */,
hb_tag_t *feature_tags /* OUT */) const
- { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
+ { return get_feature_list ().get_tags (start_offset, feature_count, feature_tags); }
const Feature& get_feature (unsigned int i) const
- { return (this+featureList)[i]; }
+ { return get_feature_list ()[i]; }
bool find_feature_index (hb_tag_t tag, unsigned int *index) const
- { return (this+featureList).find_index (tag, index); }
-
- unsigned int get_lookup_count () const
- { return (this+lookupList).len; }
- const Lookup& get_lookup (unsigned int i) const
- { return (this+lookupList)[i]; }
+ { return get_feature_list ().find_index (tag, index); }
bool find_variations_index (const int *coords, unsigned int num_coords,
unsigned int *index) const
@@ -3685,18 +4348,17 @@ struct GSUBGPOS
*index = FeatureVariations::NOT_FOUND_INDEX;
return false;
#endif
- return (version.to_int () >= 0x00010001u ? this+featureVars : Null (FeatureVariations))
- .find_index (coords, num_coords, index);
+ return get_feature_variations ().find_index (coords, num_coords, index);
}
const Feature& get_feature_variation (unsigned int feature_index,
unsigned int variations_index) const
{
#ifndef HB_NO_VAR
if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
- version.to_int () >= 0x00010001u)
+ u.version.to_int () >= 0x00010001u)
{
- const Feature *feature = (this+featureVars).find_substitute (variations_index,
- feature_index);
+ const Feature *feature = get_feature_variations ().find_substitute (variations_index,
+ feature_index);
if (feature)
return *feature;
}
@@ -3705,23 +4367,30 @@ struct GSUBGPOS
}
void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
+ const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
hb_set_t *lookup_indexes /* OUT */) const
{
#ifndef HB_NO_VAR
- if (version.to_int () >= 0x00010001u)
- (this+featureVars).collect_lookups (feature_indexes, lookup_indexes);
+ get_feature_variations ().collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
#endif
}
+#ifndef HB_NO_VAR
+ void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+ { get_feature_variations ().collect_feature_substitutes_with_variations (c); }
+#endif
+
template <typename TLookup>
void closure_lookups (hb_face_t *face,
const hb_set_t *glyphs,
hb_set_t *lookup_indexes /* IN/OUT */) const
{
hb_set_t visited_lookups, inactive_lookups;
- OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
+ hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
- for (unsigned lookup_index : + hb_iter (lookup_indexes))
+ c.set_recurse_func (TLookup::template dispatch_recurse_func<hb_closure_lookups_context_t>);
+
+ for (unsigned lookup_index : *lookup_indexes)
reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index);
hb_set_union (lookup_indexes, &visited_lookups);
@@ -3729,7 +4398,8 @@ struct GSUBGPOS
}
void prune_langsys (const hb_map_t *duplicate_feature_map,
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map,
+ const hb_set_t *layout_scripts,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map,
hb_set_t *new_feature_indexes /* OUT */) const
{
hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
@@ -3737,124 +4407,16 @@ struct GSUBGPOS
unsigned count = get_script_count ();
for (unsigned script_index = 0; script_index < count; script_index++)
{
+ const Tag& tag = get_script_tag (script_index);
+ if (!layout_scripts->has (tag)) continue;
const Script& s = get_script (script_index);
s.prune_langsys (&c, script_index);
}
}
- template <typename TLookup>
- 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);
-
- typedef LookupOffsetList<TLookup> TLookupList;
- reinterpret_cast<Offset16To<TLookupList> &> (out->lookupList)
- .serialize_subset (c->subset_context,
- reinterpret_cast<const Offset16To<TLookupList> &> (lookupList),
- this,
- c);
-
- reinterpret_cast<Offset16To<RecordListOfFeature> &> (out->featureList)
- .serialize_subset (c->subset_context,
- reinterpret_cast<const Offset16To<RecordListOfFeature> &> (featureList),
- this,
- c);
-
- out->scriptList.serialize_subset (c->subset_context,
- scriptList,
- this,
- c);
-
-#ifndef HB_NO_VAR
- if (version.to_int () >= 0x00010001u)
- {
- bool ret = out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
- if (!ret)
- {
- out->version.major = 1;
- out->version.minor = 0;
- }
- }
-#endif
-
- return_trace (true);
- }
-
- void find_duplicate_features (const hb_map_t *lookup_indices,
- const hb_set_t *feature_indices,
- hb_map_t *duplicate_feature_map /* OUT */) const
- {
- if (feature_indices->is_empty ()) return;
- hb_hashmap_t<hb_tag_t, hb_set_t *> unique_features;
- //find out duplicate features after subset
- for (unsigned i : feature_indices->iter ())
- {
- hb_tag_t t = get_feature_tag (i);
- if (t == HB_MAP_VALUE_INVALID) continue;
- if (!unique_features.has (t))
- {
- hb_set_t* indices = hb_set_create ();
- if (unlikely (indices == hb_set_get_empty () ||
- !unique_features.set (t, indices)))
- {
- hb_set_destroy (indices);
- for (auto _ : unique_features.iter ())
- hb_set_destroy (_.second);
- return;
- }
- if (unique_features.get (t))
- unique_features.get (t)->add (i);
- duplicate_feature_map->set (i, i);
- continue;
- }
-
- bool found = false;
-
- hb_set_t* same_tag_features = unique_features.get (t);
- for (unsigned other_f_index : same_tag_features->iter ())
- {
- const Feature& f = get_feature (i);
- const Feature& other_f = get_feature (other_f_index);
-
- auto f_iter =
- + hb_iter (f.lookupIndex)
- | hb_filter (lookup_indices)
- ;
-
- auto other_f_iter =
- + hb_iter (other_f.lookupIndex)
- | hb_filter (lookup_indices)
- ;
-
- bool is_equal = true;
- for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
- {
- unsigned a = *f_iter;
- unsigned b = *other_f_iter;
- if (a != b) { is_equal = false; break; }
- }
-
- if (is_equal == false || f_iter || other_f_iter) continue;
-
- found = true;
- duplicate_feature_map->set (i, other_f_index);
- break;
- }
-
- if (found == false)
- {
- same_tag_features->add (i);
- duplicate_feature_map->set (i, i);
- }
- }
-
- for (auto _ : unique_features.iter ())
- hb_set_destroy (_.second);
- }
-
void prune_features (const hb_map_t *lookup_indices, /* IN */
+ const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* IN */
+ const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, /* IN */
hb_set_t *feature_indices /* IN/OUT */) const
{
#ifndef HB_NO_VAR
@@ -3862,8 +4424,7 @@ struct GSUBGPOS
// if the FeatureVariation's table and the alternate version(s) intersect the
// set of lookup indices.
hb_set_t alternate_feature_indices;
- if (version.to_int () >= 0x00010001u)
- (this+featureVars).closure_features (lookup_indices, &alternate_feature_indices);
+ get_feature_variations ().closure_features (lookup_indices, feature_record_cond_idx_map, &alternate_feature_indices);
if (unlikely (alternate_feature_indices.in_error()))
{
feature_indices->err ();
@@ -3871,9 +4432,8 @@ struct GSUBGPOS
}
#endif
- for (unsigned i : feature_indices->iter())
+ for (unsigned i : hb_iter (feature_indices))
{
- const Feature& f = get_feature (i);
hb_tag_t tag = get_feature_tag (i);
if (tag == HB_TAG ('p', 'r', 'e', 'f'))
// Note: Never ever drop feature 'pref', even if it's empty.
@@ -3883,11 +4443,16 @@ struct GSUBGPOS
continue;
- if (!f.featureParams.is_null () &&
+ const Feature *f = &(get_feature (i));
+ const Feature** p = nullptr;
+ if (feature_substitutes_map->has (i, &p))
+ f = *p;
+
+ if (!f->featureParams.is_null () &&
tag == HB_TAG ('s', 'i', 'z', 'e'))
continue;
- if (!f.intersects_lookup_indexes (lookup_indices)
+ if (!f->intersects_lookup_indexes (lookup_indices)
#ifndef HB_NO_VAR
&& !alternate_feature_indices.has (i)
#endif
@@ -3896,32 +4461,6 @@ struct GSUBGPOS
}
}
- unsigned int get_size () const
- {
- return min_size +
- (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
- }
-
- template <typename TLookup>
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- typedef List16OfOffset16To<TLookup> TLookupList;
- if (unlikely (!(version.sanitize (c) &&
- likely (version.major == 1) &&
- scriptList.sanitize (c, this) &&
- featureList.sanitize (c, this) &&
- reinterpret_cast<const Offset16To<TLookupList> &> (lookupList).sanitize (c, this))))
- return_trace (false);
-
-#ifndef HB_NO_VAR
- if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
- return_trace (false);
-#endif
-
- return_trace (true);
- }
-
template <typename T>
struct accelerator_t
{
@@ -3936,46 +4475,59 @@ 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:
- FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
- * to 0x00010000u */
- Offset16To<ScriptList>
- scriptList; /* ScriptList table */
- Offset16To<FeatureList>
- featureList; /* FeatureList table */
- Offset16To<LookupList>
- lookupList; /* LookupList table */
- Offset32To<FeatureVariations>
- featureVars; /* Offset to Feature Variations
- table--from beginning of table
- * (may be NULL). Introduced
- * in version 0x00010001. */
+ union {
+ FixedVersion<> version; /* Version identifier */
+ GSUBGPOSVersion1_2<SmallTypes> version1;
+#ifndef HB_NO_BEYOND_64K
+ GSUBGPOSVersion1_2<MediumTypes> version2;
+#endif
+ } u;
public:
- DEFINE_SIZE_MIN (10);
+ DEFINE_SIZE_MIN (4);
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
index f4ea21a4f9..6c4055e046 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
@@ -46,7 +46,7 @@
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
-#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-layout-base-table.hh"
#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
#include "hb-ot-name-table.hh"
#include "hb-ot-os2-table.hh"
@@ -54,7 +54,8 @@
#include "hb-aat-layout-morx-table.hh"
#include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise.
-using OT::Layout::GSUB::GSUB;
+using OT::Layout::GSUB;
+using OT::Layout::GPOS;
/**
* SECTION:hb-ot-layout
@@ -78,7 +79,7 @@ using OT::Layout::GSUB::GSUB;
* Tests whether a face includes any kerning data in the 'kern' table.
* Does NOT test for kerning lookups in the GPOS table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
bool
@@ -94,7 +95,7 @@ hb_ot_layout_has_kerning (hb_face_t *face)
* Tests whether a face includes any state-machine kerning in the 'kern' table.
* Does NOT examine the GPOS table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
bool
@@ -114,7 +115,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face)
*
* Does NOT examine the GPOS table.
*
- * Return value: %true is data found, %false otherwise
+ * Return value: `true` is data found, `false` otherwise
*
**/
bool
@@ -260,7 +261,6 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
{
_hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
_hb_glyph_info_clear_lig_props (&buffer->info[i]);
- buffer->info[i].syllable() = 0;
}
}
@@ -272,7 +272,7 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
*
* Tests whether a face has any glyph classes defined in its GDEF table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
hb_bool_t
@@ -401,7 +401,7 @@ GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
}
bool
-OT::GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
+GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
hb_face_t *face HB_UNUSED) const
{
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
@@ -461,7 +461,7 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face,
* Fetches the index if a given script tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the script is found, %false otherwise
+ * Return value: `true` if the script is found, `false` otherwise
*
**/
hb_bool_t
@@ -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,11 +531,11 @@ 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
+ * `true` if one of the requested scripts is selected, `false` if a fallback
* script is selected or if no scripts are selected.
*
* Since: 2.0.0
@@ -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;
}
@@ -601,9 +601,13 @@ hb_ot_layout_table_select_script (hb_face_t *face,
* @feature_tags: (out) (array length=feature_count): Array of feature tags found in the table
*
* Fetches a list of all feature tags in the given face's GSUB or GPOS table.
+ * Note that there might be duplicate feature tags, belonging to different
+ * script/language-system pairs of the table.
*
* Return value: Total number of feature tags.
*
+ * Since: 0.6.0
+ *
**/
unsigned int
hb_ot_layout_table_get_feature_tags (hb_face_t *face,
@@ -628,7 +632,10 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
* Fetches the index for a given feature tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
+ *
+ * Since: 0.6.0
+ *
**/
bool
hb_ot_layout_table_find_feature (hb_face_t *face,
@@ -668,6 +675,8 @@ hb_ot_layout_table_find_feature (hb_face_t *face,
*
* Return value: Total number of language tags.
*
+ * Since: 0.6.0
+ *
**/
unsigned int
hb_ot_layout_script_get_language_tags (hb_face_t *face,
@@ -695,7 +704,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
* Fetches the index of a given language tag in the specified face's GSUB table
* or GPOS table, underneath the specified script tag.
*
- * Return value: %true if the language tag is found, %false otherwise
+ * Return value: `true` if the language tag is found, `false` otherwise
*
* Since: 0.6.0
* Deprecated: 2.0.0
@@ -718,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.
+ * If none of the given language tags is found, `false` is returned and
+ * @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
+ * 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);
@@ -752,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:
@@ -776,7 +831,9 @@ hb_ot_layout_script_select_language (hb_face_t *face,
* Fetches the index of a requested feature in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
+ *
+ * Since: 0.6.0
*
**/
hb_bool_t
@@ -807,7 +864,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
* Fetches the tag of a requested feature index in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
* Since: 0.9.30
**/
@@ -846,6 +903,9 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face,
* returned will begin at the offset provided.
*
* Return value: Total number of features.
+ *
+ * Since: 0.6.0
+ *
**/
unsigned int
hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
@@ -879,6 +939,9 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
* returned will begin at the offset provided.
*
* Return value: Total number of feature tags.
+ *
+ * Since: 0.6.0
+ *
**/
unsigned int
hb_ot_layout_language_get_feature_tags (hb_face_t *face,
@@ -917,7 +980,9 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face,
* Fetches the index of a given feature tag in the specified face's GSUB table
* or GPOS table, underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
+ *
+ * Since: 0.6.0
*
**/
hb_bool_t
@@ -1167,9 +1232,12 @@ script_collect_features (hb_collect_features_context_t *c,
* hb_ot_layout_collect_features:
* @face: #hb_face_t to work upon
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
- * @scripts: The array of scripts to collect features for
- * @languages: The array of languages to collect features for
- * @features: The array of features to collect
+ * @scripts: (nullable) (array zero-terminated=1): The array of scripts to collect features for,
+ * terminated by %HB_TAG_NONE
+ * @languages: (nullable) (array zero-terminated=1): The array of languages to collect features for,
+ * terminated by %HB_TAG_NONE
+ * @features: (nullable) (array zero-terminated=1): The array of features to collect,
+ * terminated by %HB_TAG_NONE
* @feature_indexes: (out): The array of feature indexes found for the query
*
* Fetches a list of all feature indexes in the specified face's GSUB table
@@ -1216,9 +1284,12 @@ hb_ot_layout_collect_features (hb_face_t *face,
* hb_ot_layout_collect_lookups:
* @face: #hb_face_t to work upon
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
- * @scripts: The array of scripts to collect lookups for
- * @languages: The array of languages to collect lookups for
- * @features: The array of features to collect lookups for
+ * @scripts: (nullable) (array zero-terminated=1): The array of scripts to collect lookups for,
+ * terminated by %HB_TAG_NONE
+ * @languages: (nullable) (array zero-terminated=1): The array of languages to collect lookups for,
+ * terminated by %HB_TAG_NONE
+ * @features: (nullable) (array zero-terminated=1): The array of features to collect lookups for,
+ * terminated by %HB_TAG_NONE
* @lookup_indexes: (out): The array of lookup indexes found for the query
*
* Fetches a list of all feature-lookup indexes in the specified face's GSUB
@@ -1246,7 +1317,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
hb_set_next (&feature_indexes, &feature_index);)
g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
- g.feature_variation_collect_lookups (&feature_indexes, lookup_indexes);
+ g.feature_variation_collect_lookups (&feature_indexes, nullptr, lookup_indexes);
}
@@ -1314,7 +1385,9 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
* Fetches a list of feature variations in the specified face's GSUB table
* or GPOS table, at the specified variation coordinates.
*
- * Return value: %true if feature variations were found, %false otherwise.
+ * Return value: `true` if feature variations were found, `false` otherwise.
+ *
+ * Since: 1.4.0
*
**/
hb_bool_t
@@ -1347,6 +1420,8 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face,
*
* Return value: Total number of lookups.
*
+ * Since: 1.4.0
+ *
**/
unsigned int
hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
@@ -1377,7 +1452,9 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
*
* Tests whether the specified face includes any GSUB substitutions.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
+ *
+ * Since: 0.6.0
*
**/
hb_bool_t
@@ -1399,7 +1476,7 @@ hb_ot_layout_has_substitution (hb_face_t *face)
* Tests whether a specified lookup in the specified face would
* trigger a substitution on the given glyph sequence.
*
- * Return value: %true if a substitution would be triggered, %false otherwise
+ * Return value: `true` if a substitution would be triggered, `false` otherwise
*
* Since: 0.9.7
**/
@@ -1410,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);
}
@@ -1434,56 +1513,6 @@ hb_ot_layout_substitute_start (hb_font_t *font,
_hb_ot_layout_set_glyph_props (font, buffer);
}
-void
-hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
- bool (*filter) (const hb_glyph_info_t *info))
-{
- /* Merge clusters and delete filtered glyphs.
- * NOTE! We can't use out-buffer as we have positioning data. */
- unsigned int j = 0;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- hb_glyph_position_t *pos = buffer->pos;
- for (unsigned int i = 0; i < count; i++)
- {
- if (filter (&info[i]))
- {
- /* Merge clusters.
- * Same logic as buffer->delete_glyph(), but for in-place removal. */
-
- unsigned int cluster = info[i].cluster;
- if (i + 1 < count && cluster == info[i + 1].cluster)
- continue; /* Cluster survives; do nothing. */
-
- if (j)
- {
- /* Merge cluster backward. */
- if (cluster < info[j - 1].cluster)
- {
- unsigned int mask = info[i].mask;
- unsigned int old_cluster = info[j - 1].cluster;
- for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
- buffer->set_cluster (info[k - 1], cluster, mask);
- }
- continue;
- }
-
- if (i + 1 < count)
- buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
-
- continue;
- }
-
- if (j != i)
- {
- info[j] = info[i];
- pos[j] = pos[i];
- }
- j++;
- }
- buffer->len = j;
-}
-
/**
* hb_ot_layout_lookup_substitute_closure:
* @face: #hb_face_t to work upon
@@ -1501,15 +1530,12 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
l.closure (&c, lookup_index);
-
- for (auto _ : done_lookups_glyph_set.iter ())
- hb_set_destroy (_.second);
}
/**
@@ -1529,7 +1555,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const GSUB& gsub = *face->table.GSUB->table;
@@ -1551,13 +1577,10 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
}
} while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
glyphs_length != glyphs->get_population ());
-
- for (auto _ : done_lookups_glyph_set.iter ())
- hb_set_destroy (_.second);
}
/*
- * OT::GPOS
+ * GPOS
*/
@@ -1567,7 +1590,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
*
* Tests whether the specified face includes any GPOS positioning.
*
- * Return value: %true if the face has GPOS data, %false otherwise
+ * Return value: `true` if the face has GPOS data, `false` otherwise
*
**/
hb_bool_t
@@ -1588,7 +1611,7 @@ hb_ot_layout_has_positioning (hb_face_t *face)
void
hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_start (font, buffer);
+ GPOS::position_start (font, buffer);
}
@@ -1603,7 +1626,7 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
void
hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_finish_advances (font, buffer);
+ GPOS::position_finish_advances (font, buffer);
}
/**
@@ -1617,7 +1640,7 @@ hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
void
hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_finish_offsets (font, buffer);
+ GPOS::position_finish_offsets (font, buffer);
}
@@ -1640,7 +1663,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
* For more information on this distinction, see the [`size` feature documentation](
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size).
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.10
**/
@@ -1652,7 +1675,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *range_start, /* OUT. May be NULL */
unsigned int *range_end /* OUT. May be NULL */)
{
- const OT::GPOS &gpos = *face->table.GPOS->table;
+ const GPOS &gpos = *face->table.GPOS->table;
const hb_tag_t tag = HB_TAG ('s','i','z','e');
unsigned int num_features = gpos.get_feature_count ();
@@ -1684,6 +1707,8 @@ hb_ot_layout_get_size_params (hb_face_t *face,
return false;
}
+
+
/**
* hb_ot_layout_feature_get_name_ids:
* @face: #hb_face_t to work upon
@@ -1704,7 +1729,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
* Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
* "Character Variant" ('cvXX') features.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.0.0
**/
@@ -1803,46 +1828,45 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
struct GSUBProxy
{
static constexpr unsigned table_index = 0u;
- static constexpr bool inplace = false;
+ static constexpr bool always_inplace = false;
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
{
static constexpr unsigned table_index = 1u;
- static constexpr bool inplace = true;
+ static constexpr bool always_inplace = true;
typedef OT::PosLookup Lookup;
GPOSProxy (hb_face_t *face) :
- table (*face->table.GPOS->table),
- accels (face->table.GPOS->accels) {}
+ accel (*face->table.GPOS) {}
- const OT::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);
+
bool ret = false;
hb_buffer_t *buffer = c->buffer;
while (buffer->idx < buffer->len && buffer->successful)
{
bool applied = false;
- if (accel.may_have (buffer->cur().codepoint) &&
+ if (accel.digest.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
- applied = accel.apply (c);
+ applied = accel.apply (c, subtable_count, use_cache);
}
if (applied)
@@ -1850,21 +1874,26 @@ apply_forward (OT::hb_ot_apply_context_t *c,
else
(void) buffer->next_glyph ();
}
+
+ if (use_cache)
+ accel.cache_leave (c);
+
return ret;
}
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;
do
{
- if (accel.may_have (buffer->cur().codepoint) &&
+ 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);
+ ret |= accel.apply (c, subtable_count, false);
/* The reverse lookup doesn't "advance" cursor (for good reason). */
buffer->idx--;
@@ -1875,28 +1904,31 @@ apply_backward (OT::hb_ot_apply_context_t *c,
}
template <typename Proxy>
-static inline void
+static inline bool
apply_string (OT::hb_ot_apply_context_t *c,
const typename Proxy::Lookup &lookup,
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
hb_buffer_t *buffer = c->buffer;
+ unsigned subtable_count = lookup.get_subtable_count ();
if (unlikely (!buffer->len || !c->lookup_mask))
- return;
+ return false;
+
+ bool ret = false;
c->set_lookup_props (lookup.get_props ());
if (likely (!lookup.is_reverse ()))
{
/* in/out forward substitution/positioning */
- if (!Proxy::inplace)
+ if (!Proxy::always_inplace)
buffer->clear_output ();
buffer->idx = 0;
- apply_forward (c, accel);
+ ret = apply_forward (c, accel, subtable_count);
- if (!Proxy::inplace)
+ if (!Proxy::always_inplace)
buffer->sync ();
}
else
@@ -1904,8 +1936,10 @@ apply_string (OT::hb_ot_apply_context_t *c,
/* in-place backward substitution/positioning */
assert (!buffer->have_output);
buffer->idx = buffer->len - 1;
- apply_backward (c, accel);
+ ret = apply_backward (c, accel, subtable_count);
}
+
+ return ret;
}
template <typename Proxy>
@@ -1917,47 +1951,76 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
const unsigned int table_index = proxy.table_index;
unsigned int i = 0;
OT::hb_ot_apply_context_t c (table_index, font, buffer);
- c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
+ c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func<OT::hb_ot_apply_context_t>);
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++)
{
const stage_map_t *stage = &stages[table_index][stage_index];
for (; i < stage->last_lookup; i++)
{
- unsigned int lookup_index = lookups[table_index][i].index;
- if (!buffer->message (font, "start lookup %d", lookup_index)) continue;
- c.set_lookup_index (lookup_index);
- c.set_lookup_mask (lookups[table_index][i].mask);
- c.set_auto_zwj (lookups[table_index][i].auto_zwj);
- c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
- c.set_random (lookups[table_index][i].random);
- c.set_per_syllable (lookups[table_index][i].per_syllable);
-
- apply_string<Proxy> (&c,
- proxy.table.get_lookup (lookup_index),
- proxy.accels[lookup_index]);
- (void) buffer->message (font, "end lookup %d", lookup_index);
+ auto &lookup = lookups[table_index][i];
+
+ unsigned int lookup_index = lookup.index;
+
+ 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 (accel->digest.may_have (c.digest))
+ {
+ c.set_lookup_index (lookup_index);
+ c.set_lookup_mask (lookup.mask);
+ c.set_auto_zwj (lookup.auto_zwj);
+ c.set_auto_zwnj (lookup.auto_zwnj);
+ c.set_random (lookup.random);
+ c.set_per_syllable (lookup.per_syllable);
+
+ apply_string<Proxy> (&c,
+ proxy.accel.table->get_lookup (lookup_index),
+ *accel);
+ }
+ 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));
+
+ 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)
- stage->pause_func (plan, font, buffer);
+ {
+ if (stage->pause_func (plan, font, buffer))
+ {
+ /* Refresh working buffer digest since buffer changed. */
+ c.digest = buffer->digest ();
+ }
+ }
}
}
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
@@ -2051,7 +2114,7 @@ hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script)
*
* Fetches a baseline value from the face.
*
- * Return value: %true if found baseline value in the font.
+ * Return value: `true` if found baseline value in the font.
*
* Since: 2.6.0
**/
@@ -2297,11 +2360,6 @@ struct hb_get_glyph_alternates_dispatch_t :
static return_t default_return_value () { return 0; }
bool stop_sublookup_iteration (return_t r) const { return r; }
- hb_face_t *face;
-
- hb_get_glyph_alternates_dispatch_t (hb_face_t *face) :
- face (face) {}
-
private:
template <typename T, typename ...Ts> auto
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
@@ -2315,6 +2373,7 @@ struct hb_get_glyph_alternates_dispatch_t :
( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
};
+#ifndef HB_NO_LAYOUT_RARELY_USED
/**
* hb_ot_layout_lookup_get_glyph_alternates:
* @face: a face.
@@ -2340,11 +2399,79 @@ hb_ot_layout_lookup_get_glyph_alternates (hb_face_t *face,
unsigned *alternate_count /* IN/OUT. May be NULL. */,
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */)
{
- hb_get_glyph_alternates_dispatch_t c (face);
+ hb_get_glyph_alternates_dispatch_t c;
const OT::SubstLookup &lookup = face->table.GSUB->table->get_lookup (lookup_index);
auto ret = lookup.dispatch (&c, glyph, start_offset, alternate_count, alternate_glyphs);
if (!ret && alternate_count) *alternate_count = 0;
return ret;
}
+
+struct hb_position_single_dispatch_t :
+ hb_dispatch_context_t<hb_position_single_dispatch_t, bool>
+{
+ static return_t default_return_value () { return false; }
+ bool stop_sublookup_iteration (return_t r) const { return r; }
+
+ private:
+ template <typename T, typename ...Ts> auto
+ _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
+ ( obj.position_single (std::forward<Ts> (ds)...) )
+ template <typename T, typename ...Ts> auto
+ _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
+ ( default_return_value () )
+ public:
+ template <typename T, typename ...Ts> auto
+ dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
+ ( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
+};
+
+/**
+ * hb_ot_layout_lookup_get_optical_bound:
+ * @font: a font.
+ * @lookup_index: index of the feature lookup to query.
+ * @direction: edge of the glyph to query.
+ * @glyph: a glyph id.
+ *
+ * Fetches the optical bound of a glyph positioned at the margin of text.
+ * The direction identifies which edge of the glyph to query.
+ *
+ * Return value: Adjustment value. Negative values mean the glyph will stick out of the margin.
+ *
+ * Since: 5.3.0
+ **/
+hb_position_t
+hb_ot_layout_lookup_get_optical_bound (hb_font_t *font,
+ unsigned lookup_index,
+ hb_direction_t direction,
+ hb_codepoint_t glyph)
+{
+ const OT::PosLookup &lookup = font->face->table.GPOS->table->get_lookup (lookup_index);
+ hb_glyph_position_t pos = {0};
+ hb_position_single_dispatch_t c;
+ lookup.dispatch (&c, font, direction, glyph, pos);
+ hb_position_t ret = 0;
+ switch (direction)
+ {
+ case HB_DIRECTION_LTR:
+ ret = pos.x_offset;
+ break;
+ case HB_DIRECTION_RTL:
+ ret = pos.x_advance - pos.x_offset;
+ break;
+ case HB_DIRECTION_TTB:
+ ret = pos.y_offset;
+ break;
+ case HB_DIRECTION_BTT:
+ ret = pos.y_advance - pos.y_offset;
+ break;
+ case HB_DIRECTION_INVALID:
+ default:
+ break;
+ }
+ return ret;
+}
+#endif
+
+
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h
index 4edddd9e0d..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,
@@ -403,6 +412,16 @@ hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *range_start, /* OUT. May be NULL */
unsigned int *range_end /* OUT. May be NULL */);
+HB_EXTERN hb_position_t
+hb_ot_layout_lookup_get_optical_bound (hb_font_t *font,
+ unsigned lookup_index,
+ hb_direction_t direction,
+ hb_codepoint_t glyph);
+
+
+/*
+ * GSUB/GPOS
+ */
HB_EXTERN hb_bool_t
hb_ot_layout_feature_get_name_ids (hb_face_t *face,
@@ -423,6 +442,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
unsigned int *char_count /* IN/OUT. May be NULL */,
hb_codepoint_t *characters /* OUT. May be NULL */);
+
/*
* BASE
*/
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
index 75bba0bc50..9505d5f147 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
@@ -102,15 +102,11 @@ HB_INTERNAL void
hb_ot_layout_substitute_start (hb_font_t *font,
hb_buffer_t *buffer);
-HB_INTERNAL void
-hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
- bool (*filter) (const hb_glyph_info_t *info));
-
namespace OT {
struct hb_ot_apply_context_t;
struct hb_ot_layout_lookup_accelerator_t;
namespace Layout {
-namespace GSUB {
+namespace GSUB_impl {
struct SubstLookup;
}
}
@@ -118,7 +114,7 @@ namespace GSUB {
HB_INTERNAL void
hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
- const OT::Layout::GSUB::SubstLookup &lookup,
+ const OT::Layout::GSUB_impl::SubstLookup &lookup,
const OT::hb_ot_layout_lookup_accelerator_t &accel);
@@ -552,7 +548,7 @@ _hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
}
-static inline void
+static inline bool
_hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -561,6 +557,7 @@ _hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
_hb_glyph_info_clear_substituted (&info[i]);
+ return false;
}
@@ -589,13 +586,11 @@ _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
{
HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
- HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
}
static inline void
_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
{
- HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
}
@@ -605,7 +600,6 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
{
HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
HB_BUFFER_ASSERT_VAR (buffer, lig_props);
- HB_BUFFER_ASSERT_VAR (buffer, syllable);
}
/* Make sure no one directly touches our props... */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
index f085c78ff8..8882dbaccb 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc
@@ -43,16 +43,16 @@ void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_o
hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
- const hb_segment_properties_t *props_)
+ const hb_segment_properties_t &props_)
{
- memset (this, 0, sizeof (*this));
+ hb_memset (this, 0, sizeof (*this));
feature_infos.init ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
stages[table_index].init ();
face = face_;
- props = *props_;
+ props = props_;
/* Fetch script/language indices for GSUB/GPOS. We need these later to skip
* features not available in either table and not waste precious bits for them. */
@@ -109,6 +109,21 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag,
info->stage[1] = current_stage[1];
}
+bool hb_ot_map_builder_t::has_feature (hb_tag_t tag)
+{
+ for (unsigned int table_index = 0; table_index < 2; table_index++)
+ {
+ if (hb_ot_layout_language_find_feature (face,
+ table_tags[table_index],
+ script_index[table_index],
+ language_index[table_index],
+ tag,
+ nullptr))
+ return true;
+ }
+ return false;
+}
+
void
hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
unsigned int table_index,
@@ -118,7 +133,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
bool auto_zwnj,
bool auto_zwj,
bool random,
- bool per_syllable)
+ bool per_syllable,
+ hb_tag_t feature_tag)
{
unsigned int lookup_indices[32];
unsigned int offset, len;
@@ -147,6 +163,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
lookup->auto_zwj = auto_zwj;
lookup->random = random;
lookup->per_syllable = per_syllable;
+ lookup->feature_tag = feature_tag;
}
offset += len;
@@ -197,24 +214,26 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
if (feature_infos.length)
{
feature_infos.qsort ();
+ auto *f = feature_infos.arrayZ;
unsigned int j = 0;
- for (unsigned int i = 1; i < feature_infos.length; i++)
- if (feature_infos[i].tag != feature_infos[j].tag)
- feature_infos[++j] = feature_infos[i];
+ unsigned count = feature_infos.length;
+ for (unsigned int i = 1; i < count; i++)
+ if (f[i].tag != f[j].tag)
+ f[++j] = f[i];
else {
- if (feature_infos[i].flags & F_GLOBAL) {
- feature_infos[j].flags |= F_GLOBAL;
- feature_infos[j].max_value = feature_infos[i].max_value;
- feature_infos[j].default_value = feature_infos[i].default_value;
+ if (f[i].flags & F_GLOBAL) {
+ f[j].flags |= F_GLOBAL;
+ f[j].max_value = f[i].max_value;
+ f[j].default_value = f[i].default_value;
} else {
- if (feature_infos[j].flags & F_GLOBAL)
- feature_infos[j].flags ^= F_GLOBAL;
- feature_infos[j].max_value = hb_max (feature_infos[j].max_value, feature_infos[i].max_value);
+ if (f[j].flags & F_GLOBAL)
+ f[j].flags ^= F_GLOBAL;
+ f[j].max_value = hb_max (f[j].max_value, f[i].max_value);
/* Inherit default_value from j */
}
- feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK);
- feature_infos[j].stage[0] = hb_min (feature_infos[j].stage[0], feature_infos[i].stage[0]);
- feature_infos[j].stage[1] = hb_min (feature_infos[j].stage[1], feature_infos[i].stage[1]);
+ f[j].flags |= (f[i].flags & F_HAS_FALLBACK);
+ f[j].stage[0] = hb_min (f[j].stage[0], f[i].stage[0]);
+ f[j].stage[1] = hb_min (f[j].stage[1], f[i].stage[1]);
}
feature_infos.shrink (j + 1);
}
@@ -224,7 +243,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
unsigned int next_bit = hb_popcount (HB_GLYPH_FLAG_DEFINED) + 1;
- for (unsigned int i = 0; i < feature_infos.length; i++)
+ unsigned count = feature_infos.length;
+ for (unsigned int i = 0; i < count; i++)
{
const feature_info_t *info = &feature_infos[i];
@@ -293,7 +313,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
map->_1_mask = (1u << map->shift) & map->mask;
map->needs_fallback = !found;
}
- feature_infos.shrink (0); /* Done with these */
+ //feature_infos.shrink (0); /* Done with these */
add_gsub_pause (nullptr);
@@ -302,6 +322,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
/* Collect lookup indices for features */
+ auto &lookups = m.lookups[table_index];
unsigned int stage_index = 0;
unsigned int last_num_lookups = 0;
@@ -314,36 +335,39 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
key.variations_index[table_index],
global_bit_mask);
- for (unsigned i = 0; i < m.features.length; i++)
- if (m.features[i].stage[table_index] == stage)
+ for (auto &feature : m.features)
+ {
+ if (feature.stage[table_index] == stage)
add_lookups (m, table_index,
- m.features[i].index[table_index],
+ feature.index[table_index],
key.variations_index[table_index],
- m.features[i].mask,
- m.features[i].auto_zwnj,
- m.features[i].auto_zwj,
- m.features[i].random,
- m.features[i].per_syllable);
+ feature.mask,
+ feature.auto_zwnj,
+ feature.auto_zwj,
+ feature.random,
+ feature.per_syllable,
+ feature.tag);
+ }
/* Sort lookups and merge duplicates */
- if (last_num_lookups < m.lookups[table_index].length)
+ if (last_num_lookups < lookups.length)
{
- m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].length);
+ lookups.as_array ().sub_array (last_num_lookups, lookups.length - last_num_lookups).qsort ();
unsigned int j = last_num_lookups;
- for (unsigned int i = j + 1; i < m.lookups[table_index].length; i++)
- if (m.lookups[table_index][i].index != m.lookups[table_index][j].index)
- m.lookups[table_index][++j] = m.lookups[table_index][i];
+ for (unsigned int i = j + 1; i < lookups.length; i++)
+ if (lookups.arrayZ[i].index != lookups.arrayZ[j].index)
+ lookups.arrayZ[++j] = lookups.arrayZ[i];
else
{
- m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask;
- m.lookups[table_index][j].auto_zwnj &= m.lookups[table_index][i].auto_zwnj;
- m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto_zwj;
+ lookups.arrayZ[j].mask |= lookups.arrayZ[i].mask;
+ lookups.arrayZ[j].auto_zwnj &= lookups.arrayZ[i].auto_zwnj;
+ lookups.arrayZ[j].auto_zwj &= lookups.arrayZ[i].auto_zwj;
}
- m.lookups[table_index].shrink (j + 1);
+ lookups.shrink (j + 1);
}
- last_num_lookups = m.lookups[table_index].length;
+ last_num_lookups = lookups.length;
if (stage_index < stages[table_index].length && stages[table_index][stage_index].index == stage) {
hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh
index f1cbf752fc..efc8cae96a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.hh
@@ -69,6 +69,7 @@ struct hb_ot_map_t
unsigned short random : 1;
unsigned short per_syllable : 1;
hb_mask_t mask;
+ hb_tag_t feature_tag;
HB_INTERNAL static int cmp (const void *pa, const void *pb)
{
@@ -78,7 +79,9 @@ struct hb_ot_map_t
}
};
- typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
+ /* Pause functions return true if new glyph indices might have been
+ * added to the buffer. This is used to update buffer digest. */
+ typedef bool (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
struct stage_map_t {
unsigned int last_lookup; /* Cumulative */
@@ -87,13 +90,13 @@ struct hb_ot_map_t
void init ()
{
- memset (this, 0, sizeof (*this));
+ hb_memset (this, 0, sizeof (*this));
- features.init ();
+ features.init0 ();
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
- lookups[table_index].init ();
- stages[table_index].init ();
+ lookups[table_index].init0 ();
+ stages[table_index].init0 ();
}
}
void fini ()
@@ -139,19 +142,15 @@ struct hb_ot_map_t
return map ? map->stage[table_index] : UINT_MAX;
}
- void get_stage_lookups (unsigned int table_index, unsigned int stage,
- const struct lookup_map_t **plookups, unsigned int *lookup_count) const
+ hb_array_t<const hb_ot_map_t::lookup_map_t>
+ get_stage_lookups (unsigned int table_index, unsigned int stage) const
{
if (unlikely (stage > stages[table_index].length))
- {
- *plookups = nullptr;
- *lookup_count = 0;
- return;
- }
+ return hb_array<const hb_ot_map_t::lookup_map_t> (nullptr, 0);
+
unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
unsigned int end = stage < stages[table_index].length ? stages[table_index][stage].last_lookup : lookups[table_index].length;
- *plookups = end == start ? nullptr : &lookups[table_index][start];
- *lookup_count = end - start;
+ return lookups[table_index].as_array ().sub_array (start, end - start);
}
HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
@@ -167,7 +166,7 @@ struct hb_ot_map_t
private:
- hb_mask_t global_mask;
+ hb_mask_t global_mask = 0;
hb_sorted_vector_t<feature_map_t> features;
hb_vector_t<lookup_map_t> lookups[2]; /* GSUB/GPOS */
@@ -204,7 +203,7 @@ struct hb_ot_map_builder_t
public:
HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
- const hb_segment_properties_t *props_);
+ const hb_segment_properties_t &props_);
HB_INTERNAL ~hb_ot_map_builder_t ();
@@ -212,6 +211,8 @@ struct hb_ot_map_builder_t
hb_ot_map_feature_flags_t flags=F_NONE,
unsigned int value=1);
+ HB_INTERNAL bool has_feature (hb_tag_t tag);
+
void add_feature (const hb_ot_map_feature_t &feat)
{ add_feature (feat.tag, feat.flags); }
@@ -241,7 +242,8 @@ struct hb_ot_map_builder_t
bool auto_zwnj = true,
bool auto_zwj = true,
bool random = false,
- bool per_syllable = false);
+ bool per_syllable = false,
+ hb_tag_t feature_tag = HB_TAG(' ',' ',' ',' '));
struct feature_info_t {
hb_tag_t tag;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
index d834d94371..dccf720f46 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh
@@ -77,11 +77,11 @@ struct MathConstants
HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2);
if (unlikely (!p)) return_trace (nullptr);
- memcpy (p, percentScaleDown, HBINT16::static_size * 2);
+ hb_memcpy (p, percentScaleDown, HBINT16::static_size * 2);
HBUINT16 *m = c->allocate_size<HBUINT16> (HBUINT16::static_size * 2);
if (unlikely (!m)) return_trace (nullptr);
- memcpy (m, minHeight, HBUINT16::static_size * 2);
+ hb_memcpy (m, minHeight, HBUINT16::static_size * 2);
unsigned count = ARRAY_LENGTH (mathValueRecords);
for (unsigned i = 0; i < count; i++)
@@ -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 =
@@ -786,7 +786,7 @@ struct MathGlyphAssembly
if (parts_count)
{
int64_t mult = font->dir_mult (direction);
- for (auto _ : hb_zip (partRecords.sub_array (start_offset, parts_count),
+ for (auto _ : hb_zip (partRecords.as_array ().sub_array (start_offset, parts_count),
hb_array (parts, *parts_count)))
_.first.extract (_.second, mult, font);
}
@@ -855,7 +855,7 @@ struct MathGlyphConstruction
if (variants_count)
{
int64_t mult = font->dir_mult (direction);
- for (auto _ : hb_zip (mathGlyphVariantRecord.sub_array (start_offset, variants_count),
+ for (auto _ : hb_zip (mathGlyphVariantRecord.as_array ().sub_array (start_offset, variants_count),
hb_array (variants, *variants_count)))
_.second = {_.first.variantGlyph, font->em_mult (_.first.advanceMeasurement, mult)};
}
@@ -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-math.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc
index f44ac35849..c515867bdf 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc
@@ -56,7 +56,7 @@
*
* Tests whether a face has a `MATH` table.
*
- * Return value: %true if the table is found, %false otherwise
+ * Return value: `true` if the table is found, `false` otherwise
*
* Since: 1.3.3
**/
@@ -142,7 +142,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
*
* Tests whether the given glyph index is an extended shape in the face.
*
- * Return value: %true if the glyph is an extended shape, %false otherwise
+ * Return value: `true` if the glyph is an extended shape, `false` otherwise
*
* Since: 1.3.3
**/
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-meta-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-meta-table.hh
index 93e64c5327..e1b68bcf91 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-meta-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-meta-table.hh
@@ -84,7 +84,7 @@ struct meta
{
if (count)
{
- + table->dataMaps.sub_array (start_offset, count)
+ + table->dataMaps.as_array ().sub_array (start_offset, count)
| hb_map (&DataMap::get_tag)
| hb_map ([](hb_tag_t tag) { return (hb_ot_meta_tag_t) tag; })
| hb_sink (hb_array (entries, *count))
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc
index f9c4b96fff..5b12482b97 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-metrics.cc
@@ -71,12 +71,12 @@ _hb_ot_metrics_get_position_common (hb_font_t *font,
#endif
#define GET_METRIC_X(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_x (_fix_ascender_descender ( \
- face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
+ ((void) (position && (*position = font->em_scalef_x (_fix_ascender_descender ( \
+ face->table.TABLE->ATTR + GET_VAR, metrics_tag)))), true))
#define GET_METRIC_Y(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
- face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
+ ((void) (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
+ face->table.TABLE->ATTR + GET_VAR, metrics_tag)))), true))
case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) ||
@@ -154,10 +154,10 @@ hb_ot_metrics_get_position (hb_font_t *font,
#endif
#define GET_METRIC_X(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR)), true))
+ ((void) (position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR))), true))
#define GET_METRIC_Y(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true))
+ ((void) (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR))), true))
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent);
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-language-static.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-language-static.hh
index c496dc2981..0e0f2d632a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-language-static.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-language-static.hh
@@ -45,7 +45,7 @@ struct hb_ot_language_map_t
};
static const hb_ot_language_map_t
-hb_ms_language_map[] =
+_hb_ms_language_map[] =
{
{0x0001, "ar"}, /* ??? */
{0x0004, "zh"}, /* ??? */
@@ -298,7 +298,7 @@ hb_ms_language_map[] =
};
static const hb_ot_language_map_t
-hb_mac_language_map[] =
+_hb_mac_language_map[] =
{
{ 0, "en"}, /* English */
{ 1, "fr"}, /* French */
@@ -441,16 +441,16 @@ hb_language_t
_hb_ot_name_language_for_ms_code (unsigned int code)
{
return _hb_ot_name_language_for (code,
- hb_ms_language_map,
- ARRAY_LENGTH (hb_ms_language_map));
+ _hb_ms_language_map,
+ ARRAY_LENGTH (_hb_ms_language_map));
}
hb_language_t
_hb_ot_name_language_for_mac_code (unsigned int code)
{
return _hb_ot_name_language_for (code,
- hb_mac_language_map,
- ARRAY_LENGTH (hb_mac_language_map));
+ _hb_mac_language_map,
+ ARRAY_LENGTH (_hb_mac_language_map));
}
#endif /* HB_OT_NAME_LANGUAGE_STATIC_HH */
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 d52367e9b1..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,354 +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"
-
-
-namespace OT {
-
-
-#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) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->embed (this);
- if (unlikely (!out)) return_trace (nullptr);
- 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)
-{
- 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;
- return strcmp (hb_language_to_string (a->language),
- hb_language_to_string (b->language));
-}
-
-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);
- 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)
- {
- TRACE_SERIALIZE (this);
-
- if (unlikely (!c->extend_min ((*this)))) return_trace (false);
-
- this->format = 0;
- this->count = it.len ();
-
- NameRecord *name_records = (NameRecord *) hb_calloc (it.len (), NameRecord::static_size);
- if (unlikely (!name_records)) return_trace (false);
-
- hb_array_t<NameRecord> records (name_records, it.len ());
-
- for (const NameRecord& record : it)
- {
- memcpy (name_records, &record, NameRecord::static_size);
- name_records++;
- }
-
- records.qsort ();
-
- c->copy_all (records, src_string_pool);
- 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);
-
- 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 ();
- })
- ;
-
- name_prime->serialize (c->serializer, it, std::addressof (this + stringOffset));
- return_trace (name_prime->count);
- }
-
- 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);
- 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;
- };
-
- /* 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 c35ac5b3dc..0323364aef 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name.cc
@@ -64,52 +64,6 @@ hb_ot_name_list_names (hb_face_t *face,
return (const hb_ot_name_entry_t *) name.names;
}
-
-template <typename in_utf_t, typename out_utf_t>
-static 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)--; /* Same 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;
-}
-
template <typename utf_t>
static inline unsigned int
hb_ot_name_get_utf (hb_face_t *face,
@@ -130,10 +84,10 @@ hb_ot_name_get_utf (hb_face_t *face,
hb_bytes_t bytes = name.get_name (idx);
if (width == 2) /* UTF16-BE */
- return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text);
+ return OT::hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text);
if (width == 1) /* ASCII */
- return hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text);
+ return OT::hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text);
}
if (text_size)
@@ -227,5 +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 f0035e2f04..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
{
@@ -166,22 +168,111 @@ struct OS2
}
}
+ float map_wdth_to_widthclass(float width) const
+ {
+ if (width < 50) return 1.0f;
+ if (width > 200) return 9.0f;
+
+ float ratio = (width - 50) / 12.5f;
+ int a = (int) floorf (ratio);
+ int b = (int) ceilf (ratio);
+
+ /* follow this maping:
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass
+ */
+ if (b <= 6) // 50-125
+ {
+ if (a == b) return a + 1.0f;
+ }
+ else if (b == 7) // no mapping for 137.5
+ {
+ a = 6;
+ b = 8;
+ }
+ else if (b == 8)
+ {
+ if (a == b) return 8.0f; // 150
+ a = 6;
+ }
+ else
+ {
+ if (a == b && a == 12) return 9.0f; //200
+ b = 12;
+ a = 8;
+ }
+
+ float va = 50 + a * 12.5f;
+ float vb = 50 + b * 12.5f;
+
+ float ret = a + (width - va) / (vb - va);
+ if (a <= 6) ret += 1.0f;
+ return ret;
+ }
+
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
OS2 *os2_prime = c->serializer->embed (this);
if (unlikely (!os2_prime)) return_trace (false);
+
+#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'));
+ 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')) &&
+ !c->plan->pinned_at_default)
+ {
+ 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))
+ return_trace (false);
+ }
+
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);
}
@@ -189,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)
{
@@ -216,17 +311,11 @@ 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://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
{
+ FONT_PAGE_NONE = 0,
FONT_PAGE_HEBREW = 0xB100, /* Hebrew Windows 3.1 font page */
FONT_PAGE_SIMP_ARABIC = 0xB200, /* Simplified Arabic Windows 3.1 font page */
FONT_PAGE_TRAD_ARABIC = 0xB300, /* Traditional Arabic Windows 3.1 font page */
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-v2subset.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh
index 0f3cd8e24f..951e6395d6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table-v2subset.hh
@@ -52,16 +52,16 @@ HB_INTERNAL bool postV2Tail::serialize (hb_serialize_context_t *c,
{
unsigned glyph_id = _.first;
unsigned new_index = _.second;
-
+
if (new_index < 258) continue;
if (copied_indices.has (new_index)) continue;
copied_indices.add (new_index);
-
+
hb_bytes_t s = reinterpret_cast<const post::accelerator_t*> (_post)->find_glyph_name (glyph_id);
HBUINT8 *o = c->allocate_size<HBUINT8> (HBUINT8::static_size * (s.length + 1));
if (unlikely (!o)) return_trace (false);
if (!c->check_assign (o[0], s.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
- memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
+ hb_memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
}
return_trace (true);
@@ -78,17 +78,19 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
post::accelerator_t _post (c->plan->source);
- hb_hashmap_t<hb_bytes_t, unsigned, std::nullptr_t, unsigned, nullptr, (unsigned)-1> glyph_name_to_new_index;
+ hb_hashmap_t<hb_bytes_t, uint32_t, true> glyph_name_to_new_index;
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
{
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
unsigned old_index = glyphNameIndex[old_gid];
unsigned new_index;
+ const uint32_t *new_index2;
if (old_index <= 257) new_index = old_index;
- else if (old_new_index_map.has (old_index)) new_index = old_new_index_map.get (old_index);
- else
+ else if (old_new_index_map.has (old_index, &new_index2))
{
+ new_index = *new_index2;
+ } else {
hb_bytes_t s = _post.find_glyph_name (old_gid);
new_index = glyph_name_to_new_index.get (s);
if (new_index == (unsigned)-1)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh
index a4844e94bc..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"
@@ -84,7 +85,7 @@ struct post
post *post_prime = c->allocate_min<post> ();
if (unlikely (!post_prime)) return_trace (false);
- memcpy (post_prime, this, post::min_size);
+ hb_memcpy (post_prime, this, post::min_size);
if (!glyph_names)
return_trace (c->check_assign (post_prime->version.major, 3,
HB_SERIALIZE_ERROR_INT_OVERFLOW)); // Version 3 does not have any glyph names.
@@ -98,10 +99,29 @@ 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')) &&
+ !c->plan->pinned_at_default)
+ {
+ 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);
+ }
+
if (glyph_names && version.major == 2)
return_trace (v2X.subset (c));
@@ -126,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)
@@ -133,7 +154,7 @@ struct post
}
~accelerator_t ()
{
- hb_free (gids_sorted_by_name.get ());
+ hb_free (gids_sorted_by_name.get_acquire ());
table.destroy ();
}
@@ -160,7 +181,7 @@ struct post
if (unlikely (!len)) return false;
retry:
- uint16_t *gids = gids_sorted_by_name.get ();
+ uint16_t *gids = gids_sorted_by_name.get_acquire ();
if (unlikely (!gids))
{
@@ -263,10 +284,10 @@ struct post
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) &&
- (version.to_int () == 0x00010000 ||
- (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
- version.to_int () == 0x00030000)));
+ return_trace (c->check_struct (this) &&
+ (version.to_int () == 0x00010000 ||
+ (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
+ version.to_int () == 0x00030000));
}
public:
@@ -274,7 +295,7 @@ struct post
* 0x00020000 for version 2.0
* 0x00025000 for version 2.5 (deprecated)
* 0x00030000 for version 3.0 */
- HBFixed italicAngle; /* Italic angle in counter-clockwise degrees
+ F16DOT16 italicAngle; /* Italic angle in counter-clockwise degrees
* from the vertical. Zero for upright text,
* negative for text that leans to the right
* (forward). */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
deleted file mode 100644
index 74bf3ca0fa..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
+++ /dev/null
@@ -1,603 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-indic-machine.rl"
-/*
- * 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 HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
-
-#include "hb.hh"
-
-enum indic_syllable_type_t {
- indic_consonant_syllable,
- indic_vowel_syllable,
- indic_standalone_cluster,
- indic_symbol_cluster,
- indic_broken_cluster,
- indic_non_indic_cluster,
-};
-
-
-#line 45 "hb-ot-shape-complex-indic-machine.hh"
-#define indic_syllable_machine_ex_A 10u
-#define indic_syllable_machine_ex_C 1u
-#define indic_syllable_machine_ex_CM 17u
-#define indic_syllable_machine_ex_CS 19u
-#define indic_syllable_machine_ex_DOTTEDCIRCLE 12u
-#define indic_syllable_machine_ex_H 4u
-#define indic_syllable_machine_ex_M 7u
-#define indic_syllable_machine_ex_N 3u
-#define indic_syllable_machine_ex_PLACEHOLDER 11u
-#define indic_syllable_machine_ex_RS 13u
-#define indic_syllable_machine_ex_Ra 16u
-#define indic_syllable_machine_ex_Repha 15u
-#define indic_syllable_machine_ex_SM 8u
-#define indic_syllable_machine_ex_Symbol 18u
-#define indic_syllable_machine_ex_V 2u
-#define indic_syllable_machine_ex_ZWJ 6u
-#define indic_syllable_machine_ex_ZWNJ 5u
-
-
-#line 65 "hb-ot-shape-complex-indic-machine.hh"
-static const unsigned char _indic_syllable_machine_trans_keys[] = {
- 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
- 4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u,
- 4u, 8u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u,
- 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u,
- 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 5u, 8u, 8u, 8u, 1u, 19u,
- 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u,
- 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u,
- 3u, 10u, 5u, 10u, 3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
- 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u,
- 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u,
- 5u, 10u, 3u, 17u, 3u, 17u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
- 3u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u,
- 4u, 10u, 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u,
- 3u, 17u, 4u, 13u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u,
- 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u,
- 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 1u, 17u,
- 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u,
- 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0
-};
-
-static const char _indic_syllable_machine_key_spans[] = {
- 1, 5, 3, 4, 5, 1, 1, 5,
- 10, 5, 1, 3, 4, 5, 1, 1,
- 5, 10, 10, 10, 1, 3, 4, 5,
- 1, 1, 5, 5, 10, 1, 3, 4,
- 5, 1, 1, 5, 5, 4, 1, 19,
- 15, 15, 14, 16, 6, 6, 1, 6,
- 16, 16, 16, 8, 7, 6, 7, 6,
- 8, 6, 15, 15, 15, 15, 14, 16,
- 15, 15, 14, 16, 6, 1, 6, 16,
- 16, 8, 7, 6, 7, 6, 6, 8,
- 6, 15, 15, 5, 15, 15, 14, 16,
- 15, 16, 6, 1, 6, 16, 16, 8,
- 7, 6, 15, 7, 6, 6, 8, 6,
- 15, 10, 5, 15, 15, 14, 16, 15,
- 16, 6, 1, 6, 16, 16, 8, 7,
- 6, 15, 7, 6, 6, 8, 6, 17,
- 15, 17, 10, 6, 1, 6, 16, 8,
- 6, 6, 1, 6, 16
-};
-
-static const short _indic_syllable_machine_index_offsets[] = {
- 0, 2, 8, 12, 17, 23, 25, 27,
- 33, 44, 50, 52, 56, 61, 67, 69,
- 71, 77, 88, 99, 110, 112, 116, 121,
- 127, 129, 131, 137, 143, 154, 156, 160,
- 165, 171, 173, 175, 181, 187, 192, 194,
- 214, 230, 246, 261, 278, 285, 292, 294,
- 301, 318, 335, 352, 361, 369, 376, 384,
- 391, 400, 407, 423, 439, 455, 471, 486,
- 503, 519, 535, 550, 567, 574, 576, 583,
- 600, 617, 626, 634, 641, 649, 656, 663,
- 672, 679, 695, 711, 717, 733, 749, 764,
- 781, 797, 814, 821, 823, 830, 847, 864,
- 873, 881, 888, 904, 912, 919, 926, 935,
- 942, 958, 969, 975, 991, 1007, 1022, 1039,
- 1055, 1072, 1079, 1081, 1088, 1105, 1122, 1131,
- 1139, 1146, 1162, 1170, 1177, 1184, 1193, 1200,
- 1218, 1234, 1252, 1263, 1270, 1272, 1279, 1296,
- 1305, 1312, 1319, 1321, 1328
-};
-
-static const unsigned char _indic_syllable_machine_indicies[] = {
- 1, 0, 2, 3, 3, 4, 1, 0,
- 3, 3, 4, 0, 3, 3, 4, 1,
- 0, 5, 3, 3, 4, 1, 0, 6,
- 0, 7, 0, 8, 3, 3, 4, 1,
- 0, 2, 3, 3, 4, 1, 0, 0,
- 0, 0, 9, 0, 11, 12, 12, 13,
- 14, 10, 14, 10, 12, 12, 13, 10,
- 12, 12, 13, 14, 10, 15, 12, 12,
- 13, 14, 10, 16, 10, 17, 10, 18,
- 12, 12, 13, 14, 10, 11, 12, 12,
- 13, 14, 10, 10, 10, 10, 19, 10,
- 11, 12, 12, 13, 14, 10, 10, 10,
- 10, 20, 10, 22, 23, 23, 24, 25,
- 21, 21, 21, 21, 26, 21, 25, 21,
- 23, 23, 24, 27, 23, 23, 24, 25,
- 21, 28, 23, 23, 24, 25, 21, 29,
- 21, 30, 21, 22, 23, 23, 24, 25,
- 21, 31, 23, 23, 24, 25, 21, 33,
- 34, 34, 35, 36, 32, 32, 32, 32,
- 37, 32, 36, 32, 34, 34, 35, 32,
- 34, 34, 35, 36, 32, 38, 34, 34,
- 35, 36, 32, 39, 32, 40, 32, 33,
- 34, 34, 35, 36, 32, 41, 34, 34,
- 35, 36, 32, 23, 23, 24, 1, 0,
- 43, 42, 45, 46, 47, 48, 49, 50,
- 24, 25, 44, 51, 52, 52, 26, 44,
- 53, 54, 55, 56, 57, 44, 59, 60,
- 61, 62, 4, 1, 58, 63, 58, 58,
- 9, 58, 58, 58, 64, 58, 65, 60,
- 66, 66, 4, 1, 58, 63, 58, 58,
- 58, 58, 58, 58, 64, 58, 60, 66,
- 66, 4, 1, 58, 63, 58, 58, 58,
- 58, 58, 58, 64, 58, 45, 58, 58,
- 58, 67, 68, 58, 1, 58, 63, 58,
- 58, 58, 58, 58, 45, 58, 69, 69,
- 58, 1, 58, 63, 58, 63, 58, 58,
- 70, 58, 63, 58, 63, 58, 63, 58,
- 58, 58, 58, 63, 58, 45, 58, 71,
- 58, 69, 69, 58, 1, 58, 63, 58,
- 58, 58, 58, 58, 45, 58, 45, 58,
- 58, 58, 69, 69, 58, 1, 58, 63,
- 58, 58, 58, 58, 58, 45, 58, 45,
- 58, 58, 58, 69, 68, 58, 1, 58,
- 63, 58, 58, 58, 58, 58, 45, 58,
- 72, 7, 73, 74, 4, 1, 58, 63,
- 58, 7, 73, 74, 4, 1, 58, 63,
- 58, 73, 73, 4, 1, 58, 63, 58,
- 75, 76, 76, 4, 1, 58, 63, 58,
- 67, 77, 58, 1, 58, 63, 58, 67,
- 58, 69, 69, 58, 1, 58, 63, 58,
- 69, 77, 58, 1, 58, 63, 58, 59,
- 60, 66, 66, 4, 1, 58, 63, 58,
- 58, 58, 58, 58, 58, 64, 58, 59,
- 60, 61, 66, 4, 1, 58, 63, 58,
- 58, 9, 58, 58, 58, 64, 58, 79,
- 80, 81, 82, 13, 14, 78, 83, 78,
- 78, 20, 78, 78, 78, 84, 78, 85,
- 80, 86, 82, 13, 14, 78, 83, 78,
- 78, 78, 78, 78, 78, 84, 78, 80,
- 86, 82, 13, 14, 78, 83, 78, 78,
- 78, 78, 78, 78, 84, 78, 87, 78,
- 78, 78, 88, 89, 78, 14, 78, 83,
- 78, 78, 78, 78, 78, 87, 78, 90,
- 80, 91, 92, 13, 14, 78, 83, 78,
- 78, 19, 78, 78, 78, 84, 78, 93,
- 80, 86, 86, 13, 14, 78, 83, 78,
- 78, 78, 78, 78, 78, 84, 78, 80,
- 86, 86, 13, 14, 78, 83, 78, 78,
- 78, 78, 78, 78, 84, 78, 87, 78,
- 78, 78, 94, 89, 78, 14, 78, 83,
- 78, 78, 78, 78, 78, 87, 78, 83,
- 78, 78, 95, 78, 83, 78, 83, 78,
- 83, 78, 78, 78, 78, 83, 78, 87,
- 78, 96, 78, 94, 94, 78, 14, 78,
- 83, 78, 78, 78, 78, 78, 87, 78,
- 87, 78, 78, 78, 94, 94, 78, 14,
- 78, 83, 78, 78, 78, 78, 78, 87,
- 78, 97, 17, 98, 99, 13, 14, 78,
- 83, 78, 17, 98, 99, 13, 14, 78,
- 83, 78, 98, 98, 13, 14, 78, 83,
- 78, 100, 101, 101, 13, 14, 78, 83,
- 78, 88, 102, 78, 14, 78, 83, 78,
- 94, 94, 78, 14, 78, 83, 78, 88,
- 78, 94, 94, 78, 14, 78, 83, 78,
- 94, 102, 78, 14, 78, 83, 78, 90,
- 80, 86, 86, 13, 14, 78, 83, 78,
- 78, 78, 78, 78, 78, 84, 78, 90,
- 80, 91, 86, 13, 14, 78, 83, 78,
- 78, 19, 78, 78, 78, 84, 78, 11,
- 12, 12, 13, 14, 78, 79, 80, 86,
- 82, 13, 14, 78, 83, 78, 78, 78,
- 78, 78, 78, 84, 78, 104, 48, 105,
- 105, 24, 25, 103, 51, 103, 103, 103,
- 103, 103, 103, 55, 103, 48, 105, 105,
- 24, 25, 103, 51, 103, 103, 103, 103,
- 103, 103, 55, 103, 106, 103, 103, 103,
- 107, 108, 103, 25, 103, 51, 103, 103,
- 103, 103, 103, 106, 103, 47, 48, 109,
- 110, 24, 25, 103, 51, 103, 103, 26,
- 103, 103, 103, 55, 103, 106, 103, 103,
- 103, 111, 108, 103, 25, 103, 51, 103,
- 103, 103, 103, 103, 106, 103, 51, 103,
- 103, 112, 103, 51, 103, 51, 103, 51,
- 103, 103, 103, 103, 51, 103, 106, 103,
- 113, 103, 111, 111, 103, 25, 103, 51,
- 103, 103, 103, 103, 103, 106, 103, 106,
- 103, 103, 103, 111, 111, 103, 25, 103,
- 51, 103, 103, 103, 103, 103, 106, 103,
- 114, 30, 115, 116, 24, 25, 103, 51,
- 103, 30, 115, 116, 24, 25, 103, 51,
- 103, 115, 115, 24, 25, 103, 51, 103,
- 47, 48, 105, 105, 24, 25, 103, 51,
- 103, 103, 103, 103, 103, 103, 55, 103,
- 117, 118, 118, 24, 25, 103, 51, 103,
- 107, 119, 103, 25, 103, 51, 103, 111,
- 111, 103, 25, 103, 51, 103, 107, 103,
- 111, 111, 103, 25, 103, 51, 103, 111,
- 119, 103, 25, 103, 51, 103, 47, 48,
- 109, 105, 24, 25, 103, 51, 103, 103,
- 26, 103, 103, 103, 55, 103, 22, 23,
- 23, 24, 25, 120, 120, 120, 120, 26,
- 120, 22, 23, 23, 24, 25, 120, 122,
- 123, 124, 125, 35, 36, 121, 126, 121,
- 121, 37, 121, 121, 121, 127, 121, 128,
- 123, 125, 125, 35, 36, 121, 126, 121,
- 121, 121, 121, 121, 121, 127, 121, 123,
- 125, 125, 35, 36, 121, 126, 121, 121,
- 121, 121, 121, 121, 127, 121, 129, 121,
- 121, 121, 130, 131, 121, 36, 121, 126,
- 121, 121, 121, 121, 121, 129, 121, 122,
- 123, 124, 52, 35, 36, 121, 126, 121,
- 121, 37, 121, 121, 121, 127, 121, 129,
- 121, 121, 121, 132, 131, 121, 36, 121,
- 126, 121, 121, 121, 121, 121, 129, 121,
- 126, 121, 121, 133, 121, 126, 121, 126,
- 121, 126, 121, 121, 121, 121, 126, 121,
- 129, 121, 134, 121, 132, 132, 121, 36,
- 121, 126, 121, 121, 121, 121, 121, 129,
- 121, 129, 121, 121, 121, 132, 132, 121,
- 36, 121, 126, 121, 121, 121, 121, 121,
- 129, 121, 135, 40, 136, 137, 35, 36,
- 121, 126, 121, 40, 136, 137, 35, 36,
- 121, 126, 121, 136, 136, 35, 36, 121,
- 126, 121, 122, 123, 125, 125, 35, 36,
- 121, 126, 121, 121, 121, 121, 121, 121,
- 127, 121, 138, 139, 139, 35, 36, 121,
- 126, 121, 130, 140, 121, 36, 121, 126,
- 121, 132, 132, 121, 36, 121, 126, 121,
- 130, 121, 132, 132, 121, 36, 121, 126,
- 121, 132, 140, 121, 36, 121, 126, 121,
- 45, 46, 47, 48, 109, 105, 24, 25,
- 103, 51, 52, 52, 26, 103, 103, 45,
- 55, 103, 59, 141, 61, 62, 4, 1,
- 58, 63, 58, 58, 9, 58, 58, 58,
- 64, 58, 45, 46, 47, 48, 142, 143,
- 24, 144, 58, 145, 58, 52, 26, 58,
- 58, 45, 55, 58, 22, 146, 146, 24,
- 144, 58, 63, 58, 58, 26, 58, 145,
- 58, 58, 147, 58, 145, 58, 145, 58,
- 145, 58, 58, 58, 58, 145, 58, 45,
- 58, 71, 22, 146, 146, 24, 144, 58,
- 63, 58, 58, 58, 58, 58, 45, 58,
- 149, 148, 150, 150, 148, 43, 148, 151,
- 148, 150, 150, 148, 43, 148, 151, 148,
- 151, 148, 148, 152, 148, 151, 148, 151,
- 148, 151, 148, 148, 148, 148, 151, 148,
- 45, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 52, 120, 120, 120, 120, 45,
- 120, 0
-};
-
-static const unsigned char _indic_syllable_machine_trans_targs[] = {
- 39, 45, 50, 2, 51, 5, 6, 53,
- 57, 58, 39, 67, 11, 73, 68, 14,
- 15, 75, 80, 81, 84, 39, 89, 21,
- 95, 90, 98, 39, 24, 25, 97, 103,
- 39, 112, 30, 118, 113, 121, 33, 34,
- 120, 126, 39, 137, 39, 40, 60, 85,
- 87, 105, 106, 91, 107, 127, 128, 99,
- 135, 140, 39, 41, 43, 8, 59, 46,
- 54, 42, 1, 44, 48, 0, 47, 49,
- 52, 3, 4, 55, 7, 56, 39, 61,
- 63, 18, 83, 69, 76, 62, 9, 64,
- 78, 71, 65, 17, 82, 66, 10, 70,
- 72, 74, 12, 13, 77, 16, 79, 39,
- 86, 26, 88, 101, 93, 19, 104, 20,
- 92, 94, 96, 22, 23, 100, 27, 102,
- 39, 39, 108, 110, 28, 35, 114, 122,
- 109, 111, 124, 116, 29, 115, 117, 119,
- 31, 32, 123, 36, 125, 129, 130, 134,
- 131, 132, 37, 133, 39, 136, 38, 138,
- 139
-};
-
-static const char _indic_syllable_machine_trans_actions[] = {
- 1, 0, 2, 0, 2, 0, 0, 2,
- 2, 2, 3, 2, 0, 2, 0, 0,
- 0, 2, 2, 2, 2, 4, 2, 0,
- 5, 0, 5, 6, 0, 0, 5, 2,
- 7, 2, 0, 2, 0, 2, 0, 0,
- 2, 2, 8, 0, 11, 2, 2, 5,
- 0, 12, 12, 0, 2, 5, 2, 5,
- 2, 0, 13, 2, 0, 0, 2, 0,
- 2, 2, 0, 2, 2, 0, 0, 2,
- 2, 0, 0, 0, 0, 2, 14, 2,
- 0, 0, 2, 0, 2, 2, 0, 2,
- 2, 2, 2, 0, 2, 2, 0, 0,
- 2, 2, 0, 0, 0, 0, 2, 15,
- 5, 0, 5, 2, 2, 0, 5, 0,
- 0, 2, 5, 0, 0, 0, 0, 2,
- 16, 17, 2, 0, 0, 0, 0, 2,
- 2, 2, 2, 2, 0, 0, 2, 2,
- 0, 0, 0, 0, 2, 0, 18, 18,
- 0, 0, 0, 0, 19, 2, 0, 0,
- 0
-};
-
-static const char _indic_syllable_machine_to_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 9,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0
-};
-
-static const char _indic_syllable_machine_from_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 10,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0
-};
-
-static const short _indic_syllable_machine_eof_trans[] = {
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 22, 22, 28, 22, 22,
- 22, 22, 22, 22, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 1, 43, 0,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 104, 104, 104,
- 104, 104, 104, 104, 104, 104, 104, 104,
- 104, 104, 104, 104, 104, 104, 104, 104,
- 104, 121, 121, 122, 122, 122, 122, 122,
- 122, 122, 122, 122, 122, 122, 122, 122,
- 122, 122, 122, 122, 122, 122, 122, 104,
- 59, 59, 59, 59, 59, 59, 59, 149,
- 149, 149, 149, 149, 121
-};
-
-static const int indic_syllable_machine_start = 39;
-static const int indic_syllable_machine_first_final = 39;
-static const int indic_syllable_machine_error = -1;
-
-static const int indic_syllable_machine_en_main = 39;
-
-
-#line 46 "hb-ot-shape-complex-indic-machine.rl"
-
-
-
-#line 102 "hb-ot-shape-complex-indic-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_indic (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 440 "hb-ot-shape-complex-indic-machine.hh"
- {
- cs = indic_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 122 "hb-ot-shape-complex-indic-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 456 "hb-ot-shape-complex-indic-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const unsigned char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _indic_syllable_machine_from_state_actions[cs] ) {
- case 10:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 470 "hb-ot-shape-complex-indic-machine.hh"
- }
-
- _keys = _indic_syllable_machine_trans_keys + (cs<<1);
- _inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
-
- _slen = _indic_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
- ( info[p].indic_category()) <= _keys[1] ?
- ( info[p].indic_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _indic_syllable_machine_trans_targs[_trans];
-
- if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _indic_syllable_machine_trans_actions[_trans] ) {
- case 2:
-#line 1 "NONE"
- {te = p+1;}
- break;
- case 11:
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
- {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
- break;
- case 13:
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
- break;
- case 14:
-#line 94 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
- break;
- case 17:
-#line 95 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
- break;
- case 19:
-#line 96 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
- break;
- case 15:
-#line 97 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_broken_cluster); }}
- break;
- case 16:
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
- break;
- case 1:
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
- break;
- case 3:
-#line 94 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
- break;
- case 7:
-#line 95 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
- break;
- case 8:
-#line 96 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
- break;
- case 4:
-#line 97 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); }}
- break;
- case 6:
-#line 1 "NONE"
- { switch( act ) {
- case 1:
- {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
- break;
- case 5:
- {{p = ((te))-1;} found_syllable (indic_broken_cluster); }
- break;
- case 6:
- {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
- break;
- }
- }
- break;
- case 18:
-#line 1 "NONE"
- {te = p+1;}
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
- {act = 1;}
- break;
- case 5:
-#line 1 "NONE"
- {te = p+1;}
-#line 97 "hb-ot-shape-complex-indic-machine.rl"
- {act = 5;}
- break;
- case 12:
-#line 1 "NONE"
- {te = p+1;}
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
- {act = 6;}
- break;
-#line 573 "hb-ot-shape-complex-indic-machine.hh"
- }
-
-_again:
- switch ( _indic_syllable_machine_to_state_actions[cs] ) {
- case 9:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 582 "hb-ot-shape-complex-indic-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _indic_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 130 "hb-ot-shape-complex-indic-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
deleted file mode 100644
index 326aa9f96e..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
+++ /dev/null
@@ -1,501 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- * ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
- *
- * on files with these headers:
- *
- * # IndicSyllabicCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # IndicPositionalCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # Blocks-14.0.0.txt
- * # Date: 2021-01-22, 23:29:00 GMT [KW]
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-indic.hh"
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-macros"
-
-#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 17 chars; Avagraha */
-#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 91 chars; Bindu */
-#define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */
-#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 59 chars; Cantillation_Mark */
-#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2206 chars; Consonant */
-#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 14 chars; Consonant_Dead */
-#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 70 chars; Consonant_Final */
-#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */
-#define ISC_CIP INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED /* 1 chars; Consonant_Initial_Postfixed */
-#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */
-#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 31 chars; Consonant_Medial */
-#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 22 chars; Consonant_Placeholder */
-#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 3 chars; Consonant_Preceding_Repha */
-#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 10 chars; Consonant_Prefixed */
-#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 94 chars; Consonant_Subjoined */
-#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 1 chars; Consonant_Succeeding_Repha */
-#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 8 chars; Consonant_With_Stacker */
-#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 3 chars; Gemination_Mark */
-#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 12 chars; Invisible_Stacker */
-#define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */
-#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
-#define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */
-#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 32 chars; Nukta */
-#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 491 chars; Number */
-#define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */
-#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
-#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 25 chars; Pure_Killer */
-#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */
-#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 25 chars; Syllable_Modifier */
-#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */
-#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */
-#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 27 chars; Virama */
-#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 35 chars; Visarga */
-#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */
-#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 686 chars; Vowel_Dependent */
-#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 486 chars; Vowel_Independent */
-
-#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 352 chars; Bottom */
-#define IMC_BL INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT /* 1 chars; Bottom_And_Left */
-#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 4 chars; Bottom_And_Right */
-#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 64 chars; Left */
-#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 22 chars; Left_And_Right */
-#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
-#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */
-#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 290 chars; Right */
-#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 418 chars; Top */
-#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */
-#define IMC_TBL INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT /* 2 chars; Top_And_Bottom_And_Left */
-#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
-#define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */
-#define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 4 chars; Top_And_Left_And_Right */
-#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 13 chars; Top_And_Right */
-#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 19 chars; Visual_Order_Left */
-
-#pragma GCC diagnostic pop
-
-#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
-
-
-static const uint16_t indic_table[] = {
-
-
-#define indic_offset_0x0028u 0
-
-
- /* Basic Latin */
-
- /* 0028 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x), _(x,x),
- /* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0038 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x00b0u 24
-
-
- /* Latin-1 Supplement */
-
- /* 00B0 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x),
-
-#define indic_offset_0x0900u 64
-
-
- /* Devanagari */
-
- /* 0900 */ _(Bi,T), _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0920 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0928 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,B), _(A,x), _(M,R), _(M,L),
- /* 0940 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T),
- /* 0948 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(M,L), _(M,R),
- /* 0950 */ _(x,x), _(Ca,T), _(Ca,B), _(x,T), _(x,T), _(M,T), _(M,B), _(M,B),
- /* 0958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0970 */ _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0978 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
-
- /* Bengali */
-
- /* 0980 */ _(CP,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
- /* 0990 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 09A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 09A8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 09B0 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
- /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L),
- /* 09C0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
- /* 09C8 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,B), _(CD,x), _(x,x),
- /* 09D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
- /* 09D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
- /* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(Bi,x), _(x,x), _(SM,T), _(x,x),
-
- /* Gurmukhi */
-
- /* 0A00 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0A08 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
- /* 0A10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0A18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0A28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0A30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x),
- /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(x,x), _(M,R), _(M,L),
- /* 0A40 */ _(M,R), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T),
- /* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x),
- /* 0A50 */ _(x,x), _(Ca,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x),
- /* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0A70 */ _(Bi,T), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,B), _(x,x), _(x,x),
- /* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Gujarati */
-
- /* 0A80 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x),
- /* 0A90 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0A98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0AA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0AA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0AB0 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
- /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L),
- /* 0AC0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(x,x), _(M,T),
- /* 0AC8 */ _(M,T), _(M,TR), _(x,x), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x),
- /* 0AD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AF8 */ _(x,x), _(C,x), _(Ca,T), _(Ca,T), _(Ca,T), _(N,T), _(N,T), _(N,T),
-
- /* Oriya */
-
- /* 0B00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
- /* 0B10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0B28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0B30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
- /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T),
- /* 0B40 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
- /* 0B48 */ _(M,TL), _(x,x), _(x,x), _(M,LR),_(M,TLR), _(V,B), _(x,x), _(x,x),
- /* 0B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,T), _(M,TR),
- /* 0B58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
- /* 0B60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0B68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0B70 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Tamil */
-
- /* 0B80 */ _(x,x), _(x,x), _(Bi,T), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0B88 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(VI,x),
- /* 0B90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(x,x), _(x,x),
- /* 0B98 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x), _(C,x),
- /* 0BA0 */ _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
- /* 0BA8 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
- /* 0BB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0BB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R),
- /* 0BC0 */ _(M,T), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L),
- /* 0BC8 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(x,x), _(x,x),
- /* 0BD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
- /* 0BD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0BE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0BE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0BF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Telugu */
-
- /* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R), _(Bi,T), _(VI,x), _(VI,x), _(VI,x),
- /* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
- /* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,T), _(M,T),
- /* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T),
- /* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x),
- /* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x),
- /* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(CD,x), _(x,x), _(x,x),
- /* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0C78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Kannada */
-
- /* 0C80 */ _(Bi,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
- /* 0C90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0C98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0CA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0CA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0CB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
- /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T),
- /* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR),
- /* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x),
- /* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x),
- /* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(C,x), _(x,x),
- /* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0CF0 */ _(x,x),_(CWS,x),_(CWS,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Malayalam */
-
- /* 0D00 */ _(Bi,T), _(Bi,T), _(Bi,R), _(Vs,R), _(Bi,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
- /* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D38 */ _(C,x), _(C,x), _(C,x), _(PK,T), _(PK,T), _(A,x), _(M,R), _(M,R),
- /* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L),
- /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,T), _(x,x),
- /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(M,R),
- /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
- /* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0D78 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x),
-
- /* Sinhala */
-
- /* 0D80 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x),
- /* 0D98 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DB0 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DB8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(x,x),
- /* 0DC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
- /* 0DC8 */ _(x,x), _(x,x), _(V,T), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
- /* 0DD0 */ _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), _(x,x), _(M,B), _(x,x),
- /* 0DD8 */ _(M,R), _(M,L), _(M,TL), _(M,L), _(M,LR),_(M,TLR), _(M,LR), _(M,R),
- /* 0DE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x1000u 1336
-
-
- /* Myanmar */
-
- /* 1000 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1008 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1010 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1020 */ _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 1028 */ _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), _(M,T), _(M,T), _(M,B),
- /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,T), _(TM,B),
- /* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R),_(CM,TBL), _(CM,B), _(CM,B), _(C,x),
- /* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(CP,x), _(x,x), _(x,x), _(CP,x), _(x,x),
- /* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R),
- /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,B), _(CM,B),
- /* 1060 */ _(CM,B), _(C,x), _(M,R), _(TM,R), _(TM,R), _(C,x), _(C,x), _(M,R),
- /* 1068 */ _(M,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(C,x), _(C,x),
- /* 1070 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(C,x), _(C,x), _(C,x),
- /* 1078 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1080 */ _(C,x), _(C,x), _(CM,B), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,R),
- /* 1088 */ _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,B), _(C,x), _(TM,R),
- /* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 1098 */ _(Nd,x), _(Nd,x), _(TM,R), _(TM,R), _(M,R), _(M,T), _(x,x), _(x,x),
-
-#define indic_offset_0x1780u 1496
-
-
- /* Khmer */
-
- /* 1780 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1788 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1790 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1798 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 17A0 */ _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(M,R), _(M,T),
- /* 17B8 */ _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,TL),_(M,TLR),
- /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,T), _(Vs,R),
- /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(SM,T),_(CSR,T), _(CK,T), _(SM,T), _(SM,T),
- /* 17D0 */ _(SM,T), _(PK,T), _(IS,x), _(SM,T), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(SM,T), _(x,x), _(x,x),
- /* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 17E8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x1cd0u 1608
-
-
- /* Vedic Extensions */
-
- /* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B),
- /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B),
- /* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O),
- /* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x),
- /* 1CF0 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(Ca,T),_(CWS,x),_(CWS,x), _(Ca,R),
- /* 1CF8 */ _(Ca,x), _(Ca,x), _(CP,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x2008u 1656
-
-
- /* General Punctuation */
-
- /* 2008 */ _(x,x), _(x,x), _(x,x), _(x,x),_(ZWNJ,x),_(ZWJ,x), _(x,x), _(x,x),
- /* 2010 */ _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x2070u 1672
-
-
- /* Superscripts and Subscripts */
-
- /* 2070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(SM,x), _(x,x), _(x,x), _(x,x),
- /* 2078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 2080 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0xa8e0u 1696
-
-
- /* Devanagari Extended */
-
- /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
- /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
- /* A8F0 */ _(Ca,T), _(Ca,T), _(Bi,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(M,T),
-
-#define indic_offset_0xa9e0u 1728
-
-
- /* Myanmar Extended-B */
-
- /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), _(x,x), _(C,x),
- /* A9E8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* A9F8 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
-
-#define indic_offset_0xaa60u 1760
-
-
- /* Myanmar Extended-A */
-
- /* AA60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* AA68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x),
- /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x),
-
-}; /* Table items: 1792; occupancy: 71% */
-
-uint16_t
-hb_indic_get_categories (hb_codepoint_t u)
-{
- switch (u >> 12)
- {
- case 0x0u:
- if (unlikely (u == 0x00A0u)) return _(CP,x);
- if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
- if (hb_in_range<hb_codepoint_t> (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
- break;
-
- case 0x1u:
- if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
- break;
-
- case 0x2u:
- if (unlikely (u == 0x25CCu)) return _(CP,x);
- if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
- if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
- break;
-
- case 0xAu:
- if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8FFu)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
- if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
- if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
- break;
-
- default:
- break;
- }
- return _(x,x);
-}
-
-#undef _
-
-#undef ISC_A
-#undef ISC_Bi
-#undef ISC_BJN
-#undef ISC_Ca
-#undef ISC_C
-#undef ISC_CD
-#undef ISC_CF
-#undef ISC_CHL
-#undef ISC_CIP
-#undef ISC_CK
-#undef ISC_CM
-#undef ISC_CP
-#undef ISC_CPR
-#undef ISC_CPrf
-#undef ISC_CS
-#undef ISC_CSR
-#undef ISC_CWS
-#undef ISC_GM
-#undef ISC_IS
-#undef ISC_ZWJ
-#undef ISC_ML
-#undef ISC_ZWNJ
-#undef ISC_N
-#undef ISC_Nd
-#undef ISC_NJ
-#undef ISC_x
-#undef ISC_PK
-#undef ISC_RS
-#undef ISC_SM
-#undef ISC_TL
-#undef ISC_TM
-#undef ISC_V
-#undef ISC_Vs
-#undef ISC_Vo
-#undef ISC_M
-#undef ISC_VI
-
-#undef IMC_B
-#undef IMC_BL
-#undef IMC_BR
-#undef IMC_L
-#undef IMC_LR
-#undef IMC_x
-#undef IMC_O
-#undef IMC_R
-#undef IMC_T
-#undef IMC_TB
-#undef IMC_TBL
-#undef IMC_TBR
-#undef IMC_TL
-#undef IMC_TLR
-#undef IMC_TR
-#undef IMC_VOL
-
-#endif
-
-/* == End of generated table == */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.hh
deleted file mode 100644
index da77a2887c..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.hh
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-syllabic.hh"
-
-
-/* buffer var allocations */
-#define indic_category() complex_var_u8_category() /* indic_category_t */
-#define indic_position() complex_var_u8_auxiliary() /* indic_position_t */
-
-
-/* Cateories used in the OpenType spec:
- * https://docs.microsoft.com/en-us/typography/script-development/devanagari
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum indic_category_t {
- OT_X = 0,
- OT_C = 1,
- OT_V = 2,
- OT_N = 3,
- OT_H = 4,
- OT_ZWNJ = 5,
- OT_ZWJ = 6,
- OT_M = 7,
- OT_SM = 8,
- /* OT_VD = 9, UNUSED; we use OT_A instead. */
- OT_A = 10,
- OT_PLACEHOLDER = 11,
- OT_DOTTEDCIRCLE = 12,
- OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
- OT_Coeng = 14, /* Khmer-style Virama. */
- OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
- OT_Ra = 16,
- OT_CM = 17, /* Consonant-Medial. */
- OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
- OT_CS = 19,
-
- /* The following are used by Khmer & Myanmar shapers. Defined
- * here for them to share. */
- OT_VAbv = 26,
- OT_VBlw = 27,
- OT_VPre = 28,
- OT_VPst = 29,
-};
-
-#define MEDIAL_FLAGS (FLAG (OT_CM))
-
-/* Note:
- *
- * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
- * cannot happen in a consonant syllable. The plus side however is, we can call the
- * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
-#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
-
-
-/* Visual positions in a syllable from left to right. */
-enum indic_position_t {
- POS_START = 0,
-
- POS_RA_TO_BECOME_REPH = 1,
- POS_PRE_M = 2,
- POS_PRE_C = 3,
-
- POS_BASE_C = 4,
- POS_AFTER_MAIN = 5,
-
- POS_ABOVE_C = 6,
-
- POS_BEFORE_SUB = 7,
- POS_BELOW_C = 8,
- POS_AFTER_SUB = 9,
-
- POS_BEFORE_POST = 10,
- POS_POST_C = 11,
- POS_AFTER_POST = 12,
-
- POS_FINAL_C = 13,
- POS_SMVD = 14,
-
- POS_END = 15
-};
-
-/* Categories used in IndicSyllabicCategory.txt from UCD. */
-enum indic_syllabic_category_t {
- INDIC_SYLLABIC_CATEGORY_OTHER = OT_X,
-
- INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Symbol,
- INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
- INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* Don't care. */
- INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK = OT_A,
- INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER = OT_M, /* U+17CD only. */
- INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_PLACEHOLDER,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA = OT_Repha,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */
- INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_CS,
- INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
- INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng,
- INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ,
- INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_NON_JOINER = OT_ZWNJ,
- INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
- INDIC_SYLLABIC_CATEGORY_NUMBER = OT_PLACEHOLDER,
- INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* Don't care. */
- INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_M, /* Is like a vowel matra. */
- INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS,
- INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_SM,
- INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N,
- INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
- INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM,
- INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V,
- INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M,
- INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V
-};
-
-/* Categories used in IndicSMatraCategory.txt from UCD */
-enum indic_matra_category_t {
- INDIC_MATRA_CATEGORY_NOT_APPLICABLE = POS_END,
-
- INDIC_MATRA_CATEGORY_LEFT = POS_PRE_C,
- INDIC_MATRA_CATEGORY_TOP = POS_ABOVE_C,
- INDIC_MATRA_CATEGORY_BOTTOM = POS_BELOW_C,
- INDIC_MATRA_CATEGORY_RIGHT = POS_POST_C,
-
- /* These should resolve to the position of the last part of the split sequence. */
- INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT = INDIC_MATRA_CATEGORY_TOP,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
-
- INDIC_MATRA_CATEGORY_OVERSTRUCK = POS_AFTER_MAIN,
- INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = POS_PRE_M
-};
-
-#define INDIC_COMBINE_CATEGORIES(S,M) \
- ( \
- static_assert_expr (S < 255 && M < 255) + \
- ( S | \
- ( \
- ( \
- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
- S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
- S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
- S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
- S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
- false \
- ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
- ) << 8 \
- ) \
- ) \
- )
-
-HB_INTERNAL uint16_t
-hb_indic_get_categories (hb_codepoint_t u);
-
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
- /* If it ligated, all bets are off. */
- if (_hb_glyph_info_ligated (&info)) return false;
- return !!(FLAG_UNSAFE (info.indic_category()) & flags);
-}
-
-static inline bool
-is_joiner (const hb_glyph_info_t &info)
-{
- return is_one_of (info, JOINER_FLAGS);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, CONSONANT_FLAGS);
-}
-
-static inline bool
-is_halant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, FLAG (OT_H));
-}
-
-#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
-
-#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
-#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
-#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
-#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
-#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
-#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
-#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
-#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
-#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
-#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
-
-
-#define MATRA_POS_LEFT(u) POS_PRE_M
-#define MATRA_POS_RIGHT(u) ( \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_BENG(u) ? POS_AFTER_POST : \
- IS_GURU(u) ? POS_AFTER_POST : \
- IS_GUJR(u) ? POS_AFTER_POST : \
- IS_ORYA(u) ? POS_AFTER_POST : \
- IS_TAML(u) ? POS_AFTER_POST : \
- IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
- IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
- IS_MLYM(u) ? POS_AFTER_POST : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-#define MATRA_POS_TOP(u) ( /* BENG and MLYM don't have top matras. */ \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
- IS_GUJR(u) ? POS_AFTER_SUB : \
- IS_ORYA(u) ? POS_AFTER_MAIN : \
- IS_TAML(u) ? POS_AFTER_SUB : \
- IS_TELU(u) ? POS_BEFORE_SUB : \
- IS_KNDA(u) ? POS_BEFORE_SUB : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-#define MATRA_POS_BOTTOM(u) ( \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_BENG(u) ? POS_AFTER_SUB : \
- IS_GURU(u) ? POS_AFTER_POST : \
- IS_GUJR(u) ? POS_AFTER_POST : \
- IS_ORYA(u) ? POS_AFTER_SUB : \
- IS_TAML(u) ? POS_AFTER_POST : \
- IS_TELU(u) ? POS_BEFORE_SUB : \
- IS_KNDA(u) ? POS_BEFORE_SUB : \
- IS_MLYM(u) ? POS_AFTER_POST : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-
-static inline indic_position_t
-matra_position_indic (hb_codepoint_t u, indic_position_t side)
-{
- switch ((int) side)
- {
- case POS_PRE_C: return MATRA_POS_LEFT (u);
- case POS_POST_C: return MATRA_POS_RIGHT (u);
- case POS_ABOVE_C: return MATRA_POS_TOP (u);
- case POS_BELOW_C: return MATRA_POS_BOTTOM (u);
- }
- return side;
-}
-
-/* XXX
- * This is a hack for now. We should move this data into the main Indic table.
- * Or completely remove it and just check in the tables.
- */
-static const hb_codepoint_t ra_chars[] = {
- 0x0930u, /* Devanagari */
- 0x09B0u, /* Bengali */
- 0x09F0u, /* Bengali */
- 0x0A30u, /* Gurmukhi */ /* No Reph */
- 0x0AB0u, /* Gujarati */
- 0x0B30u, /* Oriya */
- 0x0BB0u, /* Tamil */ /* No Reph */
- 0x0C30u, /* Telugu */ /* Reph formed only with ZWJ */
- 0x0CB0u, /* Kannada */
- 0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
-
- 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
-};
-
-static inline bool
-is_ra (hb_codepoint_t u)
-{
- return hb_array (ra_chars).lfind (u);
-}
-
-static inline void
-set_indic_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- indic_category_t cat = (indic_category_t) (type & 0xFFu);
- indic_position_t pos = (indic_position_t) (type >> 8);
-
-
- /*
- * Re-assign category
- */
-
- /* The following act more like the Bindus. */
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
- cat = OT_SM;
- /* The following act like consonants. */
- else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
- 0x1CF5u, 0x1CF6u)))
- cat = OT_C;
- /* TODO: The following should only be allowed after a Visarga.
- * For now, just treat them like regular tone marks. */
- else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
- cat = OT_A;
- /* TODO: The following should only be allowed after some of
- * the nasalization marks, maybe only for U+1CE9..U+1CF1.
- * For now, just treat them like tone marks. */
- else if (unlikely (u == 0x1CEDu))
- cat = OT_A;
- /* The following take marks in standalone clusters, similar to Avagraha. */
- else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
- 0x1CE9u, 0x1CECu,
- 0x1CEEu, 0x1CF1u)))
- {
- cat = OT_Symbol;
- static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
- }
- else if (unlikely (u == 0x0A51u))
- {
- /* https://github.com/harfbuzz/harfbuzz/issues/524 */
- cat = OT_M;
- pos = POS_BELOW_C;
- }
-
- /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
- * so the Indic shaper needs to know their categories. */
- else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
- else if (unlikely (u == 0x1133Bu || u == 0x1133Cu)) cat = OT_N;
-
- else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
- else if (unlikely (u == 0x0B55u)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/2849 */
-
- else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
- else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */
- else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
- else if (unlikely (u == 0x0D04u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/3511 */
- else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
- cat = OT_PLACEHOLDER;
- else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
- /*
- * Re-assign position.
- */
-
- if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
- {
- pos = POS_BASE_C;
- if (is_ra (u))
- cat = OT_Ra;
- }
- else if (cat == OT_M)
- {
- pos = matra_position_indic (u, pos);
- }
- else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
- {
- pos = POS_SMVD;
- }
-
- if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
-
-
-
- info.indic_category() = cat;
- info.indic_position() = pos;
-}
-
-struct hb_indic_would_substitute_feature_t
-{
- void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
- {
- zero_context = zero_context_;
- map->get_stage_lookups (0/*GSUB*/,
- map->get_feature_stage (0/*GSUB*/, feature_tag),
- &lookups, &count);
- }
-
- bool would_substitute (const hb_codepoint_t *glyphs,
- unsigned int glyphs_count,
- hb_face_t *face) const
- {
- for (unsigned int i = 0; i < count; i++)
- if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
- return true;
- return false;
- }
-
- private:
- const hb_ot_map_t::lookup_map_t *lookups;
- unsigned int count;
- bool zero_context;
-};
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer-machine.hh
deleted file mode 100644
index c52f72f394..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer-machine.hh
+++ /dev/null
@@ -1,396 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-khmer-machine.rl"
-/*
- * 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 HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-
-#include "hb.hh"
-
-enum khmer_syllable_type_t {
- khmer_consonant_syllable,
- khmer_broken_cluster,
- khmer_non_khmer_cluster,
-};
-
-
-#line 42 "hb-ot-shape-complex-khmer-machine.hh"
-#define khmer_syllable_machine_ex_C 1u
-#define khmer_syllable_machine_ex_Coeng 14u
-#define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u
-#define khmer_syllable_machine_ex_PLACEHOLDER 11u
-#define khmer_syllable_machine_ex_Ra 16u
-#define khmer_syllable_machine_ex_Robatic 20u
-#define khmer_syllable_machine_ex_V 2u
-#define khmer_syllable_machine_ex_VAbv 26u
-#define khmer_syllable_machine_ex_VBlw 27u
-#define khmer_syllable_machine_ex_VPre 28u
-#define khmer_syllable_machine_ex_VPst 29u
-#define khmer_syllable_machine_ex_Xgroup 21u
-#define khmer_syllable_machine_ex_Ygroup 22u
-#define khmer_syllable_machine_ex_ZWJ 6u
-#define khmer_syllable_machine_ex_ZWNJ 5u
-
-
-#line 60 "hb-ot-shape-complex-khmer-machine.hh"
-static const unsigned char _khmer_syllable_machine_trans_keys[] = {
- 5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u,
- 5u, 26u, 5u, 21u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u,
- 5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 29u, 5u, 29u, 5u, 29u, 5u, 29u,
- 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 26u, 5u, 29u,
- 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 5u, 29u,
- 0
-};
-
-static const char _khmer_syllable_machine_key_spans[] = {
- 22, 17, 22, 17, 16, 17, 22, 17,
- 22, 17, 17, 22, 17, 16, 17, 22,
- 17, 22, 17, 22, 29, 25, 25, 25,
- 1, 18, 25, 25, 25, 16, 22, 25,
- 25, 1, 18, 25, 25, 16, 25, 25
-};
-
-static const short _khmer_syllable_machine_index_offsets[] = {
- 0, 23, 41, 64, 82, 99, 117, 140,
- 158, 181, 199, 217, 240, 258, 275, 293,
- 316, 334, 357, 375, 398, 428, 454, 480,
- 506, 508, 527, 553, 579, 605, 622, 645,
- 671, 697, 699, 718, 744, 770, 787, 813
-};
-
-static const char _khmer_syllable_machine_indicies[] = {
- 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 2,
- 3, 0, 0, 0, 0, 4, 0, 1,
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 3,
- 0, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 3, 0, 0, 0, 0, 4, 0,
- 5, 5, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 4, 0, 6, 6, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 6, 0, 7, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 8, 0, 9, 9, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 10, 0, 0,
- 0, 0, 4, 0, 9, 9, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 10, 0, 11, 11,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 12, 0,
- 0, 0, 0, 4, 0, 11, 11, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 12, 0, 14,
- 14, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 15,
- 13, 14, 14, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 15, 16, 16, 16, 16, 17, 16,
- 18, 18, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 17, 16, 19, 19, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 19, 16, 20, 20, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 21, 16, 22, 22, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 23, 16, 16,
- 16, 16, 17, 16, 22, 22, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 23, 16, 24, 24,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 25, 16,
- 16, 16, 16, 17, 16, 24, 24, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 25, 16, 14,
- 14, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 26, 15,
- 16, 16, 16, 16, 17, 16, 28, 28,
- 27, 27, 29, 29, 27, 27, 27, 27,
- 2, 2, 27, 30, 27, 28, 27, 27,
- 27, 27, 15, 19, 27, 27, 27, 17,
- 23, 25, 21, 27, 32, 32, 31, 31,
- 31, 31, 31, 31, 31, 33, 31, 31,
- 31, 31, 31, 2, 3, 6, 31, 31,
- 31, 4, 10, 12, 8, 31, 34, 34,
- 31, 31, 31, 31, 31, 31, 31, 35,
- 31, 31, 31, 31, 31, 31, 3, 6,
- 31, 31, 31, 4, 10, 12, 8, 31,
- 5, 5, 31, 31, 31, 31, 31, 31,
- 31, 35, 31, 31, 31, 31, 31, 31,
- 4, 6, 31, 31, 31, 31, 31, 31,
- 8, 31, 6, 31, 7, 7, 31, 31,
- 31, 31, 31, 31, 31, 35, 31, 31,
- 31, 31, 31, 31, 8, 6, 31, 36,
- 36, 31, 31, 31, 31, 31, 31, 31,
- 35, 31, 31, 31, 31, 31, 31, 10,
- 6, 31, 31, 31, 4, 31, 31, 8,
- 31, 37, 37, 31, 31, 31, 31, 31,
- 31, 31, 35, 31, 31, 31, 31, 31,
- 31, 12, 6, 31, 31, 31, 4, 10,
- 31, 8, 31, 34, 34, 31, 31, 31,
- 31, 31, 31, 31, 33, 31, 31, 31,
- 31, 31, 31, 3, 6, 31, 31, 31,
- 4, 10, 12, 8, 31, 28, 28, 31,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 28, 31, 14, 14,
- 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 15, 38,
- 38, 38, 38, 17, 38, 40, 40, 39,
- 39, 39, 39, 39, 39, 39, 41, 39,
- 39, 39, 39, 39, 39, 15, 19, 39,
- 39, 39, 17, 23, 25, 21, 39, 18,
- 18, 39, 39, 39, 39, 39, 39, 39,
- 41, 39, 39, 39, 39, 39, 39, 17,
- 19, 39, 39, 39, 39, 39, 39, 21,
- 39, 19, 39, 20, 20, 39, 39, 39,
- 39, 39, 39, 39, 41, 39, 39, 39,
- 39, 39, 39, 21, 19, 39, 42, 42,
- 39, 39, 39, 39, 39, 39, 39, 41,
- 39, 39, 39, 39, 39, 39, 23, 19,
- 39, 39, 39, 17, 39, 39, 21, 39,
- 43, 43, 39, 39, 39, 39, 39, 39,
- 39, 41, 39, 39, 39, 39, 39, 39,
- 25, 19, 39, 39, 39, 17, 23, 39,
- 21, 39, 44, 44, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 44, 39, 45, 45, 39, 39, 39,
- 39, 39, 39, 39, 30, 39, 39, 39,
- 39, 39, 26, 15, 19, 39, 39, 39,
- 17, 23, 25, 21, 39, 40, 40, 39,
- 39, 39, 39, 39, 39, 39, 30, 39,
- 39, 39, 39, 39, 39, 15, 19, 39,
- 39, 39, 17, 23, 25, 21, 39, 0
-};
-
-static const char _khmer_syllable_machine_trans_targs[] = {
- 20, 1, 28, 22, 23, 3, 24, 5,
- 25, 7, 26, 9, 27, 20, 10, 31,
- 20, 32, 12, 33, 14, 34, 16, 35,
- 18, 36, 39, 20, 21, 30, 37, 20,
- 0, 29, 2, 4, 6, 8, 20, 20,
- 11, 13, 15, 17, 38, 19
-};
-
-static const char _khmer_syllable_machine_trans_actions[] = {
- 1, 0, 2, 2, 2, 0, 0, 0,
- 2, 0, 2, 0, 2, 3, 0, 4,
- 5, 2, 0, 0, 0, 2, 0, 2,
- 0, 2, 4, 8, 2, 9, 0, 10,
- 0, 0, 0, 0, 0, 0, 11, 12,
- 0, 0, 0, 0, 4, 0
-};
-
-static const char _khmer_syllable_machine_to_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const char _khmer_syllable_machine_from_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const unsigned char _khmer_syllable_machine_eof_trans[] = {
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 14, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 0, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 39, 40,
- 40, 40, 40, 40, 40, 40, 40, 40
-};
-
-static const int khmer_syllable_machine_start = 20;
-static const int khmer_syllable_machine_first_final = 20;
-static const int khmer_syllable_machine_error = -1;
-
-static const int khmer_syllable_machine_en_main = 20;
-
-
-#line 43 "hb-ot-shape-complex-khmer-machine.rl"
-
-
-
-#line 86 "hb-ot-shape-complex-khmer-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_khmer (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act HB_UNUSED;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 266 "hb-ot-shape-complex-khmer-machine.hh"
- {
- cs = khmer_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 106 "hb-ot-shape-complex-khmer-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 282 "hb-ot-shape-complex-khmer-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
- case 7:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 296 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
- _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
- _inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
-
- _slen = _khmer_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
- ( info[p].khmer_category()) <= _keys[1] ?
- ( info[p].khmer_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _khmer_syllable_machine_trans_targs[_trans];
-
- if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
- case 2:
-#line 1 "NONE"
- {te = p+1;}
- break;
- case 8:
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p+1;{ found_syllable (khmer_non_khmer_cluster); }}
- break;
- case 10:
-#line 80 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (khmer_consonant_syllable); }}
- break;
- case 12:
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (khmer_broken_cluster); }}
- break;
- case 11:
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (khmer_non_khmer_cluster); }}
- break;
- case 1:
-#line 80 "hb-ot-shape-complex-khmer-machine.rl"
- {{p = ((te))-1;}{ found_syllable (khmer_consonant_syllable); }}
- break;
- case 5:
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
- {{p = ((te))-1;}{ found_syllable (khmer_broken_cluster); }}
- break;
- case 3:
-#line 1 "NONE"
- { switch( act ) {
- case 2:
- {{p = ((te))-1;} found_syllable (khmer_broken_cluster); }
- break;
- case 3:
- {{p = ((te))-1;} found_syllable (khmer_non_khmer_cluster); }
- break;
- }
- }
- break;
- case 4:
-#line 1 "NONE"
- {te = p+1;}
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
- {act = 2;}
- break;
- case 9:
-#line 1 "NONE"
- {te = p+1;}
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
- {act = 3;}
- break;
-#line 366 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
-_again:
- switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
- case 6:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 375 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _khmer_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 114 "hb-ot-shape-complex-khmer-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.hh
deleted file mode 100644
index 35bfbb64d5..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.hh
+++ /dev/null
@@ -1,115 +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
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-indic.hh"
-
-
-/* buffer var allocations */
-#define khmer_category() indic_category() /* khmer_category_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum khmer_category_t
-{
- OT_Robatic = 20,
- OT_Xgroup = 21,
- OT_Ygroup = 22,
- //OT_VAbv = 26,
- //OT_VBlw = 27,
- //OT_VPre = 28,
- //OT_VPst = 29,
-};
-
-using khmer_position_t = indic_position_t;
-
-static inline void
-set_khmer_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- khmer_category_t cat = (khmer_category_t) (type & 0xFFu);
- khmer_position_t pos = (khmer_position_t) (type >> 8);
-
-
- /*
- * Re-assign category
- *
- * These categories are experimentally extracted from what Uniscribe allows.
- */
- switch (u)
- {
- case 0x179Au:
- cat = (khmer_category_t) OT_Ra;
- break;
-
- case 0x17CCu:
- case 0x17C9u:
- case 0x17CAu:
- cat = OT_Robatic;
- break;
-
- case 0x17C6u:
- case 0x17CBu:
- case 0x17CDu:
- case 0x17CEu:
- case 0x17CFu:
- case 0x17D0u:
- case 0x17D1u:
- cat = OT_Xgroup;
- break;
-
- case 0x17C7u:
- case 0x17C8u:
- case 0x17DDu:
- case 0x17D3u: /* Just guessing. Uniscribe doesn't categorize it. */
- cat = OT_Ygroup;
- break;
- }
-
- /*
- * Re-assign position.
- */
- if (cat == (khmer_category_t) OT_M)
- switch ((int) pos)
- {
- case POS_PRE_C: cat = (khmer_category_t) OT_VPre; break;
- case POS_BELOW_C: cat = (khmer_category_t) OT_VBlw; break;
- case POS_ABOVE_C: cat = (khmer_category_t) OT_VAbv; break;
- case POS_POST_C: cat = (khmer_category_t) OT_VPst; break;
- default: assert (0);
- }
-
- info.khmer_category() = cat;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
deleted file mode 100644
index f4ef33004d..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh
+++ /dev/null
@@ -1,492 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-myanmar-machine.rl"
-/*
- * 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 HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
-
-#include "hb.hh"
-
-enum myanmar_syllable_type_t {
- myanmar_consonant_syllable,
- myanmar_punctuation_cluster,
- myanmar_broken_cluster,
- myanmar_non_myanmar_cluster,
-};
-
-
-#line 43 "hb-ot-shape-complex-myanmar-machine.hh"
-#define myanmar_syllable_machine_ex_A 10u
-#define myanmar_syllable_machine_ex_As 18u
-#define myanmar_syllable_machine_ex_C 1u
-#define myanmar_syllable_machine_ex_CS 19u
-#define myanmar_syllable_machine_ex_D 32u
-#define myanmar_syllable_machine_ex_D0 20u
-#define myanmar_syllable_machine_ex_DB 3u
-#define myanmar_syllable_machine_ex_GB 11u
-#define myanmar_syllable_machine_ex_H 4u
-#define myanmar_syllable_machine_ex_IV 2u
-#define myanmar_syllable_machine_ex_MH 21u
-#define myanmar_syllable_machine_ex_ML 33u
-#define myanmar_syllable_machine_ex_MR 22u
-#define myanmar_syllable_machine_ex_MW 23u
-#define myanmar_syllable_machine_ex_MY 24u
-#define myanmar_syllable_machine_ex_P 31u
-#define myanmar_syllable_machine_ex_PT 25u
-#define myanmar_syllable_machine_ex_Ra 16u
-#define myanmar_syllable_machine_ex_V 8u
-#define myanmar_syllable_machine_ex_VAbv 26u
-#define myanmar_syllable_machine_ex_VBlw 27u
-#define myanmar_syllable_machine_ex_VPre 28u
-#define myanmar_syllable_machine_ex_VPst 29u
-#define myanmar_syllable_machine_ex_VS 30u
-#define myanmar_syllable_machine_ex_ZWJ 6u
-#define myanmar_syllable_machine_ex_ZWNJ 5u
-
-
-#line 72 "hb-ot-shape-complex-myanmar-machine.hh"
-static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
- 1u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
- 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
- 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u, 3u, 33u,
- 3u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
- 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
- 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u,
- 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 1u, 33u, 1u, 32u, 8u, 8u,
- 0
-};
-
-static const char _myanmar_syllable_machine_key_spans[] = {
- 33, 31, 25, 4, 25, 23, 21, 21,
- 31, 27, 27, 27, 31, 16, 31, 31,
- 27, 27, 27, 28, 27, 31, 31, 31,
- 31, 31, 25, 4, 25, 23, 21, 21,
- 31, 27, 27, 27, 31, 16, 31, 31,
- 31, 27, 27, 27, 28, 27, 31, 31,
- 31, 31, 31, 31, 31, 33, 32, 1
-};
-
-static const short _myanmar_syllable_machine_index_offsets[] = {
- 0, 34, 66, 92, 97, 123, 147, 169,
- 191, 223, 251, 279, 307, 339, 356, 388,
- 420, 448, 476, 504, 533, 561, 593, 625,
- 657, 689, 721, 747, 752, 778, 802, 824,
- 846, 878, 906, 934, 962, 994, 1011, 1043,
- 1075, 1107, 1135, 1163, 1191, 1220, 1248, 1280,
- 1312, 1344, 1376, 1408, 1440, 1472, 1506, 1539
-};
-
-static const char _myanmar_syllable_machine_indicies[] = {
- 1, 1, 2, 3, 4, 4, 0, 5,
- 0, 6, 1, 0, 0, 0, 0, 7,
- 0, 8, 9, 0, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 1,
- 21, 0, 23, 24, 25, 25, 22, 26,
- 22, 27, 22, 22, 22, 22, 22, 22,
- 22, 28, 22, 22, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 22, 22,
- 39, 22, 25, 25, 22, 26, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 40,
- 22, 22, 22, 22, 22, 22, 33, 22,
- 22, 22, 37, 22, 25, 25, 22, 26,
- 22, 25, 25, 22, 26, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 22, 22,
- 22, 37, 22, 41, 22, 25, 25, 22,
- 26, 22, 33, 22, 22, 22, 22, 22,
- 22, 22, 42, 22, 22, 22, 22, 22,
- 22, 33, 22, 25, 25, 22, 26, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 42, 22, 22, 22, 22, 22, 22, 33,
- 22, 25, 25, 22, 26, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 22, 23,
- 22, 25, 25, 22, 26, 22, 27, 22,
- 22, 22, 22, 22, 22, 22, 43, 22,
- 22, 44, 22, 22, 22, 33, 45, 22,
- 22, 37, 22, 22, 22, 43, 22, 23,
- 22, 25, 25, 22, 26, 22, 27, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 22, 22,
- 22, 37, 22, 23, 22, 25, 25, 22,
- 26, 22, 27, 22, 22, 22, 22, 22,
- 22, 22, 43, 22, 22, 22, 22, 22,
- 22, 33, 45, 22, 22, 37, 22, 23,
- 22, 25, 25, 22, 26, 22, 27, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 45, 22,
- 22, 37, 22, 23, 22, 25, 25, 22,
- 26, 22, 27, 22, 22, 22, 22, 22,
- 22, 22, 43, 22, 22, 22, 22, 22,
- 22, 33, 45, 22, 22, 37, 22, 22,
- 22, 43, 22, 1, 1, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 1, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 28, 22, 22, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 22,
- 22, 22, 39, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 46, 22, 22, 22, 22,
- 22, 22, 33, 34, 35, 36, 37, 22,
- 22, 22, 39, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 33, 34, 35, 36, 37, 22,
- 23, 22, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 33, 34,
- 35, 22, 37, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 33, 22, 35, 22, 37, 22,
- 23, 22, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 33, 34,
- 35, 36, 37, 46, 22, 23, 22, 25,
- 25, 22, 26, 22, 27, 22, 22, 22,
- 22, 22, 22, 22, 46, 22, 22, 22,
- 22, 22, 22, 33, 34, 35, 36, 37,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 29, 22, 31, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 46, 22, 22, 29, 22, 22, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 47, 22, 22, 29, 30, 31, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 29, 30, 31, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 24, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 28, 22, 22, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 49, 49, 48, 5, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 50, 48,
- 48, 48, 48, 48, 48, 14, 48, 48,
- 48, 18, 48, 49, 49, 48, 5, 48,
- 49, 49, 48, 5, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 48, 48, 48,
- 18, 48, 51, 48, 49, 49, 48, 5,
- 48, 14, 48, 48, 48, 48, 48, 48,
- 48, 52, 48, 48, 48, 48, 48, 48,
- 14, 48, 49, 49, 48, 5, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 52,
- 48, 48, 48, 48, 48, 48, 14, 48,
- 49, 49, 48, 5, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 48, 2, 48,
- 49, 49, 48, 5, 48, 6, 48, 48,
- 48, 48, 48, 48, 48, 53, 48, 48,
- 54, 48, 48, 48, 14, 55, 48, 48,
- 18, 48, 48, 48, 53, 48, 2, 48,
- 49, 49, 48, 5, 48, 6, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 48, 48, 48,
- 18, 48, 2, 48, 49, 49, 48, 5,
- 48, 6, 48, 48, 48, 48, 48, 48,
- 48, 53, 48, 48, 48, 48, 48, 48,
- 14, 55, 48, 48, 18, 48, 2, 48,
- 49, 49, 48, 5, 48, 6, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 55, 48, 48,
- 18, 48, 2, 48, 49, 49, 48, 5,
- 48, 6, 48, 48, 48, 48, 48, 48,
- 48, 53, 48, 48, 48, 48, 48, 48,
- 14, 55, 48, 48, 18, 48, 48, 48,
- 53, 48, 56, 56, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 56, 48, 2, 3, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 8, 48, 48, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 48,
- 48, 21, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 8, 48, 48, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 48, 48,
- 48, 21, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 57, 48, 48, 48, 48, 48,
- 48, 14, 15, 16, 17, 18, 48, 48,
- 48, 21, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 14, 15, 16, 17, 18, 48, 2,
- 48, 49, 49, 48, 5, 48, 6, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 14, 15, 16,
- 48, 18, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 14, 48, 16, 48, 18, 48, 2,
- 48, 49, 49, 48, 5, 48, 6, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 14, 15, 16,
- 17, 18, 57, 48, 2, 48, 49, 49,
- 48, 5, 48, 6, 48, 48, 48, 48,
- 48, 48, 48, 57, 48, 48, 48, 48,
- 48, 48, 14, 15, 16, 17, 18, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 10, 48, 12, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 57,
- 48, 48, 10, 48, 48, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 58,
- 48, 48, 10, 11, 12, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 10, 11, 12, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 3, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 8,
- 48, 48, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 23, 24, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 59,
- 22, 22, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 22, 22, 39, 22,
- 23, 60, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 28,
- 22, 22, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 22, 22, 22, 39, 22,
- 1, 1, 2, 3, 49, 49, 48, 5,
- 48, 6, 1, 48, 48, 48, 48, 1,
- 48, 8, 48, 48, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 48, 1,
- 21, 48, 1, 1, 61, 61, 61, 61,
- 61, 61, 61, 61, 1, 61, 61, 61,
- 61, 1, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 1, 61, 62, 61, 0
-};
-
-static const char _myanmar_syllable_machine_trans_targs[] = {
- 0, 1, 26, 37, 0, 27, 33, 51,
- 39, 54, 40, 46, 47, 48, 29, 42,
- 43, 44, 32, 50, 55, 45, 0, 2,
- 13, 0, 3, 9, 14, 15, 21, 22,
- 23, 5, 17, 18, 19, 8, 25, 20,
- 4, 6, 7, 10, 12, 11, 16, 24,
- 0, 0, 28, 30, 31, 34, 36, 35,
- 38, 41, 49, 52, 53, 0, 0
-};
-
-static const char _myanmar_syllable_machine_trans_actions[] = {
- 3, 0, 0, 0, 4, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 5, 0,
- 0, 6, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 7, 8, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 9, 10
-};
-
-static const char _myanmar_syllable_machine_to_state_actions[] = {
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const char _myanmar_syllable_machine_from_state_actions[] = {
- 2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const short _myanmar_syllable_machine_eof_trans[] = {
- 0, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 23, 23, 49, 62, 62
-};
-
-static const int myanmar_syllable_machine_start = 0;
-static const int myanmar_syllable_machine_first_final = 0;
-static const int myanmar_syllable_machine_error = -1;
-
-static const int myanmar_syllable_machine_en_main = 0;
-
-
-#line 44 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
-
-#line 102 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_myanmar (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act HB_UNUSED;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 382 "hb-ot-shape-complex-myanmar-machine.hh"
- {
- cs = myanmar_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 398 "hb-ot-shape-complex-myanmar-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
- case 2:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 412 "hb-ot-shape-complex-myanmar-machine.hh"
- }
-
- _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
- _inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
-
- _slen = _myanmar_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
- ( info[p].myanmar_category()) <= _keys[1] ?
- ( info[p].myanmar_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _myanmar_syllable_machine_trans_targs[_trans];
-
- if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
- case 6:
-#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
- break;
- case 4:
-#line 95 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
- break;
- case 10:
-#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_punctuation_cluster); }}
- break;
- case 8:
-#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_broken_cluster); }}
- break;
- case 3:
-#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
- break;
- case 5:
-#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
- break;
- case 7:
-#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (myanmar_broken_cluster); }}
- break;
- case 9:
-#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
- break;
-#line 462 "hb-ot-shape-complex-myanmar-machine.hh"
- }
-
-_again:
- switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
- case 1:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 471 "hb-ot-shape-complex-myanmar-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 130 "hb-ot-shape-complex-myanmar-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.hh
deleted file mode 100644
index 7fbca3878f..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.hh
+++ /dev/null
@@ -1,177 +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
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-indic.hh"
-
-
-/* buffer var allocations */
-#define myanmar_category() indic_category() /* myanmar_category_t */
-#define myanmar_position() indic_position() /* myanmar_position_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum myanmar_category_t {
- OT_As = 18, /* Asat */
- OT_D0 = 20, /* Digit zero */
- OT_DB = OT_N, /* Dot below */
- OT_GB = OT_PLACEHOLDER,
- OT_MH = 21, /* Various consonant medial types */
- OT_MR = 22, /* Various consonant medial types */
- OT_MW = 23, /* Various consonant medial types */
- OT_MY = 24, /* Various consonant medial types */
- OT_PT = 25, /* Pwo and other tones */
- //OT_VAbv = 26,
- //OT_VBlw = 27,
- //OT_VPre = 28,
- //OT_VPst = 29,
- OT_VS = 30, /* Variation selectors */
- OT_P = 31, /* Punctuation */
- OT_D = 32, /* Digits except zero */
- OT_ML = 33, /* Various consonant medial types */
-};
-
-using myanmar_position_t = indic_position_t;
-
-static inline void
-set_myanmar_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- unsigned int cat = type & 0xFFu;
- myanmar_position_t pos = (myanmar_position_t) (type >> 8);
-
- /* Myanmar
- * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
- */
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
- cat = OT_VS;
-
- switch (u)
- {
- case 0x104Eu:
- cat = OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
- break;
-
- case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
- case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
- case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
- case 0x25FEu:
- cat = OT_GB;
- break;
-
- case 0x1004u: case 0x101Bu: case 0x105Au:
- cat = OT_Ra;
- break;
-
- case 0x1032u: case 0x1036u:
- cat = OT_A;
- break;
-
- case 0x1039u:
- cat = OT_H;
- break;
-
- case 0x103Au:
- cat = OT_As;
- break;
-
- case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
- case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
- case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
- case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
- case 0x1097u: case 0x1098u: case 0x1099u:
- cat = OT_D;
- break;
-
- case 0x1040u:
- cat = OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
- break;
-
- case 0x103Eu:
- cat = OT_MH;
- break;
-
- case 0x1060u:
- cat = OT_ML;
- break;
-
- case 0x103Cu:
- cat = OT_MR;
- break;
-
- case 0x103Du: case 0x1082u:
- cat = OT_MW;
- break;
-
- case 0x103Bu: case 0x105Eu: case 0x105Fu:
- cat = OT_MY;
- break;
-
- case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
- case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
- cat = OT_PT;
- break;
-
- case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
- case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
- case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
- cat = OT_SM;
- break;
-
- case 0x104Au: case 0x104Bu:
- cat = OT_P;
- break;
-
- case 0xAA74u: case 0xAA75u: case 0xAA76u:
- /* https://github.com/harfbuzz/harfbuzz/issues/218 */
- cat = OT_C;
- break;
- }
-
- if (cat == OT_M)
- {
- switch ((int) pos)
- {
- case POS_PRE_C: cat = (myanmar_category_t) OT_VPre;
- pos = POS_PRE_M; break;
- case POS_ABOVE_C: cat = (myanmar_category_t) OT_VAbv; break;
- case POS_BELOW_C: cat = (myanmar_category_t) OT_VBlw; break;
- case POS_POST_C: cat = (myanmar_category_t) OT_VPst; break;
- }
- }
-
- info.myanmar_category() = cat;
- info.myanmar_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh
deleted file mode 100644
index 468bd95c3f..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh
+++ /dev/null
@@ -1,849 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-use-machine.rl"
-/*
- * Copyright © 2015 Mozilla Foundation.
- * Copyright © 2015 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-syllabic.hh"
-
-/* buffer var allocations */
-#define use_category() complex_var_u8_category()
-
-#define USE(Cat) use_syllable_machine_ex_##Cat
-
-enum use_syllable_type_t {
- use_virama_terminated_cluster,
- use_sakot_terminated_cluster,
- use_standard_cluster,
- use_number_joiner_terminated_cluster,
- use_numeral_cluster,
- use_symbol_cluster,
- use_hieroglyph_cluster,
- use_broken_cluster,
- use_non_cluster,
-};
-
-
-#line 57 "hb-ot-shape-complex-use-machine.hh"
-#define use_syllable_machine_ex_B 1u
-#define use_syllable_machine_ex_CGJ 6u
-#define use_syllable_machine_ex_CMAbv 31u
-#define use_syllable_machine_ex_CMBlw 32u
-#define use_syllable_machine_ex_CS 43u
-#define use_syllable_machine_ex_FAbv 24u
-#define use_syllable_machine_ex_FBlw 25u
-#define use_syllable_machine_ex_FMAbv 45u
-#define use_syllable_machine_ex_FMBlw 46u
-#define use_syllable_machine_ex_FMPst 47u
-#define use_syllable_machine_ex_FPst 26u
-#define use_syllable_machine_ex_G 49u
-#define use_syllable_machine_ex_GB 5u
-#define use_syllable_machine_ex_H 12u
-#define use_syllable_machine_ex_HN 13u
-#define use_syllable_machine_ex_IS 44u
-#define use_syllable_machine_ex_J 50u
-#define use_syllable_machine_ex_MAbv 27u
-#define use_syllable_machine_ex_MBlw 28u
-#define use_syllable_machine_ex_MPre 30u
-#define use_syllable_machine_ex_MPst 29u
-#define use_syllable_machine_ex_N 4u
-#define use_syllable_machine_ex_O 0u
-#define use_syllable_machine_ex_R 18u
-#define use_syllable_machine_ex_SB 51u
-#define use_syllable_machine_ex_SE 52u
-#define use_syllable_machine_ex_SMAbv 41u
-#define use_syllable_machine_ex_SMBlw 42u
-#define use_syllable_machine_ex_SUB 11u
-#define use_syllable_machine_ex_Sk 48u
-#define use_syllable_machine_ex_VAbv 33u
-#define use_syllable_machine_ex_VBlw 34u
-#define use_syllable_machine_ex_VMAbv 37u
-#define use_syllable_machine_ex_VMBlw 38u
-#define use_syllable_machine_ex_VMPre 23u
-#define use_syllable_machine_ex_VMPst 39u
-#define use_syllable_machine_ex_VPre 22u
-#define use_syllable_machine_ex_VPst 35u
-#define use_syllable_machine_ex_WJ 16u
-#define use_syllable_machine_ex_ZWNJ 14u
-
-
-#line 100 "hb-ot-shape-complex-use-machine.hh"
-static const unsigned char _use_syllable_machine_trans_keys[] = {
- 0u, 51u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u,
- 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u,
- 23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u,
- 1u, 1u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u,
- 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
- 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u,
- 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u,
- 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
- 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
- 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 11u, 48u, 11u, 48u,
- 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
- 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
- 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 4u, 4u, 13u, 13u,
- 1u, 48u, 11u, 48u, 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u,
- 0
-};
-
-static const char _use_syllable_machine_key_spans[] = {
- 52, 38, 38, 48, 26, 24, 23, 22,
- 2, 1, 25, 25, 25, 1, 25, 27,
- 26, 26, 26, 37, 37, 37, 37, 38,
- 1, 38, 2, 1, 38, 38, 48, 26,
- 24, 23, 22, 2, 1, 25, 25, 25,
- 1, 25, 27, 26, 26, 26, 37, 37,
- 37, 37, 38, 1, 1, 1, 38, 38,
- 48, 26, 24, 23, 22, 2, 1, 25,
- 25, 25, 1, 25, 27, 26, 26, 26,
- 37, 37, 37, 37, 38, 1, 38, 38,
- 48, 26, 24, 23, 22, 2, 1, 25,
- 25, 25, 1, 25, 27, 26, 26, 26,
- 37, 37, 37, 37, 38, 1, 1, 1,
- 48, 38, 2, 1, 5, 3, 4, 3
-};
-
-static const short _use_syllable_machine_index_offsets[] = {
- 0, 53, 92, 131, 180, 207, 232, 256,
- 279, 282, 284, 310, 336, 362, 364, 390,
- 418, 445, 472, 499, 537, 575, 613, 651,
- 690, 692, 731, 734, 736, 775, 814, 863,
- 890, 915, 939, 962, 965, 967, 993, 1019,
- 1045, 1047, 1073, 1101, 1128, 1155, 1182, 1220,
- 1258, 1296, 1334, 1373, 1375, 1377, 1379, 1418,
- 1457, 1506, 1533, 1558, 1582, 1605, 1608, 1610,
- 1636, 1662, 1688, 1690, 1716, 1744, 1771, 1798,
- 1825, 1863, 1901, 1939, 1977, 2016, 2018, 2057,
- 2096, 2145, 2172, 2197, 2221, 2244, 2247, 2249,
- 2275, 2301, 2327, 2329, 2355, 2383, 2410, 2437,
- 2464, 2502, 2540, 2578, 2616, 2655, 2657, 2659,
- 2661, 2710, 2749, 2752, 2754, 2760, 2764, 2769
-};
-
-static const char _use_syllable_machine_indicies[] = {
- 0, 1, 2, 2, 3, 4, 2, 2,
- 2, 2, 2, 5, 6, 7, 2, 2,
- 2, 2, 8, 2, 2, 2, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 2, 23, 24, 25,
- 2, 26, 27, 28, 29, 30, 31, 32,
- 29, 33, 2, 34, 2, 36, 37, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 38, 39, 40, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 35, 52,
- 53, 54, 35, 55, 56, 35, 57, 58,
- 59, 60, 57, 35, 36, 37, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 38,
- 39, 40, 41, 42, 43, 44, 45, 46,
- 48, 48, 49, 50, 51, 35, 52, 53,
- 54, 35, 35, 35, 35, 57, 58, 59,
- 60, 57, 35, 36, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 39, 40, 41, 42, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 52,
- 53, 54, 35, 35, 35, 35, 35, 58,
- 59, 60, 61, 35, 39, 40, 41, 42,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 52, 53, 54, 35, 35, 35,
- 35, 35, 58, 59, 60, 61, 35, 40,
- 41, 42, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 58, 59, 60, 35,
- 41, 42, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 58, 59, 60, 35,
- 42, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 58, 59, 60, 35, 58,
- 59, 35, 59, 35, 40, 41, 42, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 52, 53, 54, 35, 35, 35, 35,
- 35, 58, 59, 60, 61, 35, 40, 41,
- 42, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 53, 54, 35, 35,
- 35, 35, 35, 58, 59, 60, 61, 35,
- 40, 41, 42, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 54,
- 35, 35, 35, 35, 35, 58, 59, 60,
- 61, 35, 62, 35, 40, 41, 42, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 58, 59, 60, 61, 35, 38, 39,
- 40, 41, 42, 35, 35, 35, 35, 35,
- 35, 49, 50, 51, 35, 52, 53, 54,
- 35, 35, 35, 35, 35, 58, 59, 60,
- 61, 35, 39, 40, 41, 42, 35, 35,
- 35, 35, 35, 35, 49, 50, 51, 35,
- 52, 53, 54, 35, 35, 35, 35, 35,
- 58, 59, 60, 61, 35, 39, 40, 41,
- 42, 35, 35, 35, 35, 35, 35, 35,
- 50, 51, 35, 52, 53, 54, 35, 35,
- 35, 35, 35, 58, 59, 60, 61, 35,
- 39, 40, 41, 42, 35, 35, 35, 35,
- 35, 35, 35, 35, 51, 35, 52, 53,
- 54, 35, 35, 35, 35, 35, 58, 59,
- 60, 61, 35, 39, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 38, 39, 40,
- 41, 42, 35, 44, 45, 35, 35, 35,
- 49, 50, 51, 35, 52, 53, 54, 35,
- 35, 35, 35, 35, 58, 59, 60, 61,
- 35, 39, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 38, 39, 40, 41, 42,
- 35, 35, 45, 35, 35, 35, 49, 50,
- 51, 35, 52, 53, 54, 35, 35, 35,
- 35, 35, 58, 59, 60, 61, 35, 39,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 38, 39, 40, 41, 42, 35, 35,
- 35, 35, 35, 35, 49, 50, 51, 35,
- 52, 53, 54, 35, 35, 35, 35, 35,
- 58, 59, 60, 61, 35, 39, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 38,
- 39, 40, 41, 42, 43, 44, 45, 35,
- 35, 35, 49, 50, 51, 35, 52, 53,
- 54, 35, 35, 35, 35, 35, 58, 59,
- 60, 61, 35, 36, 37, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 35,
- 48, 49, 50, 51, 35, 52, 53, 54,
- 35, 35, 35, 35, 57, 58, 59, 60,
- 57, 35, 36, 35, 36, 37, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 38,
- 39, 40, 41, 42, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, 35, 52, 53,
- 54, 35, 35, 35, 35, 57, 58, 59,
- 60, 57, 35, 55, 56, 35, 56, 35,
- 64, 65, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 1, 75, 76, 77,
- 78, 63, 79, 80, 81, 63, 63, 63,
- 63, 82, 83, 84, 85, 86, 63, 64,
- 65, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 75, 76, 77, 78,
- 63, 79, 80, 81, 63, 63, 63, 63,
- 82, 83, 84, 85, 86, 63, 64, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 67, 68, 69, 70,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 79, 80, 81, 63, 63, 63,
- 63, 63, 83, 84, 85, 87, 63, 67,
- 68, 69, 70, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 79, 80, 81,
- 63, 63, 63, 63, 63, 83, 84, 85,
- 87, 63, 68, 69, 70, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 83,
- 84, 85, 63, 69, 70, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 83,
- 84, 85, 63, 70, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 83, 84,
- 85, 63, 83, 84, 63, 84, 63, 68,
- 69, 70, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 79, 80, 81, 63,
- 63, 63, 63, 63, 83, 84, 85, 87,
- 63, 68, 69, 70, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 80,
- 81, 63, 63, 63, 63, 63, 83, 84,
- 85, 87, 63, 68, 69, 70, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 81, 63, 63, 63, 63, 63,
- 83, 84, 85, 87, 63, 89, 88, 68,
- 69, 70, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 83, 84, 85, 87,
- 63, 66, 67, 68, 69, 70, 63, 63,
- 63, 63, 63, 63, 76, 77, 78, 63,
- 79, 80, 81, 63, 63, 63, 63, 63,
- 83, 84, 85, 87, 63, 67, 68, 69,
- 70, 63, 63, 63, 63, 63, 63, 76,
- 77, 78, 63, 79, 80, 81, 63, 63,
- 63, 63, 63, 83, 84, 85, 87, 63,
- 67, 68, 69, 70, 63, 63, 63, 63,
- 63, 63, 63, 77, 78, 63, 79, 80,
- 81, 63, 63, 63, 63, 63, 83, 84,
- 85, 87, 63, 67, 68, 69, 70, 63,
- 63, 63, 63, 63, 63, 63, 63, 78,
- 63, 79, 80, 81, 63, 63, 63, 63,
- 63, 83, 84, 85, 87, 63, 67, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 66, 67, 68, 69, 70, 63, 72, 73,
- 63, 63, 63, 76, 77, 78, 63, 79,
- 80, 81, 63, 63, 63, 63, 63, 83,
- 84, 85, 87, 63, 67, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 66, 67,
- 68, 69, 70, 63, 63, 73, 63, 63,
- 63, 76, 77, 78, 63, 79, 80, 81,
- 63, 63, 63, 63, 63, 83, 84, 85,
- 87, 63, 67, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 66, 67, 68, 69,
- 70, 63, 63, 63, 63, 63, 63, 76,
- 77, 78, 63, 79, 80, 81, 63, 63,
- 63, 63, 63, 83, 84, 85, 87, 63,
- 67, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 66, 67, 68, 69, 70, 71,
- 72, 73, 63, 63, 63, 76, 77, 78,
- 63, 79, 80, 81, 63, 63, 63, 63,
- 63, 83, 84, 85, 87, 63, 64, 65,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 63, 75, 76, 77, 78, 63,
- 79, 80, 81, 63, 63, 63, 63, 82,
- 83, 84, 85, 86, 63, 64, 90, 92,
- 91, 3, 93, 94, 95, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105,
- 106, 107, 108, 109, 63, 110, 111, 112,
- 63, 55, 56, 63, 113, 114, 115, 85,
- 116, 63, 94, 95, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 96, 97, 98,
- 99, 100, 101, 102, 103, 104, 106, 106,
- 107, 108, 109, 63, 110, 111, 112, 63,
- 63, 63, 63, 113, 114, 115, 85, 116,
- 63, 94, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 97,
- 98, 99, 100, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 110, 111, 112,
- 63, 63, 63, 63, 63, 114, 115, 85,
- 117, 63, 97, 98, 99, 100, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 110, 111, 112, 63, 63, 63, 63, 63,
- 114, 115, 85, 117, 63, 98, 99, 100,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 114, 115, 85, 63, 99, 100,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 114, 115, 85, 63, 100, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 114, 115, 85, 63, 114, 115, 63,
- 115, 63, 98, 99, 100, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 110,
- 111, 112, 63, 63, 63, 63, 63, 114,
- 115, 85, 117, 63, 98, 99, 100, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 111, 112, 63, 63, 63, 63,
- 63, 114, 115, 85, 117, 63, 98, 99,
- 100, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 112, 63, 63,
- 63, 63, 63, 114, 115, 85, 117, 63,
- 118, 88, 98, 99, 100, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 114,
- 115, 85, 117, 63, 96, 97, 98, 99,
- 100, 63, 63, 63, 63, 63, 63, 107,
- 108, 109, 63, 110, 111, 112, 63, 63,
- 63, 63, 63, 114, 115, 85, 117, 63,
- 97, 98, 99, 100, 63, 63, 63, 63,
- 63, 63, 107, 108, 109, 63, 110, 111,
- 112, 63, 63, 63, 63, 63, 114, 115,
- 85, 117, 63, 97, 98, 99, 100, 63,
- 63, 63, 63, 63, 63, 63, 108, 109,
- 63, 110, 111, 112, 63, 63, 63, 63,
- 63, 114, 115, 85, 117, 63, 97, 98,
- 99, 100, 63, 63, 63, 63, 63, 63,
- 63, 63, 109, 63, 110, 111, 112, 63,
- 63, 63, 63, 63, 114, 115, 85, 117,
- 63, 97, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 96, 97, 98, 99, 100,
- 63, 102, 103, 63, 63, 63, 107, 108,
- 109, 63, 110, 111, 112, 63, 63, 63,
- 63, 63, 114, 115, 85, 117, 63, 97,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 96, 97, 98, 99, 100, 63, 63,
- 103, 63, 63, 63, 107, 108, 109, 63,
- 110, 111, 112, 63, 63, 63, 63, 63,
- 114, 115, 85, 117, 63, 97, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 96,
- 97, 98, 99, 100, 63, 63, 63, 63,
- 63, 63, 107, 108, 109, 63, 110, 111,
- 112, 63, 63, 63, 63, 63, 114, 115,
- 85, 117, 63, 97, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 96, 97, 98,
- 99, 100, 101, 102, 103, 63, 63, 63,
- 107, 108, 109, 63, 110, 111, 112, 63,
- 63, 63, 63, 63, 114, 115, 85, 117,
- 63, 94, 95, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 96, 97, 98, 99,
- 100, 101, 102, 103, 104, 63, 106, 107,
- 108, 109, 63, 110, 111, 112, 63, 63,
- 63, 63, 113, 114, 115, 85, 116, 63,
- 94, 90, 94, 95, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 96, 97, 98,
- 99, 100, 101, 102, 103, 104, 105, 106,
- 107, 108, 109, 63, 110, 111, 112, 63,
- 63, 63, 63, 113, 114, 115, 85, 116,
- 63, 5, 6, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 19, 19, 20,
- 21, 22, 119, 23, 24, 25, 119, 119,
- 119, 119, 29, 30, 31, 32, 29, 119,
- 5, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 10, 11,
- 12, 13, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 23, 24, 25, 119,
- 119, 119, 119, 119, 30, 31, 32, 120,
- 119, 10, 11, 12, 13, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 23,
- 24, 25, 119, 119, 119, 119, 119, 30,
- 31, 32, 120, 119, 11, 12, 13, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 30, 31, 32, 119, 12, 13, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 30, 31, 32, 119, 13, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 30, 31, 32, 119, 30, 31, 119, 31,
- 119, 11, 12, 13, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 23, 24,
- 25, 119, 119, 119, 119, 119, 30, 31,
- 32, 120, 119, 11, 12, 13, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 24, 25, 119, 119, 119, 119, 119,
- 30, 31, 32, 120, 119, 11, 12, 13,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 25, 119, 119, 119,
- 119, 119, 30, 31, 32, 120, 119, 121,
- 119, 11, 12, 13, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 30, 31,
- 32, 120, 119, 9, 10, 11, 12, 13,
- 119, 119, 119, 119, 119, 119, 20, 21,
- 22, 119, 23, 24, 25, 119, 119, 119,
- 119, 119, 30, 31, 32, 120, 119, 10,
- 11, 12, 13, 119, 119, 119, 119, 119,
- 119, 20, 21, 22, 119, 23, 24, 25,
- 119, 119, 119, 119, 119, 30, 31, 32,
- 120, 119, 10, 11, 12, 13, 119, 119,
- 119, 119, 119, 119, 119, 21, 22, 119,
- 23, 24, 25, 119, 119, 119, 119, 119,
- 30, 31, 32, 120, 119, 10, 11, 12,
- 13, 119, 119, 119, 119, 119, 119, 119,
- 119, 22, 119, 23, 24, 25, 119, 119,
- 119, 119, 119, 30, 31, 32, 120, 119,
- 10, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 9, 10, 11, 12, 13, 119,
- 15, 16, 119, 119, 119, 20, 21, 22,
- 119, 23, 24, 25, 119, 119, 119, 119,
- 119, 30, 31, 32, 120, 119, 10, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 9, 10, 11, 12, 13, 119, 119, 16,
- 119, 119, 119, 20, 21, 22, 119, 23,
- 24, 25, 119, 119, 119, 119, 119, 30,
- 31, 32, 120, 119, 10, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 9, 10,
- 11, 12, 13, 119, 119, 119, 119, 119,
- 119, 20, 21, 22, 119, 23, 24, 25,
- 119, 119, 119, 119, 119, 30, 31, 32,
- 120, 119, 10, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 9, 10, 11, 12,
- 13, 14, 15, 16, 119, 119, 119, 20,
- 21, 22, 119, 23, 24, 25, 119, 119,
- 119, 119, 119, 30, 31, 32, 120, 119,
- 5, 6, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 119, 19, 20, 21,
- 22, 119, 23, 24, 25, 119, 119, 119,
- 119, 29, 30, 31, 32, 29, 119, 5,
- 119, 122, 119, 7, 119, 1, 119, 119,
- 119, 1, 119, 119, 119, 119, 119, 5,
- 6, 7, 119, 119, 119, 119, 119, 119,
- 119, 119, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22,
- 119, 23, 24, 25, 119, 26, 27, 119,
- 29, 30, 31, 32, 29, 119, 5, 6,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 119,
- 23, 24, 25, 119, 119, 119, 119, 29,
- 30, 31, 32, 29, 119, 26, 27, 119,
- 27, 119, 1, 123, 123, 123, 1, 123,
- 125, 124, 33, 124, 33, 125, 124, 125,
- 124, 33, 124, 34, 124, 0
-};
-
-static const char _use_syllable_machine_trans_targs[] = {
- 1, 28, 0, 52, 54, 79, 80, 102,
- 104, 92, 81, 82, 83, 84, 96, 97,
- 98, 99, 105, 100, 93, 94, 95, 87,
- 88, 89, 106, 107, 108, 101, 85, 86,
- 0, 109, 111, 0, 2, 3, 15, 4,
- 5, 6, 7, 19, 20, 21, 22, 25,
- 23, 16, 17, 18, 10, 11, 12, 26,
- 27, 24, 8, 9, 0, 13, 14, 0,
- 29, 30, 42, 31, 32, 33, 34, 46,
- 47, 48, 49, 50, 43, 44, 45, 37,
- 38, 39, 51, 35, 36, 0, 51, 40,
- 0, 41, 0, 0, 53, 0, 55, 56,
- 68, 57, 58, 59, 60, 72, 73, 74,
- 75, 78, 76, 69, 70, 71, 63, 64,
- 65, 77, 61, 62, 77, 66, 67, 0,
- 90, 91, 103, 0, 0, 110
-};
-
-static const char _use_syllable_machine_trans_actions[] = {
- 0, 0, 3, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 4, 0, 0, 5, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 6, 0, 0, 7,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 8, 0, 0, 9, 10, 0,
- 11, 0, 12, 13, 0, 14, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 8, 0, 0, 10, 0, 0, 15,
- 0, 0, 0, 16, 17, 0
-};
-
-static const char _use_syllable_machine_to_state_actions[] = {
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const char _use_syllable_machine_from_state_actions[] = {
- 2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const short _use_syllable_machine_eof_trans[] = {
- 0, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 89, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 91, 92, 94, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 89, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 91, 64, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 124, 125, 125, 125
-};
-
-static const int use_syllable_machine_start = 0;
-static const int use_syllable_machine_first_final = 0;
-static const int use_syllable_machine_error = -1;
-
-static const int use_syllable_machine_en_main = 0;
-
-
-#line 58 "hb-ot-shape-complex-use-machine.rl"
-
-
-
-#line 181 "hb-ot-shape-complex-use-machine.rl"
-
-
-#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); \
- for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-
-template <typename Iter>
-struct machine_index_t :
- hb_iter_with_fallback_t<machine_index_t<Iter>,
- typename Iter::item_t>
-{
- machine_index_t (const Iter& it) : it (it) {}
- machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
- typename Iter::item_t> (),
- it (o.it), is_null (o.is_null) {}
-
- static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
- static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
-
- typename Iter::item_t __item__ () const { return *it; }
- typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
- unsigned __len__ () const { return it.len (); }
- void __next__ () { ++it; }
- void __forward__ (unsigned n) { it += n; }
- void __prev__ () { --it; }
- void __rewind__ (unsigned n) { it -= n; }
-
- void operator = (unsigned n)
- {
- assert (n == 0);
- is_null = true;
- }
- explicit operator bool () { return !is_null; }
-
- void operator = (const machine_index_t& o)
- {
- is_null = o.is_null;
- unsigned index = (*it).first;
- unsigned n = (*o.it).first;
- if (index < n) it += n - index; else if (index > n) it -= index - n;
- }
- bool operator == (const machine_index_t& o) const
- { return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
- bool operator != (const machine_index_t& o) const { return !(*this == o); }
-
- private:
- Iter it;
- bool is_null = false;
-};
-struct
-{
- template <typename Iter,
- hb_requires (hb_is_iterable (Iter))>
- machine_index_t<hb_iter_type<Iter>>
- operator () (Iter&& it) const
- { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
-}
-HB_FUNCOBJ (machine_index);
-
-
-
-static bool
-not_ccs_default_ignorable (const hb_glyph_info_t &i)
-{ return i.use_category() != USE(CGJ); }
-
-static inline void
-find_syllables_use (hb_buffer_t *buffer)
-{
- hb_glyph_info_t *info = buffer->info;
- auto p =
- + hb_iter (info, buffer->len)
- | hb_enumerate
- | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
- hb_second)
- | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
- {
- if (p.second.use_category() == USE(ZWNJ))
- for (unsigned i = p.first + 1; i < buffer->len; ++i)
- if (not_ccs_default_ignorable (info[i]))
- return !_hb_glyph_info_is_unicode_mark (&info[i]);
- return true;
- })
- | hb_enumerate
- | machine_index
- ;
- auto pe = p + p.len ();
- auto eof = +pe;
- auto ts = +p;
- auto te = +p;
- unsigned int act HB_UNUSED;
- int cs;
-
-#line 702 "hb-ot-shape-complex-use-machine.hh"
- {
- cs = use_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 281 "hb-ot-shape-complex-use-machine.rl"
-
-
- unsigned int syllable_serial = 1;
-
-#line 715 "hb-ot-shape-complex-use-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _use_syllable_machine_from_state_actions[cs] ) {
- case 2:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 729 "hb-ot-shape-complex-use-machine.hh"
- }
-
- _keys = _use_syllable_machine_trans_keys + (cs<<1);
- _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
-
- _slen = _use_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( (*p).second.second.use_category()) &&
- ( (*p).second.second.use_category()) <= _keys[1] ?
- ( (*p).second.second.use_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _use_syllable_machine_trans_targs[_trans];
-
- if ( _use_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _use_syllable_machine_trans_actions[_trans] ) {
- case 9:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_standard_cluster); }}
- break;
- case 6:
-#line 174 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_symbol_cluster); }}
- break;
- case 4:
-#line 176 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_broken_cluster); }}
- break;
- case 3:
-#line 177 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_non_cluster); }}
- break;
- case 11:
-#line 170 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
- break;
- case 7:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_standard_cluster); }}
- break;
- case 14:
-#line 172 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
- break;
- case 13:
-#line 173 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_numeral_cluster); }}
- break;
- case 5:
-#line 174 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_symbol_cluster); }}
- break;
- case 17:
-#line 175 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
- break;
- case 15:
-#line 176 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_broken_cluster); }}
- break;
- case 16:
-#line 177 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_non_cluster); }}
- break;
- case 12:
-#line 1 "NONE"
- { switch( act ) {
- case 1:
- {{p = ((te))-1;} found_syllable (use_virama_terminated_cluster); }
- break;
- case 2:
- {{p = ((te))-1;} found_syllable (use_sakot_terminated_cluster); }
- break;
- }
- }
- break;
- case 8:
-#line 1 "NONE"
- {te = p+1;}
-#line 169 "hb-ot-shape-complex-use-machine.rl"
- {act = 1;}
- break;
- case 10:
-#line 1 "NONE"
- {te = p+1;}
-#line 170 "hb-ot-shape-complex-use-machine.rl"
- {act = 2;}
- break;
-#line 819 "hb-ot-shape-complex-use-machine.hh"
- }
-
-_again:
- switch ( _use_syllable_machine_to_state_actions[cs] ) {
- case 1:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 828 "hb-ot-shape-complex-use-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _use_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 286 "hb-ot-shape-complex-use-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.hh
deleted file mode 100644
index ea627cd27e..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.hh
+++ /dev/null
@@ -1,1570 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
- *
- * on files with these headers:
- *
- * # IndicSyllabicCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # IndicPositionalCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # ArabicShaping-14.0.0.txt
- * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
- * # DerivedCoreProperties-14.0.0.txt
- * # Date: 2021-08-12, 23:12:53 GMT
- * # Blocks-14.0.0.txt
- * # Date: 2021-01-22, 23:29:00 GMT [KW]
- * # Scripts-14.0.0.txt
- * # Date: 2021-07-10, 00:35:31 GMT
- * # Override values For Indic_Syllabic_Category
- * # Not derivable
- * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
- * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
- * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
- * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
- * # Override values For Indic_Positional_Category
- * # Not derivable
- * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
- * # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
- * # Updated for L2/19-083 by Andrew Glass 2019-05-06
- * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
- * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
- * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
- * UnicodeData.txt does not have a header.
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-use-machine.hh"
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-macros"
-#define B USE(B) /* BASE */
-#define CGJ USE(CGJ) /* CGJ */
-#define CS USE(CS) /* CONS_WITH_STACKER */
-#define G USE(G) /* HIEROGLYPH */
-#define GB USE(GB) /* BASE_OTHER */
-#define H USE(H) /* HALANT */
-#define HN USE(HN) /* HALANT_NUM */
-#define IS USE(IS) /* INVISIBLE_STACKER */
-#define J USE(J) /* HIEROGLYPH_JOINER */
-#define N USE(N) /* BASE_NUM */
-#define O USE(O) /* OTHER */
-#define R USE(R) /* REPHA */
-#define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
-#define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */
-#define SUB USE(SUB) /* CONS_SUB */
-#define Sk USE(Sk) /* SAKOT */
-#define WJ USE(WJ) /* Word_Joiner */
-#define ZWNJ USE(ZWNJ) /* ZWNJ */
-#define CMAbv USE(CMAbv)
-#define CMBlw USE(CMBlw)
-#define FAbv USE(FAbv)
-#define FBlw USE(FBlw)
-#define FPst USE(FPst)
-#define FMAbv USE(FMAbv)
-#define FMBlw USE(FMBlw)
-#define FMPst USE(FMPst)
-#define MAbv USE(MAbv)
-#define MBlw USE(MBlw)
-#define MPst USE(MPst)
-#define MPre USE(MPre)
-#define SMAbv USE(SMAbv)
-#define SMBlw USE(SMBlw)
-#define VAbv USE(VAbv)
-#define VBlw USE(VBlw)
-#define VPst USE(VPst)
-#define VPre USE(VPre)
-#define VMAbv USE(VMAbv)
-#define VMBlw USE(VMBlw)
-#define VMPst USE(VMPst)
-#define VMPre USE(VMPre)
-#pragma GCC diagnostic pop
-
-static const uint8_t use_table[] = {
-
-
-#define use_offset_0x0028u 0
-
-
- /* Basic Latin */
- O, O, O, O, O, GB, O, O,
- /* 0030 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0x00a0u 24
-
-
- /* Latin-1 Supplement */
-
- /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O, O,
- /* 00B0 */ O, O, FMPst, FMPst, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 00D0 */ O, O, O, O, O, O, O, GB,
-
-#define use_offset_0x0348u 80
-
-
- /* Combining Diacritical Marks */
- O, O, O, O, O, O, O, CGJ,
-
-#define use_offset_0x0640u 88
-
-
- /* Arabic */
-
- /* 0640 */ B, O, O, O, O, O, O, O,
-
-#define use_offset_0x07c8u 96
-
-
- /* NKo */
- O, O, B, B, B, B, B, B,
- /* 07D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 07E0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
- /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, O, O, O, B, WJ, WJ, VMAbv, O, O,
-
-#define use_offset_0x0840u 152
-
-
- /* Mandaic */
-
- /* 0840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0850 */ B, B, B, B, B, B, B, B, B, CMBlw, CMBlw, CMBlw, WJ, WJ, O, WJ,
-
-#define use_offset_0x0900u 184
-
-
- /* Devanagari */
-
- /* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0930 */ B, B, B, B, B, B, B, B, B, B, VAbv, VPst, CMBlw, B, VPst, VPre,
- /* 0940 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VPst, VPst, VPst, VPst, H, VPre, VPst,
- /* 0950 */ O, VMAbv, VMBlw, O, O, VAbv, VBlw, VBlw, B, B, B, B, B, B, B, B,
- /* 0960 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0970 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
-
- /* Bengali */
-
- /* 0980 */ GB, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B,
- /* 0990 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 09A0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 09B0 */ B, WJ, B, WJ, WJ, WJ, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre,
- /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, O, WJ,
- /* 09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, B, B, WJ, B,
- /* 09E0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FMAbv, WJ,
-
- /* Gurmukhi */
-
- /* 0A00 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B,
- /* 0A10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0A20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0A30 */ B, WJ, B, B, WJ, B, B, WJ, B, B, WJ, WJ, CMBlw, WJ, VPst, VPre,
- /* 0A40 */ VPst, VBlw, VBlw, WJ, WJ, WJ, WJ, VAbv, VAbv, WJ, WJ, VAbv, VAbv, H, WJ, WJ,
- /* 0A50 */ WJ, VMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, WJ, B, WJ,
- /* 0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Gujarati */
-
- /* 0A80 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, B, B, B, WJ, B,
- /* 0A90 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0AA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0AB0 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre,
- /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, WJ, VAbv, VAbv, VAbv, WJ, VPst, VPst, H, WJ, WJ,
- /* 0AD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 0AE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0AF0 */ O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv,
-
- /* Oriya */
-
- /* 0B00 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B,
- /* 0B10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0B20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0B30 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv,
- /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ,
- /* 0B50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ, B, B, WJ, B,
- /* 0B60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0B70 */ O, B, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Tamil */
-
- /* 0B80 */ WJ, WJ, VMAbv, O, WJ, B, B, B, B, B, B, WJ, WJ, WJ, B, B,
- /* 0B90 */ B, WJ, B, B, B, B, WJ, WJ, WJ, B, B, WJ, B, WJ, B, B,
- /* 0BA0 */ WJ, WJ, WJ, B, B, WJ, WJ, WJ, B, B, B, WJ, WJ, WJ, B, B,
- /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, VPst, VPst,
- /* 0BC0 */ VAbv, VPst, VPst, WJ, WJ, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, WJ, WJ,
- /* 0BD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ,
-
- /* Telugu */
-
- /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, WJ, B, B,
- /* 0C10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0C20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0C30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, CMBlw, B, VAbv, VAbv,
- /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ,
- /* 0C50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VBlw, WJ, B, B, B, WJ, WJ, O, WJ, WJ,
- /* 0C60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, O, O, O, O,
-
- /* Kannada */
-
- /* 0C80 */ B, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, WJ, B, B,
- /* 0C90 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0CA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 0CB0 */ B, B, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv,
- /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ,
- /* 0CD0 */ WJ, WJ, WJ, WJ, WJ, VPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, O, B, WJ,
- /* 0CE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0CF0 */ WJ, CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Malayalam */
-
- /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, B, B, B, B, B, B, B, B, B, WJ, B, B,
- /* 0D10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, VAbv, VAbv, B, VPst, VPst,
- /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, R, O,
- /* 0D50 */ WJ, WJ, WJ, WJ, O, O, O, VPst, O, O, O, O, O, O, O, B,
- /* 0D60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Sinhala */
-
- /* 0D80 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, B, B, B,
- /* 0D90 */ B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B, B, B, B,
- /* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0DB0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, WJ, B, WJ, WJ,
- /* 0DC0 */ B, B, B, B, B, B, B, WJ, WJ, WJ, H, WJ, WJ, WJ, WJ, VPst,
- /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, WJ, VBlw, WJ, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst,
- /* 0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 0DF0 */ WJ, WJ, VPst, VPst, O, WJ, WJ, WJ,
-
-#define use_offset_0x0f00u 1456
-
-
- /* Tibetan */
-
- /* 0F00 */ B, B, O, O, B, B, B, O, O, O, O, O, O, O, O, O,
- /* 0F10 */ O, O, O, O, O, O, O, O, VBlw, VBlw, O, O, O, O, O, O,
- /* 0F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0F30 */ B, B, B, B, O, FBlw, O, FBlw, O, CMAbv, O, O, O, O, VPst, VPre,
- /* 0F40 */ B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, B,
- /* 0F50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
- /* 0F70 */ WJ, CMBlw, VBlw, VAbv, VAbv, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VMAbv, O,
- /* 0F80 */ VBlw, VAbv, VMAbv, VMAbv, VBlw, O, VMAbv, VMAbv, B, B, B, B, B, SUB, SUB, SUB,
- /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 0FA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, O, O,
- /* 0FC0 */ O, O, O, O, O, O, FBlw, O,
-
-#define use_offset_0x1000u 1656
-
-
- /* Myanmar */
-
- /* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1020 */ B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VAbv, VAbv, VBlw,
- /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B,
- /* 1040 */ B, B, B, B, B, B, B, B, B, B, O, GB, O, O, GB, O,
- /* 1050 */ B, B, B, B, B, B, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw,
- /* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B,
- /* 1070 */ B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B, B, B, B, B, B, B,
- /* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst,
- /* 1090 */ B, B, B, B, B, B, B, B, B, B, VMPst, VMPst, VPst, VAbv, O, O,
-
-#define use_offset_0x1700u 1816
-
-
- /* Tagalog */
-
- /* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1710 */ B, B, VAbv, VBlw, VBlw, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B,
-
- /* Hanunoo */
-
- /* 1720 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1730 */ B, B, VAbv, VBlw, VPst, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Buhid */
-
- /* 1740 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1750 */ B, B, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Tagbanwa */
-
- /* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B, B,
- /* 1770 */ B, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Khmer */
-
- /* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 17B0 */ B, B, B, B, CGJ, CGJ, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre,
- /* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FMAbv, FAbv, CMAbv, FMAbv, VMAbv,
- /* 17D0 */ FMAbv, VAbv, IS, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, WJ, WJ,
- /* 17E0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 17F0 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Mongolian */
-
- /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, CGJ, CGJ, CGJ, WJ, CGJ,
- /* 1810 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 1820 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1830 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1870 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 1880 */ GB, GB, GB, GB, GB, CMAbv, CMAbv, B, B, B, B, B, B, B, B, B,
- /* 1890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18A0 */ B, B, B, B, B, B, B, B, B, CMBlw, B, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x1900u 2248
-
-
- /* Limbu */
-
- /* 1900 */ GB, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ,
- /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, WJ, WJ, WJ, WJ,
- /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VMAbv, FMBlw, WJ, WJ, WJ, WJ,
- /* 1940 */ O, WJ, WJ, WJ, O, O, B, B, B, B, B, B, B, B, B, B,
-
- /* Tai Le */
-
- /* 1950 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ,
- /* 1970 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* New Tai Lue */
-
- /* 1980 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ,
- /* 19B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 19D0 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, O, O,
- /* 19E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 19F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Buginese */
-
- /* 1A00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A10 */ B, B, B, B, B, B, B, VAbv, VAbv, VPre, VPst, VAbv, WJ, WJ, O, O,
-
- /* Tai Tham */
-
- /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, WJ,
- /* 1A60 */ Sk, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre,
- /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, VMAbv, VMAbv, WJ, WJ, VMBlw,
- /* 1A80 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 1A90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x1b00u 2664
-
-
- /* Balinese */
-
- /* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre,
- /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
- /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 1B60 */ O, O, O, O, O, O, O, O, O, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
- /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, WJ,
-
- /* Sundanese */
-
- /* 1B80 */ VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, IS, SUB, SUB, B, B,
- /* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
-
- /* Batak */
-
- /* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BE0 */ B, B, B, B, B, B, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv,
- /* 1BF0 */ FAbv, FAbv, CMBlw, CMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O,
-
- /* Lepcha */
-
- /* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv,
- /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, WJ, WJ, WJ, O, O, O, O, O,
- /* 1C40 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B,
-
-#define use_offset_0x1cd0u 3000
-
-
- /* Vedic Extensions */
-
- /* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw,
- /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O,
- /* 1CF0 */ O, O, O, O, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, GB, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x1df8u 3048
-
-
- /* Combining Diacritical Marks Supplement */
- O, O, O, FMAbv, O, O, O, O,
-
-#define use_offset_0x2008u 3056
-
-
- /* General Punctuation */
- O, O, O, WJ, ZWNJ, CGJ, WJ, WJ,
- /* 2010 */ GB, GB, GB, GB, GB, O, O, O, O, O, O, O, O, O, O, O,
- /* 2020 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, O,
- /* 2030 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 2040 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 2050 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 2060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Superscripts and Subscripts */
-
- /* 2070 */ O, O, WJ, WJ, FMPst, O, O, O, O, O, O, O, O, O, O, O,
- /* 2080 */ O, O, FMPst, FMPst, FMPst, O, O, O,
-
-#define use_offset_0x20f0u 3184
-
-
- /* Combining Diacritical Marks for Symbols */
-
- /* 20F0 */ VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x25c8u 3192
-
-
- /* Geometric Shapes */
- O, O, O, O, B, O, O, O,
-
-#define use_offset_0x2d30u 3200
-
-
- /* Tifinagh */
-
- /* 2D30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D60 */ B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B,
- /* 2D70 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, H,
-
-#define use_offset_0xa800u 3280
-
-
- /* Syloti Nagri */
-
- /* A800 */ B, B, VAbv, B, B, B, H, B, B, B, B, VMAbv, B, B, B, B,
- /* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, VBlw, WJ, WJ, WJ,
- /* A830 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Phags-pa */
-
- /* A840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A870 */ B, B, B, B, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Saurashtra */
-
- /* A880 */ VMPst, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A8B0 */ B, B, B, B, MPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst,
- /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O,
- /* A8D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Devanagari Extended */
-
- /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
- /* A8F0 */ VMAbv, VMAbv, B, B, O, O, O, O, O, O, O, O, O, O, B, VAbv,
-
- /* Kayah Li */
-
- /* A900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A920 */ B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VAbv, VMBlw, VMBlw, VMBlw, O, O,
-
- /* Rejang */
-
- /* A930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A940 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VBlw, VBlw, VBlw, VBlw, FAbv,
- /* A950 */ FAbv, FAbv, FPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O,
- /* A960 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ,
-
- /* Javanese */
-
- /* A980 */ VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, MBlw, MPst, MBlw,
- /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O,
- /* A9D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O,
-
- /* Myanmar Extended-B */
-
- /* A9E0 */ B, B, B, B, B, VAbv, O, B, B, B, B, B, B, B, B, B,
- /* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ,
-
- /* Cham */
-
- /* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA20 */ B, B, B, B, B, B, B, B, B, VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre,
- /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MAbv, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, WJ, WJ,
- /* AA50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, O, O, O,
-
- /* Myanmar Extended-A */
-
- /* AA60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA70 */ O, B, B, B, GB, GB, GB, O, O, O, B, VMPst, VMAbv, VMPst, B, B,
-
- /* Tai Viet */
-
- /* AA80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AAA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AAB0 */ VAbv, B, VAbv, VAbv, VBlw, B, B, VAbv, VAbv, B, B, B, B, B, VAbv, VMAbv,
- /* AAC0 */ B, VMAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* AAD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O,
-
- /* Meetei Mayek Extensions */
-
- /* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst,
- /* AAF0 */ O, O, O, O, O, VMPst, IS, WJ,
-
-#define use_offset_0xabc0u 4040
-
-
- /* Meetei Mayek */
-
- /* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* ABD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, WJ, WJ,
- /* ABF0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0xfe00u 4104
-
-
- /* Variation Selectors */
-
- /* FE00 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
-
-#define use_offset_0xfef8u 4120
-
-
- /* Arabic Presentation Forms-B */
- O, O, O, O, O, WJ, WJ, WJ,
-
-#define use_offset_0xfff0u 4128
-
-
- /* Specials */
-
- /* FFF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, WJ, WJ,
-
-#define use_offset_0x10570u 4144
-
-
- /* Vithkuqi */
-
- /* 10570 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B,
- /* 10580 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B,
- /* 10590 */ B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B, B,
- /* 105A0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 105B0 */ B, B, WJ, B, B, B, B, B, B, B, WJ, B, B, WJ, WJ, WJ,
-
-#define use_offset_0x10a00u 4224
-
-
- /* Kharoshthi */
-
- /* 10A00 */ B, VBlw, VBlw, VBlw, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, VPst, VMBlw, VMBlw, VMAbv,
- /* 10A10 */ B, B, B, B, WJ, B, B, B, WJ, B, B, B, B, B, B, B,
- /* 10A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10A30 */ B, B, B, B, B, B, WJ, WJ, CMAbv, CMBlw, CMBlw, WJ, WJ, WJ, WJ, IS,
- /* 10A40 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x10ac0u 4304
-
-
- /* Manichaean */
-
- /* 10AC0 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B,
- /* 10AD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, WJ, WJ, WJ, WJ, B, B, B, B, B,
-
-#define use_offset_0x10b80u 4352
-
-
- /* Psalter Pahlavi */
-
- /* 10B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10B90 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, WJ, WJ, WJ,
- /* 10BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, O,
-
-#define use_offset_0x10d00u 4400
-
-
- /* Hanifi Rohingya */
-
- /* 10D00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10D20 */ B, B, B, B, VMAbv, VMAbv, VMAbv, CMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10D30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x10e80u 4464
-
-
- /* Yezidi */
-
- /* 10E80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10E90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10EA0 */ B, B, B, B, B, B, B, B, B, B, WJ, VAbv, VAbv, O, WJ, WJ,
- /* 10EB0 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x10f30u 4520
-
-
- /* Sogdian */
-
- /* 10F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10F40 */ B, B, B, B, B, B, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,
- /* 10F50 */ VMBlw, B, B, B, B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Old Uyghur */
-
- /* 10F70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10F80 */ B, B, CMBlw, CMBlw, CMBlw, CMBlw, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Chorasmian */
-
- /* 10FB0 */ B, O, B, B, B, B, B, O, B, B, B, B, B, B, B, B,
- /* 10FC0 */ O, B, B, B, B, O, O, O, O, B, B, B, WJ, WJ, WJ, WJ,
- /* 10FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 10FE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 10FF0 */ O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Brahmi */
-
- /* 11000 */ VMPst, VMAbv, VMPst, CS, CS, B, B, B, B, B, B, B, B, B, B, B,
- /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw,
- /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, WJ, WJ,
- /* 11050 */ WJ, WJ, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
- /* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B,
- /* 11070 */ VAbv, B, B, VAbv, VAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, HN,
-
- /* Kaithi */
-
- /* 11080 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O,
- /* 110C0 */ O, O, VBlw, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x11100u 4928
-
-
- /* Chakma */
-
- /* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11120 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VBlw, VAbv, VAbv,
- /* 11130 */ VBlw, VAbv, VAbv, IS, CMAbv, WJ, B, B, B, B, B, B, B, B, B, B,
- /* 11140 */ O, O, O, O, B, VPst, VPst, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Mahajani */
-
- /* 11150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11170 */ B, B, B, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Sharada */
-
- /* 11180 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,
- /* 111C0 */ H, B, R, R, O, O, O, O, O, FMBlw, CMBlw, VAbv, VBlw, O, VPre, VMAbv,
- /* 111D0 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O,
-
- /* Sinhala Archaic Numbers */
-
- /* 111E0 */ WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111F0 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Khojki */
-
- /* 11200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11210 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw,
- /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, WJ,
-
-#define use_offset_0x11280u 5248
-
-
- /* Multani */
-
- /* 11280 */ B, B, B, B, B, B, B, WJ, B, WJ, B, B, B, B, WJ, B,
- /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B,
- /* 112A0 */ B, B, B, B, B, B, B, B, B, O, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Khudawadi */
-
- /* 112B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv,
- /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, WJ, WJ, WJ, WJ, WJ,
- /* 112F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Grantha */
-
- /* 11300 */ VMAbv, VMAbv, VMAbv, VMAbv, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B,
- /* 11310 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11320 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 11330 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, CMBlw, CMBlw, B, VPst, VPst,
- /* 11340 */ VAbv, VPst, VPst, VPst, VPst, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ,
- /* 11350 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, O, B, B,
- /* 11360 */ B, B, VPst, VPst, WJ, WJ, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ,
- /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ,
-
-#define use_offset_0x11400u 5496
-
-
- /* Newa */
-
- /* 11400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv,
- /* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O,
- /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, WJ, O, FMAbv, B,
- /* 11460 */ CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Tirhuta */
-
- /* 11480 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv,
- /* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 114D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x11580u 5720
-
-
- /* Siddham */
-
- /* 11580 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
- /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H,
- /* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, WJ, WJ,
- /* 115E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 115F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Modi */
-
- /* 11600 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H,
- /* 11640 */ VAbv, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11650 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ,
- /* 11670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Takri */
-
- /* 11680 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst,
- /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, B, O, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 116C0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 116D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 116E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 116F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Ahom */
-
- /* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, MBlw, MPre, MAbv,
- /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ,
- /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
- /* 11740 */ B, B, B, B, B, B, B, WJ,
-
-#define use_offset_0x11800u 6176
-
-
- /* Dogra */
-
- /* 11800 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw,
- /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x11900u 6240
-
-
- /* Dives Akuru */
-
- /* 11900 */ B, B, B, B, B, B, B, WJ, WJ, B, WJ, WJ, B, B, B, B,
- /* 11910 */ B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B,
- /* 11920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11930 */ VPst, VPst, VPst, VPst, VPst, VPre, WJ, VPre, VPre, WJ, WJ, VMAbv, VMAbv, VPst, IS, R,
- /* 11940 */ MPst, R, MPst, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x119a0u 6336
-
-
- /* Nandinagari */
-
- /* 119A0 */ B, B, B, B, B, B, B, B, WJ, WJ, B, B, B, B, B, B,
- /* 119B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 119C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 119D0 */ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VAbv, VAbv, VPst, VPst, VMPst, VMPst,
- /* 119E0 */ H, B, O, O, VPre, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 119F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Zanabazar Square */
-
- /* 11A00 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, B, B, B, B, B,
- /* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A30 */ B, B, B, FMBlw, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB,
- /* 11A40 */ O, O, O, O, O, GB, O, IS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Soyombo */
-
- /* 11A50 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VBlw, VBlw, VBlw, B, B, B, B,
- /* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A80 */ B, B, B, B, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw,
- /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, IS, O, O, O, B, O, O,
-
-#define use_offset_0x11c00u 6592
-
-
- /* Bhaiksuki */
-
- /* 11C00 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B,
- /* 11C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
- /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H,
- /* 11C40 */ B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
-
- /* Marchen */
-
- /* 11C70 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C90 */ WJ, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, WJ,
-
-#define use_offset_0x11d00u 6776
-
-
- /* Masaram Gondi */
-
- /* 11D00 */ B, B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B,
- /* 11D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, WJ, WJ, WJ, VAbv, WJ, VAbv, VAbv, WJ, VAbv,
- /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, IS, R, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11D50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Gunjala Gondi */
-
- /* 11D60 */ B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B,
- /* 11D70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D80 */ B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VPst, VPst, WJ,
- /* 11D90 */ VAbv, VAbv, WJ, VPst, VPst, VMAbv, VMPst, IS, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x11ee0u 6952
-
-
- /* Makasar */
-
- /* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O,
-
-#define use_offset_0x13000u 6976
-
-
- /* Egyptian Hieroglyphs */
-
- /* 13000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13030 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13040 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13050 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13060 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13070 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13080 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13130 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13140 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13170 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13180 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13210 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13220 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13230 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13240 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13250 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13260 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13270 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13280 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13300 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13310 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13320 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13330 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13340 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13350 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13360 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13370 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13380 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13390 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ,
-
- /* Egyptian Hieroglyph Format Controls */
-
- /* 13430 */ H, H, H, H, H, H, H, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
-#define use_offset_0x16ac0u 8064
-
-
- /* Tangsa */
-
- /* 16AC0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 16AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 16AE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ,
- /* 16AF0 */ O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Pahawh Hmong */
-
- /* 16B00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16B30 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O,
-
-#define use_offset_0x16f00u 8184
-
-
- /* Miao */
-
- /* 16F00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F40 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, CMBlw,
- /* 16F50 */ O, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F60 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F70 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, VMBlw,
- /* 16F90 */ VMBlw, VMBlw, VMBlw, O, O, O, O, O,
-
-#define use_offset_0x16fe0u 8336
-
-
- /* Ideographic Symbols and Punctuation */
-
- /* 16FE0 */ O, O, O, O, B, WJ, WJ, WJ,
-
-#define use_offset_0x18b00u 8344
-
-
- /* Khitan Small Script */
-
- /* 18B00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BF0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CD0 */ B, B, B, B, B, B, WJ, WJ,
-
-#define use_offset_0x1bc00u 8816
-
-
- /* Duployan */
-
- /* 1BC00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC60 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ,
- /* 1BC70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
- /* 1BC80 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* 1BC90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, CMBlw, CMBlw, O,
-
-#define use_offset_0x1d170u 8976
-
-
- /* Musical Symbols */
-
- /* 1D170 */ O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O,
-
-#define use_offset_0x1e100u 8992
-
-
- /* Nyiakeng Puachue Hmong */
-
- /* 1E100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ,
- /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, WJ, WJ,
- /* 1E140 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B, B,
-
-#define use_offset_0x1e290u 9072
-
-
- /* Toto */
-
- /* 1E290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E2A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, WJ,
- /* 1E2B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Wancho */
-
- /* 1E2C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E2D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E2E0 */ B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv,
- /* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, O,
-
-#define use_offset_0x1e900u 9184
-
-
- /* Adlam */
-
- /* 1E900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, WJ, WJ, WJ, WJ,
- /* 1E950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O,
-
-#define use_offset_0xe0000u 9280
-
-
- /* Tags */
-
- /* E0000 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0010 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0020 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0030 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0040 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0050 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0070 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* No_Block */
-
- /* E0080 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0090 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E00F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
- /* Variation Selectors Supplement */
-
- /* E0100 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0110 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0120 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0130 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0140 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0150 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0160 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0170 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0180 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0190 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01A0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01B0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01C0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01D0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01E0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
-
- /* No_Block */
-
- /* E01F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0200 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0210 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0220 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0230 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0240 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0250 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0260 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0270 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0280 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0290 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E02F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0300 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0310 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0320 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0330 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0340 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0350 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0360 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0370 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0380 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0390 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E03F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0400 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0410 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0420 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0430 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0440 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0450 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0460 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0480 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0490 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E04F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0500 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0510 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0520 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0530 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0540 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0550 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0560 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0570 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0580 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0590 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E05F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0600 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0610 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0620 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0630 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0640 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0650 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0660 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0680 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0690 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E06F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0700 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0710 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0720 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0730 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0740 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0750 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0760 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0770 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0780 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0790 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E07F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0800 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0810 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0820 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0830 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0840 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0850 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0860 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0870 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0880 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0890 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E08F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0900 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0910 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0920 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0930 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0940 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0950 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0960 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0970 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0980 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0990 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E09F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0A90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0AF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0B90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0BF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0C90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0CF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0D90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0DF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0E90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0ED0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0EF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
- /* E0FF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
-
-}; /* Table items: 13376; occupancy: 84% */
-
-static inline uint8_t
-hb_use_get_category (hb_glyph_info_t info)
-{
- hb_codepoint_t u = info.codepoint;
- switch (u >> 12)
- {
- case 0x0u:
- if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
- if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0640u, 0x0647u)) return use_table[u - 0x0640u + use_offset_0x0640u];
- if (hb_in_range<hb_codepoint_t> (u, 0x07C8u, 0x07FFu)) return use_table[u - 0x07C8u + use_offset_0x07c8u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0840u, 0x085Fu)) return use_table[u - 0x0840u + use_offset_0x0840u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0F00u, 0x0FC7u)) return use_table[u - 0x0F00u + use_offset_0x0f00u];
- break;
-
- case 0x1u:
- if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1700u, 0x18AFu)) return use_table[u - 0x1700u + use_offset_0x1700u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u];
- break;
-
- case 0x2u:
- if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2087u)) return use_table[u - 0x2008u + use_offset_0x2008u];
- if (hb_in_range<hb_codepoint_t> (u, 0x20F0u, 0x20F7u)) return use_table[u - 0x20F0u + use_offset_0x20f0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x25C8u, 0x25CFu)) return use_table[u - 0x25C8u + use_offset_0x25c8u];
- if (hb_in_range<hb_codepoint_t> (u, 0x2D30u, 0x2D7Fu)) return use_table[u - 0x2D30u + use_offset_0x2d30u];
- break;
-
- case 0xAu:
- if (hb_in_range<hb_codepoint_t> (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u];
- if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
- break;
-
- case 0xFu:
- if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u];
- if (hb_in_range<hb_codepoint_t> (u, 0xFEF8u, 0xFEFFu)) return use_table[u - 0xFEF8u + use_offset_0xfef8u];
- if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u];
- break;
-
- case 0x10u:
- if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10570u, 0x105BFu)) return use_table[u - 0x10570u + use_offset_0x10570u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A4Fu)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return use_table[u - 0x10B80u + use_offset_0x10b80u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D3Fu)) return use_table[u - 0x10D00u + use_offset_0x10d00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10E80u, 0x10EB7u)) return use_table[u - 0x10E80u + use_offset_0x10e80u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
- break;
-
- case 0x11u:
- if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x11747u)) return use_table[u - 0x11580u + use_offset_0x11580u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11800u, 0x1183Fu)) return use_table[u - 0x11800u + use_offset_0x11800u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11900u, 0x1195Fu)) return use_table[u - 0x11900u + use_offset_0x11900u];
- if (hb_in_range<hb_codepoint_t> (u, 0x119A0u, 0x11A9Fu)) return use_table[u - 0x119A0u + use_offset_0x119a0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11D00u, 0x11DAFu)) return use_table[u - 0x11D00u + use_offset_0x11d00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11EE0u, 0x11EF7u)) return use_table[u - 0x11EE0u + use_offset_0x11ee0u];
- break;
-
- case 0x13u:
- if (hb_in_range<hb_codepoint_t> (u, 0x13000u, 0x1343Fu)) return use_table[u - 0x13000u + use_offset_0x13000u];
- break;
-
- case 0x16u:
- if (hb_in_range<hb_codepoint_t> (u, 0x16AC0u, 0x16B37u)) return use_table[u - 0x16AC0u + use_offset_0x16ac0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x16F00u, 0x16F97u)) return use_table[u - 0x16F00u + use_offset_0x16f00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x16FE0u, 0x16FE7u)) return use_table[u - 0x16FE0u + use_offset_0x16fe0u];
- break;
-
- case 0x18u:
- if (hb_in_range<hb_codepoint_t> (u, 0x18B00u, 0x18CD7u)) return use_table[u - 0x18B00u + use_offset_0x18b00u];
- break;
-
- case 0x1Bu:
- if (hb_in_range<hb_codepoint_t> (u, 0x1BC00u, 0x1BC9Fu)) return use_table[u - 0x1BC00u + use_offset_0x1bc00u];
- break;
-
- case 0x1Du:
- if (hb_in_range<hb_codepoint_t> (u, 0x1D170u, 0x1D17Fu)) return use_table[u - 0x1D170u + use_offset_0x1d170u];
- break;
-
- case 0x1Eu:
- if (hb_in_range<hb_codepoint_t> (u, 0x1E100u, 0x1E14Fu)) return use_table[u - 0x1E100u + use_offset_0x1e100u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1E290u, 0x1E2FFu)) return use_table[u - 0x1E290u + use_offset_0x1e290u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E95Fu)) return use_table[u - 0x1E900u + use_offset_0x1e900u];
- break;
-
- case 0xE0u:
- if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u];
- break;
-
- case 0xE1u:
- if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u];
- break;
-
- default:
- break;
- }
- if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED)
- return WJ;
- return O;
-}
-
-#undef B
-#undef CGJ
-#undef CS
-#undef G
-#undef GB
-#undef H
-#undef HN
-#undef IS
-#undef J
-#undef N
-#undef O
-#undef R
-#undef SB
-#undef SE
-#undef SUB
-#undef Sk
-#undef WJ
-#undef ZWNJ
-#undef CMAbv
-#undef CMBlw
-#undef FAbv
-#undef FBlw
-#undef FPst
-#undef FMAbv
-#undef FMBlw
-#undef FMPst
-#undef MAbv
-#undef MBlw
-#undef MPst
-#undef MPre
-#undef SMAbv
-#undef SMBlw
-#undef VAbv
-#undef VBlw
-#undef VPst
-#undef VPre
-#undef VMAbv
-#undef VMBlw
-#undef VMPst
-#undef VMPre
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_TABLE_HH */
-/* == End of generated table == */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc
index aa5a8eeaa3..897377aa15 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc
@@ -29,7 +29,7 @@
#ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-normalize.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
#include "hb-ot-shape.hh"
@@ -69,7 +69,7 @@
* - When a font does not support a character but supports its canonical
* decomposition, well, use the decomposition.
*
- * - The complex shapers can customize the compose and decompose functions to
+ * - The shapers can customize the compose and decompose functions to
* offload some of their requirements to the normalizer. For example, the
* Indic shaper may want to disallow recomposing of two matras.
*/
@@ -143,8 +143,7 @@ decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint
return 1;
}
- unsigned int ret;
- if ((ret = decompose (c, shortest, a))) {
+ if (unsigned ret = decompose (c, shortest, a)) {
if (b) {
output_char (buffer, b, b_glyph);
return ret + 1;
@@ -223,7 +222,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c,
unsigned int end,
bool short_circuit HB_UNUSED)
{
- /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
+ /* Currently if there's a variation-selector we give-up on normalization, it's just too hard. */
hb_buffer_t * const buffer = c->buffer;
hb_font_t * const font = c->font;
for (; buffer->idx < end - 1 && buffer->successful;) {
@@ -342,7 +341,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
{
unsigned int end;
for (end = buffer->idx + 1; end < count; end++)
- if (unlikely (_hb_glyph_info_is_unicode_mark (&buffer->info[end])))
+ if (_hb_glyph_info_is_unicode_mark (&buffer->info[end]))
break;
if (end < count)
@@ -395,7 +394,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
break;
/* We are going to do a O(n^2). Only do this if the sequence is short. */
- if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
+ if (end - i > HB_OT_SHAPE_MAX_COMBINING_MARKS) {
i = end;
continue;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
index 99aadab3f0..3d207e0681 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
@@ -37,7 +37,7 @@
#include "hb-shaper-impl.hh"
#include "hb-ot-shape.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
#include "hb-ot-shape-fallback.hh"
#include "hb-ot-shape-normalize.hh"
@@ -53,11 +53,11 @@ _hb_codepoint_is_regional_indicator (hb_codepoint_t u)
#ifndef HB_NO_AAT_SHAPE
static inline bool
-_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t *props)
+_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t &props)
{
/* https://github.com/harfbuzz/harfbuzz/issues/2124 */
return hb_aat_layout_has_substitution (face) &&
- (HB_DIRECTION_IS_HORIZONTAL (props->direction) || !hb_ot_layout_has_substitution (face));
+ (HB_DIRECTION_IS_HORIZONTAL (props.direction) || !hb_ot_layout_has_substitution (face));
}
#endif
@@ -77,23 +77,24 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
unsigned int num_user_features);
hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face,
- const hb_segment_properties_t *props) :
+ const hb_segment_properties_t &props) :
face (face),
- props (*props),
- map (face, props),
- aat_map (face, props)
+ props (props),
+ map (face, props)
#ifndef HB_NO_AAT_SHAPE
, apply_morx (_hb_apply_morx (face, props))
#endif
{
- shaper = hb_ot_shape_complex_categorize (this);
+ shaper = hb_ot_shaper_categorize (this);
script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
script_fallback_mark_positioning = shaper->fallback_position;
+#ifndef HB_NO_AAT_SHAPE
/* https://github.com/harfbuzz/harfbuzz/issues/1528 */
- if (apply_morx && shaper != &_hb_ot_complex_shaper_default)
- shaper = &_hb_ot_complex_shaper_dumber;
+ if (apply_morx && shaper != &_hb_ot_shaper_default)
+ shaper = &_hb_ot_shaper_dumber;
+#endif
}
void
@@ -103,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'));
@@ -220,12 +217,9 @@ 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);
+ key->props);
hb_ot_shape_collect_features (&planner,
key->user_features,
@@ -239,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;
}
}
@@ -256,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
@@ -404,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);
}
@@ -527,18 +498,20 @@ hb_set_unicode_props (hb_buffer_t *buffer)
}
#endif
/* Or part of the Other_Grapheme_Extend that is not marks.
- * As of Unicode 11 that is just:
+ * As of Unicode 15 that is just:
*
* 200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER
* FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
* E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
*
* ZWNJ is special, we don't want to merge it as there's no need, and keeping
- * it separate results in more granular clusters. Ignore Katakana for now.
+ * it separate results in more granular clusters.
* Tags are used for Emoji sub-region flag sequences:
* https://github.com/harfbuzz/harfbuzz/issues/1556
+ * Katakana ones were requested:
+ * https://github.com/harfbuzz/harfbuzz/issues/3844
*/
- else if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0xE0020u, 0xE007Fu)))
+ else if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0xFF9Eu, 0xFF9Fu, 0xE0020u, 0xE007Fu)))
_hb_glyph_info_set_continuation (&info[i]);
}
}
@@ -862,7 +835,7 @@ hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
}
}
else
- hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable);
+ buffer->delete_glyphs_inplace (_hb_glyph_info_is_default_ignorable);
}
@@ -927,7 +900,7 @@ hb_ot_substitute_default (const hb_ot_shape_context_t *c)
}
static inline void
-hb_ot_substitute_complex (const hb_ot_shape_context_t *c)
+hb_ot_substitute_plan (const hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
@@ -936,7 +909,13 @@ hb_ot_substitute_complex (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
@@ -946,7 +925,7 @@ hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
_hb_buffer_allocate_gsubgpos_vars (c->buffer);
- hb_ot_substitute_complex (c);
+ hb_ot_substitute_plan (c);
#ifndef HB_NO_AAT_SHAPE
if (c->plan->apply_morx && c->plan->apply_gpos)
@@ -1039,7 +1018,7 @@ hb_ot_position_default (const hb_ot_shape_context_t *c)
}
static inline void
-hb_ot_position_complex (const hb_ot_shape_context_t *c)
+hb_ot_position_plan (const hb_ot_shape_context_t *c)
{
unsigned int count = c->buffer->len;
hb_glyph_info_t *info = c->buffer->info;
@@ -1124,7 +1103,7 @@ hb_ot_position (const hb_ot_shape_context_t *c)
hb_ot_position_default (c);
- hb_ot_position_complex (c);
+ hb_ot_position_plan (c);
if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
hb_buffer_reverse (c->buffer);
@@ -1141,6 +1120,18 @@ hb_propagate_flags (hb_buffer_t *buffer)
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS))
return;
+ /* If we are producing SAFE_TO_INSERT_TATWEEL, then do two things:
+ *
+ * - If the places that the Arabic shaper marked as SAFE_TO_INSERT_TATWEEL,
+ * are UNSAFE_TO_BREAK, then clear the SAFE_TO_INSERT_TATWEEL,
+ * - Any place that is SAFE_TO_INSERT_TATWEEL, is also now UNSAFE_TO_BREAK.
+ *
+ * We couldn't make this interaction earlier. It has to be done here.
+ */
+ bool flip_tatweel = buffer->flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL;
+
+ bool clear_concat = (buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0;
+
hb_glyph_info_t *info = buffer->info;
foreach_cluster (buffer, start, end)
@@ -1148,9 +1139,20 @@ hb_propagate_flags (hb_buffer_t *buffer)
unsigned int mask = 0;
for (unsigned int i = start; i < end; i++)
mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED;
- if (mask)
- for (unsigned int i = start; i < end; i++)
- info[i].mask |= mask;
+
+ if (flip_tatweel)
+ {
+ if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
+ mask &= ~HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL;
+ if (mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL)
+ mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
+ }
+
+ if (clear_concat)
+ mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
+
+ for (unsigned int i = start; i < end; i++)
+ info[i].mask = mask;
}
}
@@ -1159,8 +1161,6 @@ hb_propagate_flags (hb_buffer_t *buffer)
static void
hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
- c->buffer->enter ();
-
/* Save the original direction, we use it later. */
c->target_direction = c->buffer->props.direction;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh
index e8c81015c7..f84aa5c49e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh
@@ -51,7 +51,7 @@ struct hb_ot_shape_plan_key_t
bool equal (const hb_ot_shape_plan_key_t *other)
{
- return 0 == memcmp (this, other, sizeof (*this));
+ return 0 == hb_memcmp (this, other, sizeof (*this));
}
};
@@ -60,10 +60,11 @@ struct hb_shape_plan_key_t;
struct hb_ot_shape_plan_t
{
+ ~hb_ot_shape_plan_t () { fini (); }
+
hb_segment_properties_t props;
- const struct hb_ot_complex_shaper_t *shaper;
+ 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;
@@ -150,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
@@ -158,10 +158,10 @@ struct hb_ot_shape_planner_t
#endif
bool script_zero_marks : 1;
bool script_fallback_mark_positioning : 1;
- const struct hb_ot_complex_shaper_t *shaper;
+ const struct hb_ot_shaper_t *shaper;
HB_INTERNAL hb_ot_shape_planner_t (hb_face_t *face,
- const hb_segment_properties_t *props);
+ const hb_segment_properties_t &props);
HB_INTERNAL void compile (hb_ot_shape_plan_t &plan,
const hb_ot_shape_plan_key_t &key);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh
index 78f46c1cac..e7a69008b7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-fallback.hh
@@ -24,8 +24,8 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
+#ifndef HB_OT_SHAPER_ARABIC_FALLBACK_HH
+#define HB_OT_SHAPER_ARABIC_FALLBACK_HH
#include "hb.hh"
@@ -34,7 +34,11 @@
/* Features ordered the same as the entries in shaping_table rows,
- * followed by rlig. Don't change. */
+ * followed by rlig. Don't change.
+ *
+ * We currently support one subtable per lookup, and one lookup
+ * per feature. But we allow duplicate features, so we use that!
+ */
static const hb_tag_t arabic_fallback_features[] =
{
HB_TAG('i','n','i','t'),
@@ -42,6 +46,8 @@ static const hb_tag_t arabic_fallback_features[] =
HB_TAG('f','i','n','a'),
HB_TAG('i','s','o','l'),
HB_TAG('r','l','i','g'),
+ HB_TAG('r','l','i','g'),
+ HB_TAG('r','l','i','g'),
};
static OT::SubstLookup *
@@ -95,20 +101,25 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
return ret && !c.in_error () ? c.copy<OT::SubstLookup> () : nullptr;
}
+template <typename T>
static OT::SubstLookup *
arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font)
+ hb_font_t *font,
+ const T &ligature_table,
+ unsigned lookup_flags)
{
OT::HBGlyphID16 first_glyphs[ARRAY_LENGTH_CONST (ligature_table)];
unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)];
unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)];
unsigned int num_first_glyphs = 0;
- /* We know that all our ligatures are 2-component */
+ /* We know that all our ligatures have the same number of components. */
OT::HBGlyphID16 ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)];
unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)];
- OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */];
+ OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) *
+ ARRAY_LENGTH_CONST (ligature_table[0].ligatures[0].components)];
unsigned int num_ligatures = 0;
+ unsigned int num_components = 0;
/* Populate arrays */
@@ -133,21 +144,38 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
{
unsigned int first_glyph_idx = first_glyphs_indirection[i];
- for (unsigned int second_glyph_idx = 0; second_glyph_idx < ARRAY_LENGTH (ligature_table[0].ligatures); second_glyph_idx++)
+ for (unsigned int ligature_idx = 0; ligature_idx < ARRAY_LENGTH (ligature_table[0].ligatures); ligature_idx++)
{
- hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].second;
- hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].ligature;
- hb_codepoint_t second_glyph, ligature_glyph;
- if (!second_u ||
- !hb_font_get_glyph (font, second_u, 0, &second_glyph) ||
- !hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph))
+ hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].ligature;
+ hb_codepoint_t ligature_glyph;
+ if (!hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph))
continue;
- ligature_per_first_glyph_count_list[i]++;
+ const auto &components = ligature_table[first_glyph_idx].ligatures[ligature_idx].components;
+ unsigned component_count = ARRAY_LENGTH_CONST (components);
+
+ 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[j];
+ hb_codepoint_t component_glyph;
+ if (!component_u ||
+ !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;
- component_count_list[num_ligatures] = 2;
- component_list[num_ligatures] = second_glyph;
+
+ ligature_per_first_glyph_count_list[i]++;
+
num_ligatures++;
}
}
@@ -161,14 +189,13 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
hb_serialize_context_t c (buf, sizeof (buf));
OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
bool ret = lookup->serialize_ligature (&c,
- OT::LookupFlag::IgnoreMarks,
+ lookup_flags,
hb_sorted_array (first_glyphs, num_first_glyphs),
hb_array (ligature_per_first_glyph_count_list, num_first_glyphs),
hb_array (ligature_list, num_ligatures),
hb_array (component_count_list, num_ligatures),
- hb_array (component_list, num_ligatures));
+ hb_array (component_list, num_components));
c.end_serialize ();
- /* TODO sanitize the results? */
return ret && !c.in_error () ? c.copy<OT::SubstLookup> () : nullptr;
}
@@ -181,10 +208,18 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan,
if (feature_index < 4)
return arabic_fallback_synthesize_lookup_single (plan, font, feature_index);
else
- return arabic_fallback_synthesize_lookup_ligature (plan, font);
+ {
+ switch (feature_index) {
+ case 4: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_3_table, OT::LookupFlag::IgnoreMarks);
+ case 5: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_table, OT::LookupFlag::IgnoreMarks);
+ case 6: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_mark_table, 0);
+ }
+ }
+ assert (false);
+ return nullptr;
}
-#define ARABIC_FALLBACK_MAX_LOOKUPS 5
+#define ARABIC_FALLBACK_MAX_LOOKUPS ARRAY_LENGTH_CONST (arabic_fallback_features)
struct arabic_fallback_plan_t
{
@@ -193,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)
@@ -201,7 +236,7 @@ struct arabic_fallback_plan_t
#endif
#ifdef HB_WITH_WIN1256
-#include "hb-ot-shape-complex-arabic-win1256.hh"
+#include "hb-ot-shaper-arabic-win1256.hh"
#endif
struct ManifestLookup
@@ -230,9 +265,8 @@ arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUS
return false;
const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest);
- static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) ==
+ static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) <=
ARABIC_FALLBACK_MAX_LOOKUPS * sizeof (ManifestLookup), "");
- /* TODO sanitize the table? */
unsigned j = 0;
unsigned int count = manifest.len;
@@ -244,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++;
}
}
@@ -264,7 +298,7 @@ arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
const hb_ot_shape_plan_t *plan,
hb_font_t *font)
{
- static_assert ((ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS), "");
+ static_assert ((ARRAY_LENGTH_CONST (arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS), "");
unsigned int j = 0;
for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++)
{
@@ -274,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++;
}
}
@@ -321,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]);
}
@@ -338,11 +372,12 @@ 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]);
}
}
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH */
+#endif /* HB_OT_SHAPER_ARABIC_FALLBACK_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-joining-list.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-joining-list.hh
index e6339ee72b..c7b57820af 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-joining-list.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-joining-list.hh
@@ -6,14 +6,14 @@
*
* on files with these headers:
*
- * # ArabicShaping-14.0.0.txt
- * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
- * # Scripts-14.0.0.txt
- * # Date: 2021-07-10, 00:35:31 GMT
+ * # ArabicShaping-15.0.0.txt
+ * # Date: 2022-02-14, 18:50:00 GMT [KW, RP]
+ * # Scripts-15.0.0.txt
+ * # Date: 2022-04-26, 23:15:02 GMT
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
+#ifndef HB_OT_SHAPER_ARABIC_JOINING_LIST_HH
+#define HB_OT_SHAPER_ARABIC_JOINING_LIST_HH
static bool
has_arabic_joining (hb_script_t script)
@@ -42,6 +42,6 @@ has_arabic_joining (hb_script_t script)
}
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH */
+#endif /* HB_OT_SHAPER_ARABIC_JOINING_LIST_HH */
/* == End of generated function == */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-pua.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-pua.hh
new file mode 100644
index 0000000000..ba86772f84
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-pua.hh
@@ -0,0 +1,118 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-arabic-pua.py
+ *
+ */
+
+#ifndef HB_OT_SHAPER_ARABIC_PUA_HH
+#define HB_OT_SHAPER_ARABIC_PUA_HH
+
+static const uint8_t
+_hb_arabic_u8[464] =
+{
+ 84, 86, 85, 85, 85, 85, 85,213, 16, 34, 34, 34, 34, 34, 35, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 36, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 82, 16, 0, 0, 0, 0, 1, 2, 3, 4,
+ 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 7,
+ 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 0, 0, 0, 22, 0, 23, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 16, 34, 34, 34, 35, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 66, 16, 50, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68,101, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 71, 68, 68, 68, 68, 68, 68, 68,152,186, 76, 77, 68,254, 16, 50,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 5, 6,
+ 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 10, 0,
+ 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 23, 23, 29, 30, 31, 32, 33, 0, 0, 0, 0,
+ 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 36, 37, 38, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 40,
+ 41, 42, 0, 43, 44, 0, 0, 45, 46, 0, 47, 48, 49, 0, 0, 0,
+ 0, 50, 0, 0, 51, 52, 0, 53, 54, 55, 56, 57, 58, 0, 0, 0,
+ 0, 0, 59, 60, 61, 62, 63, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 66,
+ 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+};
+static const uint16_t
+_hb_arabic_u16[720] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,61728,61729,61730, 0, 0,61733, 0, 0,
+ 61736,61737,61738,61739,61790,61741,61742,61743,61872,61873,61874,61875,61876,61877,61878,61879,
+ 61880,61881,61754,61755, 0,61757, 0,61759, 0, 0, 0,61787,61788,61789, 0, 0,
+ 0, 0, 0,61731, 0, 0, 0, 0, 0, 0, 0,61732, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,61734, 0, 0, 0, 0, 0, 0, 0,61735,
+ 0, 0, 0, 0,61740, 0, 0, 0, 0, 0, 0,61755, 0, 0, 0,61759,
+ 0,61869,61765,61763,61883,61767,61882,61761,61770,61865,61772,61774,61777,61780,61783,61784,
+ 61785,61786,61792,61794,61796,61798,61800,61801,61802,61806,61810,61696,61696,61696,61696,61696,
+ 61791,61813,61816,61818,61820,61822,61921,61860,61861,61868,61864,61895,61896,61899,61892,61893,
+ 61898,61897,61894,61696,61696,61696,61696,61696,61696,61696,61696,61696,61696,61696,61696, 0,
+ 61744,61745,61746,61747,61748,61749,61750,61751,61752,61753, 0,61790,61790, 0, 0, 0,
+ 0, 0, 0, 0,61708,61709,61710,61711,61756,61758, 0, 0, 0, 0, 0, 0,
+ 0,61765,61766,61763,61764,61883,61883,61767,61768,61882,61871,61870,61870,61761,61762,61770,
+ 61770,61769,61769,61865,61866,61772,61772,61771,61771,61774,61774,61773,61773,61777,61776,61775,
+ 61775,61780,61779,61778,61778,61783,61782,61781,61781,61784,61784,61785,61785,61786,61786,61792,
+ 61792,61794,61794,61793,61793,61796,61796,61795,61795,61798,61798,61797,61797,61800,61800,61799,
+ 61799,61801,61801,61801,61801,61802,61802,61802,61802,61806,61805,61803,61804,61810,61809,61807,
+ 61808,61813,61813,61811,61812,61816,61816,61814,61815,61818,61818,61817,61817,61820,61820,61819,
+ 61819,61822,61822,61821,61821,61921,61921,61823,61823,61860,61859,61857,61858,61861,61861,61868,
+ 61867,61864,61863,61862,61862,61888,61889,61886,61887,61890,61891,61885,61884, 0, 0, 0,
+ 0, 0, 0, 0,61984,61985,61986, 0, 0,61989, 0, 0,61992,61993,61994,61995,
+ 62046,61997,61998,61999, 0, 0,62010,62011, 0,62013, 0,62015, 0, 0, 0,62043,
+ 0,62045, 0, 0, 0, 0, 0,61987, 0, 0, 0,61988, 0, 0, 0,61990,
+ 0, 0, 0,61991,61996, 0, 0, 0, 0, 0, 0,62011, 0, 0, 0,62015,
+ 0,62165,62021,62019,62170,62023,62169,62017,62028,62161,62032,62036,62040,62048,62052,62053,
+ 62055,62057,62059,62064,62068,62072,62078,62114,62115,62122,62126,61952,61952,61952,61952,61952,
+ 62047,62130,62134,62138,62142,62146,62150,62154,62155,62164,62160,62183,62184,62187,62180,62181,
+ 62186,62185,62182,61952,61952,61952,61952, 0,62000,62001,62002,62003,62004,62005,62006,62007,
+ 62008,62009, 0,62046,62046, 0, 0, 0,61964,61965,61966,61967,62012,62014, 0, 0,
+ 61954, 0,61981, 0, 0, 0,61955, 0,61982, 0,61956, 0, 0, 0,62111, 0,
+ 0, 0, 0,61970,61971,61972,61957, 0,61980, 0, 0, 0, 0, 0,61958, 0,
+ 61983, 0, 0, 0, 0, 0,62191, 0,62188,62189,62192, 0, 0, 0,61973, 0,
+ 0,62098, 0, 0,61974, 0, 0,62099, 0, 0,62101, 0, 0,61975, 0, 0,
+ 62100, 0, 0, 0,62080,62081,62082,62102, 0,62083,62084,62085,62103, 0, 0, 0,
+ 62106, 0,62107, 0,62108, 0, 0, 0,61976, 0, 0, 0, 0,62086,62087,62088,
+ 62109,61978,62089,62090,62091,62110,62093,62094, 0,62104, 0, 0, 0, 0,62095,62096,
+ 62097,62105, 0, 0,61977, 0, 0, 0, 0, 0,62075,62077,61968, 0, 0, 0,
+ 0,62021,62022,62019,62020,62170,62171,62023,62024,62169,62168,62166,62167,62017,62018,62028,
+ 62027,62025,62026,62161,62162,62032,62031,62029,62030,62036,62035,62033,62034,62040,62039,62037,
+ 62038,62048,62044,62041,62042,62052,62051,62049,62050,62053,62054,62055,62056,62057,62058,62059,
+ 62060,62064,62063,62061,62062,62068,62067,62065,62066,62072,62071,62069,62070,62078,62076,62073,
+ 62074,62114,62113,62079,62193,62118,62117,62115,62116,62122,62121,62119,62120,62126,62125,62123,
+ 62124,62130,62129,62127,62128,62134,62133,62131,62132,62138,62137,62135,62136,62142,62141,62139,
+ 62140,62146,62145,62143,62144,62150,62149,62147,62148,62154,62153,62151,62152,62155,62156,62164,
+ 62163,62160,62159,62157,62158,62176,62177,62174,62175,62178,62179,62172,62173, 0, 0, 0,
+};
+
+static inline unsigned
+_hb_arabic_b2 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>2]>>((i&3u)<<1))&3u;
+}
+static inline unsigned
+_hb_arabic_b4 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline uint_fast16_t
+_hb_arabic_pua_simp_map (unsigned u)
+{
+ return u<65277u?_hb_arabic_u16[((_hb_arabic_u8[40+(((_hb_arabic_b4(8+_hb_arabic_u8,((_hb_arabic_b2(_hb_arabic_u8,u>>3>>4>>4))<<4)+((u>>3>>4)&15u)))<<4)+((u>>3)&15u))])<<3)+((u)&7u)]:0;
+}
+static inline uint_fast16_t
+_hb_arabic_pua_trad_map (unsigned u)
+{
+ return u<65277u?_hb_arabic_u16[320+(((_hb_arabic_u8[208+(((_hb_arabic_b4(168+_hb_arabic_u8,((_hb_arabic_b4(136+_hb_arabic_u8,u>>2>>4>>4))<<4)+((u>>2>>4)&15u)))<<4)+((u>>2)&15u))])<<2)+((u)&3u))]:0;
+}
+
+#endif /* HB_OT_SHAPER_ARABIC_PUA_HH */
+
+/* == End of generated table == */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-table.hh
index c158964f2c..d7670f2f95 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-table.hh
@@ -6,15 +6,15 @@
*
* on files with these headers:
*
- * # ArabicShaping-14.0.0.txt
- * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
- * # Blocks-14.0.0.txt
- * # Date: 2021-01-22, 23:29:00 GMT [KW]
+ * # ArabicShaping-15.0.0.txt
+ * # Date: 2022-02-14, 18:50:00 GMT [KW, RP]
+ * # Blocks-15.0.0.txt
+ * # Date: 2022-01-28, 20:58:00 GMT [KW]
* UnicodeData.txt does not have a header.
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
+#ifndef HB_OT_SHAPER_ARABIC_TABLE_HH
+#define HB_OT_SHAPER_ARABIC_TABLE_HH
#define A JOINING_GROUP_ALAPH
@@ -416,26 +416,141 @@ static const uint16_t shaping_table[][4] =
static const struct ligature_set_t {
uint16_t first;
struct ligature_pairs_t {
- uint16_t second;
+ uint16_t components[1];
uint16_t ligature;
- } ligatures[4];
+ } ligatures[14];
} ligature_table[] =
{
+ { 0xFE91u, {
+ { {0xFEE2u}, 0xFC08u }, /* ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFC9Fu }, /* ARABIC LIGATURE BEH WITH MEEM INITIAL FORM */
+ { {0xFEA0u}, 0xFC9Cu }, /* ARABIC LIGATURE BEH WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFC9Du }, /* ARABIC LIGATURE BEH WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFC9Eu }, /* ARABIC LIGATURE BEH WITH KHAH INITIAL FORM */
+ }},
+ { 0xFE92u, {
+ { {0xFEAEu}, 0xFC6Au }, /* ARABIC LIGATURE BEH WITH REH FINAL FORM */
+ { {0xFEE6u}, 0xFC6Du }, /* ARABIC LIGATURE BEH WITH NOON FINAL FORM */
+ { {0xFEF2u}, 0xFC6Fu }, /* ARABIC LIGATURE BEH WITH YEH FINAL FORM */
+ }},
+ { 0xFE97u, {
+ { {0xFEE2u}, 0xFC0Eu }, /* ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFCA4u }, /* ARABIC LIGATURE TEH WITH MEEM INITIAL FORM */
+ { {0xFEA0u}, 0xFCA1u }, /* ARABIC LIGATURE TEH WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCA2u }, /* ARABIC LIGATURE TEH WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFCA3u }, /* ARABIC LIGATURE TEH WITH KHAH INITIAL FORM */
+ }},
+ { 0xFE98u, {
+ { {0xFEAEu}, 0xFC70u }, /* ARABIC LIGATURE TEH WITH REH FINAL FORM */
+ { {0xFEE6u}, 0xFC73u }, /* ARABIC LIGATURE TEH WITH NOON FINAL FORM */
+ { {0xFEF2u}, 0xFC75u }, /* ARABIC LIGATURE TEH WITH YEH FINAL FORM */
+ }},
+ { 0xFE9Bu, {
+ { {0xFEE2u}, 0xFC12u }, /* ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM */
+ }},
+ { 0xFE9Fu, {
+ { {0xFEE4u}, 0xFCA8u }, /* ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEA3u, {
+ { {0xFEE4u}, 0xFCAAu }, /* ARABIC LIGATURE HAH WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEA7u, {
+ { {0xFEE4u}, 0xFCACu }, /* ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEB3u, {
+ { {0xFEE4u}, 0xFCB0u }, /* ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEB7u, {
+ { {0xFEE4u}, 0xFD30u }, /* ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM */
+ }},
+ { 0xFED3u, {
+ { {0xFEF2u}, 0xFC32u }, /* ARABIC LIGATURE FEH WITH YEH ISOLATED FORM */
+ }},
{ 0xFEDFu, {
- { 0xFE82u, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
- { 0xFE84u, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
- { 0xFE88u, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
- { 0xFE8Eu, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
+ { {0xFE9Eu}, 0xFC3Fu }, /* ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM */
+ { {0xFEA0u}, 0xFCC9u }, /* ARABIC LIGATURE LAM WITH JEEM INITIAL FORM */
+ { {0xFEA2u}, 0xFC40u }, /* ARABIC LIGATURE LAM WITH HAH ISOLATED FORM */
+ { {0xFEA4u}, 0xFCCAu }, /* ARABIC LIGATURE LAM WITH HAH INITIAL FORM */
+ { {0xFEA6u}, 0xFC41u }, /* ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM */
+ { {0xFEA8u}, 0xFCCBu }, /* ARABIC LIGATURE LAM WITH KHAH INITIAL FORM */
+ { {0xFEE2u}, 0xFC42u }, /* ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFCCCu }, /* ARABIC LIGATURE LAM WITH MEEM INITIAL FORM */
+ { {0xFEF2u}, 0xFC44u }, /* ARABIC LIGATURE LAM WITH YEH ISOLATED FORM */
+ { {0xFEECu}, 0xFCCDu }, /* ARABIC LIGATURE LAM WITH HEH INITIAL FORM */
+ { {0xFE82u}, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
+ { {0xFE84u}, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
+ { {0xFE88u}, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
+ { {0xFE8Eu}, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
}},
{ 0xFEE0u, {
- { 0xFE82u, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
- { 0xFE84u, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
- { 0xFE88u, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
- { 0xFE8Eu, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
+ { {0xFEF0u}, 0xFC86u }, /* ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM */
+ { {0xFE82u}, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
+ { {0xFE84u}, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
+ { {0xFE88u}, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
+ { {0xFE8Eu}, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
+ }},
+ { 0xFEE3u, {
+ { {0xFEA0u}, 0xFCCEu }, /* ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCCFu }, /* ARABIC LIGATURE MEEM WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFCD0u }, /* ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM */
+ { {0xFEE4u}, 0xFCD1u }, /* ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEE7u, {
+ { {0xFEE2u}, 0xFC4Eu }, /* ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFCD5u }, /* ARABIC LIGATURE NOON WITH MEEM INITIAL FORM */
+ { {0xFEA0u}, 0xFCD2u }, /* ARABIC LIGATURE NOON WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCD3u }, /* ARABIC LIGATURE NOON WITH HAH INITIAL FORM */
+ }},
+ { 0xFEE8u, {
+ { {0xFEF2u}, 0xFC8Fu }, /* ARABIC LIGATURE NOON WITH YEH FINAL FORM */
+ }},
+ { 0xFEF3u, {
+ { {0xFEA0u}, 0xFCDAu }, /* ARABIC LIGATURE YEH WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCDBu }, /* ARABIC LIGATURE YEH WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFCDCu }, /* ARABIC LIGATURE YEH WITH KHAH INITIAL FORM */
+ { {0xFEE4u}, 0xFCDDu }, /* ARABIC LIGATURE YEH WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEF4u, {
+ { {0xFEAEu}, 0xFC91u }, /* ARABIC LIGATURE YEH WITH REH FINAL FORM */
+ { {0xFEE6u}, 0xFC94u }, /* ARABIC LIGATURE YEH WITH NOON FINAL FORM */
+ }},
+};
+
+
+static const struct ligature_mark_set_t {
+ uint16_t first;
+ struct ligature_pairs_t {
+ uint16_t components[1];
+ uint16_t ligature;
+ } ligatures[5];
+} ligature_mark_table[] =
+{
+ { 0x0651u, {
+ { {0x064Cu}, 0xFC5Eu }, /* ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM */
+ { {0x064Eu}, 0xFC60u }, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */
+ { {0x064Fu}, 0xFC61u }, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */
+ { {0x0650u}, 0xFC62u }, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */
+ { {0x064Bu}, 0xF2EEu }, /* PUA ARABIC LIGATURE SHADDA WITH FATHATAN ISOLATED FORM */
+ }},
+};
+
+
+static const struct ligature_3_set_t {
+ uint16_t first;
+ struct ligature_triplets_t {
+ uint16_t components[2];
+ uint16_t ligature;
+ } ligatures[3];
+} ligature_3_table[] =
+{
+ { 0xFEDFu, {
+ { {0xFEE4u, 0xFEA4u}, 0xFD88u}, /* ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM */
+ { {0xFEE0u, 0xFEEAu}, 0xF201u}, /* PUA ARABIC LIGATURE LELLAH ISOLATED FORM */
+ { {0xFEE4u, 0xFEA0u}, 0xF211u}, /* PUA ARABIC LIGATURE LAM WITH MEEM WITH JEEM INITIAL FORM */
}},
};
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH */
+#endif /* HB_OT_SHAPER_ARABIC_TABLE_HH */
/* == End of generated table == */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-win1256.hh
index 429974d05b..b8d481c813 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic-win1256.hh
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
+#ifndef HB_OT_SHAPER_ARABIC_WIN1256_HH
/*
@@ -342,8 +342,8 @@ OT_TABLE_END
#include "hb.hh" /* Make check-includes.sh happy. */
#endif
#ifdef OT_MEASURE
-#include "hb-ot-shape-complex-arabic-win1256.hh"
+#include "hb-ot-shaper-arabic-win1256.hh"
#endif
-#define HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH */
+#define HB_OT_SHAPER_ARABIC_WIN1256_HH
+#endif /* HB_OT_SHAPER_ARABIC_WIN1256_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.cc
index 224f8b842e..256f8f1d14 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.cc
@@ -28,14 +28,14 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-arabic.hh"
+#include "hb-ot-shaper-arabic.hh"
#include "hb-ot-shape.hh"
/* buffer var allocations */
-#define arabic_shaping_action() complex_var_u8_auxiliary() /* arabic shaping action */
+#define arabic_shaping_action() ot_shaper_var_u8_auxiliary() /* arabic shaping action */
-#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0
+#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_SHAPER0
/* See:
* https://github.com/harfbuzz/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
@@ -81,7 +81,7 @@ enum hb_arabic_joining_type_t {
JOINING_TYPE_X = 8 /* means: use general-category to choose between U or T. */
};
-#include "hb-ot-shape-complex-arabic-table.hh"
+#include "hb-ot-shaper-arabic-table.hh"
static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
{
@@ -161,16 +161,25 @@ static const struct arabic_state_table_entry {
};
-static void
+static bool
arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
record_stch (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
+static bool
+deallocate_buffer_var (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
+ return false;
+}
+
static void
collect_features_arabic (hb_ot_shape_planner_t *plan)
{
@@ -193,26 +202,24 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
* work. However, testing shows that rlig and calt are applied
* together for Mongolian in Uniscribe. As such, we only add a
* pause for Arabic, not other scripts.
- *
- * A pause after calt is required to make KFGQPC Uthmanic Script HAFS
- * work correctly. See https://github.com/harfbuzz/harfbuzz/issues/505
*/
map->enable_feature (HB_TAG('s','t','c','h'));
map->add_gsub_pause (record_stch);
- map->enable_feature (HB_TAG('c','c','m','p'));
- map->enable_feature (HB_TAG('l','o','c','l'));
+ map->enable_feature (HB_TAG('c','c','m','p'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('l','o','c','l'), F_MANUAL_ZWJ);
map->add_gsub_pause (nullptr);
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
{
bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
- map->add_feature (arabic_features[i], has_fallback ? F_HAS_FALLBACK : F_NONE);
+ map->add_feature (arabic_features[i], F_MANUAL_ZWJ | (has_fallback ? F_HAS_FALLBACK : F_NONE));
map->add_gsub_pause (nullptr);
}
+ map->add_gsub_pause (deallocate_buffer_var);
/* Normally, Unicode says a ZWNJ means "don't ligate". In Arabic script
* however, it says a ZWJ should also mean "don't ligate". So we run
@@ -223,10 +230,16 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
if (plan->props.script == HB_SCRIPT_ARABIC)
map->add_gsub_pause (arabic_fallback_shape);
- /* No pause after rclt. See 98460779bae19e4d64d29461ff154b3527bf8420. */
- map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
- map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
- map->add_gsub_pause (nullptr);
+ map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
+ /* https://github.com/harfbuzz/harfbuzz/issues/1573 */
+ if (!map->has_feature (HB_TAG('r','c','l','t')))
+ {
+ map->add_gsub_pause (nullptr);
+ map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
+ }
+
+ map->enable_feature (HB_TAG('l','i','g','a'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('c','l','i','g'), F_MANUAL_ZWJ);
/* The spec includes 'cswh'. Earlier versions of Windows
* used to enable this by default, but testing suggests
@@ -236,11 +249,11 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
* Note that IranNastaliq uses this feature extensively
* to fixup broken glyph sequences. Oh well...
* Test case: U+0643,U+0640,U+0631. */
- //map->enable_feature (HB_TAG('c','s','w','h'));
- map->enable_feature (HB_TAG('m','s','e','t'));
+ //map->enable_feature (HB_TAG('c','s','w','h'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('m','s','e','t'), F_MANUAL_ZWJ);
}
-#include "hb-ot-shape-complex-arabic-fallback.hh"
+#include "hb-ot-shaper-arabic-fallback.hh"
struct arabic_shape_plan_t
{
@@ -319,7 +332,7 @@ arabic_joining (hb_buffer_t *buffer)
if (entry->prev_action != NONE && prev != UINT_MAX)
{
info[prev].arabic_shaping_action() = entry->prev_action;
- buffer->unsafe_to_break (prev, i + 1);
+ buffer->safe_to_insert_tatweel (prev, i + 1);
}
else
{
@@ -353,7 +366,7 @@ arabic_joining (hb_buffer_t *buffer)
if (entry->prev_action != NONE && prev != UINT_MAX)
{
info[prev].arabic_shaping_action() = entry->prev_action;
- buffer->unsafe_to_break (prev, buffer->len);
+ buffer->safe_to_insert_tatweel (prev, buffer->len);
}
else if (2 <= state && state <= 5) /* States that have a possible prev_action. */
{
@@ -400,19 +413,19 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan,
setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
}
-static void
+static bool
arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
-#ifdef HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
- return;
+#ifdef HB_NO_OT_SHAPER_ARABIC_FALLBACK
+ return false;
#endif
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
if (!arabic_plan->do_fallback)
- return;
+ return false;
retry:
arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan;
@@ -428,6 +441,7 @@ retry:
}
arabic_fallback_plan_shape (fallback_plan, font, buffer);
+ return true;
}
/*
@@ -438,14 +452,14 @@ retry:
* marks can use it as well.
*/
-static void
+static bool
record_stch (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
if (!arabic_plan->has_stch)
- return;
+ return false;
/* 'stch' feature was just applied. Look for anything that multiplied,
* and record it for stch treatment later. Note that rtlm, frac, etc
@@ -461,6 +475,7 @@ record_stch (const hb_ot_shape_plan_t *plan,
info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH;
}
+ return false;
}
static void
@@ -541,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);
@@ -582,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++)
{
@@ -619,8 +634,6 @@ postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
hb_font_t *font)
{
apply_stch (plan, buffer, font);
-
- HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
}
/* https://www.unicode.org/reports/tr53/ */
@@ -662,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;
@@ -685,11 +698,11 @@ 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);
- hb_glyph_info_t temp[HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS];
+ 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);
memmove (temp, &info[i], (j - i) * sizeof (hb_glyph_info_t));
@@ -720,7 +733,7 @@ reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
+const hb_ot_shaper_t _hb_ot_shaper_arabic =
{
collect_features_arabic,
nullptr, /* override_features */
@@ -728,12 +741,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
data_destroy_arabic,
nullptr, /* preprocess_text */
postprocess_glyphs_arabic,
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
nullptr, /* compose */
setup_masks_arabic,
- HB_TAG_NONE, /* gpos_tag */
reorder_marks_arabic,
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.hh
index 5bf6ff6338..a025b1a399 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-arabic.hh
@@ -26,12 +26,12 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_HH
+#ifndef HB_OT_SHAPER_ARABIC_HH
+#define HB_OT_SHAPER_ARABIC_HH
#include "hb.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
struct arabic_shape_plan_t;
@@ -47,4 +47,4 @@ setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
hb_buffer_t *buffer,
hb_script_t script);
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_HH */
+#endif /* HB_OT_SHAPER_ARABIC_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-default.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-default.cc
index a755aea098..f0404a4d2c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-default.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-default.cc
@@ -28,10 +28,10 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
+const hb_ot_shaper_t _hb_ot_shaper_default =
{
nullptr, /* collect_features */
nullptr, /* override_features */
@@ -39,19 +39,20 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
nullptr, /* compose */
nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
+#ifndef HB_NO_AAT_SHAPE
/* Same as default but no mark advance zeroing / fallback positioning.
* Dumbest shaper ever, basically. */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_dumber =
+const hb_ot_shaper_t _hb_ot_shaper_dumber =
{
nullptr, /* collect_features */
nullptr, /* override_features */
@@ -59,15 +60,16 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_dumber =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
nullptr, /* compose */
nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
+#endif
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-hangul.cc
index 3bc9e9b961..c90476bc46 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-hangul.cc
@@ -28,7 +28,7 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
/* Hangul shaper */
@@ -119,7 +119,7 @@ data_destroy_hangul (void *data)
#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu))
/* buffer var allocations */
-#define hangul_shaping_feature() complex_var_u8_auxiliary() /* hangul jamo shaping feature */
+#define hangul_shaping_feature() ot_shaper_var_u8_auxiliary() /* hangul jamo shaping feature */
static bool
is_zero_width_char (hb_font_t *font,
@@ -414,7 +414,7 @@ setup_masks_hangul (const hb_ot_shape_plan_t *plan,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
+const hb_ot_shaper_t _hb_ot_shaper_hangul =
{
collect_features_hangul,
override_features_hangul,
@@ -422,12 +422,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
data_destroy_hangul,
preprocess_text_hangul,
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
nullptr, /* decompose */
nullptr, /* compose */
setup_masks_hangul,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-hebrew.cc
index 334d3ded82..e18edd6b3f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-hebrew.cc
@@ -28,7 +28,7 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
static bool
@@ -74,7 +74,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
bool found = (bool) c->unicode->compose (a, b, ab);
-#ifdef HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
+#ifdef HB_NO_OT_SHAPER_HEBREW_FALLBACK
return found;
#endif
@@ -89,7 +89,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
found = true;
}
break;
- case 0x05B7u: /* patah */
+ case 0x05B7u: /* PATAH */
if (a == 0x05F2u) { /* YIDDISH YOD YOD */
*ab = 0xFB1Fu;
found = true;
@@ -162,8 +162,34 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
return found;
}
+static void
+reorder_marks_hebrew (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ unsigned int start,
+ unsigned int end)
+{
+ hb_glyph_info_t *info = buffer->info;
+
+ for (unsigned i = start + 2; i < end; i++)
+ {
+ unsigned c0 = info_cc (info[i - 2]);
+ unsigned c1 = info_cc (info[i - 1]);
+ unsigned c2 = info_cc (info[i - 0]);
+
+ if ((c0 == HB_MODIFIED_COMBINING_CLASS_CCC17 || c0 == HB_MODIFIED_COMBINING_CLASS_CCC18) /* patach or qamats */ &&
+ (c1 == HB_MODIFIED_COMBINING_CLASS_CCC10 || c1 == HB_MODIFIED_COMBINING_CLASS_CCC14) /* sheva or hiriq */ &&
+ (c2 == HB_MODIFIED_COMBINING_CLASS_CCC22 || c2 == HB_UNICODE_COMBINING_CLASS_BELOW) /* meteg or below */)
+ {
+ buffer->merge_clusters (i - 1, i + 1);
+ hb_swap (info[i - 1], info[i]);
+ break;
+ }
+ }
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
+
+}
+
+const hb_ot_shaper_t _hb_ot_shaper_hebrew =
{
nullptr, /* collect_features */
nullptr, /* override_features */
@@ -171,12 +197,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
compose_hebrew,
nullptr, /* setup_masks */
+ reorder_marks_hebrew,
HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */
- nullptr, /* reorder_marks */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};
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
new file mode 100644
index 0000000000..7dd47755af
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh
@@ -0,0 +1,627 @@
+
+#line 1 "hb-ot-shaper-indic-machine.rl"
+/*
+ * 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 HB_OT_SHAPER_INDIC_MACHINE_HH
+#define HB_OT_SHAPER_INDIC_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shaper-indic.hh"
+
+/* buffer var allocations */
+#define indic_category() ot_shaper_var_u8_category() /* indic_category_t */
+#define indic_position() ot_shaper_var_u8_auxiliary() /* indic_position_t */
+
+using indic_category_t = unsigned;
+using indic_position_t = ot_position_t;
+
+#define I_Cat(Cat) indic_syllable_machine_ex_##Cat
+
+enum indic_syllable_type_t {
+ indic_consonant_syllable,
+ indic_vowel_syllable,
+ indic_standalone_cluster,
+ indic_symbol_cluster,
+ indic_broken_cluster,
+ indic_non_indic_cluster,
+};
+
+
+#line 54 "hb-ot-shaper-indic-machine.hh"
+#define indic_syllable_machine_ex_A 9u
+#define indic_syllable_machine_ex_C 1u
+#define indic_syllable_machine_ex_CM 16u
+#define indic_syllable_machine_ex_CS 18u
+#define indic_syllable_machine_ex_DOTTEDCIRCLE 11u
+#define indic_syllable_machine_ex_H 4u
+#define indic_syllable_machine_ex_M 7u
+#define indic_syllable_machine_ex_MPst 13u
+#define indic_syllable_machine_ex_N 3u
+#define indic_syllable_machine_ex_PLACEHOLDER 10u
+#define indic_syllable_machine_ex_RS 12u
+#define indic_syllable_machine_ex_Ra 15u
+#define indic_syllable_machine_ex_Repha 14u
+#define indic_syllable_machine_ex_SM 8u
+#define indic_syllable_machine_ex_Symbol 17u
+#define indic_syllable_machine_ex_V 2u
+#define indic_syllable_machine_ex_VD 9u
+#define indic_syllable_machine_ex_X 0u
+#define indic_syllable_machine_ex_ZWJ 6u
+#define indic_syllable_machine_ex_ZWNJ 5u
+
+
+#line 75 "hb-ot-shaper-indic-machine.hh"
+static const unsigned char _indic_syllable_machine_trans_keys[] = {
+ 8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
+ 8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
+ 8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u,
+ 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 5u, 13u, 8u, 8u, 1u, 18u,
+ 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u,
+ 1u, 15u, 1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u,
+ 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 3u, 16u, 3u, 16u, 4u, 16u,
+ 1u, 15u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u,
+ 1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u, 5u, 9u,
+ 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 13u, 3u, 16u, 3u, 16u,
+ 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u,
+ 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u,
+ 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 13u, 4u, 13u, 3u, 16u, 3u, 16u,
+ 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u,
+ 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u,
+ 5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 13u, 5u, 13u,
+ 5u, 13u, 9u, 9u, 5u, 9u, 1u, 15u, 3u, 9u, 5u, 9u, 5u, 9u, 9u, 9u,
+ 5u, 9u, 1u, 15u, 0
+};
+
+static const char _indic_syllable_machine_key_spans[] = {
+ 1, 10, 9, 9, 1, 10, 10, 10,
+ 1, 9, 9, 1, 10, 10, 10, 10,
+ 1, 9, 9, 1, 10, 10, 10, 1,
+ 9, 9, 1, 10, 10, 9, 1, 18,
+ 14, 14, 13, 15, 5, 5, 1, 5,
+ 15, 15, 15, 11, 10, 9, 9, 10,
+ 5, 7, 5, 14, 14, 14, 14, 13,
+ 15, 14, 14, 13, 15, 5, 1, 5,
+ 15, 15, 11, 10, 9, 9, 10, 5,
+ 5, 7, 5, 14, 14, 10, 14, 14,
+ 13, 15, 14, 15, 5, 1, 5, 15,
+ 15, 11, 10, 9, 9, 14, 10, 5,
+ 5, 7, 5, 14, 10, 10, 14, 14,
+ 13, 15, 14, 15, 5, 1, 5, 15,
+ 15, 11, 10, 9, 9, 14, 10, 5,
+ 5, 7, 5, 16, 14, 16, 10, 9,
+ 9, 1, 5, 15, 7, 5, 5, 1,
+ 5, 15
+};
+
+static const short _indic_syllable_machine_index_offsets[] = {
+ 0, 2, 13, 23, 33, 35, 46, 57,
+ 68, 70, 80, 90, 92, 103, 114, 125,
+ 136, 138, 148, 158, 160, 171, 182, 193,
+ 195, 205, 215, 217, 228, 239, 249, 251,
+ 270, 285, 300, 314, 330, 336, 342, 344,
+ 350, 366, 382, 398, 410, 421, 431, 441,
+ 452, 458, 466, 472, 487, 502, 517, 532,
+ 546, 562, 577, 592, 606, 622, 628, 630,
+ 636, 652, 668, 680, 691, 701, 711, 722,
+ 728, 734, 742, 748, 763, 778, 789, 804,
+ 819, 833, 849, 864, 880, 886, 888, 894,
+ 910, 926, 938, 949, 959, 969, 984, 995,
+ 1001, 1007, 1015, 1021, 1036, 1047, 1058, 1073,
+ 1088, 1102, 1118, 1133, 1149, 1155, 1157, 1163,
+ 1179, 1195, 1207, 1218, 1228, 1238, 1253, 1264,
+ 1270, 1276, 1284, 1290, 1307, 1322, 1339, 1350,
+ 1360, 1370, 1372, 1378, 1394, 1402, 1408, 1414,
+ 1416, 1422
+};
+
+static const unsigned char _indic_syllable_machine_indicies[] = {
+ 1, 0, 2, 3, 3, 4, 5, 0,
+ 0, 0, 0, 4, 0, 3, 3, 4,
+ 6, 0, 0, 0, 0, 4, 0, 3,
+ 3, 4, 5, 0, 0, 0, 0, 4,
+ 0, 4, 0, 7, 3, 3, 4, 5,
+ 0, 0, 0, 0, 4, 0, 2, 3,
+ 3, 4, 5, 0, 0, 0, 8, 4,
+ 0, 10, 11, 11, 12, 13, 9, 9,
+ 9, 9, 12, 9, 14, 9, 11, 11,
+ 12, 15, 9, 9, 9, 9, 12, 9,
+ 11, 11, 12, 13, 9, 9, 9, 9,
+ 12, 9, 12, 9, 16, 11, 11, 12,
+ 13, 9, 9, 9, 9, 12, 9, 10,
+ 11, 11, 12, 13, 9, 9, 9, 17,
+ 12, 9, 10, 11, 11, 12, 13, 9,
+ 9, 9, 18, 12, 9, 20, 21, 21,
+ 22, 23, 19, 19, 19, 24, 22, 19,
+ 25, 19, 21, 21, 22, 27, 26, 26,
+ 26, 26, 22, 26, 21, 21, 22, 23,
+ 19, 19, 19, 19, 22, 19, 22, 26,
+ 20, 21, 21, 22, 23, 19, 19, 19,
+ 19, 22, 19, 28, 21, 21, 22, 23,
+ 19, 19, 19, 19, 22, 19, 30, 31,
+ 31, 32, 33, 29, 29, 29, 34, 32,
+ 29, 35, 29, 31, 31, 32, 36, 29,
+ 29, 29, 29, 32, 29, 31, 31, 32,
+ 33, 29, 29, 29, 29, 32, 29, 32,
+ 29, 30, 31, 31, 32, 33, 29, 29,
+ 29, 29, 32, 29, 37, 31, 31, 32,
+ 33, 29, 29, 29, 29, 32, 29, 21,
+ 21, 22, 38, 0, 0, 0, 0, 22,
+ 0, 40, 39, 42, 43, 44, 45, 46,
+ 47, 22, 23, 48, 49, 49, 24, 22,
+ 50, 51, 52, 53, 54, 41, 56, 57,
+ 58, 59, 4, 5, 60, 55, 55, 8,
+ 4, 55, 55, 61, 55, 62, 57, 63,
+ 63, 4, 5, 60, 55, 55, 55, 4,
+ 55, 55, 61, 55, 57, 63, 63, 4,
+ 5, 60, 55, 55, 55, 4, 55, 55,
+ 61, 55, 42, 55, 55, 55, 64, 65,
+ 55, 1, 60, 55, 55, 55, 55, 55,
+ 42, 55, 66, 66, 55, 1, 60, 55,
+ 60, 55, 55, 67, 60, 55, 60, 55,
+ 60, 55, 55, 55, 60, 55, 42, 55,
+ 68, 55, 66, 66, 55, 1, 60, 55,
+ 55, 55, 55, 55, 42, 55, 42, 55,
+ 55, 55, 66, 66, 55, 1, 60, 55,
+ 55, 55, 55, 55, 42, 55, 42, 55,
+ 55, 55, 66, 65, 55, 1, 60, 55,
+ 55, 55, 55, 55, 42, 55, 69, 70,
+ 71, 71, 4, 5, 60, 55, 55, 55,
+ 4, 55, 70, 71, 71, 4, 5, 60,
+ 55, 55, 55, 4, 55, 71, 71, 4,
+ 5, 60, 55, 55, 55, 4, 55, 60,
+ 55, 55, 67, 60, 55, 55, 55, 4,
+ 55, 72, 73, 73, 4, 5, 60, 55,
+ 55, 55, 4, 55, 64, 74, 55, 1,
+ 60, 55, 64, 55, 66, 66, 55, 1,
+ 60, 55, 66, 74, 55, 1, 60, 55,
+ 56, 57, 63, 63, 4, 5, 60, 55,
+ 55, 55, 4, 55, 55, 61, 55, 56,
+ 57, 58, 63, 4, 5, 60, 55, 55,
+ 8, 4, 55, 55, 61, 55, 76, 77,
+ 78, 79, 12, 13, 80, 75, 75, 18,
+ 12, 75, 75, 81, 75, 82, 77, 83,
+ 79, 12, 13, 80, 75, 75, 75, 12,
+ 75, 75, 81, 75, 77, 83, 79, 12,
+ 13, 80, 75, 75, 75, 12, 75, 75,
+ 81, 75, 84, 75, 75, 75, 85, 86,
+ 75, 14, 80, 75, 75, 75, 75, 75,
+ 84, 75, 87, 77, 88, 89, 12, 13,
+ 80, 75, 75, 17, 12, 75, 75, 81,
+ 75, 90, 77, 83, 83, 12, 13, 80,
+ 75, 75, 75, 12, 75, 75, 81, 75,
+ 77, 83, 83, 12, 13, 80, 75, 75,
+ 75, 12, 75, 75, 81, 75, 84, 75,
+ 75, 75, 91, 86, 75, 14, 80, 75,
+ 75, 75, 75, 75, 84, 75, 80, 75,
+ 75, 92, 80, 75, 80, 75, 80, 75,
+ 75, 75, 80, 75, 84, 75, 93, 75,
+ 91, 91, 75, 14, 80, 75, 75, 75,
+ 75, 75, 84, 75, 84, 75, 75, 75,
+ 91, 91, 75, 14, 80, 75, 75, 75,
+ 75, 75, 84, 75, 94, 95, 96, 96,
+ 12, 13, 80, 75, 75, 75, 12, 75,
+ 95, 96, 96, 12, 13, 80, 75, 75,
+ 75, 12, 75, 96, 96, 12, 13, 80,
+ 75, 75, 75, 12, 75, 80, 75, 75,
+ 92, 80, 75, 75, 75, 12, 75, 97,
+ 98, 98, 12, 13, 80, 75, 75, 75,
+ 12, 75, 85, 99, 75, 14, 80, 75,
+ 91, 91, 75, 14, 80, 75, 85, 75,
+ 91, 91, 75, 14, 80, 75, 91, 99,
+ 75, 14, 80, 75, 87, 77, 83, 83,
+ 12, 13, 80, 75, 75, 75, 12, 75,
+ 75, 81, 75, 87, 77, 88, 83, 12,
+ 13, 80, 75, 75, 17, 12, 75, 75,
+ 81, 75, 10, 11, 11, 12, 13, 75,
+ 75, 75, 75, 12, 75, 76, 77, 83,
+ 79, 12, 13, 80, 75, 75, 75, 12,
+ 75, 75, 81, 75, 101, 45, 102, 102,
+ 22, 23, 48, 100, 100, 100, 22, 100,
+ 100, 52, 100, 45, 102, 102, 22, 23,
+ 48, 100, 100, 100, 22, 100, 100, 52,
+ 100, 103, 100, 100, 100, 104, 105, 100,
+ 25, 48, 100, 100, 100, 100, 100, 103,
+ 100, 44, 45, 106, 107, 22, 23, 48,
+ 100, 100, 24, 22, 100, 100, 52, 100,
+ 103, 100, 100, 100, 108, 105, 100, 25,
+ 48, 100, 100, 100, 100, 100, 103, 100,
+ 48, 100, 100, 109, 48, 100, 48, 100,
+ 48, 100, 100, 100, 48, 100, 103, 100,
+ 110, 100, 108, 108, 100, 25, 48, 100,
+ 100, 100, 100, 100, 103, 100, 103, 100,
+ 100, 100, 108, 108, 100, 25, 48, 100,
+ 100, 100, 100, 100, 103, 100, 111, 112,
+ 113, 113, 22, 23, 48, 100, 100, 100,
+ 22, 100, 112, 113, 113, 22, 23, 48,
+ 100, 100, 100, 22, 100, 113, 113, 22,
+ 23, 48, 100, 100, 100, 22, 100, 48,
+ 100, 100, 109, 48, 100, 100, 100, 22,
+ 100, 44, 45, 102, 102, 22, 23, 48,
+ 100, 100, 100, 22, 100, 100, 52, 100,
+ 114, 115, 115, 22, 23, 48, 100, 100,
+ 100, 22, 100, 104, 116, 100, 25, 48,
+ 100, 108, 108, 100, 25, 48, 100, 104,
+ 100, 108, 108, 100, 25, 48, 100, 108,
+ 116, 100, 25, 48, 100, 44, 45, 106,
+ 102, 22, 23, 48, 100, 100, 24, 22,
+ 100, 100, 52, 100, 20, 21, 21, 22,
+ 23, 117, 117, 117, 24, 22, 117, 20,
+ 21, 21, 22, 23, 117, 117, 117, 117,
+ 22, 117, 119, 120, 121, 122, 32, 33,
+ 123, 118, 118, 34, 32, 118, 118, 124,
+ 118, 125, 120, 122, 122, 32, 33, 123,
+ 118, 118, 118, 32, 118, 118, 124, 118,
+ 120, 122, 122, 32, 33, 123, 118, 118,
+ 118, 32, 118, 118, 124, 118, 126, 118,
+ 118, 118, 127, 128, 118, 35, 123, 118,
+ 118, 118, 118, 118, 126, 118, 119, 120,
+ 121, 49, 32, 33, 123, 118, 118, 34,
+ 32, 118, 118, 124, 118, 126, 118, 118,
+ 118, 129, 128, 118, 35, 123, 118, 118,
+ 118, 118, 118, 126, 118, 123, 118, 118,
+ 130, 123, 118, 123, 118, 123, 118, 118,
+ 118, 123, 118, 126, 118, 131, 118, 129,
+ 129, 118, 35, 123, 118, 118, 118, 118,
+ 118, 126, 118, 126, 118, 118, 118, 129,
+ 129, 118, 35, 123, 118, 118, 118, 118,
+ 118, 126, 118, 132, 133, 134, 134, 32,
+ 33, 123, 118, 118, 118, 32, 118, 133,
+ 134, 134, 32, 33, 123, 118, 118, 118,
+ 32, 118, 134, 134, 32, 33, 123, 118,
+ 118, 118, 32, 118, 123, 118, 118, 130,
+ 123, 118, 118, 118, 32, 118, 119, 120,
+ 122, 122, 32, 33, 123, 118, 118, 118,
+ 32, 118, 118, 124, 118, 135, 136, 136,
+ 32, 33, 123, 118, 118, 118, 32, 118,
+ 127, 137, 118, 35, 123, 118, 129, 129,
+ 118, 35, 123, 118, 127, 118, 129, 129,
+ 118, 35, 123, 118, 129, 137, 118, 35,
+ 123, 118, 42, 43, 44, 45, 106, 102,
+ 22, 23, 48, 49, 49, 24, 22, 100,
+ 42, 52, 100, 56, 138, 58, 59, 4,
+ 5, 60, 55, 55, 8, 4, 55, 55,
+ 61, 55, 42, 43, 44, 45, 139, 140,
+ 22, 141, 142, 55, 49, 24, 22, 55,
+ 42, 52, 55, 20, 143, 143, 22, 141,
+ 60, 55, 55, 24, 22, 55, 60, 55,
+ 55, 67, 60, 55, 55, 55, 22, 55,
+ 142, 55, 55, 144, 142, 55, 55, 55,
+ 22, 55, 142, 55, 142, 55, 55, 55,
+ 142, 55, 42, 55, 68, 20, 143, 143,
+ 22, 141, 60, 55, 55, 55, 22, 55,
+ 42, 55, 146, 145, 147, 147, 145, 40,
+ 148, 145, 147, 147, 145, 40, 148, 145,
+ 148, 145, 145, 149, 148, 145, 148, 145,
+ 148, 145, 145, 145, 148, 145, 42, 117,
+ 117, 117, 117, 117, 117, 117, 117, 49,
+ 117, 117, 117, 117, 42, 117, 0
+};
+
+static const unsigned char _indic_syllable_machine_trans_targs[] = {
+ 31, 37, 42, 2, 43, 46, 4, 50,
+ 51, 31, 60, 9, 66, 69, 61, 11,
+ 74, 75, 78, 31, 83, 17, 89, 92,
+ 93, 84, 31, 19, 98, 31, 107, 24,
+ 113, 116, 117, 108, 26, 122, 127, 31,
+ 134, 31, 32, 53, 79, 81, 100, 101,
+ 85, 102, 123, 124, 94, 132, 137, 31,
+ 33, 35, 6, 52, 38, 47, 34, 1,
+ 36, 40, 0, 39, 41, 44, 45, 3,
+ 48, 5, 49, 31, 54, 56, 14, 77,
+ 62, 70, 55, 7, 57, 72, 64, 58,
+ 13, 76, 59, 8, 63, 65, 67, 68,
+ 10, 71, 12, 73, 31, 80, 20, 82,
+ 96, 87, 15, 99, 16, 86, 88, 90,
+ 91, 18, 95, 21, 97, 31, 31, 103,
+ 105, 22, 27, 109, 118, 104, 106, 120,
+ 111, 23, 110, 112, 114, 115, 25, 119,
+ 28, 121, 125, 126, 131, 128, 129, 29,
+ 130, 31, 133, 30, 135, 136
+};
+
+static const char _indic_syllable_machine_trans_actions[] = {
+ 1, 0, 2, 0, 2, 0, 0, 2,
+ 2, 3, 2, 0, 2, 0, 0, 0,
+ 2, 2, 2, 4, 2, 0, 5, 0,
+ 5, 0, 6, 0, 2, 7, 2, 0,
+ 2, 0, 2, 0, 0, 2, 0, 8,
+ 0, 11, 2, 2, 5, 0, 12, 12,
+ 0, 2, 5, 2, 5, 2, 0, 13,
+ 2, 0, 0, 2, 0, 2, 2, 0,
+ 2, 2, 0, 0, 2, 2, 2, 0,
+ 0, 0, 2, 14, 2, 0, 0, 2,
+ 0, 2, 2, 0, 2, 2, 2, 2,
+ 0, 2, 2, 0, 0, 2, 2, 2,
+ 0, 0, 0, 2, 15, 5, 0, 5,
+ 2, 2, 0, 5, 0, 0, 2, 5,
+ 5, 0, 0, 0, 2, 16, 17, 2,
+ 0, 0, 0, 0, 2, 2, 2, 2,
+ 2, 0, 0, 2, 2, 2, 0, 0,
+ 0, 2, 0, 18, 18, 0, 0, 0,
+ 0, 19, 2, 0, 0, 0
+};
+
+static const char _indic_syllable_machine_to_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
+
+static const char _indic_syllable_machine_from_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
+
+static const short _indic_syllable_machine_eof_trans[] = {
+ 1, 1, 1, 1, 1, 1, 1, 10,
+ 10, 10, 10, 10, 10, 10, 10, 20,
+ 20, 27, 20, 27, 20, 20, 30, 30,
+ 30, 30, 30, 30, 30, 1, 40, 0,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 101,
+ 101, 101, 101, 101, 101, 101, 101, 101,
+ 101, 101, 101, 101, 101, 101, 101, 101,
+ 101, 101, 101, 101, 118, 118, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 101, 56, 56, 56, 56,
+ 56, 56, 56, 56, 146, 146, 146, 146,
+ 146, 118
+};
+
+static const int indic_syllable_machine_start = 31;
+static const int indic_syllable_machine_first_final = 31;
+static const int indic_syllable_machine_error = -1;
+
+static const int indic_syllable_machine_en_main = 31;
+
+
+#line 58 "hb-ot-shaper-indic-machine.rl"
+
+
+
+#line 118 "hb-ot-shaper-indic-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ 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++; \
+ if (syllable_serial == 16) syllable_serial = 1; \
+ } HB_STMT_END
+
+inline void
+find_syllables_indic (hb_buffer_t *buffer)
+{
+ unsigned int p, pe, eof, ts, te, act;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 453 "hb-ot-shaper-indic-machine.hh"
+ {
+ cs = indic_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 138 "hb-ot-shaper-indic-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 465 "hb-ot-shaper-indic-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const unsigned char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _indic_syllable_machine_from_state_actions[cs] ) {
+ case 10:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 477 "hb-ot-shaper-indic-machine.hh"
+ }
+
+ _keys = _indic_syllable_machine_trans_keys + (cs<<1);
+ _inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
+
+ _slen = _indic_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
+ ( info[p].indic_category()) <= _keys[1] ?
+ ( info[p].indic_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _indic_syllable_machine_trans_targs[_trans];
+
+ if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _indic_syllable_machine_trans_actions[_trans] ) {
+ case 2:
+#line 1 "NONE"
+ {te = p+1;}
+ break;
+ case 11:
+#line 114 "hb-ot-shaper-indic-machine.rl"
+ {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
+ break;
+ case 13:
+#line 109 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
+ break;
+ case 14:
+#line 110 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
+ break;
+ case 17:
+#line 111 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
+ break;
+ case 19:
+#line 112 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
+ break;
+ case 15:
+#line 113 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 16:
+#line 114 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
+ break;
+ case 1:
+#line 109 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
+ break;
+ case 3:
+#line 110 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
+ break;
+ case 7:
+#line 111 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
+ break;
+ case 8:
+#line 112 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
+ break;
+ case 4:
+#line 113 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 6:
+#line 1 "NONE"
+ { switch( act ) {
+ case 1:
+ {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
+ break;
+ case 5:
+ {{p = ((te))-1;} found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+ break;
+ case 6:
+ {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
+ break;
+ }
+ }
+ break;
+ case 18:
+#line 1 "NONE"
+ {te = p+1;}
+#line 109 "hb-ot-shaper-indic-machine.rl"
+ {act = 1;}
+ break;
+ case 5:
+#line 1 "NONE"
+ {te = p+1;}
+#line 113 "hb-ot-shaper-indic-machine.rl"
+ {act = 5;}
+ break;
+ case 12:
+#line 1 "NONE"
+ {te = p+1;}
+#line 114 "hb-ot-shaper-indic-machine.rl"
+ {act = 6;}
+ break;
+#line 559 "hb-ot-shaper-indic-machine.hh"
+ }
+
+_again:
+ switch ( _indic_syllable_machine_to_state_actions[cs] ) {
+ case 9:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 566 "hb-ot-shaper-indic-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _indic_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 146 "hb-ot-shaper-indic-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_INDIC_MACHINE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-table.cc
new file mode 100644
index 0000000000..d9fb0510e4
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-table.cc
@@ -0,0 +1,561 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
+ *
+ * on files with these headers:
+ *
+ * # IndicSyllabicCategory-15.0.0.txt
+ * # Date: 2022-05-26, 02:18:00 GMT [KW, RP]
+ * # IndicPositionalCategory-15.0.0.txt
+ * # Date: 2022-05-26, 02:18:00 GMT [KW, RP]
+ * # Blocks-15.0.0.txt
+ * # Date: 2022-01-28, 20:58:00 GMT [KW]
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-indic.hh"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#include "hb-ot-shaper-indic-machine.hh"
+#include "hb-ot-shaper-khmer-machine.hh"
+#include "hb-ot-shaper-myanmar-machine.hh"
+
+/* indic */
+#define OT_X I_Cat(X)
+#define OT_C I_Cat(C)
+#define OT_V I_Cat(V)
+#define OT_N I_Cat(N)
+#define OT_H I_Cat(H)
+#define OT_ZWNJ I_Cat(ZWNJ)
+#define OT_ZWJ I_Cat(ZWJ)
+#define OT_M I_Cat(M)
+#define OT_SM I_Cat(SM)
+#define OT_A I_Cat(A)
+#define OT_VD I_Cat(VD)
+#define OT_PLACEHOLDER I_Cat(PLACEHOLDER)
+#define OT_DOTTEDCIRCLE I_Cat(DOTTEDCIRCLE)
+#define OT_RS I_Cat(RS)
+#define OT_MPst I_Cat(MPst)
+#define OT_Repha I_Cat(Repha)
+#define OT_Ra I_Cat(Ra)
+#define OT_CM I_Cat(CM)
+#define OT_Symbol I_Cat(Symbol)
+#define OT_CS I_Cat(CS)
+/* khmer */
+#define OT_VAbv K_Cat(VAbv)
+#define OT_VBlw K_Cat(VBlw)
+#define OT_VPre K_Cat(VPre)
+#define OT_VPst K_Cat(VPst)
+#define OT_Robatic K_Cat(Robatic)
+#define OT_Xgroup K_Cat(Xgroup)
+#define OT_Ygroup K_Cat(Ygroup)
+/* myanmar */
+static_assert (OT_VAbv == M_Cat(VAbv), "");
+static_assert (OT_VBlw == M_Cat(VBlw), "");
+static_assert (OT_VPre == M_Cat(VPre), "");
+static_assert (OT_VPst == M_Cat(VPst), "");
+#define OT_IV M_Cat(IV)
+#define OT_As M_Cat(As)
+#define OT_DB M_Cat(DB)
+#define OT_GB M_Cat(GB)
+#define OT_MH M_Cat(MH)
+#define OT_MR M_Cat(MR)
+#define OT_MW M_Cat(MW)
+#define OT_MY M_Cat(MY)
+#define OT_PT M_Cat(PT)
+#define OT_VS M_Cat(VS)
+#define OT_ML M_Cat(ML)
+
+
+#define _OT_A OT_A /* 53 chars; A */
+#define _OT_As OT_As /* 1 chars; As */
+#define _OT_C OT_C /* 478 chars; C */
+#define _OT_CM OT_CM /* 1 chars; CM */
+#define _OT_CS OT_CS /* 2 chars; CS */
+#define _OT_DC OT_DOTTEDCIRCLE /* 1 chars; DOTTEDCIRCLE */
+#define _OT_H OT_H /* 11 chars; H */
+#define _OT_M OT_M /* 142 chars; M */
+#define _OT_MH OT_MH /* 1 chars; MH */
+#define _OT_ML OT_ML /* 1 chars; ML */
+#define _OT_MP OT_MPst /* 1 chars; MPst */
+#define _OT_MR OT_MR /* 1 chars; MR */
+#define _OT_MW OT_MW /* 2 chars; MW */
+#define _OT_MY OT_MY /* 3 chars; MY */
+#define _OT_N OT_N /* 17 chars; N */
+#define _OT_GB OT_PLACEHOLDER /* 165 chars; PLACEHOLDER */
+#define _OT_PT OT_PT /* 8 chars; PT */
+#define _OT_R OT_Ra /* 14 chars; Ra */
+#define _OT_Rf OT_Repha /* 1 chars; Repha */
+#define _OT_Rt OT_Robatic /* 3 chars; Robatic */
+#define _OT_SM OT_SM /* 56 chars; SM */
+#define _OT_S OT_Symbol /* 22 chars; Symbol */
+#define _OT_V OT_V /* 172 chars; V */
+#define _OT_VA OT_VAbv /* 18 chars; VAbv */
+#define _OT_VB OT_VBlw /* 7 chars; VBlw */
+#define _OT_VL OT_VPre /* 5 chars; VPre */
+#define _OT_VR OT_VPst /* 13 chars; VPst */
+#define _OT_VS OT_VS /* 16 chars; VS */
+#define _OT_X OT_X /* 2 chars; X */
+#define _OT_Xg OT_Xgroup /* 7 chars; Xgroup */
+#define _OT_Yg OT_Ygroup /* 4 chars; Ygroup */
+#define _OT_ZWJ OT_ZWJ /* 1 chars; ZWJ */
+#define _OT_ZWNJ OT_ZWNJ /* 1 chars; ZWNJ */
+
+#define _POS_T POS_ABOVE_C /* 22 chars; ABOVE_C */
+#define _POS_A POS_AFTER_MAIN /* 3 chars; AFTER_MAIN */
+#define _POS_AP POS_AFTER_POST /* 50 chars; AFTER_POST */
+#define _POS_AS POS_AFTER_SUB /* 51 chars; AFTER_SUB */
+#define _POS_C POS_BASE_C /* 833 chars; BASE_C */
+#define _POS_BS POS_BEFORE_SUB /* 25 chars; BEFORE_SUB */
+#define _POS_B POS_BELOW_C /* 13 chars; BELOW_C */
+#define _POS_X POS_END /* 71 chars; END */
+#define _POS_R POS_POST_C /* 13 chars; POST_C */
+#define _POS_L POS_PRE_C /* 5 chars; PRE_C */
+#define _POS_LM POS_PRE_M /* 14 chars; PRE_M */
+#define _POS_SM POS_SMVD /* 130 chars; SMVD */
+
+#pragma GCC diagnostic pop
+
+#define INDIC_COMBINE_CATEGORIES(S,M) ((S) | ((M) << 8))
+
+#define _(S,M) INDIC_COMBINE_CATEGORIES (_OT_##S, _POS_##M)
+
+
+static const uint16_t indic_table[] = {
+
+
+#define indic_offset_0x0028u 0
+
+
+ /* Basic Latin */
+
+ /* 0028 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(X,X), _(X,X),
+ /* 0030 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0038 */ _(GB,C), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x00b0u 24
+
+
+ /* Latin-1 Supplement */
+
+ /* 00B0 */ _(X,X), _(X,X),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00B8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00C0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00C8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00D0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C),
+
+#define indic_offset_0x0900u 64
+
+
+ /* Devanagari */
+
+ /* 0900 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 0908 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 0910 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0918 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0920 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0928 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0930 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0938 */ _(C,C), _(C,C), _(M,AS), _(M,AS), _(N,X), _(S,SM), _(M,AS), _(M,LM),
+ /* 0940 */ _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS),
+ /* 0948 */ _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(H,B), _(M,LM), _(M,AS),
+ /* 0950 */ _(X,X), _(A,SM), _(A,SM),_(SM,SM),_(SM,SM), _(M,AS), _(M,AS), _(M,AS),
+ /* 0958 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0960 */ _(V,C), _(V,C), _(M,AS), _(M,AS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0968 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0970 */ _(X,X), _(X,X), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 0978 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+
+ /* Bengali */
+
+ /* 0980 */ _(GB,C),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0988 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(V,C),
+ /* 0990 */ _(V,C), _(X,X), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0998 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 09A0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 09A8 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 09B0 */ _(R,C), _(X,X), _(C,C), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C),
+ /* 09B8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,AP), _(M,LM),
+ /* 09C0 */ _(M,AP), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(X,X), _(X,X), _(M,LM),
+ /* 09C8 */ _(M,LM), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(C,C), _(X,X),
+ /* 09D0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP),
+ /* 09D8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C),
+ /* 09E0 */ _(V,C), _(V,C), _(M,AS), _(M,AS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 09E8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 09F0 */ _(R,C), _(C,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 09F8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(X,X),_(SM,SM), _(X,X),
+
+ /* Gurmukhi */
+
+ /* 0A00 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0A08 */ _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(X,X), _(X,X), _(V,C),
+ /* 0A10 */ _(V,C), _(X,X), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0A18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0A20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0A28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0A30 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(X,X),
+ /* 0A38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(X,X), _(M,AP), _(M,LM),
+ /* 0A40 */_(MP,AP), _(M,AP), _(M,AP), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP),
+ /* 0A48 */ _(M,AP), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X),
+ /* 0A50 */ _(X,X), _(M,B), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0A58 */ _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(X,X), _(C,C), _(X,X),
+ /* 0A60 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0A68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0A70 */_(SM,SM),_(SM,SM), _(C,C), _(C,C), _(X,X), _(CM,C), _(X,X), _(X,X),
+ /* 0A78 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Gujarati */
+
+ /* 0A80 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0A88 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C),
+ /* 0A90 */ _(V,C), _(V,C), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0A98 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0AA0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0AA8 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0AB0 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(C,C),
+ /* 0AB8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,AP), _(M,LM),
+ /* 0AC0 */ _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(M,AS), _(X,X), _(M,AS),
+ /* 0AC8 */ _(M,AS), _(M,AP), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X),
+ /* 0AD0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0AD8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0AE0 */ _(V,C), _(V,C), _(M,AP), _(M,AP), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0AE8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0AF0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0AF8 */ _(X,X), _(C,C), _(A,SM), _(N,X), _(A,SM), _(N,X), _(N,X), _(N,X),
+
+ /* Oriya */
+
+ /* 0B00 */ _(X,X),_(SM,BS),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0B08 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(V,C),
+ /* 0B10 */ _(V,C), _(X,X), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0B18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0B20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0B28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0B30 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(C,C),
+ /* 0B38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,AP), _(M,A),
+ /* 0B40 */ _(M,AP), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(X,X), _(X,X), _(M,LM),
+ /* 0B48 */ _(M,A), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X),
+ /* 0B50 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(N,X), _(M,A), _(M,AP),
+ /* 0B58 */ _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C),
+ /* 0B60 */ _(V,C), _(V,C), _(M,AS), _(M,AS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0B68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0B70 */ _(X,X), _(C,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0B78 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Tamil */
+
+ /* 0B80 */ _(X,X), _(X,X),_(SM,SM), _(X,X), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0B88 */ _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(X,X), _(V,C), _(V,C),
+ /* 0B90 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(X,X), _(X,X),
+ /* 0B98 */ _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(X,X), _(C,C), _(C,C),
+ /* 0BA0 */ _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X), _(X,X), _(X,X),
+ /* 0BA8 */ _(C,C), _(C,C), _(C,C), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C),
+ /* 0BB0 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0BB8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP), _(M,AP),
+ /* 0BC0 */ _(M,AS), _(M,AP), _(M,AP), _(X,X), _(X,X), _(X,X), _(M,LM), _(M,LM),
+ /* 0BC8 */ _(M,LM), _(X,X), _(M,AP), _(M,AP), _(M,AP), _(H,T), _(X,X), _(X,X),
+ /* 0BD0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP),
+ /* 0BD8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0BE0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0BE8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0BF0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0BF8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Telugu */
+
+ /* 0C00 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(V,C), _(V,C), _(V,C),
+ /* 0C08 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C), _(V,C),
+ /* 0C10 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0C18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C30 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,BS), _(M,BS),
+ /* 0C40 */ _(M,BS), _(M,BS), _(M,BS), _(M,AS), _(M,AS), _(X,X), _(M,BS), _(M,BS),
+ /* 0C48 */ _(M,BS), _(X,X), _(M,BS), _(M,BS), _(M,BS), _(H,T), _(X,X), _(X,X),
+ /* 0C50 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,BS), _(M,BS), _(X,X),
+ /* 0C58 */ _(C,C), _(C,C), _(C,C), _(X,X), _(X,X), _(C,C), _(X,X), _(X,X),
+ /* 0C60 */ _(V,C), _(V,C), _(M,BS), _(M,BS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0C68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0C70 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0C78 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Kannada */
+
+ /* 0C80 */ _(GB,C),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0C88 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C), _(V,C),
+ /* 0C90 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0C98 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0CA0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0CA8 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0CB0 */ _(R,C), _(C,C), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(C,C),
+ /* 0CB8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,BS), _(M,BS),
+ /* 0CC0 */ _(M,BS), _(M,BS), _(M,BS), _(M,AS), _(M,AS), _(X,X), _(M,BS), _(M,AS),
+ /* 0CC8 */ _(M,AS), _(X,X), _(M,AS), _(M,AS), _(M,BS), _(H,T), _(X,X), _(X,X),
+ /* 0CD0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AS), _(M,AS), _(X,X),
+ /* 0CD8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X),
+ /* 0CE0 */ _(V,C), _(V,C), _(M,BS), _(M,BS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0CE8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0CF0 */ _(X,X), _(CS,C), _(CS,C),_(SM,SM), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0CF8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Malayalam */
+
+ /* 0D00 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(GB,C), _(V,C), _(V,C), _(V,C),
+ /* 0D08 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C), _(V,C),
+ /* 0D10 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0D18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D28 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D30 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D38 */ _(C,C), _(C,C), _(C,C), _(M,AS), _(M,AS), _(S,SM), _(M,AP), _(M,AP),
+ /* 0D40 */ _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(X,X), _(M,LM), _(M,LM),
+ /* 0D48 */ _(M,LM), _(X,X), _(M,AP), _(M,AP), _(M,AP), _(H,T), _(Rf,X), _(X,X),
+ /* 0D50 */ _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(C,C), _(M,AP),
+ /* 0D58 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(V,C),
+ /* 0D60 */ _(V,C), _(V,C), _(M,AP), _(M,AP), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0D68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0D70 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0D78 */ _(X,X), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+
+#define indic_offset_0x1000u 1216
+
+
+ /* Myanmar */
+
+ /* 1000 */ _(C,C), _(C,C), _(C,C), _(C,C), _(R,C), _(C,C), _(C,C), _(C,C),
+ /* 1008 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1010 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1018 */ _(C,C), _(C,C), _(C,C), _(R,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1020 */ _(C,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 1028 */ _(V,C), _(V,C), _(V,C), _(VR,R), _(VR,R), _(VA,T), _(VA,T), _(VB,B),
+ /* 1030 */ _(VB,B), _(VL,L), _(A,SM), _(VA,T), _(VA,T), _(VA,T), _(A,SM), _(N,X),
+ /* 1038 */_(SM,SM), _(H,X), _(As,X), _(MY,X), _(MR,X), _(MW,X), _(MH,X), _(C,C),
+ /* 1040 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 1048 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X), _(X,X), _(C,C), _(X,X),
+ /* 1050 */ _(C,C), _(C,C), _(V,C), _(V,C), _(V,C), _(V,C), _(VR,R), _(VR,R),
+ /* 1058 */ _(VB,B), _(VB,B), _(R,C), _(C,C), _(C,C), _(C,C), _(MY,X), _(MY,X),
+ /* 1060 */ _(ML,X), _(C,C), _(VR,R), _(PT,X), _(PT,X), _(C,C), _(C,C), _(VR,R),
+ /* 1068 */ _(VR,R), _(PT,X), _(PT,X), _(PT,X), _(PT,X), _(PT,X), _(C,C), _(C,C),
+ /* 1070 */ _(C,C), _(VA,T), _(VA,T), _(VA,T), _(VA,T), _(C,C), _(C,C), _(C,C),
+ /* 1078 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1080 */ _(C,C), _(C,C), _(MW,X), _(VR,R), _(VL,L), _(VA,T), _(VA,T),_(SM,SM),
+ /* 1088 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(C,C),_(SM,SM),
+ /* 1090 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 1098 */ _(GB,C), _(GB,C),_(SM,SM),_(SM,SM),_(SM,SM), _(VA,T), _(X,X), _(X,X),
+
+#define indic_offset_0x1780u 1376
+
+
+ /* Khmer */
+
+ /* 1780 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1788 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1790 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1798 */ _(C,C), _(C,C), _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 17A0 */ _(C,C), _(C,C), _(C,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 17A8 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 17B0 */ _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(VR,R), _(VA,T),
+ /* 17B8 */ _(VA,T), _(VA,T), _(VA,T), _(VB,B), _(VB,B), _(VB,B), _(VA,T), _(VR,R),
+ /* 17C0 */ _(VR,R), _(VL,L), _(VL,L), _(VL,L), _(VR,R), _(VR,R), _(Xg,X), _(Yg,X),
+ /* 17C8 */ _(Yg,X), _(Rt,X), _(Rt,X), _(Xg,X), _(Rt,X), _(Xg,X), _(Xg,X), _(Xg,X),
+ /* 17D0 */ _(Xg,X), _(Xg,X), _(H,X), _(Yg,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 17D8 */ _(X,X), _(GB,C), _(X,X), _(X,X), _(S,SM), _(Yg,X), _(X,X), _(X,X),
+ /* 17E0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 17E8 */ _(GB,C), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x1cd0u 1488
+
+
+ /* Vedic Extensions */
+
+ /* 1CD0 */ _(A,SM), _(A,SM), _(A,SM), _(X,X), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* 1CD8 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* 1CE0 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* 1CE8 */ _(A,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM), _(A,SM), _(S,SM), _(S,SM),
+ /* 1CF0 */ _(S,SM), _(S,SM), _(C,C), _(C,C), _(A,SM), _(C,C), _(C,C), _(A,SM),
+ /* 1CF8 */ _(A,SM), _(A,SM), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x2008u 1536
+
+
+ /* General Punctuation */
+
+ /* 2008 */ _(X,X), _(X,X), _(X,X), _(X,X),_(ZWNJ,X),_(ZWJ,X), _(X,X), _(X,X),
+ /* 2010 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X), _(X,X),
+ /* 2018 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 2020 */ _(X,X), _(X,X), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x2070u 1568
+
+
+ /* Superscripts and Subscripts */
+
+ /* 2070 */ _(X,X), _(X,X), _(X,X), _(X,X),_(SM,SM), _(X,X), _(X,X), _(X,X),
+ /* 2078 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 2080 */ _(X,X), _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x25f8u 1592
+
+
+ /* Geometric Shapes */
+
+ /* 25F8 */ _(X,X), _(X,X), _(X,X), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X),
+
+#define indic_offset_0xa8e0u 1600
+
+
+ /* Devanagari Extended */
+
+ /* A8E0 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* A8E8 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* A8F0 */ _(A,SM), _(A,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM),
+ /* A8F8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(V,C), _(M,AS),
+
+#define indic_offset_0xa9e0u 1632
+
+
+ /* Myanmar Extended-B */
+
+ /* A9E0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(VA,T), _(X,X), _(C,C),
+ /* A9E8 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* A9F0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* A9F8 */ _(GB,C), _(GB,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(X,X),
+
+#define indic_offset_0xaa60u 1664
+
+
+ /* Myanmar Extended-A */
+
+ /* AA60 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* AA68 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* AA70 */ _(X,X), _(C,C), _(C,C), _(C,C), _(GB,C), _(GB,C), _(GB,C), _(X,X),
+ /* AA78 */ _(X,X), _(X,X), _(C,C), _(PT,X), _(N,X), _(N,X), _(C,C), _(C,C),
+
+#define indic_offset_0xfe00u 1696
+
+
+ /* Variation Selectors */
+
+ /* FE00 */ _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X),
+ /* FE08 */ _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X),
+
+#define indic_offset_0x11300u 1712
+
+
+ /* Grantha */
+
+ /* 11300 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x11338u 1720
+
+ /* 11338 */ _(X,X), _(X,X), _(X,X), _(N,X), _(N,X), _(X,X), _(X,X), _(X,X),
+
+}; /* Table items: 1728; occupancy: 71% */
+
+uint16_t
+hb_indic_get_categories (hb_codepoint_t u)
+{
+ switch (u >> 12)
+ {
+ case 0x0u:
+ if (unlikely (u == 0x00A0u)) return _(GB,C);
+ if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0D7Fu)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
+ break;
+
+ case 0x1u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
+ break;
+
+ case 0x2u:
+ if (unlikely (u == 0x25CCu)) return _(DC,C);
+ if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2027u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x25F8u, 0x25FFu)) return indic_table[u - 0x25F8u + indic_offset_0x25f8u];
+ break;
+
+ case 0xAu:
+ if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8FFu)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
+ break;
+
+ case 0xFu:
+ if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return indic_table[u - 0xFE00u + indic_offset_0xfe00u];
+ break;
+
+ case 0x11u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x11307u)) return indic_table[u - 0x11300u + indic_offset_0x11300u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x11338u, 0x1133Fu)) return indic_table[u - 0x11338u + indic_offset_0x11338u];
+ break;
+
+ default:
+ break;
+ }
+ return _(X,X);
+}
+
+#undef _
+#undef INDIC_COMBINE_CATEGORIES
+
+#undef _OT_A
+#undef _OT_As
+#undef _OT_C
+#undef _OT_CM
+#undef _OT_CS
+#undef _OT_DC
+#undef _OT_H
+#undef _OT_M
+#undef _OT_MH
+#undef _OT_ML
+#undef _OT_MP
+#undef _OT_MR
+#undef _OT_MW
+#undef _OT_MY
+#undef _OT_N
+#undef _OT_GB
+#undef _OT_PT
+#undef _OT_R
+#undef _OT_Rf
+#undef _OT_Rt
+#undef _OT_SM
+#undef _OT_S
+#undef _OT_V
+#undef _OT_VA
+#undef _OT_VB
+#undef _OT_VL
+#undef _OT_VR
+#undef _OT_VS
+#undef _OT_X
+#undef _OT_Xg
+#undef _OT_Yg
+#undef _OT_ZWJ
+#undef _OT_ZWNJ
+
+#undef _POS_T
+#undef _POS_A
+#undef _POS_AP
+#undef _POS_AS
+#undef _POS_C
+#undef _POS_BS
+#undef _POS_B
+#undef _POS_X
+#undef _POS_R
+#undef _POS_L
+#undef _POS_LM
+#undef _POS_SM
+
+#endif
+
+/* == End of generated table == */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.cc
index c80f7df6a9..e3818cc37f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.cc
@@ -28,9 +28,9 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-indic.hh"
-#include "hb-ot-shape-complex-indic-machine.hh"
-#include "hb-ot-shape-complex-vowel-constraints.hh"
+#include "hb-ot-shaper-indic.hh"
+#include "hb-ot-shaper-indic-machine.hh"
+#include "hb-ot-shaper-vowel-constraints.hh"
#include "hb-ot-layout.hh"
@@ -39,6 +39,79 @@
*/
+static inline void
+set_indic_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+
+ info.indic_category() = (indic_category_t) (type & 0xFFu);
+ info.indic_position() = (indic_position_t) (type >> 8);
+}
+
+
+static inline bool
+is_one_of (const hb_glyph_info_t &info, unsigned int flags)
+{
+ /* If it ligated, all bets are off. */
+ if (_hb_glyph_info_ligated (&info)) return false;
+ return !!(FLAG_UNSAFE (info.indic_category()) & flags);
+}
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
+ * cannot happen in a consonant syllable. The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right!
+ *
+ * Keep in sync with consonant_categories in the generator. */
+#define CONSONANT_FLAGS_INDIC (FLAG (I_Cat(C)) | FLAG (I_Cat(CS)) | FLAG (I_Cat(Ra)) | FLAG (I_Cat(CM)) | FLAG (I_Cat(V)) | FLAG (I_Cat(PLACEHOLDER)) | FLAG (I_Cat(DOTTEDCIRCLE)))
+
+static inline bool
+is_consonant (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, CONSONANT_FLAGS_INDIC);
+}
+
+#define JOINER_FLAGS (FLAG (I_Cat(ZWJ)) | FLAG (I_Cat(ZWNJ)))
+
+static inline bool
+is_joiner (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, JOINER_FLAGS);
+}
+
+static inline bool
+is_halant (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, FLAG (I_Cat(H)));
+}
+
+struct hb_indic_would_substitute_feature_t
+{
+ void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
+ {
+ zero_context = zero_context_;
+ lookups = map->get_stage_lookups (0/*GSUB*/,
+ map->get_feature_stage (0/*GSUB*/, feature_tag));
+ }
+
+ bool would_substitute (const hb_codepoint_t *glyphs,
+ unsigned int glyphs_count,
+ hb_face_t *face) const
+ {
+ for (const auto &lookup : lookups)
+ if (hb_ot_layout_lookup_would_substitute (face, lookup.index, glyphs, glyphs_count, zero_context))
+ return true;
+ return false;
+ }
+
+ private:
+ hb_array_t<const hb_ot_map_t::lookup_map_t> lookups;
+ bool zero_context;
+};
+
+
/*
* Indic configurations. Note that we do not want to keep every single script-specific
* behavior in these tables necessarily. This should mainly be used for per-script
@@ -47,10 +120,6 @@
* instead of adding a new flag in these structs.
*/
-enum base_position_t {
- BASE_POS_LAST_SINHALA,
- BASE_POS_LAST
-};
enum reph_position_t {
REPH_POS_AFTER_MAIN = POS_AFTER_MAIN,
REPH_POS_BEFORE_SUB = POS_BEFORE_SUB,
@@ -72,7 +141,6 @@ struct indic_config_t
hb_script_t script;
bool has_old_spec;
hb_codepoint_t virama;
- base_position_t base_pos;
reph_position_t reph_pos;
reph_mode_t reph_mode;
blwf_mode_t blwf_mode;
@@ -81,26 +149,19 @@ struct indic_config_t
static const indic_config_t indic_configs[] =
{
/* Default. Should be first. */
- {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY},
- {HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY},
- {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA,
- REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_INVALID, false, 0,REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_DEVANAGARI,true, 0x094Du,REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_BENGALI, true, 0x09CDu,REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_GUJARATI, true, 0x0ACDu,REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_ORIYA, true, 0x0B4Du,REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_TAMIL, true, 0x0BCDu,REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_TELUGU, true, 0x0C4Du,REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY},
+ {HB_SCRIPT_KANNADA, true, 0x0CCDu,REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY},
+ {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST},
};
-
-/*
- * Indic shaper.
- */
-
static const hb_ot_map_feature_t
indic_features[] =
{
@@ -162,15 +223,15 @@ enum {
INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
};
-static void
+static bool
setup_syllables_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
initial_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
final_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
@@ -207,6 +268,7 @@ static void
override_features_indic (hb_ot_shape_planner_t *plan)
{
plan->map.disable_feature (HB_TAG('l','i','g','a'));
+ plan->map.add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
}
@@ -214,7 +276,7 @@ struct indic_shape_plan_t
{
bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
{
- hb_codepoint_t glyph = virama_glyph.get_relaxed ();
+ hb_codepoint_t glyph = virama_glyph;
if (unlikely (glyph == (hb_codepoint_t) -1))
{
if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
@@ -224,7 +286,7 @@ struct indic_shape_plan_t
/* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
* during shape planning... Instead, overwrite it here. */
- virama_glyph.set_relaxed ((int) glyph);
+ virama_glyph = (int) glyph;
}
*pglyph = glyph;
@@ -268,7 +330,7 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
#endif
- indic_plan->virama_glyph.set_relaxed (-1);
+ indic_plan->virama_glyph = -1;
/* Use zero-context would_substitute() matching for new-spec of the main
* Indic scripts, and scripts with one spec only, but not for old-specs.
@@ -351,14 +413,16 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
set_indic_properties (info[i]);
}
-static void
+static bool
setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
find_syllables_indic (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
+ return false;
}
static int
@@ -367,7 +431,7 @@ compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
int a = pa->indic_position();
int b = pb->indic_position();
- return a < b ? -1 : a == b ? 0 : +1;
+ return (int) a - (int) b;
}
@@ -379,9 +443,6 @@ update_consonant_positions_indic (const hb_ot_shape_plan_t *plan,
{
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
- if (indic_plan->config->base_pos != BASE_POS_LAST)
- return;
-
hb_codepoint_t virama;
if (indic_plan->load_virama_glyph (font, &virama))
{
@@ -416,14 +477,12 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
*/
if (buffer->props.script == HB_SCRIPT_KANNADA &&
start + 3 <= end &&
- is_one_of (info[start ], FLAG (OT_Ra)) &&
- is_one_of (info[start+1], FLAG (OT_H)) &&
- is_one_of (info[start+2], FLAG (OT_ZWJ)))
+ is_one_of (info[start ], FLAG (I_Cat(Ra))) &&
+ is_one_of (info[start+1], FLAG (I_Cat(H))) &&
+ 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:
@@ -452,7 +511,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
start + 3 <= end &&
(
(indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) ||
- (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT && info[start + 2].indic_category() == OT_ZWJ)
+ (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT && info[start + 2].indic_category() == I_Cat(ZWJ))
))
{
/* See if it matches the 'rphf' feature. */
@@ -470,7 +529,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
base = start;
has_reph = true;
}
- } else if (indic_plan->config->reph_mode == REPH_MODE_LOG_REPHA && info[start].indic_category() == OT_Repha)
+ } else if (indic_plan->config->reph_mode == REPH_MODE_LOG_REPHA && info[start].indic_category() == I_Cat(Repha))
{
limit += 1;
while (limit < end && is_joiner (info[limit]))
@@ -479,84 +538,51 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
has_reph = true;
}
- switch (indic_plan->config->base_pos)
{
- case BASE_POS_LAST:
- {
- /* -> starting from the end of the syllable, move backwards */
- unsigned int i = end;
- bool seen_below = false;
- do {
- i--;
- /* -> until a consonant is found */
- if (is_consonant (info[i]))
+ /* -> starting from the end of the syllable, move backwards */
+ unsigned int i = end;
+ bool seen_below = false;
+ do {
+ i--;
+ /* -> until a consonant is found */
+ if (is_consonant (info[i]))
+ {
+ /* -> that does not have a below-base or post-base form
+ * (post-base forms have to follow below-base forms), */
+ if (info[i].indic_position() != POS_BELOW_C &&
+ (info[i].indic_position() != POS_POST_C || seen_below))
{
- /* -> that does not have a below-base or post-base form
- * (post-base forms have to follow below-base forms), */
- if (info[i].indic_position() != POS_BELOW_C &&
- (info[i].indic_position() != POS_POST_C || seen_below))
- {
- base = i;
- break;
- }
- if (info[i].indic_position() == POS_BELOW_C)
- seen_below = true;
-
- /* -> or that is not a pre-base-reordering Ra,
- *
- * IMPLEMENTATION NOTES:
- *
- * Our pre-base-reordering Ra's are marked POS_POST_C, so will be skipped
- * by the logic above already.
- */
-
- /* -> or arrive at the first consonant. The consonant stopped at will
- * be the base. */
base = i;
+ break;
}
- else
- {
- /* A ZWJ after a Halant stops the base search, and requests an explicit
- * half form.
- * A ZWJ before a Halant, requests a subjoined form instead, and hence
- * search continues. This is particularly important for Bengali
- * sequence Ra,H,Ya that should form Ya-Phalaa by subjoining Ya. */
- if (start < i &&
- info[i].indic_category() == OT_ZWJ &&
- info[i - 1].indic_category() == OT_H)
- break;
- }
- } while (i > limit);
- }
- break;
+ if (info[i].indic_position() == POS_BELOW_C)
+ seen_below = true;
- case BASE_POS_LAST_SINHALA:
- {
- /* Sinhala base positioning is slightly different from main Indic, in that:
- * 1. Its ZWJ behavior is different,
- * 2. We don't need to look into the font for consonant positions.
- */
-
- if (!has_reph)
- base = limit;
-
- /* Find the last base consonant that is not blocked by ZWJ. If there is
- * a ZWJ right before a base consonant, that would request a subjoined form. */
- for (unsigned int i = limit; i < end; i++)
- if (is_consonant (info[i]))
- {
- if (limit < i && info[i - 1].indic_category() == OT_ZWJ)
- break;
- else
- base = i;
- }
+ /* -> or that is not a pre-base-reordering Ra,
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * Our pre-base-reordering Ra's are marked POS_POST_C, so will be skipped
+ * by the logic above already.
+ */
- /* Mark all subsequent consonants as below. */
- for (unsigned int i = base + 1; i < end; i++)
- if (is_consonant (info[i]))
- info[i].indic_position() = POS_BELOW_C;
- }
- break;
+ /* -> or arrive at the first consonant. The consonant stopped at will
+ * be the base. */
+ base = i;
+ }
+ else
+ {
+ /* A ZWJ after a Halant stops the base search, and requests an explicit
+ * half form.
+ * A ZWJ before a Halant, requests a subjoined form instead, and hence
+ * search continues. This is particularly important for Bengali
+ * sequence Ra,H,Ya that should form Ya-Phalaa by subjoining Ya. */
+ if (start < i &&
+ info[i].indic_category() == I_Cat(ZWJ) &&
+ info[i - 1].indic_category() == I_Cat(H))
+ break;
+ }
+ } while (i > limit);
}
/* -> If the syllable starts with Ra + Halant (in a script that has Reph)
@@ -611,18 +637,6 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
if (base < end)
info[base].indic_position() = POS_BASE_C;
- /* Mark final consonants. A final consonant is one appearing after a matra.
- * Happens in Sinhala. */
- for (unsigned int i = base + 1; i < end; i++)
- if (info[i].indic_category() == OT_M) {
- for (unsigned int j = i + 1; j < end; j++)
- if (is_consonant (info[j])) {
- info[j].indic_position() = POS_FINAL_C;
- break;
- }
- break;
- }
-
/* Handle beginning Ra */
if (has_reph)
info[start].indic_position() = POS_RA_TO_BECOME_REPH;
@@ -659,14 +673,14 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
{
bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA;
for (unsigned int i = base + 1; i < end; i++)
- if (info[i].indic_category() == OT_H)
+ if (info[i].indic_category() == I_Cat(H))
{
unsigned int j;
for (j = end - 1; j > i; j--)
if (is_consonant (info[j]) ||
- (disallow_double_halants && info[j].indic_category() == OT_H))
+ (disallow_double_halants && info[j].indic_category() == I_Cat(H)))
break;
- if (info[j].indic_category() != OT_H && j > i) {
+ if (info[j].indic_category() != I_Cat(H) && j > i) {
/* Move Halant to after last consonant. */
hb_glyph_info_t t = info[i];
memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0]));
@@ -681,20 +695,16 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
indic_position_t last_pos = POS_START;
for (unsigned int i = start; i < end; i++)
{
- if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_H))))
+ if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (I_Cat(N)) | FLAG (I_Cat(RS)) | FLAG (I_Cat(CM)) | FLAG (I_Cat(H)))))
{
info[i].indic_position() = last_pos;
- if (unlikely (info[i].indic_category() == OT_H &&
+ if (unlikely (info[i].indic_category() == I_Cat(H) &&
info[i].indic_position() == POS_PRE_M))
{
/*
* Uniscribe doesn't move the Halant with Left Matra.
- * TEST: U+092B,U+093F,U+094DE
- * We follow. This is important for the Sinhala
- * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
- * where U+0DD9 is a left matra and U+0DCA is the virama.
- * We don't want to move the virama with the left matra.
- * TEST: U+0D9A,U+0DDA
+ * TEST: U+092B,U+093F,U+094D
+ * We follow.
*/
for (unsigned int j = i; j > start; j--)
if (info[j - 1].indic_position() != POS_PRE_M) {
@@ -703,6 +713,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
}
}
} else if (info[i].indic_position() != POS_SMVD) {
+ if (info[i].indic_category() == I_Cat(MPst) &&
+ i > start && info[i - 1].indic_category() == I_Cat(SM))
+ info[i - 1].indic_position() = info[i].indic_position();
last_pos = (indic_position_t) info[i].indic_position();
}
}
@@ -718,7 +731,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
if (info[j].indic_position() < POS_SMVD)
info[j].indic_position() = info[i].indic_position();
last = i;
- } else if (info[i].indic_category() == OT_M)
+ } else if (FLAG_UNSAFE (info[i].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
last = i;
}
@@ -731,14 +744,40 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
/* Sit tight, rock 'n roll! */
hb_stable_sort (info + start, end - start, compare_indic_order);
- /* Find base again */
+
+ /* Find base again; also flip left-matra sequence. */
+ unsigned first_left_matra = end;
+ unsigned last_left_matra = end;
base = end;
for (unsigned int i = start; i < end; i++)
+ {
if (info[i].indic_position() == POS_BASE_C)
{
base = i;
break;
}
+ else if (info[i].indic_position() == POS_PRE_M)
+ {
+ if (first_left_matra == end)
+ first_left_matra = i;
+ last_left_matra = i;
+ }
+ }
+ /* https://github.com/harfbuzz/harfbuzz/issues/3863 */
+ if (first_left_matra < last_left_matra)
+ {
+ /* No need to merge clusters, handled later. */
+ buffer->reverse_range (first_left_matra, last_left_matra + 1);
+ /* Reverse back nuktas, etc. */
+ unsigned i = first_left_matra;
+ for (unsigned j = i; j <= last_left_matra; j++)
+ if (FLAG_UNSAFE (info[j].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
+ {
+ buffer->reverse_range (i, j + 1);
+ i = j + 1;
+ }
+ }
+
/* Things are out-of-control for post base positions, they may shuffle
* around like crazy. In old-spec mode, we move halants around, so in
* that case merge all clusters after base. Otherwise, check the sort
@@ -849,10 +888,10 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* Test case: U+0924,U+094D,U+0930,U+094d,U+200D,U+0915
*/
for (unsigned int i = start; i + 1 < base; i++)
- if (info[i ].indic_category() == OT_Ra &&
- info[i+1].indic_category() == OT_H &&
+ if (info[i ].indic_category() == I_Cat(Ra) &&
+ info[i+1].indic_category() == I_Cat(H) &&
(i + 2 == base ||
- info[i+2].indic_category() != OT_ZWJ))
+ info[i+2].indic_category() != I_Cat(ZWJ)))
{
info[i ].mask |= indic_plan->mask_array[INDIC_BLWF];
info[i+1].mask |= indic_plan->mask_array[INDIC_BLWF];
@@ -879,7 +918,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
/* Apply ZWJ/ZWNJ effects */
for (unsigned int i = start + 1; i < end; i++)
if (is_joiner (info[i])) {
- bool non_joiner = info[i].indic_category() == OT_ZWNJ;
+ bool non_joiner = info[i].indic_category() == I_Cat(ZWNJ);
unsigned int j = i;
do {
@@ -912,7 +951,7 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
/* For dotted-circle, this is what Uniscribe does:
* If dotted-circle is the last glyph, it just does nothing.
* Ie. It doesn't form Reph. */
- if (buffer->info[end - 1].indic_category() == OT_DOTTEDCIRCLE)
+ if (buffer->info[end - 1].indic_category() == I_Cat(DOTTEDCIRCLE))
return;
}
@@ -944,25 +983,29 @@ initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
}
}
-static void
+static bool
initial_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
+ bool ret = false;
if (!buffer->message (font, "start reordering indic initial"))
- return;
+ return ret;
update_consonant_positions_indic (plan, font, buffer);
- hb_syllabic_insert_dotted_circles (font, buffer,
- indic_broken_cluster,
- OT_DOTTEDCIRCLE,
- OT_Repha,
- POS_END);
+ if (hb_syllabic_insert_dotted_circles (font, buffer,
+ indic_broken_cluster,
+ I_Cat(DOTTEDCIRCLE),
+ I_Cat(Repha),
+ POS_END))
+ ret = true;
foreach_syllable (buffer, start, end)
initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
(void) buffer->message (font, "end reordering indic initial");
+
+ return ret;
}
static void
@@ -978,10 +1021,10 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
* and possibly multiple substitutions happened prior to this
* phase, and that might have messed up our properties. Recover
* from a particular case of that where we're fairly sure that a
- * class of OT_H is desired but has been lost. */
+ * class of I_Cat(H) is desired but has been lost. */
/* We don't call load_virama_glyph(), since we know it's already
* loaded. */
- hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed ();
+ hb_codepoint_t virama_glyph = indic_plan->virama_glyph;
if (virama_glyph)
{
for (unsigned int i = start; i < end; i++)
@@ -990,7 +1033,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
_hb_glyph_info_multiplied (&info[i]))
{
/* This will make sure that this glyph passes is_halant() test. */
- info[i].indic_category() = OT_H;
+ info[i].indic_category() = I_Cat(H);
_hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
}
}
@@ -1056,11 +1099,11 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
break;
}
if (base == end && start < base &&
- is_one_of (info[base - 1], FLAG (OT_ZWJ)))
+ is_one_of (info[base - 1], FLAG (I_Cat(ZWJ))))
base--;
if (base < end)
while (start < base &&
- is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_H))))
+ is_one_of (info[base], (FLAG (I_Cat(N)) | FLAG (I_Cat(H)))))
base--;
@@ -1105,7 +1148,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
{
search:
while (new_pos > start &&
- !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H)))))
+ !(is_one_of (info[new_pos], (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)) | FLAG (I_Cat(H))))))
new_pos--;
/* If we found no Halant we are done.
@@ -1122,7 +1165,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
if (new_pos + 1 < end)
{
/* -> If ZWJ follows this halant, matra is NOT repositioned after this halant. */
- if (info[new_pos + 1].indic_category() == OT_ZWJ)
+ if (info[new_pos + 1].indic_category() == I_Cat(ZWJ))
{
/* Keep searching. */
if (new_pos > start)
@@ -1195,7 +1238,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
*/
if (start + 1 < end &&
info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
- ((info[start].indic_category() == OT_Repha) ^
+ ((info[start].indic_category() == I_Cat(Repha)) ^
_hb_glyph_info_ligated_and_didnt_multiply (&info[start])))
{
unsigned int new_reph_pos;
@@ -1305,7 +1348,8 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
unlikely (is_halant (info[new_reph_pos])))
{
for (unsigned int i = base + 1; i < new_reph_pos; i++)
- if (info[i].indic_category() == OT_M) {
+ if (FLAG_UNSAFE (info[i].indic_category()) & (FLAG (I_Cat(M)) | FLAG (I_Cat(MPst))))
+ {
/* Ok, got it. */
new_reph_pos--;
}
@@ -1365,7 +1409,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
{
while (new_pos > start &&
- !(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_H))))
+ !(is_one_of (info[new_pos - 1], FLAG (I_Cat(M)) | FLAG (I_Cat(MPst)) | FLAG (I_Cat(H)))))
new_pos--;
}
@@ -1414,11 +1458,10 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
switch ((hb_tag_t) plan->props.script)
{
case HB_SCRIPT_TAMIL:
- case HB_SCRIPT_SINHALA:
break;
default:
- /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
+ /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil.
* This means, half forms are submerged into the main consonant's cluster.
* This is unnecessary, and makes cursor positioning harder, but that's what
* Uniscribe does. */
@@ -1429,13 +1472,13 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
}
-static void
+static bool
final_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
- if (unlikely (!count)) return;
+ if (unlikely (!count)) return false;
if (buffer->message (font, "start reordering indic final")) {
foreach_syllable (buffer, start, end)
@@ -1445,6 +1488,8 @@ final_reordering_indic (const hb_ot_shape_plan_t *plan,
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
+
+ return false;
}
@@ -1453,7 +1498,9 @@ preprocess_text_indic (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
hb_font_t *font)
{
- _hb_preprocess_text_vowel_constraints (plan, buffer, font);
+ const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+ if (!indic_plan->uniscribe_bug_compatible)
+ _hb_preprocess_text_vowel_constraints (plan, buffer, font);
}
static bool
@@ -1486,48 +1533,6 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
#endif
}
- if ((ab == 0x0DDAu || hb_in_range<hb_codepoint_t> (ab, 0x0DDCu, 0x0DDEu)))
- {
- /*
- * Sinhala split matras... Let the fun begin.
- *
- * These four characters have Unicode decompositions. However, Uniscribe
- * decomposes them "Khmer-style", that is, it uses the character itself to
- * get the second half. The first half of all four decompositions is always
- * U+0DD9.
- *
- * Now, there are buggy fonts, namely, the widely used lklug.ttf, that are
- * broken with Uniscribe. But we need to support them. As such, we only
- * do the Uniscribe-style decomposition if the character is transformed into
- * its "sec.half" form by the 'pstf' feature. Otherwise, we fall back to
- * Unicode decomposition.
- *
- * Note that we can't unconditionally use Unicode decomposition. That would
- * break some other fonts, that are designed to work with Uniscribe, and
- * don't have positioning features for the Unicode-style decomposition.
- *
- * Argh...
- *
- * The Uniscribe behavior is now documented in the newly published Sinhala
- * spec in 2012:
- *
- * https://docs.microsoft.com/en-us/typography/script-development/sinhala#shaping
- */
-
-
- const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data;
- hb_codepoint_t glyph;
- if (indic_plan->uniscribe_bug_compatible ||
- (c->font->get_nominal_glyph (ab, &glyph) &&
- indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
- {
- /* Ok, safe to use Uniscribe-style decomposition. */
- *a = 0x0DD9u;
- *b = ab;
- return true;
- }
- }
-
return (bool) c->unicode->decompose (ab, a, b);
}
@@ -1548,7 +1553,7 @@ compose_indic (const hb_ot_shape_normalize_context_t *c,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
+const hb_ot_shaper_t _hb_ot_shaper_indic =
{
collect_features_indic,
override_features_indic,
@@ -1556,12 +1561,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
data_destroy_indic,
preprocess_text_indic,
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
decompose_indic,
compose_indic,
setup_masks_indic,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
diff --git a/src/3rdparty/harfbuzz-ng/src/test-serialize.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.hh
index 44a2e0fe1d..4f822c26e9 100644
--- a/src/3rdparty/harfbuzz-ng/src/test-serialize.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2022 Behdad Esfahbod
+ * Copyright © 2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -21,31 +21,46 @@
* 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_OT_SHAPER_INDIC_HH
+#define HB_OT_SHAPER_INDIC_HH
+
#include "hb.hh"
-#include "hb-serialize.hh"
-#include "hb-ot-layout-common.hh"
+#include "hb-ot-shaper-syllabic.hh"
+
+
+/* Visual positions in a syllable from left to right. */
+enum ot_position_t {
+ POS_START = 0,
+
+ POS_RA_TO_BECOME_REPH = 1,
+ POS_PRE_M = 2,
+ POS_PRE_C = 3,
+
+ POS_BASE_C = 4,
+ POS_AFTER_MAIN = 5,
+
+ POS_ABOVE_C = 6,
-int
-main (int argc, char **argv)
-{
- char buf[16384];
+ POS_BEFORE_SUB = 7,
+ POS_BELOW_C = 8,
+ POS_AFTER_SUB = 9,
- hb_serialize_context_t s (buf, sizeof (buf));
+ POS_BEFORE_POST = 10,
+ POS_POST_C = 11,
+ POS_AFTER_POST = 12,
- hb_sorted_vector_t<hb_codepoint_t> v{1, 2, 5};
+ POS_SMVD = 13,
- auto c = s.start_serialize<OT::Coverage> ();
+ POS_END = 14
+};
- c->serialize (&s, hb_iter (v));
- s.end_serialize ();
+HB_INTERNAL uint16_t
+hb_indic_get_categories (hb_codepoint_t u);
- hb_bytes_t bytes = s.copy_bytes ();
- assert (bytes.length == 10);
- bytes.fini ();
- return 0;
-}
+#endif /* HB_OT_SHAPER_INDIC_HH */
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
new file mode 100644
index 0000000000..848ed231f7
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh
@@ -0,0 +1,428 @@
+
+#line 1 "hb-ot-shaper-khmer-machine.rl"
+/*
+ * 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 HB_OT_SHAPER_KHMER_MACHINE_HH
+#define HB_OT_SHAPER_KHMER_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shaper-indic.hh"
+
+/* buffer var allocations */
+#define khmer_category() ot_shaper_var_u8_category() /* khmer_category_t */
+
+using khmer_category_t = unsigned;
+
+#define K_Cat(Cat) khmer_syllable_machine_ex_##Cat
+
+enum khmer_syllable_type_t {
+ khmer_consonant_syllable,
+ khmer_broken_cluster,
+ khmer_non_khmer_cluster,
+};
+
+
+#line 49 "hb-ot-shaper-khmer-machine.hh"
+#define khmer_syllable_machine_ex_C 1u
+#define khmer_syllable_machine_ex_DOTTEDCIRCLE 11u
+#define khmer_syllable_machine_ex_H 4u
+#define khmer_syllable_machine_ex_PLACEHOLDER 10u
+#define khmer_syllable_machine_ex_Ra 15u
+#define khmer_syllable_machine_ex_Robatic 25u
+#define khmer_syllable_machine_ex_V 2u
+#define khmer_syllable_machine_ex_VAbv 20u
+#define khmer_syllable_machine_ex_VBlw 21u
+#define khmer_syllable_machine_ex_VPre 22u
+#define khmer_syllable_machine_ex_VPst 23u
+#define khmer_syllable_machine_ex_Xgroup 26u
+#define khmer_syllable_machine_ex_Ygroup 27u
+#define khmer_syllable_machine_ex_ZWJ 6u
+#define khmer_syllable_machine_ex_ZWNJ 5u
+
+
+#line 65 "hb-ot-shaper-khmer-machine.hh"
+static const unsigned char _khmer_syllable_machine_trans_keys[] = {
+ 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u,
+ 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u,
+ 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 27u, 4u, 27u, 1u, 15u,
+ 4u, 27u, 4u, 27u, 27u, 27u, 4u, 27u, 4u, 27u, 4u, 27u, 4u, 27u, 4u, 27u,
+ 4u, 27u, 1u, 15u, 4u, 27u, 4u, 27u, 27u, 27u, 4u, 27u, 4u, 27u, 4u, 27u,
+ 4u, 27u, 4u, 27u, 5u, 26u, 0
+};
+
+static const char _khmer_syllable_machine_key_spans[] = {
+ 22, 22, 15, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 15, 22, 22,
+ 22, 22, 22, 22, 22, 27, 24, 15,
+ 24, 24, 1, 24, 24, 24, 24, 24,
+ 24, 15, 24, 24, 1, 24, 24, 24,
+ 24, 24, 22
+};
+
+static const short _khmer_syllable_machine_index_offsets[] = {
+ 0, 23, 46, 62, 85, 108, 131, 154,
+ 177, 200, 223, 246, 269, 292, 308, 331,
+ 354, 377, 400, 423, 446, 469, 497, 522,
+ 538, 563, 588, 590, 615, 640, 665, 690,
+ 715, 740, 756, 781, 806, 808, 833, 858,
+ 883, 908, 933
+};
+
+static const char _khmer_syllable_machine_indicies[] = {
+ 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 3, 4, 0, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 5, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 4, 0, 6, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 7, 7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 0, 9, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0,
+ 10, 0, 9, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10,
+ 0, 11, 11, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 12, 0,
+ 11, 11, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 12, 0, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 13, 4, 0, 15, 15,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 16, 14, 14,
+ 14, 14, 17, 18, 14, 15, 15, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 18, 19, 20, 20, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 20, 14, 15, 15, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 16, 14, 14, 14, 14,
+ 14, 18, 14, 21, 21, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 16, 14, 22, 22, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 23,
+ 14, 24, 24, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 16, 14, 14, 14, 14, 14, 25, 14,
+ 24, 24, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 25, 14, 26,
+ 26, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 16, 14,
+ 14, 14, 14, 14, 27, 14, 26, 26,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 27, 14, 29, 29, 28,
+ 30, 31, 31, 28, 28, 28, 13, 13,
+ 28, 28, 28, 29, 28, 28, 28, 28,
+ 16, 25, 27, 23, 28, 17, 18, 20,
+ 28, 33, 34, 34, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 2, 10, 12, 8, 32, 13, 4,
+ 5, 32, 35, 35, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 35, 32, 33, 36, 36, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 2, 10, 12, 8, 32, 3,
+ 4, 5, 32, 37, 38, 38, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 2, 10, 12, 8, 32,
+ 32, 4, 5, 32, 5, 32, 37, 6,
+ 6, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 8, 32, 32, 2, 5, 32, 37,
+ 7, 7, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 8, 5, 32,
+ 37, 39, 39, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 2, 32, 32, 8, 32, 32, 10, 5,
+ 32, 37, 40, 40, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 2, 10, 32, 8, 32, 32, 12,
+ 5, 32, 33, 38, 38, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 2, 10, 12, 8, 32, 32,
+ 4, 5, 32, 33, 38, 38, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 2, 10, 12, 8, 32,
+ 3, 4, 5, 32, 42, 42, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 42, 41, 30, 43, 43, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 16, 25, 27, 23,
+ 41, 17, 18, 20, 41, 44, 45, 45,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 16, 25, 27,
+ 23, 41, 41, 18, 20, 41, 20, 41,
+ 44, 21, 21, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 23, 41, 41, 16, 20,
+ 41, 44, 22, 22, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 23,
+ 20, 41, 44, 46, 46, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 16, 41, 41, 23, 41, 41,
+ 25, 20, 41, 44, 47, 47, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 16, 25, 41, 23, 41,
+ 41, 27, 20, 41, 30, 45, 45, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 16, 25, 27, 23,
+ 41, 41, 18, 20, 41, 15, 15, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 16, 48, 48, 48,
+ 48, 48, 18, 48, 0
+};
+
+static const char _khmer_syllable_machine_trans_targs[] = {
+ 21, 1, 27, 31, 25, 26, 4, 5,
+ 28, 7, 29, 9, 30, 32, 21, 12,
+ 37, 41, 35, 21, 36, 15, 16, 38,
+ 18, 39, 20, 40, 21, 22, 33, 42,
+ 21, 23, 10, 24, 0, 2, 3, 6,
+ 8, 21, 34, 11, 13, 14, 17, 19,
+ 21
+};
+
+static const char _khmer_syllable_machine_trans_actions[] = {
+ 1, 0, 2, 2, 2, 0, 0, 0,
+ 2, 0, 2, 0, 2, 2, 3, 0,
+ 2, 4, 4, 5, 0, 0, 0, 2,
+ 0, 2, 0, 2, 8, 2, 0, 9,
+ 10, 0, 0, 2, 0, 0, 0, 0,
+ 0, 11, 4, 0, 0, 0, 0, 0,
+ 12
+};
+
+static const char _khmer_syllable_machine_to_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
+};
+
+static const char _khmer_syllable_machine_from_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
+};
+
+static const short _khmer_syllable_machine_eof_trans[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 15, 20, 15, 15, 15,
+ 15, 15, 15, 15, 15, 0, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 49
+};
+
+static const int khmer_syllable_machine_start = 21;
+static const int khmer_syllable_machine_first_final = 21;
+static const int khmer_syllable_machine_error = -1;
+
+static const int khmer_syllable_machine_en_main = 21;
+
+
+#line 53 "hb-ot-shaper-khmer-machine.rl"
+
+
+
+#line 102 "hb-ot-shaper-khmer-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ 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++; \
+ if (syllable_serial == 16) syllable_serial = 1; \
+ } HB_STMT_END
+
+inline void
+find_syllables_khmer (hb_buffer_t *buffer)
+{
+ unsigned int p, pe, eof, ts, te, act HB_UNUSED;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 287 "hb-ot-shaper-khmer-machine.hh"
+ {
+ cs = khmer_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 122 "hb-ot-shaper-khmer-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 299 "hb-ot-shaper-khmer-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
+ case 7:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 311 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+ _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
+ _inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
+
+ _slen = _khmer_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
+ ( info[p].khmer_category()) <= _keys[1] ?
+ ( info[p].khmer_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _khmer_syllable_machine_trans_targs[_trans];
+
+ if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
+ case 2:
+#line 1 "NONE"
+ {te = p+1;}
+ break;
+ case 8:
+#line 98 "hb-ot-shaper-khmer-machine.rl"
+ {te = p+1;{ found_syllable (khmer_non_khmer_cluster); }}
+ break;
+ case 10:
+#line 96 "hb-ot-shaper-khmer-machine.rl"
+ {te = p;p--;{ found_syllable (khmer_consonant_syllable); }}
+ break;
+ case 11:
+#line 97 "hb-ot-shaper-khmer-machine.rl"
+ {te = p;p--;{ found_syllable (khmer_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 12:
+#line 98 "hb-ot-shaper-khmer-machine.rl"
+ {te = p;p--;{ found_syllable (khmer_non_khmer_cluster); }}
+ break;
+ case 1:
+#line 96 "hb-ot-shaper-khmer-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (khmer_consonant_syllable); }}
+ break;
+ case 3:
+#line 97 "hb-ot-shaper-khmer-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (khmer_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 5:
+#line 1 "NONE"
+ { switch( act ) {
+ case 2:
+ {{p = ((te))-1;} found_syllable (khmer_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+ break;
+ case 3:
+ {{p = ((te))-1;} found_syllable (khmer_non_khmer_cluster); }
+ break;
+ }
+ }
+ break;
+ case 4:
+#line 1 "NONE"
+ {te = p+1;}
+#line 97 "hb-ot-shaper-khmer-machine.rl"
+ {act = 2;}
+ break;
+ case 9:
+#line 1 "NONE"
+ {te = p+1;}
+#line 98 "hb-ot-shaper-khmer-machine.rl"
+ {act = 3;}
+ break;
+#line 368 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+_again:
+ switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
+ case 6:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 375 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _khmer_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 130 "hb-ot-shaper-khmer-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_KHMER_MACHINE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer.cc
index a7d5bf574b..019a285102 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-khmer.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer.cc
@@ -28,8 +28,8 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-khmer.hh"
-#include "hb-ot-shape-complex-khmer-machine.hh"
+#include "hb-ot-shaper-khmer-machine.hh"
+#include "hb-ot-shaper-indic.hh"
#include "hb-ot-layout.hh"
@@ -37,6 +37,7 @@
* Khmer shaper.
*/
+
static const hb_ot_map_feature_t
khmer_features[] =
{
@@ -79,11 +80,20 @@ enum {
KHMER_BASIC_FEATURES = _KHMER_PRES, /* Don't forget to update this! */
};
-static void
+static inline void
+set_khmer_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+
+ info.khmer_category() = (khmer_category_t) (type & 0xFFu);
+}
+
+static bool
setup_syllables_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
reorder_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
@@ -115,7 +125,7 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
map->add_feature (khmer_features[i]);
/* https://github.com/harfbuzz/harfbuzz/issues/3531 */
- map->add_gsub_pause (nullptr);
+ map->add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
for (; i < KHMER_NUM_FEATURES; i++)
map->add_feature (khmer_features[i]);
@@ -182,14 +192,16 @@ setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
set_khmer_properties (info[i]);
}
-static void
+static bool
setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
find_syllables_khmer (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
+ return false;
}
@@ -230,11 +242,11 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
* the 'pref' OpenType feature applied to them.
* """
*/
- if (info[i].khmer_category() == OT_Coeng && num_coengs <= 2 && i + 1 < end)
+ if (info[i].khmer_category() == K_Cat(H) && num_coengs <= 2 && i + 1 < end)
{
num_coengs++;
- if (info[i + 1].khmer_category() == OT_Ra)
+ if (info[i + 1].khmer_category() == K_Cat(Ra))
{
for (unsigned int j = 0; j < 2; j++)
info[i + j].mask |= khmer_plan->mask_array[KHMER_PREF];
@@ -262,7 +274,7 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
}
/* Reorder left matra piece. */
- else if (info[i].khmer_category() == OT_VPre)
+ else if (info[i].khmer_category() == K_Cat(VPre))
{
/* Move to the start. */
buffer->merge_clusters (start, i + 1);
@@ -292,23 +304,27 @@ reorder_syllable_khmer (const hb_ot_shape_plan_t *plan,
}
}
-static void
+static bool
reorder_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
+ bool ret = false;
if (buffer->message (font, "start reordering khmer"))
{
- hb_syllabic_insert_dotted_circles (font, buffer,
- khmer_broken_cluster,
- OT_DOTTEDCIRCLE,
- OT_Repha);
+ if (hb_syllabic_insert_dotted_circles (font, buffer,
+ khmer_broken_cluster,
+ K_Cat(DOTTEDCIRCLE),
+ (unsigned) -1))
+ ret = true;
foreach_syllable (buffer, start, end)
reorder_syllable_khmer (plan, font->face, buffer, start, end);
(void) buffer->message (font, "end reordering khmer");
}
HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
+
+ return ret;
}
@@ -349,7 +365,7 @@ compose_khmer (const hb_ot_shape_normalize_context_t *c,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_khmer =
+const hb_ot_shaper_t _hb_ot_shaper_khmer =
{
collect_features_khmer,
override_features_khmer,
@@ -357,12 +373,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_khmer =
data_destroy_khmer,
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
decompose_khmer,
compose_khmer,
setup_masks_khmer,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
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
new file mode 100644
index 0000000000..f7b456b11f
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh
@@ -0,0 +1,553 @@
+
+#line 1 "hb-ot-shaper-myanmar-machine.rl"
+/*
+ * 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 HB_OT_SHAPER_MYANMAR_MACHINE_HH
+#define HB_OT_SHAPER_MYANMAR_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shaper-indic.hh"
+
+/* buffer var allocations */
+#define myanmar_category() ot_shaper_var_u8_category() /* myanmar_category_t */
+#define myanmar_position() ot_shaper_var_u8_auxiliary() /* myanmar_position_t */
+
+using myanmar_category_t = unsigned;
+using myanmar_position_t = ot_position_t;
+
+#define M_Cat(Cat) myanmar_syllable_machine_ex_##Cat
+
+enum myanmar_syllable_type_t {
+ myanmar_consonant_syllable,
+ myanmar_broken_cluster,
+ myanmar_non_myanmar_cluster,
+};
+
+
+#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
+#define myanmar_syllable_machine_ex_CS 18u
+#define myanmar_syllable_machine_ex_DB 3u
+#define myanmar_syllable_machine_ex_DOTTEDCIRCLE 11u
+#define myanmar_syllable_machine_ex_GB 10u
+#define myanmar_syllable_machine_ex_H 4u
+#define myanmar_syllable_machine_ex_IV 2u
+#define myanmar_syllable_machine_ex_MH 35u
+#define myanmar_syllable_machine_ex_ML 41u
+#define myanmar_syllable_machine_ex_MR 36u
+#define myanmar_syllable_machine_ex_MW 37u
+#define myanmar_syllable_machine_ex_MY 38u
+#define myanmar_syllable_machine_ex_PT 39u
+#define myanmar_syllable_machine_ex_Ra 15u
+#define myanmar_syllable_machine_ex_SM 8u
+#define myanmar_syllable_machine_ex_VAbv 20u
+#define myanmar_syllable_machine_ex_VBlw 21u
+#define myanmar_syllable_machine_ex_VPre 22u
+#define myanmar_syllable_machine_ex_VPst 23u
+#define myanmar_syllable_machine_ex_VS 40u
+#define myanmar_syllable_machine_ex_ZWJ 6u
+#define myanmar_syllable_machine_ex_ZWNJ 5u
+
+
+#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,
+ 3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 41u,
+ 3u, 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, 41u, 3u, 39u,
+ 3u, 39u, 3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u,
+ 3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 1u, 41u, 1u, 15u, 0
+};
+
+static const char _myanmar_syllable_machine_key_spans[] = {
+ 41, 39, 35, 4, 39, 37, 37, 35,
+ 35, 37, 37, 39, 35, 15, 37, 37,
+ 38, 37, 39, 39, 37, 39, 39, 39,
+ 39, 39, 35, 4, 39, 37, 37, 35,
+ 35, 37, 37, 39, 35, 15, 39, 37,
+ 37, 38, 37, 39, 39, 37, 39, 39,
+ 39, 39, 39, 39, 39, 41, 15
+};
+
+static const short _myanmar_syllable_machine_index_offsets[] = {
+ 0, 42, 82, 118, 123, 163, 201, 239,
+ 275, 311, 349, 387, 427, 463, 479, 517,
+ 555, 594, 632, 672, 712, 750, 790, 830,
+ 870, 910, 950, 986, 991, 1031, 1069, 1107,
+ 1143, 1179, 1217, 1255, 1295, 1331, 1347, 1387,
+ 1425, 1463, 1502, 1540, 1580, 1620, 1658, 1698,
+ 1738, 1778, 1818, 1858, 1898, 1938, 1980
+};
+
+static const char _myanmar_syllable_machine_indicies[] = {
+ 1, 1, 2, 3, 4, 4, 0, 5,
+ 6, 1, 1, 0, 0, 0, 7, 0,
+ 0, 8, 0, 9, 10, 11, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 0, 14, 15, 16, 17, 18, 19,
+ 20, 0, 22, 23, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 31,
+ 21, 21, 32, 33, 34, 35, 36, 37,
+ 38, 21, 24, 24, 21, 25, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 39, 21, 21,
+ 21, 21, 21, 21, 36, 21, 24, 24,
+ 21, 25, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 40, 21, 21, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 41, 21, 21, 42, 21, 21, 21, 36,
+ 21, 41, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 36,
+ 21, 43, 21, 24, 24, 21, 25, 36,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 44, 21,
+ 21, 21, 21, 21, 21, 36, 21, 24,
+ 24, 21, 25, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 44, 21, 21, 21, 21, 21,
+ 21, 36, 21, 24, 24, 21, 25, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 36, 21, 22,
+ 21, 24, 24, 21, 25, 26, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 40, 21, 21, 30, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 36, 21, 22, 21, 24,
+ 24, 21, 25, 26, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 40, 21,
+ 21, 30, 21, 21, 21, 21, 21, 21,
+ 21, 21, 41, 21, 21, 21, 21, 21,
+ 21, 36, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 40, 21, 21, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 41, 21, 21, 21, 21, 21, 21, 36,
+ 21, 41, 21, 24, 24, 21, 25, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 30, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 36, 21, 1,
+ 1, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 1, 21, 22,
+ 21, 24, 24, 21, 25, 26, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 27, 28, 21, 30, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 36, 21, 22, 21, 24,
+ 24, 21, 25, 26, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 28,
+ 21, 30, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 36, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 27, 28, 29, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 36,
+ 45, 21, 22, 21, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 36, 21,
+ 22, 21, 24, 24, 21, 25, 26, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 27, 28, 29, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 31, 21, 21,
+ 32, 33, 34, 35, 36, 21, 38, 21,
+ 22, 21, 24, 24, 21, 25, 26, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 27, 28, 29, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 45, 21, 21,
+ 21, 21, 21, 21, 36, 21, 38, 21,
+ 22, 21, 24, 24, 21, 25, 26, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 27, 28, 29, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 45, 21, 21,
+ 21, 21, 21, 21, 36, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 32, 21,
+ 34, 21, 36, 21, 38, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 45, 21, 21, 32, 21,
+ 21, 21, 36, 21, 38, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 46, 21, 21, 32, 33,
+ 34, 21, 36, 21, 38, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 32, 33,
+ 34, 21, 36, 21, 38, 21, 22, 23,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 31, 21, 21, 32, 33,
+ 34, 35, 36, 21, 38, 21, 48, 48,
+ 47, 5, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 49, 47, 47, 47, 47, 47, 47,
+ 18, 47, 48, 48, 47, 5, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 50, 47, 47, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 51, 47, 47, 52,
+ 47, 47, 47, 18, 47, 51, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 18, 47, 53, 47, 48,
+ 48, 47, 5, 18, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 54, 47, 47, 47, 47, 47,
+ 47, 18, 47, 48, 48, 47, 5, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 54, 47,
+ 47, 47, 47, 47, 47, 18, 47, 48,
+ 48, 47, 5, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 18, 47, 2, 47, 48, 48, 47,
+ 5, 6, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 50, 47, 47, 12,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 18,
+ 47, 2, 47, 48, 48, 47, 5, 6,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 50, 47, 47, 12, 47, 47,
+ 47, 47, 47, 47, 47, 47, 51, 47,
+ 47, 47, 47, 47, 47, 18, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 50, 47, 47, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 51, 47, 47, 47,
+ 47, 47, 47, 18, 47, 51, 47, 48,
+ 48, 47, 5, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 12, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 18, 47, 55, 55, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 55, 47, 2, 3, 48, 48, 47,
+ 5, 6, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 9, 10, 11, 12,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 13, 47, 47, 14, 15, 16, 17, 18,
+ 19, 20, 47, 2, 47, 48, 48, 47,
+ 5, 6, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 9, 10, 47, 12,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 18,
+ 47, 2, 47, 48, 48, 47, 5, 6,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 10, 47, 12, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 18, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 9, 10, 11, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 18, 56, 47, 2, 47,
+ 48, 48, 47, 5, 6, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 9,
+ 10, 11, 12, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 18, 47, 2, 47, 48, 48,
+ 47, 5, 6, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 13, 47, 47, 14, 15, 16, 17,
+ 18, 47, 20, 47, 2, 47, 48, 48,
+ 47, 5, 6, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 56, 47, 47, 47, 47, 47, 47,
+ 18, 47, 20, 47, 2, 47, 48, 48,
+ 47, 5, 6, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 56, 47, 47, 47, 47, 47, 47,
+ 18, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 14, 47, 16, 47, 18, 47,
+ 20, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 56,
+ 47, 47, 14, 47, 47, 47, 18, 47,
+ 20, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 57,
+ 47, 47, 14, 15, 16, 47, 18, 47,
+ 20, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 14, 15, 16, 47, 18, 47,
+ 20, 47, 2, 3, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 13,
+ 47, 47, 14, 15, 16, 17, 18, 47,
+ 20, 47, 22, 23, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 58,
+ 21, 21, 32, 33, 34, 35, 36, 37,
+ 38, 21, 22, 59, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 31,
+ 21, 21, 32, 33, 34, 35, 36, 21,
+ 38, 21, 1, 1, 2, 3, 48, 48,
+ 47, 5, 6, 1, 1, 47, 47, 47,
+ 1, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 13, 47, 47, 14, 15, 16, 17,
+ 18, 19, 20, 47, 1, 1, 60, 60,
+ 60, 60, 60, 60, 60, 1, 1, 60,
+ 60, 60, 1, 60, 0
+};
+
+static const char _myanmar_syllable_machine_trans_targs[] = {
+ 0, 1, 26, 37, 0, 27, 29, 51,
+ 54, 39, 40, 41, 28, 43, 44, 46,
+ 47, 48, 30, 50, 45, 0, 2, 13,
+ 0, 3, 5, 14, 15, 16, 4, 18,
+ 19, 21, 22, 23, 6, 25, 20, 12,
+ 9, 10, 11, 7, 8, 17, 24, 0,
+ 0, 36, 33, 34, 35, 31, 32, 38,
+ 42, 49, 52, 53, 0
+};
+
+static const char _myanmar_syllable_machine_trans_actions[] = {
+ 3, 0, 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 7,
+ 8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9
+};
+
+static const char _myanmar_syllable_machine_to_state_actions[] = {
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static const char _myanmar_syllable_machine_from_state_actions[] = {
+ 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static const short _myanmar_syllable_machine_eof_trans[] = {
+ 0, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 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, 22, 22, 48, 61
+};
+
+static const int myanmar_syllable_machine_start = 0;
+static const int myanmar_syllable_machine_first_final = 0;
+static const int myanmar_syllable_machine_error = -1;
+
+static const int myanmar_syllable_machine_en_main = 0;
+
+
+#line 55 "hb-ot-shaper-myanmar-machine.rl"
+
+
+
+#line 117 "hb-ot-shaper-myanmar-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ 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++; \
+ if (syllable_serial == 16) syllable_serial = 1; \
+ } HB_STMT_END
+
+inline void
+find_syllables_myanmar (hb_buffer_t *buffer)
+{
+ unsigned int p, pe, eof, ts, te, act HB_UNUSED;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 447 "hb-ot-shaper-myanmar-machine.hh"
+ {
+ cs = myanmar_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 137 "hb-ot-shaper-myanmar-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 463 "hb-ot-shaper-myanmar-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
+ case 2:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 477 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+ _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
+ _inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
+
+ _slen = _myanmar_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
+ ( info[p].myanmar_category()) <= _keys[1] ?
+ ( info[p].myanmar_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _myanmar_syllable_machine_trans_targs[_trans];
+
+ if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
+ case 6:
+#line 110 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
+ break;
+ case 4:
+#line 111 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
+ break;
+ case 8:
+#line 112 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 3:
+#line 113 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
+ break;
+ case 5:
+#line 110 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
+ break;
+ case 7:
+#line 112 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 9:
+#line 113 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
+ break;
+#line 523 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+_again:
+ switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
+ case 1:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 532 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 145 "hb-ot-shaper-myanmar-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_MYANMAR_MACHINE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar.cc
index 13beaf4d4c..1b2a085a8d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar.cc
@@ -28,14 +28,16 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-myanmar.hh"
-#include "hb-ot-shape-complex-myanmar-machine.hh"
+#include "hb-ot-shaper-myanmar-machine.hh"
+#include "hb-ot-shaper-indic.hh"
+#include "hb-ot-layout.hh"
/*
* Myanmar shaper.
*/
+
static const hb_tag_t
myanmar_basic_features[] =
{
@@ -62,11 +64,45 @@ myanmar_other_features[] =
HB_TAG('p','s','t','s'),
};
-static void
+static inline void
+set_myanmar_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+
+ info.myanmar_category() = (myanmar_category_t) (type & 0xFFu);
+}
+
+
+static inline bool
+is_one_of_myanmar (const hb_glyph_info_t &info, unsigned int flags)
+{
+ /* If it ligated, all bets are off. */
+ if (_hb_glyph_info_ligated (&info)) return false;
+ return !!(FLAG_UNSAFE (info.myanmar_category()) & flags);
+}
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
+ * cannot happen in a consonant syllable. The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right!
+ *
+ * Keep in sync with consonant_categories in the generator. */
+#define CONSONANT_FLAGS_MYANMAR (FLAG (M_Cat(C)) | FLAG (M_Cat(CS)) | FLAG (M_Cat(Ra)) | /* FLAG (M_Cat(CM)) | */ FLAG (M_Cat(IV)) | FLAG (M_Cat(GB)) | FLAG (M_Cat(DOTTEDCIRCLE)))
+
+static inline bool
+is_consonant_myanmar (const hb_glyph_info_t &info)
+{
+ return is_one_of_myanmar (info, CONSONANT_FLAGS_MYANMAR);
+}
+
+
+static bool
setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
reorder_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
@@ -92,6 +128,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (nullptr);
}
+ map->add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
@@ -113,14 +150,16 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
set_myanmar_properties (info[i]);
}
-static void
+static bool
setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
find_syllables_myanmar (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
+ return false;
}
static int
@@ -129,7 +168,7 @@ compare_myanmar_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
int a = pa->myanmar_position();
int b = pb->myanmar_position();
- return a < b ? -1 : a == b ? 0 : +1;
+ return (int) a - (int) b;
}
@@ -148,9 +187,9 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
{
unsigned int limit = start;
if (start + 3 <= end &&
- info[start ].myanmar_category() == OT_Ra &&
- info[start+1].myanmar_category() == OT_As &&
- info[start+2].myanmar_category() == OT_H)
+ info[start ].myanmar_category() == M_Cat(Ra) &&
+ info[start+1].myanmar_category() == M_Cat(As) &&
+ info[start+2].myanmar_category() == M_Cat(H))
{
limit += 3;
base = start;
@@ -162,7 +201,7 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
base = limit;
for (unsigned int i = limit; i < end; i++)
- if (is_consonant (info[i]))
+ if (is_consonant_myanmar (info[i]))
{
base = i;
break;
@@ -187,39 +226,40 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
* Myanmar reordering! */
for (; i < end; i++)
{
- if (info[i].myanmar_category() == OT_MR) /* Pre-base reordering */
+ if (info[i].myanmar_category() == M_Cat(MR)) /* Pre-base reordering */
{
info[i].myanmar_position() = POS_PRE_C;
continue;
}
- if (info[i].myanmar_position() < POS_BASE_C) /* Left matra */
+ if (info[i].myanmar_category() == M_Cat(VPre)) /* Left matra */
{
+ info[i].myanmar_position() = POS_PRE_M;
continue;
}
- if (info[i].myanmar_category() == OT_VS)
+ if (info[i].myanmar_category() == M_Cat(VS))
{
info[i].myanmar_position() = info[i - 1].myanmar_position();
continue;
}
- if (pos == POS_AFTER_MAIN && info[i].myanmar_category() == OT_VBlw)
+ if (pos == POS_AFTER_MAIN && info[i].myanmar_category() == M_Cat(VBlw))
{
pos = POS_BELOW_C;
info[i].myanmar_position() = pos;
continue;
}
- if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_A)
+ if (pos == POS_BELOW_C && info[i].myanmar_category() == M_Cat(A))
{
info[i].myanmar_position() = POS_BEFORE_SUB;
continue;
}
- if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_VBlw)
+ if (pos == POS_BELOW_C && info[i].myanmar_category() == M_Cat(VBlw))
{
info[i].myanmar_position() = pos;
continue;
}
- if (pos == POS_BELOW_C && info[i].myanmar_category() != OT_A)
+ if (pos == POS_BELOW_C && info[i].myanmar_category() != M_Cat(A))
{
pos = POS_AFTER_SUB;
info[i].myanmar_position() = pos;
@@ -231,6 +271,33 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
/* Sit tight, rock 'n roll! */
buffer->sort (start, end, compare_myanmar_order);
+
+ /* Flip left-matra sequence. */
+ unsigned first_left_matra = end;
+ unsigned last_left_matra = end;
+ for (unsigned int i = start; i < end; i++)
+ {
+ if (info[i].myanmar_position() == POS_PRE_M)
+ {
+ if (first_left_matra == end)
+ first_left_matra = i;
+ last_left_matra = i;
+ }
+ }
+ /* https://github.com/harfbuzz/harfbuzz/issues/3863 */
+ if (first_left_matra < last_left_matra)
+ {
+ /* No need to merge clusters, done already? */
+ buffer->reverse_range (first_left_matra, last_left_matra + 1);
+ /* Reverse back VS, etc. */
+ unsigned i = first_left_matra;
+ for (unsigned j = i; j <= last_left_matra; j++)
+ if (info[j].myanmar_category() == M_Cat(VPre))
+ {
+ buffer->reverse_range (i, j + 1);
+ i = j + 1;
+ }
+ }
}
static void
@@ -247,22 +314,23 @@ reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
initial_reordering_consonant_syllable (buffer, start, end);
break;
- case myanmar_punctuation_cluster:
case myanmar_non_myanmar_cluster:
break;
}
}
-static void
+static bool
reorder_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
+ bool ret = false;
if (buffer->message (font, "start reordering myanmar"))
{
- hb_syllabic_insert_dotted_circles (font, buffer,
- myanmar_broken_cluster,
- OT_GB);
+ if (hb_syllabic_insert_dotted_circles (font, buffer,
+ myanmar_broken_cluster,
+ M_Cat(DOTTEDCIRCLE)))
+ ret = true;
foreach_syllable (buffer, start, end)
reorder_syllable_myanmar (plan, font->face, buffer, start, end);
@@ -271,10 +339,12 @@ reorder_myanmar (const hb_ot_shape_plan_t *plan,
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
+
+ return ret;
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
+const hb_ot_shaper_t _hb_ot_shaper_myanmar =
{
collect_features_myanmar,
nullptr, /* override_features */
@@ -282,21 +352,22 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
nullptr, /* decompose */
nullptr, /* compose */
setup_masks_myanmar,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
false, /* fallback_position */
};
+#ifndef HB_NO_OT_SHAPER_MYANMAR_ZAWGYI
/* Ugly Zawgyi encoding.
* Disable all auto processing.
* https://github.com/harfbuzz/harfbuzz/issues/1162 */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi =
+const hb_ot_shaper_t _hb_ot_shaper_myanmar_zawgyi =
{
nullptr, /* collect_features */
nullptr, /* override_features */
@@ -304,15 +375,16 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi =
nullptr, /* data_destroy */
nullptr, /* preprocess_text */
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
nullptr, /* decompose */
nullptr, /* compose */
nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
+#endif
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.cc
index 76092c7f38..89226ae4a1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.cc
@@ -26,10 +26,10 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-syllabic.hh"
+#include "hb-ot-shaper-syllabic.hh"
-void
+bool
hb_syllabic_insert_dotted_circles (hb_font_t *font,
hb_buffer_t *buffer,
unsigned int broken_syllable_type,
@@ -38,32 +38,19 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
int dottedcircle_position)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
- return;
-
- /* Note: This loop is extra overhead, but should not be measurable.
- * TODO Use a buffer scratch flag to remove the loop. */
- bool has_broken_syllables = false;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- if ((info[i].syllable() & 0x0F) == broken_syllable_type)
- {
- has_broken_syllables = true;
- break;
- }
- if (likely (!has_broken_syllables))
- return;
-
+ return false;
+ if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE)))
+ return false;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
- return;
+ return false;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CCu;
- dottedcircle.complex_var_u8_category() = dottedcircle_category;
+ dottedcircle.ot_shaper_var_u8_category() = dottedcircle_category;
if (dottedcircle_position != -1)
- dottedcircle.complex_var_u8_auxiliary() = dottedcircle_position;
+ dottedcircle.ot_shaper_var_u8_auxiliary() = dottedcircle_position;
dottedcircle.codepoint = dottedcircle_glyph;
buffer->clear_output ();
@@ -87,7 +74,7 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
{
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
- buffer->cur().complex_var_u8_category() == (unsigned) repha_category)
+ buffer->cur().ot_shaper_var_u8_category() == (unsigned) repha_category)
(void) buffer->next_glyph ();
}
@@ -97,6 +84,16 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
(void) buffer->next_glyph ();
}
buffer->sync ();
+ return true;
+}
+
+HB_INTERNAL bool
+hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
+ return false;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.hh
index b901a660d3..f240ad1c26 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-syllabic.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-syllabic.hh
@@ -22,15 +22,15 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#ifndef HB_OT_SHAPE_COMPLEX_SYLLABIC_HH
-#define HB_OT_SHAPE_COMPLEX_SYLLABIC_HH
+#ifndef HB_OT_SHAPER_SYLLABIC_HH
+#define HB_OT_SHAPER_SYLLABIC_HH
#include "hb.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
-HB_INTERNAL void
+HB_INTERNAL bool
hb_syllabic_insert_dotted_circles (hb_font_t *font,
hb_buffer_t *buffer,
unsigned int broken_syllable_type,
@@ -38,5 +38,10 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
int repha_category = -1,
int dottedcircle_position = -1);
+HB_INTERNAL bool
+hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
-#endif /* HB_OT_SHAPE_COMPLEX_SYLLABIC_HH */
+
+#endif /* HB_OT_SHAPER_SYLLABIC_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-thai.cc
index a1e27a83be..6cd67cde35 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-thai.cc
@@ -28,7 +28,7 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
/* Thai / Lao shaper */
@@ -98,9 +98,9 @@ static hb_codepoint_t
thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
{
struct thai_pua_mapping_t {
- hb_codepoint_t u;
- hb_codepoint_t win_pua;
- hb_codepoint_t mac_pua;
+ uint16_t u;
+ uint16_t win_pua;
+ uint16_t mac_pua;
} const *pua_mappings = nullptr;
static const thai_pua_mapping_t SD_mappings[] = {
{0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */
@@ -222,7 +222,7 @@ do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
hb_font_t *font)
{
-#ifdef HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
+#ifdef HB_NO_OT_SHAPER_THAI_FALLBACK
return;
#endif
@@ -279,7 +279,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
* to be what Uniscribe and other engines implement. According to Eric Muller:
*
* When you have a SARA AM, decompose it in NIKHAHIT + SARA AA, *and* move the
- * NIKHAHIT backwards over any tone mark (0E48-0E4B).
+ * NIKHAHIT backwards over any above-base marks.
*
* <0E14, 0E4B, 0E33> -> <0E14, 0E4D, 0E4B, 0E32>
*
@@ -308,8 +308,8 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
* Nikhahit: U+0E4D U+0ECD
*
* Testing shows that Uniscribe reorder the following marks:
- * Thai: <0E31,0E34..0E37,0E47..0E4E>
- * Lao: <0EB1,0EB4..0EB7,0EC7..0ECE>
+ * Thai: <0E31,0E34..0E37, 0E47..0E4E>
+ * Lao: <0EB1,0EB4..0EB7,0EBB,0EC8..0ECD>
*
* Note how the Lao versions are the same as Thai + 0x80.
*/
@@ -319,7 +319,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
#define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u)
#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du)
#define SARA_AA_FROM_SARA_AM(x) ((x) - 1)
-#define IS_TONE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u))
+#define IS_ABOVE_BASE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u, 0x0E3Bu, 0x0E3Bu))
buffer->clear_output ();
unsigned int count = buffer->len;
@@ -343,7 +343,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
/* Ok, let's see... */
unsigned int start = end - 2;
- while (start > 0 && IS_TONE_MARK (buffer->out_info[start - 1].codepoint))
+ while (start > 0 && IS_ABOVE_BASE_MARK (buffer->out_info[start - 1].codepoint))
start--;
if (start + 2 < end)
@@ -371,7 +371,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
do_thai_pua_shaping (plan, buffer, font);
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
+const hb_ot_shaper_t _hb_ot_shaper_thai =
{
nullptr, /* collect_features */
nullptr, /* override_features */
@@ -379,12 +379,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
nullptr, /* data_destroy */
preprocess_text_thai,
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
nullptr, /* decompose */
nullptr, /* compose */
nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
false,/* fallback_position */
};
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
new file mode 100644
index 0000000000..7249c33356
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh
@@ -0,0 +1,1080 @@
+
+#line 1 "hb-ot-shaper-use-machine.rl"
+/*
+ * Copyright © 2015 Mozilla Foundation.
+ * Copyright © 2015 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_USE_MACHINE_HH
+#define HB_OT_SHAPER_USE_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper-syllabic.hh"
+
+/* buffer var allocations */
+#define use_category() ot_shaper_var_u8_category()
+
+#define USE(Cat) use_syllable_machine_ex_##Cat
+
+enum use_syllable_type_t {
+ use_virama_terminated_cluster,
+ use_sakot_terminated_cluster,
+ use_standard_cluster,
+ use_number_joiner_terminated_cluster,
+ use_numeral_cluster,
+ use_symbol_cluster,
+ use_hieroglyph_cluster,
+ use_broken_cluster,
+ use_non_cluster,
+};
+
+
+#line 54 "hb-ot-shaper-use-machine.hh"
+#define use_syllable_machine_ex_B 1u
+#define use_syllable_machine_ex_CGJ 6u
+#define use_syllable_machine_ex_CMAbv 31u
+#define use_syllable_machine_ex_CMBlw 32u
+#define use_syllable_machine_ex_CS 43u
+#define use_syllable_machine_ex_FAbv 24u
+#define use_syllable_machine_ex_FBlw 25u
+#define use_syllable_machine_ex_FMAbv 45u
+#define use_syllable_machine_ex_FMBlw 46u
+#define use_syllable_machine_ex_FMPst 47u
+#define use_syllable_machine_ex_FPst 26u
+#define use_syllable_machine_ex_G 49u
+#define use_syllable_machine_ex_GB 5u
+#define use_syllable_machine_ex_H 12u
+#define use_syllable_machine_ex_HN 13u
+#define use_syllable_machine_ex_HVM 53u
+#define use_syllable_machine_ex_IS 44u
+#define use_syllable_machine_ex_J 50u
+#define use_syllable_machine_ex_MAbv 27u
+#define use_syllable_machine_ex_MBlw 28u
+#define use_syllable_machine_ex_MPre 30u
+#define use_syllable_machine_ex_MPst 29u
+#define use_syllable_machine_ex_N 4u
+#define use_syllable_machine_ex_O 0u
+#define use_syllable_machine_ex_R 18u
+#define use_syllable_machine_ex_SB 51u
+#define use_syllable_machine_ex_SE 52u
+#define use_syllable_machine_ex_SMAbv 41u
+#define use_syllable_machine_ex_SMBlw 42u
+#define use_syllable_machine_ex_SUB 11u
+#define use_syllable_machine_ex_Sk 48u
+#define use_syllable_machine_ex_VAbv 33u
+#define use_syllable_machine_ex_VBlw 34u
+#define use_syllable_machine_ex_VMAbv 37u
+#define use_syllable_machine_ex_VMBlw 38u
+#define use_syllable_machine_ex_VMPre 23u
+#define use_syllable_machine_ex_VMPst 39u
+#define use_syllable_machine_ex_VPre 22u
+#define use_syllable_machine_ex_VPst 35u
+#define use_syllable_machine_ex_WJ 16u
+#define use_syllable_machine_ex_ZWNJ 14u
+
+
+#line 96 "hb-ot-shaper-use-machine.hh"
+static const unsigned char _use_syllable_machine_trans_keys[] = {
+ 0u, 53u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u,
+ 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u,
+ 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u,
+ 12u, 53u, 11u, 53u, 1u, 14u, 1u, 48u, 11u, 53u, 14u, 42u, 14u, 42u, 11u, 53u,
+ 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u,
+ 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u,
+ 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u,
+ 1u, 14u, 1u, 14u, 1u, 48u, 13u, 14u, 4u, 14u, 11u, 53u, 11u, 53u, 1u, 53u,
+ 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u,
+ 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u,
+ 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 14u, 1u, 14u,
+ 1u, 48u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u,
+ 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u,
+ 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u,
+ 12u, 53u, 11u, 53u, 1u, 14u, 1u, 48u, 4u, 14u, 13u, 14u, 1u, 53u, 11u, 53u,
+ 14u, 42u, 14u, 42u, 1u, 5u, 14u, 52u, 14u, 52u, 14u, 51u, 0
+};
+
+static const char _use_syllable_machine_key_spans[] = {
+ 54, 43, 43, 53, 35, 34, 34, 34,
+ 33, 33, 1, 35, 35, 35, 14, 35,
+ 40, 40, 40, 40, 42, 40, 42, 42,
+ 42, 43, 14, 48, 43, 29, 29, 43,
+ 43, 53, 35, 34, 34, 34, 33, 33,
+ 1, 35, 35, 35, 14, 35, 40, 40,
+ 40, 40, 42, 40, 42, 42, 42, 43,
+ 14, 14, 48, 2, 11, 43, 43, 53,
+ 35, 34, 34, 34, 33, 33, 1, 35,
+ 35, 35, 14, 35, 40, 40, 40, 40,
+ 42, 40, 42, 42, 42, 43, 14, 14,
+ 48, 43, 43, 53, 35, 34, 34, 34,
+ 33, 33, 1, 35, 35, 35, 14, 35,
+ 40, 40, 40, 40, 42, 40, 42, 42,
+ 42, 43, 14, 48, 11, 2, 53, 43,
+ 29, 29, 5, 39, 39, 38
+};
+
+static const short _use_syllable_machine_index_offsets[] = {
+ 0, 55, 99, 143, 197, 233, 268, 303,
+ 338, 372, 406, 408, 444, 480, 516, 531,
+ 567, 608, 649, 690, 731, 774, 815, 858,
+ 901, 944, 988, 1003, 1052, 1096, 1126, 1156,
+ 1200, 1244, 1298, 1334, 1369, 1404, 1439, 1473,
+ 1507, 1509, 1545, 1581, 1617, 1632, 1668, 1709,
+ 1750, 1791, 1832, 1875, 1916, 1959, 2002, 2045,
+ 2089, 2104, 2119, 2168, 2171, 2183, 2227, 2271,
+ 2325, 2361, 2396, 2431, 2466, 2500, 2534, 2536,
+ 2572, 2608, 2644, 2659, 2695, 2736, 2777, 2818,
+ 2859, 2902, 2943, 2986, 3029, 3072, 3116, 3131,
+ 3146, 3195, 3239, 3283, 3337, 3373, 3408, 3443,
+ 3478, 3512, 3546, 3548, 3584, 3620, 3656, 3671,
+ 3707, 3748, 3789, 3830, 3871, 3914, 3955, 3998,
+ 4041, 4084, 4128, 4143, 4192, 4204, 4207, 4261,
+ 4305, 4335, 4365, 4371, 4411, 4451
+};
+
+static const unsigned char _use_syllable_machine_indicies[] = {
+ 0, 1, 2, 2, 3, 4, 2, 2,
+ 2, 2, 2, 5, 6, 7, 8, 2,
+ 2, 2, 9, 2, 2, 2, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 2, 24, 25, 26,
+ 2, 27, 28, 29, 30, 31, 32, 33,
+ 30, 34, 2, 35, 2, 36, 2, 38,
+ 39, 37, 40, 37, 37, 37, 37, 37,
+ 37, 37, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54,
+ 37, 55, 56, 57, 37, 58, 59, 37,
+ 60, 61, 62, 63, 60, 37, 37, 37,
+ 37, 64, 37, 38, 39, 37, 40, 37,
+ 37, 37, 37, 37, 37, 37, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 51,
+ 51, 52, 53, 54, 37, 55, 56, 57,
+ 37, 37, 37, 37, 60, 61, 62, 63,
+ 60, 37, 37, 37, 37, 64, 37, 38,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 40, 37, 37, 37,
+ 37, 37, 37, 37, 37, 42, 43, 44,
+ 45, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 55, 56, 57, 37, 37,
+ 37, 37, 37, 61, 62, 63, 65, 37,
+ 37, 37, 37, 42, 37, 40, 37, 37,
+ 37, 37, 37, 37, 37, 37, 42, 43,
+ 44, 45, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 55, 56, 57, 37,
+ 37, 37, 37, 37, 61, 62, 63, 65,
+ 37, 40, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 43, 44, 45, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 61, 62, 63, 37, 40, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 44,
+ 45, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 61, 62, 63, 37, 40,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 45, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 61, 62,
+ 63, 37, 40, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 61, 62, 37, 40, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 62, 37, 40, 37,
+ 40, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 43, 44, 45, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 55,
+ 56, 57, 37, 37, 37, 37, 37, 61,
+ 62, 63, 65, 37, 40, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 43, 44,
+ 45, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 56, 57, 37, 37,
+ 37, 37, 37, 61, 62, 63, 65, 37,
+ 40, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 43, 44, 45, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 57, 37, 37, 37, 37, 37, 61,
+ 62, 63, 65, 37, 66, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 40, 37, 40, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 43, 44, 45,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 61, 62, 63, 65, 37, 40,
+ 37, 37, 37, 37, 37, 37, 37, 41,
+ 42, 43, 44, 45, 37, 37, 37, 37,
+ 37, 37, 52, 53, 54, 37, 55, 56,
+ 57, 37, 37, 37, 37, 37, 61, 62,
+ 63, 65, 37, 37, 37, 37, 42, 37,
+ 40, 37, 37, 37, 37, 37, 37, 37,
+ 37, 42, 43, 44, 45, 37, 37, 37,
+ 37, 37, 37, 52, 53, 54, 37, 55,
+ 56, 57, 37, 37, 37, 37, 37, 61,
+ 62, 63, 65, 37, 37, 37, 37, 42,
+ 37, 40, 37, 37, 37, 37, 37, 37,
+ 37, 37, 42, 43, 44, 45, 37, 37,
+ 37, 37, 37, 37, 37, 53, 54, 37,
+ 55, 56, 57, 37, 37, 37, 37, 37,
+ 61, 62, 63, 65, 37, 37, 37, 37,
+ 42, 37, 40, 37, 37, 37, 37, 37,
+ 37, 37, 37, 42, 43, 44, 45, 37,
+ 37, 37, 37, 37, 37, 37, 37, 54,
+ 37, 55, 56, 57, 37, 37, 37, 37,
+ 37, 61, 62, 63, 65, 37, 37, 37,
+ 37, 42, 37, 67, 37, 40, 37, 37,
+ 37, 37, 37, 37, 37, 41, 42, 43,
+ 44, 45, 37, 47, 48, 37, 37, 37,
+ 52, 53, 54, 37, 55, 56, 57, 37,
+ 37, 37, 37, 37, 61, 62, 63, 65,
+ 37, 37, 37, 37, 42, 37, 40, 37,
+ 37, 37, 37, 37, 37, 37, 37, 42,
+ 43, 44, 45, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 55, 56, 57,
+ 37, 37, 37, 37, 37, 61, 62, 63,
+ 65, 37, 37, 37, 37, 42, 37, 67,
+ 37, 40, 37, 37, 37, 37, 37, 37,
+ 37, 41, 42, 43, 44, 45, 37, 37,
+ 48, 37, 37, 37, 52, 53, 54, 37,
+ 55, 56, 57, 37, 37, 37, 37, 37,
+ 61, 62, 63, 65, 37, 37, 37, 37,
+ 42, 37, 67, 37, 40, 37, 37, 37,
+ 37, 37, 37, 37, 41, 42, 43, 44,
+ 45, 37, 37, 37, 37, 37, 37, 52,
+ 53, 54, 37, 55, 56, 57, 37, 37,
+ 37, 37, 37, 61, 62, 63, 65, 37,
+ 37, 37, 37, 42, 37, 67, 37, 40,
+ 37, 37, 37, 37, 37, 37, 37, 41,
+ 42, 43, 44, 45, 46, 47, 48, 37,
+ 37, 37, 52, 53, 54, 37, 55, 56,
+ 57, 37, 37, 37, 37, 37, 61, 62,
+ 63, 65, 37, 37, 37, 37, 42, 37,
+ 38, 39, 37, 40, 37, 37, 37, 37,
+ 37, 37, 37, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 37, 51, 52, 53,
+ 54, 37, 55, 56, 57, 37, 37, 37,
+ 37, 60, 61, 62, 63, 60, 37, 37,
+ 37, 37, 64, 37, 38, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 40, 37, 38, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 40, 37, 37, 37, 37, 37, 37, 37,
+ 37, 42, 43, 44, 45, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 55,
+ 56, 57, 37, 37, 37, 37, 37, 61,
+ 62, 63, 65, 37, 38, 39, 37, 40,
+ 37, 37, 37, 37, 37, 37, 37, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 37, 55, 56,
+ 57, 37, 37, 37, 37, 60, 61, 62,
+ 63, 60, 37, 37, 37, 37, 64, 37,
+ 40, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 58, 59, 37, 40, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 59, 37, 69, 70, 68, 71,
+ 68, 68, 68, 68, 68, 68, 68, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80,
+ 1, 81, 82, 83, 84, 68, 85, 86,
+ 87, 68, 68, 68, 68, 88, 89, 90,
+ 91, 92, 68, 68, 68, 68, 93, 68,
+ 69, 70, 68, 71, 68, 68, 68, 68,
+ 68, 68, 68, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 81, 82, 83,
+ 84, 68, 85, 86, 87, 68, 68, 68,
+ 68, 88, 89, 90, 91, 92, 68, 68,
+ 68, 68, 93, 68, 69, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 71, 68, 68, 68, 68, 68, 68,
+ 68, 68, 73, 74, 75, 76, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 85, 86, 87, 68, 68, 68, 68, 68,
+ 89, 90, 91, 94, 68, 68, 68, 68,
+ 73, 68, 71, 68, 68, 68, 68, 68,
+ 68, 68, 68, 73, 74, 75, 76, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 85, 86, 87, 68, 68, 68, 68,
+ 68, 89, 90, 91, 94, 68, 71, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 74, 75, 76, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 89, 90, 91,
+ 68, 71, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 75, 76, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 89, 90, 91, 68, 71, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 76, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 89, 90, 91, 68, 71,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 89, 90,
+ 68, 71, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 90, 68, 71, 68, 71, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 74,
+ 75, 76, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 85, 86, 87, 68,
+ 68, 68, 68, 68, 89, 90, 91, 94,
+ 68, 71, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 74, 75, 76, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 86, 87, 68, 68, 68, 68, 68,
+ 89, 90, 91, 94, 68, 71, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 74,
+ 75, 76, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 87, 68,
+ 68, 68, 68, 68, 89, 90, 91, 94,
+ 68, 96, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 97, 95,
+ 71, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 74, 75, 76, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 89,
+ 90, 91, 94, 68, 71, 68, 68, 68,
+ 68, 68, 68, 68, 72, 73, 74, 75,
+ 76, 68, 68, 68, 68, 68, 68, 82,
+ 83, 84, 68, 85, 86, 87, 68, 68,
+ 68, 68, 68, 89, 90, 91, 94, 68,
+ 68, 68, 68, 73, 68, 71, 68, 68,
+ 68, 68, 68, 68, 68, 68, 73, 74,
+ 75, 76, 68, 68, 68, 68, 68, 68,
+ 82, 83, 84, 68, 85, 86, 87, 68,
+ 68, 68, 68, 68, 89, 90, 91, 94,
+ 68, 68, 68, 68, 73, 68, 71, 68,
+ 68, 68, 68, 68, 68, 68, 68, 73,
+ 74, 75, 76, 68, 68, 68, 68, 68,
+ 68, 68, 83, 84, 68, 85, 86, 87,
+ 68, 68, 68, 68, 68, 89, 90, 91,
+ 94, 68, 68, 68, 68, 73, 68, 71,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 73, 74, 75, 76, 68, 68, 68, 68,
+ 68, 68, 68, 68, 84, 68, 85, 86,
+ 87, 68, 68, 68, 68, 68, 89, 90,
+ 91, 94, 68, 68, 68, 68, 73, 68,
+ 98, 68, 71, 68, 68, 68, 68, 68,
+ 68, 68, 72, 73, 74, 75, 76, 68,
+ 78, 79, 68, 68, 68, 82, 83, 84,
+ 68, 85, 86, 87, 68, 68, 68, 68,
+ 68, 89, 90, 91, 94, 68, 68, 68,
+ 68, 73, 68, 71, 68, 68, 68, 68,
+ 68, 68, 68, 68, 73, 74, 75, 76,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 85, 86, 87, 68, 68, 68,
+ 68, 68, 89, 90, 91, 94, 68, 68,
+ 68, 68, 73, 68, 98, 68, 71, 68,
+ 68, 68, 68, 68, 68, 68, 72, 73,
+ 74, 75, 76, 68, 68, 79, 68, 68,
+ 68, 82, 83, 84, 68, 85, 86, 87,
+ 68, 68, 68, 68, 68, 89, 90, 91,
+ 94, 68, 68, 68, 68, 73, 68, 98,
+ 68, 71, 68, 68, 68, 68, 68, 68,
+ 68, 72, 73, 74, 75, 76, 68, 68,
+ 68, 68, 68, 68, 82, 83, 84, 68,
+ 85, 86, 87, 68, 68, 68, 68, 68,
+ 89, 90, 91, 94, 68, 68, 68, 68,
+ 73, 68, 98, 68, 71, 68, 68, 68,
+ 68, 68, 68, 68, 72, 73, 74, 75,
+ 76, 77, 78, 79, 68, 68, 68, 82,
+ 83, 84, 68, 85, 86, 87, 68, 68,
+ 68, 68, 68, 89, 90, 91, 94, 68,
+ 68, 68, 68, 73, 68, 69, 70, 68,
+ 71, 68, 68, 68, 68, 68, 68, 68,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 68, 81, 82, 83, 84, 68, 85,
+ 86, 87, 68, 68, 68, 68, 88, 89,
+ 90, 91, 92, 68, 68, 68, 68, 93,
+ 68, 69, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 100, 99,
+ 69, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 97, 95, 69,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 71, 68, 68, 68,
+ 68, 68, 68, 68, 68, 73, 74, 75,
+ 76, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 85, 86, 87, 68, 68,
+ 68, 68, 68, 89, 90, 91, 94, 68,
+ 102, 103, 101, 3, 104, 104, 104, 104,
+ 104, 104, 104, 104, 104, 105, 104, 106,
+ 107, 68, 71, 68, 68, 68, 68, 68,
+ 68, 68, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121,
+ 68, 122, 123, 124, 68, 58, 59, 68,
+ 125, 126, 127, 128, 129, 68, 68, 68,
+ 68, 130, 68, 106, 107, 68, 71, 68,
+ 68, 68, 68, 68, 68, 68, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 118,
+ 118, 119, 120, 121, 68, 122, 123, 124,
+ 68, 68, 68, 68, 125, 126, 127, 128,
+ 129, 68, 68, 68, 68, 130, 68, 106,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 71, 68, 68, 68,
+ 68, 68, 68, 68, 68, 109, 110, 111,
+ 112, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 122, 123, 124, 68, 68,
+ 68, 68, 68, 126, 127, 128, 131, 68,
+ 68, 68, 68, 109, 68, 71, 68, 68,
+ 68, 68, 68, 68, 68, 68, 109, 110,
+ 111, 112, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 122, 123, 124, 68,
+ 68, 68, 68, 68, 126, 127, 128, 131,
+ 68, 71, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 110, 111, 112, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 126, 127, 128, 68, 71, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 111,
+ 112, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 126, 127, 128, 68, 71,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 112, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 126, 127,
+ 128, 68, 71, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 126, 127, 68, 71, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 127, 68, 71, 68,
+ 71, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 110, 111, 112, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 122,
+ 123, 124, 68, 68, 68, 68, 68, 126,
+ 127, 128, 131, 68, 71, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 110, 111,
+ 112, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 123, 124, 68, 68,
+ 68, 68, 68, 126, 127, 128, 131, 68,
+ 71, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 110, 111, 112, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 124, 68, 68, 68, 68, 68, 126,
+ 127, 128, 131, 68, 132, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 97, 95, 71, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 110, 111, 112,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 126, 127, 128, 131, 68, 71,
+ 68, 68, 68, 68, 68, 68, 68, 108,
+ 109, 110, 111, 112, 68, 68, 68, 68,
+ 68, 68, 119, 120, 121, 68, 122, 123,
+ 124, 68, 68, 68, 68, 68, 126, 127,
+ 128, 131, 68, 68, 68, 68, 109, 68,
+ 71, 68, 68, 68, 68, 68, 68, 68,
+ 68, 109, 110, 111, 112, 68, 68, 68,
+ 68, 68, 68, 119, 120, 121, 68, 122,
+ 123, 124, 68, 68, 68, 68, 68, 126,
+ 127, 128, 131, 68, 68, 68, 68, 109,
+ 68, 71, 68, 68, 68, 68, 68, 68,
+ 68, 68, 109, 110, 111, 112, 68, 68,
+ 68, 68, 68, 68, 68, 120, 121, 68,
+ 122, 123, 124, 68, 68, 68, 68, 68,
+ 126, 127, 128, 131, 68, 68, 68, 68,
+ 109, 68, 71, 68, 68, 68, 68, 68,
+ 68, 68, 68, 109, 110, 111, 112, 68,
+ 68, 68, 68, 68, 68, 68, 68, 121,
+ 68, 122, 123, 124, 68, 68, 68, 68,
+ 68, 126, 127, 128, 131, 68, 68, 68,
+ 68, 109, 68, 133, 68, 71, 68, 68,
+ 68, 68, 68, 68, 68, 108, 109, 110,
+ 111, 112, 68, 114, 115, 68, 68, 68,
+ 119, 120, 121, 68, 122, 123, 124, 68,
+ 68, 68, 68, 68, 126, 127, 128, 131,
+ 68, 68, 68, 68, 109, 68, 71, 68,
+ 68, 68, 68, 68, 68, 68, 68, 109,
+ 110, 111, 112, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 122, 123, 124,
+ 68, 68, 68, 68, 68, 126, 127, 128,
+ 131, 68, 68, 68, 68, 109, 68, 133,
+ 68, 71, 68, 68, 68, 68, 68, 68,
+ 68, 108, 109, 110, 111, 112, 68, 68,
+ 115, 68, 68, 68, 119, 120, 121, 68,
+ 122, 123, 124, 68, 68, 68, 68, 68,
+ 126, 127, 128, 131, 68, 68, 68, 68,
+ 109, 68, 133, 68, 71, 68, 68, 68,
+ 68, 68, 68, 68, 108, 109, 110, 111,
+ 112, 68, 68, 68, 68, 68, 68, 119,
+ 120, 121, 68, 122, 123, 124, 68, 68,
+ 68, 68, 68, 126, 127, 128, 131, 68,
+ 68, 68, 68, 109, 68, 133, 68, 71,
+ 68, 68, 68, 68, 68, 68, 68, 108,
+ 109, 110, 111, 112, 113, 114, 115, 68,
+ 68, 68, 119, 120, 121, 68, 122, 123,
+ 124, 68, 68, 68, 68, 68, 126, 127,
+ 128, 131, 68, 68, 68, 68, 109, 68,
+ 106, 107, 68, 71, 68, 68, 68, 68,
+ 68, 68, 68, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 68, 118, 119, 120,
+ 121, 68, 122, 123, 124, 68, 68, 68,
+ 68, 125, 126, 127, 128, 129, 68, 68,
+ 68, 68, 130, 68, 106, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 100, 99, 106, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 97, 95, 106, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 71,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 109, 110, 111, 112, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 122, 123,
+ 124, 68, 68, 68, 68, 68, 126, 127,
+ 128, 131, 68, 106, 107, 68, 71, 68,
+ 68, 68, 68, 68, 68, 68, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 68, 122, 123, 124,
+ 68, 68, 68, 68, 125, 126, 127, 128,
+ 129, 68, 68, 68, 68, 130, 68, 5,
+ 6, 134, 8, 134, 134, 134, 134, 134,
+ 134, 134, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 20, 20, 21, 22, 23,
+ 134, 24, 25, 26, 134, 134, 134, 134,
+ 30, 31, 32, 33, 30, 134, 134, 134,
+ 134, 36, 134, 5, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 8, 134, 134, 134, 134, 134, 134, 134,
+ 134, 11, 12, 13, 14, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 24,
+ 25, 26, 134, 134, 134, 134, 134, 31,
+ 32, 33, 135, 134, 134, 134, 134, 11,
+ 134, 8, 134, 134, 134, 134, 134, 134,
+ 134, 134, 11, 12, 13, 14, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 24, 25, 26, 134, 134, 134, 134, 134,
+ 31, 32, 33, 135, 134, 8, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 12,
+ 13, 14, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 31, 32, 33, 134,
+ 8, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 13, 14, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 31,
+ 32, 33, 134, 8, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 14,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 31, 32, 33, 134, 8, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 31, 32, 134,
+ 8, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 32, 134, 8, 134, 8, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 12, 13,
+ 14, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 24, 25, 26, 134, 134,
+ 134, 134, 134, 31, 32, 33, 135, 134,
+ 8, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 12, 13, 14, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 25, 26, 134, 134, 134, 134, 134, 31,
+ 32, 33, 135, 134, 8, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 12, 13,
+ 14, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 26, 134, 134,
+ 134, 134, 134, 31, 32, 33, 135, 134,
+ 136, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 8, 134, 8,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 12, 13, 14, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 31, 32,
+ 33, 135, 134, 8, 134, 134, 134, 134,
+ 134, 134, 134, 10, 11, 12, 13, 14,
+ 134, 134, 134, 134, 134, 134, 21, 22,
+ 23, 134, 24, 25, 26, 134, 134, 134,
+ 134, 134, 31, 32, 33, 135, 134, 134,
+ 134, 134, 11, 134, 8, 134, 134, 134,
+ 134, 134, 134, 134, 134, 11, 12, 13,
+ 14, 134, 134, 134, 134, 134, 134, 21,
+ 22, 23, 134, 24, 25, 26, 134, 134,
+ 134, 134, 134, 31, 32, 33, 135, 134,
+ 134, 134, 134, 11, 134, 8, 134, 134,
+ 134, 134, 134, 134, 134, 134, 11, 12,
+ 13, 14, 134, 134, 134, 134, 134, 134,
+ 134, 22, 23, 134, 24, 25, 26, 134,
+ 134, 134, 134, 134, 31, 32, 33, 135,
+ 134, 134, 134, 134, 11, 134, 8, 134,
+ 134, 134, 134, 134, 134, 134, 134, 11,
+ 12, 13, 14, 134, 134, 134, 134, 134,
+ 134, 134, 134, 23, 134, 24, 25, 26,
+ 134, 134, 134, 134, 134, 31, 32, 33,
+ 135, 134, 134, 134, 134, 11, 134, 137,
+ 134, 8, 134, 134, 134, 134, 134, 134,
+ 134, 10, 11, 12, 13, 14, 134, 16,
+ 17, 134, 134, 134, 21, 22, 23, 134,
+ 24, 25, 26, 134, 134, 134, 134, 134,
+ 31, 32, 33, 135, 134, 134, 134, 134,
+ 11, 134, 8, 134, 134, 134, 134, 134,
+ 134, 134, 134, 11, 12, 13, 14, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 24, 25, 26, 134, 134, 134, 134,
+ 134, 31, 32, 33, 135, 134, 134, 134,
+ 134, 11, 134, 137, 134, 8, 134, 134,
+ 134, 134, 134, 134, 134, 10, 11, 12,
+ 13, 14, 134, 134, 17, 134, 134, 134,
+ 21, 22, 23, 134, 24, 25, 26, 134,
+ 134, 134, 134, 134, 31, 32, 33, 135,
+ 134, 134, 134, 134, 11, 134, 137, 134,
+ 8, 134, 134, 134, 134, 134, 134, 134,
+ 10, 11, 12, 13, 14, 134, 134, 134,
+ 134, 134, 134, 21, 22, 23, 134, 24,
+ 25, 26, 134, 134, 134, 134, 134, 31,
+ 32, 33, 135, 134, 134, 134, 134, 11,
+ 134, 137, 134, 8, 134, 134, 134, 134,
+ 134, 134, 134, 10, 11, 12, 13, 14,
+ 15, 16, 17, 134, 134, 134, 21, 22,
+ 23, 134, 24, 25, 26, 134, 134, 134,
+ 134, 134, 31, 32, 33, 135, 134, 134,
+ 134, 134, 11, 134, 5, 6, 134, 8,
+ 134, 134, 134, 134, 134, 134, 134, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18,
+ 134, 20, 21, 22, 23, 134, 24, 25,
+ 26, 134, 134, 134, 134, 30, 31, 32,
+ 33, 30, 134, 134, 134, 134, 36, 134,
+ 5, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 8, 134, 5,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 8, 134, 134, 134,
+ 134, 134, 134, 134, 134, 11, 12, 13,
+ 14, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 24, 25, 26, 134, 134,
+ 134, 134, 134, 31, 32, 33, 135, 134,
+ 138, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 8, 134, 7, 8, 134, 1,
+ 134, 134, 134, 1, 134, 134, 134, 134,
+ 134, 5, 6, 7, 8, 134, 134, 134,
+ 134, 134, 134, 134, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 134, 24, 25, 26, 134, 27,
+ 28, 134, 30, 31, 32, 33, 30, 134,
+ 134, 134, 134, 36, 134, 5, 6, 134,
+ 8, 134, 134, 134, 134, 134, 134, 134,
+ 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 134, 24,
+ 25, 26, 134, 134, 134, 134, 30, 31,
+ 32, 33, 30, 134, 134, 134, 134, 36,
+ 134, 8, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 27, 28, 134, 8,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 28, 134, 1, 139, 139,
+ 139, 1, 139, 141, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 142,
+ 140, 34, 140, 141, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 34, 142,
+ 140, 142, 140, 141, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 34, 140,
+ 35, 140, 0
+};
+
+static const char _use_syllable_machine_trans_targs[] = {
+ 1, 31, 0, 59, 61, 90, 91, 116,
+ 0, 118, 104, 92, 93, 94, 95, 108,
+ 110, 111, 112, 119, 113, 105, 106, 107,
+ 99, 100, 101, 120, 121, 122, 114, 96,
+ 97, 98, 123, 125, 115, 0, 2, 3,
+ 0, 16, 4, 5, 6, 7, 20, 22,
+ 23, 24, 28, 25, 17, 18, 19, 11,
+ 12, 13, 29, 30, 26, 8, 9, 10,
+ 27, 14, 15, 21, 0, 32, 33, 0,
+ 46, 34, 35, 36, 37, 50, 52, 53,
+ 54, 55, 47, 48, 49, 41, 42, 43,
+ 56, 38, 39, 40, 57, 58, 44, 0,
+ 45, 0, 51, 0, 0, 0, 60, 0,
+ 0, 0, 62, 63, 76, 64, 65, 66,
+ 67, 80, 82, 83, 84, 89, 85, 77,
+ 78, 79, 71, 72, 73, 86, 68, 69,
+ 70, 87, 88, 74, 75, 81, 0, 102,
+ 103, 109, 117, 0, 0, 0, 124
+};
+
+static const char _use_syllable_machine_trans_actions[] = {
+ 0, 0, 3, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 7, 0, 0, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 10, 0, 11, 12, 13, 0, 14,
+ 15, 16, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 17, 0,
+ 0, 0, 0, 18, 19, 20, 0
+};
+
+static const char _use_syllable_machine_to_state_actions[] = {
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
+
+static const char _use_syllable_machine_from_state_actions[] = {
+ 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
+
+static const short _use_syllable_machine_eof_trans[] = {
+ 0, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 96, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 100, 96, 69, 102, 105, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 96, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 100, 96,
+ 69, 69, 135, 135, 135, 135, 135, 135,
+ 135, 135, 135, 135, 135, 135, 135, 135,
+ 135, 135, 135, 135, 135, 135, 135, 135,
+ 135, 135, 135, 135, 135, 135, 135, 135,
+ 135, 135, 140, 141, 141, 141
+};
+
+static const int use_syllable_machine_start = 0;
+static const int use_syllable_machine_first_final = 0;
+static const int use_syllable_machine_error = -1;
+
+static const int use_syllable_machine_en_main = 0;
+
+
+#line 58 "hb-ot-shaper-use-machine.rl"
+
+
+
+#line 182 "hb-ot-shaper-use-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %u..%u %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
+ for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (syllable_serial == 16) syllable_serial = 1; \
+ } HB_STMT_END
+
+
+template <typename Iter>
+struct machine_index_t :
+ hb_iter_with_fallback_t<machine_index_t<Iter>,
+ typename Iter::item_t>
+{
+ machine_index_t (const Iter& it) : it (it) {}
+ machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
+ typename Iter::item_t> (),
+ it (o.it), is_null (o.is_null) {}
+
+ static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
+ static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
+
+ typename Iter::item_t __item__ () const { return *it; }
+ typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
+ unsigned __len__ () const { return it.len (); }
+ void __next__ () { ++it; }
+ void __forward__ (unsigned n) { it += n; }
+ void __prev__ () { --it; }
+ void __rewind__ (unsigned n) { it -= n; }
+
+ void operator = (unsigned n)
+ {
+ assert (n == 0);
+ is_null = true;
+ }
+ explicit operator bool () { return !is_null; }
+
+ void operator = (const machine_index_t& o)
+ {
+ is_null = o.is_null;
+ unsigned index = (*it).first;
+ unsigned n = (*o.it).first;
+ if (index < n) it += n - index; else if (index > n) it -= index - n;
+ }
+ bool operator == (const machine_index_t& o) const
+ { return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
+ bool operator != (const machine_index_t& o) const { return !(*this == o); }
+
+ private:
+ Iter it;
+ bool is_null = false;
+};
+struct
+{
+ template <typename Iter,
+ hb_requires (hb_is_iterable (Iter))>
+ machine_index_t<hb_iter_type<Iter>>
+ operator () (Iter&& it) const
+ { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
+}
+HB_FUNCOBJ (machine_index);
+
+
+
+static bool
+not_ccs_default_ignorable (const hb_glyph_info_t &i)
+{ return i.use_category() != USE(CGJ); }
+
+static inline void
+find_syllables_use (hb_buffer_t *buffer)
+{
+ hb_glyph_info_t *info = buffer->info;
+ auto p =
+ + hb_iter (info, buffer->len)
+ | hb_enumerate
+ | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
+ hb_second)
+ | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
+ {
+ if (p.second.use_category() == USE(ZWNJ))
+ for (unsigned i = p.first + 1; i < buffer->len; ++i)
+ if (not_ccs_default_ignorable (info[i]))
+ return !_hb_glyph_info_is_unicode_mark (&info[i]);
+ return true;
+ })
+ | hb_enumerate
+ | machine_index
+ ;
+ auto pe = p + p.len ();
+ auto eof = +pe;
+ auto ts = +p;
+ auto te = +p;
+ unsigned int act HB_UNUSED;
+ int cs;
+
+#line 922 "hb-ot-shaper-use-machine.hh"
+ {
+ cs = use_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 282 "hb-ot-shaper-use-machine.rl"
+
+
+ unsigned int syllable_serial = 1;
+
+#line 931 "hb-ot-shaper-use-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const unsigned char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _use_syllable_machine_from_state_actions[cs] ) {
+ case 2:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 943 "hb-ot-shaper-use-machine.hh"
+ }
+
+ _keys = _use_syllable_machine_trans_keys + (cs<<1);
+ _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
+
+ _slen = _use_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( (*p).second.second.use_category()) &&
+ ( (*p).second.second.use_category()) <= _keys[1] ?
+ ( (*p).second.second.use_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _use_syllable_machine_trans_targs[_trans];
+
+ if ( _use_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _use_syllable_machine_trans_actions[_trans] ) {
+ case 12:
+#line 170 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_virama_terminated_cluster); }}
+ break;
+ case 10:
+#line 171 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_sakot_terminated_cluster); }}
+ break;
+ case 8:
+#line 172 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_standard_cluster); }}
+ break;
+ case 16:
+#line 173 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_number_joiner_terminated_cluster); }}
+ break;
+ case 14:
+#line 174 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_numeral_cluster); }}
+ break;
+ case 6:
+#line 175 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_symbol_cluster); }}
+ break;
+ case 20:
+#line 176 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_hieroglyph_cluster); }}
+ break;
+ case 4:
+#line 177 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 3:
+#line 178 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_non_cluster); }}
+ break;
+ case 11:
+#line 170 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_virama_terminated_cluster); }}
+ break;
+ case 9:
+#line 171 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
+ break;
+ case 7:
+#line 172 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_standard_cluster); }}
+ break;
+ case 15:
+#line 173 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
+ break;
+ case 13:
+#line 174 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_numeral_cluster); }}
+ break;
+ case 5:
+#line 175 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_symbol_cluster); }}
+ break;
+ case 19:
+#line 176 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
+ break;
+ case 17:
+#line 177 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 18:
+#line 178 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_non_cluster); }}
+ break;
+#line 1014 "hb-ot-shaper-use-machine.hh"
+ }
+
+_again:
+ switch ( _use_syllable_machine_to_state_actions[cs] ) {
+ case 1:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 1021 "hb-ot-shaper-use-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _use_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 287 "hb-ot-shaper-use-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_USE_MACHINE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-table.hh
new file mode 100644
index 0000000000..6b6b552ee5
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-table.hh
@@ -0,0 +1,674 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
+ *
+ * on files with these headers:
+ *
+ * # IndicSyllabicCategory-15.0.0.txt
+ * # Date: 2022-05-26, 02:18:00 GMT [KW, RP]
+ * # IndicPositionalCategory-15.0.0.txt
+ * # Date: 2022-05-26, 02:18:00 GMT [KW, RP]
+ * # ArabicShaping-15.0.0.txt
+ * # Date: 2022-02-14, 18:50:00 GMT [KW, RP]
+ * # DerivedCoreProperties-15.0.0.txt
+ * # Date: 2022-08-05, 22:17:05 GMT
+ * # Blocks-15.0.0.txt
+ * # Date: 2022-01-28, 20:58:00 GMT [KW]
+ * # Scripts-15.0.0.txt
+ * # Date: 2022-04-26, 23:15:02 GMT
+ * # Override values For Indic_Syllabic_Category
+ * # Not derivable
+ * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
+ * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
+ * # Override values For Indic_Positional_Category
+ * # Not derivable
+ * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
+ * # Updated for L2/19-083 by Andrew Glass 2019-05-06
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
+ * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
+ * UnicodeData.txt does not have a header.
+ */
+
+#ifndef HB_OT_SHAPER_USE_TABLE_HH
+#define HB_OT_SHAPER_USE_TABLE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper-use-machine.hh"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+#define B USE(B) /* BASE */
+#define CGJ USE(CGJ) /* CGJ */
+#define CS USE(CS) /* CONS_WITH_STACKER */
+#define G USE(G) /* HIEROGLYPH */
+#define GB USE(GB) /* BASE_OTHER */
+#define H USE(H) /* HALANT */
+#define HN USE(HN) /* HALANT_NUM */
+#define HVM USE(HVM) /* HALANT_OR_VOWEL_MODIFIER */
+#define IS USE(IS) /* INVISIBLE_STACKER */
+#define J USE(J) /* HIEROGLYPH_JOINER */
+#define N USE(N) /* BASE_NUM */
+#define O USE(O) /* OTHER */
+#define R USE(R) /* REPHA */
+#define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
+#define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */
+#define SUB USE(SUB) /* CONS_SUB */
+#define Sk USE(Sk) /* SAKOT */
+#define WJ USE(WJ) /* Word_Joiner */
+#define ZWNJ USE(ZWNJ) /* ZWNJ */
+#define CMAbv USE(CMAbv)
+#define CMBlw USE(CMBlw)
+#define FAbv USE(FAbv)
+#define FBlw USE(FBlw)
+#define FPst USE(FPst)
+#define FMAbv USE(FMAbv)
+#define FMBlw USE(FMBlw)
+#define FMPst USE(FMPst)
+#define MAbv USE(MAbv)
+#define MBlw USE(MBlw)
+#define MPst USE(MPst)
+#define MPre USE(MPre)
+#define SMAbv USE(SMAbv)
+#define SMBlw USE(SMBlw)
+#define VAbv USE(VAbv)
+#define VBlw USE(VBlw)
+#define VPst USE(VPst)
+#define VPre USE(VPre)
+#define VMAbv USE(VMAbv)
+#define VMBlw USE(VMBlw)
+#define VMPst USE(VMPst)
+#define VMPre USE(VMPre)
+#pragma GCC diagnostic pop
+
+
+#ifndef HB_OPTIMIZE_SIZE
+
+static const uint8_t
+hb_use_u8[3141] =
+{
+ 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 14, 0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 4, 2, 2,
+ 5, 6, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 2, 2, 17,
+ 18, 19, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 2, 33, 2, 2, 2,
+ 2, 34, 35, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 37, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 38, 39, 40, 41, 42, 43, 2, 44, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 46, 2,
+ 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 48, 49, 2, 2, 2,
+ 2, 2, 2, 2, 2, 50, 51, 2, 52, 2, 2, 53, 2, 2, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 2, 64, 65, 2, 66, 67, 68, 69,
+ 2, 70, 2, 71, 72, 73, 74, 2, 2, 75, 76, 77, 78, 2, 79, 80,
+ 2, 81, 81, 81, 81, 81, 81, 81, 81, 82, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 83, 84, 2, 2, 2, 2, 2, 2, 2, 85,
+ 86, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 81, 81, 81, 87, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 88, 89, 2, 2, 2, 2, 2,
+ 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 91, 2, 2, 92, 2, 2, 2, 93, 2, 2, 2, 2, 2,
+ 2, 2, 2, 94, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 95, 95, 96, 97, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4,
+ 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 8, 9, 9, 9, 9, 0, 0, 0, 7, 10,
+ 0, 2, 2, 2, 2, 11, 12, 0, 0, 9, 13, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 14, 15, 16, 17, 18, 19, 20, 14, 21, 22,
+ 23, 10, 24, 25, 18, 2, 2, 2, 2, 2, 18, 0, 2, 2, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 26, 27, 28, 2, 2, 2, 7,
+ 28, 7, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, 2,
+ 2, 7, 7, 0, 2, 2, 0, 15, 16, 17, 18, 29, 30, 31, 30, 32,
+ 0, 0, 0, 0, 33, 0, 0, 2, 28, 2, 0, 0, 0, 0, 0, 7,
+ 34, 10, 13, 28, 2, 2, 7, 0, 28, 7, 2, 28, 7, 2, 0, 35,
+ 16, 17, 29, 0, 25, 36, 25, 37, 0, 38, 0, 0, 0, 28, 2, 7,
+ 7, 0, 0, 0, 2, 2, 2, 2, 2, 39, 40, 41, 0, 0, 0, 0,
+ 0, 10, 13, 28, 2, 2, 2, 2, 28, 2, 28, 2, 2, 2, 2, 2,
+ 2, 7, 2, 28, 2, 2, 0, 15, 16, 17, 18, 19, 25, 20, 33, 22,
+ 0, 0, 0, 0, 0, 28, 39, 39, 42, 10, 27, 28, 2, 2, 2, 7,
+ 28, 7, 2, 28, 2, 2, 0, 15, 43, 0, 0, 25, 20, 0, 0, 2,
+ 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 44, 28, 2, 2, 7, 0,
+ 2, 7, 2, 2, 0, 28, 7, 7, 2, 0, 28, 7, 0, 2, 7, 0,
+ 2, 2, 2, 2, 2, 2, 0, 0, 21, 14, 45, 0, 46, 31, 46, 32,
+ 0, 0, 0, 0, 33, 0, 0, 0, 0, 13, 27, 47, 2, 2, 2, 7,
+ 2, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 15,
+ 20, 14, 21, 45, 20, 36, 20, 37, 0, 0, 0, 25, 29, 2, 7, 0,
+ 0, 8, 27, 28, 2, 2, 2, 7, 2, 2, 2, 28, 2, 2, 0, 15,
+ 43, 0, 0, 33, 45, 0, 0, 0, 7, 48, 49, 0, 0, 0, 0, 0,
+ 0, 9, 27, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 50, 51,
+ 21, 21, 17, 29, 46, 31, 46, 32, 52, 0, 0, 0, 33, 0, 0, 0,
+ 28, 10, 27, 28, 2, 2, 2, 2, 2, 2, 2, 2, 7, 0, 2, 2,
+ 2, 2, 28, 2, 2, 2, 2, 28, 0, 2, 2, 2, 7, 0, 53, 0,
+ 33, 21, 20, 29, 29, 16, 46, 46, 23, 0, 21, 0, 0, 0, 0, 0,
+ 0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0,
+ 0, 2, 2, 54, 54, 55, 0, 0, 16, 2, 2, 2, 2, 28, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 7, 0, 56, 19, 57, 20, 20, 18, 18,
+ 44, 19, 9, 29, 9, 2, 2, 58, 59, 59, 59, 59, 59, 60, 59, 59,
+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61,
+ 0, 0, 0, 0, 62, 0, 0, 0, 0, 2, 2, 2, 2, 2, 63, 43,
+ 57, 64, 20, 20, 65, 66, 67, 68, 69, 2, 2, 2, 2, 2, 1, 0,
+ 3, 2, 2, 2, 21, 18, 2, 2, 70, 69, 71, 72, 63, 71, 27, 27,
+ 2, 50, 20, 51, 2, 2, 2, 2, 2, 2, 73, 74, 75, 27, 27, 76,
+ 77, 2, 2, 2, 2, 2, 27, 43, 0, 2, 57, 78, 0, 0, 0, 0,
+ 28, 2, 57, 45, 0, 0, 0, 0, 0, 2, 57, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 2, 7, 2, 7, 57, 0, 0, 0, 0, 0,
+ 0, 2, 2, 79, 43, 20, 57, 18, 46, 46, 46, 46, 13, 80, 81, 82,
+ 83, 84, 85, 0, 0, 0, 0, 86, 0, 7, 0, 0, 28, 0, 87, 79,
+ 88, 2, 2, 2, 2, 7, 0, 0, 0, 40, 40, 89, 90, 2, 2, 2,
+ 2, 2, 2, 2, 2, 11, 7, 0, 0, 91, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 7, 20, 78, 43, 20, 92, 59, 0,
+ 0, 93, 94, 93, 93, 95, 96, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0,
+ 0, 2, 2, 2, 2, 27, 0, 0, 0, 2, 2, 2, 2, 2, 7, 0,
+ 0, 2, 2, 2, 50, 97, 43, 0, 0, 2, 2, 98, 99, 100, 101, 59,
+ 61, 102, 14, 43, 20, 57, 19, 78, 46, 46, 74, 9, 9, 9, 103, 44,
+ 38, 9, 104, 72, 2, 2, 2, 2, 2, 2, 2, 105, 20, 18, 18, 20,
+ 46, 46, 20, 106, 2, 2, 2, 7, 0, 0, 0, 0, 0, 0, 107, 108,
+ 109, 109, 109, 0, 0, 0, 0, 0, 0, 104, 72, 2, 2, 2, 2, 2,
+ 2, 58, 59, 57, 23, 20, 110, 59, 2, 2, 2, 2, 105, 20, 21, 43,
+ 43, 100, 12, 0, 0, 0, 0, 0, 0, 2, 2, 59, 16, 46, 21, 111,
+ 100, 100, 100, 112, 113, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 28,
+ 2, 9, 44, 114, 114, 114, 9, 114, 114, 13, 114, 114, 114, 24, 0, 38,
+ 0, 0, 0, 115, 49, 9, 3, 0, 0, 0, 0, 0, 0, 0, 116, 0,
+ 0, 0, 0, 0, 0, 0, 4, 117, 118, 40, 40, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 118, 118, 119, 118, 118, 118, 118, 118, 118, 118,
+ 118, 0, 0, 120, 0, 0, 0, 0, 0, 0, 5, 120, 0, 0, 0, 0,
+ 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
+ 0, 2, 2, 2, 2, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0,
+ 121, 2, 51, 2, 106, 2, 8, 2, 2, 2, 63, 17, 14, 0, 0, 29,
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 27, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 122, 21, 21, 21, 21, 21, 21, 21, 123, 0, 0, 0, 0,
+ 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0,
+ 50, 2, 2, 2, 20, 20, 124, 114, 0, 2, 2, 2, 125, 18, 57, 18,
+ 111, 100, 126, 0, 0, 0, 0, 0, 0, 9, 127, 2, 2, 2, 2, 2,
+ 2, 2, 128, 21, 20, 18, 46, 129, 130, 131, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 50, 28, 2, 2, 2, 2, 2, 2, 2, 2, 8, 20, 57,
+ 97, 74, 132, 133, 134, 0, 0, 0, 0, 2, 135, 2, 2, 2, 2, 136,
+ 0, 28, 2, 40, 3, 0, 77, 13, 2, 51, 20, 137, 50, 51, 2, 2,
+ 103, 8, 7, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 138, 19,
+ 23, 0, 0, 139, 140, 0, 0, 0, 0, 2, 63, 43, 21, 78, 45, 141,
+ 0, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0,
+ 4, 118, 118, 118, 118, 119, 0, 0, 0, 2, 2, 2, 2, 2, 7, 2,
+ 2, 2, 7, 2, 28, 2, 2, 2, 2, 2, 28, 2, 2, 2, 28, 7,
+ 0, 125, 18, 25, 29, 0, 0, 142, 143, 2, 2, 28, 2, 28, 2, 2,
+ 2, 2, 2, 2, 0, 12, 35, 0, 144, 2, 2, 11, 35, 0, 28, 2,
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 2, 2,
+ 7, 2, 2, 9, 39, 0, 0, 0, 0, 2, 2, 2, 2, 2, 25, 36,
+ 0, 2, 2, 2, 114, 114, 114, 114, 114, 145, 2, 7, 0, 0, 0, 0,
+ 0, 2, 12, 12, 0, 0, 0, 0, 0, 7, 2, 2, 7, 2, 2, 2,
+ 2, 28, 2, 7, 0, 28, 2, 0, 0, 146, 147, 148, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 20, 20, 18, 18, 18, 20, 20, 131, 0, 0, 0,
+ 0, 0, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 2, 2, 2, 2,
+ 2, 51, 50, 51, 0, 0, 0, 0, 150, 9, 72, 2, 2, 2, 2, 2,
+ 2, 16, 17, 19, 14, 22, 35, 0, 0, 0, 29, 0, 0, 0, 0, 0,
+ 0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 125, 18, 20, 151,
+ 20, 19, 152, 153, 2, 2, 2, 2, 2, 0, 0, 63, 154, 0, 0, 0,
+ 0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20,
+ 20, 106, 155, 0, 0, 54, 156, 29, 157, 28, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 158, 42, 0, 0, 0,
+ 47, 125, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 7, 7, 2, 2,
+ 28, 2, 2, 2, 2, 2, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2,
+ 8, 16, 17, 19, 20, 159, 29, 0, 0, 9, 9, 28, 2, 2, 2, 7,
+ 28, 7, 2, 28, 2, 2, 56, 15, 21, 14, 21, 45, 30, 31, 30, 32,
+ 0, 0, 0, 0, 33, 0, 0, 0, 2, 2, 21, 0, 9, 9, 9, 44,
+ 0, 9, 9, 44, 0, 0, 0, 0, 0, 2, 2, 63, 23, 18, 18, 18,
+ 20, 21, 123, 13, 15, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0,
+ 160, 161, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23,
+ 157, 9, 162, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 63, 23, 18, 18, 0, 46, 46, 9, 163, 35, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 2, 18, 0, 21, 17, 18, 18, 19, 14, 80,
+ 163, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 164,
+ 23, 18, 20, 20, 162, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41,
+ 133, 21, 20, 18, 74, 19, 20, 0, 0, 2, 2, 2, 7, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 2, 16, 17, 18, 19, 20, 103, 163, 35, 0,
+ 0, 2, 2, 2, 7, 28, 0, 2, 2, 2, 2, 28, 7, 2, 2, 2,
+ 2, 21, 21, 16, 30, 31, 10, 165, 166, 167, 168, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 0, 2, 2, 2, 63, 23, 18, 18, 0, 20, 21,
+ 27, 106, 0, 31, 0, 0, 0, 0, 0, 50, 18, 20, 20, 20, 137, 2,
+ 2, 2, 169, 170, 9, 13, 171, 70, 172, 0, 0, 1, 144, 0, 0, 0,
+ 0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 173, 173,
+ 173, 173, 173, 173, 13, 174, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9,
+ 163, 0, 59, 59, 59, 59, 59, 59, 59, 64, 19, 80, 44, 0, 0, 0,
+ 0, 2, 2, 2, 7, 2, 28, 2, 2, 50, 20, 20, 29, 0, 36, 20,
+ 25, 9, 156, 175, 171, 0, 0, 0, 0, 2, 2, 2, 28, 7, 2, 2,
+ 2, 2, 2, 2, 2, 2, 21, 21, 45, 20, 33, 80, 66, 0, 0, 0,
+ 0, 2, 176, 64, 45, 0, 0, 0, 0, 9, 177, 2, 2, 2, 2, 2,
+ 2, 2, 2, 21, 20, 18, 29, 0, 46, 14, 140, 0, 0, 0, 0, 0,
+ 0, 178, 178, 178, 106, 179, 178, 0, 0, 145, 2, 2, 180, 114, 114, 114,
+ 114, 114, 114, 114, 0, 0, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 7, 0, 56, 181, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,
+ 38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56,
+ 35, 0, 4, 118, 118, 118, 119, 0, 0, 9, 9, 9, 47, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ 44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 2, 2, 2, 2, 20,
+ 20, 2, 2, 42, 42, 42, 90, 0, 0, O, O, O, GB, B, B, GB,
+ O, O, WJ,FMPst,FMPst, O, CGJ, B, O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,
+ CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw,
+ VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre, VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,
+ VMPst, O, B, VBlw, O, O, VPre, VPre, O, VPre, H, O, VPst,FMAbv, O,CMBlw,
+ O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst,
+ VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv, B, O, CS, CS,VMPst, B, VAbv, VAbv,
+ B, R, O, HVM, O, O,FMBlw, O,CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB,
+ SUB, O, SUB, SUB, O,FMBlw, O, B, VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv,
+ MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,
+ VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ, CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,
+ VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B, CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB,
+ B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw,
+ SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,
+ SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,
+ CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H,
+ VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H,
+ O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,
+ VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst,
+ CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R,
+ R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst,
+ H,VMPst, VAbv,VMAbv, VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R,
+ MBlw, MBlw, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, R,VMPst, H, H, B,
+ H, B,VMBlw, O, VBlw,
+};
+static const uint16_t
+hb_use_u16[784] =
+{
+ 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 11,
+ 0, 0, 0, 0, 9, 12, 0, 0, 13, 9, 9, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 17, 25, 26, 20, 21, 27, 28, 29, 30, 31,
+ 32, 33, 21, 34, 35, 0, 17, 36, 37, 20, 21, 38, 23, 39, 17, 40,
+ 41, 42, 43, 44, 45, 46, 30, 0, 47, 48, 21, 49, 50, 51, 17, 0,
+ 52, 48, 21, 53, 50, 54, 17, 55, 56, 48, 9, 57, 58, 59, 17, 0,
+ 60, 61, 9, 62, 63, 64, 30, 65, 66, 67, 9, 68, 69, 9, 70, 71,
+ 72, 73, 74, 75, 76, 0, 0, 0, 9, 9, 77, 78, 79, 80, 81, 82,
+ 83, 84, 0, 0, 0, 0, 0, 0, 9, 85, 9, 86, 9, 87, 88, 89,
+ 9, 9, 9, 90, 91, 92, 2, 0, 93, 0, 9, 9, 9, 9, 9, 94,
+ 95, 9, 96, 0, 0, 0, 0, 0, 97, 98, 99,100, 30, 9,101,102,
+ 9, 9,103, 9,104,105, 0, 0, 9,106, 9, 9, 9,107,108,109,
+ 2, 2, 0, 0, 0, 0, 0, 0,110, 9, 9,111,112, 2,113,114,
+ 115, 9,116, 9, 9, 9,117,118, 9, 9,119,120,121, 0, 0, 0,
+ 0, 0, 0, 0, 0,122,123,124, 0, 0, 0, 0, 0, 0, 0,125,
+ 126,127,128, 0, 0, 0,129,130,131, 0, 0, 0, 0, 0, 0,132,
+ 0, 0, 0, 0,133, 0, 0, 0, 0, 0, 0, 9, 9, 9,134,135,
+ 136, 9,137, 0, 9, 9, 9,138,139, 9, 9,140,141, 2,142,143,
+ 9, 9,144, 9,145,146, 0, 0,147, 9, 9,148,149, 2,150, 98,
+ 9, 9,151,152,153, 2, 9,154, 9, 9, 9,155,156, 0,157,158,
+ 0, 0, 0, 0, 9, 9,159, 2,160, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,161, 0, 0, 0, 0, 0, 0, 0,162,
+ 0, 0, 0, 0, 0, 0, 0,163,163,164, 33,165, 0, 0, 0, 0,
+ 166,167, 9,168, 94, 0, 0, 0, 0, 0, 0, 0, 69, 9,169, 0,
+ 9,170,171, 0, 0, 0, 0, 0, 9, 9,172, 2, 0, 0, 0, 0,
+ 9, 9,173,170, 0, 0, 0, 0, 0, 0, 0, 9,174,175, 0, 9,
+ 176, 0, 0,177,178, 0, 0, 0,179, 9, 9,180,181,182,183,184,
+ 185, 9, 9,186,187, 0, 0, 0,188, 9,189,190,191, 9, 9,192,
+ 185, 9, 9,193,194,105,195,102, 9, 33,196,197,198, 0, 0, 0,
+ 199,200, 94, 9, 9,201,202, 2,203, 20, 21,204,205,206,207,208,
+ 9, 9, 9,209,210,211,212, 0,195, 9, 9,213,214, 2, 0, 0,
+ 9, 9,215,216,217,218, 0, 0, 9, 9, 9,219,220, 2, 0, 0,
+ 9, 9,221,222, 2, 0, 0, 0, 9,223,224,103,225, 0, 0, 0,
+ 9, 9,226,227, 0, 0, 0, 0,228,229, 9,230,231, 2, 0, 0,
+ 0, 0,232, 9, 9,233,234, 0,235, 9, 9,236,237,238, 9, 9,
+ 239,240, 0, 0, 0, 0, 0, 0, 21, 9,215,241, 7, 9, 70, 18,
+ 9,242, 73,243, 0, 0, 0, 0,244, 9, 9,245,246, 2,247, 9,
+ 248,249, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,250,
+ 251, 48, 9,252,253, 2, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9,254,255,256, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 9, 9, 9,257, 0, 0, 0, 0, 9, 9, 9, 9,258,259,260,260,
+ 261,262, 0, 0, 0, 0,263, 0, 9, 9, 9, 9, 9,264, 0, 0,
+ 9, 9, 9, 9, 9, 9,105, 70, 94,265, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,266, 9, 9, 70,267,268, 0, 0, 0,
+ 0, 9,269, 0, 9, 9,270, 2, 0, 0, 0, 0, 0, 9,271, 2,
+ 9, 9, 9, 9,272, 2, 0, 0,129,129,129,129,129,129,129,129,
+ 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,129,
+};
+
+static inline unsigned
+hb_use_b4 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline uint_fast8_t
+hb_use_get_category (unsigned u)
+{
+ return u<921600u?hb_use_u8[2777+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+}
+
+
+#else
+
+static const uint8_t
+hb_use_u8[3413] =
+{
+ 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 14, 0, 1, 1, 2, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 1,
+ 11, 12, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 17, 18, 19, 1,
+ 1, 20, 1, 1, 1, 1, 21, 1, 1, 1, 1, 1, 1, 1, 22, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 24, 25, 26, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27,
+ 28, 1, 1, 1, 1, 1, 29, 1, 1, 1, 1, 30, 31, 1, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 1, 46, 47, 48,
+ 49, 50, 50, 50, 50, 51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 52, 53, 1, 1, 1,
+ 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 50, 55, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 56, 1, 1,
+ 1, 1, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 58, 59, 1, 60, 1, 1, 1, 1, 61, 1, 1, 1, 1, 1,
+ 1, 62, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 8, 0, 0, 0, 0,
+ 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 36, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 0, 55, 56, 57, 58, 59, 0, 0, 0, 60, 61, 62, 63, 55, 64, 65,
+ 66, 67, 55, 55, 68, 69, 70, 0, 0, 71, 72, 73, 74, 55, 75, 76,
+ 0, 77, 55, 78, 79, 80, 0, 0, 0, 81, 82, 83, 84, 85, 86, 55,
+ 87, 55, 88, 89, 0, 0, 0, 90, 91, 0, 0, 0, 0, 0, 0, 0,
+ 92, 93, 94, 0, 95, 96, 0, 0, 97, 0, 0, 0, 0, 0, 0, 98,
+ 0, 0, 99, 55, 100, 0, 0, 0, 0, 101, 102, 55, 103, 104, 105, 106,
+ 107, 55, 108, 109, 0, 110, 111, 112, 113, 55, 114, 115, 116, 55, 117, 118,
+ 119, 0, 0, 0, 0, 0, 0, 55, 120, 121, 0, 0, 0, 0, 0, 0,
+ 122, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 124, 125, 126, 0,
+ 0, 127, 128, 129, 0, 0, 0, 50, 130, 0, 0, 0, 0, 131, 132, 0,
+ 0, 55, 133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 134, 0,
+ 0, 0, 99, 135, 99, 136, 137, 138, 0, 139, 140, 141, 142, 143, 144, 145,
+ 0, 146, 147, 148, 149, 143, 150, 151, 152, 153, 154, 155, 0, 156, 157, 158,
+ 159, 160, 161, 162, 163, 0, 0, 0, 0, 55, 164, 165, 166, 167, 168, 169,
+ 0, 0, 0, 0, 0, 55, 170, 171, 0, 55, 172, 173, 0, 55, 174, 66,
+ 0, 175, 176, 177, 0, 0, 0, 0, 0, 55, 178, 0, 0, 0, 0, 0,
+ 0, 179, 180, 181, 0, 0, 182, 183, 184, 185, 186, 187, 55, 188, 0, 0,
+ 0, 189, 190, 191, 192, 193, 194, 0, 0, 195, 196, 197, 198, 199, 66, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 200, 201, 202, 203, 0, 0, 0, 0,
+ 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 204, 205, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 66, 0, 55, 206, 0, 0, 0, 0, 0,
+ 0, 55, 55, 207, 208, 209, 0, 0, 210, 55, 55, 55, 55, 55, 55, 211,
+ 0, 55, 55, 55, 212, 213, 0, 0, 0, 0, 0, 0, 214, 0, 0, 0,
+ 0, 55, 215, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 217, 55,
+ 218, 0, 0, 0, 0, 0, 0, 99, 219, 55, 55, 220, 0, 0, 0, 0,
+ 0, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 222, 222,
+ 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4,
+ 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 8, 9, 9, 9, 9, 0, 0, 0, 7, 10,
+ 0, 2, 2, 2, 2, 11, 12, 0, 0, 9, 13, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 14, 15, 16, 17, 18, 19, 20, 14, 21, 22,
+ 23, 10, 24, 25, 18, 2, 2, 2, 2, 2, 18, 0, 2, 2, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 26, 27, 28, 2, 2, 2, 7,
+ 28, 7, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, 2,
+ 2, 7, 7, 0, 2, 2, 0, 15, 16, 17, 18, 29, 30, 31, 30, 32,
+ 0, 0, 0, 0, 33, 0, 0, 2, 28, 2, 0, 0, 0, 0, 0, 7,
+ 34, 10, 13, 28, 2, 2, 7, 0, 28, 7, 2, 28, 7, 2, 0, 35,
+ 16, 17, 29, 0, 25, 36, 25, 37, 0, 38, 0, 0, 0, 28, 2, 7,
+ 7, 0, 0, 0, 2, 2, 2, 2, 2, 39, 40, 41, 0, 0, 0, 0,
+ 0, 10, 13, 28, 2, 2, 2, 2, 28, 2, 28, 2, 2, 2, 2, 2,
+ 2, 7, 2, 28, 2, 2, 0, 15, 16, 17, 18, 19, 25, 20, 33, 22,
+ 0, 0, 0, 0, 0, 28, 39, 39, 42, 10, 27, 28, 2, 2, 2, 7,
+ 28, 7, 2, 28, 2, 2, 0, 15, 43, 0, 0, 25, 20, 0, 0, 2,
+ 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 44, 28, 2, 2, 7, 0,
+ 2, 7, 2, 2, 0, 28, 7, 7, 2, 0, 28, 7, 0, 2, 7, 0,
+ 2, 2, 2, 2, 2, 2, 0, 0, 21, 14, 45, 0, 46, 31, 46, 32,
+ 0, 0, 0, 0, 33, 0, 0, 0, 0, 13, 27, 47, 2, 2, 2, 7,
+ 2, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 15,
+ 20, 14, 21, 45, 20, 36, 20, 37, 0, 0, 0, 25, 29, 2, 7, 0,
+ 0, 8, 27, 28, 2, 2, 2, 7, 2, 2, 2, 28, 2, 2, 0, 15,
+ 43, 0, 0, 33, 45, 0, 0, 0, 7, 48, 49, 0, 0, 0, 0, 0,
+ 0, 9, 27, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 50, 51,
+ 21, 21, 17, 29, 46, 31, 46, 32, 52, 0, 0, 0, 33, 0, 0, 0,
+ 28, 10, 27, 28, 2, 2, 2, 2, 2, 2, 2, 2, 7, 0, 2, 2,
+ 2, 2, 28, 2, 2, 2, 2, 28, 0, 2, 2, 2, 7, 0, 53, 0,
+ 33, 21, 20, 29, 29, 16, 46, 46, 23, 0, 21, 0, 0, 0, 0, 0,
+ 0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0,
+ 0, 2, 2, 54, 54, 55, 0, 0, 16, 2, 2, 2, 2, 28, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 7, 0, 56, 19, 57, 20, 20, 18, 18,
+ 44, 19, 9, 29, 9, 2, 2, 58, 59, 59, 59, 59, 59, 60, 59, 59,
+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61,
+ 0, 0, 0, 0, 62, 0, 0, 0, 0, 2, 2, 2, 2, 2, 63, 43,
+ 57, 64, 20, 20, 65, 66, 67, 68, 69, 2, 2, 2, 2, 2, 1, 0,
+ 3, 2, 2, 2, 21, 18, 2, 2, 70, 69, 71, 72, 63, 71, 27, 27,
+ 2, 50, 20, 51, 2, 2, 2, 2, 2, 2, 73, 74, 75, 27, 27, 76,
+ 77, 2, 2, 2, 2, 2, 27, 43, 0, 2, 57, 78, 0, 0, 0, 0,
+ 28, 2, 57, 45, 0, 0, 0, 0, 0, 2, 57, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 2, 7, 2, 7, 57, 0, 0, 0, 0, 0,
+ 0, 2, 2, 79, 43, 20, 57, 18, 46, 46, 46, 46, 13, 80, 81, 82,
+ 83, 84, 85, 0, 0, 0, 0, 86, 0, 7, 0, 0, 28, 0, 87, 79,
+ 88, 2, 2, 2, 2, 7, 0, 0, 0, 40, 40, 89, 90, 2, 2, 2,
+ 2, 2, 2, 2, 2, 11, 7, 0, 0, 91, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 7, 20, 78, 43, 20, 92, 59, 0,
+ 0, 93, 94, 93, 93, 95, 96, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0,
+ 0, 2, 2, 2, 2, 27, 0, 0, 0, 2, 2, 2, 2, 2, 7, 0,
+ 0, 2, 2, 2, 50, 97, 43, 0, 0, 2, 2, 98, 99, 100, 101, 59,
+ 61, 102, 14, 43, 20, 57, 19, 78, 46, 46, 74, 9, 9, 9, 103, 44,
+ 38, 9, 104, 72, 2, 2, 2, 2, 2, 2, 2, 105, 20, 18, 18, 20,
+ 46, 46, 20, 106, 2, 2, 2, 7, 0, 0, 0, 0, 0, 0, 107, 108,
+ 109, 109, 109, 0, 0, 0, 0, 0, 0, 104, 72, 2, 2, 2, 2, 2,
+ 2, 58, 59, 57, 23, 20, 110, 59, 2, 2, 2, 2, 105, 20, 21, 43,
+ 43, 100, 12, 0, 0, 0, 0, 0, 0, 2, 2, 59, 16, 46, 21, 111,
+ 100, 100, 100, 112, 113, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 28,
+ 2, 9, 44, 114, 114, 114, 9, 114, 114, 13, 114, 114, 114, 24, 0, 38,
+ 0, 0, 0, 115, 49, 9, 3, 0, 0, 0, 0, 0, 0, 0, 116, 0,
+ 0, 0, 0, 0, 0, 0, 4, 117, 118, 40, 40, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 118, 118, 119, 118, 118, 118, 118, 118, 118, 118,
+ 118, 0, 0, 120, 0, 0, 0, 0, 0, 0, 5, 120, 0, 0, 0, 0,
+ 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
+ 0, 2, 2, 2, 2, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0,
+ 121, 2, 51, 2, 106, 2, 8, 2, 2, 2, 63, 17, 14, 0, 0, 29,
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 27, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 122, 21, 21, 21, 21, 21, 21, 21, 123, 0, 0, 0, 0,
+ 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0,
+ 50, 2, 2, 2, 20, 20, 124, 114, 0, 2, 2, 2, 125, 18, 57, 18,
+ 111, 100, 126, 0, 0, 0, 0, 0, 0, 9, 127, 2, 2, 2, 2, 2,
+ 2, 2, 128, 21, 20, 18, 46, 129, 130, 131, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 50, 28, 2, 2, 2, 2, 2, 2, 2, 2, 8, 20, 57,
+ 97, 74, 132, 133, 134, 0, 0, 0, 0, 2, 135, 2, 2, 2, 2, 136,
+ 0, 28, 2, 40, 3, 0, 77, 13, 2, 51, 20, 137, 50, 51, 2, 2,
+ 103, 8, 7, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 138, 19,
+ 23, 0, 0, 139, 140, 0, 0, 0, 0, 2, 63, 43, 21, 78, 45, 141,
+ 0, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0,
+ 4, 118, 118, 118, 118, 119, 0, 0, 0, 2, 2, 2, 2, 2, 7, 2,
+ 2, 2, 7, 2, 28, 2, 2, 2, 2, 2, 28, 2, 2, 2, 28, 7,
+ 0, 125, 18, 25, 29, 0, 0, 142, 143, 2, 2, 28, 2, 28, 2, 2,
+ 2, 2, 2, 2, 0, 12, 35, 0, 144, 2, 2, 11, 35, 0, 28, 2,
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 2, 2,
+ 7, 2, 2, 9, 39, 0, 0, 0, 0, 2, 2, 2, 2, 2, 25, 36,
+ 0, 2, 2, 2, 114, 114, 114, 114, 114, 145, 2, 7, 0, 0, 0, 0,
+ 0, 2, 12, 12, 0, 0, 0, 0, 0, 7, 2, 2, 7, 2, 2, 2,
+ 2, 28, 2, 7, 0, 28, 2, 0, 0, 146, 147, 148, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 20, 20, 18, 18, 18, 20, 20, 131, 0, 0, 0,
+ 0, 0, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 2, 2, 2, 2,
+ 2, 51, 50, 51, 0, 0, 0, 0, 150, 9, 72, 2, 2, 2, 2, 2,
+ 2, 16, 17, 19, 14, 22, 35, 0, 0, 0, 29, 0, 0, 0, 0, 0,
+ 0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 125, 18, 20, 151,
+ 20, 19, 152, 153, 2, 2, 2, 2, 2, 0, 0, 63, 154, 0, 0, 0,
+ 0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20,
+ 20, 106, 155, 0, 0, 54, 156, 29, 157, 28, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 158, 42, 0, 0, 0,
+ 47, 125, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 7, 7, 2, 2,
+ 28, 2, 2, 2, 2, 2, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2,
+ 8, 16, 17, 19, 20, 159, 29, 0, 0, 9, 9, 28, 2, 2, 2, 7,
+ 28, 7, 2, 28, 2, 2, 56, 15, 21, 14, 21, 45, 30, 31, 30, 32,
+ 0, 0, 0, 0, 33, 0, 0, 0, 2, 2, 21, 0, 9, 9, 9, 44,
+ 0, 9, 9, 44, 0, 0, 0, 0, 0, 2, 2, 63, 23, 18, 18, 18,
+ 20, 21, 123, 13, 15, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0,
+ 160, 161, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23,
+ 157, 9, 162, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 63, 23, 18, 18, 0, 46, 46, 9, 163, 35, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 2, 18, 0, 21, 17, 18, 18, 19, 14, 80,
+ 163, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 164,
+ 23, 18, 20, 20, 162, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41,
+ 133, 21, 20, 18, 74, 19, 20, 0, 0, 2, 2, 2, 7, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 2, 16, 17, 18, 19, 20, 103, 163, 35, 0,
+ 0, 2, 2, 2, 7, 28, 0, 2, 2, 2, 2, 28, 7, 2, 2, 2,
+ 2, 21, 21, 16, 30, 31, 10, 165, 166, 167, 168, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 0, 2, 2, 2, 63, 23, 18, 18, 0, 20, 21,
+ 27, 106, 0, 31, 0, 0, 0, 0, 0, 50, 18, 20, 20, 20, 137, 2,
+ 2, 2, 169, 170, 9, 13, 171, 70, 172, 0, 0, 1, 144, 0, 0, 0,
+ 0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 173, 173,
+ 173, 173, 173, 173, 13, 174, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9,
+ 163, 0, 59, 59, 59, 59, 59, 59, 59, 64, 19, 80, 44, 0, 0, 0,
+ 0, 2, 2, 2, 7, 2, 28, 2, 2, 50, 20, 20, 29, 0, 36, 20,
+ 25, 9, 156, 175, 171, 0, 0, 0, 0, 2, 2, 2, 28, 7, 2, 2,
+ 2, 2, 2, 2, 2, 2, 21, 21, 45, 20, 33, 80, 66, 0, 0, 0,
+ 0, 2, 176, 64, 45, 0, 0, 0, 0, 9, 177, 2, 2, 2, 2, 2,
+ 2, 2, 2, 21, 20, 18, 29, 0, 46, 14, 140, 0, 0, 0, 0, 0,
+ 0, 178, 178, 178, 106, 179, 178, 0, 0, 145, 2, 2, 180, 114, 114, 114,
+ 114, 114, 114, 114, 0, 0, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 7, 0, 56, 181, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,
+ 38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56,
+ 35, 0, 4, 118, 118, 118, 119, 0, 0, 9, 9, 9, 47, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ 44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 2, 2, 2, 2, 20,
+ 20, 2, 2, 42, 42, 42, 90, 0, 0, O, O, O, GB, B, B, GB,
+ O, O, WJ,FMPst,FMPst, O, CGJ, B, O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,
+ CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw,
+ VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre, VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,
+ VMPst, O, B, VBlw, O, O, VPre, VPre, O, VPre, H, O, VPst,FMAbv, O,CMBlw,
+ O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst,
+ VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv, B, O, CS, CS,VMPst, B, VAbv, VAbv,
+ B, R, O, HVM, O, O,FMBlw, O,CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB,
+ SUB, O, SUB, SUB, O,FMBlw, O, B, VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv,
+ MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,
+ VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ, CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,
+ VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B, CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB,
+ B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw,
+ SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,
+ SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,
+ CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H,
+ VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H,
+ O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,
+ VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst,
+ CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R,
+ R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst,
+ H,VMPst, VAbv,VMAbv, VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R,
+ MBlw, MBlw, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, R,VMPst, H, H, B,
+ H, B,VMBlw, O, VBlw,
+};
+static const uint16_t
+hb_use_u16[448] =
+{
+ 0, 0, 1, 2, 3, 4, 0, 5, 6, 0, 7, 0, 8, 9, 10, 11,
+ 9, 12, 13, 9, 9, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 17, 25, 26, 20, 21, 27, 28, 29, 30, 31, 32, 33, 21, 34, 35, 0,
+ 17, 36, 37, 20, 21, 38, 23, 39, 17, 40, 41, 42, 43, 44, 45, 46,
+ 30, 0, 47, 48, 21, 49, 50, 51, 17, 0, 52, 48, 21, 53, 50, 54,
+ 17, 55, 56, 48, 9, 57, 58, 59, 60, 61, 9, 62, 63, 64, 30, 65,
+ 66, 67, 9, 68, 69, 9, 70, 71, 72, 73, 74, 75, 76, 0, 9, 9,
+ 77, 78, 79, 80, 81, 82, 83, 84, 9, 85, 9, 86, 9, 87, 88, 89,
+ 9, 90, 91, 92, 2, 0, 93, 0, 9, 94, 95, 9, 96, 0, 97, 98,
+ 99,100, 30, 9,101,102,103, 9,104,105, 9,106, 9,107,108,109,
+ 2, 2,110, 9, 9,111,112, 2,113,114,115, 9,116, 9,117,118,
+ 119,120,121, 0, 0,122,123,124, 0,125,126,127,128, 0,129,130,
+ 131, 0, 0,132,133, 0, 0, 9,134,135,136, 9,137, 0, 9,138,
+ 139, 9, 9,140,141, 2,142,143,144, 9,145,146,147, 9, 9,148,
+ 149, 2,150, 98,151,152,153, 2, 9,154, 9,155,156, 0,157,158,
+ 159, 2,160, 0, 0,161, 0,162, 0,163,163,164, 33,165,166,167,
+ 9,168, 94, 0,169, 0, 9,170,171, 0,172, 2,173,170,174,175,
+ 176, 0, 0,177,178, 0,179, 9, 9,180,181,182,183,184,185, 9,
+ 9,186,187, 0,188, 9,189,190,191, 9, 9,192, 9,193,194,105,
+ 195,102, 9, 33,196,197,198, 0,199,200, 94, 9, 9,201,202, 2,
+ 203, 20, 21,204,205,206,207,208, 9,209,210,211,212, 0,195, 9,
+ 9,213,214, 2,215,216,217,218, 9,219,220, 2,221,222, 9,223,
+ 224,103,225, 0,226,227,228,229, 9,230,231, 2,232, 9, 9,233,
+ 234, 0,235, 9, 9,236,237,238,239,240, 21, 9,215,241, 7, 9,
+ 70, 18, 9,242, 73,243,244, 9, 9,245,246, 2,247, 9,248,249,
+ 9,250,251, 48, 9,252,253, 2, 9,254,255,256, 9,257,258,259,
+ 260,260,261,262,263, 0, 9,264,105, 70, 94,265, 0,266, 70,267,
+ 268, 0,269, 0,270, 2,271, 2,272, 2,129,129,160,160,160,129,
+};
+
+static inline unsigned
+hb_use_b4 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline uint_fast8_t
+hb_use_get_category (unsigned u)
+{
+ return u<921600u?hb_use_u8[3049+(((hb_use_u8[865+(((hb_use_u16[((hb_use_u8[353+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+}
+
+#endif
+
+#undef B
+#undef CGJ
+#undef CS
+#undef G
+#undef GB
+#undef H
+#undef HN
+#undef HVM
+#undef IS
+#undef J
+#undef N
+#undef O
+#undef R
+#undef SB
+#undef SE
+#undef SUB
+#undef Sk
+#undef WJ
+#undef ZWNJ
+#undef CMAbv
+#undef CMBlw
+#undef FAbv
+#undef FBlw
+#undef FPst
+#undef FMAbv
+#undef FMBlw
+#undef FMPst
+#undef MAbv
+#undef MBlw
+#undef MPst
+#undef MPre
+#undef SMAbv
+#undef SMBlw
+#undef VAbv
+#undef VBlw
+#undef VPst
+#undef VPre
+#undef VMAbv
+#undef VMBlw
+#undef VMPst
+#undef VMPre
+
+
+#endif /* HB_OT_SHAPER_USE_TABLE_HH */
+/* == End of generated table == */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use.cc
index 1d13c8a126..342aba1235 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use.cc
@@ -30,11 +30,11 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-use-machine.hh"
-#include "hb-ot-shape-complex-use-table.hh"
-#include "hb-ot-shape-complex-arabic.hh"
-#include "hb-ot-shape-complex-arabic-joining-list.hh"
-#include "hb-ot-shape-complex-vowel-constraints.hh"
+#include "hb-ot-shaper-use-machine.hh"
+#include "hb-ot-shaper-use-table.hh"
+#include "hb-ot-shaper-arabic.hh"
+#include "hb-ot-shaper-arabic-joining-list.hh"
+#include "hb-ot-shaper-vowel-constraints.hh"
/*
@@ -89,19 +89,19 @@ use_other_features[] =
HB_TAG('p','s','t','s'),
};
-static void
+static bool
setup_syllables_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
record_rphf_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
record_pref_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
-static void
+static bool
reorder_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
@@ -133,6 +133,7 @@ collect_features_use (hb_ot_shape_planner_t *plan)
map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (reorder_use);
+ map->add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
/* "Topographical features" */
for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)
@@ -205,7 +206,7 @@ setup_masks_use (const hb_ot_shape_plan_t *plan,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- info[i].use_category() = hb_use_get_category (info[i]);
+ info[i].use_category() = hb_use_get_category (info[i].codepoint);
}
static void
@@ -292,19 +293,21 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
}
}
-static void
+static bool
setup_syllables_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
find_syllables_use (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
setup_rphf_mask (plan, buffer);
setup_topographical_masks (plan, buffer);
+ return false;
}
-static void
+static bool
record_rphf_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -312,7 +315,7 @@ record_rphf_use (const hb_ot_shape_plan_t *plan,
const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
hb_mask_t mask = use_plan->rphf_mask;
- if (!mask) return;
+ if (!mask) return false;
hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end)
@@ -325,9 +328,10 @@ record_rphf_use (const hb_ot_shape_plan_t *plan,
break;
}
}
+ return false;
}
-static void
+static bool
record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
@@ -344,12 +348,13 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
break;
}
}
+ return false;
}
static inline bool
is_halant_use (const hb_glyph_info_t &info)
{
- return (info.use_category() == USE(H) || info.use_category() == USE(IS)) &&
+ return (info.use_category() == USE(H) || info.use_category() == USE(HVM) || info.use_category() == USE(IS)) &&
!_hb_glyph_info_ligated (&info);
}
@@ -436,17 +441,19 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
}
}
-static void
+static bool
reorder_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
+ bool ret = false;
if (buffer->message (font, "start reordering USE"))
{
- hb_syllabic_insert_dotted_circles (font, buffer,
- use_broken_cluster,
- USE(B),
- USE(R));
+ if (hb_syllabic_insert_dotted_circles (font, buffer,
+ use_broken_cluster,
+ USE(B),
+ USE(R)))
+ ret = true;
foreach_syllable (buffer, start, end)
reorder_syllable_use (buffer, start, end);
@@ -455,6 +462,8 @@ reorder_use (const hb_ot_shape_plan_t *plan,
}
HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
+
+ return ret;
}
@@ -480,7 +489,7 @@ compose_use (const hb_ot_shape_normalize_context_t *c,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
+const hb_ot_shaper_t _hb_ot_shaper_use =
{
collect_features_use,
nullptr, /* override_features */
@@ -488,12 +497,12 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
data_destroy_use,
preprocess_text_use,
nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
nullptr, /* decompose */
compose_use,
setup_masks_use,
- HB_TAG_NONE, /* gpos_tag */
nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
false, /* fallback_position */
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-vowel-constraints.cc
index d2cca105a4..e76b554b00 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-vowel-constraints.cc
@@ -10,15 +10,15 @@
* # Date: 2015-03-12, 21:17:00 GMT [AG]
* # Date: 2019-11-08, 23:22:00 GMT [AG]
*
- * # Scripts-14.0.0.txt
- * # Date: 2021-07-10, 00:35:31 GMT
+ * # Scripts-15.0.0.txt
+ * # Date: 2022-04-26, 23:15:02 GMT
*/
#include "hb.hh"
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-vowel-constraints.hh"
+#include "hb-ot-shaper-vowel-constraints.hh"
static void
_output_dotted_circle (hb_buffer_t *buffer)
@@ -39,7 +39,7 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
hb_font_t *font HB_UNUSED)
{
-#ifdef HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
+#ifdef HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS
return;
#endif
if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)
@@ -342,6 +342,40 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
break;
+ case HB_SCRIPT_KHOJKI:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x11200u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x1122Cu: case 0x11231u: case 0x11233u:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x11206u:
+ matched = 0x1122Cu == buffer->cur (1).codepoint;
+ break;
+ case 0x1122Cu:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x11230u: case 0x11231u:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x11240u:
+ matched = 0x1122Eu == buffer->cur (1).codepoint;
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
case HB_SCRIPT_KHUDAWADI:
for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
{
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-vowel-constraints.hh
index d9082d4ead..5a7ee1b0f2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-vowel-constraints.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-vowel-constraints.hh
@@ -24,16 +24,16 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
-#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
+#ifndef HB_OT_SHAPER_VOWEL_CONSTRAINTS_HH
+#define HB_OT_SHAPER_VOWEL_CONSTRAINTS_HH
#include "hb.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
HB_INTERNAL void
_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
hb_font_t *font);
-#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */
+#endif /* HB_OT_SHAPER_VOWEL_CONSTRAINTS_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper.hh
index 8012a9ae94..0207b2bbe3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper.hh
@@ -24,8 +24,8 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_HH
-#define HB_OT_SHAPE_COMPLEX_HH
+#ifndef HB_OT_SHAPER_HH
+#define HB_OT_SHAPER_HH
#include "hb.hh"
@@ -34,12 +34,12 @@
#include "hb-ot-shape-normalize.hh"
-/* buffer var allocations, used by complex shapers */
-#define complex_var_u8_category() var2.u8[2]
-#define complex_var_u8_auxiliary() var2.u8[3]
+/* buffer var allocations, used by all OT shapers */
+#define ot_shaper_var_u8_category() var2.u8[2]
+#define ot_shaper_var_u8_auxiliary() var2.u8[3]
-#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
+#define HB_OT_SHAPE_MAX_COMBINING_MARKS 32
enum hb_ot_shape_zero_width_marks_type_t {
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
@@ -49,22 +49,22 @@ enum hb_ot_shape_zero_width_marks_type_t {
/* Master OT shaper list */
-#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
- HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
- HB_COMPLEX_SHAPER_IMPLEMENT (default) \
- HB_COMPLEX_SHAPER_IMPLEMENT (dumber) \
- HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
- HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
- HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
- HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
- HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
- HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_zawgyi) \
- HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
- HB_COMPLEX_SHAPER_IMPLEMENT (use) \
+#define HB_OT_SHAPERS_IMPLEMENT_SHAPERS \
+ HB_OT_SHAPER_IMPLEMENT (arabic) \
+ HB_OT_SHAPER_IMPLEMENT (default) \
+ HB_OT_SHAPER_IMPLEMENT (dumber) \
+ HB_OT_SHAPER_IMPLEMENT (hangul) \
+ HB_OT_SHAPER_IMPLEMENT (hebrew) \
+ HB_OT_SHAPER_IMPLEMENT (indic) \
+ HB_OT_SHAPER_IMPLEMENT (khmer) \
+ HB_OT_SHAPER_IMPLEMENT (myanmar) \
+ HB_OT_SHAPER_IMPLEMENT (myanmar_zawgyi) \
+ HB_OT_SHAPER_IMPLEMENT (thai) \
+ HB_OT_SHAPER_IMPLEMENT (use) \
/* ^--- Add new shapers here; keep sorted. */
-struct hb_ot_complex_shaper_t
+struct hb_ot_shaper_t
{
/* collect_features()
* Called during shape_plan().
@@ -117,8 +117,6 @@ struct hb_ot_complex_shaper_t
hb_font_t *font);
- hb_ot_shape_normalization_mode_t normalization_preference;
-
/* decompose()
* Called during shape()'s normalization.
* May be NULL.
@@ -147,12 +145,6 @@ struct hb_ot_complex_shaper_t
hb_buffer_t *buffer,
hb_font_t *font);
- /* gpos_tag()
- * If not HB_TAG_NONE, then must match found GPOS script tag for
- * GPOS to be applied. Otherwise, fallback positioning will be used.
- */
- hb_tag_t gpos_tag;
-
/* reorder_marks()
* Called during shape().
* Shapers can use to modify ordering of combining marks.
@@ -163,23 +155,31 @@ struct hb_ot_complex_shaper_t
unsigned int start,
unsigned int end);
+ /* gpos_tag()
+ * If not HB_TAG_NONE, then must match found GPOS script tag for
+ * GPOS to be applied. Otherwise, fallback positioning will be used.
+ */
+ hb_tag_t gpos_tag;
+
+ hb_ot_shape_normalization_mode_t normalization_preference;
+
hb_ot_shape_zero_width_marks_type_t zero_width_marks;
bool fallback_position;
};
-#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
-HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
-#undef HB_COMPLEX_SHAPER_IMPLEMENT
+#define HB_OT_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_shaper_t _hb_ot_shaper_##name;
+HB_OT_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_OT_SHAPER_IMPLEMENT
-static inline const hb_ot_complex_shaper_t *
-hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
+static inline const hb_ot_shaper_t *
+hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
{
switch ((hb_tag_t) planner->props.script)
{
default:
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
/* Unicode-1.1 additions */
@@ -195,28 +195,28 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
planner->props.script == HB_SCRIPT_ARABIC) &&
HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
- return &_hb_ot_complex_shaper_arabic;
+ return &_hb_ot_shaper_arabic;
else
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
/* Unicode-1.1 additions */
case HB_SCRIPT_THAI:
case HB_SCRIPT_LAO:
- return &_hb_ot_complex_shaper_thai;
+ return &_hb_ot_shaper_thai;
/* Unicode-1.1 additions */
case HB_SCRIPT_HANGUL:
- return &_hb_ot_complex_shaper_hangul;
+ return &_hb_ot_shaper_hangul;
/* Unicode-1.1 additions */
case HB_SCRIPT_HEBREW:
- return &_hb_ot_complex_shaper_hebrew;
+ return &_hb_ot_shaper_hebrew;
/* Unicode-1.1 additions */
@@ -230,9 +230,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_TAMIL:
case HB_SCRIPT_TELUGU:
- /* Unicode-3.0 additions */
- case HB_SCRIPT_SINHALA:
-
/* If the designer designed the font for the 'DFLT' script,
* (or we ended up arbitrarily pick 'latn'), use the default shaper.
* Otherwise, use the specific shaper.
@@ -240,14 +237,14 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
* If it's indy3 tag, send to USE. */
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
else if ((planner->map.chosen_script[0] & 0x000000FF) == '3')
- return &_hb_ot_complex_shaper_use;
+ return &_hb_ot_shaper_use;
else
- return &_hb_ot_complex_shaper_indic;
+ return &_hb_ot_shaper_indic;
case HB_SCRIPT_KHMER:
- return &_hb_ot_complex_shaper_khmer;
+ return &_hb_ot_shaper_khmer;
case HB_SCRIPT_MYANMAR:
/* If the designer designed the font for the 'DFLT' script,
@@ -260,16 +257,18 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
else
- return &_hb_ot_complex_shaper_myanmar;
+ return &_hb_ot_shaper_myanmar;
+#ifndef HB_NO_OT_SHAPER_MYANMAR_ZAWGYI
#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g'))
case HB_SCRIPT_MYANMAR_ZAWGYI:
/* https://github.com/harfbuzz/harfbuzz/issues/1162 */
- return &_hb_ot_complex_shaper_myanmar_zawgyi;
+ return &_hb_ot_shaper_myanmar_zawgyi;
+#endif
/* Unicode-2.0 additions */
@@ -277,7 +276,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-3.0 additions */
case HB_SCRIPT_MONGOLIAN:
- //case HB_SCRIPT_SINHALA:
+ case HB_SCRIPT_SINHALA:
/* Unicode-3.2 additions */
case HB_SCRIPT_BUHID:
@@ -383,6 +382,10 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_TOTO:
case HB_SCRIPT_VITHKUQI:
+ /* Unicode-15.0 additions */
+ case HB_SCRIPT_KAWI:
+ case HB_SCRIPT_NAG_MUNDARI:
+
/* If the designer designed the font for the 'DFLT' script,
* (or we ended up arbitrarily pick 'latn'), use the default shaper.
* Otherwise, use the specific shaper.
@@ -390,11 +393,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
* GSUB/GPOS needed, so there may be no scripts found! */
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
else
- return &_hb_ot_complex_shaper_use;
+ return &_hb_ot_shaper_use;
}
}
-#endif /* HB_OT_SHAPE_COMPLEX_HH */
+#endif /* HB_OT_SHAPER_HH */
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 41d1734b39..2006f677d1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-stat-table.hh
@@ -57,6 +57,31 @@ enum
// Reserved = 0xFFFC /* Reserved for future use — set to zero. */
};
+struct StatAxisRecord
+{
+ int cmp (hb_tag_t key) const { return tag.cmp (key); }
+
+ hb_ot_name_id_t get_name_id () const { return nameID; }
+
+ hb_tag_t get_axis_tag () const { return tag; }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (likely (c->check_struct (this)));
+ }
+
+ protected:
+ Tag tag; /* A tag identifying the axis of design variation. */
+ NameID nameID; /* The name ID for entries in the 'name' table that
+ * provide a display string for this axis. */
+ HBUINT16 ordering; /* A value that applications can use to determine
+ * primary sorting of face names, or for ordering
+ * of descriptors when composing family or face names. */
+ public:
+ DEFINE_SIZE_STATIC (8);
+};
+
struct AxisValueFormat1
{
unsigned int get_axis_index () const { return axisIndex; }
@@ -64,10 +89,41 @@ struct AxisValueFormat1
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+ hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ unsigned axis_idx = get_axis_index ();
+ return axis_records[axis_idx].get_axis_tag ();
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_tag_t axis_tag = get_axis_tag (axis_records);
+ float axis_value = get_value ();
+
+ if (!user_axes_location->has (axis_tag) ||
+ fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
+ return true;
+
+ return false;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
+
+ if (keep_axis_value (axis_records, user_axes_location))
+ return_trace (c->serializer->embed (this));
+
+ return_trace (false);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -80,7 +136,7 @@ struct AxisValueFormat1
NameID valueNameID; /* The name ID for entries in the 'name' table
* that provide a display string for this
* attribute value. */
- HBFixed value; /* A numeric value for this attribute value. */
+ F16DOT16 value; /* A numeric value for this attribute value. */
public:
DEFINE_SIZE_STATIC (12);
};
@@ -92,10 +148,41 @@ struct AxisValueFormat2
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+ hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ unsigned axis_idx = get_axis_index ();
+ return axis_records[axis_idx].get_axis_tag ();
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_tag_t axis_tag = get_axis_tag (axis_records);
+ float axis_value = get_value ();
+
+ if (!user_axes_location->has (axis_tag) ||
+ fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
+ return true;
+
+ return false;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
+
+ if (keep_axis_value (axis_records, user_axes_location))
+ return_trace (c->serializer->embed (this));
+
+ return_trace (false);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -108,10 +195,10 @@ struct AxisValueFormat2
NameID valueNameID; /* The name ID for entries in the 'name' table
* that provide a display string for this
* attribute value. */
- HBFixed nominalValue; /* A numeric value for this attribute value. */
- HBFixed rangeMinValue; /* The minimum value for a range associated
+ F16DOT16 nominalValue; /* A numeric value for this attribute value. */
+ F16DOT16 rangeMinValue; /* The minimum value for a range associated
* with the specified name ID. */
- HBFixed rangeMaxValue; /* The maximum value for a range associated
+ F16DOT16 rangeMaxValue; /* The maximum value for a range associated
* with the specified name ID. */
public:
DEFINE_SIZE_STATIC (20);
@@ -124,10 +211,41 @@ struct AxisValueFormat3
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+ hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ unsigned axis_idx = get_axis_index ();
+ return axis_records[axis_idx].get_axis_tag ();
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_tag_t axis_tag = get_axis_tag (axis_records);
+ float axis_value = get_value ();
+
+ if (!user_axes_location->has (axis_tag) ||
+ fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
+ return true;
+
+ return false;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = &c->plan->user_axes_location;
+
+ if (keep_axis_value (axis_records, user_axes_location))
+ return_trace (c->serializer->embed (this));
+
+ return_trace (false);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -140,8 +258,8 @@ struct AxisValueFormat3
NameID valueNameID; /* The name ID for entries in the 'name' table
* that provide a display string for this
* attribute value. */
- HBFixed value; /* A numeric value for this attribute value. */
- HBFixed linkedValue; /* The numeric value for a style-linked mapping
+ F16DOT16 value; /* A numeric value for this attribute value. */
+ F16DOT16 linkedValue; /* The numeric value for a style-linked mapping
* from this value. */
public:
DEFINE_SIZE_STATIC (16);
@@ -155,14 +273,14 @@ struct AxisValueRecord
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
HBUINT16 axisIndex; /* Zero-base index into the axis record array
* identifying the axis to which this value
* applies. Must be less than designAxisCount. */
- HBFixed value; /* A numeric value for this attribute value. */
+ F16DOT16 value; /* A numeric value for this attribute value. */
public:
DEFINE_SIZE_STATIC (6);
};
@@ -172,12 +290,47 @@ struct AxisValueFormat4
const AxisValueRecord &get_axis_record (unsigned int axis_index) const
{ return axisValues.as_array (axisCount)[axis_index]; }
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount);
+
+ for (const auto& rec : axis_value_records)
+ {
+ unsigned axis_idx = rec.get_axis_index ();
+ float axis_value = rec.get_value ();
+ hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag ();
+
+ if (user_axes_location->has (axis_tag) &&
+ fabsf(axis_value - user_axes_location->get (axis_tag)) > 0.001f)
+ return false;
+ }
+
+ return true;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location = &c->plan->user_axes_location;
+ if (!keep_axis_value (axis_records, user_axes_location))
+ return_trace (false);
+
+ unsigned total_size = min_size + axisCount * AxisValueRecord::static_size;
+ auto *out = c->serializer->allocate_size<AxisValueFormat4> (total_size);
+ if (unlikely (!out)) return_trace (false);
+ hb_memcpy (out, this, total_size);
+ return_trace (true);
+ }
+
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (likely (c->check_struct (this) &&
+ axisValues.sanitize (c, axisCount)));
}
protected:
@@ -234,6 +387,33 @@ 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);
+ 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)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.keep_axis_value (axis_records, user_axes_location);
+ case 2: return u.format2.keep_axis_value (axis_records, user_axes_location);
+ case 3: return u.format3.keep_axis_value (axis_records, user_axes_location);
+ case 4: return u.format4.keep_axis_value (axis_records, user_axes_location);
+ default:return false;
+ }
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -263,27 +443,35 @@ struct AxisValue
DEFINE_SIZE_UNION (2, format);
};
-struct StatAxisRecord
+struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>>
{
- int cmp (hb_tag_t key) const { return tag.cmp (key); }
+ bool subset (hb_subset_context_t *c,
+ unsigned axisValueCount,
+ unsigned& count,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!out)) return_trace (false);
- hb_ot_name_id_t get_name_id () const { return nameID; }
+ auto axisValueOffsets = as_array (axisValueCount);
+ count = 0;
+ for (const auto& offset : axisValueOffsets)
+ {
+ if (!offset) continue;
+ auto o_snap = c->serializer->snapshot ();
+ auto *o = c->serializer->embed (offset);
+ if (!o) return_trace (false);
+ if (!o->serialize_subset (c, offset, this, axis_records))
+ {
+ c->serializer->revert (o_snap);
+ continue;
+ }
+ count++;
+ }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (count);
}
-
- protected:
- Tag tag; /* A tag identifying the axis of design variation. */
- NameID nameID; /* The name ID for entries in the 'name' table that
- * provide a display string for this axis. */
- HBUINT16 ordering; /* A value that applications can use to determine
- * primary sorting of face names, or for ordering
- * of descriptors when composing family or face names. */
- public:
- DEFINE_SIZE_STATIC (8);
};
struct STAT
@@ -329,7 +517,8 @@ struct STAT
return axis_value.get_value_name_id ();
}
- void collect_name_ids (hb_set_t *nameids_to_retain) const
+ void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ hb_set_t *nameids_to_retain /* OUT */) const
{
if (!has_data ()) return;
@@ -338,13 +527,38 @@ struct STAT
| hb_sink (nameids_to_retain)
;
+ auto designAxes = get_design_axes ();
+
+ get_axis_value_offsets ()
| hb_map (hb_add (&(this + offsetToAxisValueOffsets)))
+ | hb_filter ([&] (const AxisValue& _)
+ { return _.keep_axis_value (designAxes, user_axes_location); })
| hb_map (&AxisValue::get_value_name_id)
| hb_sink (nameids_to_retain)
;
}
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ STAT *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ auto designAxes = get_design_axes ();
+ for (unsigned i = 0; i < (unsigned)designAxisCount; i++)
+ if (unlikely (!c->serializer->embed (designAxes[i])))
+ return_trace (false);
+
+ if (designAxisCount)
+ c->serializer->check_assign (out->designAxesOffset, this->get_size (),
+ HB_SERIALIZE_ERROR_INT_OVERFLOW);
+
+ unsigned count = 0;
+ out->offsetToAxisValueOffsets.serialize_subset (c, offsetToAxisValueOffsets, this,
+ axisValueCount, count, designAxes);
+ return_trace (c->serializer->check_assign (out->axisValueCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -381,7 +595,7 @@ struct STAT
* set to zero; if designAxisCount is greater
* than zero, must be greater than zero. */
HBUINT16 axisValueCount; /* The number of axis value tables. */
- NNOffset32To<UnsizedArrayOf<Offset16To<AxisValue>>>
+ NNOffset32To<AxisValueOffsetArray>
offsetToAxisValueOffsets;
/* Offset in bytes from the beginning of
* the STAT table to the start of the design
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh
index 5261783277..9394b90ee6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag-table.hh
@@ -13,1612 +13,1617 @@
#ifndef HB_OT_TAG_TABLE_HH
#define HB_OT_TAG_TABLE_HH
-static const LangTag ot_languages[] = {
- {"aa", HB_TAG('A','F','R',' ')}, /* Afar */
- {"aae", HB_TAG('S','Q','I',' ')}, /* Arbëreshë Albanian -> Albanian */
- {"aao", HB_TAG('A','R','A',' ')}, /* Algerian Saharan Arabic -> Arabic */
- {"aat", HB_TAG('S','Q','I',' ')}, /* Arvanitika Albanian -> Albanian */
- {"ab", HB_TAG('A','B','K',' ')}, /* Abkhazian */
- {"aba", HB_TAG_NONE }, /* Abé != Abaza */
- {"abh", HB_TAG('A','R','A',' ')}, /* Tajiki Arabic -> Arabic */
- {"abq", HB_TAG('A','B','A',' ')}, /* Abaza */
- {"abs", HB_TAG('C','P','P',' ')}, /* Ambonese Malay -> Creoles */
- {"abv", HB_TAG('A','R','A',' ')}, /* Baharna Arabic -> Arabic */
- {"acf", HB_TAG('F','A','N',' ')}, /* Saint Lucian Creole French -> French Antillean */
- {"acf", HB_TAG('C','P','P',' ')}, /* Saint Lucian Creole French -> Creoles */
-/*{"ach", HB_TAG('A','C','H',' ')},*/ /* Acoli -> Acholi */
- {"acm", HB_TAG('A','R','A',' ')}, /* Mesopotamian Arabic -> Arabic */
- {"acq", HB_TAG('A','R','A',' ')}, /* Ta'izzi-Adeni Arabic -> Arabic */
- {"acr", HB_TAG('A','C','R',' ')}, /* Achi */
- {"acr", HB_TAG('M','Y','N',' ')}, /* Achi -> Mayan */
- {"acw", HB_TAG('A','R','A',' ')}, /* Hijazi Arabic -> Arabic */
- {"acx", HB_TAG('A','R','A',' ')}, /* Omani Arabic -> Arabic */
- {"acy", HB_TAG('A','R','A',' ')}, /* Cypriot Arabic -> Arabic */
- {"ada", HB_TAG('D','N','G',' ')}, /* Adangme -> Dangme */
- {"adf", HB_TAG('A','R','A',' ')}, /* Dhofari Arabic -> Arabic */
- {"adp", HB_TAG('D','Z','N',' ')}, /* Adap (retired code) -> Dzongkha */
-/*{"ady", HB_TAG('A','D','Y',' ')},*/ /* Adyghe */
- {"aeb", HB_TAG('A','R','A',' ')}, /* Tunisian Arabic -> Arabic */
- {"aec", HB_TAG('A','R','A',' ')}, /* Saidi Arabic -> Arabic */
- {"af", HB_TAG('A','F','K',' ')}, /* Afrikaans */
- {"afb", HB_TAG('A','R','A',' ')}, /* Gulf Arabic -> Arabic */
- {"afk", HB_TAG_NONE }, /* Nanubae != Afrikaans */
- {"afs", HB_TAG('C','P','P',' ')}, /* Afro-Seminole Creole -> Creoles */
- {"agu", HB_TAG('M','Y','N',' ')}, /* Aguacateco -> Mayan */
- {"agw", HB_TAG_NONE }, /* Kahua != Agaw */
- {"ahg", HB_TAG('A','G','W',' ')}, /* Qimant -> Agaw */
- {"aht", HB_TAG('A','T','H',' ')}, /* Ahtena -> Athapaskan */
- {"aig", HB_TAG('C','P','P',' ')}, /* Antigua and Barbuda Creole English -> Creoles */
- {"aii", HB_TAG('S','W','A',' ')}, /* Assyrian Neo-Aramaic -> Swadaya Aramaic */
- {"aii", HB_TAG('S','Y','R',' ')}, /* Assyrian Neo-Aramaic -> Syriac */
-/*{"aio", HB_TAG('A','I','O',' ')},*/ /* Aiton */
- {"aiw", HB_TAG('A','R','I',' ')}, /* Aari */
- {"ajp", HB_TAG('A','R','A',' ')}, /* South Levantine Arabic -> Arabic */
- {"ajt", HB_TAG('A','R','A',' ')}, /* Judeo-Tunisian Arabic (retired code) -> Arabic */
- {"ak", HB_TAG('A','K','A',' ')}, /* Akan [macrolanguage] */
- {"akb", HB_TAG('A','K','B',' ')}, /* Batak Angkola */
- {"akb", HB_TAG('B','T','K',' ')}, /* Batak Angkola -> Batak */
- {"aln", HB_TAG('S','Q','I',' ')}, /* Gheg Albanian -> Albanian */
- {"als", HB_TAG('S','Q','I',' ')}, /* Tosk Albanian -> Albanian */
-/*{"alt", HB_TAG('A','L','T',' ')},*/ /* Southern Altai -> Altai */
- {"am", HB_TAG('A','M','H',' ')}, /* Amharic */
- {"amf", HB_TAG('H','B','N',' ')}, /* Hamer-Banna -> Hammer-Banna */
- {"amw", HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic -> Syriac */
- {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */
-/*{"ang", HB_TAG('A','N','G',' ')},*/ /* Old English (ca. 450-1100) -> Anglo-Saxon */
- {"aoa", HB_TAG('C','P','P',' ')}, /* Angolar -> Creoles */
- {"apa", HB_TAG('A','T','H',' ')}, /* Apache [collection] -> Athapaskan */
- {"apc", HB_TAG('A','R','A',' ')}, /* North Levantine Arabic -> Arabic */
- {"apd", HB_TAG('A','R','A',' ')}, /* Sudanese Arabic -> Arabic */
- {"apj", HB_TAG('A','T','H',' ')}, /* Jicarilla Apache -> Athapaskan */
- {"apk", HB_TAG('A','T','H',' ')}, /* Kiowa Apache -> Athapaskan */
- {"apl", HB_TAG('A','T','H',' ')}, /* Lipan Apache -> Athapaskan */
- {"apm", HB_TAG('A','T','H',' ')}, /* Mescalero-Chiricahua Apache -> Athapaskan */
- {"apw", HB_TAG('A','T','H',' ')}, /* Western Apache -> Athapaskan */
- {"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */
- {"arb", HB_TAG('A','R','A',' ')}, /* Standard Arabic -> Arabic */
- {"ari", HB_TAG_NONE }, /* Arikara != Aari */
- {"ark", HB_TAG_NONE }, /* Arikapú != Rakhine */
- {"arn", HB_TAG('M','A','P',' ')}, /* Mapudungun */
- {"arq", HB_TAG('A','R','A',' ')}, /* Algerian Arabic -> Arabic */
- {"ars", HB_TAG('A','R','A',' ')}, /* Najdi Arabic -> Arabic */
- {"ary", HB_TAG('M','O','R',' ')}, /* Moroccan Arabic -> Moroccan */
- {"ary", HB_TAG('A','R','A',' ')}, /* Moroccan Arabic -> Arabic */
- {"arz", HB_TAG('A','R','A',' ')}, /* Egyptian Arabic -> Arabic */
- {"as", HB_TAG('A','S','M',' ')}, /* Assamese */
-/*{"ast", HB_TAG('A','S','T',' ')},*/ /* Asturian */
-/*{"ath", HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */
- {"atj", HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */
- {"atv", HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */
- {"auj", HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */
- {"auz", HB_TAG('A','R','A',' ')}, /* Uzbeki Arabic -> Arabic */
- {"av", HB_TAG('A','V','R',' ')}, /* Avaric -> Avar */
- {"avl", HB_TAG('A','R','A',' ')}, /* Eastern Egyptian Bedawi Arabic -> Arabic */
-/*{"avn", HB_TAG('A','V','N',' ')},*/ /* Avatime */
-/*{"awa", HB_TAG('A','W','A',' ')},*/ /* Awadhi */
- {"ay", HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */
- {"ayc", HB_TAG('A','Y','M',' ')}, /* Southern Aymara -> Aymara */
- {"ayh", HB_TAG('A','R','A',' ')}, /* Hadrami Arabic -> Arabic */
- {"ayl", HB_TAG('A','R','A',' ')}, /* Libyan Arabic -> Arabic */
- {"ayn", HB_TAG('A','R','A',' ')}, /* Sanaani Arabic -> Arabic */
- {"ayp", HB_TAG('A','R','A',' ')}, /* North Mesopotamian Arabic -> Arabic */
- {"ayr", HB_TAG('A','Y','M',' ')}, /* Central Aymara -> Aymara */
- {"az", HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */
- {"azb", HB_TAG('A','Z','B',' ')}, /* South Azerbaijani -> Torki */
- {"azb", HB_TAG('A','Z','E',' ')}, /* South Azerbaijani -> Azerbaijani */
- {"azd", HB_TAG('N','A','H',' ')}, /* Eastern Durango Nahuatl -> Nahuatl */
- {"azj", HB_TAG('A','Z','E',' ')}, /* North Azerbaijani -> Azerbaijani */
- {"azn", HB_TAG('N','A','H',' ')}, /* Western Durango Nahuatl -> Nahuatl */
- {"azz", HB_TAG('N','A','H',' ')}, /* Highland Puebla Nahuatl -> Nahuatl */
- {"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */
- {"bad", HB_TAG('B','A','D','0')}, /* Banda [collection] */
- {"bag", HB_TAG_NONE }, /* Tuki != Baghelkhandi */
- {"bah", HB_TAG('C','P','P',' ')}, /* Bahamas Creole English -> Creoles */
- {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [collection] */
- {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolanguage] */
-/*{"ban", HB_TAG('B','A','N',' ')},*/ /* Balinese */
-/*{"bar", HB_TAG('B','A','R',' ')},*/ /* Bavarian */
- {"bau", HB_TAG_NONE }, /* Bada (Nigeria) != Baulé */
- {"bbc", HB_TAG('B','B','C',' ')}, /* Batak Toba */
- {"bbc", HB_TAG('B','T','K',' ')}, /* Batak Toba -> Batak */
- {"bbj", HB_TAG('B','M','L',' ')}, /* Ghomálá' -> Bamileke */
- {"bbp", HB_TAG('B','A','D','0')}, /* West Central Banda -> Banda */
- {"bbr", HB_TAG_NONE }, /* Girawa != Berber */
- {"bbz", HB_TAG('A','R','A',' ')}, /* Babalia Creole Arabic (retired code) -> Arabic */
- {"bcc", HB_TAG('B','L','I',' ')}, /* Southern Balochi -> Baluchi */
- {"bch", HB_TAG_NONE }, /* Bariai != Bench */
- {"bci", HB_TAG('B','A','U',' ')}, /* Baoulé -> Baulé */
- {"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol -> Bikol */
- {"bcq", HB_TAG('B','C','H',' ')}, /* Bench */
- {"bcr", HB_TAG('A','T','H',' ')}, /* Babine -> Athapaskan */
-/*{"bdy", HB_TAG('B','D','Y',' ')},*/ /* Bandjalang */
- {"be", HB_TAG('B','E','L',' ')}, /* Belarusian -> Belarussian */
- {"bea", HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */
- {"beb", HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */
-/*{"bem", HB_TAG('B','E','M',' ')},*/ /* Bemba (Zambia) */
- {"ber", HB_TAG('B','B','R',' ')}, /* Berber [collection] */
- {"bew", HB_TAG('C','P','P',' ')}, /* Betawi -> Creoles */
- {"bfl", HB_TAG('B','A','D','0')}, /* Banda-Ndélé -> Banda */
- {"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */
- {"bft", HB_TAG('B','L','T',' ')}, /* Balti */
- {"bfu", HB_TAG('L','A','H',' ')}, /* Gahri -> Lahuli */
- {"bfy", HB_TAG('B','A','G',' ')}, /* Bagheli -> Baghelkhandi */
- {"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */
-/*{"bgc", HB_TAG('B','G','C',' ')},*/ /* Haryanvi */
- {"bgn", HB_TAG('B','L','I',' ')}, /* Western Balochi -> Baluchi */
- {"bgp", HB_TAG('B','L','I',' ')}, /* Eastern Balochi -> Baluchi */
- {"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */
- {"bgq", HB_TAG('R','A','J',' ')}, /* Bagri -> Rajasthani */
- {"bgr", HB_TAG('Q','I','N',' ')}, /* Bawm Chin -> Chin */
- {"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */
-/*{"bhi", HB_TAG('B','H','I',' ')},*/ /* Bhilali -> Bhili */
- {"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) -> Bikol */
-/*{"bho", HB_TAG('B','H','O',' ')},*/ /* Bhojpuri */
- {"bhr", HB_TAG('M','L','G',' ')}, /* Bara Malagasy -> Malagasy */
- {"bi", HB_TAG('B','I','S',' ')}, /* Bislama */
- {"bi", HB_TAG('C','P','P',' ')}, /* Bislama -> Creoles */
-/*{"bik", HB_TAG('B','I','K',' ')},*/ /* Bikol [macrolanguage] */
- {"bil", HB_TAG_NONE }, /* Bile != Bilen */
- {"bin", HB_TAG('E','D','O',' ')}, /* Edo */
- {"biu", HB_TAG('Q','I','N',' ')}, /* Biete -> Chin */
-/*{"bjj", HB_TAG('B','J','J',' ')},*/ /* Kanauji */
- {"bjn", HB_TAG('M','L','Y',' ')}, /* Banjar -> Malay */
- {"bjo", HB_TAG('B','A','D','0')}, /* Mid-Southern Banda -> Banda */
- {"bjq", HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
- {"bjs", HB_TAG('C','P','P',' ')}, /* Bajan -> Creoles */
- {"bjt", HB_TAG('B','L','N',' ')}, /* Balanta-Ganja -> Balante */
- {"bkf", HB_TAG_NONE }, /* Beeke != Blackfoot */
- {"bko", HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */
- {"bla", HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */
- {"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */
- {"blg", HB_TAG('I','B','A',' ')}, /* Balau (retired code) -> Iban */
- {"bli", HB_TAG_NONE }, /* Bolia != Baluchi */
- {"blk", HB_TAG('B','L','K',' ')}, /* Pa’o Karen */
- {"blk", HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */
- {"bln", HB_TAG('B','I','K',' ')}, /* Southern Catanduanes Bikol -> Bikol */
- {"blt", HB_TAG_NONE }, /* Tai Dam != Balti */
- {"bm", HB_TAG('B','M','B',' ')}, /* Bambara (Bamanankan) */
- {"bmb", HB_TAG_NONE }, /* Bembe != Bambara (Bamanankan) */
- {"bml", HB_TAG_NONE }, /* Bomboli != Bamileke */
- {"bmm", HB_TAG('M','L','G',' ')}, /* Northern Betsimisaraka Malagasy -> Malagasy */
- {"bn", HB_TAG('B','E','N',' ')}, /* Bengali */
- {"bo", HB_TAG('T','I','B',' ')}, /* Tibetan */
- {"bpd", HB_TAG('B','A','D','0')}, /* Banda-Banda -> Banda */
- {"bpl", HB_TAG('C','P','P',' ')}, /* Broome Pearling Lugger Pidgin -> Creoles */
- {"bpq", HB_TAG('C','P','P',' ')}, /* Banda Malay -> Creoles */
-/*{"bpy", HB_TAG('B','P','Y',' ')},*/ /* Bishnupriya -> Bishnupriya Manipuri */
- {"bqi", HB_TAG('L','R','C',' ')}, /* Bakhtiari -> Luri */
- {"bqk", HB_TAG('B','A','D','0')}, /* Banda-Mbrès -> Banda */
- {"br", HB_TAG('B','R','E',' ')}, /* Breton */
- {"bra", HB_TAG('B','R','I',' ')}, /* Braj -> Braj Bhasha */
- {"brc", HB_TAG('C','P','P',' ')}, /* Berbice Creole Dutch -> Creoles */
-/*{"brh", HB_TAG('B','R','H',' ')},*/ /* Brahui */
- {"bri", HB_TAG_NONE }, /* Mokpwe != Braj Bhasha */
- {"brm", HB_TAG_NONE }, /* Barambu != Burmese */
-/*{"brx", HB_TAG('B','R','X',' ')},*/ /* Bodo (India) */
- {"bs", HB_TAG('B','O','S',' ')}, /* Bosnian */
- {"bsh", HB_TAG_NONE }, /* Kati != Bashkir */
-/*{"bsk", HB_TAG('B','S','K',' ')},*/ /* Burushaski */
- {"btb", HB_TAG('B','T','I',' ')}, /* Beti (Cameroon) (retired code) */
- {"btd", HB_TAG('B','T','D',' ')}, /* Batak Dairi (Pakpak) */
- {"btd", HB_TAG('B','T','K',' ')}, /* Batak Dairi -> Batak */
- {"bti", HB_TAG_NONE }, /* Burate != Beti */
- {"btj", HB_TAG('M','L','Y',' ')}, /* Bacanese Malay -> Malay */
-/*{"btk", HB_TAG('B','T','K',' ')},*/ /* Batak [collection] */
- {"btm", HB_TAG('B','T','M',' ')}, /* Batak Mandailing */
- {"btm", HB_TAG('B','T','K',' ')}, /* Batak Mandailing -> Batak */
- {"bto", HB_TAG('B','I','K',' ')}, /* Rinconada Bikol -> Bikol */
- {"bts", HB_TAG('B','T','S',' ')}, /* Batak Simalungun */
- {"bts", HB_TAG('B','T','K',' ')}, /* Batak Simalungun -> Batak */
- {"btx", HB_TAG('B','T','X',' ')}, /* Batak Karo */
- {"btx", HB_TAG('B','T','K',' ')}, /* Batak Karo -> Batak */
- {"btz", HB_TAG('B','T','Z',' ')}, /* Batak Alas-Kluet */
- {"btz", HB_TAG('B','T','K',' ')}, /* Batak Alas-Kluet -> Batak */
-/*{"bug", HB_TAG('B','U','G',' ')},*/ /* Buginese -> Bugis */
- {"bum", HB_TAG('B','T','I',' ')}, /* Bulu (Cameroon) -> Beti */
- {"bve", HB_TAG('M','L','Y',' ')}, /* Berau Malay -> Malay */
- {"bvu", HB_TAG('M','L','Y',' ')}, /* Bukit Malay -> Malay */
- {"bwe", HB_TAG('K','R','N',' ')}, /* Bwe Karen -> Karen */
- {"bxk", HB_TAG('L','U','H',' ')}, /* Bukusu -> Luyia */
- {"bxo", HB_TAG('C','P','P',' ')}, /* Barikanchi -> Creoles */
- {"bxp", HB_TAG('B','T','I',' ')}, /* Bebil -> Beti */
- {"bxr", HB_TAG('R','B','U',' ')}, /* Russia Buriat -> Russian Buriat */
- {"byn", HB_TAG('B','I','L',' ')}, /* Bilin -> Bilen */
- {"byv", HB_TAG('B','Y','V',' ')}, /* Medumba */
- {"byv", HB_TAG('B','M','L',' ')}, /* Medumba -> Bamileke */
- {"bzc", HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy -> Malagasy */
- {"bzj", HB_TAG('C','P','P',' ')}, /* Belize Kriol English -> Creoles */
- {"bzk", HB_TAG('C','P','P',' ')}, /* Nicaragua Creole English -> Creoles */
- {"ca", HB_TAG('C','A','T',' ')}, /* Catalan */
- {"caa", HB_TAG('M','Y','N',' ')}, /* Chortí -> Mayan */
- {"cac", HB_TAG('M','Y','N',' ')}, /* Chuj -> Mayan */
- {"caf", HB_TAG('C','R','R',' ')}, /* Southern Carrier -> Carrier */
- {"caf", HB_TAG('A','T','H',' ')}, /* Southern Carrier -> Athapaskan */
- {"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */
- {"cak", HB_TAG('M','Y','N',' ')}, /* Kaqchikel -> Mayan */
- {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano -> Zamboanga Chavacano */
- {"cbk", HB_TAG('C','P','P',' ')}, /* Chavacano -> Creoles */
- {"cbl", HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin -> Chin */
- {"ccl", HB_TAG('C','P','P',' ')}, /* Cutchi-Swahili -> Creoles */
- {"ccm", HB_TAG('C','P','P',' ')}, /* Malaccan Creole Malay -> Creoles */
- {"cco", HB_TAG('C','C','H','N')}, /* Comaltepec Chinantec -> Chinantec */
- {"ccq", HB_TAG('A','R','K',' ')}, /* Chaungtha (retired code) -> Rakhine */
- {"cdo", HB_TAG('Z','H','S',' ')}, /* Min Dong Chinese -> Chinese, Simplified */
- {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */
-/*{"ceb", HB_TAG('C','E','B',' ')},*/ /* Cebuano */
- {"cek", HB_TAG('Q','I','N',' ')}, /* Eastern Khumi Chin -> Chin */
- {"cey", HB_TAG('Q','I','N',' ')}, /* Ekai Chin -> Chin */
- {"cfm", HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) */
- {"cfm", HB_TAG('Q','I','N',' ')}, /* Falam Chin -> Chin */
-/*{"cgg", HB_TAG('C','G','G',' ')},*/ /* Chiga */
- {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */
- {"chf", HB_TAG('M','Y','N',' ')}, /* Tabasco Chontal -> Mayan */
- {"chg", HB_TAG_NONE }, /* Chagatai != Chaha Gurage */
- {"chh", HB_TAG_NONE }, /* Chinook != Chattisgarhi */
- {"chj", HB_TAG('C','C','H','N')}, /* Ojitlán Chinantec -> Chinantec */
- {"chk", HB_TAG('C','H','K','0')}, /* Chuukese */
- {"chm", HB_TAG('H','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> High Mari */
- {"chm", HB_TAG('L','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> Low Mari */
- {"chn", HB_TAG('C','P','P',' ')}, /* Chinook jargon -> Creoles */
-/*{"cho", HB_TAG('C','H','O',' ')},*/ /* Choctaw */
- {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */
- {"chp", HB_TAG('S','A','Y',' ')}, /* Chipewyan -> Sayisi */
- {"chp", HB_TAG('A','T','H',' ')}, /* Chipewyan -> Athapaskan */
- {"chq", HB_TAG('C','C','H','N')}, /* Quiotepec Chinantec -> Chinantec */
-/*{"chr", HB_TAG('C','H','R',' ')},*/ /* Cherokee */
-/*{"chy", HB_TAG('C','H','Y',' ')},*/ /* Cheyenne */
- {"chz", HB_TAG('C','C','H','N')}, /* Ozumacín Chinantec -> Chinantec */
- {"ciw", HB_TAG('O','J','B',' ')}, /* Chippewa -> Ojibway */
-/*{"cja", HB_TAG('C','J','A',' ')},*/ /* Western Cham */
-/*{"cjm", HB_TAG('C','J','M',' ')},*/ /* Eastern Cham */
- {"cjy", HB_TAG('Z','H','S',' ')}, /* Jinyu Chinese -> Chinese, Simplified */
- {"cka", HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin (retired code) -> Chin */
- {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish -> Kurdish */
- {"ckn", HB_TAG('Q','I','N',' ')}, /* Kaang Chin -> Chin */
- {"cks", HB_TAG('C','P','P',' ')}, /* Tayo -> Creoles */
- {"ckt", HB_TAG('C','H','K',' ')}, /* Chukot -> Chukchi */
- {"ckz", HB_TAG('M','Y','N',' ')}, /* Cakchiquel-Quiché Mixed Language -> Mayan */
- {"clc", HB_TAG('A','T','H',' ')}, /* Chilcotin -> Athapaskan */
- {"cld", HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic -> Syriac */
- {"cle", HB_TAG('C','C','H','N')}, /* Lealao Chinantec -> Chinantec */
- {"clj", HB_TAG('Q','I','N',' ')}, /* Laitu Chin -> Chin */
- {"clt", HB_TAG('Q','I','N',' ')}, /* Lautu Chin -> Chin */
- {"cmn", HB_TAG('Z','H','S',' ')}, /* Mandarin Chinese -> Chinese, Simplified */
- {"cmr", HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin -> Chin */
- {"cnb", HB_TAG('Q','I','N',' ')}, /* Chinbon Chin -> Chin */
- {"cnh", HB_TAG('Q','I','N',' ')}, /* Hakha Chin -> Chin */
- {"cnk", HB_TAG('Q','I','N',' ')}, /* Khumi Chin -> Chin */
- {"cnl", HB_TAG('C','C','H','N')}, /* Lalana Chinantec -> Chinantec */
- {"cnp", HB_TAG('Z','H','S',' ')}, /* Northern Ping Chinese -> Chinese, Simplified */
- {"cnr", HB_TAG('S','R','B',' ')}, /* Montenegrin -> Serbian */
- {"cnt", HB_TAG('C','C','H','N')}, /* Tepetotutla Chinantec -> Chinantec */
- {"cnu", HB_TAG('B','B','R',' ')}, /* Chenoua -> Berber */
- {"cnw", HB_TAG('Q','I','N',' ')}, /* Ngawn Chin -> Chin */
- {"co", HB_TAG('C','O','S',' ')}, /* Corsican */
- {"coa", HB_TAG('M','L','Y',' ')}, /* Cocos Islands Malay -> Malay */
- {"cob", HB_TAG('M','Y','N',' ')}, /* Chicomuceltec -> Mayan */
-/*{"cop", HB_TAG('C','O','P',' ')},*/ /* Coptic */
- {"coq", HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */
- {"cpa", HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */
- {"cpe", HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [collection] -> Creoles */
- {"cpf", HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [collection] -> Creoles */
- {"cpi", HB_TAG('C','P','P',' ')}, /* Chinese Pidgin English -> Creoles */
-/*{"cpp", HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [collection] -> Creoles */
- {"cpx", HB_TAG('Z','H','S',' ')}, /* Pu-Xian Chinese -> Chinese, Simplified */
- {"cqd", HB_TAG('H','M','N',' ')}, /* Chuanqiandian Cluster Miao -> Hmong */
- {"cqu", HB_TAG('Q','U','H',' ')}, /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
- {"cqu", HB_TAG('Q','U','Z',' ')}, /* Chilean Quechua (retired code) -> Quechua */
- {"cr", HB_TAG('C','R','E',' ')}, /* Cree [macrolanguage] */
- {"crh", HB_TAG('C','R','T',' ')}, /* Crimean Tatar */
- {"cri", HB_TAG('C','P','P',' ')}, /* Sãotomense -> Creoles */
- {"crj", HB_TAG('E','C','R',' ')}, /* Southern East Cree -> Eastern Cree */
- {"crj", HB_TAG('Y','C','R',' ')}, /* Southern East Cree -> Y-Cree */
- {"crj", HB_TAG('C','R','E',' ')}, /* Southern East Cree -> Cree */
- {"crk", HB_TAG('W','C','R',' ')}, /* Plains Cree -> West-Cree */
- {"crk", HB_TAG('Y','C','R',' ')}, /* Plains Cree -> Y-Cree */
- {"crk", HB_TAG('C','R','E',' ')}, /* Plains Cree -> Cree */
- {"crl", HB_TAG('E','C','R',' ')}, /* Northern East Cree -> Eastern Cree */
- {"crl", HB_TAG('Y','C','R',' ')}, /* Northern East Cree -> Y-Cree */
- {"crl", HB_TAG('C','R','E',' ')}, /* Northern East Cree -> Cree */
- {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */
- {"crm", HB_TAG('L','C','R',' ')}, /* Moose Cree -> L-Cree */
- {"crm", HB_TAG('C','R','E',' ')}, /* Moose Cree -> Cree */
- {"crp", HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [collection] -> Creoles */
- {"crr", HB_TAG_NONE }, /* Carolina Algonquian != Carrier */
- {"crs", HB_TAG('C','P','P',' ')}, /* Seselwa Creole French -> Creoles */
- {"crt", HB_TAG_NONE }, /* Iyojwa'ja Chorote != Crimean Tatar */
- {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */
- {"crx", HB_TAG('A','T','H',' ')}, /* Carrier -> Athapaskan */
- {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */
- {"csa", HB_TAG('C','C','H','N')}, /* Chiltepec Chinantec -> Chinantec */
-/*{"csb", HB_TAG('C','S','B',' ')},*/ /* Kashubian */
- {"csh", HB_TAG('Q','I','N',' ')}, /* Asho Chin -> Chin */
- {"csj", HB_TAG('Q','I','N',' ')}, /* Songlai Chin -> Chin */
- {"csl", HB_TAG_NONE }, /* Chinese Sign Language != Church Slavonic */
- {"cso", HB_TAG('C','C','H','N')}, /* Sochiapam Chinantec -> Chinantec */
- {"csp", HB_TAG('Z','H','S',' ')}, /* Southern Ping Chinese -> Chinese, Simplified */
- {"csv", HB_TAG('Q','I','N',' ')}, /* Sumtu Chin -> Chin */
- {"csw", HB_TAG('N','C','R',' ')}, /* Swampy Cree -> N-Cree */
- {"csw", HB_TAG('N','H','C',' ')}, /* Swampy Cree -> Norway House Cree */
- {"csw", HB_TAG('C','R','E',' ')}, /* Swampy Cree -> Cree */
- {"csy", HB_TAG('Q','I','N',' ')}, /* Siyin Chin -> Chin */
- {"ctc", HB_TAG('A','T','H',' ')}, /* Chetco -> Athapaskan */
- {"ctd", HB_TAG('Q','I','N',' ')}, /* Tedim Chin -> Chin */
- {"cte", HB_TAG('C','C','H','N')}, /* Tepinapa Chinantec -> Chinantec */
-/*{"ctg", HB_TAG('C','T','G',' ')},*/ /* Chittagonian */
- {"cth", HB_TAG('Q','I','N',' ')}, /* Thaiphum Chin -> Chin */
- {"ctl", HB_TAG('C','C','H','N')}, /* Tlacoatzintepec Chinantec -> Chinantec */
- {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol -> Bikol */
-/*{"ctt", HB_TAG('C','T','T',' ')},*/ /* Wayanad Chetti */
- {"ctu", HB_TAG('M','Y','N',' ')}, /* Chol -> Mayan */
- {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavonic */
- {"cuc", HB_TAG('C','C','H','N')}, /* Usila Chinantec -> Chinantec */
-/*{"cuk", HB_TAG('C','U','K',' ')},*/ /* San Blas Kuna */
- {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */
- {"cvn", HB_TAG('C','C','H','N')}, /* Valle Nacional Chinantec -> Chinantec */
- {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */
- {"cwd", HB_TAG('T','C','R',' ')}, /* Woods Cree -> TH-Cree */
- {"cwd", HB_TAG('C','R','E',' ')}, /* Woods Cree -> Cree */
- {"cy", HB_TAG('W','E','L',' ')}, /* Welsh */
- {"czh", HB_TAG('Z','H','S',' ')}, /* Huizhou Chinese -> Chinese, Simplified */
- {"czo", HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */
- {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */
- {"da", HB_TAG('D','A','N',' ')}, /* Danish */
-/*{"dag", HB_TAG('D','A','G',' ')},*/ /* Dagbani */
- {"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */
- {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */
-/*{"dar", HB_TAG('D','A','R',' ')},*/ /* Dargwa */
-/*{"dax", HB_TAG('D','A','X',' ')},*/ /* Dayi */
- {"dcr", HB_TAG('C','P','P',' ')}, /* Negerhollands -> Creoles */
- {"de", HB_TAG('D','E','U',' ')}, /* German */
- {"den", HB_TAG('S','L','A',' ')}, /* Slave (Athapascan) [macrolanguage] -> Slavey */
- {"den", HB_TAG('A','T','H',' ')}, /* Slave (Athapascan) [macrolanguage] -> Athapaskan */
- {"dep", HB_TAG('C','P','P',' ')}, /* Pidgin Delaware -> Creoles */
- {"dgo", HB_TAG('D','G','O',' ')}, /* Dogri (individual language) */
- {"dgo", HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) */
- {"dgr", HB_TAG('A','T','H',' ')}, /* Dogrib -> Athapaskan */
- {"dhd", HB_TAG('M','A','W',' ')}, /* Dhundari -> Marwari */
-/*{"dhg", HB_TAG('D','H','G',' ')},*/ /* Dhangu */
- {"dhv", HB_TAG_NONE }, /* Dehu != Divehi (Dhivehi, Maldivian) (deprecated) */
- {"dib", HB_TAG('D','N','K',' ')}, /* South Central Dinka -> Dinka */
- {"dik", HB_TAG('D','N','K',' ')}, /* Southwestern Dinka -> Dinka */
- {"din", HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */
- {"dip", HB_TAG('D','N','K',' ')}, /* Northeastern Dinka -> Dinka */
- {"diq", HB_TAG('D','I','Q',' ')}, /* Dimli */
- {"diq", HB_TAG('Z','Z','A',' ')}, /* Dimli -> Zazaki */
- {"diw", HB_TAG('D','N','K',' ')}, /* Northwestern Dinka -> Dinka */
- {"dje", HB_TAG('D','J','R',' ')}, /* Zarma */
- {"djk", HB_TAG('C','P','P',' ')}, /* Eastern Maroon Creole -> Creoles */
- {"djr", HB_TAG('D','J','R','0')}, /* Djambarrpuyngu */
- {"dks", HB_TAG('D','N','K',' ')}, /* Southeastern Dinka -> Dinka */
- {"dng", HB_TAG('D','U','N',' ')}, /* Dungan */
-/*{"dnj", HB_TAG('D','N','J',' ')},*/ /* Dan */
- {"dnk", HB_TAG_NONE }, /* Dengka != Dinka */
- {"doi", HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) [macrolanguage] */
- {"drh", HB_TAG('M','N','G',' ')}, /* Darkhat (retired code) -> Mongolian */
- {"dri", HB_TAG_NONE }, /* C'Lela != Dari */
- {"drw", HB_TAG('D','R','I',' ')}, /* Darwazi (retired code) -> Dari */
- {"drw", HB_TAG('F','A','R',' ')}, /* Darwazi (retired code) -> Persian */
- {"dsb", HB_TAG('L','S','B',' ')}, /* Lower Sorbian */
- {"dty", HB_TAG('N','E','P',' ')}, /* Dotyali -> Nepali */
-/*{"duj", HB_TAG('D','U','J',' ')},*/ /* Dhuwal (retired code) */
- {"dun", HB_TAG_NONE }, /* Dusun Deyah != Dungan */
- {"dup", HB_TAG('M','L','Y',' ')}, /* Duano -> Malay */
- {"dv", HB_TAG('D','I','V',' ')}, /* Divehi (Dhivehi, Maldivian) */
- {"dv", HB_TAG('D','H','V',' ')}, /* Divehi (Dhivehi, Maldivian) (deprecated) */
- {"dwk", HB_TAG('K','U','I',' ')}, /* Dawik Kui -> Kui */
- {"dwu", HB_TAG('D','U','J',' ')}, /* Dhuwal */
- {"dwy", HB_TAG('D','U','J',' ')}, /* Dhuwaya -> Dhuwal */
- {"dyu", HB_TAG('J','U','L',' ')}, /* Dyula -> Jula */
- {"dz", HB_TAG('D','Z','N',' ')}, /* Dzongkha */
- {"dzn", HB_TAG_NONE }, /* Dzando != Dzongkha */
- {"ecr", HB_TAG_NONE }, /* Eteocretan != Eastern Cree */
- {"ee", HB_TAG('E','W','E',' ')}, /* Ewe */
-/*{"efi", HB_TAG('E','F','I',' ')},*/ /* Efik */
- {"ekk", HB_TAG('E','T','I',' ')}, /* Standard Estonian -> Estonian */
- {"eky", HB_TAG('K','R','N',' ')}, /* Eastern Kayah -> Karen */
- {"el", HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) -> Greek */
- {"emk", HB_TAG('E','M','K',' ')}, /* Eastern Maninkakan */
- {"emk", HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan -> Maninka */
- {"emy", HB_TAG('M','Y','N',' ')}, /* Epigraphic Mayan -> Mayan */
- {"en", HB_TAG('E','N','G',' ')}, /* English */
- {"enb", HB_TAG('K','A','L',' ')}, /* Markweeta -> Kalenjin */
- {"enf", HB_TAG('F','N','E',' ')}, /* Forest Enets */
- {"enh", HB_TAG('T','N','E',' ')}, /* Tundra Enets */
- {"eo", HB_TAG('N','T','O',' ')}, /* Esperanto */
- {"es", HB_TAG('E','S','P',' ')}, /* Spanish */
- {"esg", HB_TAG('G','O','N',' ')}, /* Aheri Gondi -> Gondi */
- {"esi", HB_TAG('I','P','K',' ')}, /* North Alaskan Inupiatun -> Inupiat */
- {"esk", HB_TAG('I','P','K',' ')}, /* Northwest Alaska Inupiatun -> Inupiat */
-/*{"esu", HB_TAG('E','S','U',' ')},*/ /* Central Yupik */
- {"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */
- {"eto", HB_TAG('B','T','I',' ')}, /* Eton (Cameroon) -> Beti */
- {"eu", HB_TAG('E','U','Q',' ')}, /* Basque */
- {"euq", HB_TAG_NONE }, /* Basque [collection] != Basque */
- {"eve", HB_TAG('E','V','N',' ')}, /* Even */
- {"evn", HB_TAG('E','V','K',' ')}, /* Evenki */
- {"ewo", HB_TAG('B','T','I',' ')}, /* Ewondo -> Beti */
- {"eyo", HB_TAG('K','A','L',' ')}, /* Keiyo -> Kalenjin */
- {"fa", HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */
- {"fab", HB_TAG('C','P','P',' ')}, /* Fa d'Ambu -> Creoles */
- {"fan", HB_TAG('F','A','N','0')}, /* Fang (Equatorial Guinea) */
- {"fan", HB_TAG('B','T','I',' ')}, /* Fang (Equatorial Guinea) -> Beti */
- {"far", HB_TAG_NONE }, /* Fataleka != Persian */
- {"fat", HB_TAG('F','A','T',' ')}, /* Fanti */
- {"fat", HB_TAG('A','K','A',' ')}, /* Fanti -> Akan */
- {"fbl", HB_TAG('B','I','K',' ')}, /* West Albay Bikol -> Bikol */
- {"ff", HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */
- {"ffm", HB_TAG('F','U','L',' ')}, /* Maasina Fulfulde -> Fulah */
- {"fi", HB_TAG('F','I','N',' ')}, /* Finnish */
- {"fil", HB_TAG('P','I','L',' ')}, /* Filipino */
- {"fj", HB_TAG('F','J','I',' ')}, /* Fijian */
- {"flm", HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) (retired code) */
- {"flm", HB_TAG('Q','I','N',' ')}, /* Falam Chin (retired code) -> Chin */
- {"fmp", HB_TAG('F','M','P',' ')}, /* Fe’fe’ */
- {"fmp", HB_TAG('B','M','L',' ')}, /* Fe'fe' -> Bamileke */
- {"fng", HB_TAG('C','P','P',' ')}, /* Fanagalo -> Creoles */
- {"fo", HB_TAG('F','O','S',' ')}, /* Faroese */
-/*{"fon", HB_TAG('F','O','N',' ')},*/ /* Fon */
- {"fos", HB_TAG_NONE }, /* Siraya != Faroese */
- {"fpe", HB_TAG('C','P','P',' ')}, /* Fernando Po Creole English -> Creoles */
- {"fr", HB_TAG('F','R','A',' ')}, /* French */
-/*{"frc", HB_TAG('F','R','C',' ')},*/ /* Cajun French */
-/*{"frp", HB_TAG('F','R','P',' ')},*/ /* Arpitan */
- {"fub", HB_TAG('F','U','L',' ')}, /* Adamawa Fulfulde -> Fulah */
- {"fuc", HB_TAG('F','U','L',' ')}, /* Pulaar -> Fulah */
- {"fue", HB_TAG('F','U','L',' ')}, /* Borgu Fulfulde -> Fulah */
- {"fuf", HB_TAG('F','T','A',' ')}, /* Pular -> Futa */
- {"fuf", HB_TAG('F','U','L',' ')}, /* Pular -> Fulah */
- {"fuh", HB_TAG('F','U','L',' ')}, /* Western Niger Fulfulde -> Fulah */
- {"fui", HB_TAG('F','U','L',' ')}, /* Bagirmi Fulfulde -> Fulah */
- {"fuq", HB_TAG('F','U','L',' ')}, /* Central-Eastern Niger Fulfulde -> Fulah */
- {"fur", HB_TAG('F','R','L',' ')}, /* Friulian */
- {"fuv", HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */
- {"fuv", HB_TAG('F','U','L',' ')}, /* Nigerian Fulfulde -> Fulah */
- {"fy", HB_TAG('F','R','I',' ')}, /* Western Frisian -> Frisian */
- {"ga", HB_TAG('I','R','I',' ')}, /* Irish */
- {"gaa", HB_TAG('G','A','D',' ')}, /* Ga */
- {"gac", HB_TAG('C','P','P',' ')}, /* Mixed Great Andamanese -> Creoles */
- {"gad", HB_TAG_NONE }, /* Gaddang != Ga */
- {"gae", HB_TAG_NONE }, /* Guarequena != Scottish Gaelic (Gaelic) */
-/*{"gag", HB_TAG('G','A','G',' ')},*/ /* Gagauz */
- {"gal", HB_TAG_NONE }, /* Galolen != Galician */
- {"gan", HB_TAG('Z','H','S',' ')}, /* Gan Chinese -> Chinese, Simplified */
- {"gar", HB_TAG_NONE }, /* Galeya != Garshuni */
- {"gaw", HB_TAG_NONE }, /* Nobonob != Garhwali */
- {"gax", HB_TAG('O','R','O',' ')}, /* Borana-Arsi-Guji Oromo -> Oromo */
- {"gaz", HB_TAG('O','R','O',' ')}, /* West Central Oromo -> Oromo */
- {"gbm", HB_TAG('G','A','W',' ')}, /* Garhwali */
- {"gce", HB_TAG('A','T','H',' ')}, /* Galice -> Athapaskan */
- {"gcf", HB_TAG('C','P','P',' ')}, /* Guadeloupean Creole French -> Creoles */
- {"gcl", HB_TAG('C','P','P',' ')}, /* Grenadian Creole English -> Creoles */
- {"gcr", HB_TAG('C','P','P',' ')}, /* Guianese Creole French -> Creoles */
- {"gd", HB_TAG('G','A','E',' ')}, /* Scottish Gaelic (Gaelic) */
- {"gda", HB_TAG('R','A','J',' ')}, /* Gade Lohar -> Rajasthani */
-/*{"gez", HB_TAG('G','E','Z',' ')},*/ /* Geez */
- {"ggo", HB_TAG('G','O','N',' ')}, /* Southern Gondi (retired code) -> Gondi */
- {"gha", HB_TAG('B','B','R',' ')}, /* Ghadamès -> Berber */
- {"ghk", HB_TAG('K','R','N',' ')}, /* Geko Karen -> Karen */
- {"gho", HB_TAG('B','B','R',' ')}, /* Ghomara -> Berber */
- {"gib", HB_TAG('C','P','P',' ')}, /* Gibanawa -> Creoles */
-/*{"gih", HB_TAG('G','I','H',' ')},*/ /* Githabul */
- {"gil", HB_TAG('G','I','L','0')}, /* Kiribati (Gilbertese) */
- {"gju", HB_TAG('R','A','J',' ')}, /* Gujari -> Rajasthani */
- {"gkp", HB_TAG('G','K','P',' ')}, /* Guinea Kpelle -> Kpelle (Guinea) */
- {"gkp", HB_TAG('K','P','L',' ')}, /* Guinea Kpelle -> Kpelle */
- {"gl", HB_TAG('G','A','L',' ')}, /* Galician */
- {"gld", HB_TAG('N','A','N',' ')}, /* Nanai */
-/*{"glk", HB_TAG('G','L','K',' ')},*/ /* Gilaki */
- {"gmz", HB_TAG_NONE }, /* Mgbolizhia != Gumuz */
- {"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */
- {"gnb", HB_TAG('Q','I','N',' ')}, /* Gangte -> Chin */
-/*{"gnn", HB_TAG('G','N','N',' ')},*/ /* Gumatj */
- {"gno", HB_TAG('G','O','N',' ')}, /* Northern Gondi -> Gondi */
- {"gnw", HB_TAG('G','U','A',' ')}, /* Western Bolivian Guaraní -> Guarani */
-/*{"gog", HB_TAG('G','O','G',' ')},*/ /* Gogo */
- {"gom", HB_TAG('K','O','K',' ')}, /* Goan Konkani -> Konkani */
-/*{"gon", HB_TAG('G','O','N',' ')},*/ /* Gondi [macrolanguage] */
- {"goq", HB_TAG('C','P','P',' ')}, /* Gorap -> Creoles */
- {"gox", HB_TAG('B','A','D','0')}, /* Gobu -> Banda */
- {"gpe", HB_TAG('C','P','P',' ')}, /* Ghanaian Pidgin English -> Creoles */
- {"gro", HB_TAG_NONE }, /* Groma != Garo */
- {"grr", HB_TAG('B','B','R',' ')}, /* Taznatit -> Berber */
- {"grt", HB_TAG('G','R','O',' ')}, /* Garo */
- {"gru", HB_TAG('S','O','G',' ')}, /* Kistane -> Sodo Gurage */
- {"gsw", HB_TAG('A','L','S',' ')}, /* Alsatian */
- {"gu", HB_TAG('G','U','J',' ')}, /* Gujarati */
- {"gua", HB_TAG_NONE }, /* Shiki != Guarani */
-/*{"guc", HB_TAG('G','U','C',' ')},*/ /* Wayuu */
-/*{"guf", HB_TAG('G','U','F',' ')},*/ /* Gupapuyngu */
- {"gug", HB_TAG('G','U','A',' ')}, /* Paraguayan Guaraní -> Guarani */
- {"gui", HB_TAG('G','U','A',' ')}, /* Eastern Bolivian Guaraní -> Guarani */
- {"guk", HB_TAG('G','M','Z',' ')}, /* Gumuz */
- {"gul", HB_TAG('C','P','P',' ')}, /* Sea Island Creole English -> Creoles */
- {"gun", HB_TAG('G','U','A',' ')}, /* Mbyá Guaraní -> Guarani */
-/*{"guz", HB_TAG('G','U','Z',' ')},*/ /* Gusii */
- {"gv", HB_TAG('M','N','X',' ')}, /* Manx */
- {"gwi", HB_TAG('A','T','H',' ')}, /* Gwichʼin -> Athapaskan */
- {"gyn", HB_TAG('C','P','P',' ')}, /* Guyanese Creole English -> Creoles */
- {"ha", HB_TAG('H','A','U',' ')}, /* Hausa */
- {"haa", HB_TAG('A','T','H',' ')}, /* Han -> Athapaskan */
- {"hae", HB_TAG('O','R','O',' ')}, /* Eastern Oromo -> Oromo */
- {"hai", HB_TAG('H','A','I','0')}, /* Haida [macrolanguage] */
- {"hak", HB_TAG('Z','H','S',' ')}, /* Hakka Chinese -> Chinese, Simplified */
- {"hal", HB_TAG_NONE }, /* Halang != Halam (Falam Chin) */
- {"har", HB_TAG('H','R','I',' ')}, /* Harari */
-/*{"haw", HB_TAG('H','A','W',' ')},*/ /* Hawaiian */
- {"hax", HB_TAG('H','A','I','0')}, /* Southern Haida -> Haida */
-/*{"hay", HB_TAG('H','A','Y',' ')},*/ /* Haya */
-/*{"haz", HB_TAG('H','A','Z',' ')},*/ /* Hazaragi */
- {"hbn", HB_TAG_NONE }, /* Heiban != Hammer-Banna */
- {"hca", HB_TAG('C','P','P',' ')}, /* Andaman Creole Hindi -> Creoles */
- {"hdn", HB_TAG('H','A','I','0')}, /* Northern Haida -> Haida */
- {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */
- {"hea", HB_TAG('H','M','N',' ')}, /* Northern Qiandong Miao -> Hmong */
-/*{"hei", HB_TAG('H','E','I',' ')},*/ /* Heiltsuk */
- {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */
-/*{"hil", HB_TAG('H','I','L',' ')},*/ /* Hiligaynon */
- {"hji", HB_TAG('M','L','Y',' ')}, /* Haji -> Malay */
- {"hlt", HB_TAG('Q','I','N',' ')}, /* Matu Chin -> Chin */
- {"hma", HB_TAG('H','M','N',' ')}, /* Southern Mashan Hmong -> Hmong */
- {"hmc", HB_TAG('H','M','N',' ')}, /* Central Huishui Hmong -> Hmong */
- {"hmd", HB_TAG('H','M','D',' ')}, /* Large Flowery Miao -> A-Hmao */
- {"hmd", HB_TAG('H','M','N',' ')}, /* Large Flowery Miao -> Hmong */
- {"hme", HB_TAG('H','M','N',' ')}, /* Eastern Huishui Hmong -> Hmong */
- {"hmg", HB_TAG('H','M','N',' ')}, /* Southwestern Guiyang Hmong -> Hmong */
- {"hmh", HB_TAG('H','M','N',' ')}, /* Southwestern Huishui Hmong -> Hmong */
- {"hmi", HB_TAG('H','M','N',' ')}, /* Northern Huishui Hmong -> Hmong */
- {"hmj", HB_TAG('H','M','N',' ')}, /* Ge -> Hmong */
- {"hml", HB_TAG('H','M','N',' ')}, /* Luopohe Hmong -> Hmong */
- {"hmm", HB_TAG('H','M','N',' ')}, /* Central Mashan Hmong -> Hmong */
-/*{"hmn", HB_TAG('H','M','N',' ')},*/ /* Hmong [macrolanguage] */
- {"hmp", HB_TAG('H','M','N',' ')}, /* Northern Mashan Hmong -> Hmong */
- {"hmq", HB_TAG('H','M','N',' ')}, /* Eastern Qiandong Miao -> Hmong */
- {"hmr", HB_TAG('Q','I','N',' ')}, /* Hmar -> Chin */
- {"hms", HB_TAG('H','M','N',' ')}, /* Southern Qiandong Miao -> Hmong */
- {"hmw", HB_TAG('H','M','N',' ')}, /* Western Mashan Hmong -> Hmong */
- {"hmy", HB_TAG('H','M','N',' ')}, /* Southern Guiyang Hmong -> Hmong */
- {"hmz", HB_TAG('H','M','Z',' ')}, /* Hmong Shua -> Hmong Shuat */
- {"hmz", HB_TAG('H','M','N',' ')}, /* Hmong Shua -> Hmong */
-/*{"hnd", HB_TAG('H','N','D',' ')},*/ /* Southern Hindko -> Hindko */
- {"hne", HB_TAG('C','H','H',' ')}, /* Chhattisgarhi -> Chattisgarhi */
- {"hnj", HB_TAG('H','M','N',' ')}, /* Hmong Njua -> Hmong */
- {"hno", HB_TAG('H','N','D',' ')}, /* Northern Hindko -> Hindko */
- {"ho", HB_TAG('H','M','O',' ')}, /* Hiri Motu */
- {"ho", HB_TAG('C','P','P',' ')}, /* Hiri Motu -> Creoles */
- {"hoc", HB_TAG('H','O',' ',' ')}, /* Ho */
- {"hoi", HB_TAG('A','T','H',' ')}, /* Holikachuk -> Athapaskan */
- {"hoj", HB_TAG('H','A','R',' ')}, /* Hadothi -> Harauti */
- {"hoj", HB_TAG('R','A','J',' ')}, /* Hadothi -> Rajasthani */
- {"hr", HB_TAG('H','R','V',' ')}, /* Croatian */
- {"hra", HB_TAG('Q','I','N',' ')}, /* Hrangkhol -> Chin */
- {"hrm", HB_TAG('H','M','N',' ')}, /* Horned Miao -> Hmong */
- {"hsb", HB_TAG('U','S','B',' ')}, /* Upper Sorbian */
- {"hsn", HB_TAG('Z','H','S',' ')}, /* Xiang Chinese -> Chinese, Simplified */
- {"ht", HB_TAG('H','A','I',' ')}, /* Haitian (Haitian Creole) */
- {"ht", HB_TAG('C','P','P',' ')}, /* Haitian -> Creoles */
- {"hu", HB_TAG('H','U','N',' ')}, /* Hungarian */
- {"huj", HB_TAG('H','M','N',' ')}, /* Northern Guiyang Hmong -> Hmong */
- {"hup", HB_TAG('A','T','H',' ')}, /* Hupa -> Athapaskan */
- {"hus", HB_TAG('M','Y','N',' ')}, /* Huastec -> Mayan */
- {"hwc", HB_TAG('C','P','P',' ')}, /* Hawai'i Creole English -> Creoles */
- {"hy", HB_TAG('H','Y','E','0')}, /* Armenian -> Armenian East */
- {"hy", HB_TAG('H','Y','E',' ')}, /* Armenian */
- {"hyw", HB_TAG('H','Y','E',' ')}, /* Western Armenian -> Armenian */
- {"hz", HB_TAG('H','E','R',' ')}, /* Herero */
- {"ia", HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */
-/*{"iba", HB_TAG('I','B','A',' ')},*/ /* Iban */
-/*{"ibb", HB_TAG('I','B','B',' ')},*/ /* Ibibio */
- {"iby", HB_TAG('I','J','O',' ')}, /* Ibani -> Ijo */
- {"icr", HB_TAG('C','P','P',' ')}, /* Islander Creole English -> Creoles */
- {"id", HB_TAG('I','N','D',' ')}, /* Indonesian */
- {"id", HB_TAG('M','L','Y',' ')}, /* Indonesian -> Malay */
- {"ida", HB_TAG('L','U','H',' ')}, /* Idakho-Isukha-Tiriki -> Luyia */
- {"idb", HB_TAG('C','P','P',' ')}, /* Indo-Portuguese -> Creoles */
- {"ie", HB_TAG('I','L','E',' ')}, /* Interlingue */
- {"ig", HB_TAG('I','B','O',' ')}, /* Igbo */
- {"igb", HB_TAG('E','B','I',' ')}, /* Ebira */
- {"ihb", HB_TAG('C','P','P',' ')}, /* Iha Based Pidgin -> Creoles */
- {"ii", HB_TAG('Y','I','M',' ')}, /* Sichuan Yi -> Yi Modern */
- {"ijc", HB_TAG('I','J','O',' ')}, /* Izon -> Ijo */
- {"ije", HB_TAG('I','J','O',' ')}, /* Biseni -> Ijo */
- {"ijn", HB_TAG('I','J','O',' ')}, /* Kalabari -> Ijo */
-/*{"ijo", HB_TAG('I','J','O',' ')},*/ /* Ijo [collection] */
- {"ijs", HB_TAG('I','J','O',' ')}, /* Southeast Ijo -> Ijo */
- {"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] -> Inupiat */
- {"ike", HB_TAG('I','N','U',' ')}, /* Eastern Canadian Inuktitut -> Inuktitut */
- {"ike", HB_TAG('I','N','U','K')}, /* Eastern Canadian Inuktitut -> Nunavik Inuktitut */
- {"ikt", HB_TAG('I','N','U',' ')}, /* Inuinnaqtun -> Inuktitut */
-/*{"ilo", HB_TAG('I','L','O',' ')},*/ /* Iloko -> Ilokano */
- {"in", HB_TAG('I','N','D',' ')}, /* Indonesian (retired code) */
- {"in", HB_TAG('M','L','Y',' ')}, /* Indonesian (retired code) -> Malay */
- {"ing", HB_TAG('A','T','H',' ')}, /* Degexit'an -> Athapaskan */
- {"inh", HB_TAG('I','N','G',' ')}, /* Ingush */
- {"io", HB_TAG('I','D','O',' ')}, /* Ido */
- {"iri", HB_TAG_NONE }, /* Rigwe != Irish */
-/*{"iru", HB_TAG('I','R','U',' ')},*/ /* Irula */
- {"is", HB_TAG('I','S','L',' ')}, /* Icelandic */
- {"ism", HB_TAG_NONE }, /* Masimasi != Inari Sami */
- {"it", HB_TAG('I','T','A',' ')}, /* Italian */
- {"itz", HB_TAG('M','Y','N',' ')}, /* Itzá -> Mayan */
- {"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */
- {"iu", HB_TAG('I','N','U','K')}, /* Inuktitut [macrolanguage] -> Nunavik Inuktitut */
- {"iw", HB_TAG('I','W','R',' ')}, /* Hebrew (retired code) */
- {"ixl", HB_TAG('M','Y','N',' ')}, /* Ixil -> Mayan */
- {"ja", HB_TAG('J','A','N',' ')}, /* Japanese */
- {"jac", HB_TAG('M','Y','N',' ')}, /* Popti' -> Mayan */
- {"jak", HB_TAG('M','L','Y',' ')}, /* Jakun -> Malay */
- {"jam", HB_TAG('J','A','M',' ')}, /* Jamaican Creole English -> Jamaican Creole */
- {"jam", HB_TAG('C','P','P',' ')}, /* Jamaican Creole English -> Creoles */
- {"jan", HB_TAG_NONE }, /* Jandai != Japanese */
- {"jax", HB_TAG('M','L','Y',' ')}, /* Jambi Malay -> Malay */
- {"jbe", HB_TAG('B','B','R',' ')}, /* Judeo-Berber -> Berber */
- {"jbn", HB_TAG('B','B','R',' ')}, /* Nafusi -> Berber */
-/*{"jbo", HB_TAG('J','B','O',' ')},*/ /* Lojban */
-/*{"jct", HB_TAG('J','C','T',' ')},*/ /* Krymchak */
- {"jgo", HB_TAG('B','M','L',' ')}, /* Ngomba -> Bamileke */
- {"ji", HB_TAG('J','I','I',' ')}, /* Yiddish (retired code) */
- {"jii", HB_TAG_NONE }, /* Jiiddu != Yiddish */
- {"jkm", HB_TAG('K','R','N',' ')}, /* Mobwa Karen -> Karen */
- {"jkp", HB_TAG('K','R','N',' ')}, /* Paku Karen -> Karen */
- {"jud", HB_TAG_NONE }, /* Worodougou != Ladino */
- {"jul", HB_TAG_NONE }, /* Jirel != Jula */
- {"jv", HB_TAG('J','A','V',' ')}, /* Javanese */
- {"jvd", HB_TAG('C','P','P',' ')}, /* Javindo -> Creoles */
- {"jw", HB_TAG('J','A','V',' ')}, /* Javanese (retired code) */
- {"ka", HB_TAG('K','A','T',' ')}, /* Georgian */
- {"kaa", HB_TAG('K','R','K',' ')}, /* Karakalpak */
- {"kab", HB_TAG('K','A','B','0')}, /* Kabyle */
- {"kab", HB_TAG('B','B','R',' ')}, /* Kabyle -> Berber */
- {"kac", HB_TAG_NONE }, /* Kachin != Kachchi */
- {"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
- {"kar", HB_TAG('K','R','N',' ')}, /* Karen [collection] */
-/*{"kaw", HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */
- {"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */
- {"kby", HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */
- {"kca", HB_TAG('K','H','K',' ')}, /* Khanty -> Khanty-Kazim */
- {"kca", HB_TAG('K','H','S',' ')}, /* Khanty -> Khanty-Shurishkar */
- {"kca", HB_TAG('K','H','V',' ')}, /* Khanty -> Khanty-Vakhi */
- {"kcn", HB_TAG('C','P','P',' ')}, /* Nubi -> Creoles */
-/*{"kde", HB_TAG('K','D','E',' ')},*/ /* Makonde */
- {"kdr", HB_TAG('K','R','M',' ')}, /* Karaim */
- {"kdt", HB_TAG('K','U','Y',' ')}, /* Kuy */
- {"kea", HB_TAG('K','E','A',' ')}, /* Kabuverdianu (Crioulo) */
- {"kea", HB_TAG('C','P','P',' ')}, /* Kabuverdianu -> Creoles */
- {"keb", HB_TAG_NONE }, /* Kélé != Kebena */
- {"kek", HB_TAG('K','E','K',' ')}, /* Kekchi */
- {"kek", HB_TAG('M','Y','N',' ')}, /* Kekchí -> Mayan */
- {"kex", HB_TAG('K','K','N',' ')}, /* Kukna -> Kokni */
- {"kfa", HB_TAG('K','O','D',' ')}, /* Kodava -> Kodagu */
- {"kfr", HB_TAG('K','A','C',' ')}, /* Kachhi -> Kachchi */
- {"kfx", HB_TAG('K','U','L',' ')}, /* Kullu Pahari -> Kulvi */
- {"kfy", HB_TAG('K','M','N',' ')}, /* Kumaoni */
- {"kg", HB_TAG('K','O','N','0')}, /* Kongo [macrolanguage] */
- {"kge", HB_TAG_NONE }, /* Komering != Khutsuri Georgian */
- {"kha", HB_TAG('K','S','I',' ')}, /* Khasi */
- {"khb", HB_TAG('X','B','D',' ')}, /* Lü */
- {"khk", HB_TAG('M','N','G',' ')}, /* Halh Mongolian -> Mongolian */
- {"khn", HB_TAG_NONE }, /* Khandesi != Khamti Shan (Microsoft fonts) */
- {"khs", HB_TAG_NONE }, /* Kasua != Khanty-Shurishkar */
- {"kht", HB_TAG('K','H','T',' ')}, /* Khamti -> Khamti Shan */
- {"kht", HB_TAG('K','H','N',' ')}, /* Khamti -> Khamti Shan (Microsoft fonts) */
- {"khv", HB_TAG_NONE }, /* Khvarshi != Khanty-Vakhi */
-/*{"khw", HB_TAG('K','H','W',' ')},*/ /* Khowar */
- {"ki", HB_TAG('K','I','K',' ')}, /* Kikuyu (Gikuyu) */
- {"kis", HB_TAG_NONE }, /* Kis != Kisii */
- {"kiu", HB_TAG('K','I','U',' ')}, /* Kirmanjki */
- {"kiu", HB_TAG('Z','Z','A',' ')}, /* Kirmanjki -> Zazaki */
- {"kj", HB_TAG('K','U','A',' ')}, /* Kuanyama */
- {"kjb", HB_TAG('M','Y','N',' ')}, /* Q'anjob'al -> Mayan */
-/*{"kjd", HB_TAG('K','J','D',' ')},*/ /* Southern Kiwai */
- {"kjh", HB_TAG('K','H','A',' ')}, /* Khakas -> Khakass */
- {"kjp", HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen -> Eastern Pwo Karen */
- {"kjp", HB_TAG('K','R','N',' ')}, /* Pwo Eastern Karen -> Karen */
- {"kjt", HB_TAG('K','R','N',' ')}, /* Phrae Pwo Karen -> Karen */
-/*{"kjz", HB_TAG('K','J','Z',' ')},*/ /* Bumthangkha */
- {"kk", HB_TAG('K','A','Z',' ')}, /* Kazakh */
- {"kkn", HB_TAG_NONE }, /* Kon Keu != Kokni */
- {"kkz", HB_TAG('A','T','H',' ')}, /* Kaska -> Athapaskan */
- {"kl", HB_TAG('G','R','N',' ')}, /* Greenlandic */
- {"klm", HB_TAG_NONE }, /* Migum != Kalmyk */
- {"kln", HB_TAG('K','A','L',' ')}, /* Kalenjin [macrolanguage] */
- {"km", HB_TAG('K','H','M',' ')}, /* Khmer */
- {"kmb", HB_TAG('M','B','N',' ')}, /* Kimbundu -> Mbundu */
- {"kmn", HB_TAG_NONE }, /* Awtuw != Kumaoni */
- {"kmo", HB_TAG_NONE }, /* Kwoma != Komo */
- {"kmr", HB_TAG('K','U','R',' ')}, /* Northern Kurdish -> Kurdish */
- {"kms", HB_TAG_NONE }, /* Kamasau != Komso */
- {"kmv", HB_TAG('C','P','P',' ')}, /* Karipúna Creole French -> Creoles */
- {"kmw", HB_TAG('K','M','O',' ')}, /* Komo (Democratic Republic of Congo) */
-/*{"kmz", HB_TAG('K','M','Z',' ')},*/ /* Khorasani Turkish -> Khorasani Turkic */
- {"kn", HB_TAG('K','A','N',' ')}, /* Kannada */
- {"knc", HB_TAG('K','N','R',' ')}, /* Central Kanuri -> Kanuri */
- {"kng", HB_TAG('K','O','N','0')}, /* Koongo -> Kongo */
- {"knj", HB_TAG('M','Y','N',' ')}, /* Western Kanjobal -> Mayan */
- {"knn", HB_TAG('K','O','K',' ')}, /* Konkani */
- {"knr", HB_TAG_NONE }, /* Kaningra != Kanuri */
- {"ko", HB_TAG('K','O','R',' ')}, /* Korean */
- {"ko", HB_TAG('K','O','H',' ')}, /* Korean -> Korean Old Hangul */
- {"kod", HB_TAG_NONE }, /* Kodi != Kodagu */
- {"koh", HB_TAG_NONE }, /* Koyo != Korean Old Hangul */
- {"koi", HB_TAG('K','O','P',' ')}, /* Komi-Permyak */
- {"koi", HB_TAG('K','O','M',' ')}, /* Komi-Permyak -> Komi */
-/*{"kok", HB_TAG('K','O','K',' ')},*/ /* Konkani [macrolanguage] */
- {"kop", HB_TAG_NONE }, /* Waube != Komi-Permyak */
-/*{"kos", HB_TAG('K','O','S',' ')},*/ /* Kosraean */
- {"koy", HB_TAG('A','T','H',' ')}, /* Koyukon -> Athapaskan */
- {"koz", HB_TAG_NONE }, /* Korak != Komi-Zyrian */
- {"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */
- {"kpl", HB_TAG_NONE }, /* Kpala != Kpelle */
- {"kpp", HB_TAG('K','R','N',' ')}, /* Paku Karen (retired code) -> Karen */
- {"kpv", HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */
- {"kpv", HB_TAG('K','O','M',' ')}, /* Komi-Zyrian -> Komi */
- {"kpy", HB_TAG('K','Y','K',' ')}, /* Koryak */
- {"kqs", HB_TAG('K','I','S',' ')}, /* Northern Kissi -> Kisii */
- {"kqy", HB_TAG('K','R','T',' ')}, /* Koorete */
- {"kr", HB_TAG('K','N','R',' ')}, /* Kanuri [macrolanguage] */
- {"krc", HB_TAG('K','A','R',' ')}, /* Karachay-Balkar -> Karachay */
- {"krc", HB_TAG('B','A','L',' ')}, /* Karachay-Balkar -> Balkar */
- {"kri", HB_TAG('K','R','I',' ')}, /* Krio */
- {"kri", HB_TAG('C','P','P',' ')}, /* Krio -> Creoles */
- {"krk", HB_TAG_NONE }, /* Kerek != Karakalpak */
-/*{"krl", HB_TAG('K','R','L',' ')},*/ /* Karelian */
- {"krm", HB_TAG_NONE }, /* Krim (retired code) != Karaim */
- {"krn", HB_TAG_NONE }, /* Sapo != Karen */
- {"krt", HB_TAG('K','N','R',' ')}, /* Tumari Kanuri -> Kanuri */
- {"kru", HB_TAG('K','U','U',' ')}, /* Kurukh */
- {"ks", HB_TAG('K','S','H',' ')}, /* Kashmiri */
- {"ksh", HB_TAG('K','S','H','0')}, /* Kölsch -> Ripuarian */
- {"ksi", HB_TAG_NONE }, /* Krisa != Khasi */
- {"ksm", HB_TAG_NONE }, /* Kumba != Kildin Sami */
- {"kss", HB_TAG('K','I','S',' ')}, /* Southern Kisi -> Kisii */
- {"ksw", HB_TAG('K','S','W',' ')}, /* S’gaw Karen */
- {"ksw", HB_TAG('K','R','N',' ')}, /* S'gaw Karen -> Karen */
- {"ktb", HB_TAG('K','E','B',' ')}, /* Kambaata -> Kebena */
- {"ktu", HB_TAG('K','O','N',' ')}, /* Kituba (Democratic Republic of Congo) -> Kikongo */
- {"ktw", HB_TAG('A','T','H',' ')}, /* Kato -> Athapaskan */
- {"ku", HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */
- {"kui", HB_TAG_NONE }, /* Kuikúro-Kalapálo != Kui */
- {"kul", HB_TAG_NONE }, /* Kulere != Kulvi */
-/*{"kum", HB_TAG('K','U','M',' ')},*/ /* Kumyk */
- {"kuu", HB_TAG('A','T','H',' ')}, /* Upper Kuskokwim -> Athapaskan */
- {"kuw", HB_TAG('B','A','D','0')}, /* Kpagua -> Banda */
- {"kuy", HB_TAG_NONE }, /* Kuuku-Ya'u != Kuy */
- {"kv", HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */
- {"kvb", HB_TAG('M','L','Y',' ')}, /* Kubu -> Malay */
- {"kvl", HB_TAG('K','R','N',' ')}, /* Kayaw -> Karen */
- {"kvq", HB_TAG('K','R','N',' ')}, /* Geba Karen -> Karen */
- {"kvr", HB_TAG('M','L','Y',' ')}, /* Kerinci -> Malay */
- {"kvt", HB_TAG('K','R','N',' ')}, /* Lahta Karen -> Karen */
- {"kvu", HB_TAG('K','R','N',' ')}, /* Yinbaw Karen -> Karen */
- {"kvy", HB_TAG('K','R','N',' ')}, /* Yintale Karen -> Karen */
- {"kw", HB_TAG('C','O','R',' ')}, /* Cornish */
-/*{"kwk", HB_TAG('K','W','K',' ')},*/ /* Kwakiutl -> Kwakʼwala */
- {"kww", HB_TAG('C','P','P',' ')}, /* Kwinti -> Creoles */
- {"kwy", HB_TAG('K','O','N','0')}, /* San Salvador Kongo -> Kongo */
- {"kxc", HB_TAG('K','M','S',' ')}, /* Konso -> Komso */
- {"kxd", HB_TAG('M','L','Y',' ')}, /* Brunei -> Malay */
- {"kxf", HB_TAG('K','R','N',' ')}, /* Manumanaw Karen -> Karen */
- {"kxk", HB_TAG('K','R','N',' ')}, /* Zayein Karen -> Karen */
- {"kxl", HB_TAG('K','U','U',' ')}, /* Nepali Kurux (retired code) -> Kurukh */
- {"kxu", HB_TAG('K','U','I',' ')}, /* Kui (India) (retired code) */
- {"ky", HB_TAG('K','I','R',' ')}, /* Kirghiz (Kyrgyz) */
- {"kyk", HB_TAG_NONE }, /* Kamayo != Koryak */
- {"kyu", HB_TAG('K','Y','U',' ')}, /* Western Kayah */
- {"kyu", HB_TAG('K','R','N',' ')}, /* Western Kayah -> Karen */
- {"la", HB_TAG('L','A','T',' ')}, /* Latin */
- {"lac", HB_TAG('M','Y','N',' ')}, /* Lacandon -> Mayan */
- {"lad", HB_TAG('J','U','D',' ')}, /* Ladino */
- {"lah", HB_TAG_NONE }, /* Lahnda [macrolanguage] != Lahuli */
- {"lak", HB_TAG_NONE }, /* Laka (Nigeria) (retired code) != Lak */
- {"lam", HB_TAG_NONE }, /* Lamba != Lambani */
- {"laz", HB_TAG_NONE }, /* Aribwatsa != Laz */
- {"lb", HB_TAG('L','T','Z',' ')}, /* Luxembourgish */
- {"lbe", HB_TAG('L','A','K',' ')}, /* Lak */
- {"lbj", HB_TAG('L','D','K',' ')}, /* Ladakhi */
- {"lbl", HB_TAG('B','I','K',' ')}, /* Libon Bikol -> Bikol */
- {"lce", HB_TAG('M','L','Y',' ')}, /* Loncong -> Malay */
- {"lcf", HB_TAG('M','L','Y',' ')}, /* Lubu -> Malay */
- {"ldi", HB_TAG('K','O','N','0')}, /* Laari -> Kongo */
- {"ldk", HB_TAG_NONE }, /* Leelau != Ladakhi */
-/*{"lef", HB_TAG('L','E','F',' ')},*/ /* Lelemi */
-/*{"lez", HB_TAG('L','E','Z',' ')},*/ /* Lezghian -> Lezgi */
- {"lg", HB_TAG('L','U','G',' ')}, /* Ganda */
- {"li", HB_TAG('L','I','M',' ')}, /* Limburgish */
- {"lif", HB_TAG('L','M','B',' ')}, /* Limbu */
-/*{"lij", HB_TAG('L','I','J',' ')},*/ /* Ligurian */
- {"lir", HB_TAG('C','P','P',' ')}, /* Liberian English -> Creoles */
-/*{"lis", HB_TAG('L','I','S',' ')},*/ /* Lisu */
- {"liw", HB_TAG('M','L','Y',' ')}, /* Col -> Malay */
- {"liy", HB_TAG('B','A','D','0')}, /* Banda-Bambari -> Banda */
-/*{"ljp", HB_TAG('L','J','P',' ')},*/ /* Lampung Api -> Lampung */
- {"lkb", HB_TAG('L','U','H',' ')}, /* Kabras -> Luyia */
-/*{"lki", HB_TAG('L','K','I',' ')},*/ /* Laki */
- {"lko", HB_TAG('L','U','H',' ')}, /* Khayo -> Luyia */
- {"lks", HB_TAG('L','U','H',' ')}, /* Kisa -> Luyia */
- {"lld", HB_TAG('L','A','D',' ')}, /* Ladin */
- {"lma", HB_TAG_NONE }, /* East Limba != Low Mari */
- {"lmb", HB_TAG_NONE }, /* Merei != Limbu */
- {"lmn", HB_TAG('L','A','M',' ')}, /* Lambadi -> Lambani */
-/*{"lmo", HB_TAG('L','M','O',' ')},*/ /* Lombard */
- {"lmw", HB_TAG_NONE }, /* Lake Miwok != Lomwe */
- {"ln", HB_TAG('L','I','N',' ')}, /* Lingala */
- {"lna", HB_TAG('B','A','D','0')}, /* Langbashe -> Banda */
- {"lnl", HB_TAG('B','A','D','0')}, /* South Central Banda -> Banda */
- {"lo", HB_TAG('L','A','O',' ')}, /* Lao */
-/*{"lom", HB_TAG('L','O','M',' ')},*/ /* Loma (Liberia) */
- {"lou", HB_TAG('C','P','P',' ')}, /* Louisiana Creole -> Creoles */
-/*{"lpo", HB_TAG('L','P','O',' ')},*/ /* Lipo */
-/*{"lrc", HB_TAG('L','R','C',' ')},*/ /* Northern Luri -> Luri */
- {"lri", HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */
- {"lrm", HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */
- {"lrt", HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */
- {"lsb", HB_TAG_NONE }, /* Burundian Sign Language != Lower Sorbian */
- {"lsm", HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */
- {"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */
- {"ltg", HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */
- {"lth", HB_TAG_NONE }, /* Thur != Lithuanian */
- {"lto", HB_TAG('L','U','H',' ')}, /* Tsotso -> Luyia */
- {"lts", HB_TAG('L','U','H',' ')}, /* Tachoni -> Luyia */
- {"lu", HB_TAG('L','U','B',' ')}, /* Luba-Katanga */
-/*{"lua", HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */
-/*{"luo", HB_TAG('L','U','O',' ')},*/ /* Luo (Kenya and Tanzania) */
- {"lus", HB_TAG('M','I','Z',' ')}, /* Lushai -> Mizo */
- {"lus", HB_TAG('Q','I','N',' ')}, /* Lushai -> Chin */
- {"luy", HB_TAG('L','U','H',' ')}, /* Luyia [macrolanguage] */
- {"luz", HB_TAG('L','R','C',' ')}, /* Southern Luri -> Luri */
- {"lv", HB_TAG('L','V','I',' ')}, /* Latvian [macrolanguage] */
- {"lvi", HB_TAG_NONE }, /* Lavi != Latvian */
- {"lvs", HB_TAG('L','V','I',' ')}, /* Standard Latvian -> Latvian */
- {"lwg", HB_TAG('L','U','H',' ')}, /* Wanga -> Luyia */
- {"lzh", HB_TAG('Z','H','T',' ')}, /* Literary Chinese -> Chinese, Traditional */
- {"lzz", HB_TAG('L','A','Z',' ')}, /* Laz */
-/*{"mad", HB_TAG('M','A','D',' ')},*/ /* Madurese -> Madura */
-/*{"mag", HB_TAG('M','A','G',' ')},*/ /* Magahi */
- {"mai", HB_TAG('M','T','H',' ')}, /* Maithili */
- {"maj", HB_TAG_NONE }, /* Jalapa De Díaz Mazatec != Majang */
- {"mak", HB_TAG('M','K','R',' ')}, /* Makasar */
- {"mam", HB_TAG('M','A','M',' ')}, /* Mam */
- {"mam", HB_TAG('M','Y','N',' ')}, /* Mam -> Mayan */
- {"man", HB_TAG('M','N','K',' ')}, /* Mandingo [macrolanguage] -> Maninka */
- {"map", HB_TAG_NONE }, /* Austronesian [collection] != Mapudungun */
- {"maw", HB_TAG_NONE }, /* Mampruli != Marwari */
- {"max", HB_TAG('M','L','Y',' ')}, /* North Moluccan Malay -> Malay */
- {"max", HB_TAG('C','P','P',' ')}, /* North Moluccan Malay -> Creoles */
- {"mbf", HB_TAG('C','P','P',' ')}, /* Baba Malay -> Creoles */
- {"mbn", HB_TAG_NONE }, /* Macaguán != Mbundu */
-/*{"mbo", HB_TAG('M','B','O',' ')},*/ /* Mbo (Cameroon) */
- {"mch", HB_TAG_NONE }, /* Maquiritari != Manchu */
- {"mcm", HB_TAG('C','P','P',' ')}, /* Malaccan Creole Portuguese -> Creoles */
- {"mcr", HB_TAG_NONE }, /* Menya != Moose Cree */
- {"mct", HB_TAG('B','T','I',' ')}, /* Mengisa -> Beti */
- {"mde", HB_TAG_NONE }, /* Maba (Chad) != Mende */
- {"mdf", HB_TAG('M','O','K',' ')}, /* Moksha */
-/*{"mdr", HB_TAG('M','D','R',' ')},*/ /* Mandar */
- {"mdy", HB_TAG('M','L','E',' ')}, /* Male (Ethiopia) */
- {"men", HB_TAG('M','D','E',' ')}, /* Mende (Sierra Leone) */
- {"meo", HB_TAG('M','L','Y',' ')}, /* Kedah Malay -> Malay */
-/*{"mer", HB_TAG('M','E','R',' ')},*/ /* Meru */
- {"mfa", HB_TAG('M','F','A',' ')}, /* Pattani Malay */
- {"mfa", HB_TAG('M','L','Y',' ')}, /* Pattani Malay -> Malay */
- {"mfb", HB_TAG('M','L','Y',' ')}, /* Bangka -> Malay */
- {"mfe", HB_TAG('M','F','E',' ')}, /* Morisyen */
- {"mfe", HB_TAG('C','P','P',' ')}, /* Morisyen -> Creoles */
- {"mfp", HB_TAG('C','P','P',' ')}, /* Makassar Malay -> Creoles */
- {"mg", HB_TAG('M','L','G',' ')}, /* Malagasy [macrolanguage] */
- {"mh", HB_TAG('M','A','H',' ')}, /* Marshallese */
- {"mhc", HB_TAG('M','Y','N',' ')}, /* Mocho -> Mayan */
- {"mhr", HB_TAG('L','M','A',' ')}, /* Eastern Mari -> Low Mari */
- {"mhv", HB_TAG('A','R','K',' ')}, /* Arakanese (retired code) -> Rakhine */
- {"mi", HB_TAG('M','R','I',' ')}, /* Maori */
- {"min", HB_TAG('M','I','N',' ')}, /* Minangkabau */
- {"min", HB_TAG('M','L','Y',' ')}, /* Minangkabau -> Malay */
- {"miz", HB_TAG_NONE }, /* Coatzospan Mixtec != Mizo */
- {"mk", HB_TAG('M','K','D',' ')}, /* Macedonian */
- {"mkn", HB_TAG('C','P','P',' ')}, /* Kupang Malay -> Creoles */
- {"mkr", HB_TAG_NONE }, /* Malas != Makasar */
- {"mku", HB_TAG('M','N','K',' ')}, /* Konyanka Maninka -> Maninka */
-/*{"mkw", HB_TAG('M','K','W',' ')},*/ /* Kituba (Congo) */
- {"ml", HB_TAG('M','A','L',' ')}, /* Malayalam -> Malayalam Traditional */
- {"ml", HB_TAG('M','L','R',' ')}, /* Malayalam -> Malayalam Reformed */
- {"mle", HB_TAG_NONE }, /* Manambu != Male */
- {"mln", HB_TAG_NONE }, /* Malango != Malinke */
- {"mlq", HB_TAG('M','L','N',' ')}, /* Western Maninkakan -> Malinke */
- {"mlq", HB_TAG('M','N','K',' ')}, /* Western Maninkakan -> Maninka */
- {"mlr", HB_TAG_NONE }, /* Vame != Malayalam Reformed */
- {"mmr", HB_TAG('H','M','N',' ')}, /* Western Xiangxi Miao -> Hmong */
- {"mn", HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */
- {"mnc", HB_TAG('M','C','H',' ')}, /* Manchu */
- {"mnd", HB_TAG_NONE }, /* Mondé != Mandinka */
- {"mng", HB_TAG_NONE }, /* Eastern Mnong != Mongolian */
- {"mnh", HB_TAG('B','A','D','0')}, /* Mono (Democratic Republic of Congo) -> Banda */
-/*{"mni", HB_TAG('M','N','I',' ')},*/ /* Manipuri */
- {"mnk", HB_TAG('M','N','D',' ')}, /* Mandinka */
- {"mnk", HB_TAG('M','N','K',' ')}, /* Mandinka -> Maninka */
- {"mnp", HB_TAG('Z','H','S',' ')}, /* Min Bei Chinese -> Chinese, Simplified */
- {"mns", HB_TAG('M','A','N',' ')}, /* Mansi */
- {"mnw", HB_TAG('M','O','N',' ')}, /* Mon */
- {"mnw", HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */
- {"mnx", HB_TAG_NONE }, /* Manikion != Manx */
- {"mo", HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */
- {"mo", HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */
- {"mod", HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */
-/*{"moh", HB_TAG('M','O','H',' ')},*/ /* Mohawk */
- {"mok", HB_TAG_NONE }, /* Morori != Moksha */
- {"mop", HB_TAG('M','Y','N',' ')}, /* Mopán Maya -> Mayan */
- {"mor", HB_TAG_NONE }, /* Moro != Moroccan */
-/*{"mos", HB_TAG('M','O','S',' ')},*/ /* Mossi */
- {"mpe", HB_TAG('M','A','J',' ')}, /* Majang */
- {"mqg", HB_TAG('M','L','Y',' ')}, /* Kota Bangun Kutai Malay -> Malay */
- {"mr", HB_TAG('M','A','R',' ')}, /* Marathi */
- {"mrh", HB_TAG('Q','I','N',' ')}, /* Mara Chin -> Chin */
- {"mrj", HB_TAG('H','M','A',' ')}, /* Western Mari -> High Mari */
- {"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */
- {"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka -> Maninka */
- {"msh", HB_TAG('M','L','G',' ')}, /* Masikoro Malagasy -> Malagasy */
- {"msi", HB_TAG('M','L','Y',' ')}, /* Sabah Malay -> Malay */
- {"msi", HB_TAG('C','P','P',' ')}, /* Sabah Malay -> Creoles */
- {"mt", HB_TAG('M','T','S',' ')}, /* Maltese */
- {"mth", HB_TAG_NONE }, /* Munggui != Maithili */
- {"mtr", HB_TAG('M','A','W',' ')}, /* Mewari -> Marwari */
- {"mts", HB_TAG_NONE }, /* Yora != Maltese */
- {"mud", HB_TAG('C','P','P',' ')}, /* Mednyj Aleut -> Creoles */
- {"mui", HB_TAG('M','L','Y',' ')}, /* Musi -> Malay */
- {"mun", HB_TAG_NONE }, /* Munda [collection] != Mundari */
- {"mup", HB_TAG('R','A','J',' ')}, /* Malvi -> Rajasthani */
- {"muq", HB_TAG('H','M','N',' ')}, /* Eastern Xiangxi Miao -> Hmong */
-/*{"mus", HB_TAG('M','U','S',' ')},*/ /* Creek -> Muscogee */
- {"mvb", HB_TAG('A','T','H',' ')}, /* Mattole -> Athapaskan */
- {"mve", HB_TAG('M','A','W',' ')}, /* Marwari (Pakistan) */
- {"mvf", HB_TAG('M','N','G',' ')}, /* Peripheral Mongolian -> Mongolian */
- {"mwk", HB_TAG('M','N','K',' ')}, /* Kita Maninkakan -> Maninka */
-/*{"mwl", HB_TAG('M','W','L',' ')},*/ /* Mirandese */
- {"mwq", HB_TAG('Q','I','N',' ')}, /* Mün Chin -> Chin */
- {"mwr", HB_TAG('M','A','W',' ')}, /* Marwari [macrolanguage] */
- {"mww", HB_TAG('M','W','W',' ')}, /* Hmong Daw */
- {"mww", HB_TAG('H','M','N',' ')}, /* Hmong Daw -> Hmong */
- {"my", HB_TAG('B','R','M',' ')}, /* Burmese */
- {"mym", HB_TAG('M','E','N',' ')}, /* Me’en */
-/*{"myn", HB_TAG('M','Y','N',' ')},*/ /* Mayan [collection] */
- {"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) -> Maninka */
- {"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */
- {"mzb", HB_TAG('B','B','R',' ')}, /* Tumzabt -> Berber */
-/*{"mzn", HB_TAG('M','Z','N',' ')},*/ /* Mazanderani */
- {"mzs", HB_TAG('C','P','P',' ')}, /* Macanese -> Creoles */
- {"na", HB_TAG('N','A','U',' ')}, /* Nauru -> Nauruan */
- {"nag", HB_TAG('N','A','G',' ')}, /* Naga Pidgin -> Naga-Assamese */
- {"nag", HB_TAG('C','P','P',' ')}, /* Naga Pidgin -> Creoles */
-/*{"nah", HB_TAG('N','A','H',' ')},*/ /* Nahuatl [collection] */
- {"nan", HB_TAG('Z','H','S',' ')}, /* Min Nan Chinese -> Chinese, Simplified */
-/*{"nap", HB_TAG('N','A','P',' ')},*/ /* Neapolitan */
- {"nas", HB_TAG_NONE }, /* Naasioi != Naskapi */
- {"naz", HB_TAG('N','A','H',' ')}, /* Coatepec Nahuatl -> Nahuatl */
- {"nb", HB_TAG('N','O','R',' ')}, /* Norwegian Bokmål -> Norwegian */
- {"nch", HB_TAG('N','A','H',' ')}, /* Central Huasteca Nahuatl -> Nahuatl */
- {"nci", HB_TAG('N','A','H',' ')}, /* Classical Nahuatl -> Nahuatl */
- {"ncj", HB_TAG('N','A','H',' ')}, /* Northern Puebla Nahuatl -> Nahuatl */
- {"ncl", HB_TAG('N','A','H',' ')}, /* Michoacán Nahuatl -> Nahuatl */
- {"ncr", HB_TAG_NONE }, /* Ncane != N-Cree */
- {"ncx", HB_TAG('N','A','H',' ')}, /* Central Puebla Nahuatl -> Nahuatl */
- {"nd", HB_TAG('N','D','B',' ')}, /* North Ndebele -> Ndebele */
- {"ndb", HB_TAG_NONE }, /* Kenswei Nsei != Ndebele */
-/*{"ndc", HB_TAG('N','D','C',' ')},*/ /* Ndau */
- {"ndg", HB_TAG_NONE }, /* Ndengereko != Ndonga */
-/*{"nds", HB_TAG('N','D','S',' ')},*/ /* Low Saxon */
- {"ne", HB_TAG('N','E','P',' ')}, /* Nepali [macrolanguage] */
- {"nef", HB_TAG('C','P','P',' ')}, /* Nefamese -> Creoles */
-/*{"new", HB_TAG('N','E','W',' ')},*/ /* Newari */
- {"ng", HB_TAG('N','D','G',' ')}, /* Ndonga */
-/*{"nga", HB_TAG('N','G','A',' ')},*/ /* Ngbaka */
- {"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */
- {"ngm", HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */
- {"ngo", HB_TAG('S','X','T',' ')}, /* Ngoni (retired code) -> Sutu */
- {"ngr", HB_TAG_NONE }, /* Engdewu != Nagari */
- {"ngu", HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */
- {"nhc", HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */
- {"nhd", HB_TAG('G','U','A',' ')}, /* Chiripá -> Guarani */
- {"nhe", HB_TAG('N','A','H',' ')}, /* Eastern Huasteca Nahuatl -> Nahuatl */
- {"nhg", HB_TAG('N','A','H',' ')}, /* Tetelcingo Nahuatl -> Nahuatl */
- {"nhi", HB_TAG('N','A','H',' ')}, /* Zacatlán-Ahuacatlán-Tepetzintla Nahuatl -> Nahuatl */
- {"nhk", HB_TAG('N','A','H',' ')}, /* Isthmus-Cosoleacaque Nahuatl -> Nahuatl */
- {"nhm", HB_TAG('N','A','H',' ')}, /* Morelos Nahuatl -> Nahuatl */
- {"nhn", HB_TAG('N','A','H',' ')}, /* Central Nahuatl -> Nahuatl */
- {"nhp", HB_TAG('N','A','H',' ')}, /* Isthmus-Pajapan Nahuatl -> Nahuatl */
- {"nhq", HB_TAG('N','A','H',' ')}, /* Huaxcaleca Nahuatl -> Nahuatl */
- {"nht", HB_TAG('N','A','H',' ')}, /* Ometepec Nahuatl -> Nahuatl */
- {"nhv", HB_TAG('N','A','H',' ')}, /* Temascaltepec Nahuatl -> Nahuatl */
- {"nhw", HB_TAG('N','A','H',' ')}, /* Western Huasteca Nahuatl -> Nahuatl */
- {"nhx", HB_TAG('N','A','H',' ')}, /* Isthmus-Mecayapan Nahuatl -> Nahuatl */
- {"nhy", HB_TAG('N','A','H',' ')}, /* Northern Oaxaca Nahuatl -> Nahuatl */
- {"nhz", HB_TAG('N','A','H',' ')}, /* Santa María La Alta Nahuatl -> Nahuatl */
- {"niq", HB_TAG('K','A','L',' ')}, /* Nandi -> Kalenjin */
- {"nis", HB_TAG_NONE }, /* Nimi != Nisi */
-/*{"niu", HB_TAG('N','I','U',' ')},*/ /* Niuean */
- {"niv", HB_TAG('G','I','L',' ')}, /* Gilyak */
- {"njt", HB_TAG('C','P','P',' ')}, /* Ndyuka-Trio Pidgin -> Creoles */
- {"njz", HB_TAG('N','I','S',' ')}, /* Nyishi -> Nisi */
- {"nko", HB_TAG_NONE }, /* Nkonya != N’Ko */
- {"nkx", HB_TAG('I','J','O',' ')}, /* Nkoroo -> Ijo */
- {"nl", HB_TAG('N','L','D',' ')}, /* Dutch */
- {"nla", HB_TAG('B','M','L',' ')}, /* Ngombale -> Bamileke */
- {"nle", HB_TAG('L','U','H',' ')}, /* East Nyala -> Luyia */
- {"nln", HB_TAG('N','A','H',' ')}, /* Durango Nahuatl (retired code) -> Nahuatl */
- {"nlv", HB_TAG('N','A','H',' ')}, /* Orizaba Nahuatl -> Nahuatl */
- {"nn", HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk (Nynorsk, Norwegian) */
- {"nnh", HB_TAG('B','M','L',' ')}, /* Ngiemboon -> Bamileke */
- {"nnz", HB_TAG('B','M','L',' ')}, /* Nda'nda' -> Bamileke */
- {"no", HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */
- {"nod", HB_TAG('N','T','A',' ')}, /* Northern Thai -> Northern Tai */
-/*{"noe", HB_TAG('N','O','E',' ')},*/ /* Nimadi */
-/*{"nog", HB_TAG('N','O','G',' ')},*/ /* Nogai */
-/*{"nov", HB_TAG('N','O','V',' ')},*/ /* Novial */
- {"npi", HB_TAG('N','E','P',' ')}, /* Nepali */
- {"npl", HB_TAG('N','A','H',' ')}, /* Southeastern Puebla Nahuatl -> Nahuatl */
- {"nqo", HB_TAG('N','K','O',' ')}, /* N’Ko */
- {"nr", HB_TAG('N','D','B',' ')}, /* South Ndebele -> Ndebele */
- {"nsk", HB_TAG('N','A','S',' ')}, /* Naskapi */
- {"nsm", HB_TAG_NONE }, /* Sumi Naga != Northern Sami */
-/*{"nso", HB_TAG('N','S','O',' ')},*/ /* Northern Sotho */
- {"nsu", HB_TAG('N','A','H',' ')}, /* Sierra Negra Nahuatl -> Nahuatl */
- {"nto", HB_TAG_NONE }, /* Ntomba != Esperanto */
- {"nue", HB_TAG('B','A','D','0')}, /* Ngundu -> Banda */
- {"nuu", HB_TAG('B','A','D','0')}, /* Ngbundu -> Banda */
- {"nuz", HB_TAG('N','A','H',' ')}, /* Tlamacazapa Nahuatl -> Nahuatl */
- {"nv", HB_TAG('N','A','V',' ')}, /* Navajo */
- {"nv", HB_TAG('A','T','H',' ')}, /* Navajo -> Athapaskan */
- {"nwe", HB_TAG('B','M','L',' ')}, /* Ngwe -> Bamileke */
- {"ny", HB_TAG('C','H','I',' ')}, /* Chichewa (Chewa, Nyanja) */
- {"nyd", HB_TAG('L','U','H',' ')}, /* Nyore -> Luyia */
-/*{"nym", HB_TAG('N','Y','M',' ')},*/ /* Nyamwezi */
- {"nyn", HB_TAG('N','K','L',' ')}, /* Nyankole */
-/*{"nza", HB_TAG('N','Z','A',' ')},*/ /* Tigon Mbembe -> Mbembe Tigon */
- {"oc", HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */
- {"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] -> Ojibway */
-/*{"ojb", HB_TAG('O','J','B',' ')},*/ /* Northwestern Ojibwa -> Ojibway */
- {"ojc", HB_TAG('O','J','B',' ')}, /* Central Ojibwa -> Ojibway */
- {"ojg", HB_TAG('O','J','B',' ')}, /* Eastern Ojibwa -> Ojibway */
- {"ojs", HB_TAG('O','C','R',' ')}, /* Severn Ojibwa -> Oji-Cree */
- {"ojs", HB_TAG('O','J','B',' ')}, /* Severn Ojibwa -> Ojibway */
- {"ojw", HB_TAG('O','J','B',' ')}, /* Western Ojibwa -> Ojibway */
- {"okd", HB_TAG('I','J','O',' ')}, /* Okodia -> Ijo */
- {"oki", HB_TAG('K','A','L',' ')}, /* Okiek -> Kalenjin */
- {"okm", HB_TAG('K','O','H',' ')}, /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
- {"okr", HB_TAG('I','J','O',' ')}, /* Kirike -> Ijo */
- {"om", HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */
- {"onx", HB_TAG('C','P','P',' ')}, /* Onin Based Pidgin -> Creoles */
- {"oor", HB_TAG('C','P','P',' ')}, /* Oorlams -> Creoles */
- {"or", HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) [macrolanguage] */
- {"orc", HB_TAG('O','R','O',' ')}, /* Orma -> Oromo */
- {"orn", HB_TAG('M','L','Y',' ')}, /* Orang Kanaq -> Malay */
- {"oro", HB_TAG_NONE }, /* Orokolo != Oromo */
- {"orr", HB_TAG('I','J','O',' ')}, /* Oruma -> Ijo */
- {"ors", HB_TAG('M','L','Y',' ')}, /* Orang Seletar -> Malay */
- {"ory", HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) */
- {"os", HB_TAG('O','S','S',' ')}, /* Ossetian */
- {"otw", HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */
- {"oua", HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */
- {"pa", HB_TAG('P','A','N',' ')}, /* Punjabi */
- {"paa", HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */
-/*{"pag", HB_TAG('P','A','G',' ')},*/ /* Pangasinan */
- {"pal", HB_TAG_NONE }, /* Pahlavi != Pali */
-/*{"pam", HB_TAG('P','A','M',' ')},*/ /* Pampanga -> Pampangan */
- {"pap", HB_TAG('P','A','P','0')}, /* Papiamento -> Papiamentu */
- {"pap", HB_TAG('C','P','P',' ')}, /* Papiamento -> Creoles */
- {"pas", HB_TAG_NONE }, /* Papasena != Pashto */
-/*{"pau", HB_TAG('P','A','U',' ')},*/ /* Palauan */
- {"pbt", HB_TAG('P','A','S',' ')}, /* Southern Pashto -> Pashto */
- {"pbu", HB_TAG('P','A','S',' ')}, /* Northern Pashto -> Pashto */
-/*{"pcc", HB_TAG('P','C','C',' ')},*/ /* Bouyei */
-/*{"pcd", HB_TAG('P','C','D',' ')},*/ /* Picard */
- {"pce", HB_TAG('P','L','G',' ')}, /* Ruching Palaung -> Palaung */
- {"pck", HB_TAG('Q','I','N',' ')}, /* Paite Chin -> Chin */
- {"pcm", HB_TAG('C','P','P',' ')}, /* Nigerian Pidgin -> Creoles */
-/*{"pdc", HB_TAG('P','D','C',' ')},*/ /* Pennsylvania German */
- {"pdu", HB_TAG('K','R','N',' ')}, /* Kayan -> Karen */
- {"pea", HB_TAG('C','P','P',' ')}, /* Peranakan Indonesian -> Creoles */
- {"pel", HB_TAG('M','L','Y',' ')}, /* Pekal -> Malay */
- {"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian -> Persian */
- {"pey", HB_TAG('C','P','P',' ')}, /* Petjo -> Creoles */
- {"pga", HB_TAG('A','R','A',' ')}, /* Sudanese Creole Arabic -> Arabic */
- {"pga", HB_TAG('C','P','P',' ')}, /* Sudanese Creole Arabic -> Creoles */
-/*{"phk", HB_TAG('P','H','K',' ')},*/ /* Phake */
- {"pi", HB_TAG('P','A','L',' ')}, /* Pali */
- {"pih", HB_TAG('P','I','H',' ')}, /* Pitcairn-Norfolk -> Norfolk */
- {"pih", HB_TAG('C','P','P',' ')}, /* Pitcairn-Norfolk -> Creoles */
- {"pil", HB_TAG_NONE }, /* Yom != Filipino */
- {"pis", HB_TAG('C','P','P',' ')}, /* Pijin -> Creoles */
- {"pkh", HB_TAG('Q','I','N',' ')}, /* Pankhu -> Chin */
- {"pko", HB_TAG('K','A','L',' ')}, /* Pökoot -> Kalenjin */
- {"pl", HB_TAG('P','L','K',' ')}, /* Polish */
- {"plg", HB_TAG_NONE }, /* Pilagá != Palaung */
- {"plk", HB_TAG_NONE }, /* Kohistani Shina != Polish */
- {"pll", HB_TAG('P','L','G',' ')}, /* Shwe Palaung -> Palaung */
- {"pln", HB_TAG('C','P','P',' ')}, /* Palenquero -> Creoles */
- {"plp", HB_TAG('P','A','P',' ')}, /* Palpa (retired code) */
- {"plt", HB_TAG('M','L','G',' ')}, /* Plateau Malagasy -> Malagasy */
- {"pml", HB_TAG('C','P','P',' ')}, /* Lingua Franca -> Creoles */
-/*{"pms", HB_TAG('P','M','S',' ')},*/ /* Piemontese */
- {"pmy", HB_TAG('C','P','P',' ')}, /* Papuan Malay -> Creoles */
-/*{"pnb", HB_TAG('P','N','B',' ')},*/ /* Western Panjabi */
- {"poc", HB_TAG('M','Y','N',' ')}, /* Poqomam -> Mayan */
- {"poh", HB_TAG('P','O','H',' ')}, /* Poqomchi' -> Pocomchi */
- {"poh", HB_TAG('M','Y','N',' ')}, /* Poqomchi' -> Mayan */
-/*{"pon", HB_TAG('P','O','N',' ')},*/ /* Pohnpeian */
- {"pov", HB_TAG('C','P','P',' ')}, /* Upper Guinea Crioulo -> Creoles */
- {"ppa", HB_TAG('B','A','G',' ')}, /* Pao (retired code) -> Baghelkhandi */
- {"pre", HB_TAG('C','P','P',' ')}, /* Principense -> Creoles */
-/*{"pro", HB_TAG('P','R','O',' ')},*/ /* Old Provençal (to 1500) -> Provençal / Old Provençal */
- {"prs", HB_TAG('D','R','I',' ')}, /* Dari */
- {"prs", HB_TAG('F','A','R',' ')}, /* Dari -> Persian */
- {"ps", HB_TAG('P','A','S',' ')}, /* Pashto [macrolanguage] */
- {"pse", HB_TAG('M','L','Y',' ')}, /* Central Malay -> Malay */
- {"pst", HB_TAG('P','A','S',' ')}, /* Central Pashto -> Pashto */
- {"pt", HB_TAG('P','T','G',' ')}, /* Portuguese */
- {"pub", HB_TAG('Q','I','N',' ')}, /* Purum -> Chin */
- {"puz", HB_TAG('Q','I','N',' ')}, /* Purum Naga (retired code) -> Chin */
- {"pwo", HB_TAG('P','W','O',' ')}, /* Pwo Western Karen -> Western Pwo Karen */
- {"pwo", HB_TAG('K','R','N',' ')}, /* Pwo Western Karen -> Karen */
- {"pww", HB_TAG('K','R','N',' ')}, /* Pwo Northern Karen -> Karen */
- {"qu", HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */
- {"qub", HB_TAG('Q','W','H',' ')}, /* Huallaga Huánuco Quechua -> Quechua (Peru) */
- {"qub", HB_TAG('Q','U','Z',' ')}, /* Huallaga Huánuco Quechua -> Quechua */
- {"quc", HB_TAG('Q','U','C',' ')}, /* K’iche’ */
- {"quc", HB_TAG('M','Y','N',' ')}, /* K'iche' -> Mayan */
- {"qud", HB_TAG('Q','V','I',' ')}, /* Calderón Highland Quichua -> Quechua (Ecuador) */
- {"qud", HB_TAG('Q','U','Z',' ')}, /* Calderón Highland Quichua -> Quechua */
- {"quf", HB_TAG('Q','U','Z',' ')}, /* Lambayeque Quechua -> Quechua */
- {"qug", HB_TAG('Q','V','I',' ')}, /* Chimborazo Highland Quichua -> Quechua (Ecuador) */
- {"qug", HB_TAG('Q','U','Z',' ')}, /* Chimborazo Highland Quichua -> Quechua */
- {"quh", HB_TAG('Q','U','H',' ')}, /* South Bolivian Quechua -> Quechua (Bolivia) */
- {"quh", HB_TAG('Q','U','Z',' ')}, /* South Bolivian Quechua -> Quechua */
- {"quk", HB_TAG('Q','U','Z',' ')}, /* Chachapoyas Quechua -> Quechua */
- {"qul", HB_TAG('Q','U','H',' ')}, /* North Bolivian Quechua -> Quechua (Bolivia) */
- {"qul", HB_TAG('Q','U','Z',' ')}, /* North Bolivian Quechua -> Quechua */
- {"qum", HB_TAG('M','Y','N',' ')}, /* Sipacapense -> Mayan */
- {"qup", HB_TAG('Q','V','I',' ')}, /* Southern Pastaza Quechua -> Quechua (Ecuador) */
- {"qup", HB_TAG('Q','U','Z',' ')}, /* Southern Pastaza Quechua -> Quechua */
- {"qur", HB_TAG('Q','W','H',' ')}, /* Yanahuanca Pasco Quechua -> Quechua (Peru) */
- {"qur", HB_TAG('Q','U','Z',' ')}, /* Yanahuanca Pasco Quechua -> Quechua */
- {"qus", HB_TAG('Q','U','H',' ')}, /* Santiago del Estero Quichua -> Quechua (Bolivia) */
- {"qus", HB_TAG('Q','U','Z',' ')}, /* Santiago del Estero Quichua -> Quechua */
- {"quv", HB_TAG('M','Y','N',' ')}, /* Sacapulteco -> Mayan */
- {"quw", HB_TAG('Q','V','I',' ')}, /* Tena Lowland Quichua -> Quechua (Ecuador) */
- {"quw", HB_TAG('Q','U','Z',' ')}, /* Tena Lowland Quichua -> Quechua */
- {"qux", HB_TAG('Q','W','H',' ')}, /* Yauyos Quechua -> Quechua (Peru) */
- {"qux", HB_TAG('Q','U','Z',' ')}, /* Yauyos Quechua -> Quechua */
- {"quy", HB_TAG('Q','U','Z',' ')}, /* Ayacucho Quechua -> Quechua */
-/*{"quz", HB_TAG('Q','U','Z',' ')},*/ /* Cusco Quechua -> Quechua */
- {"qva", HB_TAG('Q','W','H',' ')}, /* Ambo-Pasco Quechua -> Quechua (Peru) */
- {"qva", HB_TAG('Q','U','Z',' ')}, /* Ambo-Pasco Quechua -> Quechua */
- {"qvc", HB_TAG('Q','U','Z',' ')}, /* Cajamarca Quechua -> Quechua */
- {"qve", HB_TAG('Q','U','Z',' ')}, /* Eastern Apurímac Quechua -> Quechua */
- {"qvh", HB_TAG('Q','W','H',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
- {"qvh", HB_TAG('Q','U','Z',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua */
- {"qvi", HB_TAG('Q','V','I',' ')}, /* Imbabura Highland Quichua -> Quechua (Ecuador) */
- {"qvi", HB_TAG('Q','U','Z',' ')}, /* Imbabura Highland Quichua -> Quechua */
- {"qvj", HB_TAG('Q','V','I',' ')}, /* Loja Highland Quichua -> Quechua (Ecuador) */
- {"qvj", HB_TAG('Q','U','Z',' ')}, /* Loja Highland Quichua -> Quechua */
- {"qvl", HB_TAG('Q','W','H',' ')}, /* Cajatambo North Lima Quechua -> Quechua (Peru) */
- {"qvl", HB_TAG('Q','U','Z',' ')}, /* Cajatambo North Lima Quechua -> Quechua */
- {"qvm", HB_TAG('Q','W','H',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
- {"qvm", HB_TAG('Q','U','Z',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua */
- {"qvn", HB_TAG('Q','W','H',' ')}, /* North Junín Quechua -> Quechua (Peru) */
- {"qvn", HB_TAG('Q','U','Z',' ')}, /* North Junín Quechua -> Quechua */
- {"qvo", HB_TAG('Q','V','I',' ')}, /* Napo Lowland Quechua -> Quechua (Ecuador) */
- {"qvo", HB_TAG('Q','U','Z',' ')}, /* Napo Lowland Quechua -> Quechua */
- {"qvp", HB_TAG('Q','W','H',' ')}, /* Pacaraos Quechua -> Quechua (Peru) */
- {"qvp", HB_TAG('Q','U','Z',' ')}, /* Pacaraos Quechua -> Quechua */
- {"qvs", HB_TAG('Q','U','Z',' ')}, /* San Martín Quechua -> Quechua */
- {"qvw", HB_TAG('Q','W','H',' ')}, /* Huaylla Wanca Quechua -> Quechua (Peru) */
- {"qvw", HB_TAG('Q','U','Z',' ')}, /* Huaylla Wanca Quechua -> Quechua */
- {"qvz", HB_TAG('Q','V','I',' ')}, /* Northern Pastaza Quichua -> Quechua (Ecuador) */
- {"qvz", HB_TAG('Q','U','Z',' ')}, /* Northern Pastaza Quichua -> Quechua */
- {"qwa", HB_TAG('Q','W','H',' ')}, /* Corongo Ancash Quechua -> Quechua (Peru) */
- {"qwa", HB_TAG('Q','U','Z',' ')}, /* Corongo Ancash Quechua -> Quechua */
- {"qwc", HB_TAG('Q','U','Z',' ')}, /* Classical Quechua -> Quechua */
- {"qwh", HB_TAG('Q','W','H',' ')}, /* Huaylas Ancash Quechua -> Quechua (Peru) */
- {"qwh", HB_TAG('Q','U','Z',' ')}, /* Huaylas Ancash Quechua -> Quechua */
- {"qws", HB_TAG('Q','W','H',' ')}, /* Sihuas Ancash Quechua -> Quechua (Peru) */
- {"qws", HB_TAG('Q','U','Z',' ')}, /* Sihuas Ancash Quechua -> Quechua */
- {"qwt", HB_TAG('A','T','H',' ')}, /* Kwalhioqua-Tlatskanai -> Athapaskan */
- {"qxa", HB_TAG('Q','W','H',' ')}, /* Chiquián Ancash Quechua -> Quechua (Peru) */
- {"qxa", HB_TAG('Q','U','Z',' ')}, /* Chiquián Ancash Quechua -> Quechua */
- {"qxc", HB_TAG('Q','W','H',' ')}, /* Chincha Quechua -> Quechua (Peru) */
- {"qxc", HB_TAG('Q','U','Z',' ')}, /* Chincha Quechua -> Quechua */
- {"qxh", HB_TAG('Q','W','H',' ')}, /* Panao Huánuco Quechua -> Quechua (Peru) */
- {"qxh", HB_TAG('Q','U','Z',' ')}, /* Panao Huánuco Quechua -> Quechua */
- {"qxl", HB_TAG('Q','V','I',' ')}, /* Salasaca Highland Quichua -> Quechua (Ecuador) */
- {"qxl", HB_TAG('Q','U','Z',' ')}, /* Salasaca Highland Quichua -> Quechua */
- {"qxn", HB_TAG('Q','W','H',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
- {"qxn", HB_TAG('Q','U','Z',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua */
- {"qxo", HB_TAG('Q','W','H',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
- {"qxo", HB_TAG('Q','U','Z',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua */
- {"qxp", HB_TAG('Q','U','Z',' ')}, /* Puno Quechua -> Quechua */
- {"qxr", HB_TAG('Q','V','I',' ')}, /* Cañar Highland Quichua -> Quechua (Ecuador) */
- {"qxr", HB_TAG('Q','U','Z',' ')}, /* Cañar Highland Quichua -> Quechua */
- {"qxt", HB_TAG('Q','W','H',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
- {"qxt", HB_TAG('Q','U','Z',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua */
- {"qxu", HB_TAG('Q','U','Z',' ')}, /* Arequipa-La Unión Quechua -> Quechua */
- {"qxw", HB_TAG('Q','W','H',' ')}, /* Jauja Wanca Quechua -> Quechua (Peru) */
- {"qxw", HB_TAG('Q','U','Z',' ')}, /* Jauja Wanca Quechua -> Quechua */
- {"rag", HB_TAG('L','U','H',' ')}, /* Logooli -> Luyia */
-/*{"raj", HB_TAG('R','A','J',' ')},*/ /* Rajasthani [macrolanguage] */
- {"ral", HB_TAG('Q','I','N',' ')}, /* Ralte -> Chin */
-/*{"rar", HB_TAG('R','A','R',' ')},*/ /* Rarotongan */
- {"rbb", HB_TAG('P','L','G',' ')}, /* Rumai Palaung -> Palaung */
- {"rbl", HB_TAG('B','I','K',' ')}, /* Miraya Bikol -> Bikol */
- {"rcf", HB_TAG('C','P','P',' ')}, /* Réunion Creole French -> Creoles */
-/*{"rej", HB_TAG('R','E','J',' ')},*/ /* Rejang */
-/*{"rhg", HB_TAG('R','H','G',' ')},*/ /* Rohingya */
-/*{"ria", HB_TAG('R','I','A',' ')},*/ /* Riang (India) */
- {"rif", HB_TAG('R','I','F',' ')}, /* Tarifit */
- {"rif", HB_TAG('B','B','R',' ')}, /* Tarifit -> Berber */
-/*{"rit", HB_TAG('R','I','T',' ')},*/ /* Ritharrngu -> Ritarungo */
- {"rki", HB_TAG('A','R','K',' ')}, /* Rakhine */
-/*{"rkw", HB_TAG('R','K','W',' ')},*/ /* Arakwal */
- {"rm", HB_TAG('R','M','S',' ')}, /* Romansh */
- {"rmc", HB_TAG('R','O','Y',' ')}, /* Carpathian Romani -> Romany */
- {"rmf", HB_TAG('R','O','Y',' ')}, /* Kalo Finnish Romani -> Romany */
- {"rml", HB_TAG('R','O','Y',' ')}, /* Baltic Romani -> Romany */
- {"rmn", HB_TAG('R','O','Y',' ')}, /* Balkan Romani -> Romany */
- {"rmo", HB_TAG('R','O','Y',' ')}, /* Sinte Romani -> Romany */
- {"rms", HB_TAG_NONE }, /* Romanian Sign Language != Romansh */
- {"rmw", HB_TAG('R','O','Y',' ')}, /* Welsh Romani -> Romany */
- {"rmy", HB_TAG('R','M','Y',' ')}, /* Vlax Romani */
- {"rmy", HB_TAG('R','O','Y',' ')}, /* Vlax Romani -> Romany */
- {"rmz", HB_TAG('A','R','K',' ')}, /* Marma -> Rakhine */
- {"rn", HB_TAG('R','U','N',' ')}, /* Rundi */
- {"ro", HB_TAG('R','O','M',' ')}, /* Romanian */
- {"rom", HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */
- {"rop", HB_TAG('C','P','P',' ')}, /* Kriol -> Creoles */
- {"rtc", HB_TAG('Q','I','N',' ')}, /* Rungtu Chin -> Chin */
-/*{"rtm", HB_TAG('R','T','M',' ')},*/ /* Rotuman */
- {"ru", HB_TAG('R','U','S',' ')}, /* Russian */
- {"rue", HB_TAG('R','S','Y',' ')}, /* Rusyn */
-/*{"rup", HB_TAG('R','U','P',' ')},*/ /* Aromanian */
- {"rw", HB_TAG('R','U','A',' ')}, /* Kinyarwanda */
- {"rwr", HB_TAG('M','A','W',' ')}, /* Marwari (India) */
- {"sa", HB_TAG('S','A','N',' ')}, /* Sanskrit */
- {"sad", HB_TAG_NONE }, /* Sandawe != Sadri */
- {"sah", HB_TAG('Y','A','K',' ')}, /* Yakut -> Sakha */
- {"sam", HB_TAG('P','A','A',' ')}, /* Samaritan Aramaic -> Palestinian Aramaic */
-/*{"sas", HB_TAG('S','A','S',' ')},*/ /* Sasak */
-/*{"sat", HB_TAG('S','A','T',' ')},*/ /* Santali */
- {"say", HB_TAG_NONE }, /* Saya != Sayisi */
- {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */
- {"scf", HB_TAG('C','P','P',' ')}, /* San Miguel Creole French -> Creoles */
- {"sch", HB_TAG('Q','I','N',' ')}, /* Sakachep -> Chin */
- {"sci", HB_TAG('C','P','P',' ')}, /* Sri Lankan Creole Malay -> Creoles */
- {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */
-/*{"scn", HB_TAG('S','C','N',' ')},*/ /* Sicilian */
-/*{"sco", HB_TAG('S','C','O',' ')},*/ /* Scots */
- {"scs", HB_TAG('S','C','S',' ')}, /* North Slavey */
- {"scs", HB_TAG('S','L','A',' ')}, /* North Slavey -> Slavey */
- {"scs", HB_TAG('A','T','H',' ')}, /* North Slavey -> Athapaskan */
- {"sd", HB_TAG('S','N','D',' ')}, /* Sindhi */
- {"sdc", HB_TAG('S','R','D',' ')}, /* Sassarese Sardinian -> Sardinian */
- {"sdh", HB_TAG('K','U','R',' ')}, /* Southern Kurdish -> Kurdish */
- {"sdn", HB_TAG('S','R','D',' ')}, /* Gallurese Sardinian -> Sardinian */
- {"sds", HB_TAG('B','B','R',' ')}, /* Sened -> Berber */
- {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */
- {"seh", HB_TAG('S','N','A',' ')}, /* Sena */
- {"sek", HB_TAG('A','T','H',' ')}, /* Sekani -> Athapaskan */
-/*{"sel", HB_TAG('S','E','L',' ')},*/ /* Selkup */
- {"sez", HB_TAG('Q','I','N',' ')}, /* Senthang Chin -> Chin */
- {"sfm", HB_TAG('S','F','M',' ')}, /* Small Flowery Miao */
- {"sfm", HB_TAG('H','M','N',' ')}, /* Small Flowery Miao -> Hmong */
- {"sg", HB_TAG('S','G','O',' ')}, /* Sango */
-/*{"sga", HB_TAG('S','G','A',' ')},*/ /* Old Irish (to 900) */
- {"sgc", HB_TAG('K','A','L',' ')}, /* Kipsigis -> Kalenjin */
- {"sgo", HB_TAG_NONE }, /* Songa (retired code) != Sango */
-/*{"sgs", HB_TAG('S','G','S',' ')},*/ /* Samogitian */
- {"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage -> Chaha Gurage */
- {"sh", HB_TAG('B','O','S',' ')}, /* Serbo-Croatian [macrolanguage] -> Bosnian */
- {"sh", HB_TAG('H','R','V',' ')}, /* Serbo-Croatian [macrolanguage] -> Croatian */
- {"sh", HB_TAG('S','R','B',' ')}, /* Serbo-Croatian [macrolanguage] -> Serbian */
- {"shi", HB_TAG('S','H','I',' ')}, /* Tachelhit */
- {"shi", HB_TAG('B','B','R',' ')}, /* Tachelhit -> Berber */
- {"shl", HB_TAG('Q','I','N',' ')}, /* Shendu -> Chin */
-/*{"shn", HB_TAG('S','H','N',' ')},*/ /* Shan */
- {"shu", HB_TAG('A','R','A',' ')}, /* Chadian Arabic -> Arabic */
- {"shy", HB_TAG('B','B','R',' ')}, /* Tachawit -> Berber */
- {"si", HB_TAG('S','N','H',' ')}, /* Sinhala (Sinhalese) */
- {"sib", HB_TAG_NONE }, /* Sebop != Sibe */
-/*{"sid", HB_TAG('S','I','D',' ')},*/ /* Sidamo */
- {"sig", HB_TAG_NONE }, /* Paasaal != Silte Gurage */
- {"siz", HB_TAG('B','B','R',' ')}, /* Siwi -> Berber */
- {"sjd", HB_TAG('K','S','M',' ')}, /* Kildin Sami */
- {"sjo", HB_TAG('S','I','B',' ')}, /* Xibe -> Sibe */
- {"sjs", HB_TAG('B','B','R',' ')}, /* Senhaja De Srair -> Berber */
- {"sk", HB_TAG('S','K','Y',' ')}, /* Slovak */
- {"skg", HB_TAG('M','L','G',' ')}, /* Sakalava Malagasy -> Malagasy */
- {"skr", HB_TAG('S','R','K',' ')}, /* Saraiki */
- {"sks", HB_TAG_NONE }, /* Maia != Skolt Sami */
- {"skw", HB_TAG('C','P','P',' ')}, /* Skepi Creole Dutch -> Creoles */
- {"sky", HB_TAG_NONE }, /* Sikaiana != Slovak */
- {"sl", HB_TAG('S','L','V',' ')}, /* Slovenian */
- {"sla", HB_TAG_NONE }, /* Slavic [collection] != Slavey */
- {"sm", HB_TAG('S','M','O',' ')}, /* Samoan */
- {"sma", HB_TAG('S','S','M',' ')}, /* Southern Sami */
- {"smd", HB_TAG('M','B','N',' ')}, /* Sama (retired code) -> Mbundu */
- {"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */
- {"sml", HB_TAG_NONE }, /* Central Sama != Somali */
- {"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */
- {"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */
- {"smt", HB_TAG('Q','I','N',' ')}, /* Simte -> Chin */
- {"sn", HB_TAG('S','N','A','0')}, /* Shona */
- {"snb", HB_TAG('I','B','A',' ')}, /* Sebuyau (retired code) -> Iban */
- {"snh", HB_TAG_NONE }, /* Shinabo (retired code) != Sinhala (Sinhalese) */
-/*{"snk", HB_TAG('S','N','K',' ')},*/ /* Soninke */
- {"so", HB_TAG('S','M','L',' ')}, /* Somali */
- {"sog", HB_TAG_NONE }, /* Sogdian != Sodo Gurage */
-/*{"sop", HB_TAG('S','O','P',' ')},*/ /* Songe */
- {"spv", HB_TAG('O','R','I',' ')}, /* Sambalpuri -> Odia (formerly Oriya) */
- {"spy", HB_TAG('K','A','L',' ')}, /* Sabaot -> Kalenjin */
- {"sq", HB_TAG('S','Q','I',' ')}, /* Albanian [macrolanguage] */
- {"sr", HB_TAG('S','R','B',' ')}, /* Serbian */
- {"srb", HB_TAG_NONE }, /* Sora != Serbian */
- {"src", HB_TAG('S','R','D',' ')}, /* Logudorese Sardinian -> Sardinian */
- {"srk", HB_TAG_NONE }, /* Serudung Murut != Saraiki */
- {"srm", HB_TAG('C','P','P',' ')}, /* Saramaccan -> Creoles */
- {"srn", HB_TAG('C','P','P',' ')}, /* Sranan Tongo -> Creoles */
- {"sro", HB_TAG('S','R','D',' ')}, /* Campidanese Sardinian -> Sardinian */
-/*{"srr", HB_TAG('S','R','R',' ')},*/ /* Serer */
- {"srs", HB_TAG('A','T','H',' ')}, /* Sarsi -> Athapaskan */
- {"ss", HB_TAG('S','W','Z',' ')}, /* Swati */
- {"ssh", HB_TAG('A','R','A',' ')}, /* Shihhi Arabic -> Arabic */
- {"ssl", HB_TAG_NONE }, /* Western Sisaala != South Slavey */
- {"ssm", HB_TAG_NONE }, /* Semnam != Southern Sami */
- {"st", HB_TAG('S','O','T',' ')}, /* Southern Sotho */
- {"sta", HB_TAG('C','P','P',' ')}, /* Settla -> Creoles */
-/*{"stq", HB_TAG('S','T','Q',' ')},*/ /* Saterfriesisch -> Saterland Frisian */
- {"stv", HB_TAG('S','I','G',' ')}, /* Silt'e -> Silte Gurage */
- {"su", HB_TAG('S','U','N',' ')}, /* Sundanese */
-/*{"suk", HB_TAG('S','U','K',' ')},*/ /* Sukuma */
- {"suq", HB_TAG('S','U','R',' ')}, /* Suri */
- {"sur", HB_TAG_NONE }, /* Mwaghavul != Suri */
- {"sv", HB_TAG('S','V','E',' ')}, /* Swedish */
-/*{"sva", HB_TAG('S','V','A',' ')},*/ /* Svan */
- {"svc", HB_TAG('C','P','P',' ')}, /* Vincentian Creole English -> Creoles */
- {"sve", HB_TAG_NONE }, /* Serili != Swedish */
- {"sw", HB_TAG('S','W','K',' ')}, /* Swahili [macrolanguage] */
- {"swb", HB_TAG('C','M','R',' ')}, /* Maore Comorian -> Comorian */
- {"swc", HB_TAG('S','W','K',' ')}, /* Congo Swahili -> Swahili */
- {"swh", HB_TAG('S','W','K',' ')}, /* Swahili */
- {"swk", HB_TAG_NONE }, /* Malawi Sena != Swahili */
- {"swn", HB_TAG('B','B','R',' ')}, /* Sawknah -> Berber */
- {"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati -> Marwari */
-/*{"sxu", HB_TAG('S','X','U',' ')},*/ /* Upper Saxon */
- {"syc", HB_TAG('S','Y','R',' ')}, /* Classical Syriac -> Syriac */
-/*{"syl", HB_TAG('S','Y','L',' ')},*/ /* Sylheti */
-/*{"syr", HB_TAG('S','Y','R',' ')},*/ /* Syriac [macrolanguage] */
-/*{"szl", HB_TAG('S','Z','L',' ')},*/ /* Silesian */
- {"ta", HB_TAG('T','A','M',' ')}, /* Tamil */
- {"taa", HB_TAG('A','T','H',' ')}, /* Lower Tanana -> Athapaskan */
-/*{"tab", HB_TAG('T','A','B',' ')},*/ /* Tabassaran -> Tabasaran */
- {"taj", HB_TAG_NONE }, /* Eastern Tamang != Tajiki */
- {"taq", HB_TAG('T','M','H',' ')}, /* Tamasheq -> Tamashek */
- {"taq", HB_TAG('B','B','R',' ')}, /* Tamasheq -> Berber */
- {"tas", HB_TAG('C','P','P',' ')}, /* Tay Boi -> Creoles */
- {"tau", HB_TAG('A','T','H',' ')}, /* Upper Tanana -> Athapaskan */
- {"tcb", HB_TAG('A','T','H',' ')}, /* Tanacross -> Athapaskan */
- {"tce", HB_TAG('A','T','H',' ')}, /* Southern Tutchone -> Athapaskan */
- {"tch", HB_TAG('C','P','P',' ')}, /* Turks And Caicos Creole English -> Creoles */
- {"tcp", HB_TAG('Q','I','N',' ')}, /* Tawr Chin -> Chin */
- {"tcs", HB_TAG('C','P','P',' ')}, /* Torres Strait Creole -> Creoles */
- {"tcy", HB_TAG('T','U','L',' ')}, /* Tulu -> Tumbuka */
- {"tcz", HB_TAG('Q','I','N',' ')}, /* Thado Chin -> Chin */
-/*{"tdd", HB_TAG('T','D','D',' ')},*/ /* Tai Nüa -> Dehong Dai */
- {"tdx", HB_TAG('M','L','G',' ')}, /* Tandroy-Mahafaly Malagasy -> Malagasy */
- {"te", HB_TAG('T','E','L',' ')}, /* Telugu */
- {"tec", HB_TAG('K','A','L',' ')}, /* Terik -> Kalenjin */
- {"tem", HB_TAG('T','M','N',' ')}, /* Timne -> Temne */
-/*{"tet", HB_TAG('T','E','T',' ')},*/ /* Tetum */
- {"tez", HB_TAG('B','B','R',' ')}, /* Tetserret -> Berber */
- {"tfn", HB_TAG('A','T','H',' ')}, /* Tanaina -> Athapaskan */
- {"tg", HB_TAG('T','A','J',' ')}, /* Tajik -> Tajiki */
- {"tgh", HB_TAG('C','P','P',' ')}, /* Tobagonian Creole English -> Creoles */
- {"tgj", HB_TAG('N','I','S',' ')}, /* Tagin -> Nisi */
- {"tgn", HB_TAG_NONE }, /* Tandaganon != Tongan */
- {"tgr", HB_TAG_NONE }, /* Tareng != Tigre */
- {"tgx", HB_TAG('A','T','H',' ')}, /* Tagish -> Athapaskan */
- {"tgy", HB_TAG_NONE }, /* Togoyo != Tigrinya */
- {"th", HB_TAG('T','H','A',' ')}, /* Thai */
- {"tht", HB_TAG('A','T','H',' ')}, /* Tahltan -> Athapaskan */
- {"thv", HB_TAG('T','M','H',' ')}, /* Tahaggart Tamahaq -> Tamashek */
- {"thv", HB_TAG('B','B','R',' ')}, /* Tahaggart Tamahaq -> Berber */
- {"thz", HB_TAG('T','M','H',' ')}, /* Tayart Tamajeq -> Tamashek */
- {"thz", HB_TAG('B','B','R',' ')}, /* Tayart Tamajeq -> Berber */
- {"ti", HB_TAG('T','G','Y',' ')}, /* Tigrinya */
- {"tia", HB_TAG('B','B','R',' ')}, /* Tidikelt Tamazight -> Berber */
- {"tig", HB_TAG('T','G','R',' ')}, /* Tigre */
-/*{"tiv", HB_TAG('T','I','V',' ')},*/ /* Tiv */
-/*{"tjl", HB_TAG('T','J','L',' ')},*/ /* Tai Laing */
- {"tjo", HB_TAG('B','B','R',' ')}, /* Temacine Tamazight -> Berber */
- {"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */
- {"tkg", HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */
- {"tkm", HB_TAG_NONE }, /* Takelma != Turkmen */
- {"tl", HB_TAG('T','G','L',' ')}, /* Tagalog */
-/*{"tli", HB_TAG('T','L','I',' ')},*/ /* Tlingit */
- {"tmg", HB_TAG('C','P','P',' ')}, /* Ternateño -> Creoles */
- {"tmh", HB_TAG('T','M','H',' ')}, /* Tamashek [macrolanguage] */
- {"tmh", HB_TAG('B','B','R',' ')}, /* Tamashek [macrolanguage] -> Berber */
- {"tmn", HB_TAG_NONE }, /* Taman (Indonesia) != Temne */
- {"tmw", HB_TAG('M','L','Y',' ')}, /* Temuan -> Malay */
- {"tn", HB_TAG('T','N','A',' ')}, /* Tswana */
- {"tna", HB_TAG_NONE }, /* Tacana != Tswana */
- {"tne", HB_TAG_NONE }, /* Tinoc Kallahan (retired code) != Tundra Enets */
- {"tnf", HB_TAG('D','R','I',' ')}, /* Tangshewi (retired code) -> Dari */
- {"tnf", HB_TAG('F','A','R',' ')}, /* Tangshewi (retired code) -> Persian */
- {"tng", HB_TAG_NONE }, /* Tobanga != Tonga */
- {"to", HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) -> Tongan */
- {"tod", HB_TAG('T','O','D','0')}, /* Toma */
- {"toi", HB_TAG('T','N','G',' ')}, /* Tonga (Zambia) */
- {"toj", HB_TAG('M','Y','N',' ')}, /* Tojolabal -> Mayan */
- {"tol", HB_TAG('A','T','H',' ')}, /* Tolowa -> Athapaskan */
- {"tor", HB_TAG('B','A','D','0')}, /* Togbo-Vara Banda -> Banda */
- {"tpi", HB_TAG('T','P','I',' ')}, /* Tok Pisin */
- {"tpi", HB_TAG('C','P','P',' ')}, /* Tok Pisin -> Creoles */
- {"tr", HB_TAG('T','R','K',' ')}, /* Turkish */
- {"trf", HB_TAG('C','P','P',' ')}, /* Trinidadian Creole English -> Creoles */
- {"trk", HB_TAG_NONE }, /* Turkic [collection] != Turkish */
- {"tru", HB_TAG('T','U','A',' ')}, /* Turoyo -> Turoyo Aramaic */
- {"tru", HB_TAG('S','Y','R',' ')}, /* Turoyo -> Syriac */
- {"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */
- {"tsg", HB_TAG_NONE }, /* Tausug != Tsonga */
-/*{"tsj", HB_TAG('T','S','J',' ')},*/ /* Tshangla */
- {"tt", HB_TAG('T','A','T',' ')}, /* Tatar */
- {"ttc", HB_TAG('M','Y','N',' ')}, /* Tektiteko -> Mayan */
- {"ttm", HB_TAG('A','T','H',' ')}, /* Northern Tutchone -> Athapaskan */
- {"ttq", HB_TAG('T','M','H',' ')}, /* Tawallammat Tamajaq -> Tamashek */
- {"ttq", HB_TAG('B','B','R',' ')}, /* Tawallammat Tamajaq -> Berber */
- {"tua", HB_TAG_NONE }, /* Wiarumus != Turoyo Aramaic */
- {"tul", HB_TAG_NONE }, /* Tula != Tumbuka */
-/*{"tum", HB_TAG('T','U','M',' ')},*/ /* Tumbuka -> Tulu */
- {"tuu", HB_TAG('A','T','H',' ')}, /* Tututni -> Athapaskan */
- {"tuv", HB_TAG_NONE }, /* Turkana != Tuvin */
- {"tuy", HB_TAG('K','A','L',' ')}, /* Tugen -> Kalenjin */
-/*{"tvl", HB_TAG('T','V','L',' ')},*/ /* Tuvalu */
- {"tvy", HB_TAG('C','P','P',' ')}, /* Timor Pidgin -> Creoles */
- {"tw", HB_TAG('T','W','I',' ')}, /* Twi */
- {"tw", HB_TAG('A','K','A',' ')}, /* Twi -> Akan */
- {"txc", HB_TAG('A','T','H',' ')}, /* Tsetsaut -> Athapaskan */
- {"txy", HB_TAG('M','L','G',' ')}, /* Tanosy Malagasy -> Malagasy */
- {"ty", HB_TAG('T','H','T',' ')}, /* Tahitian */
- {"tyv", HB_TAG('T','U','V',' ')}, /* Tuvinian -> Tuvin */
-/*{"tyz", HB_TAG('T','Y','Z',' ')},*/ /* Tày */
- {"tzh", HB_TAG('M','Y','N',' ')}, /* Tzeltal -> Mayan */
- {"tzj", HB_TAG('M','Y','N',' ')}, /* Tz'utujil -> Mayan */
- {"tzm", HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight -> Tamazight */
- {"tzm", HB_TAG('B','B','R',' ')}, /* Central Atlas Tamazight -> Berber */
- {"tzo", HB_TAG('T','Z','O',' ')}, /* Tzotzil */
- {"tzo", HB_TAG('M','Y','N',' ')}, /* Tzotzil -> Mayan */
- {"ubl", HB_TAG('B','I','K',' ')}, /* Buhi'non Bikol -> Bikol */
-/*{"udm", HB_TAG('U','D','M',' ')},*/ /* Udmurt */
- {"ug", HB_TAG('U','Y','G',' ')}, /* Uyghur */
- {"uk", HB_TAG('U','K','R',' ')}, /* Ukrainian */
- {"uki", HB_TAG('K','U','I',' ')}, /* Kui (India) */
- {"uln", HB_TAG('C','P','P',' ')}, /* Unserdeutsch -> Creoles */
-/*{"umb", HB_TAG('U','M','B',' ')},*/ /* Umbundu */
- {"unr", HB_TAG('M','U','N',' ')}, /* Mundari */
- {"ur", HB_TAG('U','R','D',' ')}, /* Urdu */
- {"urk", HB_TAG('M','L','Y',' ')}, /* Urak Lawoi' -> Malay */
- {"usp", HB_TAG('M','Y','N',' ')}, /* Uspanteco -> Mayan */
- {"uz", HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */
- {"uzn", HB_TAG('U','Z','B',' ')}, /* Northern Uzbek -> Uzbek */
- {"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek -> Uzbek */
- {"vap", HB_TAG('Q','I','N',' ')}, /* Vaiphei -> Chin */
- {"ve", HB_TAG('V','E','N',' ')}, /* Venda */
-/*{"vec", HB_TAG('V','E','C',' ')},*/ /* Venetian */
- {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */
- {"vic", HB_TAG('C','P','P',' ')}, /* Virgin Islands Creole English -> Creoles */
- {"vit", HB_TAG_NONE }, /* Viti != Vietnamese */
- {"vkk", HB_TAG('M','L','Y',' ')}, /* Kaur -> Malay */
- {"vkp", HB_TAG('C','P','P',' ')}, /* Korlai Creole Portuguese -> Creoles */
- {"vkt", HB_TAG('M','L','Y',' ')}, /* Tenggarong Kutai Malay -> Malay */
- {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams -> Dutch (Flemish) */
- {"vmw", HB_TAG('M','A','K',' ')}, /* Makhuwa */
- {"vo", HB_TAG('V','O','L',' ')}, /* Volapük */
-/*{"vro", HB_TAG('V','R','O',' ')},*/ /* Võro */
- {"wa", HB_TAG('W','L','N',' ')}, /* Walloon */
- {"wag", HB_TAG_NONE }, /* Wa'ema != Wagdi */
-/*{"war", HB_TAG('W','A','R',' ')},*/ /* Waray (Philippines) -> Waray-Waray */
- {"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */
- {"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */
- {"wbr", HB_TAG('R','A','J',' ')}, /* Wagdi -> Rajasthani */
-/*{"wci", HB_TAG('W','C','I',' ')},*/ /* Waci Gbe */
- {"wea", HB_TAG('K','R','N',' ')}, /* Wewaw -> Karen */
- {"wes", HB_TAG('C','P','P',' ')}, /* Cameroon Pidgin -> Creoles */
- {"weu", HB_TAG('Q','I','N',' ')}, /* Rawngtu Chin -> Chin */
- {"wlc", HB_TAG('C','M','R',' ')}, /* Mwali Comorian -> Comorian */
- {"wle", HB_TAG('S','I','G',' ')}, /* Wolane -> Silte Gurage */
- {"wlk", HB_TAG('A','T','H',' ')}, /* Wailaki -> Athapaskan */
- {"wni", HB_TAG('C','M','R',' ')}, /* Ndzwani Comorian -> Comorian */
- {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */
- {"wry", HB_TAG('M','A','W',' ')}, /* Merwari -> Marwari */
- {"wsg", HB_TAG('G','O','N',' ')}, /* Adilabad Gondi -> Gondi */
-/*{"wtm", HB_TAG('W','T','M',' ')},*/ /* Mewati */
- {"wuu", HB_TAG('Z','H','S',' ')}, /* Wu Chinese -> Chinese, Simplified */
- {"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */
- {"xal", HB_TAG('T','O','D',' ')}, /* Kalmyk -> Todo */
- {"xan", HB_TAG('S','E','K',' ')}, /* Xamtanga -> Sekota */
- {"xbd", HB_TAG_NONE }, /* Bindal != Lü */
- {"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */
-/*{"xjb", HB_TAG('X','J','B',' ')},*/ /* Minjungbal -> Minjangbal */
-/*{"xkf", HB_TAG('X','K','F',' ')},*/ /* Khengkha */
- {"xmg", HB_TAG('B','M','L',' ')}, /* Mengaka -> Bamileke */
- {"xmm", HB_TAG('M','L','Y',' ')}, /* Manado Malay -> Malay */
- {"xmm", HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */
- {"xmv", HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */
- {"xmw", HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */
- {"xnj", HB_TAG('S','X','T',' ')}, /* Ngoni (Tanzania) -> Sutu */
- {"xnq", HB_TAG('S','X','T',' ')}, /* Ngoni (Mozambique) -> Sutu */
- {"xnr", HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */
-/*{"xog", HB_TAG('X','O','G',' ')},*/ /* Soga */
- {"xpe", HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */
- {"xpe", HB_TAG('K','P','L',' ')}, /* Liberia Kpelle -> Kpelle */
- {"xsl", HB_TAG('S','S','L',' ')}, /* South Slavey */
- {"xsl", HB_TAG('S','L','A',' ')}, /* South Slavey -> Slavey */
- {"xsl", HB_TAG('A','T','H',' ')}, /* South Slavey -> Athapaskan */
- {"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) -> Silte Gurage */
-/*{"xub", HB_TAG('X','U','B',' ')},*/ /* Betta Kurumba -> Bette Kuruma */
-/*{"xuj", HB_TAG('X','U','J',' ')},*/ /* Jennu Kurumba -> Jennu Kuruma */
- {"xup", HB_TAG('A','T','H',' ')}, /* Upper Umpqua -> Athapaskan */
- {"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat -> Todo */
- {"yaj", HB_TAG('B','A','D','0')}, /* Banda-Yangere -> Banda */
- {"yak", HB_TAG_NONE }, /* Yakama != Sakha */
-/*{"yao", HB_TAG('Y','A','O',' ')},*/ /* Yao */
-/*{"yap", HB_TAG('Y','A','P',' ')},*/ /* Yapese */
- {"yba", HB_TAG_NONE }, /* Yala != Yoruba */
- {"ybb", HB_TAG('B','M','L',' ')}, /* Yemba -> Bamileke */
- {"ybd", HB_TAG('A','R','K',' ')}, /* Yangbye (retired code) -> Rakhine */
- {"ydd", HB_TAG('J','I','I',' ')}, /* Eastern Yiddish -> Yiddish */
-/*{"ygp", HB_TAG('Y','G','P',' ')},*/ /* Gepo */
- {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */
- {"yih", HB_TAG('J','I','I',' ')}, /* Western Yiddish -> Yiddish */
- {"yim", HB_TAG_NONE }, /* Yimchungru Naga != Yi Modern */
-/*{"yna", HB_TAG('Y','N','A',' ')},*/ /* Aluo */
- {"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */
- {"yos", HB_TAG('Q','I','N',' ')}, /* Yos (retired code) -> Chin */
- {"yua", HB_TAG('M','Y','N',' ')}, /* Yucateco -> Mayan */
- {"yue", HB_TAG('Z','H','H',' ')}, /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */
-/*{"ywq", HB_TAG('Y','W','Q',' ')},*/ /* Wuding-Luquan Yi */
- {"za", HB_TAG('Z','H','A',' ')}, /* Zhuang [macrolanguage] */
- {"zch", HB_TAG('Z','H','A',' ')}, /* Central Hongshuihe Zhuang -> Zhuang */
- {"zdj", HB_TAG('C','M','R',' ')}, /* Ngazidja Comorian -> Comorian */
-/*{"zea", HB_TAG('Z','E','A',' ')},*/ /* Zeeuws -> Zealandic */
- {"zeh", HB_TAG('Z','H','A',' ')}, /* Eastern Hongshuihe Zhuang -> Zhuang */
- {"zen", HB_TAG('B','B','R',' ')}, /* Zenaga -> Berber */
- {"zgb", HB_TAG('Z','H','A',' ')}, /* Guibei Zhuang -> Zhuang */
- {"zgh", HB_TAG('Z','G','H',' ')}, /* Standard Moroccan Tamazight */
- {"zgh", HB_TAG('B','B','R',' ')}, /* Standard Moroccan Tamazight -> Berber */
- {"zgm", HB_TAG('Z','H','A',' ')}, /* Minz Zhuang -> Zhuang */
- {"zgn", HB_TAG('Z','H','A',' ')}, /* Guibian Zhuang -> Zhuang */
- {"zh", HB_TAG('Z','H','S',' ')}, /* Chinese, Simplified [macrolanguage] */
- {"zhd", HB_TAG('Z','H','A',' ')}, /* Dai Zhuang -> Zhuang */
- {"zhn", HB_TAG('Z','H','A',' ')}, /* Nong Zhuang -> Zhuang */
- {"zlj", HB_TAG('Z','H','A',' ')}, /* Liujiang Zhuang -> Zhuang */
- {"zlm", HB_TAG('M','L','Y',' ')}, /* Malay */
- {"zln", HB_TAG('Z','H','A',' ')}, /* Lianshan Zhuang -> Zhuang */
- {"zlq", HB_TAG('Z','H','A',' ')}, /* Liuqian Zhuang -> Zhuang */
- {"zmi", HB_TAG('M','L','Y',' ')}, /* Negeri Sembilan Malay -> Malay */
- {"zmz", HB_TAG('B','A','D','0')}, /* Mbandja -> Banda */
- {"znd", HB_TAG_NONE }, /* Zande [collection] != Zande */
- {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */
- {"zom", HB_TAG('Q','I','N',' ')}, /* Zou -> Chin */
- {"zqe", HB_TAG('Z','H','A',' ')}, /* Qiubei Zhuang -> Zhuang */
- {"zsm", HB_TAG('M','L','Y',' ')}, /* Standard Malay -> Malay */
- {"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */
- {"zum", HB_TAG('L','R','C',' ')}, /* Kumzari -> Luri */
- {"zyb", HB_TAG('Z','H','A',' ')}, /* Yongbei Zhuang -> Zhuang */
- {"zyg", HB_TAG('Z','H','A',' ')}, /* Yang Zhuang -> Zhuang */
- {"zyj", HB_TAG('Z','H','A',' ')}, /* Youjiang Zhuang -> Zhuang */
- {"zyn", HB_TAG('Z','H','A',' ')}, /* Yongnan Zhuang -> Zhuang */
- {"zyp", HB_TAG('Q','I','N',' ')}, /* Zyphe Chin -> Chin */
-/*{"zza", HB_TAG('Z','Z','A',' ')},*/ /* Zazaki [macrolanguage] */
- {"zzj", HB_TAG('Z','H','A',' ')}, /* Zuojiang Zhuang -> Zhuang */
+static const LangTag ot_languages2[] = {
+ {HB_TAG('a','a',' ',' '), HB_TAG('A','F','R',' ')}, /* Afar */
+ {HB_TAG('a','b',' ',' '), HB_TAG('A','B','K',' ')}, /* Abkhazian */
+ {HB_TAG('a','f',' ',' '), HB_TAG('A','F','K',' ')}, /* Afrikaans */
+ {HB_TAG('a','k',' ',' '), HB_TAG('A','K','A',' ')}, /* Akan [macrolanguage] */
+ {HB_TAG('a','m',' ',' '), HB_TAG('A','M','H',' ')}, /* Amharic */
+ {HB_TAG('a','n',' ',' '), HB_TAG('A','R','G',' ')}, /* Aragonese */
+ {HB_TAG('a','r',' ',' '), HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */
+ {HB_TAG('a','s',' ',' '), HB_TAG('A','S','M',' ')}, /* Assamese */
+ {HB_TAG('a','v',' ',' '), HB_TAG('A','V','R',' ')}, /* Avaric -> Avar */
+ {HB_TAG('a','y',' ',' '), HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */
+ {HB_TAG('a','z',' ',' '), HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */
+ {HB_TAG('b','a',' ',' '), HB_TAG('B','S','H',' ')}, /* Bashkir */
+ {HB_TAG('b','e',' ',' '), HB_TAG('B','E','L',' ')}, /* Belarusian -> Belarussian */
+ {HB_TAG('b','g',' ',' '), HB_TAG('B','G','R',' ')}, /* Bulgarian */
+ {HB_TAG('b','i',' ',' '), HB_TAG('B','I','S',' ')}, /* Bislama */
+ {HB_TAG('b','i',' ',' '), HB_TAG('C','P','P',' ')}, /* Bislama -> Creoles */
+ {HB_TAG('b','m',' ',' '), HB_TAG('B','M','B',' ')}, /* Bambara (Bamanankan) */
+ {HB_TAG('b','n',' ',' '), HB_TAG('B','E','N',' ')}, /* Bengali */
+ {HB_TAG('b','o',' ',' '), HB_TAG('T','I','B',' ')}, /* Tibetan */
+ {HB_TAG('b','r',' ',' '), HB_TAG('B','R','E',' ')}, /* Breton */
+ {HB_TAG('b','s',' ',' '), HB_TAG('B','O','S',' ')}, /* Bosnian */
+ {HB_TAG('c','a',' ',' '), HB_TAG('C','A','T',' ')}, /* Catalan */
+ {HB_TAG('c','e',' ',' '), HB_TAG('C','H','E',' ')}, /* Chechen */
+ {HB_TAG('c','h',' ',' '), HB_TAG('C','H','A',' ')}, /* Chamorro */
+ {HB_TAG('c','o',' ',' '), HB_TAG('C','O','S',' ')}, /* Corsican */
+ {HB_TAG('c','r',' ',' '), HB_TAG('C','R','E',' ')}, /* Cree [macrolanguage] */
+ {HB_TAG('c','s',' ',' '), HB_TAG('C','S','Y',' ')}, /* Czech */
+ {HB_TAG('c','u',' ',' '), HB_TAG('C','S','L',' ')}, /* Church Slavonic */
+ {HB_TAG('c','v',' ',' '), HB_TAG('C','H','U',' ')}, /* Chuvash */
+ {HB_TAG('c','y',' ',' '), HB_TAG('W','E','L',' ')}, /* Welsh */
+ {HB_TAG('d','a',' ',' '), HB_TAG('D','A','N',' ')}, /* Danish */
+ {HB_TAG('d','e',' ',' '), HB_TAG('D','E','U',' ')}, /* German */
+ {HB_TAG('d','v',' ',' '), HB_TAG('D','I','V',' ')}, /* Divehi (Dhivehi, Maldivian) */
+ {HB_TAG('d','v',' ',' '), HB_TAG('D','H','V',' ')}, /* Divehi (Dhivehi, Maldivian) (deprecated) */
+ {HB_TAG('d','z',' ',' '), HB_TAG('D','Z','N',' ')}, /* Dzongkha */
+ {HB_TAG('e','e',' ',' '), HB_TAG('E','W','E',' ')}, /* Ewe */
+ {HB_TAG('e','l',' ',' '), HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) -> Greek */
+ {HB_TAG('e','n',' ',' '), HB_TAG('E','N','G',' ')}, /* English */
+ {HB_TAG('e','o',' ',' '), HB_TAG('N','T','O',' ')}, /* Esperanto */
+ {HB_TAG('e','s',' ',' '), HB_TAG('E','S','P',' ')}, /* Spanish */
+ {HB_TAG('e','t',' ',' '), HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */
+ {HB_TAG('e','u',' ',' '), HB_TAG('E','U','Q',' ')}, /* Basque */
+ {HB_TAG('f','a',' ',' '), HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */
+ {HB_TAG('f','f',' ',' '), HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */
+ {HB_TAG('f','i',' ',' '), HB_TAG('F','I','N',' ')}, /* Finnish */
+ {HB_TAG('f','j',' ',' '), HB_TAG('F','J','I',' ')}, /* Fijian */
+ {HB_TAG('f','o',' ',' '), HB_TAG('F','O','S',' ')}, /* Faroese */
+ {HB_TAG('f','r',' ',' '), HB_TAG('F','R','A',' ')}, /* French */
+ {HB_TAG('f','y',' ',' '), HB_TAG('F','R','I',' ')}, /* Western Frisian -> Frisian */
+ {HB_TAG('g','a',' ',' '), HB_TAG('I','R','I',' ')}, /* Irish */
+ {HB_TAG('g','d',' ',' '), HB_TAG('G','A','E',' ')}, /* Scottish Gaelic (Gaelic) */
+ {HB_TAG('g','l',' ',' '), HB_TAG('G','A','L',' ')}, /* Galician */
+ {HB_TAG('g','n',' ',' '), HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */
+ {HB_TAG('g','u',' ',' '), HB_TAG('G','U','J',' ')}, /* Gujarati */
+ {HB_TAG('g','v',' ',' '), HB_TAG('M','N','X',' ')}, /* Manx */
+ {HB_TAG('h','a',' ',' '), HB_TAG('H','A','U',' ')}, /* Hausa */
+ {HB_TAG('h','e',' ',' '), HB_TAG('I','W','R',' ')}, /* Hebrew */
+ {HB_TAG('h','i',' ',' '), HB_TAG('H','I','N',' ')}, /* Hindi */
+ {HB_TAG('h','o',' ',' '), HB_TAG('H','M','O',' ')}, /* Hiri Motu */
+ {HB_TAG('h','o',' ',' '), HB_TAG('C','P','P',' ')}, /* Hiri Motu -> Creoles */
+ {HB_TAG('h','r',' ',' '), HB_TAG('H','R','V',' ')}, /* Croatian */
+ {HB_TAG('h','t',' ',' '), HB_TAG('H','A','I',' ')}, /* Haitian (Haitian Creole) */
+ {HB_TAG('h','t',' ',' '), HB_TAG('C','P','P',' ')}, /* Haitian -> Creoles */
+ {HB_TAG('h','u',' ',' '), HB_TAG('H','U','N',' ')}, /* Hungarian */
+ {HB_TAG('h','y',' ',' '), HB_TAG('H','Y','E','0')}, /* Armenian -> Armenian East */
+ {HB_TAG('h','y',' ',' '), HB_TAG('H','Y','E',' ')}, /* Armenian */
+ {HB_TAG('h','z',' ',' '), HB_TAG('H','E','R',' ')}, /* Herero */
+ {HB_TAG('i','a',' ',' '), HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */
+ {HB_TAG('i','d',' ',' '), HB_TAG('I','N','D',' ')}, /* Indonesian */
+ {HB_TAG('i','d',' ',' '), HB_TAG('M','L','Y',' ')}, /* Indonesian -> Malay */
+ {HB_TAG('i','e',' ',' '), HB_TAG('I','L','E',' ')}, /* Interlingue */
+ {HB_TAG('i','g',' ',' '), HB_TAG('I','B','O',' ')}, /* Igbo */
+ {HB_TAG('i','i',' ',' '), HB_TAG('Y','I','M',' ')}, /* Sichuan Yi -> Yi Modern */
+ {HB_TAG('i','k',' ',' '), HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] -> Inupiat */
+ {HB_TAG('i','n',' ',' '), HB_TAG('I','N','D',' ')}, /* Indonesian (retired code) */
+ {HB_TAG('i','n',' ',' '), HB_TAG('M','L','Y',' ')}, /* Indonesian (retired code) -> Malay */
+ {HB_TAG('i','o',' ',' '), HB_TAG('I','D','O',' ')}, /* Ido */
+ {HB_TAG('i','s',' ',' '), HB_TAG('I','S','L',' ')}, /* Icelandic */
+ {HB_TAG('i','t',' ',' '), HB_TAG('I','T','A',' ')}, /* Italian */
+ {HB_TAG('i','u',' ',' '), HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */
+ {HB_TAG('i','u',' ',' '), HB_TAG('I','N','U','K')}, /* Inuktitut [macrolanguage] -> Nunavik Inuktitut */
+ {HB_TAG('i','w',' ',' '), HB_TAG('I','W','R',' ')}, /* Hebrew (retired code) */
+ {HB_TAG('j','a',' ',' '), HB_TAG('J','A','N',' ')}, /* Japanese */
+ {HB_TAG('j','i',' ',' '), HB_TAG('J','I','I',' ')}, /* Yiddish (retired code) */
+ {HB_TAG('j','v',' ',' '), HB_TAG('J','A','V',' ')}, /* Javanese */
+ {HB_TAG('j','w',' ',' '), HB_TAG('J','A','V',' ')}, /* Javanese (retired code) */
+ {HB_TAG('k','a',' ',' '), HB_TAG('K','A','T',' ')}, /* Georgian */
+ {HB_TAG('k','g',' ',' '), HB_TAG('K','O','N','0')}, /* Kongo [macrolanguage] */
+ {HB_TAG('k','i',' ',' '), HB_TAG('K','I','K',' ')}, /* Kikuyu (Gikuyu) */
+ {HB_TAG('k','j',' ',' '), HB_TAG('K','U','A',' ')}, /* Kuanyama */
+ {HB_TAG('k','k',' ',' '), HB_TAG('K','A','Z',' ')}, /* Kazakh */
+ {HB_TAG('k','l',' ',' '), HB_TAG('G','R','N',' ')}, /* Greenlandic */
+ {HB_TAG('k','m',' ',' '), HB_TAG('K','H','M',' ')}, /* Khmer */
+ {HB_TAG('k','n',' ',' '), HB_TAG('K','A','N',' ')}, /* Kannada */
+ {HB_TAG('k','o',' ',' '), HB_TAG('K','O','R',' ')}, /* Korean */
+ {HB_TAG('k','o',' ',' '), HB_TAG('K','O','H',' ')}, /* Korean -> Korean Old Hangul */
+ {HB_TAG('k','r',' ',' '), HB_TAG('K','N','R',' ')}, /* Kanuri [macrolanguage] */
+ {HB_TAG('k','s',' ',' '), HB_TAG('K','S','H',' ')}, /* Kashmiri */
+ {HB_TAG('k','u',' ',' '), HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */
+ {HB_TAG('k','v',' ',' '), HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */
+ {HB_TAG('k','w',' ',' '), HB_TAG('C','O','R',' ')}, /* Cornish */
+ {HB_TAG('k','y',' ',' '), HB_TAG('K','I','R',' ')}, /* Kirghiz (Kyrgyz) */
+ {HB_TAG('l','a',' ',' '), HB_TAG('L','A','T',' ')}, /* Latin */
+ {HB_TAG('l','b',' ',' '), HB_TAG('L','T','Z',' ')}, /* Luxembourgish */
+ {HB_TAG('l','g',' ',' '), HB_TAG('L','U','G',' ')}, /* Ganda */
+ {HB_TAG('l','i',' ',' '), HB_TAG('L','I','M',' ')}, /* Limburgish */
+ {HB_TAG('l','n',' ',' '), HB_TAG('L','I','N',' ')}, /* Lingala */
+ {HB_TAG('l','o',' ',' '), HB_TAG('L','A','O',' ')}, /* Lao */
+ {HB_TAG('l','t',' ',' '), HB_TAG('L','T','H',' ')}, /* Lithuanian */
+ {HB_TAG('l','u',' ',' '), HB_TAG('L','U','B',' ')}, /* Luba-Katanga */
+ {HB_TAG('l','v',' ',' '), HB_TAG('L','V','I',' ')}, /* Latvian [macrolanguage] */
+ {HB_TAG('m','g',' ',' '), HB_TAG('M','L','G',' ')}, /* Malagasy [macrolanguage] */
+ {HB_TAG('m','h',' ',' '), HB_TAG('M','A','H',' ')}, /* Marshallese */
+ {HB_TAG('m','i',' ',' '), HB_TAG('M','R','I',' ')}, /* Maori */
+ {HB_TAG('m','k',' ',' '), HB_TAG('M','K','D',' ')}, /* Macedonian */
+ {HB_TAG('m','l',' ',' '), HB_TAG('M','A','L',' ')}, /* Malayalam -> Malayalam Traditional */
+ {HB_TAG('m','l',' ',' '), HB_TAG('M','L','R',' ')}, /* Malayalam -> Malayalam Reformed */
+ {HB_TAG('m','n',' ',' '), HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */
+ {HB_TAG('m','o',' ',' '), HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */
+ {HB_TAG('m','o',' ',' '), HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */
+ {HB_TAG('m','r',' ',' '), HB_TAG('M','A','R',' ')}, /* Marathi */
+ {HB_TAG('m','s',' ',' '), HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */
+ {HB_TAG('m','t',' ',' '), HB_TAG('M','T','S',' ')}, /* Maltese */
+ {HB_TAG('m','y',' ',' '), HB_TAG('B','R','M',' ')}, /* Burmese */
+ {HB_TAG('n','a',' ',' '), HB_TAG('N','A','U',' ')}, /* Nauru -> Nauruan */
+ {HB_TAG('n','b',' ',' '), HB_TAG('N','O','R',' ')}, /* Norwegian Bokmål -> Norwegian */
+ {HB_TAG('n','d',' ',' '), HB_TAG('N','D','B',' ')}, /* North Ndebele -> Ndebele */
+ {HB_TAG('n','e',' ',' '), HB_TAG('N','E','P',' ')}, /* Nepali [macrolanguage] */
+ {HB_TAG('n','g',' ',' '), HB_TAG('N','D','G',' ')}, /* Ndonga */
+ {HB_TAG('n','l',' ',' '), HB_TAG('N','L','D',' ')}, /* Dutch */
+ {HB_TAG('n','n',' ',' '), HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+ {HB_TAG('n','o',' ',' '), HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */
+ {HB_TAG('n','r',' ',' '), HB_TAG('N','D','B',' ')}, /* South Ndebele -> Ndebele */
+ {HB_TAG('n','v',' ',' '), HB_TAG('N','A','V',' ')}, /* Navajo */
+ {HB_TAG('n','v',' ',' '), HB_TAG('A','T','H',' ')}, /* Navajo -> Athapaskan */
+ {HB_TAG('n','y',' ',' '), HB_TAG('C','H','I',' ')}, /* Chichewa (Chewa, Nyanja) */
+ {HB_TAG('o','c',' ',' '), HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */
+ {HB_TAG('o','j',' ',' '), HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] -> Ojibway */
+ {HB_TAG('o','m',' ',' '), HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */
+ {HB_TAG('o','r',' ',' '), HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) [macrolanguage] */
+ {HB_TAG('o','s',' ',' '), HB_TAG('O','S','S',' ')}, /* Ossetian */
+ {HB_TAG('p','a',' ',' '), HB_TAG('P','A','N',' ')}, /* Punjabi */
+ {HB_TAG('p','i',' ',' '), HB_TAG('P','A','L',' ')}, /* Pali */
+ {HB_TAG('p','l',' ',' '), HB_TAG('P','L','K',' ')}, /* Polish */
+ {HB_TAG('p','s',' ',' '), HB_TAG('P','A','S',' ')}, /* Pashto [macrolanguage] */
+ {HB_TAG('p','t',' ',' '), HB_TAG('P','T','G',' ')}, /* Portuguese */
+ {HB_TAG('q','u',' ',' '), HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */
+ {HB_TAG('r','m',' ',' '), HB_TAG('R','M','S',' ')}, /* Romansh */
+ {HB_TAG('r','n',' ',' '), HB_TAG('R','U','N',' ')}, /* Rundi */
+ {HB_TAG('r','o',' ',' '), HB_TAG('R','O','M',' ')}, /* Romanian */
+ {HB_TAG('r','u',' ',' '), HB_TAG('R','U','S',' ')}, /* Russian */
+ {HB_TAG('r','w',' ',' '), HB_TAG('R','U','A',' ')}, /* Kinyarwanda */
+ {HB_TAG('s','a',' ',' '), HB_TAG('S','A','N',' ')}, /* Sanskrit */
+ {HB_TAG('s','c',' ',' '), HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */
+ {HB_TAG('s','d',' ',' '), HB_TAG('S','N','D',' ')}, /* Sindhi */
+ {HB_TAG('s','e',' ',' '), HB_TAG('N','S','M',' ')}, /* Northern Sami */
+ {HB_TAG('s','g',' ',' '), HB_TAG('S','G','O',' ')}, /* Sango */
+ {HB_TAG('s','h',' ',' '), HB_TAG('B','O','S',' ')}, /* Serbo-Croatian [macrolanguage] -> Bosnian */
+ {HB_TAG('s','h',' ',' '), HB_TAG('H','R','V',' ')}, /* Serbo-Croatian [macrolanguage] -> Croatian */
+ {HB_TAG('s','h',' ',' '), HB_TAG('S','R','B',' ')}, /* Serbo-Croatian [macrolanguage] -> Serbian */
+ {HB_TAG('s','i',' ',' '), HB_TAG('S','N','H',' ')}, /* Sinhala (Sinhalese) */
+ {HB_TAG('s','k',' ',' '), HB_TAG('S','K','Y',' ')}, /* Slovak */
+ {HB_TAG('s','l',' ',' '), HB_TAG('S','L','V',' ')}, /* Slovenian */
+ {HB_TAG('s','m',' ',' '), HB_TAG('S','M','O',' ')}, /* Samoan */
+ {HB_TAG('s','n',' ',' '), HB_TAG('S','N','A','0')}, /* Shona */
+ {HB_TAG('s','o',' ',' '), HB_TAG('S','M','L',' ')}, /* Somali */
+ {HB_TAG('s','q',' ',' '), HB_TAG('S','Q','I',' ')}, /* Albanian [macrolanguage] */
+ {HB_TAG('s','r',' ',' '), HB_TAG('S','R','B',' ')}, /* Serbian */
+ {HB_TAG('s','s',' ',' '), HB_TAG('S','W','Z',' ')}, /* Swati */
+ {HB_TAG('s','t',' ',' '), HB_TAG('S','O','T',' ')}, /* Southern Sotho */
+ {HB_TAG('s','u',' ',' '), HB_TAG('S','U','N',' ')}, /* Sundanese */
+ {HB_TAG('s','v',' ',' '), HB_TAG('S','V','E',' ')}, /* Swedish */
+ {HB_TAG('s','w',' ',' '), HB_TAG('S','W','K',' ')}, /* Swahili [macrolanguage] */
+ {HB_TAG('t','a',' ',' '), HB_TAG('T','A','M',' ')}, /* Tamil */
+ {HB_TAG('t','e',' ',' '), HB_TAG('T','E','L',' ')}, /* Telugu */
+ {HB_TAG('t','g',' ',' '), HB_TAG('T','A','J',' ')}, /* Tajik -> Tajiki */
+ {HB_TAG('t','h',' ',' '), HB_TAG('T','H','A',' ')}, /* Thai */
+ {HB_TAG('t','i',' ',' '), HB_TAG('T','G','Y',' ')}, /* Tigrinya */
+ {HB_TAG('t','k',' ',' '), HB_TAG('T','K','M',' ')}, /* Turkmen */
+ {HB_TAG('t','l',' ',' '), HB_TAG('T','G','L',' ')}, /* Tagalog */
+ {HB_TAG('t','n',' ',' '), HB_TAG('T','N','A',' ')}, /* Tswana */
+ {HB_TAG('t','o',' ',' '), HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) -> Tongan */
+ {HB_TAG('t','r',' ',' '), HB_TAG('T','R','K',' ')}, /* Turkish */
+ {HB_TAG('t','s',' ',' '), HB_TAG('T','S','G',' ')}, /* Tsonga */
+ {HB_TAG('t','t',' ',' '), HB_TAG('T','A','T',' ')}, /* Tatar */
+ {HB_TAG('t','w',' ',' '), HB_TAG('T','W','I',' ')}, /* Twi */
+ {HB_TAG('t','w',' ',' '), HB_TAG('A','K','A',' ')}, /* Twi -> Akan */
+ {HB_TAG('t','y',' ',' '), HB_TAG('T','H','T',' ')}, /* Tahitian */
+ {HB_TAG('u','g',' ',' '), HB_TAG('U','Y','G',' ')}, /* Uyghur */
+ {HB_TAG('u','k',' ',' '), HB_TAG('U','K','R',' ')}, /* Ukrainian */
+ {HB_TAG('u','r',' ',' '), HB_TAG('U','R','D',' ')}, /* Urdu */
+ {HB_TAG('u','z',' ',' '), HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */
+ {HB_TAG('v','e',' ',' '), HB_TAG('V','E','N',' ')}, /* Venda */
+ {HB_TAG('v','i',' ',' '), HB_TAG('V','I','T',' ')}, /* Vietnamese */
+ {HB_TAG('v','o',' ',' '), HB_TAG('V','O','L',' ')}, /* Volapük */
+ {HB_TAG('w','a',' ',' '), HB_TAG('W','L','N',' ')}, /* Walloon */
+ {HB_TAG('w','o',' ',' '), HB_TAG('W','L','F',' ')}, /* Wolof */
+ {HB_TAG('x','h',' ',' '), HB_TAG('X','H','S',' ')}, /* Xhosa */
+ {HB_TAG('y','i',' ',' '), HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */
+ {HB_TAG('y','o',' ',' '), HB_TAG('Y','B','A',' ')}, /* Yoruba */
+ {HB_TAG('z','a',' ',' '), HB_TAG('Z','H','A',' ')}, /* Zhuang [macrolanguage] */
+ {HB_TAG('z','h',' ',' '), HB_TAG('Z','H','S',' ')}, /* Chinese, Simplified [macrolanguage] */
+ {HB_TAG('z','u',' ',' '), HB_TAG('Z','U','L',' ')}, /* Zulu */
};
+#ifndef HB_NO_LANGUAGE_LONG
+static const LangTag ot_languages3[] = {
+ {HB_TAG('a','a','e',' '), HB_TAG('S','Q','I',' ')}, /* Arbëreshë Albanian -> Albanian */
+ {HB_TAG('a','a','o',' '), HB_TAG('A','R','A',' ')}, /* Algerian Saharan Arabic -> Arabic */
+ {HB_TAG('a','a','t',' '), HB_TAG('S','Q','I',' ')}, /* Arvanitika Albanian -> Albanian */
+ {HB_TAG('a','b','a',' '), HB_TAG_NONE }, /* Abé != Abaza */
+ {HB_TAG('a','b','h',' '), HB_TAG('A','R','A',' ')}, /* Tajiki Arabic -> Arabic */
+ {HB_TAG('a','b','q',' '), HB_TAG('A','B','A',' ')}, /* Abaza */
+ {HB_TAG('a','b','s',' '), HB_TAG('C','P','P',' ')}, /* Ambonese Malay -> Creoles */
+ {HB_TAG('a','b','v',' '), HB_TAG('A','R','A',' ')}, /* Baharna Arabic -> Arabic */
+ {HB_TAG('a','c','f',' '), HB_TAG('F','A','N',' ')}, /* Saint Lucian Creole French -> French Antillean */
+ {HB_TAG('a','c','f',' '), HB_TAG('C','P','P',' ')}, /* Saint Lucian Creole French -> Creoles */
+/*{HB_TAG('a','c','h',' '), HB_TAG('A','C','H',' ')},*/ /* Acoli -> Acholi */
+ {HB_TAG('a','c','m',' '), HB_TAG('A','R','A',' ')}, /* Mesopotamian Arabic -> Arabic */
+ {HB_TAG('a','c','q',' '), HB_TAG('A','R','A',' ')}, /* Ta'izzi-Adeni Arabic -> Arabic */
+ {HB_TAG('a','c','r',' '), HB_TAG('A','C','R',' ')}, /* Achi */
+ {HB_TAG('a','c','r',' '), HB_TAG('M','Y','N',' ')}, /* Achi -> Mayan */
+ {HB_TAG('a','c','w',' '), HB_TAG('A','R','A',' ')}, /* Hijazi Arabic -> Arabic */
+ {HB_TAG('a','c','x',' '), HB_TAG('A','R','A',' ')}, /* Omani Arabic -> Arabic */
+ {HB_TAG('a','c','y',' '), HB_TAG('A','R','A',' ')}, /* Cypriot Arabic -> Arabic */
+ {HB_TAG('a','d','a',' '), HB_TAG('D','N','G',' ')}, /* Adangme -> Dangme */
+ {HB_TAG('a','d','f',' '), HB_TAG('A','R','A',' ')}, /* Dhofari Arabic -> Arabic */
+ {HB_TAG('a','d','p',' '), HB_TAG('D','Z','N',' ')}, /* Adap (retired code) -> Dzongkha */
+/*{HB_TAG('a','d','y',' '), HB_TAG('A','D','Y',' ')},*/ /* Adyghe */
+ {HB_TAG('a','e','b',' '), HB_TAG('A','R','A',' ')}, /* Tunisian Arabic -> Arabic */
+ {HB_TAG('a','e','c',' '), HB_TAG('A','R','A',' ')}, /* Saidi Arabic -> Arabic */
+ {HB_TAG('a','f','b',' '), HB_TAG('A','R','A',' ')}, /* Gulf Arabic -> Arabic */
+ {HB_TAG('a','f','k',' '), HB_TAG_NONE }, /* Nanubae != Afrikaans */
+ {HB_TAG('a','f','s',' '), HB_TAG('C','P','P',' ')}, /* Afro-Seminole Creole -> Creoles */
+ {HB_TAG('a','g','u',' '), HB_TAG('M','Y','N',' ')}, /* Aguacateco -> Mayan */
+ {HB_TAG('a','g','w',' '), HB_TAG_NONE }, /* Kahua != Agaw */
+ {HB_TAG('a','h','g',' '), HB_TAG('A','G','W',' ')}, /* Qimant -> Agaw */
+ {HB_TAG('a','h','t',' '), HB_TAG('A','T','H',' ')}, /* Ahtena -> Athapaskan */
+ {HB_TAG('a','i','g',' '), HB_TAG('C','P','P',' ')}, /* Antigua and Barbuda Creole English -> Creoles */
+ {HB_TAG('a','i','i',' '), HB_TAG('S','W','A',' ')}, /* Assyrian Neo-Aramaic -> Swadaya Aramaic */
+ {HB_TAG('a','i','i',' '), HB_TAG('S','Y','R',' ')}, /* Assyrian Neo-Aramaic -> Syriac */
+/*{HB_TAG('a','i','o',' '), HB_TAG('A','I','O',' ')},*/ /* Aiton */
+ {HB_TAG('a','i','w',' '), HB_TAG('A','R','I',' ')}, /* Aari */
+ {HB_TAG('a','j','p',' '), HB_TAG('A','R','A',' ')}, /* South Levantine Arabic -> Arabic */
+ {HB_TAG('a','j','t',' '), HB_TAG('A','R','A',' ')}, /* Judeo-Tunisian Arabic (retired code) -> Arabic */
+ {HB_TAG('a','k','b',' '), HB_TAG('A','K','B',' ')}, /* Batak Angkola */
+ {HB_TAG('a','k','b',' '), HB_TAG('B','T','K',' ')}, /* Batak Angkola -> Batak */
+ {HB_TAG('a','l','n',' '), HB_TAG('S','Q','I',' ')}, /* Gheg Albanian -> Albanian */
+ {HB_TAG('a','l','s',' '), HB_TAG('S','Q','I',' ')}, /* Tosk Albanian -> Albanian */
+/*{HB_TAG('a','l','t',' '), HB_TAG('A','L','T',' ')},*/ /* Southern Altai -> Altai */
+ {HB_TAG('a','m','f',' '), HB_TAG('H','B','N',' ')}, /* Hamer-Banna -> Hammer-Banna */
+ {HB_TAG('a','m','w',' '), HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic -> Syriac */
+/*{HB_TAG('a','n','g',' '), HB_TAG('A','N','G',' ')},*/ /* Old English (ca. 450-1100) -> Anglo-Saxon */
+ {HB_TAG('a','o','a',' '), HB_TAG('C','P','P',' ')}, /* Angolar -> Creoles */
+ {HB_TAG('a','p','a',' '), HB_TAG('A','T','H',' ')}, /* Apache [collection] -> Athapaskan */
+ {HB_TAG('a','p','c',' '), HB_TAG('A','R','A',' ')}, /* North Levantine Arabic -> Arabic */
+ {HB_TAG('a','p','d',' '), HB_TAG('A','R','A',' ')}, /* Sudanese Arabic -> Arabic */
+ {HB_TAG('a','p','j',' '), HB_TAG('A','T','H',' ')}, /* Jicarilla Apache -> Athapaskan */
+ {HB_TAG('a','p','k',' '), HB_TAG('A','T','H',' ')}, /* Kiowa Apache -> Athapaskan */
+ {HB_TAG('a','p','l',' '), HB_TAG('A','T','H',' ')}, /* Lipan Apache -> Athapaskan */
+ {HB_TAG('a','p','m',' '), HB_TAG('A','T','H',' ')}, /* Mescalero-Chiricahua Apache -> Athapaskan */
+ {HB_TAG('a','p','w',' '), HB_TAG('A','T','H',' ')}, /* Western Apache -> Athapaskan */
+ {HB_TAG('a','r','b',' '), HB_TAG('A','R','A',' ')}, /* Standard Arabic -> Arabic */
+ {HB_TAG('a','r','i',' '), HB_TAG_NONE }, /* Arikara != Aari */
+ {HB_TAG('a','r','k',' '), HB_TAG_NONE }, /* Arikapú != Rakhine */
+ {HB_TAG('a','r','n',' '), HB_TAG('M','A','P',' ')}, /* Mapudungun */
+ {HB_TAG('a','r','q',' '), HB_TAG('A','R','A',' ')}, /* Algerian Arabic -> Arabic */
+ {HB_TAG('a','r','s',' '), HB_TAG('A','R','A',' ')}, /* Najdi Arabic -> Arabic */
+ {HB_TAG('a','r','y',' '), HB_TAG('M','O','R',' ')}, /* Moroccan Arabic -> Moroccan */
+ {HB_TAG('a','r','y',' '), HB_TAG('A','R','A',' ')}, /* Moroccan Arabic -> Arabic */
+ {HB_TAG('a','r','z',' '), HB_TAG('A','R','A',' ')}, /* Egyptian Arabic -> Arabic */
+/*{HB_TAG('a','s','t',' '), HB_TAG('A','S','T',' ')},*/ /* Asturian */
+/*{HB_TAG('a','t','h',' '), HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */
+ {HB_TAG('a','t','j',' '), HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */
+ {HB_TAG('a','t','v',' '), HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */
+ {HB_TAG('a','u','j',' '), HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */
+ {HB_TAG('a','u','z',' '), HB_TAG('A','R','A',' ')}, /* Uzbeki Arabic -> Arabic */
+ {HB_TAG('a','v','l',' '), HB_TAG('A','R','A',' ')}, /* Eastern Egyptian Bedawi Arabic -> Arabic */
+/*{HB_TAG('a','v','n',' '), HB_TAG('A','V','N',' ')},*/ /* Avatime */
+/*{HB_TAG('a','w','a',' '), HB_TAG('A','W','A',' ')},*/ /* Awadhi */
+ {HB_TAG('a','y','c',' '), HB_TAG('A','Y','M',' ')}, /* Southern Aymara -> Aymara */
+ {HB_TAG('a','y','h',' '), HB_TAG('A','R','A',' ')}, /* Hadrami Arabic -> Arabic */
+ {HB_TAG('a','y','l',' '), HB_TAG('A','R','A',' ')}, /* Libyan Arabic -> Arabic */
+ {HB_TAG('a','y','n',' '), HB_TAG('A','R','A',' ')}, /* Sanaani Arabic -> Arabic */
+ {HB_TAG('a','y','p',' '), HB_TAG('A','R','A',' ')}, /* North Mesopotamian Arabic -> Arabic */
+ {HB_TAG('a','y','r',' '), HB_TAG('A','Y','M',' ')}, /* Central Aymara -> Aymara */
+ {HB_TAG('a','z','b',' '), HB_TAG('A','Z','B',' ')}, /* South Azerbaijani -> Torki */
+ {HB_TAG('a','z','b',' '), HB_TAG('A','Z','E',' ')}, /* South Azerbaijani -> Azerbaijani */
+ {HB_TAG('a','z','d',' '), HB_TAG('N','A','H',' ')}, /* Eastern Durango Nahuatl -> Nahuatl */
+ {HB_TAG('a','z','j',' '), HB_TAG('A','Z','E',' ')}, /* North Azerbaijani -> Azerbaijani */
+ {HB_TAG('a','z','n',' '), HB_TAG('N','A','H',' ')}, /* Western Durango Nahuatl -> Nahuatl */
+ {HB_TAG('a','z','z',' '), HB_TAG('N','A','H',' ')}, /* Highland Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('b','a','d',' '), HB_TAG('B','A','D','0')}, /* Banda [collection] */
+ {HB_TAG('b','a','g',' '), HB_TAG_NONE }, /* Tuki != Baghelkhandi */
+ {HB_TAG('b','a','h',' '), HB_TAG('C','P','P',' ')}, /* Bahamas Creole English -> Creoles */
+ {HB_TAG('b','a','i',' '), HB_TAG('B','M','L',' ')}, /* Bamileke [collection] */
+ {HB_TAG('b','a','l',' '), HB_TAG('B','L','I',' ')}, /* Baluchi [macrolanguage] */
+/*{HB_TAG('b','a','n',' '), HB_TAG('B','A','N',' ')},*/ /* Balinese */
+/*{HB_TAG('b','a','r',' '), HB_TAG('B','A','R',' ')},*/ /* Bavarian */
+ {HB_TAG('b','a','u',' '), HB_TAG_NONE }, /* Bada (Nigeria) != Baulé */
+ {HB_TAG('b','b','c',' '), HB_TAG('B','B','C',' ')}, /* Batak Toba */
+ {HB_TAG('b','b','c',' '), HB_TAG('B','T','K',' ')}, /* Batak Toba -> Batak */
+ {HB_TAG('b','b','j',' '), HB_TAG('B','M','L',' ')}, /* Ghomálá' -> Bamileke */
+ {HB_TAG('b','b','p',' '), HB_TAG('B','A','D','0')}, /* West Central Banda -> Banda */
+ {HB_TAG('b','b','r',' '), HB_TAG_NONE }, /* Girawa != Berber */
+ {HB_TAG('b','b','z',' '), HB_TAG('A','R','A',' ')}, /* Babalia Creole Arabic (retired code) -> Arabic */
+ {HB_TAG('b','c','c',' '), HB_TAG('B','L','I',' ')}, /* Southern Balochi -> Baluchi */
+ {HB_TAG('b','c','h',' '), HB_TAG_NONE }, /* Bariai != Bench */
+ {HB_TAG('b','c','i',' '), HB_TAG('B','A','U',' ')}, /* Baoulé -> Baulé */
+ {HB_TAG('b','c','l',' '), HB_TAG('B','I','K',' ')}, /* Central Bikol -> Bikol */
+ {HB_TAG('b','c','q',' '), HB_TAG('B','C','H',' ')}, /* Bench */
+ {HB_TAG('b','c','r',' '), HB_TAG('A','T','H',' ')}, /* Babine -> Athapaskan */
+/*{HB_TAG('b','d','y',' '), HB_TAG('B','D','Y',' ')},*/ /* Bandjalang */
+ {HB_TAG('b','e','a',' '), HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */
+ {HB_TAG('b','e','b',' '), HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */
+/*{HB_TAG('b','e','m',' '), HB_TAG('B','E','M',' ')},*/ /* Bemba (Zambia) */
+ {HB_TAG('b','e','r',' '), HB_TAG('B','B','R',' ')}, /* Berber [collection] */
+ {HB_TAG('b','e','w',' '), HB_TAG('C','P','P',' ')}, /* Betawi -> Creoles */
+ {HB_TAG('b','f','l',' '), HB_TAG('B','A','D','0')}, /* Banda-Ndélé -> Banda */
+ {HB_TAG('b','f','q',' '), HB_TAG('B','A','D',' ')}, /* Badaga */
+ {HB_TAG('b','f','t',' '), HB_TAG('B','L','T',' ')}, /* Balti */
+ {HB_TAG('b','f','u',' '), HB_TAG('L','A','H',' ')}, /* Gahri -> Lahuli */
+ {HB_TAG('b','f','y',' '), HB_TAG('B','A','G',' ')}, /* Bagheli -> Baghelkhandi */
+/*{HB_TAG('b','g','c',' '), HB_TAG('B','G','C',' ')},*/ /* Haryanvi */
+ {HB_TAG('b','g','n',' '), HB_TAG('B','L','I',' ')}, /* Western Balochi -> Baluchi */
+ {HB_TAG('b','g','p',' '), HB_TAG('B','L','I',' ')}, /* Eastern Balochi -> Baluchi */
+ {HB_TAG('b','g','q',' '), HB_TAG('B','G','Q',' ')}, /* Bagri */
+ {HB_TAG('b','g','q',' '), HB_TAG('R','A','J',' ')}, /* Bagri -> Rajasthani */
+ {HB_TAG('b','g','r',' '), HB_TAG('Q','I','N',' ')}, /* Bawm Chin -> Chin */
+ {HB_TAG('b','h','b',' '), HB_TAG('B','H','I',' ')}, /* Bhili */
+/*{HB_TAG('b','h','i',' '), HB_TAG('B','H','I',' ')},*/ /* Bhilali -> Bhili */
+ {HB_TAG('b','h','k',' '), HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) -> Bikol */
+/*{HB_TAG('b','h','o',' '), HB_TAG('B','H','O',' ')},*/ /* Bhojpuri */
+ {HB_TAG('b','h','r',' '), HB_TAG('M','L','G',' ')}, /* Bara Malagasy -> Malagasy */
+/*{HB_TAG('b','i','k',' '), HB_TAG('B','I','K',' ')},*/ /* Bikol [macrolanguage] */
+ {HB_TAG('b','i','l',' '), HB_TAG_NONE }, /* Bile != Bilen */
+ {HB_TAG('b','i','n',' '), HB_TAG('E','D','O',' ')}, /* Edo */
+ {HB_TAG('b','i','u',' '), HB_TAG('Q','I','N',' ')}, /* Biete -> Chin */
+/*{HB_TAG('b','j','j',' '), HB_TAG('B','J','J',' ')},*/ /* Kanauji */
+ {HB_TAG('b','j','n',' '), HB_TAG('M','L','Y',' ')}, /* Banjar -> Malay */
+ {HB_TAG('b','j','o',' '), HB_TAG('B','A','D','0')}, /* Mid-Southern Banda -> Banda */
+ {HB_TAG('b','j','q',' '), HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
+ {HB_TAG('b','j','s',' '), HB_TAG('C','P','P',' ')}, /* Bajan -> Creoles */
+ {HB_TAG('b','j','t',' '), HB_TAG('B','L','N',' ')}, /* Balanta-Ganja -> Balante */
+ {HB_TAG('b','k','f',' '), HB_TAG_NONE }, /* Beeke != Blackfoot */
+ {HB_TAG('b','k','o',' '), HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */
+ {HB_TAG('b','l','a',' '), HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */
+ {HB_TAG('b','l','e',' '), HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */
+ {HB_TAG('b','l','g',' '), HB_TAG('I','B','A',' ')}, /* Balau (retired code) -> Iban */
+ {HB_TAG('b','l','i',' '), HB_TAG_NONE }, /* Bolia != Baluchi */
+ {HB_TAG('b','l','k',' '), HB_TAG('B','L','K',' ')}, /* Pa’o Karen */
+ {HB_TAG('b','l','k',' '), HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */
+ {HB_TAG('b','l','n',' '), HB_TAG('B','I','K',' ')}, /* Southern Catanduanes Bikol -> Bikol */
+ {HB_TAG('b','l','t',' '), HB_TAG_NONE }, /* Tai Dam != Balti */
+ {HB_TAG('b','m','b',' '), HB_TAG_NONE }, /* Bembe != Bambara (Bamanankan) */
+ {HB_TAG('b','m','l',' '), HB_TAG_NONE }, /* Bomboli != Bamileke */
+ {HB_TAG('b','m','m',' '), HB_TAG('M','L','G',' ')}, /* Northern Betsimisaraka Malagasy -> Malagasy */
+ {HB_TAG('b','p','d',' '), HB_TAG('B','A','D','0')}, /* Banda-Banda -> Banda */
+ {HB_TAG('b','p','l',' '), HB_TAG('C','P','P',' ')}, /* Broome Pearling Lugger Pidgin -> Creoles */
+ {HB_TAG('b','p','q',' '), HB_TAG('C','P','P',' ')}, /* Banda Malay -> Creoles */
+/*{HB_TAG('b','p','y',' '), HB_TAG('B','P','Y',' ')},*/ /* Bishnupriya -> Bishnupriya Manipuri */
+ {HB_TAG('b','q','i',' '), HB_TAG('L','R','C',' ')}, /* Bakhtiari -> Luri */
+ {HB_TAG('b','q','k',' '), HB_TAG('B','A','D','0')}, /* Banda-Mbrès -> Banda */
+ {HB_TAG('b','r','a',' '), HB_TAG('B','R','I',' ')}, /* Braj -> Braj Bhasha */
+ {HB_TAG('b','r','c',' '), HB_TAG('C','P','P',' ')}, /* Berbice Creole Dutch -> Creoles */
+/*{HB_TAG('b','r','h',' '), HB_TAG('B','R','H',' ')},*/ /* Brahui */
+ {HB_TAG('b','r','i',' '), HB_TAG_NONE }, /* Mokpwe != Braj Bhasha */
+ {HB_TAG('b','r','m',' '), HB_TAG_NONE }, /* Barambu != Burmese */
+/*{HB_TAG('b','r','x',' '), HB_TAG('B','R','X',' ')},*/ /* Bodo (India) */
+ {HB_TAG('b','s','h',' '), HB_TAG_NONE }, /* Kati != Bashkir */
+/*{HB_TAG('b','s','k',' '), HB_TAG('B','S','K',' ')},*/ /* Burushaski */
+ {HB_TAG('b','t','b',' '), HB_TAG('B','T','I',' ')}, /* Beti (Cameroon) (retired code) */
+ {HB_TAG('b','t','d',' '), HB_TAG('B','T','D',' ')}, /* Batak Dairi (Pakpak) */
+ {HB_TAG('b','t','d',' '), HB_TAG('B','T','K',' ')}, /* Batak Dairi -> Batak */
+ {HB_TAG('b','t','i',' '), HB_TAG_NONE }, /* Burate != Beti */
+ {HB_TAG('b','t','j',' '), HB_TAG('M','L','Y',' ')}, /* Bacanese Malay -> Malay */
+/*{HB_TAG('b','t','k',' '), HB_TAG('B','T','K',' ')},*/ /* Batak [collection] */
+ {HB_TAG('b','t','m',' '), HB_TAG('B','T','M',' ')}, /* Batak Mandailing */
+ {HB_TAG('b','t','m',' '), HB_TAG('B','T','K',' ')}, /* Batak Mandailing -> Batak */
+ {HB_TAG('b','t','o',' '), HB_TAG('B','I','K',' ')}, /* Rinconada Bikol -> Bikol */
+ {HB_TAG('b','t','s',' '), HB_TAG('B','T','S',' ')}, /* Batak Simalungun */
+ {HB_TAG('b','t','s',' '), HB_TAG('B','T','K',' ')}, /* Batak Simalungun -> Batak */
+ {HB_TAG('b','t','x',' '), HB_TAG('B','T','X',' ')}, /* Batak Karo */
+ {HB_TAG('b','t','x',' '), HB_TAG('B','T','K',' ')}, /* Batak Karo -> Batak */
+ {HB_TAG('b','t','z',' '), HB_TAG('B','T','Z',' ')}, /* Batak Alas-Kluet */
+ {HB_TAG('b','t','z',' '), HB_TAG('B','T','K',' ')}, /* Batak Alas-Kluet -> Batak */
+/*{HB_TAG('b','u','g',' '), HB_TAG('B','U','G',' ')},*/ /* Buginese -> Bugis */
+ {HB_TAG('b','u','m',' '), HB_TAG('B','T','I',' ')}, /* Bulu (Cameroon) -> Beti */
+ {HB_TAG('b','v','e',' '), HB_TAG('M','L','Y',' ')}, /* Berau Malay -> Malay */
+ {HB_TAG('b','v','u',' '), HB_TAG('M','L','Y',' ')}, /* Bukit Malay -> Malay */
+ {HB_TAG('b','w','e',' '), HB_TAG('K','R','N',' ')}, /* Bwe Karen -> Karen */
+ {HB_TAG('b','x','k',' '), HB_TAG('L','U','H',' ')}, /* Bukusu -> Luyia */
+ {HB_TAG('b','x','o',' '), HB_TAG('C','P','P',' ')}, /* Barikanchi -> Creoles */
+ {HB_TAG('b','x','p',' '), HB_TAG('B','T','I',' ')}, /* Bebil -> Beti */
+ {HB_TAG('b','x','r',' '), HB_TAG('R','B','U',' ')}, /* Russia Buriat -> Russian Buriat */
+ {HB_TAG('b','y','n',' '), HB_TAG('B','I','L',' ')}, /* Bilin -> Bilen */
+ {HB_TAG('b','y','v',' '), HB_TAG('B','Y','V',' ')}, /* Medumba */
+ {HB_TAG('b','y','v',' '), HB_TAG('B','M','L',' ')}, /* Medumba -> Bamileke */
+ {HB_TAG('b','z','c',' '), HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy -> Malagasy */
+ {HB_TAG('b','z','j',' '), HB_TAG('C','P','P',' ')}, /* Belize Kriol English -> Creoles */
+ {HB_TAG('b','z','k',' '), HB_TAG('C','P','P',' ')}, /* Nicaragua Creole English -> Creoles */
+ {HB_TAG('c','a','a',' '), HB_TAG('M','Y','N',' ')}, /* Chortí -> Mayan */
+ {HB_TAG('c','a','c',' '), HB_TAG('M','Y','N',' ')}, /* Chuj -> Mayan */
+ {HB_TAG('c','a','f',' '), HB_TAG('C','R','R',' ')}, /* Southern Carrier -> Carrier */
+ {HB_TAG('c','a','f',' '), HB_TAG('A','T','H',' ')}, /* Southern Carrier -> Athapaskan */
+ {HB_TAG('c','a','k',' '), HB_TAG('C','A','K',' ')}, /* Kaqchikel */
+ {HB_TAG('c','a','k',' '), HB_TAG('M','Y','N',' ')}, /* Kaqchikel -> Mayan */
+ {HB_TAG('c','b','k',' '), HB_TAG('C','B','K',' ')}, /* Chavacano -> Zamboanga Chavacano */
+ {HB_TAG('c','b','k',' '), HB_TAG('C','P','P',' ')}, /* Chavacano -> Creoles */
+ {HB_TAG('c','b','l',' '), HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin -> Chin */
+ {HB_TAG('c','c','l',' '), HB_TAG('C','P','P',' ')}, /* Cutchi-Swahili -> Creoles */
+ {HB_TAG('c','c','m',' '), HB_TAG('C','P','P',' ')}, /* Malaccan Creole Malay -> Creoles */
+ {HB_TAG('c','c','o',' '), HB_TAG('C','C','H','N')}, /* Comaltepec Chinantec -> Chinantec */
+ {HB_TAG('c','c','q',' '), HB_TAG('A','R','K',' ')}, /* Chaungtha (retired code) -> Rakhine */
+ {HB_TAG('c','d','o',' '), HB_TAG('Z','H','S',' ')}, /* Min Dong Chinese -> Chinese, Simplified */
+/*{HB_TAG('c','e','b',' '), HB_TAG('C','E','B',' ')},*/ /* Cebuano */
+ {HB_TAG('c','e','k',' '), HB_TAG('Q','I','N',' ')}, /* Eastern Khumi Chin -> Chin */
+ {HB_TAG('c','e','y',' '), HB_TAG('Q','I','N',' ')}, /* Ekai Chin -> Chin */
+ {HB_TAG('c','f','m',' '), HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) */
+ {HB_TAG('c','f','m',' '), HB_TAG('Q','I','N',' ')}, /* Falam Chin -> Chin */
+/*{HB_TAG('c','g','g',' '), HB_TAG('C','G','G',' ')},*/ /* Chiga */
+ {HB_TAG('c','h','f',' '), HB_TAG('M','Y','N',' ')}, /* Tabasco Chontal -> Mayan */
+ {HB_TAG('c','h','g',' '), HB_TAG_NONE }, /* Chagatai != Chaha Gurage */
+ {HB_TAG('c','h','h',' '), HB_TAG_NONE }, /* Chinook != Chattisgarhi */
+ {HB_TAG('c','h','j',' '), HB_TAG('C','C','H','N')}, /* Ojitlán Chinantec -> Chinantec */
+ {HB_TAG('c','h','k',' '), HB_TAG('C','H','K','0')}, /* Chuukese */
+ {HB_TAG('c','h','m',' '), HB_TAG('H','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> High Mari */
+ {HB_TAG('c','h','m',' '), HB_TAG('L','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> Low Mari */
+ {HB_TAG('c','h','n',' '), HB_TAG('C','P','P',' ')}, /* Chinook jargon -> Creoles */
+/*{HB_TAG('c','h','o',' '), HB_TAG('C','H','O',' ')},*/ /* Choctaw */
+ {HB_TAG('c','h','p',' '), HB_TAG('C','H','P',' ')}, /* Chipewyan */
+ {HB_TAG('c','h','p',' '), HB_TAG('S','A','Y',' ')}, /* Chipewyan -> Sayisi */
+ {HB_TAG('c','h','p',' '), HB_TAG('A','T','H',' ')}, /* Chipewyan -> Athapaskan */
+ {HB_TAG('c','h','q',' '), HB_TAG('C','C','H','N')}, /* Quiotepec Chinantec -> Chinantec */
+/*{HB_TAG('c','h','r',' '), HB_TAG('C','H','R',' ')},*/ /* Cherokee */
+/*{HB_TAG('c','h','y',' '), HB_TAG('C','H','Y',' ')},*/ /* Cheyenne */
+ {HB_TAG('c','h','z',' '), HB_TAG('C','C','H','N')}, /* Ozumacín Chinantec -> Chinantec */
+ {HB_TAG('c','i','w',' '), HB_TAG('O','J','B',' ')}, /* Chippewa -> Ojibway */
+/*{HB_TAG('c','j','a',' '), HB_TAG('C','J','A',' ')},*/ /* Western Cham */
+/*{HB_TAG('c','j','m',' '), HB_TAG('C','J','M',' ')},*/ /* Eastern Cham */
+ {HB_TAG('c','j','y',' '), HB_TAG('Z','H','S',' ')}, /* Jinyu Chinese -> Chinese, Simplified */
+ {HB_TAG('c','k','a',' '), HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin (retired code) -> Chin */
+ {HB_TAG('c','k','b',' '), HB_TAG('K','U','R',' ')}, /* Central Kurdish -> Kurdish */
+ {HB_TAG('c','k','n',' '), HB_TAG('Q','I','N',' ')}, /* Kaang Chin -> Chin */
+ {HB_TAG('c','k','s',' '), HB_TAG('C','P','P',' ')}, /* Tayo -> Creoles */
+ {HB_TAG('c','k','t',' '), HB_TAG('C','H','K',' ')}, /* Chukot -> Chukchi */
+ {HB_TAG('c','k','z',' '), HB_TAG('M','Y','N',' ')}, /* Cakchiquel-Quiché Mixed Language -> Mayan */
+ {HB_TAG('c','l','c',' '), HB_TAG('A','T','H',' ')}, /* Chilcotin -> Athapaskan */
+ {HB_TAG('c','l','d',' '), HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic -> Syriac */
+ {HB_TAG('c','l','e',' '), HB_TAG('C','C','H','N')}, /* Lealao Chinantec -> Chinantec */
+ {HB_TAG('c','l','j',' '), HB_TAG('Q','I','N',' ')}, /* Laitu Chin -> Chin */
+ {HB_TAG('c','l','t',' '), HB_TAG('Q','I','N',' ')}, /* Lautu Chin -> Chin */
+ {HB_TAG('c','m','n',' '), HB_TAG('Z','H','S',' ')}, /* Mandarin Chinese -> Chinese, Simplified */
+ {HB_TAG('c','m','r',' '), HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin -> Chin */
+ {HB_TAG('c','n','b',' '), HB_TAG('Q','I','N',' ')}, /* Chinbon Chin -> Chin */
+ {HB_TAG('c','n','h',' '), HB_TAG('Q','I','N',' ')}, /* Hakha Chin -> Chin */
+ {HB_TAG('c','n','k',' '), HB_TAG('Q','I','N',' ')}, /* Khumi Chin -> Chin */
+ {HB_TAG('c','n','l',' '), HB_TAG('C','C','H','N')}, /* Lalana Chinantec -> Chinantec */
+ {HB_TAG('c','n','p',' '), HB_TAG('Z','H','S',' ')}, /* Northern Ping Chinese -> Chinese, Simplified */
+ {HB_TAG('c','n','r',' '), HB_TAG('S','R','B',' ')}, /* Montenegrin -> Serbian */
+ {HB_TAG('c','n','t',' '), HB_TAG('C','C','H','N')}, /* Tepetotutla Chinantec -> Chinantec */
+ {HB_TAG('c','n','u',' '), HB_TAG('B','B','R',' ')}, /* Chenoua -> Berber */
+ {HB_TAG('c','n','w',' '), HB_TAG('Q','I','N',' ')}, /* Ngawn Chin -> Chin */
+ {HB_TAG('c','o','a',' '), HB_TAG('M','L','Y',' ')}, /* Cocos Islands Malay -> Malay */
+ {HB_TAG('c','o','b',' '), HB_TAG('M','Y','N',' ')}, /* Chicomuceltec -> Mayan */
+/*{HB_TAG('c','o','p',' '), HB_TAG('C','O','P',' ')},*/ /* Coptic */
+ {HB_TAG('c','o','q',' '), HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */
+ {HB_TAG('c','p','a',' '), HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */
+ {HB_TAG('c','p','e',' '), HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','p','f',' '), HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','p','i',' '), HB_TAG('C','P','P',' ')}, /* Chinese Pidgin English -> Creoles */
+/*{HB_TAG('c','p','p',' '), HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','p','x',' '), HB_TAG('Z','H','S',' ')}, /* Pu-Xian Chinese -> Chinese, Simplified */
+ {HB_TAG('c','q','d',' '), HB_TAG('H','M','N',' ')}, /* Chuanqiandian Cluster Miao -> Hmong */
+ {HB_TAG('c','q','u',' '), HB_TAG('Q','U','H',' ')}, /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
+ {HB_TAG('c','q','u',' '), HB_TAG('Q','U','Z',' ')}, /* Chilean Quechua (retired code) -> Quechua */
+ {HB_TAG('c','r','h',' '), HB_TAG('C','R','T',' ')}, /* Crimean Tatar */
+ {HB_TAG('c','r','i',' '), HB_TAG('C','P','P',' ')}, /* Sãotomense -> Creoles */
+ {HB_TAG('c','r','j',' '), HB_TAG('E','C','R',' ')}, /* Southern East Cree -> Eastern Cree */
+ {HB_TAG('c','r','j',' '), HB_TAG('Y','C','R',' ')}, /* Southern East Cree -> Y-Cree */
+ {HB_TAG('c','r','j',' '), HB_TAG('C','R','E',' ')}, /* Southern East Cree -> Cree */
+ {HB_TAG('c','r','k',' '), HB_TAG('W','C','R',' ')}, /* Plains Cree -> West-Cree */
+ {HB_TAG('c','r','k',' '), HB_TAG('Y','C','R',' ')}, /* Plains Cree -> Y-Cree */
+ {HB_TAG('c','r','k',' '), HB_TAG('C','R','E',' ')}, /* Plains Cree -> Cree */
+ {HB_TAG('c','r','l',' '), HB_TAG('E','C','R',' ')}, /* Northern East Cree -> Eastern Cree */
+ {HB_TAG('c','r','l',' '), HB_TAG('Y','C','R',' ')}, /* Northern East Cree -> Y-Cree */
+ {HB_TAG('c','r','l',' '), HB_TAG('C','R','E',' ')}, /* Northern East Cree -> Cree */
+ {HB_TAG('c','r','m',' '), HB_TAG('M','C','R',' ')}, /* Moose Cree */
+ {HB_TAG('c','r','m',' '), HB_TAG('L','C','R',' ')}, /* Moose Cree -> L-Cree */
+ {HB_TAG('c','r','m',' '), HB_TAG('C','R','E',' ')}, /* Moose Cree -> Cree */
+ {HB_TAG('c','r','p',' '), HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','r','r',' '), HB_TAG_NONE }, /* Carolina Algonquian != Carrier */
+ {HB_TAG('c','r','s',' '), HB_TAG('C','P','P',' ')}, /* Seselwa Creole French -> Creoles */
+ {HB_TAG('c','r','t',' '), HB_TAG_NONE }, /* Iyojwa'ja Chorote != Crimean Tatar */
+ {HB_TAG('c','r','x',' '), HB_TAG('C','R','R',' ')}, /* Carrier */
+ {HB_TAG('c','r','x',' '), HB_TAG('A','T','H',' ')}, /* Carrier -> Athapaskan */
+ {HB_TAG('c','s','a',' '), HB_TAG('C','C','H','N')}, /* Chiltepec Chinantec -> Chinantec */
+/*{HB_TAG('c','s','b',' '), HB_TAG('C','S','B',' ')},*/ /* Kashubian */
+ {HB_TAG('c','s','h',' '), HB_TAG('Q','I','N',' ')}, /* Asho Chin -> Chin */
+ {HB_TAG('c','s','j',' '), HB_TAG('Q','I','N',' ')}, /* Songlai Chin -> Chin */
+ {HB_TAG('c','s','l',' '), HB_TAG_NONE }, /* Chinese Sign Language != Church Slavonic */
+ {HB_TAG('c','s','o',' '), HB_TAG('C','C','H','N')}, /* Sochiapam Chinantec -> Chinantec */
+ {HB_TAG('c','s','p',' '), HB_TAG('Z','H','S',' ')}, /* Southern Ping Chinese -> Chinese, Simplified */
+ {HB_TAG('c','s','v',' '), HB_TAG('Q','I','N',' ')}, /* Sumtu Chin -> Chin */
+ {HB_TAG('c','s','w',' '), HB_TAG('N','C','R',' ')}, /* Swampy Cree -> N-Cree */
+ {HB_TAG('c','s','w',' '), HB_TAG('N','H','C',' ')}, /* Swampy Cree -> Norway House Cree */
+ {HB_TAG('c','s','w',' '), HB_TAG('C','R','E',' ')}, /* Swampy Cree -> Cree */
+ {HB_TAG('c','s','y',' '), HB_TAG('Q','I','N',' ')}, /* Siyin Chin -> Chin */
+ {HB_TAG('c','t','c',' '), HB_TAG('A','T','H',' ')}, /* Chetco -> Athapaskan */
+ {HB_TAG('c','t','d',' '), HB_TAG('Q','I','N',' ')}, /* Tedim Chin -> Chin */
+ {HB_TAG('c','t','e',' '), HB_TAG('C','C','H','N')}, /* Tepinapa Chinantec -> Chinantec */
+/*{HB_TAG('c','t','g',' '), HB_TAG('C','T','G',' ')},*/ /* Chittagonian */
+ {HB_TAG('c','t','h',' '), HB_TAG('Q','I','N',' ')}, /* Thaiphum Chin -> Chin */
+ {HB_TAG('c','t','l',' '), HB_TAG('C','C','H','N')}, /* Tlacoatzintepec Chinantec -> Chinantec */
+ {HB_TAG('c','t','s',' '), HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol -> Bikol */
+/*{HB_TAG('c','t','t',' '), HB_TAG('C','T','T',' ')},*/ /* Wayanad Chetti */
+ {HB_TAG('c','t','u',' '), HB_TAG('M','Y','N',' ')}, /* Chol -> Mayan */
+ {HB_TAG('c','u','c',' '), HB_TAG('C','C','H','N')}, /* Usila Chinantec -> Chinantec */
+/*{HB_TAG('c','u','k',' '), HB_TAG('C','U','K',' ')},*/ /* San Blas Kuna */
+ {HB_TAG('c','v','n',' '), HB_TAG('C','C','H','N')}, /* Valle Nacional Chinantec -> Chinantec */
+ {HB_TAG('c','w','d',' '), HB_TAG('D','C','R',' ')}, /* Woods Cree */
+ {HB_TAG('c','w','d',' '), HB_TAG('T','C','R',' ')}, /* Woods Cree -> TH-Cree */
+ {HB_TAG('c','w','d',' '), HB_TAG('C','R','E',' ')}, /* Woods Cree -> Cree */
+ {HB_TAG('c','z','h',' '), HB_TAG('Z','H','S',' ')}, /* Huizhou Chinese -> Chinese, Simplified */
+ {HB_TAG('c','z','o',' '), HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */
+ {HB_TAG('c','z','t',' '), HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */
+/*{HB_TAG('d','a','g',' '), HB_TAG('D','A','G',' ')},*/ /* Dagbani */
+ {HB_TAG('d','a','o',' '), HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */
+ {HB_TAG('d','a','p',' '), HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */
+/*{HB_TAG('d','a','r',' '), HB_TAG('D','A','R',' ')},*/ /* Dargwa */
+/*{HB_TAG('d','a','x',' '), HB_TAG('D','A','X',' ')},*/ /* Dayi */
+ {HB_TAG('d','c','r',' '), HB_TAG('C','P','P',' ')}, /* Negerhollands -> Creoles */
+ {HB_TAG('d','e','n',' '), HB_TAG('S','L','A',' ')}, /* Slave (Athapascan) [macrolanguage] -> Slavey */
+ {HB_TAG('d','e','n',' '), HB_TAG('A','T','H',' ')}, /* Slave (Athapascan) [macrolanguage] -> Athapaskan */
+ {HB_TAG('d','e','p',' '), HB_TAG('C','P','P',' ')}, /* Pidgin Delaware -> Creoles */
+ {HB_TAG('d','g','o',' '), HB_TAG('D','G','O',' ')}, /* Dogri (individual language) */
+ {HB_TAG('d','g','o',' '), HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) */
+ {HB_TAG('d','g','r',' '), HB_TAG('A','T','H',' ')}, /* Dogrib -> Athapaskan */
+ {HB_TAG('d','h','d',' '), HB_TAG('M','A','W',' ')}, /* Dhundari -> Marwari */
+/*{HB_TAG('d','h','g',' '), HB_TAG('D','H','G',' ')},*/ /* Dhangu */
+ {HB_TAG('d','h','v',' '), HB_TAG_NONE }, /* Dehu != Divehi (Dhivehi, Maldivian) (deprecated) */
+ {HB_TAG('d','i','b',' '), HB_TAG('D','N','K',' ')}, /* South Central Dinka -> Dinka */
+ {HB_TAG('d','i','k',' '), HB_TAG('D','N','K',' ')}, /* Southwestern Dinka -> Dinka */
+ {HB_TAG('d','i','n',' '), HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */
+ {HB_TAG('d','i','p',' '), HB_TAG('D','N','K',' ')}, /* Northeastern Dinka -> Dinka */
+ {HB_TAG('d','i','q',' '), HB_TAG('D','I','Q',' ')}, /* Dimli */
+ {HB_TAG('d','i','q',' '), HB_TAG('Z','Z','A',' ')}, /* Dimli -> Zazaki */
+ {HB_TAG('d','i','w',' '), HB_TAG('D','N','K',' ')}, /* Northwestern Dinka -> Dinka */
+ {HB_TAG('d','j','e',' '), HB_TAG('D','J','R',' ')}, /* Zarma */
+ {HB_TAG('d','j','k',' '), HB_TAG('C','P','P',' ')}, /* Eastern Maroon Creole -> Creoles */
+ {HB_TAG('d','j','r',' '), HB_TAG('D','J','R','0')}, /* Djambarrpuyngu */
+ {HB_TAG('d','k','s',' '), HB_TAG('D','N','K',' ')}, /* Southeastern Dinka -> Dinka */
+ {HB_TAG('d','n','g',' '), HB_TAG('D','U','N',' ')}, /* Dungan */
+/*{HB_TAG('d','n','j',' '), HB_TAG('D','N','J',' ')},*/ /* Dan */
+ {HB_TAG('d','n','k',' '), HB_TAG_NONE }, /* Dengka != Dinka */
+ {HB_TAG('d','o','i',' '), HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) [macrolanguage] */
+ {HB_TAG('d','r','h',' '), HB_TAG('M','N','G',' ')}, /* Darkhat (retired code) -> Mongolian */
+ {HB_TAG('d','r','i',' '), HB_TAG_NONE }, /* C'Lela != Dari */
+ {HB_TAG('d','r','w',' '), HB_TAG('D','R','I',' ')}, /* Darwazi (retired code) -> Dari */
+ {HB_TAG('d','r','w',' '), HB_TAG('F','A','R',' ')}, /* Darwazi (retired code) -> Persian */
+ {HB_TAG('d','s','b',' '), HB_TAG('L','S','B',' ')}, /* Lower Sorbian */
+ {HB_TAG('d','t','y',' '), HB_TAG('N','E','P',' ')}, /* Dotyali -> Nepali */
+/*{HB_TAG('d','u','j',' '), HB_TAG('D','U','J',' ')},*/ /* Dhuwal (retired code) */
+ {HB_TAG('d','u','n',' '), HB_TAG_NONE }, /* Dusun Deyah != Dungan */
+ {HB_TAG('d','u','p',' '), HB_TAG('M','L','Y',' ')}, /* Duano -> Malay */
+ {HB_TAG('d','w','k',' '), HB_TAG('K','U','I',' ')}, /* Dawik Kui -> Kui */
+ {HB_TAG('d','w','u',' '), HB_TAG('D','U','J',' ')}, /* Dhuwal */
+ {HB_TAG('d','w','y',' '), HB_TAG('D','U','J',' ')}, /* Dhuwaya -> Dhuwal */
+ {HB_TAG('d','y','u',' '), HB_TAG('J','U','L',' ')}, /* Dyula -> Jula */
+ {HB_TAG('d','z','n',' '), HB_TAG_NONE }, /* Dzando != Dzongkha */
+ {HB_TAG('e','c','r',' '), HB_TAG_NONE }, /* Eteocretan != Eastern Cree */
+/*{HB_TAG('e','f','i',' '), HB_TAG('E','F','I',' ')},*/ /* Efik */
+ {HB_TAG('e','k','k',' '), HB_TAG('E','T','I',' ')}, /* Standard Estonian -> Estonian */
+ {HB_TAG('e','k','y',' '), HB_TAG('K','R','N',' ')}, /* Eastern Kayah -> Karen */
+ {HB_TAG('e','m','k',' '), HB_TAG('E','M','K',' ')}, /* Eastern Maninkakan */
+ {HB_TAG('e','m','k',' '), HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan -> Maninka */
+ {HB_TAG('e','m','y',' '), HB_TAG('M','Y','N',' ')}, /* Epigraphic Mayan -> Mayan */
+ {HB_TAG('e','n','b',' '), HB_TAG('K','A','L',' ')}, /* Markweeta -> Kalenjin */
+ {HB_TAG('e','n','f',' '), HB_TAG('F','N','E',' ')}, /* Forest Enets */
+ {HB_TAG('e','n','h',' '), HB_TAG('T','N','E',' ')}, /* Tundra Enets */
+ {HB_TAG('e','s','g',' '), HB_TAG('G','O','N',' ')}, /* Aheri Gondi -> Gondi */
+ {HB_TAG('e','s','i',' '), HB_TAG('I','P','K',' ')}, /* North Alaskan Inupiatun -> Inupiat */
+ {HB_TAG('e','s','k',' '), HB_TAG('I','P','K',' ')}, /* Northwest Alaska Inupiatun -> Inupiat */
+/*{HB_TAG('e','s','u',' '), HB_TAG('E','S','U',' ')},*/ /* Central Yupik */
+ {HB_TAG('e','t','o',' '), HB_TAG('B','T','I',' ')}, /* Eton (Cameroon) -> Beti */
+ {HB_TAG('e','u','q',' '), HB_TAG_NONE }, /* Basque [collection] != Basque */
+ {HB_TAG('e','v','e',' '), HB_TAG('E','V','N',' ')}, /* Even */
+ {HB_TAG('e','v','n',' '), HB_TAG('E','V','K',' ')}, /* Evenki */
+ {HB_TAG('e','w','o',' '), HB_TAG('B','T','I',' ')}, /* Ewondo -> Beti */
+ {HB_TAG('e','y','o',' '), HB_TAG('K','A','L',' ')}, /* Keiyo -> Kalenjin */
+ {HB_TAG('f','a','b',' '), HB_TAG('C','P','P',' ')}, /* Fa d'Ambu -> Creoles */
+ {HB_TAG('f','a','n',' '), HB_TAG('F','A','N','0')}, /* Fang (Equatorial Guinea) */
+ {HB_TAG('f','a','n',' '), HB_TAG('B','T','I',' ')}, /* Fang (Equatorial Guinea) -> Beti */
+ {HB_TAG('f','a','r',' '), HB_TAG_NONE }, /* Fataleka != Persian */
+ {HB_TAG('f','a','t',' '), HB_TAG('F','A','T',' ')}, /* Fanti */
+ {HB_TAG('f','a','t',' '), HB_TAG('A','K','A',' ')}, /* Fanti -> Akan */
+ {HB_TAG('f','b','l',' '), HB_TAG('B','I','K',' ')}, /* West Albay Bikol -> Bikol */
+ {HB_TAG('f','f','m',' '), HB_TAG('F','U','L',' ')}, /* Maasina Fulfulde -> Fulah */
+ {HB_TAG('f','i','l',' '), HB_TAG('P','I','L',' ')}, /* Filipino */
+ {HB_TAG('f','l','m',' '), HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) (retired code) */
+ {HB_TAG('f','l','m',' '), HB_TAG('Q','I','N',' ')}, /* Falam Chin (retired code) -> Chin */
+ {HB_TAG('f','m','p',' '), HB_TAG('F','M','P',' ')}, /* Fe’fe’ */
+ {HB_TAG('f','m','p',' '), HB_TAG('B','M','L',' ')}, /* Fe'fe' -> Bamileke */
+ {HB_TAG('f','n','g',' '), HB_TAG('C','P','P',' ')}, /* Fanagalo -> Creoles */
+/*{HB_TAG('f','o','n',' '), HB_TAG('F','O','N',' ')},*/ /* Fon */
+ {HB_TAG('f','o','s',' '), HB_TAG_NONE }, /* Siraya != Faroese */
+ {HB_TAG('f','p','e',' '), HB_TAG('C','P','P',' ')}, /* Fernando Po Creole English -> Creoles */
+/*{HB_TAG('f','r','c',' '), HB_TAG('F','R','C',' ')},*/ /* Cajun French */
+/*{HB_TAG('f','r','p',' '), HB_TAG('F','R','P',' ')},*/ /* Arpitan */
+ {HB_TAG('f','u','b',' '), HB_TAG('F','U','L',' ')}, /* Adamawa Fulfulde -> Fulah */
+ {HB_TAG('f','u','c',' '), HB_TAG('F','U','L',' ')}, /* Pulaar -> Fulah */
+ {HB_TAG('f','u','e',' '), HB_TAG('F','U','L',' ')}, /* Borgu Fulfulde -> Fulah */
+ {HB_TAG('f','u','f',' '), HB_TAG('F','T','A',' ')}, /* Pular -> Futa */
+ {HB_TAG('f','u','f',' '), HB_TAG('F','U','L',' ')}, /* Pular -> Fulah */
+ {HB_TAG('f','u','h',' '), HB_TAG('F','U','L',' ')}, /* Western Niger Fulfulde -> Fulah */
+ {HB_TAG('f','u','i',' '), HB_TAG('F','U','L',' ')}, /* Bagirmi Fulfulde -> Fulah */
+ {HB_TAG('f','u','q',' '), HB_TAG('F','U','L',' ')}, /* Central-Eastern Niger Fulfulde -> Fulah */
+ {HB_TAG('f','u','r',' '), HB_TAG('F','R','L',' ')}, /* Friulian */
+ {HB_TAG('f','u','v',' '), HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */
+ {HB_TAG('f','u','v',' '), HB_TAG('F','U','L',' ')}, /* Nigerian Fulfulde -> Fulah */
+ {HB_TAG('g','a','a',' '), HB_TAG('G','A','D',' ')}, /* Ga */
+ {HB_TAG('g','a','c',' '), HB_TAG('C','P','P',' ')}, /* Mixed Great Andamanese -> Creoles */
+ {HB_TAG('g','a','d',' '), HB_TAG_NONE }, /* Gaddang != Ga */
+ {HB_TAG('g','a','e',' '), HB_TAG_NONE }, /* Guarequena != Scottish Gaelic (Gaelic) */
+/*{HB_TAG('g','a','g',' '), HB_TAG('G','A','G',' ')},*/ /* Gagauz */
+ {HB_TAG('g','a','l',' '), HB_TAG_NONE }, /* Galolen != Galician */
+ {HB_TAG('g','a','n',' '), HB_TAG('Z','H','S',' ')}, /* Gan Chinese -> Chinese, Simplified */
+ {HB_TAG('g','a','r',' '), HB_TAG_NONE }, /* Galeya != Garshuni */
+ {HB_TAG('g','a','w',' '), HB_TAG_NONE }, /* Nobonob != Garhwali */
+ {HB_TAG('g','a','x',' '), HB_TAG('O','R','O',' ')}, /* Borana-Arsi-Guji Oromo -> Oromo */
+ {HB_TAG('g','a','z',' '), HB_TAG('O','R','O',' ')}, /* West Central Oromo -> Oromo */
+ {HB_TAG('g','b','m',' '), HB_TAG('G','A','W',' ')}, /* Garhwali */
+ {HB_TAG('g','c','e',' '), HB_TAG('A','T','H',' ')}, /* Galice -> Athapaskan */
+ {HB_TAG('g','c','f',' '), HB_TAG('C','P','P',' ')}, /* Guadeloupean Creole French -> Creoles */
+ {HB_TAG('g','c','l',' '), HB_TAG('C','P','P',' ')}, /* Grenadian Creole English -> Creoles */
+ {HB_TAG('g','c','r',' '), HB_TAG('C','P','P',' ')}, /* Guianese Creole French -> Creoles */
+ {HB_TAG('g','d','a',' '), HB_TAG('R','A','J',' ')}, /* Gade Lohar -> Rajasthani */
+/*{HB_TAG('g','e','z',' '), HB_TAG('G','E','Z',' ')},*/ /* Geez */
+ {HB_TAG('g','g','o',' '), HB_TAG('G','O','N',' ')}, /* Southern Gondi (retired code) -> Gondi */
+ {HB_TAG('g','h','a',' '), HB_TAG('B','B','R',' ')}, /* Ghadamès -> Berber */
+ {HB_TAG('g','h','k',' '), HB_TAG('K','R','N',' ')}, /* Geko Karen -> Karen */
+ {HB_TAG('g','h','o',' '), HB_TAG('B','B','R',' ')}, /* Ghomara -> Berber */
+ {HB_TAG('g','i','b',' '), HB_TAG('C','P','P',' ')}, /* Gibanawa -> Creoles */
+/*{HB_TAG('g','i','h',' '), HB_TAG('G','I','H',' ')},*/ /* Githabul */
+ {HB_TAG('g','i','l',' '), HB_TAG('G','I','L','0')}, /* Kiribati (Gilbertese) */
+ {HB_TAG('g','j','u',' '), HB_TAG('R','A','J',' ')}, /* Gujari -> Rajasthani */
+ {HB_TAG('g','k','p',' '), HB_TAG('G','K','P',' ')}, /* Guinea Kpelle -> Kpelle (Guinea) */
+ {HB_TAG('g','k','p',' '), HB_TAG('K','P','L',' ')}, /* Guinea Kpelle -> Kpelle */
+ {HB_TAG('g','l','d',' '), HB_TAG('N','A','N',' ')}, /* Nanai */
+/*{HB_TAG('g','l','k',' '), HB_TAG('G','L','K',' ')},*/ /* Gilaki */
+ {HB_TAG('g','m','z',' '), HB_TAG_NONE }, /* Mgbolizhia != Gumuz */
+ {HB_TAG('g','n','b',' '), HB_TAG('Q','I','N',' ')}, /* Gangte -> Chin */
+/*{HB_TAG('g','n','n',' '), HB_TAG('G','N','N',' ')},*/ /* Gumatj */
+ {HB_TAG('g','n','o',' '), HB_TAG('G','O','N',' ')}, /* Northern Gondi -> Gondi */
+ {HB_TAG('g','n','w',' '), HB_TAG('G','U','A',' ')}, /* Western Bolivian Guaraní -> Guarani */
+/*{HB_TAG('g','o','g',' '), HB_TAG('G','O','G',' ')},*/ /* Gogo */
+ {HB_TAG('g','o','m',' '), HB_TAG('K','O','K',' ')}, /* Goan Konkani -> Konkani */
+/*{HB_TAG('g','o','n',' '), HB_TAG('G','O','N',' ')},*/ /* Gondi [macrolanguage] */
+ {HB_TAG('g','o','q',' '), HB_TAG('C','P','P',' ')}, /* Gorap -> Creoles */
+ {HB_TAG('g','o','x',' '), HB_TAG('B','A','D','0')}, /* Gobu -> Banda */
+ {HB_TAG('g','p','e',' '), HB_TAG('C','P','P',' ')}, /* Ghanaian Pidgin English -> Creoles */
+ {HB_TAG('g','r','o',' '), HB_TAG_NONE }, /* Groma != Garo */
+ {HB_TAG('g','r','r',' '), HB_TAG('B','B','R',' ')}, /* Taznatit -> Berber */
+ {HB_TAG('g','r','t',' '), HB_TAG('G','R','O',' ')}, /* Garo */
+ {HB_TAG('g','r','u',' '), HB_TAG('S','O','G',' ')}, /* Kistane -> Sodo Gurage */
+ {HB_TAG('g','s','w',' '), HB_TAG('A','L','S',' ')}, /* Alsatian */
+ {HB_TAG('g','u','a',' '), HB_TAG_NONE }, /* Shiki != Guarani */
+/*{HB_TAG('g','u','c',' '), HB_TAG('G','U','C',' ')},*/ /* Wayuu */
+/*{HB_TAG('g','u','f',' '), HB_TAG('G','U','F',' ')},*/ /* Gupapuyngu */
+ {HB_TAG('g','u','g',' '), HB_TAG('G','U','A',' ')}, /* Paraguayan Guaraní -> Guarani */
+ {HB_TAG('g','u','i',' '), HB_TAG('G','U','A',' ')}, /* Eastern Bolivian Guaraní -> Guarani */
+ {HB_TAG('g','u','k',' '), HB_TAG('G','M','Z',' ')}, /* Gumuz */
+ {HB_TAG('g','u','l',' '), HB_TAG('C','P','P',' ')}, /* Sea Island Creole English -> Creoles */
+ {HB_TAG('g','u','n',' '), HB_TAG('G','U','A',' ')}, /* Mbyá Guaraní -> Guarani */
+/*{HB_TAG('g','u','z',' '), HB_TAG('G','U','Z',' ')},*/ /* Gusii */
+ {HB_TAG('g','w','i',' '), HB_TAG('A','T','H',' ')}, /* Gwichʼin -> Athapaskan */
+ {HB_TAG('g','y','n',' '), HB_TAG('C','P','P',' ')}, /* Guyanese Creole English -> Creoles */
+ {HB_TAG('h','a','a',' '), HB_TAG('A','T','H',' ')}, /* Han -> Athapaskan */
+ {HB_TAG('h','a','e',' '), HB_TAG('O','R','O',' ')}, /* Eastern Oromo -> Oromo */
+ {HB_TAG('h','a','i',' '), HB_TAG('H','A','I','0')}, /* Haida [macrolanguage] */
+ {HB_TAG('h','a','k',' '), HB_TAG('Z','H','S',' ')}, /* Hakka Chinese -> Chinese, Simplified */
+ {HB_TAG('h','a','l',' '), HB_TAG_NONE }, /* Halang != Halam (Falam Chin) */
+ {HB_TAG('h','a','r',' '), HB_TAG('H','R','I',' ')}, /* Harari */
+/*{HB_TAG('h','a','w',' '), HB_TAG('H','A','W',' ')},*/ /* Hawaiian */
+ {HB_TAG('h','a','x',' '), HB_TAG('H','A','I','0')}, /* Southern Haida -> Haida */
+/*{HB_TAG('h','a','y',' '), HB_TAG('H','A','Y',' ')},*/ /* Haya */
+/*{HB_TAG('h','a','z',' '), HB_TAG('H','A','Z',' ')},*/ /* Hazaragi */
+ {HB_TAG('h','b','n',' '), HB_TAG_NONE }, /* Heiban != Hammer-Banna */
+ {HB_TAG('h','c','a',' '), HB_TAG('C','P','P',' ')}, /* Andaman Creole Hindi -> Creoles */
+ {HB_TAG('h','d','n',' '), HB_TAG('H','A','I','0')}, /* Northern Haida -> Haida */
+ {HB_TAG('h','e','a',' '), HB_TAG('H','M','N',' ')}, /* Northern Qiandong Miao -> Hmong */
+/*{HB_TAG('h','e','i',' '), HB_TAG('H','E','I',' ')},*/ /* Heiltsuk */
+/*{HB_TAG('h','i','l',' '), HB_TAG('H','I','L',' ')},*/ /* Hiligaynon */
+ {HB_TAG('h','j','i',' '), HB_TAG('M','L','Y',' ')}, /* Haji -> Malay */
+ {HB_TAG('h','l','t',' '), HB_TAG('Q','I','N',' ')}, /* Matu Chin -> Chin */
+ {HB_TAG('h','m','a',' '), HB_TAG('H','M','N',' ')}, /* Southern Mashan Hmong -> Hmong */
+ {HB_TAG('h','m','c',' '), HB_TAG('H','M','N',' ')}, /* Central Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','d',' '), HB_TAG('H','M','D',' ')}, /* Large Flowery Miao -> A-Hmao */
+ {HB_TAG('h','m','d',' '), HB_TAG('H','M','N',' ')}, /* Large Flowery Miao -> Hmong */
+ {HB_TAG('h','m','e',' '), HB_TAG('H','M','N',' ')}, /* Eastern Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','g',' '), HB_TAG('H','M','N',' ')}, /* Southwestern Guiyang Hmong -> Hmong */
+ {HB_TAG('h','m','h',' '), HB_TAG('H','M','N',' ')}, /* Southwestern Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','i',' '), HB_TAG('H','M','N',' ')}, /* Northern Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','j',' '), HB_TAG('H','M','N',' ')}, /* Ge -> Hmong */
+ {HB_TAG('h','m','l',' '), HB_TAG('H','M','N',' ')}, /* Luopohe Hmong -> Hmong */
+ {HB_TAG('h','m','m',' '), HB_TAG('H','M','N',' ')}, /* Central Mashan Hmong -> Hmong */
+/*{HB_TAG('h','m','n',' '), HB_TAG('H','M','N',' ')},*/ /* Hmong [macrolanguage] */
+ {HB_TAG('h','m','p',' '), HB_TAG('H','M','N',' ')}, /* Northern Mashan Hmong -> Hmong */
+ {HB_TAG('h','m','q',' '), HB_TAG('H','M','N',' ')}, /* Eastern Qiandong Miao -> Hmong */
+ {HB_TAG('h','m','r',' '), HB_TAG('Q','I','N',' ')}, /* Hmar -> Chin */
+ {HB_TAG('h','m','s',' '), HB_TAG('H','M','N',' ')}, /* Southern Qiandong Miao -> Hmong */
+ {HB_TAG('h','m','w',' '), HB_TAG('H','M','N',' ')}, /* Western Mashan Hmong -> Hmong */
+ {HB_TAG('h','m','y',' '), HB_TAG('H','M','N',' ')}, /* Southern Guiyang Hmong -> Hmong */
+ {HB_TAG('h','m','z',' '), HB_TAG('H','M','Z',' ')}, /* Hmong Shua -> Hmong Shuat */
+ {HB_TAG('h','m','z',' '), HB_TAG('H','M','N',' ')}, /* Hmong Shua -> Hmong */
+/*{HB_TAG('h','n','d',' '), HB_TAG('H','N','D',' ')},*/ /* Southern Hindko -> Hindko */
+ {HB_TAG('h','n','e',' '), HB_TAG('C','H','H',' ')}, /* Chhattisgarhi -> Chattisgarhi */
+ {HB_TAG('h','n','j',' '), HB_TAG('H','M','N',' ')}, /* Hmong Njua -> Hmong */
+ {HB_TAG('h','n','o',' '), HB_TAG('H','N','D',' ')}, /* Northern Hindko -> Hindko */
+ {HB_TAG('h','o','c',' '), HB_TAG('H','O',' ',' ')}, /* Ho */
+ {HB_TAG('h','o','i',' '), HB_TAG('A','T','H',' ')}, /* Holikachuk -> Athapaskan */
+ {HB_TAG('h','o','j',' '), HB_TAG('H','A','R',' ')}, /* Hadothi -> Harauti */
+ {HB_TAG('h','o','j',' '), HB_TAG('R','A','J',' ')}, /* Hadothi -> Rajasthani */
+ {HB_TAG('h','r','a',' '), HB_TAG('Q','I','N',' ')}, /* Hrangkhol -> Chin */
+ {HB_TAG('h','r','m',' '), HB_TAG('H','M','N',' ')}, /* Horned Miao -> Hmong */
+ {HB_TAG('h','s','b',' '), HB_TAG('U','S','B',' ')}, /* Upper Sorbian */
+ {HB_TAG('h','s','n',' '), HB_TAG('Z','H','S',' ')}, /* Xiang Chinese -> Chinese, Simplified */
+ {HB_TAG('h','u','j',' '), HB_TAG('H','M','N',' ')}, /* Northern Guiyang Hmong -> Hmong */
+ {HB_TAG('h','u','p',' '), HB_TAG('A','T','H',' ')}, /* Hupa -> Athapaskan */
+ {HB_TAG('h','u','s',' '), HB_TAG('M','Y','N',' ')}, /* Huastec -> Mayan */
+ {HB_TAG('h','w','c',' '), HB_TAG('C','P','P',' ')}, /* Hawai'i Creole English -> Creoles */
+ {HB_TAG('h','y','w',' '), HB_TAG('H','Y','E',' ')}, /* Western Armenian -> Armenian */
+/*{HB_TAG('i','b','a',' '), HB_TAG('I','B','A',' ')},*/ /* Iban */
+/*{HB_TAG('i','b','b',' '), HB_TAG('I','B','B',' ')},*/ /* Ibibio */
+ {HB_TAG('i','b','y',' '), HB_TAG('I','J','O',' ')}, /* Ibani -> Ijo */
+ {HB_TAG('i','c','r',' '), HB_TAG('C','P','P',' ')}, /* Islander Creole English -> Creoles */
+ {HB_TAG('i','d','a',' '), HB_TAG('L','U','H',' ')}, /* Idakho-Isukha-Tiriki -> Luyia */
+ {HB_TAG('i','d','b',' '), HB_TAG('C','P','P',' ')}, /* Indo-Portuguese -> Creoles */
+ {HB_TAG('i','g','b',' '), HB_TAG('E','B','I',' ')}, /* Ebira */
+ {HB_TAG('i','h','b',' '), HB_TAG('C','P','P',' ')}, /* Iha Based Pidgin -> Creoles */
+ {HB_TAG('i','j','c',' '), HB_TAG('I','J','O',' ')}, /* Izon -> Ijo */
+ {HB_TAG('i','j','e',' '), HB_TAG('I','J','O',' ')}, /* Biseni -> Ijo */
+ {HB_TAG('i','j','n',' '), HB_TAG('I','J','O',' ')}, /* Kalabari -> Ijo */
+/*{HB_TAG('i','j','o',' '), HB_TAG('I','J','O',' ')},*/ /* Ijo [collection] */
+ {HB_TAG('i','j','s',' '), HB_TAG('I','J','O',' ')}, /* Southeast Ijo -> Ijo */
+ {HB_TAG('i','k','e',' '), HB_TAG('I','N','U',' ')}, /* Eastern Canadian Inuktitut -> Inuktitut */
+ {HB_TAG('i','k','e',' '), HB_TAG('I','N','U','K')}, /* Eastern Canadian Inuktitut -> Nunavik Inuktitut */
+ {HB_TAG('i','k','t',' '), HB_TAG('I','N','U',' ')}, /* Inuinnaqtun -> Inuktitut */
+/*{HB_TAG('i','l','o',' '), HB_TAG('I','L','O',' ')},*/ /* Iloko -> Ilokano */
+ {HB_TAG('i','n','g',' '), HB_TAG('A','T','H',' ')}, /* Degexit'an -> Athapaskan */
+ {HB_TAG('i','n','h',' '), HB_TAG('I','N','G',' ')}, /* Ingush */
+ {HB_TAG('i','r','i',' '), HB_TAG_NONE }, /* Rigwe != Irish */
+/*{HB_TAG('i','r','u',' '), HB_TAG('I','R','U',' ')},*/ /* Irula */
+ {HB_TAG('i','s','m',' '), HB_TAG_NONE }, /* Masimasi != Inari Sami */
+ {HB_TAG('i','t','z',' '), HB_TAG('M','Y','N',' ')}, /* Itzá -> Mayan */
+ {HB_TAG('i','x','l',' '), HB_TAG('M','Y','N',' ')}, /* Ixil -> Mayan */
+ {HB_TAG('j','a','c',' '), HB_TAG('M','Y','N',' ')}, /* Popti' -> Mayan */
+ {HB_TAG('j','a','k',' '), HB_TAG('M','L','Y',' ')}, /* Jakun -> Malay */
+ {HB_TAG('j','a','m',' '), HB_TAG('J','A','M',' ')}, /* Jamaican Creole English -> Jamaican Creole */
+ {HB_TAG('j','a','m',' '), HB_TAG('C','P','P',' ')}, /* Jamaican Creole English -> Creoles */
+ {HB_TAG('j','a','n',' '), HB_TAG_NONE }, /* Jandai != Japanese */
+ {HB_TAG('j','a','x',' '), HB_TAG('M','L','Y',' ')}, /* Jambi Malay -> Malay */
+ {HB_TAG('j','b','e',' '), HB_TAG('B','B','R',' ')}, /* Judeo-Berber -> Berber */
+ {HB_TAG('j','b','n',' '), HB_TAG('B','B','R',' ')}, /* Nafusi -> Berber */
+/*{HB_TAG('j','b','o',' '), HB_TAG('J','B','O',' ')},*/ /* Lojban */
+/*{HB_TAG('j','c','t',' '), HB_TAG('J','C','T',' ')},*/ /* Krymchak */
+ {HB_TAG('j','g','o',' '), HB_TAG('B','M','L',' ')}, /* Ngomba -> Bamileke */
+ {HB_TAG('j','i','i',' '), HB_TAG_NONE }, /* Jiiddu != Yiddish */
+ {HB_TAG('j','k','m',' '), HB_TAG('K','R','N',' ')}, /* Mobwa Karen -> Karen */
+ {HB_TAG('j','k','p',' '), HB_TAG('K','R','N',' ')}, /* Paku Karen -> Karen */
+ {HB_TAG('j','u','d',' '), HB_TAG_NONE }, /* Worodougou != Ladino */
+ {HB_TAG('j','u','l',' '), HB_TAG_NONE }, /* Jirel != Jula */
+ {HB_TAG('j','v','d',' '), HB_TAG('C','P','P',' ')}, /* Javindo -> Creoles */
+ {HB_TAG('k','a','a',' '), HB_TAG('K','R','K',' ')}, /* Karakalpak */
+ {HB_TAG('k','a','b',' '), HB_TAG('K','A','B','0')}, /* Kabyle */
+ {HB_TAG('k','a','b',' '), HB_TAG('B','B','R',' ')}, /* Kabyle -> Berber */
+ {HB_TAG('k','a','c',' '), HB_TAG_NONE }, /* Kachin != Kachchi */
+ {HB_TAG('k','a','m',' '), HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
+ {HB_TAG('k','a','r',' '), HB_TAG('K','R','N',' ')}, /* Karen [collection] */
+/*{HB_TAG('k','a','w',' '), HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */
+ {HB_TAG('k','b','d',' '), HB_TAG('K','A','B',' ')}, /* Kabardian */
+ {HB_TAG('k','b','y',' '), HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */
+ {HB_TAG('k','c','a',' '), HB_TAG('K','H','K',' ')}, /* Khanty -> Khanty-Kazim */
+ {HB_TAG('k','c','a',' '), HB_TAG('K','H','S',' ')}, /* Khanty -> Khanty-Shurishkar */
+ {HB_TAG('k','c','a',' '), HB_TAG('K','H','V',' ')}, /* Khanty -> Khanty-Vakhi */
+ {HB_TAG('k','c','n',' '), HB_TAG('C','P','P',' ')}, /* Nubi -> Creoles */
+/*{HB_TAG('k','d','e',' '), HB_TAG('K','D','E',' ')},*/ /* Makonde */
+ {HB_TAG('k','d','r',' '), HB_TAG('K','R','M',' ')}, /* Karaim */
+ {HB_TAG('k','d','t',' '), HB_TAG('K','U','Y',' ')}, /* Kuy */
+ {HB_TAG('k','e','a',' '), HB_TAG('K','E','A',' ')}, /* Kabuverdianu (Crioulo) */
+ {HB_TAG('k','e','a',' '), HB_TAG('C','P','P',' ')}, /* Kabuverdianu -> Creoles */
+ {HB_TAG('k','e','b',' '), HB_TAG_NONE }, /* Kélé != Kebena */
+ {HB_TAG('k','e','k',' '), HB_TAG('K','E','K',' ')}, /* Kekchi */
+ {HB_TAG('k','e','k',' '), HB_TAG('M','Y','N',' ')}, /* Kekchí -> Mayan */
+ {HB_TAG('k','e','x',' '), HB_TAG('K','K','N',' ')}, /* Kukna -> Kokni */
+ {HB_TAG('k','f','a',' '), HB_TAG('K','O','D',' ')}, /* Kodava -> Kodagu */
+ {HB_TAG('k','f','r',' '), HB_TAG('K','A','C',' ')}, /* Kachhi -> Kachchi */
+ {HB_TAG('k','f','x',' '), HB_TAG('K','U','L',' ')}, /* Kullu Pahari -> Kulvi */
+ {HB_TAG('k','f','y',' '), HB_TAG('K','M','N',' ')}, /* Kumaoni */
+ {HB_TAG('k','g','e',' '), HB_TAG_NONE }, /* Komering != Khutsuri Georgian */
+ {HB_TAG('k','h','a',' '), HB_TAG('K','S','I',' ')}, /* Khasi */
+ {HB_TAG('k','h','b',' '), HB_TAG('X','B','D',' ')}, /* Lü */
+ {HB_TAG('k','h','k',' '), HB_TAG('M','N','G',' ')}, /* Halh Mongolian -> Mongolian */
+ {HB_TAG('k','h','n',' '), HB_TAG_NONE }, /* Khandesi != Khamti Shan (Microsoft fonts) */
+ {HB_TAG('k','h','s',' '), HB_TAG_NONE }, /* Kasua != Khanty-Shurishkar */
+ {HB_TAG('k','h','t',' '), HB_TAG('K','H','T',' ')}, /* Khamti -> Khamti Shan */
+ {HB_TAG('k','h','t',' '), HB_TAG('K','H','N',' ')}, /* Khamti -> Khamti Shan (Microsoft fonts) */
+ {HB_TAG('k','h','v',' '), HB_TAG_NONE }, /* Khvarshi != Khanty-Vakhi */
+/*{HB_TAG('k','h','w',' '), HB_TAG('K','H','W',' ')},*/ /* Khowar */
+ {HB_TAG('k','i','s',' '), HB_TAG_NONE }, /* Kis != Kisii */
+ {HB_TAG('k','i','u',' '), HB_TAG('K','I','U',' ')}, /* Kirmanjki */
+ {HB_TAG('k','i','u',' '), HB_TAG('Z','Z','A',' ')}, /* Kirmanjki -> Zazaki */
+ {HB_TAG('k','j','b',' '), HB_TAG('M','Y','N',' ')}, /* Q'anjob'al -> Mayan */
+/*{HB_TAG('k','j','d',' '), HB_TAG('K','J','D',' ')},*/ /* Southern Kiwai */
+ {HB_TAG('k','j','h',' '), HB_TAG('K','H','A',' ')}, /* Khakas -> Khakass */
+ {HB_TAG('k','j','p',' '), HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen -> Eastern Pwo Karen */
+ {HB_TAG('k','j','p',' '), HB_TAG('K','R','N',' ')}, /* Pwo Eastern Karen -> Karen */
+ {HB_TAG('k','j','t',' '), HB_TAG('K','R','N',' ')}, /* Phrae Pwo Karen -> Karen */
+/*{HB_TAG('k','j','z',' '), HB_TAG('K','J','Z',' ')},*/ /* Bumthangkha */
+ {HB_TAG('k','k','n',' '), HB_TAG_NONE }, /* Kon Keu != Kokni */
+ {HB_TAG('k','k','z',' '), HB_TAG('A','T','H',' ')}, /* Kaska -> Athapaskan */
+ {HB_TAG('k','l','m',' '), HB_TAG_NONE }, /* Migum != Kalmyk */
+ {HB_TAG('k','l','n',' '), HB_TAG('K','A','L',' ')}, /* Kalenjin [macrolanguage] */
+ {HB_TAG('k','m','b',' '), HB_TAG('M','B','N',' ')}, /* Kimbundu -> Mbundu */
+ {HB_TAG('k','m','n',' '), HB_TAG_NONE }, /* Awtuw != Kumaoni */
+ {HB_TAG('k','m','o',' '), HB_TAG_NONE }, /* Kwoma != Komo */
+ {HB_TAG('k','m','r',' '), HB_TAG('K','U','R',' ')}, /* Northern Kurdish -> Kurdish */
+ {HB_TAG('k','m','s',' '), HB_TAG_NONE }, /* Kamasau != Komso */
+ {HB_TAG('k','m','v',' '), HB_TAG('C','P','P',' ')}, /* Karipúna Creole French -> Creoles */
+ {HB_TAG('k','m','w',' '), HB_TAG('K','M','O',' ')}, /* Komo (Democratic Republic of Congo) */
+/*{HB_TAG('k','m','z',' '), HB_TAG('K','M','Z',' ')},*/ /* Khorasani Turkish -> Khorasani Turkic */
+ {HB_TAG('k','n','c',' '), HB_TAG('K','N','R',' ')}, /* Central Kanuri -> Kanuri */
+ {HB_TAG('k','n','g',' '), HB_TAG('K','O','N','0')}, /* Koongo -> Kongo */
+ {HB_TAG('k','n','j',' '), HB_TAG('M','Y','N',' ')}, /* Western Kanjobal -> Mayan */
+ {HB_TAG('k','n','n',' '), HB_TAG('K','O','K',' ')}, /* Konkani */
+ {HB_TAG('k','n','r',' '), HB_TAG_NONE }, /* Kaningra != Kanuri */
+ {HB_TAG('k','o','d',' '), HB_TAG_NONE }, /* Kodi != Kodagu */
+ {HB_TAG('k','o','h',' '), HB_TAG_NONE }, /* Koyo != Korean Old Hangul */
+ {HB_TAG('k','o','i',' '), HB_TAG('K','O','P',' ')}, /* Komi-Permyak */
+ {HB_TAG('k','o','i',' '), HB_TAG('K','O','M',' ')}, /* Komi-Permyak -> Komi */
+/*{HB_TAG('k','o','k',' '), HB_TAG('K','O','K',' ')},*/ /* Konkani [macrolanguage] */
+ {HB_TAG('k','o','p',' '), HB_TAG_NONE }, /* Waube != Komi-Permyak */
+/*{HB_TAG('k','o','s',' '), HB_TAG('K','O','S',' ')},*/ /* Kosraean */
+ {HB_TAG('k','o','y',' '), HB_TAG('A','T','H',' ')}, /* Koyukon -> Athapaskan */
+ {HB_TAG('k','o','z',' '), HB_TAG_NONE }, /* Korak != Komi-Zyrian */
+ {HB_TAG('k','p','e',' '), HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */
+ {HB_TAG('k','p','l',' '), HB_TAG_NONE }, /* Kpala != Kpelle */
+ {HB_TAG('k','p','p',' '), HB_TAG('K','R','N',' ')}, /* Paku Karen (retired code) -> Karen */
+ {HB_TAG('k','p','v',' '), HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */
+ {HB_TAG('k','p','v',' '), HB_TAG('K','O','M',' ')}, /* Komi-Zyrian -> Komi */
+ {HB_TAG('k','p','y',' '), HB_TAG('K','Y','K',' ')}, /* Koryak */
+ {HB_TAG('k','q','s',' '), HB_TAG('K','I','S',' ')}, /* Northern Kissi -> Kisii */
+ {HB_TAG('k','q','y',' '), HB_TAG('K','R','T',' ')}, /* Koorete */
+ {HB_TAG('k','r','c',' '), HB_TAG('K','A','R',' ')}, /* Karachay-Balkar -> Karachay */
+ {HB_TAG('k','r','c',' '), HB_TAG('B','A','L',' ')}, /* Karachay-Balkar -> Balkar */
+ {HB_TAG('k','r','i',' '), HB_TAG('K','R','I',' ')}, /* Krio */
+ {HB_TAG('k','r','i',' '), HB_TAG('C','P','P',' ')}, /* Krio -> Creoles */
+ {HB_TAG('k','r','k',' '), HB_TAG_NONE }, /* Kerek != Karakalpak */
+/*{HB_TAG('k','r','l',' '), HB_TAG('K','R','L',' ')},*/ /* Karelian */
+ {HB_TAG('k','r','m',' '), HB_TAG_NONE }, /* Krim (retired code) != Karaim */
+ {HB_TAG('k','r','n',' '), HB_TAG_NONE }, /* Sapo != Karen */
+ {HB_TAG('k','r','t',' '), HB_TAG('K','N','R',' ')}, /* Tumari Kanuri -> Kanuri */
+ {HB_TAG('k','r','u',' '), HB_TAG('K','U','U',' ')}, /* Kurukh */
+ {HB_TAG('k','s','h',' '), HB_TAG('K','S','H','0')}, /* Kölsch -> Ripuarian */
+ {HB_TAG('k','s','i',' '), HB_TAG_NONE }, /* Krisa != Khasi */
+ {HB_TAG('k','s','m',' '), HB_TAG_NONE }, /* Kumba != Kildin Sami */
+ {HB_TAG('k','s','s',' '), HB_TAG('K','I','S',' ')}, /* Southern Kisi -> Kisii */
+ {HB_TAG('k','s','w',' '), HB_TAG('K','S','W',' ')}, /* S’gaw Karen */
+ {HB_TAG('k','s','w',' '), HB_TAG('K','R','N',' ')}, /* S'gaw Karen -> Karen */
+ {HB_TAG('k','t','b',' '), HB_TAG('K','E','B',' ')}, /* Kambaata -> Kebena */
+ {HB_TAG('k','t','u',' '), HB_TAG('K','O','N',' ')}, /* Kituba (Democratic Republic of Congo) -> Kikongo */
+ {HB_TAG('k','t','w',' '), HB_TAG('A','T','H',' ')}, /* Kato -> Athapaskan */
+ {HB_TAG('k','u','i',' '), HB_TAG_NONE }, /* Kuikúro-Kalapálo != Kui */
+ {HB_TAG('k','u','l',' '), HB_TAG_NONE }, /* Kulere != Kulvi */
+/*{HB_TAG('k','u','m',' '), HB_TAG('K','U','M',' ')},*/ /* Kumyk */
+ {HB_TAG('k','u','u',' '), HB_TAG('A','T','H',' ')}, /* Upper Kuskokwim -> Athapaskan */
+ {HB_TAG('k','u','w',' '), HB_TAG('B','A','D','0')}, /* Kpagua -> Banda */
+ {HB_TAG('k','u','y',' '), HB_TAG_NONE }, /* Kuuku-Ya'u != Kuy */
+ {HB_TAG('k','v','b',' '), HB_TAG('M','L','Y',' ')}, /* Kubu -> Malay */
+ {HB_TAG('k','v','l',' '), HB_TAG('K','R','N',' ')}, /* Kayaw -> Karen */
+ {HB_TAG('k','v','q',' '), HB_TAG('K','R','N',' ')}, /* Geba Karen -> Karen */
+ {HB_TAG('k','v','r',' '), HB_TAG('M','L','Y',' ')}, /* Kerinci -> Malay */
+ {HB_TAG('k','v','t',' '), HB_TAG('K','R','N',' ')}, /* Lahta Karen -> Karen */
+ {HB_TAG('k','v','u',' '), HB_TAG('K','R','N',' ')}, /* Yinbaw Karen -> Karen */
+ {HB_TAG('k','v','y',' '), HB_TAG('K','R','N',' ')}, /* Yintale Karen -> Karen */
+/*{HB_TAG('k','w','k',' '), HB_TAG('K','W','K',' ')},*/ /* Kwakiutl -> Kwakʼwala */
+ {HB_TAG('k','w','w',' '), HB_TAG('C','P','P',' ')}, /* Kwinti -> Creoles */
+ {HB_TAG('k','w','y',' '), HB_TAG('K','O','N','0')}, /* San Salvador Kongo -> Kongo */
+ {HB_TAG('k','x','c',' '), HB_TAG('K','M','S',' ')}, /* Konso -> Komso */
+ {HB_TAG('k','x','d',' '), HB_TAG('M','L','Y',' ')}, /* Brunei -> Malay */
+ {HB_TAG('k','x','f',' '), HB_TAG('K','R','N',' ')}, /* Manumanaw Karen -> Karen */
+ {HB_TAG('k','x','k',' '), HB_TAG('K','R','N',' ')}, /* Zayein Karen -> Karen */
+ {HB_TAG('k','x','l',' '), HB_TAG('K','U','U',' ')}, /* Nepali Kurux (retired code) -> Kurukh */
+ {HB_TAG('k','x','u',' '), HB_TAG('K','U','I',' ')}, /* Kui (India) (retired code) */
+ {HB_TAG('k','y','k',' '), HB_TAG_NONE }, /* Kamayo != Koryak */
+ {HB_TAG('k','y','u',' '), HB_TAG('K','Y','U',' ')}, /* Western Kayah */
+ {HB_TAG('k','y','u',' '), HB_TAG('K','R','N',' ')}, /* Western Kayah -> Karen */
+ {HB_TAG('l','a','c',' '), HB_TAG('M','Y','N',' ')}, /* Lacandon -> Mayan */
+ {HB_TAG('l','a','d',' '), HB_TAG('J','U','D',' ')}, /* Ladino */
+ {HB_TAG('l','a','h',' '), HB_TAG_NONE }, /* Lahnda [macrolanguage] != Lahuli */
+ {HB_TAG('l','a','k',' '), HB_TAG_NONE }, /* Laka (Nigeria) (retired code) != Lak */
+ {HB_TAG('l','a','m',' '), HB_TAG_NONE }, /* Lamba != Lambani */
+ {HB_TAG('l','a','z',' '), HB_TAG_NONE }, /* Aribwatsa != Laz */
+ {HB_TAG('l','b','e',' '), HB_TAG('L','A','K',' ')}, /* Lak */
+ {HB_TAG('l','b','j',' '), HB_TAG('L','D','K',' ')}, /* Ladakhi */
+ {HB_TAG('l','b','l',' '), HB_TAG('B','I','K',' ')}, /* Libon Bikol -> Bikol */
+ {HB_TAG('l','c','e',' '), HB_TAG('M','L','Y',' ')}, /* Loncong -> Malay */
+ {HB_TAG('l','c','f',' '), HB_TAG('M','L','Y',' ')}, /* Lubu -> Malay */
+ {HB_TAG('l','d','i',' '), HB_TAG('K','O','N','0')}, /* Laari -> Kongo */
+ {HB_TAG('l','d','k',' '), HB_TAG_NONE }, /* Leelau != Ladakhi */
+/*{HB_TAG('l','e','f',' '), HB_TAG('L','E','F',' ')},*/ /* Lelemi */
+/*{HB_TAG('l','e','z',' '), HB_TAG('L','E','Z',' ')},*/ /* Lezghian -> Lezgi */
+ {HB_TAG('l','i','f',' '), HB_TAG('L','M','B',' ')}, /* Limbu */
+/*{HB_TAG('l','i','j',' '), HB_TAG('L','I','J',' ')},*/ /* Ligurian */
+ {HB_TAG('l','i','r',' '), HB_TAG('C','P','P',' ')}, /* Liberian English -> Creoles */
+/*{HB_TAG('l','i','s',' '), HB_TAG('L','I','S',' ')},*/ /* Lisu */
+ {HB_TAG('l','i','w',' '), HB_TAG('M','L','Y',' ')}, /* Col -> Malay */
+ {HB_TAG('l','i','y',' '), HB_TAG('B','A','D','0')}, /* Banda-Bambari -> Banda */
+/*{HB_TAG('l','j','p',' '), HB_TAG('L','J','P',' ')},*/ /* Lampung Api -> Lampung */
+ {HB_TAG('l','k','b',' '), HB_TAG('L','U','H',' ')}, /* Kabras -> Luyia */
+/*{HB_TAG('l','k','i',' '), HB_TAG('L','K','I',' ')},*/ /* Laki */
+ {HB_TAG('l','k','o',' '), HB_TAG('L','U','H',' ')}, /* Khayo -> Luyia */
+ {HB_TAG('l','k','s',' '), HB_TAG('L','U','H',' ')}, /* Kisa -> Luyia */
+ {HB_TAG('l','l','d',' '), HB_TAG('L','A','D',' ')}, /* Ladin */
+ {HB_TAG('l','m','a',' '), HB_TAG_NONE }, /* East Limba != Low Mari */
+ {HB_TAG('l','m','b',' '), HB_TAG_NONE }, /* Merei != Limbu */
+ {HB_TAG('l','m','n',' '), HB_TAG('L','A','M',' ')}, /* Lambadi -> Lambani */
+/*{HB_TAG('l','m','o',' '), HB_TAG('L','M','O',' ')},*/ /* Lombard */
+ {HB_TAG('l','m','w',' '), HB_TAG_NONE }, /* Lake Miwok != Lomwe */
+ {HB_TAG('l','n','a',' '), HB_TAG('B','A','D','0')}, /* Langbashe -> Banda */
+ {HB_TAG('l','n','l',' '), HB_TAG('B','A','D','0')}, /* South Central Banda -> Banda */
+/*{HB_TAG('l','o','m',' '), HB_TAG('L','O','M',' ')},*/ /* Loma (Liberia) */
+ {HB_TAG('l','o','u',' '), HB_TAG('C','P','P',' ')}, /* Louisiana Creole -> Creoles */
+/*{HB_TAG('l','p','o',' '), HB_TAG('L','P','O',' ')},*/ /* Lipo */
+/*{HB_TAG('l','r','c',' '), HB_TAG('L','R','C',' ')},*/ /* Northern Luri -> Luri */
+ {HB_TAG('l','r','i',' '), HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */
+ {HB_TAG('l','r','m',' '), HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */
+ {HB_TAG('l','r','t',' '), HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */
+ {HB_TAG('l','s','b',' '), HB_TAG_NONE }, /* Burundian Sign Language != Lower Sorbian */
+ {HB_TAG('l','s','m',' '), HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */
+ {HB_TAG('l','t','g',' '), HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */
+ {HB_TAG('l','t','h',' '), HB_TAG_NONE }, /* Thur != Lithuanian */
+ {HB_TAG('l','t','o',' '), HB_TAG('L','U','H',' ')}, /* Tsotso -> Luyia */
+ {HB_TAG('l','t','s',' '), HB_TAG('L','U','H',' ')}, /* Tachoni -> Luyia */
+/*{HB_TAG('l','u','a',' '), HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */
+/*{HB_TAG('l','u','o',' '), HB_TAG('L','U','O',' ')},*/ /* Luo (Kenya and Tanzania) */
+ {HB_TAG('l','u','s',' '), HB_TAG('M','I','Z',' ')}, /* Lushai -> Mizo */
+ {HB_TAG('l','u','s',' '), HB_TAG('Q','I','N',' ')}, /* Lushai -> Chin */
+ {HB_TAG('l','u','y',' '), HB_TAG('L','U','H',' ')}, /* Luyia [macrolanguage] */
+ {HB_TAG('l','u','z',' '), HB_TAG('L','R','C',' ')}, /* Southern Luri -> Luri */
+ {HB_TAG('l','v','i',' '), HB_TAG_NONE }, /* Lavi != Latvian */
+ {HB_TAG('l','v','s',' '), HB_TAG('L','V','I',' ')}, /* Standard Latvian -> Latvian */
+ {HB_TAG('l','w','g',' '), HB_TAG('L','U','H',' ')}, /* Wanga -> Luyia */
+ {HB_TAG('l','z','h',' '), HB_TAG('Z','H','T',' ')}, /* Literary Chinese -> Chinese, Traditional */
+ {HB_TAG('l','z','z',' '), HB_TAG('L','A','Z',' ')}, /* Laz */
+/*{HB_TAG('m','a','d',' '), HB_TAG('M','A','D',' ')},*/ /* Madurese -> Madura */
+/*{HB_TAG('m','a','g',' '), HB_TAG('M','A','G',' ')},*/ /* Magahi */
+ {HB_TAG('m','a','i',' '), HB_TAG('M','T','H',' ')}, /* Maithili */
+ {HB_TAG('m','a','j',' '), HB_TAG_NONE }, /* Jalapa De Díaz Mazatec != Majang */
+ {HB_TAG('m','a','k',' '), HB_TAG('M','K','R',' ')}, /* Makasar */
+ {HB_TAG('m','a','m',' '), HB_TAG('M','A','M',' ')}, /* Mam */
+ {HB_TAG('m','a','m',' '), HB_TAG('M','Y','N',' ')}, /* Mam -> Mayan */
+ {HB_TAG('m','a','n',' '), HB_TAG('M','N','K',' ')}, /* Mandingo [macrolanguage] -> Maninka */
+ {HB_TAG('m','a','p',' '), HB_TAG_NONE }, /* Austronesian [collection] != Mapudungun */
+ {HB_TAG('m','a','w',' '), HB_TAG_NONE }, /* Mampruli != Marwari */
+ {HB_TAG('m','a','x',' '), HB_TAG('M','L','Y',' ')}, /* North Moluccan Malay -> Malay */
+ {HB_TAG('m','a','x',' '), HB_TAG('C','P','P',' ')}, /* North Moluccan Malay -> Creoles */
+ {HB_TAG('m','b','f',' '), HB_TAG('C','P','P',' ')}, /* Baba Malay -> Creoles */
+ {HB_TAG('m','b','n',' '), HB_TAG_NONE }, /* Macaguán != Mbundu */
+/*{HB_TAG('m','b','o',' '), HB_TAG('M','B','O',' ')},*/ /* Mbo (Cameroon) */
+ {HB_TAG('m','c','h',' '), HB_TAG_NONE }, /* Maquiritari != Manchu */
+ {HB_TAG('m','c','m',' '), HB_TAG('C','P','P',' ')}, /* Malaccan Creole Portuguese -> Creoles */
+ {HB_TAG('m','c','r',' '), HB_TAG_NONE }, /* Menya != Moose Cree */
+ {HB_TAG('m','c','t',' '), HB_TAG('B','T','I',' ')}, /* Mengisa -> Beti */
+ {HB_TAG('m','d','e',' '), HB_TAG_NONE }, /* Maba (Chad) != Mende */
+ {HB_TAG('m','d','f',' '), HB_TAG('M','O','K',' ')}, /* Moksha */
+/*{HB_TAG('m','d','r',' '), HB_TAG('M','D','R',' ')},*/ /* Mandar */
+ {HB_TAG('m','d','y',' '), HB_TAG('M','L','E',' ')}, /* Male (Ethiopia) */
+ {HB_TAG('m','e','n',' '), HB_TAG('M','D','E',' ')}, /* Mende (Sierra Leone) */
+ {HB_TAG('m','e','o',' '), HB_TAG('M','L','Y',' ')}, /* Kedah Malay -> Malay */
+/*{HB_TAG('m','e','r',' '), HB_TAG('M','E','R',' ')},*/ /* Meru */
+ {HB_TAG('m','f','a',' '), HB_TAG('M','F','A',' ')}, /* Pattani Malay */
+ {HB_TAG('m','f','a',' '), HB_TAG('M','L','Y',' ')}, /* Pattani Malay -> Malay */
+ {HB_TAG('m','f','b',' '), HB_TAG('M','L','Y',' ')}, /* Bangka -> Malay */
+ {HB_TAG('m','f','e',' '), HB_TAG('M','F','E',' ')}, /* Morisyen */
+ {HB_TAG('m','f','e',' '), HB_TAG('C','P','P',' ')}, /* Morisyen -> Creoles */
+ {HB_TAG('m','f','p',' '), HB_TAG('C','P','P',' ')}, /* Makassar Malay -> Creoles */
+ {HB_TAG('m','h','c',' '), HB_TAG('M','Y','N',' ')}, /* Mocho -> Mayan */
+ {HB_TAG('m','h','r',' '), HB_TAG('L','M','A',' ')}, /* Eastern Mari -> Low Mari */
+ {HB_TAG('m','h','v',' '), HB_TAG('A','R','K',' ')}, /* Arakanese (retired code) -> Rakhine */
+ {HB_TAG('m','i','n',' '), HB_TAG('M','I','N',' ')}, /* Minangkabau */
+ {HB_TAG('m','i','n',' '), HB_TAG('M','L','Y',' ')}, /* Minangkabau -> Malay */
+ {HB_TAG('m','i','z',' '), HB_TAG_NONE }, /* Coatzospan Mixtec != Mizo */
+ {HB_TAG('m','k','n',' '), HB_TAG('C','P','P',' ')}, /* Kupang Malay -> Creoles */
+ {HB_TAG('m','k','r',' '), HB_TAG_NONE }, /* Malas != Makasar */
+ {HB_TAG('m','k','u',' '), HB_TAG('M','N','K',' ')}, /* Konyanka Maninka -> Maninka */
+/*{HB_TAG('m','k','w',' '), HB_TAG('M','K','W',' ')},*/ /* Kituba (Congo) */
+ {HB_TAG('m','l','e',' '), HB_TAG_NONE }, /* Manambu != Male */
+ {HB_TAG('m','l','n',' '), HB_TAG_NONE }, /* Malango != Malinke */
+ {HB_TAG('m','l','q',' '), HB_TAG('M','L','N',' ')}, /* Western Maninkakan -> Malinke */
+ {HB_TAG('m','l','q',' '), HB_TAG('M','N','K',' ')}, /* Western Maninkakan -> Maninka */
+ {HB_TAG('m','l','r',' '), HB_TAG_NONE }, /* Vame != Malayalam Reformed */
+ {HB_TAG('m','m','r',' '), HB_TAG('H','M','N',' ')}, /* Western Xiangxi Miao -> Hmong */
+ {HB_TAG('m','n','c',' '), HB_TAG('M','C','H',' ')}, /* Manchu */
+ {HB_TAG('m','n','d',' '), HB_TAG_NONE }, /* Mondé != Mandinka */
+ {HB_TAG('m','n','g',' '), HB_TAG_NONE }, /* Eastern Mnong != Mongolian */
+ {HB_TAG('m','n','h',' '), HB_TAG('B','A','D','0')}, /* Mono (Democratic Republic of Congo) -> Banda */
+/*{HB_TAG('m','n','i',' '), HB_TAG('M','N','I',' ')},*/ /* Manipuri */
+ {HB_TAG('m','n','k',' '), HB_TAG('M','N','D',' ')}, /* Mandinka */
+ {HB_TAG('m','n','k',' '), HB_TAG('M','N','K',' ')}, /* Mandinka -> Maninka */
+ {HB_TAG('m','n','p',' '), HB_TAG('Z','H','S',' ')}, /* Min Bei Chinese -> Chinese, Simplified */
+ {HB_TAG('m','n','s',' '), HB_TAG('M','A','N',' ')}, /* Mansi */
+ {HB_TAG('m','n','w',' '), HB_TAG('M','O','N',' ')}, /* Mon */
+ {HB_TAG('m','n','w',' '), HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */
+ {HB_TAG('m','n','x',' '), HB_TAG_NONE }, /* Manikion != Manx */
+ {HB_TAG('m','o','d',' '), HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */
+/*{HB_TAG('m','o','h',' '), HB_TAG('M','O','H',' ')},*/ /* Mohawk */
+ {HB_TAG('m','o','k',' '), HB_TAG_NONE }, /* Morori != Moksha */
+ {HB_TAG('m','o','p',' '), HB_TAG('M','Y','N',' ')}, /* Mopán Maya -> Mayan */
+ {HB_TAG('m','o','r',' '), HB_TAG_NONE }, /* Moro != Moroccan */
+/*{HB_TAG('m','o','s',' '), HB_TAG('M','O','S',' ')},*/ /* Mossi */
+ {HB_TAG('m','p','e',' '), HB_TAG('M','A','J',' ')}, /* Majang */
+ {HB_TAG('m','q','g',' '), HB_TAG('M','L','Y',' ')}, /* Kota Bangun Kutai Malay -> Malay */
+ {HB_TAG('m','r','h',' '), HB_TAG('Q','I','N',' ')}, /* Mara Chin -> Chin */
+ {HB_TAG('m','r','j',' '), HB_TAG('H','M','A',' ')}, /* Western Mari -> High Mari */
+ {HB_TAG('m','s','c',' '), HB_TAG('M','N','K',' ')}, /* Sankaran Maninka -> Maninka */
+ {HB_TAG('m','s','h',' '), HB_TAG('M','L','G',' ')}, /* Masikoro Malagasy -> Malagasy */
+ {HB_TAG('m','s','i',' '), HB_TAG('M','L','Y',' ')}, /* Sabah Malay -> Malay */
+ {HB_TAG('m','s','i',' '), HB_TAG('C','P','P',' ')}, /* Sabah Malay -> Creoles */
+ {HB_TAG('m','t','h',' '), HB_TAG_NONE }, /* Munggui != Maithili */
+ {HB_TAG('m','t','r',' '), HB_TAG('M','A','W',' ')}, /* Mewari -> Marwari */
+ {HB_TAG('m','t','s',' '), HB_TAG_NONE }, /* Yora != Maltese */
+ {HB_TAG('m','u','d',' '), HB_TAG('C','P','P',' ')}, /* Mednyj Aleut -> Creoles */
+ {HB_TAG('m','u','i',' '), HB_TAG('M','L','Y',' ')}, /* Musi -> Malay */
+ {HB_TAG('m','u','n',' '), HB_TAG_NONE }, /* Munda [collection] != Mundari */
+ {HB_TAG('m','u','p',' '), HB_TAG('R','A','J',' ')}, /* Malvi -> Rajasthani */
+ {HB_TAG('m','u','q',' '), HB_TAG('H','M','N',' ')}, /* Eastern Xiangxi Miao -> Hmong */
+/*{HB_TAG('m','u','s',' '), HB_TAG('M','U','S',' ')},*/ /* Creek -> Muscogee */
+ {HB_TAG('m','v','b',' '), HB_TAG('A','T','H',' ')}, /* Mattole -> Athapaskan */
+ {HB_TAG('m','v','e',' '), HB_TAG('M','A','W',' ')}, /* Marwari (Pakistan) */
+ {HB_TAG('m','v','f',' '), HB_TAG('M','N','G',' ')}, /* Peripheral Mongolian -> Mongolian */
+ {HB_TAG('m','w','k',' '), HB_TAG('M','N','K',' ')}, /* Kita Maninkakan -> Maninka */
+/*{HB_TAG('m','w','l',' '), HB_TAG('M','W','L',' ')},*/ /* Mirandese */
+ {HB_TAG('m','w','q',' '), HB_TAG('Q','I','N',' ')}, /* Mün Chin -> Chin */
+ {HB_TAG('m','w','r',' '), HB_TAG('M','A','W',' ')}, /* Marwari [macrolanguage] */
+ {HB_TAG('m','w','w',' '), HB_TAG('M','W','W',' ')}, /* Hmong Daw */
+ {HB_TAG('m','w','w',' '), HB_TAG('H','M','N',' ')}, /* Hmong Daw -> Hmong */
+ {HB_TAG('m','y','m',' '), HB_TAG('M','E','N',' ')}, /* Me’en */
+/*{HB_TAG('m','y','n',' '), HB_TAG('M','Y','N',' ')},*/ /* Mayan [collection] */
+ {HB_TAG('m','y','q',' '), HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) -> Maninka */
+ {HB_TAG('m','y','v',' '), HB_TAG('E','R','Z',' ')}, /* Erzya */
+ {HB_TAG('m','z','b',' '), HB_TAG('B','B','R',' ')}, /* Tumzabt -> Berber */
+/*{HB_TAG('m','z','n',' '), HB_TAG('M','Z','N',' ')},*/ /* Mazanderani */
+ {HB_TAG('m','z','s',' '), HB_TAG('C','P','P',' ')}, /* Macanese -> Creoles */
+ {HB_TAG('n','a','g',' '), HB_TAG('N','A','G',' ')}, /* Naga Pidgin -> Naga-Assamese */
+ {HB_TAG('n','a','g',' '), HB_TAG('C','P','P',' ')}, /* Naga Pidgin -> Creoles */
+/*{HB_TAG('n','a','h',' '), HB_TAG('N','A','H',' ')},*/ /* Nahuatl [collection] */
+ {HB_TAG('n','a','n',' '), HB_TAG('Z','H','S',' ')}, /* Min Nan Chinese -> Chinese, Simplified */
+/*{HB_TAG('n','a','p',' '), HB_TAG('N','A','P',' ')},*/ /* Neapolitan */
+ {HB_TAG('n','a','s',' '), HB_TAG_NONE }, /* Naasioi != Naskapi */
+ {HB_TAG('n','a','z',' '), HB_TAG('N','A','H',' ')}, /* Coatepec Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','h',' '), HB_TAG('N','A','H',' ')}, /* Central Huasteca Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','i',' '), HB_TAG('N','A','H',' ')}, /* Classical Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','j',' '), HB_TAG('N','A','H',' ')}, /* Northern Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','l',' '), HB_TAG('N','A','H',' ')}, /* Michoacán Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','r',' '), HB_TAG_NONE }, /* Ncane != N-Cree */
+ {HB_TAG('n','c','x',' '), HB_TAG('N','A','H',' ')}, /* Central Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('n','d','b',' '), HB_TAG_NONE }, /* Kenswei Nsei != Ndebele */
+/*{HB_TAG('n','d','c',' '), HB_TAG('N','D','C',' ')},*/ /* Ndau */
+ {HB_TAG('n','d','g',' '), HB_TAG_NONE }, /* Ndengereko != Ndonga */
+/*{HB_TAG('n','d','s',' '), HB_TAG('N','D','S',' ')},*/ /* Low Saxon */
+ {HB_TAG('n','e','f',' '), HB_TAG('C','P','P',' ')}, /* Nefamese -> Creoles */
+/*{HB_TAG('n','e','w',' '), HB_TAG('N','E','W',' ')},*/ /* Newari */
+/*{HB_TAG('n','g','a',' '), HB_TAG('N','G','A',' ')},*/ /* Ngbaka */
+ {HB_TAG('n','g','l',' '), HB_TAG('L','M','W',' ')}, /* Lomwe */
+ {HB_TAG('n','g','m',' '), HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */
+ {HB_TAG('n','g','o',' '), HB_TAG('S','X','T',' ')}, /* Ngoni (retired code) -> Sutu */
+ {HB_TAG('n','g','r',' '), HB_TAG_NONE }, /* Engdewu != Nagari */
+ {HB_TAG('n','g','u',' '), HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','c',' '), HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','d',' '), HB_TAG('G','U','A',' ')}, /* Chiripá -> Guarani */
+ {HB_TAG('n','h','e',' '), HB_TAG('N','A','H',' ')}, /* Eastern Huasteca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','g',' '), HB_TAG('N','A','H',' ')}, /* Tetelcingo Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','i',' '), HB_TAG('N','A','H',' ')}, /* Zacatlán-Ahuacatlán-Tepetzintla Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','k',' '), HB_TAG('N','A','H',' ')}, /* Isthmus-Cosoleacaque Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','m',' '), HB_TAG('N','A','H',' ')}, /* Morelos Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','n',' '), HB_TAG('N','A','H',' ')}, /* Central Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','p',' '), HB_TAG('N','A','H',' ')}, /* Isthmus-Pajapan Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','q',' '), HB_TAG('N','A','H',' ')}, /* Huaxcaleca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','t',' '), HB_TAG('N','A','H',' ')}, /* Ometepec Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','v',' '), HB_TAG('N','A','H',' ')}, /* Temascaltepec Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','w',' '), HB_TAG('N','A','H',' ')}, /* Western Huasteca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','x',' '), HB_TAG('N','A','H',' ')}, /* Isthmus-Mecayapan Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','y',' '), HB_TAG('N','A','H',' ')}, /* Northern Oaxaca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','z',' '), HB_TAG('N','A','H',' ')}, /* Santa María La Alta Nahuatl -> Nahuatl */
+ {HB_TAG('n','i','q',' '), HB_TAG('K','A','L',' ')}, /* Nandi -> Kalenjin */
+ {HB_TAG('n','i','s',' '), HB_TAG_NONE }, /* Nimi != Nisi */
+/*{HB_TAG('n','i','u',' '), HB_TAG('N','I','U',' ')},*/ /* Niuean */
+ {HB_TAG('n','i','v',' '), HB_TAG('G','I','L',' ')}, /* Gilyak */
+ {HB_TAG('n','j','t',' '), HB_TAG('C','P','P',' ')}, /* Ndyuka-Trio Pidgin -> Creoles */
+ {HB_TAG('n','j','z',' '), HB_TAG('N','I','S',' ')}, /* Nyishi -> Nisi */
+ {HB_TAG('n','k','o',' '), HB_TAG_NONE }, /* Nkonya != N’Ko */
+ {HB_TAG('n','k','x',' '), HB_TAG('I','J','O',' ')}, /* Nkoroo -> Ijo */
+ {HB_TAG('n','l','a',' '), HB_TAG('B','M','L',' ')}, /* Ngombale -> Bamileke */
+ {HB_TAG('n','l','e',' '), HB_TAG('L','U','H',' ')}, /* East Nyala -> Luyia */
+ {HB_TAG('n','l','n',' '), HB_TAG('N','A','H',' ')}, /* Durango Nahuatl (retired code) -> Nahuatl */
+ {HB_TAG('n','l','v',' '), HB_TAG('N','A','H',' ')}, /* Orizaba Nahuatl -> Nahuatl */
+ {HB_TAG('n','n','h',' '), HB_TAG('B','M','L',' ')}, /* Ngiemboon -> Bamileke */
+ {HB_TAG('n','n','z',' '), HB_TAG('B','M','L',' ')}, /* Nda'nda' -> Bamileke */
+ {HB_TAG('n','o','d',' '), HB_TAG('N','T','A',' ')}, /* Northern Thai -> Northern Tai */
+/*{HB_TAG('n','o','e',' '), HB_TAG('N','O','E',' ')},*/ /* Nimadi */
+/*{HB_TAG('n','o','g',' '), HB_TAG('N','O','G',' ')},*/ /* Nogai */
+/*{HB_TAG('n','o','v',' '), HB_TAG('N','O','V',' ')},*/ /* Novial */
+ {HB_TAG('n','p','i',' '), HB_TAG('N','E','P',' ')}, /* Nepali */
+ {HB_TAG('n','p','l',' '), HB_TAG('N','A','H',' ')}, /* Southeastern Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('n','q','o',' '), HB_TAG('N','K','O',' ')}, /* N’Ko */
+ {HB_TAG('n','s','k',' '), HB_TAG('N','A','S',' ')}, /* Naskapi */
+ {HB_TAG('n','s','m',' '), HB_TAG_NONE }, /* Sumi Naga != Northern Sami */
+/*{HB_TAG('n','s','o',' '), HB_TAG('N','S','O',' ')},*/ /* Northern Sotho */
+ {HB_TAG('n','s','u',' '), HB_TAG('N','A','H',' ')}, /* Sierra Negra Nahuatl -> Nahuatl */
+ {HB_TAG('n','t','o',' '), HB_TAG_NONE }, /* Ntomba != Esperanto */
+ {HB_TAG('n','u','e',' '), HB_TAG('B','A','D','0')}, /* Ngundu -> Banda */
+ {HB_TAG('n','u','u',' '), HB_TAG('B','A','D','0')}, /* Ngbundu -> Banda */
+ {HB_TAG('n','u','z',' '), HB_TAG('N','A','H',' ')}, /* Tlamacazapa Nahuatl -> Nahuatl */
+ {HB_TAG('n','w','e',' '), HB_TAG('B','M','L',' ')}, /* Ngwe -> Bamileke */
+ {HB_TAG('n','y','d',' '), HB_TAG('L','U','H',' ')}, /* Nyore -> Luyia */
+/*{HB_TAG('n','y','m',' '), HB_TAG('N','Y','M',' ')},*/ /* Nyamwezi */
+ {HB_TAG('n','y','n',' '), HB_TAG('N','K','L',' ')}, /* Nyankole */
+/*{HB_TAG('n','z','a',' '), HB_TAG('N','Z','A',' ')},*/ /* Tigon Mbembe -> Mbembe Tigon */
+/*{HB_TAG('o','j','b',' '), HB_TAG('O','J','B',' ')},*/ /* Northwestern Ojibwa -> Ojibway */
+ {HB_TAG('o','j','c',' '), HB_TAG('O','J','B',' ')}, /* Central Ojibwa -> Ojibway */
+ {HB_TAG('o','j','g',' '), HB_TAG('O','J','B',' ')}, /* Eastern Ojibwa -> Ojibway */
+ {HB_TAG('o','j','s',' '), HB_TAG('O','C','R',' ')}, /* Severn Ojibwa -> Oji-Cree */
+ {HB_TAG('o','j','s',' '), HB_TAG('O','J','B',' ')}, /* Severn Ojibwa -> Ojibway */
+ {HB_TAG('o','j','w',' '), HB_TAG('O','J','B',' ')}, /* Western Ojibwa -> Ojibway */
+ {HB_TAG('o','k','d',' '), HB_TAG('I','J','O',' ')}, /* Okodia -> Ijo */
+ {HB_TAG('o','k','i',' '), HB_TAG('K','A','L',' ')}, /* Okiek -> Kalenjin */
+ {HB_TAG('o','k','m',' '), HB_TAG('K','O','H',' ')}, /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
+ {HB_TAG('o','k','r',' '), HB_TAG('I','J','O',' ')}, /* Kirike -> Ijo */
+ {HB_TAG('o','n','x',' '), HB_TAG('C','P','P',' ')}, /* Onin Based Pidgin -> Creoles */
+ {HB_TAG('o','o','r',' '), HB_TAG('C','P','P',' ')}, /* Oorlams -> Creoles */
+ {HB_TAG('o','r','c',' '), HB_TAG('O','R','O',' ')}, /* Orma -> Oromo */
+ {HB_TAG('o','r','n',' '), HB_TAG('M','L','Y',' ')}, /* Orang Kanaq -> Malay */
+ {HB_TAG('o','r','o',' '), HB_TAG_NONE }, /* Orokolo != Oromo */
+ {HB_TAG('o','r','r',' '), HB_TAG('I','J','O',' ')}, /* Oruma -> Ijo */
+ {HB_TAG('o','r','s',' '), HB_TAG('M','L','Y',' ')}, /* Orang Seletar -> Malay */
+ {HB_TAG('o','r','y',' '), HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) */
+ {HB_TAG('o','t','w',' '), HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */
+ {HB_TAG('o','u','a',' '), HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */
+ {HB_TAG('p','a','a',' '), HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */
+/*{HB_TAG('p','a','g',' '), HB_TAG('P','A','G',' ')},*/ /* Pangasinan */
+ {HB_TAG('p','a','l',' '), HB_TAG_NONE }, /* Pahlavi != Pali */
+/*{HB_TAG('p','a','m',' '), HB_TAG('P','A','M',' ')},*/ /* Pampanga -> Pampangan */
+ {HB_TAG('p','a','p',' '), HB_TAG('P','A','P','0')}, /* Papiamento -> Papiamentu */
+ {HB_TAG('p','a','p',' '), HB_TAG('C','P','P',' ')}, /* Papiamento -> Creoles */
+ {HB_TAG('p','a','s',' '), HB_TAG_NONE }, /* Papasena != Pashto */
+/*{HB_TAG('p','a','u',' '), HB_TAG('P','A','U',' ')},*/ /* Palauan */
+ {HB_TAG('p','b','t',' '), HB_TAG('P','A','S',' ')}, /* Southern Pashto -> Pashto */
+ {HB_TAG('p','b','u',' '), HB_TAG('P','A','S',' ')}, /* Northern Pashto -> Pashto */
+/*{HB_TAG('p','c','c',' '), HB_TAG('P','C','C',' ')},*/ /* Bouyei */
+/*{HB_TAG('p','c','d',' '), HB_TAG('P','C','D',' ')},*/ /* Picard */
+ {HB_TAG('p','c','e',' '), HB_TAG('P','L','G',' ')}, /* Ruching Palaung -> Palaung */
+ {HB_TAG('p','c','k',' '), HB_TAG('Q','I','N',' ')}, /* Paite Chin -> Chin */
+ {HB_TAG('p','c','m',' '), HB_TAG('C','P','P',' ')}, /* Nigerian Pidgin -> Creoles */
+/*{HB_TAG('p','d','c',' '), HB_TAG('P','D','C',' ')},*/ /* Pennsylvania German */
+ {HB_TAG('p','d','u',' '), HB_TAG('K','R','N',' ')}, /* Kayan -> Karen */
+ {HB_TAG('p','e','a',' '), HB_TAG('C','P','P',' ')}, /* Peranakan Indonesian -> Creoles */
+ {HB_TAG('p','e','l',' '), HB_TAG('M','L','Y',' ')}, /* Pekal -> Malay */
+ {HB_TAG('p','e','s',' '), HB_TAG('F','A','R',' ')}, /* Iranian Persian -> Persian */
+ {HB_TAG('p','e','y',' '), HB_TAG('C','P','P',' ')}, /* Petjo -> Creoles */
+ {HB_TAG('p','g','a',' '), HB_TAG('A','R','A',' ')}, /* Sudanese Creole Arabic -> Arabic */
+ {HB_TAG('p','g','a',' '), HB_TAG('C','P','P',' ')}, /* Sudanese Creole Arabic -> Creoles */
+/*{HB_TAG('p','h','k',' '), HB_TAG('P','H','K',' ')},*/ /* Phake */
+ {HB_TAG('p','i','h',' '), HB_TAG('P','I','H',' ')}, /* Pitcairn-Norfolk -> Norfolk */
+ {HB_TAG('p','i','h',' '), HB_TAG('C','P','P',' ')}, /* Pitcairn-Norfolk -> Creoles */
+ {HB_TAG('p','i','l',' '), HB_TAG_NONE }, /* Yom != Filipino */
+ {HB_TAG('p','i','s',' '), HB_TAG('C','P','P',' ')}, /* Pijin -> Creoles */
+ {HB_TAG('p','k','h',' '), HB_TAG('Q','I','N',' ')}, /* Pankhu -> Chin */
+ {HB_TAG('p','k','o',' '), HB_TAG('K','A','L',' ')}, /* Pökoot -> Kalenjin */
+ {HB_TAG('p','l','g',' '), HB_TAG_NONE }, /* Pilagá != Palaung */
+ {HB_TAG('p','l','k',' '), HB_TAG_NONE }, /* Kohistani Shina != Polish */
+ {HB_TAG('p','l','l',' '), HB_TAG('P','L','G',' ')}, /* Shwe Palaung -> Palaung */
+ {HB_TAG('p','l','n',' '), HB_TAG('C','P','P',' ')}, /* Palenquero -> Creoles */
+ {HB_TAG('p','l','p',' '), HB_TAG('P','A','P',' ')}, /* Palpa (retired code) */
+ {HB_TAG('p','l','t',' '), HB_TAG('M','L','G',' ')}, /* Plateau Malagasy -> Malagasy */
+ {HB_TAG('p','m','l',' '), HB_TAG('C','P','P',' ')}, /* Lingua Franca -> Creoles */
+/*{HB_TAG('p','m','s',' '), HB_TAG('P','M','S',' ')},*/ /* Piemontese */
+ {HB_TAG('p','m','y',' '), HB_TAG('C','P','P',' ')}, /* Papuan Malay -> Creoles */
+/*{HB_TAG('p','n','b',' '), HB_TAG('P','N','B',' ')},*/ /* Western Panjabi */
+ {HB_TAG('p','o','c',' '), HB_TAG('M','Y','N',' ')}, /* Poqomam -> Mayan */
+ {HB_TAG('p','o','h',' '), HB_TAG('P','O','H',' ')}, /* Poqomchi' -> Pocomchi */
+ {HB_TAG('p','o','h',' '), HB_TAG('M','Y','N',' ')}, /* Poqomchi' -> Mayan */
+/*{HB_TAG('p','o','n',' '), HB_TAG('P','O','N',' ')},*/ /* Pohnpeian */
+ {HB_TAG('p','o','v',' '), HB_TAG('C','P','P',' ')}, /* Upper Guinea Crioulo -> Creoles */
+ {HB_TAG('p','p','a',' '), HB_TAG('B','A','G',' ')}, /* Pao (retired code) -> Baghelkhandi */
+ {HB_TAG('p','r','e',' '), HB_TAG('C','P','P',' ')}, /* Principense -> Creoles */
+/*{HB_TAG('p','r','o',' '), HB_TAG('P','R','O',' ')},*/ /* Old Provençal (to 1500) -> Provençal / Old Provençal */
+ {HB_TAG('p','r','s',' '), HB_TAG('D','R','I',' ')}, /* Dari */
+ {HB_TAG('p','r','s',' '), HB_TAG('F','A','R',' ')}, /* Dari -> Persian */
+ {HB_TAG('p','s','e',' '), HB_TAG('M','L','Y',' ')}, /* Central Malay -> Malay */
+ {HB_TAG('p','s','t',' '), HB_TAG('P','A','S',' ')}, /* Central Pashto -> Pashto */
+ {HB_TAG('p','u','b',' '), HB_TAG('Q','I','N',' ')}, /* Purum -> Chin */
+ {HB_TAG('p','u','z',' '), HB_TAG('Q','I','N',' ')}, /* Purum Naga (retired code) -> Chin */
+ {HB_TAG('p','w','o',' '), HB_TAG('P','W','O',' ')}, /* Pwo Western Karen -> Western Pwo Karen */
+ {HB_TAG('p','w','o',' '), HB_TAG('K','R','N',' ')}, /* Pwo Western Karen -> Karen */
+ {HB_TAG('p','w','w',' '), HB_TAG('K','R','N',' ')}, /* Pwo Northern Karen -> Karen */
+ {HB_TAG('q','u','b',' '), HB_TAG('Q','W','H',' ')}, /* Huallaga Huánuco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','u','b',' '), HB_TAG('Q','U','Z',' ')}, /* Huallaga Huánuco Quechua -> Quechua */
+ {HB_TAG('q','u','c',' '), HB_TAG('Q','U','C',' ')}, /* K’iche’ */
+ {HB_TAG('q','u','c',' '), HB_TAG('M','Y','N',' ')}, /* K'iche' -> Mayan */
+ {HB_TAG('q','u','d',' '), HB_TAG('Q','V','I',' ')}, /* Calderón Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','d',' '), HB_TAG('Q','U','Z',' ')}, /* Calderón Highland Quichua -> Quechua */
+ {HB_TAG('q','u','f',' '), HB_TAG('Q','U','Z',' ')}, /* Lambayeque Quechua -> Quechua */
+ {HB_TAG('q','u','g',' '), HB_TAG('Q','V','I',' ')}, /* Chimborazo Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','g',' '), HB_TAG('Q','U','Z',' ')}, /* Chimborazo Highland Quichua -> Quechua */
+ {HB_TAG('q','u','h',' '), HB_TAG('Q','U','H',' ')}, /* South Bolivian Quechua -> Quechua (Bolivia) */
+ {HB_TAG('q','u','h',' '), HB_TAG('Q','U','Z',' ')}, /* South Bolivian Quechua -> Quechua */
+ {HB_TAG('q','u','k',' '), HB_TAG('Q','U','Z',' ')}, /* Chachapoyas Quechua -> Quechua */
+ {HB_TAG('q','u','l',' '), HB_TAG('Q','U','H',' ')}, /* North Bolivian Quechua -> Quechua (Bolivia) */
+ {HB_TAG('q','u','l',' '), HB_TAG('Q','U','Z',' ')}, /* North Bolivian Quechua -> Quechua */
+ {HB_TAG('q','u','m',' '), HB_TAG('M','Y','N',' ')}, /* Sipacapense -> Mayan */
+ {HB_TAG('q','u','p',' '), HB_TAG('Q','V','I',' ')}, /* Southern Pastaza Quechua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','p',' '), HB_TAG('Q','U','Z',' ')}, /* Southern Pastaza Quechua -> Quechua */
+ {HB_TAG('q','u','r',' '), HB_TAG('Q','W','H',' ')}, /* Yanahuanca Pasco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','u','r',' '), HB_TAG('Q','U','Z',' ')}, /* Yanahuanca Pasco Quechua -> Quechua */
+ {HB_TAG('q','u','s',' '), HB_TAG('Q','U','H',' ')}, /* Santiago del Estero Quichua -> Quechua (Bolivia) */
+ {HB_TAG('q','u','s',' '), HB_TAG('Q','U','Z',' ')}, /* Santiago del Estero Quichua -> Quechua */
+ {HB_TAG('q','u','v',' '), HB_TAG('M','Y','N',' ')}, /* Sacapulteco -> Mayan */
+ {HB_TAG('q','u','w',' '), HB_TAG('Q','V','I',' ')}, /* Tena Lowland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','w',' '), HB_TAG('Q','U','Z',' ')}, /* Tena Lowland Quichua -> Quechua */
+ {HB_TAG('q','u','x',' '), HB_TAG('Q','W','H',' ')}, /* Yauyos Quechua -> Quechua (Peru) */
+ {HB_TAG('q','u','x',' '), HB_TAG('Q','U','Z',' ')}, /* Yauyos Quechua -> Quechua */
+ {HB_TAG('q','u','y',' '), HB_TAG('Q','U','Z',' ')}, /* Ayacucho Quechua -> Quechua */
+/*{HB_TAG('q','u','z',' '), HB_TAG('Q','U','Z',' ')},*/ /* Cusco Quechua -> Quechua */
+ {HB_TAG('q','v','a',' '), HB_TAG('Q','W','H',' ')}, /* Ambo-Pasco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','a',' '), HB_TAG('Q','U','Z',' ')}, /* Ambo-Pasco Quechua -> Quechua */
+ {HB_TAG('q','v','c',' '), HB_TAG('Q','U','Z',' ')}, /* Cajamarca Quechua -> Quechua */
+ {HB_TAG('q','v','e',' '), HB_TAG('Q','U','Z',' ')}, /* Eastern Apurímac Quechua -> Quechua */
+ {HB_TAG('q','v','h',' '), HB_TAG('Q','W','H',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','h',' '), HB_TAG('Q','U','Z',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua */
+ {HB_TAG('q','v','i',' '), HB_TAG('Q','V','I',' ')}, /* Imbabura Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','i',' '), HB_TAG('Q','U','Z',' ')}, /* Imbabura Highland Quichua -> Quechua */
+ {HB_TAG('q','v','j',' '), HB_TAG('Q','V','I',' ')}, /* Loja Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','j',' '), HB_TAG('Q','U','Z',' ')}, /* Loja Highland Quichua -> Quechua */
+ {HB_TAG('q','v','l',' '), HB_TAG('Q','W','H',' ')}, /* Cajatambo North Lima Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','l',' '), HB_TAG('Q','U','Z',' ')}, /* Cajatambo North Lima Quechua -> Quechua */
+ {HB_TAG('q','v','m',' '), HB_TAG('Q','W','H',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','m',' '), HB_TAG('Q','U','Z',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua */
+ {HB_TAG('q','v','n',' '), HB_TAG('Q','W','H',' ')}, /* North Junín Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','n',' '), HB_TAG('Q','U','Z',' ')}, /* North Junín Quechua -> Quechua */
+ {HB_TAG('q','v','o',' '), HB_TAG('Q','V','I',' ')}, /* Napo Lowland Quechua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','o',' '), HB_TAG('Q','U','Z',' ')}, /* Napo Lowland Quechua -> Quechua */
+ {HB_TAG('q','v','p',' '), HB_TAG('Q','W','H',' ')}, /* Pacaraos Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','p',' '), HB_TAG('Q','U','Z',' ')}, /* Pacaraos Quechua -> Quechua */
+ {HB_TAG('q','v','s',' '), HB_TAG('Q','U','Z',' ')}, /* San Martín Quechua -> Quechua */
+ {HB_TAG('q','v','w',' '), HB_TAG('Q','W','H',' ')}, /* Huaylla Wanca Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','w',' '), HB_TAG('Q','U','Z',' ')}, /* Huaylla Wanca Quechua -> Quechua */
+ {HB_TAG('q','v','z',' '), HB_TAG('Q','V','I',' ')}, /* Northern Pastaza Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','z',' '), HB_TAG('Q','U','Z',' ')}, /* Northern Pastaza Quichua -> Quechua */
+ {HB_TAG('q','w','a',' '), HB_TAG('Q','W','H',' ')}, /* Corongo Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','w','a',' '), HB_TAG('Q','U','Z',' ')}, /* Corongo Ancash Quechua -> Quechua */
+ {HB_TAG('q','w','c',' '), HB_TAG('Q','U','Z',' ')}, /* Classical Quechua -> Quechua */
+ {HB_TAG('q','w','h',' '), HB_TAG('Q','W','H',' ')}, /* Huaylas Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','w','h',' '), HB_TAG('Q','U','Z',' ')}, /* Huaylas Ancash Quechua -> Quechua */
+ {HB_TAG('q','w','s',' '), HB_TAG('Q','W','H',' ')}, /* Sihuas Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','w','s',' '), HB_TAG('Q','U','Z',' ')}, /* Sihuas Ancash Quechua -> Quechua */
+ {HB_TAG('q','w','t',' '), HB_TAG('A','T','H',' ')}, /* Kwalhioqua-Tlatskanai -> Athapaskan */
+ {HB_TAG('q','x','a',' '), HB_TAG('Q','W','H',' ')}, /* Chiquián Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','a',' '), HB_TAG('Q','U','Z',' ')}, /* Chiquián Ancash Quechua -> Quechua */
+ {HB_TAG('q','x','c',' '), HB_TAG('Q','W','H',' ')}, /* Chincha Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','c',' '), HB_TAG('Q','U','Z',' ')}, /* Chincha Quechua -> Quechua */
+ {HB_TAG('q','x','h',' '), HB_TAG('Q','W','H',' ')}, /* Panao Huánuco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','h',' '), HB_TAG('Q','U','Z',' ')}, /* Panao Huánuco Quechua -> Quechua */
+ {HB_TAG('q','x','l',' '), HB_TAG('Q','V','I',' ')}, /* Salasaca Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','x','l',' '), HB_TAG('Q','U','Z',' ')}, /* Salasaca Highland Quichua -> Quechua */
+ {HB_TAG('q','x','n',' '), HB_TAG('Q','W','H',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','n',' '), HB_TAG('Q','U','Z',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua */
+ {HB_TAG('q','x','o',' '), HB_TAG('Q','W','H',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','o',' '), HB_TAG('Q','U','Z',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua */
+ {HB_TAG('q','x','p',' '), HB_TAG('Q','U','Z',' ')}, /* Puno Quechua -> Quechua */
+ {HB_TAG('q','x','r',' '), HB_TAG('Q','V','I',' ')}, /* Cañar Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','x','r',' '), HB_TAG('Q','U','Z',' ')}, /* Cañar Highland Quichua -> Quechua */
+ {HB_TAG('q','x','t',' '), HB_TAG('Q','W','H',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','t',' '), HB_TAG('Q','U','Z',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua */
+ {HB_TAG('q','x','u',' '), HB_TAG('Q','U','Z',' ')}, /* Arequipa-La Unión Quechua -> Quechua */
+ {HB_TAG('q','x','w',' '), HB_TAG('Q','W','H',' ')}, /* Jauja Wanca Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','w',' '), HB_TAG('Q','U','Z',' ')}, /* Jauja Wanca Quechua -> Quechua */
+ {HB_TAG('r','a','g',' '), HB_TAG('L','U','H',' ')}, /* Logooli -> Luyia */
+/*{HB_TAG('r','a','j',' '), HB_TAG('R','A','J',' ')},*/ /* Rajasthani [macrolanguage] */
+ {HB_TAG('r','a','l',' '), HB_TAG('Q','I','N',' ')}, /* Ralte -> Chin */
+/*{HB_TAG('r','a','r',' '), HB_TAG('R','A','R',' ')},*/ /* Rarotongan */
+ {HB_TAG('r','b','b',' '), HB_TAG('P','L','G',' ')}, /* Rumai Palaung -> Palaung */
+ {HB_TAG('r','b','l',' '), HB_TAG('B','I','K',' ')}, /* Miraya Bikol -> Bikol */
+ {HB_TAG('r','c','f',' '), HB_TAG('C','P','P',' ')}, /* Réunion Creole French -> Creoles */
+/*{HB_TAG('r','e','j',' '), HB_TAG('R','E','J',' ')},*/ /* Rejang */
+/*{HB_TAG('r','h','g',' '), HB_TAG('R','H','G',' ')},*/ /* Rohingya */
+/*{HB_TAG('r','i','a',' '), HB_TAG('R','I','A',' ')},*/ /* Riang (India) */
+ {HB_TAG('r','i','f',' '), HB_TAG('R','I','F',' ')}, /* Tarifit */
+ {HB_TAG('r','i','f',' '), HB_TAG('B','B','R',' ')}, /* Tarifit -> Berber */
+/*{HB_TAG('r','i','t',' '), HB_TAG('R','I','T',' ')},*/ /* Ritharrngu -> Ritarungo */
+ {HB_TAG('r','k','i',' '), HB_TAG('A','R','K',' ')}, /* Rakhine */
+/*{HB_TAG('r','k','w',' '), HB_TAG('R','K','W',' ')},*/ /* Arakwal */
+ {HB_TAG('r','m','c',' '), HB_TAG('R','O','Y',' ')}, /* Carpathian Romani -> Romany */
+ {HB_TAG('r','m','f',' '), HB_TAG('R','O','Y',' ')}, /* Kalo Finnish Romani -> Romany */
+ {HB_TAG('r','m','l',' '), HB_TAG('R','O','Y',' ')}, /* Baltic Romani -> Romany */
+ {HB_TAG('r','m','n',' '), HB_TAG('R','O','Y',' ')}, /* Balkan Romani -> Romany */
+ {HB_TAG('r','m','o',' '), HB_TAG('R','O','Y',' ')}, /* Sinte Romani -> Romany */
+ {HB_TAG('r','m','s',' '), HB_TAG_NONE }, /* Romanian Sign Language != Romansh */
+ {HB_TAG('r','m','w',' '), HB_TAG('R','O','Y',' ')}, /* Welsh Romani -> Romany */
+ {HB_TAG('r','m','y',' '), HB_TAG('R','M','Y',' ')}, /* Vlax Romani */
+ {HB_TAG('r','m','y',' '), HB_TAG('R','O','Y',' ')}, /* Vlax Romani -> Romany */
+ {HB_TAG('r','m','z',' '), HB_TAG('A','R','K',' ')}, /* Marma -> Rakhine */
+ {HB_TAG('r','o','m',' '), HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */
+ {HB_TAG('r','o','p',' '), HB_TAG('C','P','P',' ')}, /* Kriol -> Creoles */
+ {HB_TAG('r','t','c',' '), HB_TAG('Q','I','N',' ')}, /* Rungtu Chin -> Chin */
+/*{HB_TAG('r','t','m',' '), HB_TAG('R','T','M',' ')},*/ /* Rotuman */
+ {HB_TAG('r','u','e',' '), HB_TAG('R','S','Y',' ')}, /* Rusyn */
+/*{HB_TAG('r','u','p',' '), HB_TAG('R','U','P',' ')},*/ /* Aromanian */
+ {HB_TAG('r','w','r',' '), HB_TAG('M','A','W',' ')}, /* Marwari (India) */
+ {HB_TAG('s','a','d',' '), HB_TAG_NONE }, /* Sandawe != Sadri */
+ {HB_TAG('s','a','h',' '), HB_TAG('Y','A','K',' ')}, /* Yakut -> Sakha */
+ {HB_TAG('s','a','m',' '), HB_TAG('P','A','A',' ')}, /* Samaritan Aramaic -> Palestinian Aramaic */
+/*{HB_TAG('s','a','s',' '), HB_TAG('S','A','S',' ')},*/ /* Sasak */
+/*{HB_TAG('s','a','t',' '), HB_TAG('S','A','T',' ')},*/ /* Santali */
+ {HB_TAG('s','a','y',' '), HB_TAG_NONE }, /* Saya != Sayisi */
+ {HB_TAG('s','c','f',' '), HB_TAG('C','P','P',' ')}, /* San Miguel Creole French -> Creoles */
+ {HB_TAG('s','c','h',' '), HB_TAG('Q','I','N',' ')}, /* Sakachep -> Chin */
+ {HB_TAG('s','c','i',' '), HB_TAG('C','P','P',' ')}, /* Sri Lankan Creole Malay -> Creoles */
+ {HB_TAG('s','c','k',' '), HB_TAG('S','A','D',' ')}, /* Sadri */
+/*{HB_TAG('s','c','n',' '), HB_TAG('S','C','N',' ')},*/ /* Sicilian */
+/*{HB_TAG('s','c','o',' '), HB_TAG('S','C','O',' ')},*/ /* Scots */
+ {HB_TAG('s','c','s',' '), HB_TAG('S','C','S',' ')}, /* North Slavey */
+ {HB_TAG('s','c','s',' '), HB_TAG('S','L','A',' ')}, /* North Slavey -> Slavey */
+ {HB_TAG('s','c','s',' '), HB_TAG('A','T','H',' ')}, /* North Slavey -> Athapaskan */
+ {HB_TAG('s','d','c',' '), HB_TAG('S','R','D',' ')}, /* Sassarese Sardinian -> Sardinian */
+ {HB_TAG('s','d','h',' '), HB_TAG('K','U','R',' ')}, /* Southern Kurdish -> Kurdish */
+ {HB_TAG('s','d','n',' '), HB_TAG('S','R','D',' ')}, /* Gallurese Sardinian -> Sardinian */
+ {HB_TAG('s','d','s',' '), HB_TAG('B','B','R',' ')}, /* Sened -> Berber */
+ {HB_TAG('s','e','h',' '), HB_TAG('S','N','A',' ')}, /* Sena */
+ {HB_TAG('s','e','k',' '), HB_TAG('A','T','H',' ')}, /* Sekani -> Athapaskan */
+/*{HB_TAG('s','e','l',' '), HB_TAG('S','E','L',' ')},*/ /* Selkup */
+ {HB_TAG('s','e','z',' '), HB_TAG('Q','I','N',' ')}, /* Senthang Chin -> Chin */
+ {HB_TAG('s','f','m',' '), HB_TAG('S','F','M',' ')}, /* Small Flowery Miao */
+ {HB_TAG('s','f','m',' '), HB_TAG('H','M','N',' ')}, /* Small Flowery Miao -> Hmong */
+/*{HB_TAG('s','g','a',' '), HB_TAG('S','G','A',' ')},*/ /* Old Irish (to 900) */
+ {HB_TAG('s','g','c',' '), HB_TAG('K','A','L',' ')}, /* Kipsigis -> Kalenjin */
+ {HB_TAG('s','g','o',' '), HB_TAG_NONE }, /* Songa (retired code) != Sango */
+/*{HB_TAG('s','g','s',' '), HB_TAG('S','G','S',' ')},*/ /* Samogitian */
+ {HB_TAG('s','g','w',' '), HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage -> Chaha Gurage */
+ {HB_TAG('s','h','i',' '), HB_TAG('S','H','I',' ')}, /* Tachelhit */
+ {HB_TAG('s','h','i',' '), HB_TAG('B','B','R',' ')}, /* Tachelhit -> Berber */
+ {HB_TAG('s','h','l',' '), HB_TAG('Q','I','N',' ')}, /* Shendu -> Chin */
+/*{HB_TAG('s','h','n',' '), HB_TAG('S','H','N',' ')},*/ /* Shan */
+ {HB_TAG('s','h','u',' '), HB_TAG('A','R','A',' ')}, /* Chadian Arabic -> Arabic */
+ {HB_TAG('s','h','y',' '), HB_TAG('B','B','R',' ')}, /* Tachawit -> Berber */
+ {HB_TAG('s','i','b',' '), HB_TAG_NONE }, /* Sebop != Sibe */
+/*{HB_TAG('s','i','d',' '), HB_TAG('S','I','D',' ')},*/ /* Sidamo */
+ {HB_TAG('s','i','g',' '), HB_TAG_NONE }, /* Paasaal != Silte Gurage */
+ {HB_TAG('s','i','z',' '), HB_TAG('B','B','R',' ')}, /* Siwi -> Berber */
+ {HB_TAG('s','j','d',' '), HB_TAG('K','S','M',' ')}, /* Kildin Sami */
+ {HB_TAG('s','j','o',' '), HB_TAG('S','I','B',' ')}, /* Xibe -> Sibe */
+ {HB_TAG('s','j','s',' '), HB_TAG('B','B','R',' ')}, /* Senhaja De Srair -> Berber */
+ {HB_TAG('s','k','g',' '), HB_TAG('M','L','G',' ')}, /* Sakalava Malagasy -> Malagasy */
+ {HB_TAG('s','k','r',' '), HB_TAG('S','R','K',' ')}, /* Saraiki */
+ {HB_TAG('s','k','s',' '), HB_TAG_NONE }, /* Maia != Skolt Sami */
+ {HB_TAG('s','k','w',' '), HB_TAG('C','P','P',' ')}, /* Skepi Creole Dutch -> Creoles */
+ {HB_TAG('s','k','y',' '), HB_TAG_NONE }, /* Sikaiana != Slovak */
+ {HB_TAG('s','l','a',' '), HB_TAG_NONE }, /* Slavic [collection] != Slavey */
+ {HB_TAG('s','m','a',' '), HB_TAG('S','S','M',' ')}, /* Southern Sami */
+ {HB_TAG('s','m','d',' '), HB_TAG('M','B','N',' ')}, /* Sama (retired code) -> Mbundu */
+ {HB_TAG('s','m','j',' '), HB_TAG('L','S','M',' ')}, /* Lule Sami */
+ {HB_TAG('s','m','l',' '), HB_TAG_NONE }, /* Central Sama != Somali */
+ {HB_TAG('s','m','n',' '), HB_TAG('I','S','M',' ')}, /* Inari Sami */
+ {HB_TAG('s','m','s',' '), HB_TAG('S','K','S',' ')}, /* Skolt Sami */
+ {HB_TAG('s','m','t',' '), HB_TAG('Q','I','N',' ')}, /* Simte -> Chin */
+ {HB_TAG('s','n','b',' '), HB_TAG('I','B','A',' ')}, /* Sebuyau (retired code) -> Iban */
+ {HB_TAG('s','n','h',' '), HB_TAG_NONE }, /* Shinabo (retired code) != Sinhala (Sinhalese) */
+/*{HB_TAG('s','n','k',' '), HB_TAG('S','N','K',' ')},*/ /* Soninke */
+ {HB_TAG('s','o','g',' '), HB_TAG_NONE }, /* Sogdian != Sodo Gurage */
+/*{HB_TAG('s','o','p',' '), HB_TAG('S','O','P',' ')},*/ /* Songe */
+ {HB_TAG('s','p','v',' '), HB_TAG('O','R','I',' ')}, /* Sambalpuri -> Odia (formerly Oriya) */
+ {HB_TAG('s','p','y',' '), HB_TAG('K','A','L',' ')}, /* Sabaot -> Kalenjin */
+ {HB_TAG('s','r','b',' '), HB_TAG_NONE }, /* Sora != Serbian */
+ {HB_TAG('s','r','c',' '), HB_TAG('S','R','D',' ')}, /* Logudorese Sardinian -> Sardinian */
+ {HB_TAG('s','r','k',' '), HB_TAG_NONE }, /* Serudung Murut != Saraiki */
+ {HB_TAG('s','r','m',' '), HB_TAG('C','P','P',' ')}, /* Saramaccan -> Creoles */
+ {HB_TAG('s','r','n',' '), HB_TAG('C','P','P',' ')}, /* Sranan Tongo -> Creoles */
+ {HB_TAG('s','r','o',' '), HB_TAG('S','R','D',' ')}, /* Campidanese Sardinian -> Sardinian */
+/*{HB_TAG('s','r','r',' '), HB_TAG('S','R','R',' ')},*/ /* Serer */
+ {HB_TAG('s','r','s',' '), HB_TAG('A','T','H',' ')}, /* Sarsi -> Athapaskan */
+ {HB_TAG('s','s','h',' '), HB_TAG('A','R','A',' ')}, /* Shihhi Arabic -> Arabic */
+ {HB_TAG('s','s','l',' '), HB_TAG_NONE }, /* Western Sisaala != South Slavey */
+ {HB_TAG('s','s','m',' '), HB_TAG_NONE }, /* Semnam != Southern Sami */
+ {HB_TAG('s','t','a',' '), HB_TAG('C','P','P',' ')}, /* Settla -> Creoles */
+/*{HB_TAG('s','t','q',' '), HB_TAG('S','T','Q',' ')},*/ /* Saterfriesisch -> Saterland Frisian */
+ {HB_TAG('s','t','v',' '), HB_TAG('S','I','G',' ')}, /* Silt'e -> Silte Gurage */
+/*{HB_TAG('s','u','k',' '), HB_TAG('S','U','K',' ')},*/ /* Sukuma */
+ {HB_TAG('s','u','q',' '), HB_TAG('S','U','R',' ')}, /* Suri */
+ {HB_TAG('s','u','r',' '), HB_TAG_NONE }, /* Mwaghavul != Suri */
+/*{HB_TAG('s','v','a',' '), HB_TAG('S','V','A',' ')},*/ /* Svan */
+ {HB_TAG('s','v','c',' '), HB_TAG('C','P','P',' ')}, /* Vincentian Creole English -> Creoles */
+ {HB_TAG('s','v','e',' '), HB_TAG_NONE }, /* Serili != Swedish */
+ {HB_TAG('s','w','b',' '), HB_TAG('C','M','R',' ')}, /* Maore Comorian -> Comorian */
+ {HB_TAG('s','w','c',' '), HB_TAG('S','W','K',' ')}, /* Congo Swahili -> Swahili */
+ {HB_TAG('s','w','h',' '), HB_TAG('S','W','K',' ')}, /* Swahili */
+ {HB_TAG('s','w','k',' '), HB_TAG_NONE }, /* Malawi Sena != Swahili */
+ {HB_TAG('s','w','n',' '), HB_TAG('B','B','R',' ')}, /* Sawknah -> Berber */
+ {HB_TAG('s','w','v',' '), HB_TAG('M','A','W',' ')}, /* Shekhawati -> Marwari */
+/*{HB_TAG('s','x','u',' '), HB_TAG('S','X','U',' ')},*/ /* Upper Saxon */
+ {HB_TAG('s','y','c',' '), HB_TAG('S','Y','R',' ')}, /* Classical Syriac -> Syriac */
+/*{HB_TAG('s','y','l',' '), HB_TAG('S','Y','L',' ')},*/ /* Sylheti */
+/*{HB_TAG('s','y','r',' '), HB_TAG('S','Y','R',' ')},*/ /* Syriac [macrolanguage] */
+/*{HB_TAG('s','z','l',' '), HB_TAG('S','Z','L',' ')},*/ /* Silesian */
+ {HB_TAG('t','a','a',' '), HB_TAG('A','T','H',' ')}, /* Lower Tanana -> Athapaskan */
+/*{HB_TAG('t','a','b',' '), HB_TAG('T','A','B',' ')},*/ /* Tabassaran -> Tabasaran */
+ {HB_TAG('t','a','j',' '), HB_TAG_NONE }, /* Eastern Tamang != Tajiki */
+ {HB_TAG('t','a','q',' '), HB_TAG('T','M','H',' ')}, /* Tamasheq -> Tamashek */
+ {HB_TAG('t','a','q',' '), HB_TAG('B','B','R',' ')}, /* Tamasheq -> Berber */
+ {HB_TAG('t','a','s',' '), HB_TAG('C','P','P',' ')}, /* Tay Boi -> Creoles */
+ {HB_TAG('t','a','u',' '), HB_TAG('A','T','H',' ')}, /* Upper Tanana -> Athapaskan */
+ {HB_TAG('t','c','b',' '), HB_TAG('A','T','H',' ')}, /* Tanacross -> Athapaskan */
+ {HB_TAG('t','c','e',' '), HB_TAG('A','T','H',' ')}, /* Southern Tutchone -> Athapaskan */
+ {HB_TAG('t','c','h',' '), HB_TAG('C','P','P',' ')}, /* Turks And Caicos Creole English -> Creoles */
+ {HB_TAG('t','c','p',' '), HB_TAG('Q','I','N',' ')}, /* Tawr Chin -> Chin */
+ {HB_TAG('t','c','s',' '), HB_TAG('C','P','P',' ')}, /* Torres Strait Creole -> Creoles */
+ {HB_TAG('t','c','y',' '), HB_TAG('T','U','L',' ')}, /* Tulu -> Tumbuka */
+ {HB_TAG('t','c','z',' '), HB_TAG('Q','I','N',' ')}, /* Thado Chin -> Chin */
+/*{HB_TAG('t','d','d',' '), HB_TAG('T','D','D',' ')},*/ /* Tai Nüa -> Dehong Dai */
+ {HB_TAG('t','d','x',' '), HB_TAG('M','L','G',' ')}, /* Tandroy-Mahafaly Malagasy -> Malagasy */
+ {HB_TAG('t','e','c',' '), HB_TAG('K','A','L',' ')}, /* Terik -> Kalenjin */
+ {HB_TAG('t','e','m',' '), HB_TAG('T','M','N',' ')}, /* Timne -> Temne */
+/*{HB_TAG('t','e','t',' '), HB_TAG('T','E','T',' ')},*/ /* Tetum */
+ {HB_TAG('t','e','z',' '), HB_TAG('B','B','R',' ')}, /* Tetserret -> Berber */
+ {HB_TAG('t','f','n',' '), HB_TAG('A','T','H',' ')}, /* Tanaina -> Athapaskan */
+ {HB_TAG('t','g','h',' '), HB_TAG('C','P','P',' ')}, /* Tobagonian Creole English -> Creoles */
+ {HB_TAG('t','g','j',' '), HB_TAG('N','I','S',' ')}, /* Tagin -> Nisi */
+ {HB_TAG('t','g','n',' '), HB_TAG_NONE }, /* Tandaganon != Tongan */
+ {HB_TAG('t','g','r',' '), HB_TAG_NONE }, /* Tareng != Tigre */
+ {HB_TAG('t','g','x',' '), HB_TAG('A','T','H',' ')}, /* Tagish -> Athapaskan */
+ {HB_TAG('t','g','y',' '), HB_TAG_NONE }, /* Togoyo != Tigrinya */
+ {HB_TAG('t','h','t',' '), HB_TAG('A','T','H',' ')}, /* Tahltan -> Athapaskan */
+ {HB_TAG('t','h','v',' '), HB_TAG('T','M','H',' ')}, /* Tahaggart Tamahaq -> Tamashek */
+ {HB_TAG('t','h','v',' '), HB_TAG('B','B','R',' ')}, /* Tahaggart Tamahaq -> Berber */
+ {HB_TAG('t','h','z',' '), HB_TAG('T','M','H',' ')}, /* Tayart Tamajeq -> Tamashek */
+ {HB_TAG('t','h','z',' '), HB_TAG('B','B','R',' ')}, /* Tayart Tamajeq -> Berber */
+ {HB_TAG('t','i','a',' '), HB_TAG('B','B','R',' ')}, /* Tidikelt Tamazight -> Berber */
+ {HB_TAG('t','i','g',' '), HB_TAG('T','G','R',' ')}, /* Tigre */
+/*{HB_TAG('t','i','v',' '), HB_TAG('T','I','V',' ')},*/ /* Tiv */
+/*{HB_TAG('t','j','l',' '), HB_TAG('T','J','L',' ')},*/ /* Tai Laing */
+ {HB_TAG('t','j','o',' '), HB_TAG('B','B','R',' ')}, /* Temacine Tamazight -> Berber */
+ {HB_TAG('t','k','g',' '), HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */
+ {HB_TAG('t','k','m',' '), HB_TAG_NONE }, /* Takelma != Turkmen */
+/*{HB_TAG('t','l','i',' '), HB_TAG('T','L','I',' ')},*/ /* Tlingit */
+ {HB_TAG('t','m','g',' '), HB_TAG('C','P','P',' ')}, /* Ternateño -> Creoles */
+ {HB_TAG('t','m','h',' '), HB_TAG('T','M','H',' ')}, /* Tamashek [macrolanguage] */
+ {HB_TAG('t','m','h',' '), HB_TAG('B','B','R',' ')}, /* Tamashek [macrolanguage] -> Berber */
+ {HB_TAG('t','m','n',' '), HB_TAG_NONE }, /* Taman (Indonesia) != Temne */
+ {HB_TAG('t','m','w',' '), HB_TAG('M','L','Y',' ')}, /* Temuan -> Malay */
+ {HB_TAG('t','n','a',' '), HB_TAG_NONE }, /* Tacana != Tswana */
+ {HB_TAG('t','n','e',' '), HB_TAG_NONE }, /* Tinoc Kallahan (retired code) != Tundra Enets */
+ {HB_TAG('t','n','f',' '), HB_TAG('D','R','I',' ')}, /* Tangshewi (retired code) -> Dari */
+ {HB_TAG('t','n','f',' '), HB_TAG('F','A','R',' ')}, /* Tangshewi (retired code) -> Persian */
+ {HB_TAG('t','n','g',' '), HB_TAG_NONE }, /* Tobanga != Tonga */
+ {HB_TAG('t','o','d',' '), HB_TAG('T','O','D','0')}, /* Toma */
+ {HB_TAG('t','o','i',' '), HB_TAG('T','N','G',' ')}, /* Tonga (Zambia) */
+ {HB_TAG('t','o','j',' '), HB_TAG('M','Y','N',' ')}, /* Tojolabal -> Mayan */
+ {HB_TAG('t','o','l',' '), HB_TAG('A','T','H',' ')}, /* Tolowa -> Athapaskan */
+ {HB_TAG('t','o','r',' '), HB_TAG('B','A','D','0')}, /* Togbo-Vara Banda -> Banda */
+ {HB_TAG('t','p','i',' '), HB_TAG('T','P','I',' ')}, /* Tok Pisin */
+ {HB_TAG('t','p','i',' '), HB_TAG('C','P','P',' ')}, /* Tok Pisin -> Creoles */
+ {HB_TAG('t','r','f',' '), HB_TAG('C','P','P',' ')}, /* Trinidadian Creole English -> Creoles */
+ {HB_TAG('t','r','k',' '), HB_TAG_NONE }, /* Turkic [collection] != Turkish */
+ {HB_TAG('t','r','u',' '), HB_TAG('T','U','A',' ')}, /* Turoyo -> Turoyo Aramaic */
+ {HB_TAG('t','r','u',' '), HB_TAG('S','Y','R',' ')}, /* Turoyo -> Syriac */
+ {HB_TAG('t','s','g',' '), HB_TAG_NONE }, /* Tausug != Tsonga */
+/*{HB_TAG('t','s','j',' '), HB_TAG('T','S','J',' ')},*/ /* Tshangla */
+ {HB_TAG('t','t','c',' '), HB_TAG('M','Y','N',' ')}, /* Tektiteko -> Mayan */
+ {HB_TAG('t','t','m',' '), HB_TAG('A','T','H',' ')}, /* Northern Tutchone -> Athapaskan */
+ {HB_TAG('t','t','q',' '), HB_TAG('T','M','H',' ')}, /* Tawallammat Tamajaq -> Tamashek */
+ {HB_TAG('t','t','q',' '), HB_TAG('B','B','R',' ')}, /* Tawallammat Tamajaq -> Berber */
+ {HB_TAG('t','u','a',' '), HB_TAG_NONE }, /* Wiarumus != Turoyo Aramaic */
+ {HB_TAG('t','u','l',' '), HB_TAG_NONE }, /* Tula != Tumbuka */
+/*{HB_TAG('t','u','m',' '), HB_TAG('T','U','M',' ')},*/ /* Tumbuka -> Tulu */
+ {HB_TAG('t','u','u',' '), HB_TAG('A','T','H',' ')}, /* Tututni -> Athapaskan */
+ {HB_TAG('t','u','v',' '), HB_TAG_NONE }, /* Turkana != Tuvin */
+ {HB_TAG('t','u','y',' '), HB_TAG('K','A','L',' ')}, /* Tugen -> Kalenjin */
+/*{HB_TAG('t','v','l',' '), HB_TAG('T','V','L',' ')},*/ /* Tuvalu */
+ {HB_TAG('t','v','y',' '), HB_TAG('C','P','P',' ')}, /* Timor Pidgin -> Creoles */
+ {HB_TAG('t','x','c',' '), HB_TAG('A','T','H',' ')}, /* Tsetsaut -> Athapaskan */
+ {HB_TAG('t','x','y',' '), HB_TAG('M','L','G',' ')}, /* Tanosy Malagasy -> Malagasy */
+ {HB_TAG('t','y','v',' '), HB_TAG('T','U','V',' ')}, /* Tuvinian -> Tuvin */
+/*{HB_TAG('t','y','z',' '), HB_TAG('T','Y','Z',' ')},*/ /* Tày */
+ {HB_TAG('t','z','h',' '), HB_TAG('M','Y','N',' ')}, /* Tzeltal -> Mayan */
+ {HB_TAG('t','z','j',' '), HB_TAG('M','Y','N',' ')}, /* Tz'utujil -> Mayan */
+ {HB_TAG('t','z','m',' '), HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight -> Tamazight */
+ {HB_TAG('t','z','m',' '), HB_TAG('B','B','R',' ')}, /* Central Atlas Tamazight -> Berber */
+ {HB_TAG('t','z','o',' '), HB_TAG('T','Z','O',' ')}, /* Tzotzil */
+ {HB_TAG('t','z','o',' '), HB_TAG('M','Y','N',' ')}, /* Tzotzil -> Mayan */
+ {HB_TAG('u','b','l',' '), HB_TAG('B','I','K',' ')}, /* Buhi'non Bikol -> Bikol */
+/*{HB_TAG('u','d','m',' '), HB_TAG('U','D','M',' ')},*/ /* Udmurt */
+ {HB_TAG('u','k','i',' '), HB_TAG('K','U','I',' ')}, /* Kui (India) */
+ {HB_TAG('u','l','n',' '), HB_TAG('C','P','P',' ')}, /* Unserdeutsch -> Creoles */
+/*{HB_TAG('u','m','b',' '), HB_TAG('U','M','B',' ')},*/ /* Umbundu */
+ {HB_TAG('u','n','r',' '), HB_TAG('M','U','N',' ')}, /* Mundari */
+ {HB_TAG('u','r','k',' '), HB_TAG('M','L','Y',' ')}, /* Urak Lawoi' -> Malay */
+ {HB_TAG('u','s','p',' '), HB_TAG('M','Y','N',' ')}, /* Uspanteco -> Mayan */
+ {HB_TAG('u','z','n',' '), HB_TAG('U','Z','B',' ')}, /* Northern Uzbek -> Uzbek */
+ {HB_TAG('u','z','s',' '), HB_TAG('U','Z','B',' ')}, /* Southern Uzbek -> Uzbek */
+ {HB_TAG('v','a','p',' '), HB_TAG('Q','I','N',' ')}, /* Vaiphei -> Chin */
+/*{HB_TAG('v','e','c',' '), HB_TAG('V','E','C',' ')},*/ /* Venetian */
+ {HB_TAG('v','i','c',' '), HB_TAG('C','P','P',' ')}, /* Virgin Islands Creole English -> Creoles */
+ {HB_TAG('v','i','t',' '), HB_TAG_NONE }, /* Viti != Vietnamese */
+ {HB_TAG('v','k','k',' '), HB_TAG('M','L','Y',' ')}, /* Kaur -> Malay */
+ {HB_TAG('v','k','p',' '), HB_TAG('C','P','P',' ')}, /* Korlai Creole Portuguese -> Creoles */
+ {HB_TAG('v','k','t',' '), HB_TAG('M','L','Y',' ')}, /* Tenggarong Kutai Malay -> Malay */
+ {HB_TAG('v','l','s',' '), HB_TAG('F','L','E',' ')}, /* Vlaams -> Dutch (Flemish) */
+ {HB_TAG('v','m','w',' '), HB_TAG('M','A','K',' ')}, /* Makhuwa */
+/*{HB_TAG('v','r','o',' '), HB_TAG('V','R','O',' ')},*/ /* Võro */
+ {HB_TAG('w','a','g',' '), HB_TAG_NONE }, /* Wa'ema != Wagdi */
+/*{HB_TAG('w','a','r',' '), HB_TAG('W','A','R',' ')},*/ /* Waray (Philippines) -> Waray-Waray */
+ {HB_TAG('w','b','m',' '), HB_TAG('W','A',' ',' ')}, /* Wa */
+ {HB_TAG('w','b','r',' '), HB_TAG('W','A','G',' ')}, /* Wagdi */
+ {HB_TAG('w','b','r',' '), HB_TAG('R','A','J',' ')}, /* Wagdi -> Rajasthani */
+/*{HB_TAG('w','c','i',' '), HB_TAG('W','C','I',' ')},*/ /* Waci Gbe */
+ {HB_TAG('w','e','a',' '), HB_TAG('K','R','N',' ')}, /* Wewaw -> Karen */
+ {HB_TAG('w','e','s',' '), HB_TAG('C','P','P',' ')}, /* Cameroon Pidgin -> Creoles */
+ {HB_TAG('w','e','u',' '), HB_TAG('Q','I','N',' ')}, /* Rawngtu Chin -> Chin */
+ {HB_TAG('w','l','c',' '), HB_TAG('C','M','R',' ')}, /* Mwali Comorian -> Comorian */
+ {HB_TAG('w','l','e',' '), HB_TAG('S','I','G',' ')}, /* Wolane -> Silte Gurage */
+ {HB_TAG('w','l','k',' '), HB_TAG('A','T','H',' ')}, /* Wailaki -> Athapaskan */
+ {HB_TAG('w','n','i',' '), HB_TAG('C','M','R',' ')}, /* Ndzwani Comorian -> Comorian */
+ {HB_TAG('w','r','y',' '), HB_TAG('M','A','W',' ')}, /* Merwari -> Marwari */
+ {HB_TAG('w','s','g',' '), HB_TAG('G','O','N',' ')}, /* Adilabad Gondi -> Gondi */
+/*{HB_TAG('w','t','m',' '), HB_TAG('W','T','M',' ')},*/ /* Mewati */
+ {HB_TAG('w','u','u',' '), HB_TAG('Z','H','S',' ')}, /* Wu Chinese -> Chinese, Simplified */
+ {HB_TAG('x','a','l',' '), HB_TAG('K','L','M',' ')}, /* Kalmyk */
+ {HB_TAG('x','a','l',' '), HB_TAG('T','O','D',' ')}, /* Kalmyk -> Todo */
+ {HB_TAG('x','a','n',' '), HB_TAG('S','E','K',' ')}, /* Xamtanga -> Sekota */
+ {HB_TAG('x','b','d',' '), HB_TAG_NONE }, /* Bindal != Lü */
+/*{HB_TAG('x','j','b',' '), HB_TAG('X','J','B',' ')},*/ /* Minjungbal -> Minjangbal */
+/*{HB_TAG('x','k','f',' '), HB_TAG('X','K','F',' ')},*/ /* Khengkha */
+ {HB_TAG('x','m','g',' '), HB_TAG('B','M','L',' ')}, /* Mengaka -> Bamileke */
+ {HB_TAG('x','m','m',' '), HB_TAG('M','L','Y',' ')}, /* Manado Malay -> Malay */
+ {HB_TAG('x','m','m',' '), HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */
+ {HB_TAG('x','m','v',' '), HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */
+ {HB_TAG('x','m','w',' '), HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */
+ {HB_TAG('x','n','j',' '), HB_TAG('S','X','T',' ')}, /* Ngoni (Tanzania) -> Sutu */
+ {HB_TAG('x','n','q',' '), HB_TAG('S','X','T',' ')}, /* Ngoni (Mozambique) -> Sutu */
+ {HB_TAG('x','n','r',' '), HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */
+/*{HB_TAG('x','o','g',' '), HB_TAG('X','O','G',' ')},*/ /* Soga */
+ {HB_TAG('x','p','e',' '), HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */
+ {HB_TAG('x','p','e',' '), HB_TAG('K','P','L',' ')}, /* Liberia Kpelle -> Kpelle */
+ {HB_TAG('x','s','l',' '), HB_TAG('S','S','L',' ')}, /* South Slavey */
+ {HB_TAG('x','s','l',' '), HB_TAG('S','L','A',' ')}, /* South Slavey -> Slavey */
+ {HB_TAG('x','s','l',' '), HB_TAG('A','T','H',' ')}, /* South Slavey -> Athapaskan */
+ {HB_TAG('x','s','t',' '), HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) -> Silte Gurage */
+/*{HB_TAG('x','u','b',' '), HB_TAG('X','U','B',' ')},*/ /* Betta Kurumba -> Bette Kuruma */
+/*{HB_TAG('x','u','j',' '), HB_TAG('X','U','J',' ')},*/ /* Jennu Kurumba -> Jennu Kuruma */
+ {HB_TAG('x','u','p',' '), HB_TAG('A','T','H',' ')}, /* Upper Umpqua -> Athapaskan */
+ {HB_TAG('x','w','o',' '), HB_TAG('T','O','D',' ')}, /* Written Oirat -> Todo */
+ {HB_TAG('y','a','j',' '), HB_TAG('B','A','D','0')}, /* Banda-Yangere -> Banda */
+ {HB_TAG('y','a','k',' '), HB_TAG_NONE }, /* Yakama != Sakha */
+/*{HB_TAG('y','a','o',' '), HB_TAG('Y','A','O',' ')},*/ /* Yao */
+/*{HB_TAG('y','a','p',' '), HB_TAG('Y','A','P',' ')},*/ /* Yapese */
+ {HB_TAG('y','b','a',' '), HB_TAG_NONE }, /* Yala != Yoruba */
+ {HB_TAG('y','b','b',' '), HB_TAG('B','M','L',' ')}, /* Yemba -> Bamileke */
+ {HB_TAG('y','b','d',' '), HB_TAG('A','R','K',' ')}, /* Yangbye (retired code) -> Rakhine */
+ {HB_TAG('y','d','d',' '), HB_TAG('J','I','I',' ')}, /* Eastern Yiddish -> Yiddish */
+/*{HB_TAG('y','g','p',' '), HB_TAG('Y','G','P',' ')},*/ /* Gepo */
+ {HB_TAG('y','i','h',' '), HB_TAG('J','I','I',' ')}, /* Western Yiddish -> Yiddish */
+ {HB_TAG('y','i','m',' '), HB_TAG_NONE }, /* Yimchungru Naga != Yi Modern */
+/*{HB_TAG('y','n','a',' '), HB_TAG('Y','N','A',' ')},*/ /* Aluo */
+ {HB_TAG('y','o','s',' '), HB_TAG('Q','I','N',' ')}, /* Yos (retired code) -> Chin */
+ {HB_TAG('y','u','a',' '), HB_TAG('M','Y','N',' ')}, /* Yucateco -> Mayan */
+ {HB_TAG('y','u','e',' '), HB_TAG('Z','H','H',' ')}, /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */
+/*{HB_TAG('y','w','q',' '), HB_TAG('Y','W','Q',' ')},*/ /* Wuding-Luquan Yi */
+ {HB_TAG('z','c','h',' '), HB_TAG('Z','H','A',' ')}, /* Central Hongshuihe Zhuang -> Zhuang */
+ {HB_TAG('z','d','j',' '), HB_TAG('C','M','R',' ')}, /* Ngazidja Comorian -> Comorian */
+/*{HB_TAG('z','e','a',' '), HB_TAG('Z','E','A',' ')},*/ /* Zeeuws -> Zealandic */
+ {HB_TAG('z','e','h',' '), HB_TAG('Z','H','A',' ')}, /* Eastern Hongshuihe Zhuang -> Zhuang */
+ {HB_TAG('z','e','n',' '), HB_TAG('B','B','R',' ')}, /* Zenaga -> Berber */
+ {HB_TAG('z','g','b',' '), HB_TAG('Z','H','A',' ')}, /* Guibei Zhuang -> Zhuang */
+ {HB_TAG('z','g','h',' '), HB_TAG('Z','G','H',' ')}, /* Standard Moroccan Tamazight */
+ {HB_TAG('z','g','h',' '), HB_TAG('B','B','R',' ')}, /* Standard Moroccan Tamazight -> Berber */
+ {HB_TAG('z','g','m',' '), HB_TAG('Z','H','A',' ')}, /* Minz Zhuang -> Zhuang */
+ {HB_TAG('z','g','n',' '), HB_TAG('Z','H','A',' ')}, /* Guibian Zhuang -> Zhuang */
+ {HB_TAG('z','h','d',' '), HB_TAG('Z','H','A',' ')}, /* Dai Zhuang -> Zhuang */
+ {HB_TAG('z','h','n',' '), HB_TAG('Z','H','A',' ')}, /* Nong Zhuang -> Zhuang */
+ {HB_TAG('z','l','j',' '), HB_TAG('Z','H','A',' ')}, /* Liujiang Zhuang -> Zhuang */
+ {HB_TAG('z','l','m',' '), HB_TAG('M','L','Y',' ')}, /* Malay */
+ {HB_TAG('z','l','n',' '), HB_TAG('Z','H','A',' ')}, /* Lianshan Zhuang -> Zhuang */
+ {HB_TAG('z','l','q',' '), HB_TAG('Z','H','A',' ')}, /* Liuqian Zhuang -> Zhuang */
+ {HB_TAG('z','m','i',' '), HB_TAG('M','L','Y',' ')}, /* Negeri Sembilan Malay -> Malay */
+ {HB_TAG('z','m','z',' '), HB_TAG('B','A','D','0')}, /* Mbandja -> Banda */
+ {HB_TAG('z','n','d',' '), HB_TAG_NONE }, /* Zande [collection] != Zande */
+ {HB_TAG('z','n','e',' '), HB_TAG('Z','N','D',' ')}, /* Zande */
+ {HB_TAG('z','o','m',' '), HB_TAG('Q','I','N',' ')}, /* Zou -> Chin */
+ {HB_TAG('z','q','e',' '), HB_TAG('Z','H','A',' ')}, /* Qiubei Zhuang -> Zhuang */
+ {HB_TAG('z','s','m',' '), HB_TAG('M','L','Y',' ')}, /* Standard Malay -> Malay */
+ {HB_TAG('z','u','m',' '), HB_TAG('L','R','C',' ')}, /* Kumzari -> Luri */
+ {HB_TAG('z','y','b',' '), HB_TAG('Z','H','A',' ')}, /* Yongbei Zhuang -> Zhuang */
+ {HB_TAG('z','y','g',' '), HB_TAG('Z','H','A',' ')}, /* Yang Zhuang -> Zhuang */
+ {HB_TAG('z','y','j',' '), HB_TAG('Z','H','A',' ')}, /* Youjiang Zhuang -> Zhuang */
+ {HB_TAG('z','y','n',' '), HB_TAG('Z','H','A',' ')}, /* Yongnan Zhuang -> Zhuang */
+ {HB_TAG('z','y','p',' '), HB_TAG('Q','I','N',' ')}, /* Zyphe Chin -> Chin */
+/*{HB_TAG('z','z','a',' '), HB_TAG('Z','Z','A',' ')},*/ /* Zazaki [macrolanguage] */
+ {HB_TAG('z','z','j',' '), HB_TAG('Z','H','A',' ')}, /* Zuojiang Zhuang -> Zhuang */
+};
+#endif
+
/**
* hb_ot_tags_from_complex_language:
* @lang_str: a BCP 47 language tag to convert.
@@ -1633,75 +1638,81 @@ static const LangTag ot_languages[] = {
*
* Return value: Whether any language systems were retrieved.
**/
-static bool
+static inline bool
hb_ot_tags_from_complex_language (const char *lang_str,
const char *limit,
unsigned int *count /* IN/OUT */,
hb_tag_t *tags /* OUT */)
{
- if (subtag_matches (lang_str, limit, "-fonnapa"))
- {
- /* Undetermined; North American Phonetic Alphabet */
- tags[0] = HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-polyton"))
- {
- /* Modern Greek (1453-); Polytonic Greek */
- tags[0] = HB_TAG('P','G','R',' '); /* Polytonic Greek */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-arevmda"))
- {
- /* Armenian; Western Armenian (retired code) */
- tags[0] = HB_TAG('H','Y','E',' '); /* Armenian */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-provenc"))
- {
- /* Occitan (post 1500); Provençal */
- tags[0] = HB_TAG('P','R','O',' '); /* Provençal / Old Provençal */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-fonipa"))
- {
- /* Undetermined; International Phonetic Alphabet */
- tags[0] = HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-geok"))
- {
- /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
- tags[0] = HB_TAG('K','G','E',' '); /* Khutsuri Georgian */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-syre"))
+ if (limit - lang_str >= 7)
{
- /* Undetermined; Syriac (Estrangelo variant) */
- tags[0] = HB_TAG('S','Y','R','E'); /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-syrj"))
- {
- /* Undetermined; Syriac (Western variant) */
- tags[0] = HB_TAG('S','Y','R','J'); /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-syrn"))
- {
- /* Undetermined; Syriac (Eastern variant) */
- tags[0] = HB_TAG('S','Y','R','N'); /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
- *count = 1;
- return true;
+ const char *p = strchr (lang_str, '-');
+ if (!p || p >= limit || limit - p < 5) goto out;
+ if (subtag_matches (p, limit, "-fonnapa", 8))
+ {
+ /* Undetermined; North American Phonetic Alphabet */
+ tags[0] = HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-polyton", 8))
+ {
+ /* Modern Greek (1453-); Polytonic Greek */
+ tags[0] = HB_TAG('P','G','R',' '); /* Polytonic Greek */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-arevmda", 8))
+ {
+ /* Armenian; Western Armenian (retired code) */
+ tags[0] = HB_TAG('H','Y','E',' '); /* Armenian */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-provenc", 8))
+ {
+ /* Occitan (post 1500); Provençal */
+ tags[0] = HB_TAG('P','R','O',' '); /* Provençal / Old Provençal */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-fonipa", 7))
+ {
+ /* Undetermined; International Phonetic Alphabet */
+ tags[0] = HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-geok", 5))
+ {
+ /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+ tags[0] = HB_TAG('K','G','E',' '); /* Khutsuri Georgian */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-syre", 5))
+ {
+ /* Undetermined; Syriac (Estrangelo variant) */
+ tags[0] = HB_TAG('S','Y','R','E'); /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-syrj", 5))
+ {
+ /* Undetermined; Syriac (Western variant) */
+ tags[0] = HB_TAG('S','Y','R','J'); /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-syrn", 5))
+ {
+ /* Undetermined; Syriac (Eastern variant) */
+ tags[0] = HB_TAG('S','Y','R','N'); /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
+ *count = 1;
+ return true;
+ }
}
+out:
switch (lang_str[0])
{
case 'a':
@@ -1714,14 +1725,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'c':
- if (lang_matches (&lang_str[1], "do-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "do-hant-hk", 10))
{
/* Min Dong Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "do-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "do-hant-mo", 10))
{
/* Min Dong Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1734,14 +1745,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "jy-hant-hk", 10))
{
/* Jinyu Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "jy-hant-mo", 10))
{
/* Jinyu Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1754,14 +1765,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "mn-hant-hk", 10))
{
/* Mandarin Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "mn-hant-mo", 10))
{
/* Mandarin Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1774,14 +1785,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-hk", 10))
{
/* Northern Ping Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-mo", 10))
{
/* Northern Ping Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1794,14 +1805,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "px-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "px-hant-hk", 10))
{
/* Pu-Xian Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "px-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "px-hant-mo", 10))
{
/* Pu-Xian Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1814,14 +1825,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "sp-hant-hk", 10))
{
/* Southern Ping Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "sp-hant-mo", 10))
{
/* Southern Ping Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1834,14 +1845,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "zh-hant-hk", 10))
{
/* Huizhou Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "zh-hant-mo", 10))
{
/* Huizhou Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1854,14 +1865,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "zo-hant-hk", 10))
{
/* Min Zhong Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "zo-hant-mo", 10))
{
/* Min Zhong Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1874,112 +1885,112 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "do-hans"))
+ if (lang_matches (&lang_str[1], limit, "do-hans", 7))
{
/* Min Dong Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "do-hant"))
+ if (lang_matches (&lang_str[1], limit, "do-hant", 7))
{
/* Min Dong Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hans"))
+ if (lang_matches (&lang_str[1], limit, "jy-hans", 7))
{
/* Jinyu Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hant"))
+ if (lang_matches (&lang_str[1], limit, "jy-hant", 7))
{
/* Jinyu Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hans"))
+ if (lang_matches (&lang_str[1], limit, "mn-hans", 7))
{
/* Mandarin Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hant"))
+ if (lang_matches (&lang_str[1], limit, "mn-hant", 7))
{
/* Mandarin Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hans"))
+ if (lang_matches (&lang_str[1], limit, "np-hans", 7))
{
/* Northern Ping Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant"))
+ if (lang_matches (&lang_str[1], limit, "np-hant", 7))
{
/* Northern Ping Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "px-hans"))
+ if (lang_matches (&lang_str[1], limit, "px-hans", 7))
{
/* Pu-Xian Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "px-hant"))
+ if (lang_matches (&lang_str[1], limit, "px-hant", 7))
{
/* Pu-Xian Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hans"))
+ if (lang_matches (&lang_str[1], limit, "sp-hans", 7))
{
/* Southern Ping Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hant"))
+ if (lang_matches (&lang_str[1], limit, "sp-hant", 7))
{
/* Southern Ping Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hans"))
+ if (lang_matches (&lang_str[1], limit, "zh-hans", 7))
{
/* Huizhou Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hant"))
+ if (lang_matches (&lang_str[1], limit, "zh-hant", 7))
{
/* Huizhou Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hans"))
+ if (lang_matches (&lang_str[1], limit, "zo-hans", 7))
{
/* Min Zhong Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hant"))
+ if (lang_matches (&lang_str[1], limit, "zo-hant", 7))
{
/* Min Zhong Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -1987,7 +1998,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "do-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Dong Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -1995,7 +2006,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "do-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Dong Chinese; Macao */
unsigned int i;
@@ -2009,7 +2020,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "do-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Dong Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2017,7 +2028,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "jy-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Jinyu Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2025,7 +2036,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "jy-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Jinyu Chinese; Macao */
unsigned int i;
@@ -2039,7 +2050,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "jy-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Jinyu Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2047,7 +2058,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "mn-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Mandarin Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2055,7 +2066,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "mn-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Mandarin Chinese; Macao */
unsigned int i;
@@ -2069,7 +2080,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "mn-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Mandarin Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2077,7 +2088,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Northern Ping Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2085,7 +2096,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Northern Ping Chinese; Macao */
unsigned int i;
@@ -2099,7 +2110,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Northern Ping Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2107,7 +2118,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "px-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Pu-Xian Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2115,7 +2126,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "px-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Pu-Xian Chinese; Macao */
unsigned int i;
@@ -2129,7 +2140,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "px-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Pu-Xian Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2137,7 +2148,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sp-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Southern Ping Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2145,7 +2156,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sp-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Southern Ping Chinese; Macao */
unsigned int i;
@@ -2159,7 +2170,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sp-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Southern Ping Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2167,7 +2178,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zh-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Huizhou Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2175,7 +2186,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zh-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Huizhou Chinese; Macao */
unsigned int i;
@@ -2189,7 +2200,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zh-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Huizhou Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2197,7 +2208,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zo-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Zhong Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2205,7 +2216,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zo-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Zhong Chinese; Macao */
unsigned int i;
@@ -2219,7 +2230,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zo-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Zhong Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2228,14 +2239,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'g':
- if (lang_matches (&lang_str[1], "an-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-hk", 10))
{
/* Gan Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-mo", 10))
{
/* Gan Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2248,21 +2259,21 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "an-hans"))
+ if (lang_matches (&lang_str[1], limit, "an-hans", 7))
{
/* Gan Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant"))
+ if (lang_matches (&lang_str[1], limit, "an-hant", 7))
{
/* Gan Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "a-latg"))
+ if (lang_matches (&lang_str[1], limit, "a-latg", 6))
{
/* Irish; Latin (Gaelic variant) */
tags[0] = HB_TAG('I','R','T',' '); /* Irish Traditional */
@@ -2270,7 +2281,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Gan Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2278,7 +2289,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Gan Chinese; Macao */
unsigned int i;
@@ -2292,7 +2303,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Gan Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2301,14 +2312,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'h':
- if (lang_matches (&lang_str[1], "ak-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "ak-hant-hk", 10))
{
/* Hakka Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "ak-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "ak-hant-mo", 10))
{
/* Hakka Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2321,14 +2332,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "sn-hant-hk", 10))
{
/* Xiang Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "sn-hant-mo", 10))
{
/* Xiang Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2341,28 +2352,28 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "ak-hans"))
+ if (lang_matches (&lang_str[1], limit, "ak-hans", 7))
{
/* Hakka Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "ak-hant"))
+ if (lang_matches (&lang_str[1], limit, "ak-hant", 7))
{
/* Hakka Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hans"))
+ if (lang_matches (&lang_str[1], limit, "sn-hans", 7))
{
/* Xiang Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hant"))
+ if (lang_matches (&lang_str[1], limit, "sn-hant", 7))
{
/* Xiang Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2370,7 +2381,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "ak-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Hakka Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2378,7 +2389,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "ak-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Hakka Chinese; Macao */
unsigned int i;
@@ -2392,7 +2403,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "ak-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Hakka Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2400,7 +2411,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sn-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Xiang Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2408,7 +2419,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sn-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Xiang Chinese; Macao */
unsigned int i;
@@ -2422,7 +2433,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sn-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Xiang Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2460,7 +2471,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'l':
- if (lang_matches (&lang_str[1], "zh-hans"))
+ if (lang_matches (&lang_str[1], limit, "zh-hans", 7))
{
/* Literary Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
@@ -2469,14 +2480,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'm':
- if (lang_matches (&lang_str[1], "np-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-hk", 10))
{
/* Min Bei Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-mo", 10))
{
/* Min Bei Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2489,14 +2500,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "np-hans"))
+ if (lang_matches (&lang_str[1], limit, "np-hans", 7))
{
/* Min Bei Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant"))
+ if (lang_matches (&lang_str[1], limit, "np-hant", 7))
{
/* Min Bei Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2504,7 +2515,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Bei Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2512,7 +2523,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Bei Chinese; Macao */
unsigned int i;
@@ -2526,7 +2537,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Bei Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2534,7 +2545,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "nw-", 3)
- && subtag_matches (lang_str, limit, "-th"))
+ && subtag_matches (lang_str, limit, "-th", 3))
{
/* Mon; Thailand */
tags[0] = HB_TAG('M','O','N','T'); /* Thailand Mon */
@@ -2543,14 +2554,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'n':
- if (lang_matches (&lang_str[1], "an-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-hk", 10))
{
/* Min Nan Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-mo", 10))
{
/* Min Nan Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2563,14 +2574,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "an-hans"))
+ if (lang_matches (&lang_str[1], limit, "an-hans", 7))
{
/* Min Nan Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant"))
+ if (lang_matches (&lang_str[1], limit, "an-hant", 7))
{
/* Min Nan Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2578,7 +2589,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Nan Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2586,7 +2597,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Nan Chinese; Macao */
unsigned int i;
@@ -2600,7 +2611,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Nan Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2624,7 +2635,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
break;
case 'r':
if (0 == strncmp (&lang_str[1], "o-", 2)
- && subtag_matches (lang_str, limit, "-md"))
+ && subtag_matches (lang_str, limit, "-md", 3))
{
/* Romanian; Moldova */
unsigned int i;
@@ -2639,14 +2650,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'w':
- if (lang_matches (&lang_str[1], "uu-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "uu-hant-hk", 10))
{
/* Wu Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "uu-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "uu-hant-mo", 10))
{
/* Wu Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2659,14 +2670,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "uu-hans"))
+ if (lang_matches (&lang_str[1], limit, "uu-hans", 7))
{
/* Wu Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "uu-hant"))
+ if (lang_matches (&lang_str[1], limit, "uu-hant", 7))
{
/* Wu Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2674,7 +2685,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "uu-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Wu Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2682,7 +2693,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "uu-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Wu Chinese; Macao */
unsigned int i;
@@ -2696,7 +2707,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "uu-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Wu Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2705,7 +2716,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'y':
- if (lang_matches (&lang_str[1], "ue-hans"))
+ if (lang_matches (&lang_str[1], limit, "ue-hans", 7))
{
/* Yue Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
@@ -2714,14 +2725,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'z':
- if (lang_matches (&lang_str[1], "h-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "h-hant-hk", 9))
{
/* Chinese [macrolanguage]; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "h-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "h-hant-mo", 9))
{
/* Chinese [macrolanguage]; Han (Traditional variant); Macao */
unsigned int i;
@@ -2741,14 +2752,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "h-hans"))
+ if (lang_matches (&lang_str[1], limit, "h-hans", 6))
{
/* Chinese [macrolanguage]; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "h-hant"))
+ if (lang_matches (&lang_str[1], limit, "h-hant", 6))
{
/* Chinese [macrolanguage]; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2763,7 +2774,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "h-", 2)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Chinese [macrolanguage]; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2771,7 +2782,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "h-", 2)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Chinese [macrolanguage]; Macao */
unsigned int i;
@@ -2785,7 +2796,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "h-", 2)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Chinese [macrolanguage]; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2809,7 +2820,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
* Return value: The #hb_language_t corresponding to the BCP 47 language tag,
* or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
**/
-static hb_language_t
+static inline hb_language_t
hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
{
switch (tag)
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
index f50be97ad3..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,
@@ -189,48 +200,48 @@ hb_ot_tag_to_script (hb_tag_t tag)
/* hb_language_t */
-static bool
+static inline bool
subtag_matches (const char *lang_str,
const char *limit,
- const char *subtag)
+ const char *subtag,
+ unsigned subtag_len)
{
+ if (likely ((unsigned) (limit - lang_str) < subtag_len))
+ return false;
+
do {
const char *s = strstr (lang_str, subtag);
if (!s || s >= limit)
return false;
- if (!ISALNUM (s[strlen (subtag)]))
+ if (!ISALNUM (s[subtag_len]))
return true;
- lang_str = s + strlen (subtag);
+ lang_str = s + subtag_len;
} while (true);
}
-static hb_bool_t
-lang_matches (const char *lang_str, const char *spec)
+static bool
+lang_matches (const char *lang_str,
+ const char *limit,
+ const char *spec,
+ unsigned spec_len)
{
- unsigned int len = strlen (spec);
+ /* Same as hb_language_matches(); duplicated. */
+
+ if (likely ((unsigned) (limit - lang_str) < spec_len))
+ return false;
- return strncmp (lang_str, spec, len) == 0 &&
- (lang_str[len] == '\0' || lang_str[len] == '-');
+ return strncmp (lang_str, spec, spec_len) == 0 &&
+ (lang_str[spec_len] == '\0' || lang_str[spec_len] == '-');
}
struct LangTag
{
- char language[4];
+ hb_tag_t language;
hb_tag_t tag;
- int cmp (const char *a) const
+ int cmp (hb_tag_t a) const
{
- const char *b = this->language;
- unsigned int da, db;
- const char *p;
-
- p = strchr (a, '-');
- da = p ? (unsigned int) (p - a) : strlen (a);
-
- p = strchr (b, '-');
- db = p ? (unsigned int) (p - b) : strlen (b);
-
- return strncmp (a, b, hb_max (da, db));
+ return a < this->language ? -1 : a > this->language ? +1 : 0;
}
int cmp (const LangTag *that) const
{ return cmp (that->language); }
@@ -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)
{
@@ -265,16 +285,19 @@ hb_ot_tags_from_language (const char *lang_str,
unsigned int *count,
hb_tag_t *tags)
{
- const char *s;
- unsigned int tag_idx;
+#ifndef HB_NO_LANGUAGE_LONG
/* Check for matches of multiple subtags. */
if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags))
return;
+#endif
/* Find a language matching in the first component. */
- s = strchr (lang_str, '-');
+#ifndef HB_NO_LANGUAGE_LONG
+ const char *s; s = strchr (lang_str, '-');
+#endif
{
+#ifndef HB_NO_LANGUAGE_LONG
if (s && limit - lang_str >= 6)
{
const char *extlang_end = strchr (s + 1, '-');
@@ -283,17 +306,42 @@ hb_ot_tags_from_language (const char *lang_str,
ISALPHA (s[1]))
lang_str = s + 1;
}
- if (hb_sorted_array (ot_languages).bfind (lang_str, &tag_idx))
+#endif
+ const LangTag *ot_languages = nullptr;
+ unsigned ot_languages_len = 0;
+ const char *dash = strchr (lang_str, '-');
+ unsigned first_len = dash ? dash - lang_str : limit - lang_str;
+ if (first_len == 2)
+ {
+ ot_languages = ot_languages2;
+ ot_languages_len = ARRAY_LENGTH (ot_languages2);
+ }
+#ifndef HB_NO_LANGUAGE_LONG
+ else if (first_len == 3)
{
+ ot_languages = ot_languages3;
+ ot_languages_len = ARRAY_LENGTH (ot_languages3);
+ }
+#endif
+
+ hb_tag_t lang_tag = hb_tag_from_string (lang_str, first_len);
+
+ static hb_atomic_int_t last_tag_idx; /* Poor man's cache. */
+ unsigned tag_idx = last_tag_idx;
+
+ if (likely (tag_idx < ot_languages_len && ot_languages[tag_idx].language == lang_tag) ||
+ hb_sorted_array (ot_languages, ot_languages_len).bfind (lang_tag, &tag_idx))
+ {
+ last_tag_idx = tag_idx;
unsigned int i;
while (tag_idx != 0 &&
- 0 == strcmp (ot_languages[tag_idx].language, ot_languages[tag_idx - 1].language))
+ ot_languages[tag_idx].language == ot_languages[tag_idx - 1].language)
tag_idx--;
for (i = 0;
i < *count &&
- tag_idx + i < ARRAY_LENGTH (ot_languages) &&
+ tag_idx + i < ot_languages_len &&
ot_languages[tag_idx + i].tag != HB_TAG_NONE &&
- 0 == strcmp (ot_languages[tag_idx + i].language, ot_languages[tag_idx].language);
+ ot_languages[tag_idx + i].language == ot_languages[tag_idx].language;
i++)
tags[i] = ot_languages[tag_idx + i].tag;
*count = i;
@@ -301,6 +349,7 @@ hb_ot_tags_from_language (const char *lang_str,
}
}
+#ifndef HB_NO_LANGUAGE_LONG
if (!s)
s = lang_str + strlen (lang_str);
if (s - lang_str == 3) {
@@ -309,6 +358,7 @@ hb_ot_tags_from_language (const char *lang_str,
*count = 1;
return;
}
+#endif
*count = 0;
}
@@ -453,15 +503,29 @@ hb_ot_tag_to_language (hb_tag_t tag)
if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
return nullptr;
+#ifndef HB_NO_LANGUAGE_LONG
{
hb_language_t disambiguated_tag = hb_ot_ambiguous_tag_to_language (tag);
if (disambiguated_tag != HB_LANGUAGE_INVALID)
return disambiguated_tag;
}
+#endif
- for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
- if (ot_languages[i].tag == tag)
- return hb_language_from_string (ot_languages[i].language, -1);
+ char buf[4];
+ for (i = 0; i < ARRAY_LENGTH (ot_languages2); i++)
+ if (ot_languages2[i].tag == tag)
+ {
+ hb_tag_to_string (ot_languages2[i].language, buf);
+ return hb_language_from_string (buf, 2);
+ }
+#ifndef HB_NO_LANGUAGE_LONG
+ for (i = 0; i < ARRAY_LENGTH (ot_languages3); i++)
+ if (ot_languages3[i].tag == tag)
+ {
+ hb_tag_to_string (ot_languages3[i].language, buf);
+ return hb_language_from_string (buf, 3);
+ }
+#endif
/* Return a custom language in the form of "x-hbot-AABBCCDD".
* If it's three letters long, also guess it's ISO 639-3 and lower-case and
@@ -533,7 +597,7 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag,
else
{
int shift;
- memcpy (buf, lang_str, len);
+ hb_memcpy (buf, lang_str, len);
if (lang_str[0] != 'x' || lang_str[1] != '-') {
buf[len++] = '-';
buf[len++] = 'x';
@@ -557,16 +621,28 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag,
static inline void
test_langs_sorted ()
{
- for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
+ for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages2); i++)
+ {
+ int c = ot_languages2[i].cmp (&ot_languages2[i - 1]);
+ if (c > 0)
+ {
+ 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();
+ }
+ }
+#ifndef HB_NO_LANGUAGE_LONG
+ for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages3); i++)
{
- int c = ot_languages[i].cmp (&ot_languages[i - 1]);
+ int c = ot_languages3[i].cmp (&ot_languages3[i - 1]);
if (c > 0)
{
- fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n",
- i, ot_languages[i-1].language, c, ot_languages[i].language);
+ 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();
}
}
+#endif
}
int
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 65f26c1d22..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
@@ -28,6 +28,8 @@
#define HB_OT_VAR_AVAR_TABLE_HH
#include "hb-open-type.hh"
+#include "hb-ot-var-common.hh"
+
/*
* avar -- Axis Variations
@@ -40,6 +42,28 @@
namespace OT {
+/* "Spec": https://github.com/be-fonts/boring-expansion-spec/issues/14 */
+struct avarV2Tail
+{
+ friend struct avar;
+
+ bool sanitize (hb_sanitize_context_t *c,
+ const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (varIdxMap.sanitize (c, base) &&
+ varStore.sanitize (c, base));
+ }
+
+ protected:
+ Offset32To<DeltaSetIndexMap> varIdxMap; /* Offset from the beginning of 'avar' table. */
+ Offset32To<VariationStore> varStore; /* Offset from the beginning of 'avar' table. */
+
+ public:
+ DEFINE_SIZE_STATIC (8);
+};
+
+
struct AxisValueMap
{
bool sanitize (hb_sanitize_context_t *c) const
@@ -62,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. */
@@ -106,12 +130,24 @@ struct avar
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;
+ bool has_data () const { return version.to_int (); }
+
+ const SegmentMaps* get_segment_maps () const
+ { return &firstAxisSegmentMaps; }
+
+ unsigned get_axis_count () const
+ { return axisCount; }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- if (unlikely (!(version.sanitize (c) &&
- version.major == 1 &&
- c->check_struct (this))))
+ if (!(version.sanitize (c) &&
+ (version.major == 1
+#ifndef HB_NO_AVAR2
+ || version.major == 2
+#endif
+ ) &&
+ c->check_struct (this)))
return_trace (false);
const SegmentMaps *map = &firstAxisSegmentMaps;
@@ -123,6 +159,15 @@ struct avar
map = &StructAfter<SegmentMaps> (*map);
}
+#ifndef HB_NO_AVAR2
+ if (version.major < 2)
+ return_trace (true);
+
+ const auto &v2 = * (const avarV2Tail *) map;
+ if (unlikely (!v2.sanitize (c, this)))
+ return_trace (false);
+#endif
+
return_trace (true);
}
@@ -136,6 +181,36 @@ struct avar
coords[i] = map->map (coords[i]);
map = &StructAfter<SegmentMaps> (*map);
}
+
+#ifndef HB_NO_AVAR2
+ if (version.major < 2)
+ return;
+
+ for (; count < axisCount; count++)
+ map = &StructAfter<SegmentMaps> (*map);
+
+ const auto &v2 = * (const avarV2Tail *) map;
+
+ const auto &varidx_map = this+v2.varIdxMap;
+ const auto &var_store = this+v2.varStore;
+ auto *var_store_cache = var_store.create_cache ();
+
+ hb_vector_t<int> out;
+ out.alloc (coords_length);
+ for (unsigned i = 0; i < coords_length; i++)
+ {
+ int v = coords[i];
+ uint32_t varidx = varidx_map.map (i);
+ float delta = var_store.get_delta (varidx, coords, coords_length, var_store_cache);
+ v += roundf (delta);
+ v = hb_clamp (v, -(1<<14), +(1<<14));
+ out.push (v);
+ }
+ for (unsigned i = 0; i < coords_length; i++)
+ coords[i] = out[i];
+
+ OT::VariationStore::destroy_cache (var_store_cache);
+#endif
}
void unmap_coords (int *coords, unsigned int coords_length) const
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
index 0eafb949d5..4997c2e2e8 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
@@ -31,12 +31,13 @@
namespace OT {
-struct DeltaSetIndexMapFormat0
+template <typename MapCountT>
+struct DeltaSetIndexMapFormat01
{
friend struct DeltaSetIndexMap;
private:
- DeltaSetIndexMapFormat0* copy (hb_serialize_context_t *c) const
+ DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
auto *out = c->start_embed (this);
@@ -46,7 +47,7 @@ struct DeltaSetIndexMapFormat0
HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
if (unlikely (!p)) return_trace (nullptr);
- memcpy (p, this, HBUINT8::static_size * total_size);
+ hb_memcpy (p, this, HBUINT8::static_size * total_size);
return_trace (out);
}
@@ -128,56 +129,12 @@ struct DeltaSetIndexMapFormat0
HBUINT8 format; /* Format identifier--format = 0 */
HBUINT8 entryFormat; /* A packed field that describes the compressed
* representation of delta-set indices. */
- HBUINT16 mapCount; /* The number of mapping entries. */
+ MapCountT mapCount; /* The number of mapping entries. */
UnsizedArrayOf<HBUINT8>
mapDataZ; /* The delta-set index mapping data. */
public:
- DEFINE_SIZE_ARRAY (4, mapDataZ);
-};
-
-struct DeltaSetIndexMapFormat1
-{
- friend struct DeltaSetIndexMap;
-
- private:
- DeltaSetIndexMapFormat1* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->start_embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- unsigned total_size = min_size + mapCount * get_width ();
- HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
- if (unlikely (!p)) return_trace (nullptr);
-
- memcpy (p, this, HBUINT8::static_size * total_size);
- return_trace (out);
- }
-
- unsigned get_map_count () const { return mapCount; }
- unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; }
- unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- c->check_range (mapDataZ.arrayZ,
- mapCount,
- get_width ()));
- }
-
- protected:
- HBUINT8 format; /* Format identifier--format = 1 */
- HBUINT8 entryFormat; /* A packed field that describes the compressed
- * representation of delta-set indices. */
- HBUINT32 mapCount; /* The number of mapping entries. */
- UnsizedArrayOf<HBUINT8>
- mapDataZ; /* The delta-set index mapping data. */
-
- public:
- DEFINE_SIZE_ARRAY (6, mapDataZ);
+ DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
};
struct DeltaSetIndexMap
@@ -186,8 +143,11 @@ struct DeltaSetIndexMap
bool serialize (hb_serialize_context_t *c, const T &plan)
{
TRACE_SERIALIZE (this);
+ unsigned length = plan.get_output_map ().length;
+ u.format = length <= 0xFFFF ? 0 : 1;
switch (u.format) {
case 0: return_trace (u.format0.serialize (c, plan));
+ case 1: return_trace (u.format1.serialize (c, plan));
default:return_trace (false);
}
}
@@ -196,6 +156,7 @@ struct DeltaSetIndexMap
{
switch (u.format) {
case 0: return (u.format0.map (v));
+ case 1: return (u.format1.map (v));
default:return v;
}
}
@@ -250,14 +211,33 @@ struct DeltaSetIndexMap
protected:
union {
- HBUINT8 format; /* Format identifier */
- DeltaSetIndexMapFormat0 format0;
- DeltaSetIndexMapFormat1 format1;
+ HBUINT8 format; /* Format identifier */
+ DeltaSetIndexMapFormat01<HBUINT16> format0;
+ DeltaSetIndexMapFormat01<HBUINT32> format1;
} u;
public:
DEFINE_SIZE_UNION (1, format);
};
+
+struct VarStoreInstancer
+{
+ VarStoreInstancer (const VariationStore &varStore,
+ const DeltaSetIndexMap &varIdxMap,
+ hb_array_t<int> coords) :
+ varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
+
+ operator bool () const { return bool (coords); }
+
+ float operator() (uint32_t varIdx, unsigned short offset = 0) const
+ { return varStore.get_delta (varIdxMap.map (VarIdx::add (varIdx, offset)), coords); }
+
+ const VariationStore &varStore;
+ const DeltaSetIndexMap &varIdxMap;
+ hb_array_t<int> coords;
+};
+
+
} /* namespace OT */
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 e066558683..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
@@ -44,9 +44,47 @@ struct InstanceRecord
{
friend struct fvar;
- hb_array_t<const HBFixed> get_coordinates (unsigned int axis_count) const
+ hb_array_t<const F16DOT16> get_coordinates (unsigned int axis_count) const
{ return coordinatesZ.as_array (axis_count); }
+ bool subset (hb_subset_context_t *c,
+ unsigned axis_count,
+ bool has_postscript_nameid) const
+ {
+ TRACE_SUBSET (this);
+ if (unlikely (!c->serializer->embed (subfamilyNameID))) return_trace (false);
+ 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;
+ 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 (axes_location->has (*axis_tag) &&
+ fabsf (axes_location->get (*axis_tag) - coords[i].to_float ()) > 0.001f)
+ return_trace (false);
+
+ if (!c->plan->axes_index_map.has (i))
+ continue;
+
+ if (!c->serializer->embed (coords[i]))
+ return_trace (false);
+ }
+
+ if (has_postscript_nameid)
+ {
+ NameID name_id;
+ name_id = StructAfter<NameID> (coords);
+ if (!c->serializer->embed (name_id))
+ return_trace (false);
+ }
+
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
{
TRACE_SANITIZE (this);
@@ -58,7 +96,7 @@ struct InstanceRecord
NameID subfamilyNameID;/* The name ID for entries in the 'name' table
* that provide subfamily names for this instance. */
HBUINT16 flags; /* Reserved for future use — set to 0. */
- UnsizedArrayOf<HBFixed>
+ UnsizedArrayOf<F16DOT16>
coordinatesZ; /* The coordinates array for this instance. */
//NameID postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
// * table that provide PostScript names for this
@@ -96,6 +134,8 @@ struct AxisRecord
info->reserved = 0;
}
+ hb_tag_t get_axis_tag () const { return axisTag; }
+
int normalize_axis_value (float v) const
{
float min_value, default_value, max_value;
@@ -133,21 +173,25 @@ struct AxisRecord
return_trace (c->check_struct (this));
}
- protected:
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.to_float ();
}
public:
Tag axisTag; /* Tag identifying the design variation for the axis. */
protected:
- HBFixed minValue; /* The minimum coordinate value for the axis. */
- HBFixed defaultValue; /* The default coordinate value for the axis. */
- HBFixed maxValue; /* The maximum coordinate value for the axis. */
+ F16DOT16 minValue; /* The minimum coordinate value for the axis. */
+ F16DOT16 defaultValue; /* The default coordinate value for the axis. */
+ F16DOT16 maxValue; /* The maximum coordinate value for the axis. */
public:
HBUINT16 flags; /* Axis flags. */
NameID axisNameID; /* The name ID for entries in the 'name' table that
@@ -213,7 +257,7 @@ struct fvar
if (!axis_index) axis_index = &i;
*axis_index = HB_OT_VAR_NO_AXIS_INDEX;
auto axes = get_axes ();
- return axes.lfind (tag, axis_index) && (axes[*axis_index].get_axis_deprecated (info), true);
+ return axes.lfind (tag, axis_index) && ((void) axes[*axis_index].get_axis_deprecated (info), true);
}
#endif
bool
@@ -221,7 +265,7 @@ struct fvar
{
unsigned i;
auto axes = get_axes ();
- return axes.lfind (tag, &i) && (axes[i].get_axis_info (i, info), true);
+ return axes.lfind (tag, &i) && ((void) axes[i].get_axis_info (i, info), true);
}
int normalize_axis_value (unsigned int axis_index, float v) const
@@ -262,7 +306,7 @@ struct fvar
if (coords_length && *coords_length)
{
- hb_array_t<const HBFixed> instanceCoords = instance->get_coordinates (axisCount)
+ hb_array_t<const F16DOT16> instanceCoords = instance->get_coordinates (axisCount)
.sub_array (0, coords_length);
for (unsigned int i = 0; i < instanceCoords.length; i++)
coords[i] = instanceCoords.arrayZ[i].to_float ();
@@ -270,24 +314,91 @@ struct fvar
return axisCount;
}
- void collect_name_ids (hb_set_t *nameids) const
+ void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ hb_set_t *nameids /* IN/OUT */) const
{
if (!has_data ()) return;
+ hb_map_t pinned_axes;
- + get_axes ()
- | hb_map (&AxisRecord::get_name_id)
- | hb_sink (nameids)
- ;
+ auto axis_records = get_axes ();
+ for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
+ {
+ hb_tag_t axis_tag = axis_records[i].get_axis_tag ();
+ if (user_axes_location->has (axis_tag))
+ {
+ pinned_axes.set (i, axis_tag);
+ continue;
+ }
+
+ nameids->add (axis_records[i].get_name_id ());
+ }
+
+ for (unsigned i = 0 ; i < (unsigned)instanceCount; i++)
+ {
+ const InstanceRecord *instance = get_instance (i);
+
+ if (hb_any (+ hb_enumerate (instance->get_coordinates (axisCount))
+ | hb_filter (pinned_axes, hb_first)
+ | hb_map ([&] (const hb_pair_t<unsigned, const F16DOT16&>& _)
+ {
+ hb_tag_t axis_tag = pinned_axes.get (_.first);
+ float location = user_axes_location->get (axis_tag);
+ if (fabs ((double)location - (double)_.second.to_float ()) > 0.001) return true;
+ return false;
+ })
+ ))
+ continue;
+
+ nameids->add (instance->subfamilyNameID);
+
+ if (instanceSize >= axisCount * 4 + 6)
+ {
+ unsigned post_script_name_id = StructAfter<NameID> (instance->get_coordinates (axisCount));
+ if (post_script_name_id != HB_OT_NAME_ID_INVALID) nameids->add (post_script_name_id);
+ }
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ unsigned retained_axis_count = c->plan->axes_index_map.get_population ();
+ if (!retained_axis_count) //all axes are pinned
+ return_trace (false);
+
+ fvar *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
- + hb_range ((unsigned) instanceCount)
- | hb_map ([this] (const unsigned _) { return get_instance_subfamily_name_id (_); })
- | hb_sink (nameids)
- ;
+ if (!c->serializer->check_assign (out->axisCount, retained_axis_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
- + hb_range ((unsigned) instanceCount)
- | hb_map ([this] (const unsigned _) { return get_instance_postscript_name_id (_); })
- | hb_sink (nameids)
- ;
+ bool has_postscript_nameid = false;
+ if (instanceSize >= axisCount * 4 + 6)
+ has_postscript_nameid = true;
+
+ if (!c->serializer->check_assign (out->instanceSize, retained_axis_count * 4 + (has_postscript_nameid ? 6 : 4),
+ HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+
+ auto axes_records = get_axes ();
+ for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
+ {
+ if (!c->plan->axes_index_map.has (i)) continue;
+ if (unlikely (!c->serializer->embed (axes_records[i])))
+ return_trace (false);
+ }
+
+ if (!c->serializer->check_assign (out->firstAxis, get_size (), HB_SERIALIZE_ERROR_INT_OVERFLOW))
+ return_trace (false);
+
+ for (unsigned i = 0 ; i < (unsigned)instanceCount; i++)
+ {
+ const InstanceRecord *instance = get_instance (i);
+ auto snap = c->serializer->snapshot ();
+ if (!instance->subset (c, axisCount, has_postscript_nameid))
+ c->serializer->revert (snap);
+ }
+ return_trace (true);
}
public:
@@ -315,8 +426,8 @@ struct fvar
HBUINT16 instanceCount; /* The number of named instances defined in the font
* (the number of records in the instances array). */
HBUINT16 instanceSize; /* The size in bytes of each InstanceRecord — set
- * to either axisCount * sizeof(HBFixed) + 4, or to
- * axisCount * sizeof(HBFixed) + 6. */
+ * to either axisCount * sizeof(F16DOT16) + 4, or to
+ * axisCount * sizeof(F16DOT16) + 6. */
public:
DEFINE_SIZE_STATIC (16);
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 618cec08fb..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
@@ -45,9 +45,10 @@ struct contour_point_t
void translate (const contour_point_t &p) { x += p.x; y += p.y; }
- uint8_t flag;
- float x, y;
- bool is_end_point;
+ float x = 0.f;
+ float y = 0.f;
+ uint8_t flag = 0;
+ bool is_end_point = false;
};
struct contour_point_vector_t : hb_vector_t<contour_point_t>
@@ -55,16 +56,23 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t>
void extend (const hb_array_t<contour_point_t> &a)
{
unsigned int old_len = length;
- resize (old_len + a.length);
- for (unsigned int i = 0; i < a.length; i++)
- (*this)[old_len + i] = a[i];
+ if (unlikely (!resize (old_len + a.length, false)))
+ return;
+ auto arrayZ = this->arrayZ + old_len;
+ unsigned count = a.length;
+ hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0]));
}
void transform (const float (&matrix)[4])
{
- for (unsigned int i = 0; i < length; i++)
+ if (matrix[0] == 1.f && matrix[1] == 0.f &&
+ matrix[2] == 0.f && matrix[3] == 1.f)
+ return;
+ auto arrayZ = this->arrayZ;
+ unsigned count = length;
+ for (unsigned i = 0; i < count; i++)
{
- contour_point_t &p = (*this)[i];
+ contour_point_t &p = arrayZ[i];
float x_ = p.x * matrix[0] + p.y * matrix[2];
p.y = p.x * matrix[1] + p.y * matrix[3];
p.x = x_;
@@ -73,8 +81,12 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t>
void translate (const contour_point_t& delta)
{
- for (unsigned int i = 0; i < length; i++)
- (*this)[i].translate (delta);
+ if (delta.x == 0.f && delta.y == 0.f)
+ return;
+ auto arrayZ = this->arrayZ;
+ unsigned count = length;
+ for (unsigned i = 0; i < count; i++)
+ arrayZ[i].translate (delta);
}
};
@@ -89,7 +101,7 @@ struct TupleVariationHeader
const TupleVariationHeader &get_next (unsigned axis_count) const
{ return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count)); }
- float calculate_scalar (const int *coords, unsigned int coord_count,
+ float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
const hb_array_t<const F2DOT14> shared_tuples) const
{
hb_array_t<const F2DOT14> peak_tuple;
@@ -116,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;
@@ -208,7 +220,7 @@ struct GlyphVariationData
{
const HBUINT8 *base = &(var_data+var_data->data);
const HBUINT8 *p = base;
- if (!unpack_points (p, shared_indices, var_data_bytes)) return false;
+ if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
data_offset = p - base;
}
return true;
@@ -218,8 +230,8 @@ struct GlyphVariationData
{
return (index < var_data->tupleVarCount.get_count ()) &&
var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) &&
- var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (), current_tuple->get_size (axis_count))) &&
- current_tuple->get_size (axis_count);
+ var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (),
+ current_tuple->get_size (axis_count)));
}
bool move_to_next ()
@@ -258,7 +270,7 @@ struct GlyphVariationData
static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
hb_vector_t<unsigned int> &points /* OUT */,
- const hb_bytes_t &bytes)
+ const HBUINT8 *end)
{
enum packed_point_flag_t
{
@@ -266,52 +278,51 @@ struct GlyphVariationData
POINT_RUN_COUNT_MASK = 0x7F
};
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
- uint16_t count = *p++;
+ unsigned count = *p++;
if (count & POINTS_ARE_WORDS)
{
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
}
- points.resize (count);
+ if (unlikely (!points.resize (count, false))) return false;
- unsigned int n = 0;
- uint16_t i = 0;
+ unsigned n = 0;
+ unsigned i = 0;
while (i < count)
{
- if (unlikely (!bytes.check_range (p))) return false;
- uint16_t j;
- uint8_t control = *p++;
- uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1;
+ if (unlikely (p + 1 > end)) return false;
+ unsigned control = *p++;
+ unsigned run_count = (control & POINT_RUN_COUNT_MASK) + 1;
+ if (unlikely (i + run_count > count)) return false;
+ unsigned j;
if (control & POINTS_ARE_WORDS)
{
- for (j = 0; j < run_count && i < count; j++, i++)
+ if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
+ for (j = 0; j < run_count; j++, i++)
{
- if (unlikely (!bytes.check_range ((const HBUINT16 *) p)))
- return false;
n += *(const HBUINT16 *)p;
- points[i] = n;
+ points.arrayZ[i] = n;
p += HBUINT16::static_size;
}
}
else
{
- for (j = 0; j < run_count && i < count; j++, i++)
+ if (unlikely (p + run_count > end)) return false;
+ for (j = 0; j < run_count; j++, i++)
{
- if (unlikely (!bytes.check_range (p))) return false;
n += *p++;
- points[i] = n;
+ points.arrayZ[i] = n;
}
}
- if (j < run_count) return false;
}
return true;
}
static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
hb_vector_t<int> &deltas /* IN/OUT */,
- const hb_bytes_t &bytes)
+ const HBUINT8 *end)
{
enum packed_delta_flag_t
{
@@ -320,34 +331,37 @@ struct GlyphVariationData
DELTA_RUN_COUNT_MASK = 0x3F
};
- unsigned int i = 0;
- unsigned int count = deltas.length;
+ unsigned i = 0;
+ unsigned count = deltas.length;
while (i < count)
{
- if (unlikely (!bytes.check_range (p))) return false;
- uint8_t control = *p++;
- unsigned int run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
- unsigned int j;
+ if (unlikely (p + 1 > end)) return false;
+ unsigned control = *p++;
+ unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
+ if (unlikely (i + run_count > count)) return false;
+ unsigned j;
if (control & DELTAS_ARE_ZERO)
- for (j = 0; j < run_count && i < count; j++, i++)
- deltas[i] = 0;
+ {
+ for (j = 0; j < run_count; j++, i++)
+ deltas.arrayZ[i] = 0;
+ }
else if (control & DELTAS_ARE_WORDS)
- for (j = 0; j < run_count && i < count; j++, i++)
+ {
+ if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
+ for (j = 0; j < run_count; j++, i++)
{
- if (unlikely (!bytes.check_range ((const HBUINT16 *) p)))
- return false;
- deltas[i] = *(const HBINT16 *) p;
+ deltas.arrayZ[i] = * (const HBINT16 *) p;
p += HBUINT16::static_size;
}
+ }
else
- for (j = 0; j < run_count && i < count; j++, i++)
+ {
+ if (unlikely (p + run_count > end)) return false;
+ for (j = 0; j < run_count; j++, i++)
{
- if (unlikely (!bytes.check_range (p)))
- return false;
- deltas[i] = *(const HBINT8 *) p++;
+ deltas.arrayZ[i] = * (const HBINT8 *) p++;
}
- if (j < run_count)
- return false;
+ }
}
return true;
}
@@ -390,13 +404,10 @@ struct gvar
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && (version.major == 1) &&
- (glyphCount == c->get_num_glyphs ()) &&
sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
(is_long_offset () ?
c->check_array (get_long_offset_array (), glyphCount+1) :
- c->check_array (get_short_offset_array (), glyphCount+1)) &&
- c->check_array (((const HBUINT8*)&(this+dataZ)) + get_offset (0),
- get_offset (glyphCount) - get_offset (0)));
+ c->check_array (get_short_offset_array (), glyphCount+1)));
}
/* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */
@@ -443,7 +454,7 @@ struct gvar
F2DOT14 *tuples = c->serializer->allocate_size<F2DOT14> (shared_tuple_size);
if (!tuples) return_trace (false);
out->sharedTuples = (char *) tuples - (char *) out;
- memcpy (tuples, this+sharedTuples, shared_tuple_size);
+ hb_memcpy (tuples, this+sharedTuples, shared_tuple_size);
}
char *subset_data = c->serializer->allocate_size<char> (subset_data_size);
@@ -466,7 +477,7 @@ struct gvar
((HBUINT16 *) subset_offsets)[gid] = glyph_offset / 2;
if (var_data_bytes.length > 0)
- memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
+ hb_memcpy (subset_data, var_data_bytes.arrayZ, var_data_bytes.length);
subset_data += var_data_bytes.length;
glyph_offset += var_data_bytes.length;
}
@@ -482,7 +493,9 @@ struct gvar
const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob, hb_codepoint_t glyph) const
{
unsigned start_offset = get_offset (glyph);
- unsigned length = get_offset (glyph+1) - start_offset;
+ unsigned end_offset = get_offset (glyph+1);
+ if (unlikely (end_offset < start_offset)) return hb_bytes_t ();
+ unsigned length = end_offset - start_offset;
hb_bytes_t var_data = blob->as_bytes ().sub_array (((unsigned) dataZ) + start_offset, length);
return likely (var_data.length >= GlyphVariationData::min_size) ? var_data : hb_bytes_t ();
}
@@ -490,7 +503,11 @@ struct gvar
bool is_long_offset () const { return flags & 1; }
unsigned get_offset (unsigned i) const
- { return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2; }
+ {
+ if (unlikely (i > glyphCount)) return 0;
+ _hb_compiler_memory_r_barrier ();
+ return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
+ }
const HBUINT32 * get_long_offset_array () const { return (const HBUINT32 *) &offsetZ; }
const HBUINT16 *get_short_offset_array () const { return (const HBUINT16 *) &offsetZ; }
@@ -503,19 +520,17 @@ struct gvar
~accelerator_t () { table.destroy (); }
private:
- struct x_getter { static float get (const contour_point_t &p) { return p.x; } };
- struct y_getter { static float get (const contour_point_t &p) { return p.y; } };
- template <typename T>
static float infer_delta (const hb_array_t<contour_point_t> points,
const hb_array_t<contour_point_t> deltas,
- unsigned int target, unsigned int prev, unsigned int next)
+ unsigned int target, unsigned int prev, unsigned int next,
+ float contour_point_t::*m)
{
- float target_val = T::get (points[target]);
- float prev_val = T::get (points[prev]);
- float next_val = T::get (points[next]);
- float prev_delta = T::get (deltas[prev]);
- float next_delta = T::get (deltas[next]);
+ float target_val = points.arrayZ[target].*m;
+ float prev_val = points.arrayZ[prev].*m;
+ float next_val = points.arrayZ[next].*m;
+ float prev_delta = deltas.arrayZ[prev].*m;
+ float next_delta = deltas.arrayZ[next].*m;
if (prev_val == next_val)
return (prev_delta == next_delta) ? prev_delta : 0.f;
@@ -526,18 +541,18 @@ struct gvar
/* linear interpolation */
float r = (target_val - prev_val) / (next_val - prev_val);
- return (1.f - r) * prev_delta + r * next_delta;
+ return prev_delta + r * (next_delta - prev_delta);
}
static unsigned int next_index (unsigned int i, unsigned int start, unsigned int end)
{ return (i >= end) ? start : (i + 1); }
public:
- bool apply_deltas_to_points (hb_codepoint_t glyph, hb_font_t *font,
+ bool apply_deltas_to_points (hb_codepoint_t glyph,
+ hb_array_t<int> coords,
const hb_array_t<contour_point_t> points) const
{
- /* num_coords should exactly match gvar's axisCount due to how GlyphVariationData tuples are aligned */
- if (!font->num_coords || font->num_coords != table->axisCount) return true;
+ if (!coords) return true;
if (unlikely (glyph >= table->glyphCount)) return true;
@@ -550,22 +565,26 @@ struct gvar
return true; /* so isn't applied at all */
/* Save original points for inferred delta calculation */
- contour_point_vector_t orig_points;
- orig_points.resize (points.length);
- for (unsigned int i = 0; i < orig_points.length; i++)
- orig_points[i] = points[i];
+ contour_point_vector_t orig_points_vec;
+ orig_points_vec.extend (points);
+ if (unlikely (orig_points_vec.in_error ())) return false;
+ auto orig_points = orig_points_vec.as_array ();
- contour_point_vector_t deltas; /* flag is used to indicate referenced point */
- deltas.resize (points.length);
+ contour_point_vector_t deltas_vec; /* flag is used to indicate referenced point */
+ if (unlikely (!deltas_vec.resize (points.length, false))) return false;
+ auto deltas = deltas_vec.as_array ();
hb_vector_t<unsigned> end_points;
for (unsigned i = 0; i < points.length; ++i)
- if (points[i].is_end_point)
+ if (points.arrayZ[i].is_end_point)
end_points.push (i);
- int *coords = font->coords;
- unsigned num_coords = font->num_coords;
+ unsigned num_coords = table->axisCount;
hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
+
+ hb_vector_t<unsigned int> private_indices;
+ hb_vector_t<int> x_deltas;
+ hb_vector_t<int> y_deltas;
do
{
float scalar = iterator.current_tuple->calculate_scalar (coords, num_coords, shared_tuples);
@@ -575,90 +594,106 @@ struct gvar
if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
return false;
- hb_bytes_t bytes ((const char *) p, length);
- hb_vector_t<unsigned int> private_indices;
+ const HBUINT8 *end = p + length;
+
bool has_private_points = iterator.current_tuple->has_private_points ();
if (has_private_points &&
- !GlyphVariationData::unpack_points (p, private_indices, bytes))
+ !GlyphVariationData::unpack_points (p, private_indices, end))
return false;
const hb_array_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
bool apply_to_all = (indices.length == 0);
unsigned int num_deltas = apply_to_all ? points.length : indices.length;
- hb_vector_t<int> x_deltas;
- x_deltas.resize (num_deltas);
- if (!GlyphVariationData::unpack_deltas (p, x_deltas, bytes))
- return false;
- hb_vector_t<int> y_deltas;
- y_deltas.resize (num_deltas);
- if (!GlyphVariationData::unpack_deltas (p, y_deltas, bytes))
- return false;
+ if (unlikely (!x_deltas.resize (num_deltas, false))) return false;
+ if (unlikely (!GlyphVariationData::unpack_deltas (p, x_deltas, end))) return false;
+ if (unlikely (!y_deltas.resize (num_deltas, false))) return false;
+ if (unlikely (!GlyphVariationData::unpack_deltas (p, y_deltas, end))) return false;
- for (unsigned int i = 0; i < deltas.length; i++)
- deltas[i].init ();
- for (unsigned int i = 0; i < num_deltas; i++)
- {
- unsigned int pt_index = apply_to_all ? i : indices[i];
- deltas[pt_index].flag = 1; /* this point is referenced, i.e., explicit deltas specified */
- deltas[pt_index].x += x_deltas[i] * scalar;
- deltas[pt_index].y += y_deltas[i] * scalar;
- }
+ hb_memset (deltas.arrayZ, 0, deltas.get_size ());
+
+ unsigned ref_points = 0;
+ if (scalar != 1.0f)
+ for (unsigned int i = 0; i < num_deltas; i++)
+ {
+ unsigned int pt_index = apply_to_all ? i : indices[i];
+ if (unlikely (pt_index >= deltas.length)) continue;
+ auto &delta = deltas.arrayZ[pt_index];
+ ref_points += !delta.flag;
+ delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
+ delta.x += x_deltas.arrayZ[i] * scalar;
+ delta.y += y_deltas.arrayZ[i] * scalar;
+ }
+ else
+ for (unsigned int i = 0; i < num_deltas; i++)
+ {
+ unsigned int pt_index = apply_to_all ? i : indices[i];
+ if (unlikely (pt_index >= deltas.length)) continue;
+ auto &delta = deltas.arrayZ[pt_index];
+ ref_points += !delta.flag;
+ delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
+ delta.x += x_deltas.arrayZ[i];
+ delta.y += y_deltas.arrayZ[i];
+ }
/* infer deltas for unreferenced points */
- unsigned start_point = 0;
- for (unsigned c = 0; c < end_points.length; c++)
+ if (ref_points && ref_points < orig_points.length)
{
- unsigned end_point = end_points[c];
+ unsigned start_point = 0;
+ for (unsigned c = 0; c < end_points.length; c++)
+ {
+ unsigned end_point = end_points.arrayZ[c];
- /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
- unsigned unref_count = 0;
- for (unsigned i = start_point; i <= end_point; i++)
- if (!deltas[i].flag) unref_count++;
+ /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
+ unsigned unref_count = 0;
+ for (unsigned i = start_point; i < end_point + 1; i++)
+ unref_count += deltas.arrayZ[i].flag;
+ unref_count = (end_point - start_point + 1) - unref_count;
- unsigned j = start_point;
- if (unref_count == 0 || unref_count > end_point - start_point)
- goto no_more_gaps;
+ unsigned j = start_point;
+ if (unref_count == 0 || unref_count > end_point - start_point)
+ goto no_more_gaps;
- for (;;)
- {
- /* Locate the next gap of unreferenced points between two referenced points prev and next.
- * Note that a gap may wrap around at left (start_point) and/or at right (end_point).
- */
- unsigned int prev, next, i;
- for (;;)
- {
- i = j;
- j = next_index (i, start_point, end_point);
- if (deltas[i].flag && !deltas[j].flag) break;
- }
- prev = j = i;
- for (;;)
- {
- i = j;
- j = next_index (i, start_point, end_point);
- if (!deltas[i].flag && deltas[j].flag) break;
- }
- next = j;
- /* Infer deltas for all unref points in the gap between prev and next */
- i = prev;
for (;;)
{
- i = next_index (i, start_point, end_point);
- if (i == next) break;
- deltas[i].x = infer_delta<x_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
- deltas[i].y = infer_delta<y_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
- if (--unref_count == 0) goto no_more_gaps;
+ /* Locate the next gap of unreferenced points between two referenced points prev and next.
+ * Note that a gap may wrap around at left (start_point) and/or at right (end_point).
+ */
+ unsigned int prev, next, i;
+ for (;;)
+ {
+ i = j;
+ j = next_index (i, start_point, end_point);
+ if (deltas.arrayZ[i].flag && !deltas.arrayZ[j].flag) break;
+ }
+ prev = j = i;
+ for (;;)
+ {
+ i = j;
+ j = next_index (i, start_point, end_point);
+ if (!deltas.arrayZ[i].flag && deltas.arrayZ[j].flag) break;
+ }
+ next = j;
+ /* Infer deltas for all unref points in the gap between prev and next */
+ i = prev;
+ for (;;)
+ {
+ i = next_index (i, start_point, end_point);
+ if (i == next) break;
+ deltas.arrayZ[i].x = infer_delta (orig_points, deltas, i, prev, next, &contour_point_t::x);
+ deltas.arrayZ[i].y = infer_delta (orig_points, deltas, i, prev, next, &contour_point_t::y);
+ if (--unref_count == 0) goto no_more_gaps;
+ }
}
+ no_more_gaps:
+ start_point = end_point + 1;
}
-no_more_gaps:
- start_point = end_point + 1;
}
/* apply specified / inferred deltas to points */
for (unsigned int i = 0; i < points.length; i++)
{
- points[i].x += deltas[i].x;
- points[i].y += deltas[i].y;
+ points.arrayZ[i].x += deltas.arrayZ[i].x;
+ points.arrayZ[i].y += deltas.arrayZ[i].y;
}
} while (iterator.move_to_next ());
@@ -696,7 +731,7 @@ no_more_gaps:
offsetZ; /* Offsets from the start of the GlyphVariationData array
* to each GlyphVariationData table. */
public:
- DEFINE_SIZE_MIN (20);
+ DEFINE_SIZE_ARRAY (20, offsetZ);
};
struct gvar_accelerator_t : gvar::accelerator_t {
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
index e9d90352f0..53355c5077 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh
@@ -319,23 +319,27 @@ struct HVARVVAR
hvar_plan.index_map_plans.as_array ()));
}
- float get_advance_var (hb_codepoint_t glyph, hb_font_t *font) const
+ float get_advance_delta_unscaled (hb_codepoint_t glyph,
+ const int *coords, unsigned int coord_count,
+ VariationStore::cache_t *store_cache = nullptr) const
{
uint32_t varidx = (this+advMap).map (glyph);
- return (this+varStore).get_delta (varidx, font->coords, font->num_coords);
+ return (this+varStore).get_delta (varidx,
+ coords, coord_count,
+ store_cache);
}
- float get_side_bearing_var (hb_codepoint_t glyph,
- const int *coords, unsigned int coord_count) const
+ bool get_lsb_delta_unscaled (hb_codepoint_t glyph,
+ const int *coords, unsigned int coord_count,
+ float *lsb) const
{
- if (!has_side_bearing_deltas ()) return 0.f;
+ if (!lsbMap) return false;
uint32_t varidx = (this+lsbMap).map (glyph);
- return (this+varStore).get_delta (varidx, coords, coord_count);
+ *lsb = (this+varStore).get_delta (varidx, coords, coord_count);
+ return true;
}
- bool has_side_bearing_deltas () const { return lsbMap && rsbMap; }
-
- protected:
+ public:
FixedVersion<>version; /* Version of the metrics variation table
* initially set to 0x00010000u */
Offset32To<VariationStore>
@@ -387,6 +391,16 @@ struct VVAR : HVARVVAR {
bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); }
+ bool get_vorg_delta_unscaled (hb_codepoint_t glyph,
+ const int *coords, unsigned int coord_count,
+ float *delta) const
+ {
+ if (!vorgMap) return false;
+ uint32_t varidx = (this+vorgMap).map (glyph);
+ *delta = (this+varStore).get_delta (varidx, coords, coord_count);
+ return true;
+ }
+
protected:
Offset32To<DeltaSetIndexMap>
vorgMap; /* Offset to vertical-origin var-idx mapping. */
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 208db46741..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
@@ -43,7 +43,7 @@ struct VariationValueRecord
public:
Tag valueTag; /* Four-byte tag identifying a font-wide measure. */
- HBUINT32 varIdx; /* Outer/inner index into VariationStore item. */
+ VarIdx varIdx; /* Outer/inner index into VariationStore item. */
public:
DEFINE_SIZE_STATIC (8);
@@ -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-ot-var.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc
index 0376e26b4a..f000f27263 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc
@@ -56,7 +56,7 @@
*
* Tests whether a face includes any OpenType variation data in the `fvar` table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.4.2
**/
@@ -162,7 +162,7 @@ hb_ot_var_get_axis_infos (hb_face_t *face,
* Fetches the variation-axis information corresponding to the specified axis tag
* in the specified face.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.2.0
**/
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-machinery.cc b/src/3rdparty/harfbuzz-ng/src/hb-outline.hh
index 7fc9c24b59..c463993cfb 100644
--- a/src/3rdparty/harfbuzz-ng/src/test-machinery.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-outline.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2022 Behdad Esfahbod
+ * Copyright © 2023 Behdad Esfahbod
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -22,25 +22,62 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
+#ifndef HB_OUTLINE_HH
+#define HB_OUTLINE_HH
+
#include "hb.hh"
-#include "hb-machinery.hh"
-struct hb_intp_lazy_loader_t : hb_lazy_loader_t<int, hb_intp_lazy_loader_t>
+#include "hb-draw.hh"
+
+
+struct hb_outline_point_t
{
- static int* create () { return nullptr; }
- static void destroy (int* l) {}
- static int* get_null () { return nullptr; }
+ 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_void_lazy_loader_t : hb_lazy_loader_t<void, hb_void_lazy_loader_t>
+struct hb_outline_vector_t
{
- static void* create () { return nullptr; }
- static void destroy (void* l) {}
- static void* get_null () { return nullptr; }
+ float normalize_len ()
+ {
+ float len = hypotf (x, y);
+ if (len)
+ {
+ x /= len;
+ y /= len;
+ }
+ return len;
+ }
+
+ float x, y;
};
-int
-main (int argc, char **argv)
+struct hb_outline_t
{
- return 0;
-}
+ void reset () { points.shrink (0, false); contours.resize (0); }
+
+ 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);
+
+ hb_vector_t<hb_outline_point_t> points;
+ hb_vector_t<unsigned> contours;
+};
+
+HB_INTERNAL hb_draw_funcs_t *
+hb_outline_recording_pen_get_funcs ();
+
+
+#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 dcf8f6627d..ee43721a38 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-pool.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-pool.hh
@@ -31,19 +31,17 @@
/* 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) {}
- ~hb_pool_t () { fini (); }
-
- void fini ()
+ ~hb_pool_t ()
{
next = nullptr;
- for (chunk_t *_ : chunks) hb_free (_);
-
- chunks.fini ();
+ + hb_iter (chunks)
+ | hb_apply (hb_free)
+ ;
}
T* alloc ()
@@ -60,7 +58,7 @@ struct hb_pool_t
T* obj = next;
next = * ((T**) next);
- memset (obj, 0, sizeof (T));
+ hb_memset (obj, 0, sizeof (T));
return obj;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh b/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh
index 7d799ae906..93a7842eb0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-priority-queue.hh
@@ -38,18 +38,11 @@
*/
struct hb_priority_queue_t
{
- HB_DELETE_COPY_ASSIGN (hb_priority_queue_t);
- hb_priority_queue_t () { init (); }
- ~hb_priority_queue_t () { fini (); }
-
private:
typedef hb_pair_t<int64_t, unsigned> item_t;
hb_vector_t<item_t> heap;
public:
- void init () { heap.init (); }
-
- void fini () { heap.fini (); }
void reset () { heap.resize (0); }
@@ -58,16 +51,21 @@ struct hb_priority_queue_t
void insert (int64_t priority, unsigned value)
{
heap.push (item_t (priority, value));
+ if (unlikely (heap.in_error ())) return;
bubble_up (heap.length - 1);
}
item_t pop_minimum ()
{
- item_t result = heap[0];
+ assert (!is_empty ());
+
+ item_t result = heap.arrayZ[0];
- heap[0] = heap[heap.length - 1];
- heap.shrink (heap.length - 1);
- bubble_down (0);
+ heap.arrayZ[0] = heap.arrayZ[heap.length - 1];
+ heap.resize (heap.length - 1);
+
+ if (!is_empty ())
+ bubble_down (0);
return result;
}
@@ -104,6 +102,8 @@ struct hb_priority_queue_t
void bubble_down (unsigned index)
{
+ assert (index < heap.length);
+
unsigned left = left_child (index);
unsigned right = right_child (index);
@@ -113,11 +113,11 @@ struct hb_priority_queue_t
return;
bool has_right = right < heap.length;
- if (heap[index].first <= heap[left].first
- && (!has_right || heap[index].first <= heap[right].first))
+ if (heap.arrayZ[index].first <= heap.arrayZ[left].first
+ && (!has_right || heap.arrayZ[index].first <= heap.arrayZ[right].first))
return;
- if (!has_right || heap[left].first < heap[right].first)
+ if (!has_right || heap.arrayZ[left].first < heap.arrayZ[right].first)
{
swap (index, left);
bubble_down (left);
@@ -130,10 +130,12 @@ struct hb_priority_queue_t
void bubble_up (unsigned index)
{
+ assert (index < heap.length);
+
if (index == 0) return;
unsigned parent_index = parent (index);
- if (heap[parent_index].first <= heap[index].first)
+ if (heap.arrayZ[parent_index].first <= heap.arrayZ[index].first)
return;
swap (index, parent_index);
@@ -142,9 +144,9 @@ struct hb_priority_queue_t
void swap (unsigned a, unsigned b)
{
- item_t temp = heap[a];
- heap[a] = heap[b];
- heap[b] = temp;
+ assert (a < heap.length);
+ assert (b < heap.length);
+ hb_swap (heap.arrayZ[a], heap.arrayZ[b]);
}
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh b/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
index 2a9e75c45b..cd57ade072 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
@@ -29,1077 +29,157 @@
#include "hb-open-type.hh"
#include "hb-map.hh"
-#include "hb-priority-queue.hh"
-#include "hb-serialize.hh"
#include "hb-vector.hh"
+#include "graph/graph.hh"
+#include "graph/gsubgpos-graph.hh"
+#include "graph/serialize.hh"
+
+using graph::graph_t;
/*
* For a detailed writeup on the overflow resolution algorithm see:
* docs/repacker.md
*/
-struct graph_t
-{
- struct vertex_t
- {
- hb_serialize_context_t::object_t obj;
- int64_t distance = 0 ;
- int64_t space = 0 ;
- hb_vector_t<unsigned> parents;
- unsigned start = 0;
- unsigned end = 0;
- unsigned priority = 0;
-
- bool is_shared () const
- {
- return parents.length > 1;
- }
-
- unsigned incoming_edges () const
- {
- return parents.length;
- }
-
- void remove_parent (unsigned parent_index)
- {
- for (unsigned i = 0; i < parents.length; i++)
- {
- if (parents[i] != parent_index) continue;
- parents.remove (i);
- break;
- }
- }
-
- void remap_parents (const hb_vector_t<unsigned>& id_map)
- {
- for (unsigned i = 0; i < parents.length; i++)
- parents[i] = id_map[parents[i]];
- }
-
- void remap_parent (unsigned old_index, unsigned new_index)
- {
- for (unsigned i = 0; i < parents.length; i++)
- {
- if (parents[i] == old_index)
- parents[i] = new_index;
- }
- }
-
- bool is_leaf () const
- {
- return !obj.real_links.length && !obj.virtual_links.length;
- }
-
- bool raise_priority ()
- {
- if (has_max_priority ()) return false;
- priority++;
- return true;
- }
-
- bool has_max_priority () const {
- return priority >= 3;
- }
-
- int64_t modified_distance (unsigned order) const
- {
- // TODO(garretrieger): once priority is high enough, should try
- // setting distance = 0 which will force to sort immediately after
- // it's parent where possible.
-
- int64_t modified_distance =
- hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF);
- if (has_max_priority ()) {
- modified_distance = 0;
- }
- return (modified_distance << 18) | (0x003FFFF & order);
- }
-
- int64_t distance_modifier () const
- {
- if (!priority) return 0;
- int64_t table_size = obj.tail - obj.head;
-
- if (priority == 1)
- return -table_size / 2;
-
- return -table_size;
- }
- };
-
- struct overflow_record_t
- {
- unsigned parent;
- unsigned child;
- };
-
- /*
- * A topological sorting of an object graph. Ordered
- * in reverse serialization order (first object in the
- * serialization is at the end of the list). This matches
- * the 'packed' object stack used internally in the
- * serializer
- */
- template<typename T>
- graph_t (const T& objects)
- : parents_invalid (true),
- distance_invalid (true),
- positions_invalid (true),
- successful (true)
- {
- num_roots_for_space_.push (1);
- bool removed_nil = false;
- for (unsigned i = 0; i < objects.length; i++)
- {
- // TODO(grieger): check all links point to valid objects.
-
- // If this graph came from a serialization buffer object 0 is the
- // nil object. We don't need it for our purposes here so drop it.
- if (i == 0 && !objects[i])
- {
- removed_nil = true;
- continue;
- }
-
- vertex_t* v = vertices_.push ();
- if (check_success (!vertices_.in_error ()))
- v->obj = *objects[i];
- if (!removed_nil) continue;
- // Fix indices to account for removed nil object.
- for (auto& l : v->obj.all_links_writer ()) {
- l.objidx--;
- }
- }
- }
-
- ~graph_t ()
- {
- vertices_.fini ();
- }
-
- bool in_error () const
- {
- return !successful ||
- vertices_.in_error () ||
- num_roots_for_space_.in_error ();
- }
-
- const vertex_t& root () const
- {
- return vertices_[root_idx ()];
- }
-
- unsigned root_idx () const
- {
- // Object graphs are in reverse order, the first object is at the end
- // of the vector. Since the graph is topologically sorted it's safe to
- // assume the first object has no incoming edges.
- return vertices_.length - 1;
- }
-
- const hb_serialize_context_t::object_t& object(unsigned i) const
- {
- return vertices_[i].obj;
- }
-
- /*
- * serialize graph into the provided serialization buffer.
- */
- hb_blob_t* serialize () const
- {
- hb_vector_t<char> buffer;
- size_t size = serialized_length ();
- if (!buffer.alloc (size)) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
- return nullptr;
- }
- hb_serialize_context_t c((void *) buffer, size);
-
- c.start_serialize<void> ();
- for (unsigned i = 0; i < vertices_.length; i++) {
- c.push ();
-
- size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
- char* start = c.allocate_size <char> (size);
- if (!start) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space.");
- return nullptr;
- }
-
- memcpy (start, vertices_[i].obj.head, size);
-
- // Only real links needs to be serialized.
- for (const auto& link : vertices_[i].obj.real_links)
- serialize_link (link, start, &c);
-
- // All duplications are already encoded in the graph, so don't
- // enable sharing during packing.
- c.pop_pack (false);
- }
- c.end_serialize ();
-
- if (c.in_error ()) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d",
- c.errors);
- return nullptr;
- }
-
- return c.copy_blob ();
- }
-
- /*
- * Generates a new topological sorting of graph using Kahn's
- * algorithm: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms
- */
- void sort_kahn ()
- {
- positions_invalid = true;
-
- if (vertices_.length <= 1) {
- // Graph of 1 or less doesn't need sorting.
- return;
- }
-
- hb_vector_t<unsigned> queue;
- hb_vector_t<vertex_t> sorted_graph;
- if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
- hb_vector_t<unsigned> id_map;
- if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
-
- hb_vector_t<unsigned> removed_edges;
- if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
- update_parents ();
-
- queue.push (root_idx ());
- int new_id = vertices_.length - 1;
-
- while (!queue.in_error () && queue.length)
- {
- unsigned next_id = queue[0];
- queue.remove (0);
-
- vertex_t& next = vertices_[next_id];
- sorted_graph[new_id] = next;
- id_map[next_id] = new_id--;
-
- for (const auto& link : next.obj.all_links ()) {
- removed_edges[link.objidx]++;
- if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
- queue.push (link.objidx);
- }
- }
-
- check_success (!queue.in_error ());
- check_success (!sorted_graph.in_error ());
- if (!check_success (new_id == -1))
- print_orphaned_nodes ();
-
- remap_all_obj_indices (id_map, &sorted_graph);
-
- hb_swap (vertices_, sorted_graph);
- sorted_graph.fini ();
- }
-
- /*
- * Generates a new topological sorting of graph ordered by the shortest
- * distance to each node.
- */
- void sort_shortest_distance ()
- {
- positions_invalid = true;
-
- if (vertices_.length <= 1) {
- // Graph of 1 or less doesn't need sorting.
- return;
- }
-
- update_distances ();
- hb_priority_queue_t queue;
- hb_vector_t<vertex_t> sorted_graph;
- if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
- hb_vector_t<unsigned> id_map;
- if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
-
- hb_vector_t<unsigned> removed_edges;
- if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
- update_parents ();
-
- queue.insert (root ().modified_distance (0), root_idx ());
- int new_id = root_idx ();
- unsigned order = 1;
- while (!queue.in_error () && !queue.is_empty ())
- {
- unsigned next_id = queue.pop_minimum().second;
-
- vertex_t& next = vertices_[next_id];
- sorted_graph[new_id] = next;
- id_map[next_id] = new_id--;
-
- for (const auto& link : next.obj.all_links ()) {
- removed_edges[link.objidx]++;
- if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
- // Add the order that the links were encountered to the priority.
- // This ensures that ties between priorities objects are broken in a consistent
- // way. More specifically this is set up so that if a set of objects have the same
- // distance they'll be added to the topological order in the order that they are
- // referenced from the parent object.
- queue.insert (vertices_[link.objidx].modified_distance (order++),
- link.objidx);
- }
- }
-
- check_success (!queue.in_error ());
- check_success (!sorted_graph.in_error ());
- if (!check_success (new_id == -1))
- print_orphaned_nodes ();
-
- remap_all_obj_indices (id_map, &sorted_graph);
-
- hb_swap (vertices_, sorted_graph);
- sorted_graph.fini ();
- }
-
- /*
- * Assign unique space numbers to each connected subgraph of 32 bit offset(s).
- */
- bool assign_32bit_spaces ()
- {
- unsigned root_index = root_idx ();
- hb_set_t visited;
- hb_set_t roots;
- for (unsigned i = 0; i <= root_index; i++)
- {
- // Only real links can form 32 bit spaces
- for (auto& l : vertices_[i].obj.real_links)
- {
- if (l.width == 4 && !l.is_signed)
- {
- roots.add (l.objidx);
- find_subgraph (l.objidx, visited);
- }
- }
- }
-
- // Mark everything not in the subgraphs of 32 bit roots as visited.
- // This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs.
- visited.invert ();
-
- if (!roots) return false;
-
- while (roots)
- {
- unsigned next = HB_SET_VALUE_INVALID;
- if (unlikely (!check_success (!roots.in_error ()))) break;
- if (!roots.next (&next)) break;
-
- hb_set_t connected_roots;
- find_connected_nodes (next, roots, visited, connected_roots);
- if (unlikely (!check_success (!connected_roots.in_error ()))) break;
-
- isolate_subgraph (connected_roots);
- if (unlikely (!check_success (!connected_roots.in_error ()))) break;
-
- unsigned next_space = this->next_space ();
- num_roots_for_space_.push (0);
- for (unsigned root : connected_roots)
- {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space);
- vertices_[root].space = next_space;
- num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1;
- distance_invalid = true;
- positions_invalid = true;
- }
-
- // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space
- // into the 32 bit space as needed, instead of using isolation.
- }
-
-
-
- return true;
- }
-
- /*
- * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph
- * that originate from outside of the subgraph will be removed by duplicating the linked to
- * object.
- *
- * Indices stored in roots will be updated if any of the roots are duplicated to new indices.
- */
- bool isolate_subgraph (hb_set_t& roots)
- {
- update_parents ();
- hb_hashmap_t<unsigned, unsigned> subgraph;
-
- // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these
- // set the subgraph incoming edge count to match all of root_idx's incoming edges
- hb_set_t parents;
- for (unsigned root_idx : roots)
- {
- subgraph.set (root_idx, wide_parents (root_idx, parents));
- find_subgraph (root_idx, subgraph);
- }
-
- unsigned original_root_idx = root_idx ();
- hb_hashmap_t<unsigned, unsigned> index_map;
- bool made_changes = false;
- for (auto entry : subgraph.iter ())
- {
- const auto& node = vertices_[entry.first];
- unsigned subgraph_incoming_edges = entry.second;
-
- if (subgraph_incoming_edges < node.incoming_edges ())
- {
- // Only de-dup objects with incoming links from outside the subgraph.
- made_changes = true;
- duplicate_subgraph (entry.first, index_map);
- }
- }
-
- if (!made_changes)
- return false;
-
- if (original_root_idx != root_idx ()
- && parents.has (original_root_idx))
- {
- // If the root idx has changed since parents was determined, update root idx in parents
- parents.add (root_idx ());
- parents.del (original_root_idx);
- }
-
- auto new_subgraph =
- + subgraph.keys ()
- | hb_map([&] (unsigned node_idx) {
- if (index_map.has (node_idx)) return index_map[node_idx];
- return node_idx;
- })
- ;
-
- remap_obj_indices (index_map, new_subgraph);
- remap_obj_indices (index_map, parents.iter (), true);
-
- // Update roots set with new indices as needed.
- unsigned next = HB_SET_VALUE_INVALID;
- while (roots.next (&next))
- {
- if (index_map.has (next))
- {
- roots.del (next);
- roots.add (index_map[next]);
- }
- }
-
- return true;
- }
-
- void find_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& subgraph)
- {
- for (const auto& link : vertices_[node_idx].obj.all_links ())
- {
- if (subgraph.has (link.objidx))
- {
- subgraph.set (link.objidx, subgraph[link.objidx] + 1);
- continue;
- }
- subgraph.set (link.objidx, 1);
- find_subgraph (link.objidx, subgraph);
- }
- }
+struct lookup_size_t
+{
+ unsigned lookup_index;
+ size_t size;
+ unsigned num_subtables;
- void find_subgraph (unsigned node_idx, hb_set_t& subgraph)
+ static int cmp (const void* a, const void* b)
{
- if (subgraph.has (node_idx)) return;
- subgraph.add (node_idx);
- for (const auto& link : vertices_[node_idx].obj.all_links ())
- find_subgraph (link.objidx, subgraph);
+ return cmp ((const lookup_size_t*) a,
+ (const lookup_size_t*) b);
}
- /*
- * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
- * links. index_map is updated with mappings from old id to new id. If a duplication has already
- * been performed for a given index, then it will be skipped.
- */
- void duplicate_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& index_map)
+ static int cmp (const lookup_size_t* a, const lookup_size_t* b)
{
- if (index_map.has (node_idx))
- return;
-
- index_map.set (node_idx, duplicate (node_idx));
- for (const auto& l : object (node_idx).all_links ()) {
- duplicate_subgraph (l.objidx, index_map);
- }
- }
-
- /*
- * Creates a copy of node_idx and returns it's new index.
- */
- unsigned duplicate (unsigned node_idx)
- {
- positions_invalid = true;
- distance_invalid = true;
-
- auto* clone = vertices_.push ();
- auto& child = vertices_[node_idx];
- if (vertices_.in_error ()) {
- return -1;
- }
-
- clone->obj.head = child.obj.head;
- clone->obj.tail = child.obj.tail;
- clone->distance = child.distance;
- clone->space = child.space;
- clone->parents.reset ();
-
- unsigned clone_idx = vertices_.length - 2;
- for (const auto& l : child.obj.real_links)
- {
- clone->obj.real_links.push (l);
- vertices_[l.objidx].parents.push (clone_idx);
+ double subtables_per_byte_a = (double) a->num_subtables / (double) a->size;
+ double subtables_per_byte_b = (double) b->num_subtables / (double) b->size;
+ if (subtables_per_byte_a == subtables_per_byte_b) {
+ return b->lookup_index - a->lookup_index;
}
- for (const auto& l : child.obj.virtual_links)
- {
- clone->obj.virtual_links.push (l);
- vertices_[l.objidx].parents.push (clone_idx);
- }
-
- check_success (!clone->obj.real_links.in_error ());
- check_success (!clone->obj.virtual_links.in_error ());
-
- // The last object is the root of the graph, so swap back the root to the end.
- // The root's obj idx does change, however since it's root nothing else refers to it.
- // all other obj idx's will be unaffected.
- vertex_t root = vertices_[vertices_.length - 2];
- vertices_[clone_idx] = *clone;
- vertices_[vertices_.length - 1] = root;
- // Since the root moved, update the parents arrays of all children on the root.
- for (const auto& l : root.obj.all_links ())
- vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
-
- return clone_idx;
+ double cmp = subtables_per_byte_b - subtables_per_byte_a;
+ if (cmp < 0) return -1;
+ if (cmp > 0) return 1;
+ return 0;
}
+};
- /*
- * Creates a copy of child and re-assigns the link from
- * parent to the clone. The copy is a shallow copy, objects
- * linked from child are not duplicated.
- */
- bool duplicate (unsigned parent_idx, unsigned child_idx)
- {
- update_parents ();
-
- unsigned links_to_child = 0;
- for (const auto& l : vertices_[parent_idx].obj.all_links ())
- {
- if (l.objidx == child_idx) links_to_child++;
- }
-
- if (vertices_[child_idx].incoming_edges () <= links_to_child)
- {
- // Can't duplicate this node, doing so would orphan the original one as all remaining links
- // to child are from parent.
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
- parent_idx, child_idx);
+static inline
+bool _presplit_subtables_if_needed (graph::gsubgpos_graph_context_t& ext_context)
+{
+ // For each lookup this will check the size of subtables and split them as needed
+ // so that no subtable is at risk of overflowing. (where we support splitting for
+ // that subtable type).
+ //
+ // TODO(grieger): de-dup newly added nodes as necessary. Probably just want a full de-dup
+ // pass after this processing is done. Not super necessary as splits are
+ // only done where overflow is likely, so de-dup probably will get undone
+ // later anyways.
+ for (unsigned lookup_index : ext_context.lookups.keys ())
+ {
+ graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
+ if (!lookup->split_subtables_if_needed (ext_context, lookup_index))
return false;
- }
-
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
- parent_idx, child_idx);
-
- unsigned clone_idx = duplicate (child_idx);
- if (clone_idx == (unsigned) -1) return false;
- // duplicate shifts the root node idx, so if parent_idx was root update it.
- if (parent_idx == clone_idx) parent_idx++;
-
- auto& parent = vertices_[parent_idx];
- for (auto& l : parent.obj.all_links_writer ())
- {
- if (l.objidx != child_idx)
- continue;
-
- reassign_link (l, parent_idx, clone_idx);
- }
-
- return true;
- }
-
- /*
- * Raises the sorting priority of all children.
- */
- bool raise_childrens_priority (unsigned parent_idx)
- {
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d",
- 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
- // to update distances or edge counts.
- auto& parent = vertices_[parent_idx].obj;
- bool made_change = false;
- for (auto& l : parent.all_links_writer ())
- made_change |= vertices_[l.objidx].raise_priority ();
- return made_change;
}
- /*
- * Will any offsets overflow on graph when it's serialized?
- */
- bool will_overflow (hb_vector_t<overflow_record_t>* overflows = nullptr)
- {
- if (overflows) overflows->resize (0);
- update_positions ();
-
- for (int parent_idx = vertices_.length - 1; parent_idx >= 0; parent_idx--)
- {
- // Don't need to check virtual links for overflow
- for (const auto& link : vertices_[parent_idx].obj.real_links)
- {
- int64_t offset = compute_offset (parent_idx, link);
- if (is_valid_offset (offset, link))
- continue;
-
- if (!overflows) return true;
-
- overflow_record_t r;
- r.parent = parent_idx;
- r.child = link.objidx;
- overflows->push (r);
- }
- }
-
- if (!overflows) return false;
- return overflows->length;
- }
-
- void print_orphaned_nodes ()
- {
- if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
-
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
- parents_invalid = true;
- update_parents();
-
- for (unsigned i = 0; i < root_idx (); i++)
- {
- const auto& v = vertices_[i];
- if (!v.parents)
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i);
- }
- }
-
- void print_overflows (const hb_vector_t<overflow_record_t>& overflows)
- {
- if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
-
- update_parents ();
- int limit = 10;
- for (const auto& o : overflows)
- {
- if (!limit--) break;
- const auto& parent = vertices_[o.parent];
- const auto& child = vertices_[o.child];
- DEBUG_MSG (SUBSET_REPACK, nullptr,
- " overflow from "
- "%4d (%4d in, %4d out, space %2d) => "
- "%4d (%4d in, %4d out, space %2d)",
- o.parent,
- parent.incoming_edges (),
- parent.obj.real_links.length + parent.obj.virtual_links.length,
- space_for (o.parent),
- o.child,
- child.incoming_edges (),
- child.obj.real_links.length + child.obj.virtual_links.length,
- space_for (o.child));
- }
- if (overflows.length > 10) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10);
- }
- }
-
- unsigned num_roots_for_space (unsigned space) const
- {
- return num_roots_for_space_[space];
- }
-
- unsigned next_space () const
- {
- return num_roots_for_space_.length;
- }
-
- void move_to_new_space (const hb_set_t& indices)
- {
- num_roots_for_space_.push (0);
- unsigned new_space = num_roots_for_space_.length - 1;
-
- for (unsigned index : indices) {
- auto& node = vertices_[index];
- num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1;
- num_roots_for_space_[new_space] = num_roots_for_space_[new_space] + 1;
- node.space = new_space;
- distance_invalid = true;
- positions_invalid = true;
- }
- }
-
- unsigned space_for (unsigned index, unsigned* root = nullptr) const
- {
- const auto& node = vertices_[index];
- if (node.space)
- {
- if (root != nullptr)
- *root = index;
- return node.space;
- }
-
- if (!node.parents)
- {
- if (root)
- *root = index;
- return 0;
- }
-
- return space_for (node.parents[0], root);
- }
-
- void err_other_error () { this->successful = false; }
-
- private:
-
- size_t serialized_length () const {
- size_t total_size = 0;
- for (unsigned i = 0; i < vertices_.length; i++) {
- size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
- total_size += size;
- }
- return total_size;
- }
+ return true;
+}
- /*
- * Returns the numbers of incoming edges that are 32bits wide.
- */
- unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
- {
- unsigned count = 0;
+/*
+ * Analyze the lookups in a GSUB/GPOS table and decide if any should be promoted
+ * to extension lookups.
+ */
+static inline
+bool _promote_extensions_if_needed (graph::gsubgpos_graph_context_t& ext_context)
+{
+ // Simple Algorithm (v1, current):
+ // 1. Calculate how many bytes each non-extension lookup consumes.
+ // 2. Select up to 64k of those to remain as non-extension (greedy, highest subtables per byte first)
+ // 3. Promote the rest.
+ //
+ // Advanced Algorithm (v2, not implemented):
+ // 1. Perform connected component analysis using lookups as roots.
+ // 2. Compute size of each connected component.
+ // 3. Select up to 64k worth of connected components to remain as non-extensions.
+ // (greedy, highest subtables per byte first)
+ // 4. Promote the rest.
+
+ // TODO(garretrieger): support extension demotion, then consider all lookups. Requires advanced algo.
+ // TODO(garretrieger): also support extension promotion during iterative resolution phase, then
+ // we can use a less conservative threshold here.
+ // TODO(grieger): skip this for the 24 bit case.
+ if (!ext_context.lookups) return true;
+
+ hb_vector_t<lookup_size_t> lookup_sizes;
+ lookup_sizes.alloc (ext_context.lookups.get_population (), true);
+
+ for (unsigned lookup_index : ext_context.lookups.keys ())
+ {
+ const graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
hb_set_t visited;
- for (unsigned p : vertices_[node_idx].parents)
- {
- if (visited.has (p)) continue;
- visited.add (p);
-
- // Only real links can be wide
- for (const auto& l : vertices_[p].obj.real_links)
- {
- if (l.objidx == node_idx && l.width == 4 && !l.is_signed)
- {
- count++;
- parents.add (p);
- }
- }
- }
- return count;
- }
-
- bool check_success (bool success)
- { return this->successful && (success || (err_other_error (), false)); }
-
- /*
- * Creates a map from objid to # of incoming edges.
- */
- void update_parents ()
- {
- if (!parents_invalid) return;
-
- for (unsigned i = 0; i < vertices_.length; i++)
- vertices_[i].parents.reset ();
-
- for (unsigned p = 0; p < vertices_.length; p++)
- {
- for (auto& l : vertices_[p].obj.all_links ())
- {
- vertices_[l.objidx].parents.push (p);
- }
- }
-
- parents_invalid = false;
- }
-
- /*
- * compute the serialized start and end positions for each vertex.
- */
- void update_positions ()
- {
- if (!positions_invalid) return;
-
- unsigned current_pos = 0;
- for (int i = root_idx (); i >= 0; i--)
- {
- auto& v = vertices_[i];
- v.start = current_pos;
- current_pos += v.obj.tail - v.obj.head;
- v.end = current_pos;
- }
-
- positions_invalid = false;
+ lookup_sizes.push (lookup_size_t {
+ lookup_index,
+ ext_context.graph.find_subgraph_size (lookup_index, visited),
+ lookup->number_of_subtables (),
+ });
}
- /*
- * Finds the distance to each object in the graph
- * from the initial node.
- */
- void update_distances ()
- {
- if (!distance_invalid) return;
-
- // Uses Dijkstra's algorithm to find all of the shortest distances.
- // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
- //
- // Implementation Note:
- // Since our priority queue doesn't support fast priority decreases
- // we instead just add new entries into the queue when a priority changes.
- // Redundant ones are filtered out later on by the visited set.
- // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
- // for practical performance this is faster then using a more advanced queue
- // (such as a fibonacci queue) with a fast decrease priority.
- for (unsigned i = 0; i < vertices_.length; i++)
- {
- if (i == vertices_.length - 1)
- vertices_[i].distance = 0;
- else
- vertices_[i].distance = hb_int_max (int64_t);
- }
-
- hb_priority_queue_t queue;
- queue.insert (0, vertices_.length - 1);
-
- hb_vector_t<bool> visited;
- visited.resize (vertices_.length);
-
- while (!queue.in_error () && !queue.is_empty ())
- {
- unsigned next_idx = queue.pop_minimum ().second;
- if (visited[next_idx]) continue;
- const auto& next = vertices_[next_idx];
- int64_t next_distance = vertices_[next_idx].distance;
- visited[next_idx] = true;
-
- for (const auto& link : next.obj.all_links ())
- {
- if (visited[link.objidx]) continue;
-
- const auto& child = vertices_[link.objidx].obj;
- unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
- int64_t child_weight = (child.tail - child.head) +
- ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
- int64_t child_distance = next_distance + child_weight;
-
- if (child_distance < vertices_[link.objidx].distance)
- {
- vertices_[link.objidx].distance = child_distance;
- queue.insert (child_distance, link.objidx);
- }
- }
- }
+ lookup_sizes.qsort ();
- check_success (!queue.in_error ());
- if (!check_success (queue.is_empty ()))
- {
- print_orphaned_nodes ();
- return;
- }
+ size_t lookup_list_size = ext_context.graph.vertices_[ext_context.lookup_list_index].table_size ();
+ size_t l2_l3_size = lookup_list_size; // Lookup List + Lookups
+ size_t l3_l4_size = 0; // Lookups + SubTables
+ size_t l4_plus_size = 0; // SubTables + their descendants
- distance_invalid = false;
- }
-
- int64_t compute_offset (
- unsigned parent_idx,
- const hb_serialize_context_t::object_t::link_t& link) const
+ // Start by assuming all lookups are using extension subtables, this size will be removed later
+ // if it's decided to not make a lookup extension.
+ for (auto p : lookup_sizes)
{
- const auto& parent = vertices_[parent_idx];
- const auto& child = vertices_[link.objidx];
- int64_t offset = 0;
- switch ((hb_serialize_context_t::whence_t) link.whence) {
- case hb_serialize_context_t::whence_t::Head:
- offset = child.start - parent.start; break;
- case hb_serialize_context_t::whence_t::Tail:
- offset = child.start - parent.end; break;
- case hb_serialize_context_t::whence_t::Absolute:
- offset = child.start; break;
- }
-
- assert (offset >= link.bias);
- offset -= link.bias;
- return offset;
+ unsigned subtables_size = p.num_subtables * 8;
+ l3_l4_size += subtables_size;
+ l4_plus_size += subtables_size;
}
- bool is_valid_offset (int64_t offset,
- const hb_serialize_context_t::object_t::link_t& link) const
+ bool layers_full = false;
+ for (auto p : lookup_sizes)
{
- if (unlikely (!link.width))
- // Virtual links can't overflow.
- return link.is_signed || offset >= 0;
-
- if (link.is_signed)
- {
- if (link.width == 4)
- return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
- else
- return offset >= -(1 << 15) && offset < (1 << 15);
- }
- else
- {
- if (link.width == 4)
- return offset >= 0 && offset < ((int64_t) 1 << 32);
- else if (link.width == 3)
- return offset >= 0 && offset < ((int32_t) 1 << 24);
- else
- return offset >= 0 && offset < (1 << 16);
- }
- }
-
- /*
- * Updates a link in the graph to point to a different object. Corrects the
- * parents vector on the previous and new child nodes.
- */
- void reassign_link (hb_serialize_context_t::object_t::link_t& link,
- unsigned parent_idx,
- unsigned new_idx)
- {
- unsigned old_idx = link.objidx;
- link.objidx = new_idx;
- vertices_[old_idx].remove_parent (parent_idx);
- vertices_[new_idx].parents.push (parent_idx);
- }
-
- /*
- * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts.
- */
- template<typename Iterator, hb_requires (hb_is_iterator (Iterator))>
- void remap_obj_indices (const hb_hashmap_t<unsigned, unsigned>& id_map,
- Iterator subgraph,
- bool only_wide = false)
- {
- if (!id_map) return;
- for (unsigned i : subgraph)
- {
- for (auto& link : vertices_[i].obj.all_links_writer ())
- {
- if (!id_map.has (link.objidx)) continue;
- if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
-
- reassign_link (link, i, id_map[link.objidx]);
- }
- }
- }
+ const graph::Lookup* lookup = ext_context.lookups.get(p.lookup_index);
+ if (lookup->is_extension (ext_context.table_tag))
+ // already an extension so size is counted by the loop above.
+ continue;
- /*
- * Updates all objidx's in all links using the provided mapping.
- */
- void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
- hb_vector_t<vertex_t>* sorted_graph) const
- {
- for (unsigned i = 0; i < sorted_graph->length; i++)
+ if (!layers_full)
{
- (*sorted_graph)[i].remap_parents (id_map);
- for (auto& link : (*sorted_graph)[i].obj.all_links_writer ())
- {
- link.objidx = id_map[link.objidx];
- }
- }
- }
+ size_t lookup_size = ext_context.graph.vertices_[p.lookup_index].table_size ();
+ hb_set_t visited;
+ size_t subtables_size = ext_context.graph.find_subgraph_size (p.lookup_index, visited, 1) - lookup_size;
+ size_t remaining_size = p.size - subtables_size - lookup_size;
- template <typename O> void
- serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
- char* head,
- hb_serialize_context_t* c) const
- {
- OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
- *offset = 0;
- c->add_link (*offset,
- // serializer has an extra nil object at the start of the
- // object array. So all id's are +1 of what our id's are.
- link.objidx + 1,
- (hb_serialize_context_t::whence_t) link.whence,
- link.bias);
- }
-
- void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
- char* head,
- hb_serialize_context_t* c) const
- {
- switch (link.width)
- {
- case 0:
- // Virtual links aren't serialized.
- return;
- case 4:
- if (link.is_signed)
- {
- serialize_link_of_type<OT::HBINT32> (link, head, c);
- } else {
- serialize_link_of_type<OT::HBUINT32> (link, head, c);
- }
- return;
- case 2:
- if (link.is_signed)
- {
- serialize_link_of_type<OT::HBINT16> (link, head, c);
- } else {
- serialize_link_of_type<OT::HBUINT16> (link, head, c);
- }
- return;
- case 3:
- serialize_link_of_type<OT::HBUINT24> (link, head, c);
- return;
- default:
- // Unexpected link width.
- assert (0);
- }
- }
+ l2_l3_size += lookup_size;
+ l3_l4_size += lookup_size + subtables_size;
+ l3_l4_size -= p.num_subtables * 8;
+ l4_plus_size += subtables_size + remaining_size;
- /*
- * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped.
- * For this search the graph is treated as being undirected.
- *
- * Connected targets will be added to connected and removed from targets. All visited nodes
- * will be added to visited.
- */
- void find_connected_nodes (unsigned start_idx,
- hb_set_t& targets,
- hb_set_t& visited,
- hb_set_t& connected)
- {
- if (unlikely (!check_success (!visited.in_error ()))) return;
- if (visited.has (start_idx)) return;
- visited.add (start_idx);
+ if (l2_l3_size < (1 << 16)
+ && l3_l4_size < (1 << 16)
+ && l4_plus_size < (1 << 16)) continue; // this lookup fits within all layers groups
- if (targets.has (start_idx))
- {
- targets.del (start_idx);
- connected.add (start_idx);
+ layers_full = true;
}
- const auto& v = vertices_[start_idx];
-
- // Graph is treated as undirected so search children and parents of start_idx
- for (const auto& l : v.obj.all_links ())
- find_connected_nodes (l.objidx, targets, visited, connected);
-
- for (unsigned p : v.parents)
- find_connected_nodes (p, targets, visited, connected);
+ if (!ext_context.lookups.get(p.lookup_index)->make_extension (ext_context, p.lookup_index))
+ return false;
}
- public:
- // TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
- hb_vector_t<vertex_t> vertices_;
- private:
- bool parents_invalid;
- bool distance_invalid;
- bool positions_invalid;
- bool successful;
- hb_vector_t<unsigned> num_roots_for_space_;
-};
+ return true;
+}
static inline
-bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& overflows,
graph_t& sorted_graph)
{
unsigned space = 0;
@@ -1107,7 +187,7 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& ov
for (int i = overflows.length - 1; i >= 0; i--)
{
- const graph_t::overflow_record_t& r = overflows[i];
+ const graph::overflow_record_t& r = overflows[i];
unsigned root;
unsigned overflow_space = sorted_graph.space_for (r.parent, &root);
@@ -1129,14 +209,14 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& ov
// Only move at most half of the roots in a space at a time.
unsigned extra = roots_to_isolate.get_population () - maximum_to_move;
while (extra--) {
- unsigned root = HB_SET_VALUE_INVALID;
+ uint32_t root = HB_SET_VALUE_INVALID;
roots_to_isolate.previous (&root);
roots_to_isolate.del (root);
}
}
DEBUG_MSG (SUBSET_REPACK, nullptr,
- "Overflow in space %d (%d roots). Moving %d roots to space %d.",
+ "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 (),
@@ -1149,7 +229,7 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& ov
}
static inline
-bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows,
hb_set_t& priority_bumped_parents,
graph_t& sorted_graph)
{
@@ -1158,13 +238,13 @@ bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflow
// Try resolving the furthest overflows first.
for (int i = overflows.length - 1; i >= 0; i--)
{
- const graph_t::overflow_record_t& r = overflows[i];
+ const graph::overflow_record_t& r = overflows[i];
const auto& child = sorted_graph.vertices_[r.child];
if (child.is_shared ())
{
// The child object is shared, we may be able to eliminate the overflow
// by duplicating it.
- if (!sorted_graph.duplicate (r.parent, r.child)) continue;
+ if (sorted_graph.duplicate (r.parent, r.child) == (unsigned) -1) continue;
return true;
}
@@ -1196,57 +276,66 @@ bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflow
return resolution_attempted;
}
-/*
- * Attempts to modify the topological sorting of the provided object graph to
- * eliminate offset overflows in the links between objects of the graph. If a
- * non-overflowing ordering is found the updated graph is serialized it into the
- * provided serialization context.
- *
- * If necessary the structure of the graph may be modified in ways that do not
- * affect the functionality of the graph. For example shared objects may be
- * duplicated.
- *
- * For a detailed writeup describing how the algorithm operates see:
- * docs/repacker.md
- */
-template<typename T>
-inline hb_blob_t*
-hb_resolve_overflows (const T& packed,
- hb_tag_t table_tag,
- unsigned max_rounds = 20) {
- // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts
- // so try it first to save time.
- graph_t sorted_graph (packed);
- sorted_graph.sort_kahn ();
- if (!sorted_graph.will_overflow ())
+inline bool
+hb_resolve_graph_overflows (hb_tag_t table_tag,
+ unsigned max_rounds ,
+ bool recalculate_extensions,
+ graph_t& sorted_graph /* IN/OUT */)
+{
+ sorted_graph.sort_shortest_distance ();
+ if (sorted_graph.in_error ())
{
- return sorted_graph.serialize ();
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state after initial sort.");
+ return false;
}
- sorted_graph.sort_shortest_distance ();
+ bool will_overflow = graph::will_overflow (sorted_graph);
+ if (!will_overflow)
+ return true;
+ graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph);
if ((table_tag == HB_OT_TAG_GPOS
|| table_tag == HB_OT_TAG_GSUB)
- && sorted_graph.will_overflow ())
+ && will_overflow)
{
+ if (recalculate_extensions)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
+ if (!_presplit_subtables_if_needed (ext_context)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Subtable splitting failed.");
+ return false;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Promoting lookups to extensions if needed.");
+ if (!_promote_extensions_if_needed (ext_context)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Extensions promotion failed.");
+ return false;
+ }
+ }
+
DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs.");
- if (sorted_graph.assign_32bit_spaces ())
+ if (sorted_graph.assign_spaces ())
sorted_graph.sort_shortest_distance ();
+ else
+ sorted_graph.sort_shortest_distance_if_needed ();
}
unsigned round = 0;
- hb_vector_t<graph_t::overflow_record_t> overflows;
+ hb_vector_t<graph::overflow_record_t> overflows;
// TODO(garretrieger): select a good limit for max rounds.
while (!sorted_graph.in_error ()
- && sorted_graph.will_overflow (&overflows)
- && round++ < max_rounds) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %d ===", round);
- sorted_graph.print_overflows (overflows);
+ && graph::will_overflow (sorted_graph, &overflows)
+ && round < max_rounds) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %u ===", round);
+ print_overflows (sorted_graph, overflows);
hb_set_t priority_bumped_parents;
if (!_try_isolating_subgraphs (overflows, sorted_graph))
{
+ // Don't count space isolation towards round limit. Only increment
+ // round counter if space isolation made no changes.
+ round++;
if (!_process_overflows (overflows, priority_bumped_parents, sorted_graph))
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :(");
@@ -1260,16 +349,62 @@ hb_resolve_overflows (const T& packed,
if (sorted_graph.in_error ())
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "Sorted graph in error state.");
- return nullptr;
+ return false;
}
- if (sorted_graph.will_overflow ())
+ if (graph::will_overflow (sorted_graph))
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Attempts to modify the topological sorting of the provided object graph to
+ * eliminate offset overflows in the links between objects of the graph. If a
+ * non-overflowing ordering is found the updated graph is serialized it into the
+ * provided serialization context.
+ *
+ * If necessary the structure of the graph may be modified in ways that do not
+ * affect the functionality of the graph. For example shared objects may be
+ * duplicated.
+ *
+ * For a detailed writeup describing how the algorithm operates see:
+ * docs/repacker.md
+ */
+template<typename T>
+inline hb_blob_t*
+hb_resolve_overflows (const T& packed,
+ hb_tag_t table_tag,
+ unsigned max_rounds = 20,
+ bool recalculate_extensions = false) {
+ graph_t sorted_graph (packed);
+ if (sorted_graph.in_error ())
+ {
+ // Invalid graph definition.
return nullptr;
}
- return sorted_graph.serialize ();
+ if (!sorted_graph.is_fully_connected ())
+ {
+ sorted_graph.print_orphaned_nodes ();
+ return nullptr;
+ }
+
+ if (sorted_graph.in_error ())
+ {
+ // Allocations failed somewhere
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Graph is in error, likely due to a memory allocation error.");
+ return nullptr;
+ }
+
+ if (!hb_resolve_graph_overflows (table_tag, max_rounds, recalculate_extensions, sorted_graph))
+ return nullptr;
+
+ return graph::serialize (sorted_graph);
}
#endif /* HB_REPACKER_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
index 65c2772201..eb907c6b2a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
@@ -198,10 +198,11 @@ struct hb_sanitize_context_t :
void start_processing ()
{
reset_object ();
- if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR)))
+ unsigned m;
+ if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR, &m)))
this->max_ops = HB_SANITIZE_MAX_OPS_MAX;
else
- this->max_ops = hb_clamp ((unsigned) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+ this->max_ops = hb_clamp (m,
(unsigned) HB_SANITIZE_MAX_OPS_MIN,
(unsigned) HB_SANITIZE_MAX_OPS_MAX);
this->edit_count = 0;
@@ -239,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");
@@ -252,8 +253,9 @@ struct hb_sanitize_context_t :
unsigned int a,
unsigned int b) const
{
- return !hb_unsigned_mul_overflows (a, b) &&
- this->check_range (base, a * b);
+ unsigned m;
+ return !hb_unsigned_mul_overflows (a, b, &m) &&
+ this->check_range (base, m);
}
template <typename T>
@@ -262,8 +264,9 @@ struct hb_sanitize_context_t :
unsigned int b,
unsigned int c) const
{
- return !hb_unsigned_mul_overflows (a, b) &&
- this->check_range (base, a * b, c);
+ unsigned m;
+ return !hb_unsigned_mul_overflows (a, b, &m) &&
+ this->check_range (base, m, c);
}
template <typename T>
@@ -305,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,
@@ -350,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 40895a4548..61ec0253a0 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh
@@ -74,23 +74,32 @@ struct hb_serialize_context_t
}
object_t () = default;
-
+
#ifdef HB_EXPERIMENTAL_API
object_t (const hb_object_t &o)
{
head = o.head;
tail = o.tail;
next = nullptr;
- real_links.alloc (o.num_real_links);
+ 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]);
}
#endif
+ friend void swap (object_t& a, object_t& b)
+ {
+ hb_swap (a.head, b.head);
+ hb_swap (a.tail, b.tail);
+ hb_swap (a.next, b.next);
+ hb_swap (a.real_links, b.real_links);
+ hb_swap (a.virtual_links, b.virtual_links);
+ }
+
bool operator == (const object_t &o) const
{
// Virtual links aren't considered for equality since they don't affect the functionality
@@ -111,10 +120,10 @@ struct hb_serialize_context_t
struct link_t
{
unsigned width: 3;
- bool is_signed: 1;
+ unsigned is_signed: 1;
unsigned whence: 2;
- unsigned position: 28;
- unsigned bias;
+ unsigned bias : 26;
+ unsigned position;
objidx_t objidx;
link_t () = default;
@@ -130,6 +139,14 @@ struct hb_serialize_context_t
objidx = o.objidx;
}
#endif
+
+ HB_INTERNAL static int cmp (const void* a, const void* b)
+ {
+ int cmp = ((const link_t*)a)->position - ((const link_t*)b)->position;
+ if (cmp) return cmp;
+
+ return ((const link_t*)a)->objidx - ((const link_t*)b)->objidx;
+ }
};
char *head;
@@ -177,7 +194,6 @@ struct hb_serialize_context_t
current = current->next;
_->fini ();
}
- object_pool.fini ();
}
bool in_error () const { return bool (errors); }
@@ -207,6 +223,7 @@ struct hb_serialize_context_t
this->errors = HB_SERIALIZE_ERROR_NONE;
this->head = this->start;
this->tail = this->end;
+ this->zerocopy = nullptr;
this->debug_depth = 0;
fini ();
@@ -306,10 +323,11 @@ struct hb_serialize_context_t
{
object_t *obj = current;
if (unlikely (!obj)) return;
- if (unlikely (in_error())) return;
+ if (unlikely (in_error() && !only_overflow ())) return;
current = current->next;
- revert (obj->head, obj->tail);
+ revert (zerocopy ? zerocopy : obj->head, obj->tail);
+ zerocopy = nullptr;
obj->fini ();
object_pool.release (obj);
}
@@ -327,8 +345,11 @@ struct hb_serialize_context_t
current = current->next;
obj->tail = head;
obj->next = nullptr;
+ assert (obj->head <= obj->tail);
unsigned len = obj->tail - obj->head;
- head = obj->head; /* Rewind head. */
+ head = zerocopy ? zerocopy : obj->head; /* Rewind head. */
+ bool was_zerocopy = zerocopy;
+ zerocopy = nullptr;
if (!len)
{
@@ -338,9 +359,11 @@ struct hb_serialize_context_t
}
objidx_t objidx;
+ uint32_t hash = 0;
if (share)
{
- objidx = packed_map.get (obj);
+ hash = hb_hash (obj);
+ objidx = packed_map.get_with_hash (obj, hash);
if (objidx)
{
merge_virtual_links (obj, objidx);
@@ -350,7 +373,10 @@ struct hb_serialize_context_t
}
tail -= len;
- memmove (tail, obj->head, len);
+ if (was_zerocopy)
+ assert (tail == obj->head);
+ else
+ memmove (tail, obj->head, len);
obj->head = tail;
obj->tail = tail + len;
@@ -368,7 +394,7 @@ struct hb_serialize_context_t
objidx = packed.length - 1;
- if (share) packed_map.set (obj, objidx);
+ if (share) packed_map.set_with_hash (obj, hash, objidx);
propagate_error (packed_map);
return objidx;
@@ -552,8 +578,26 @@ struct hb_serialize_context_t
return !bool ((errors = (errors | err_type)));
}
+ bool start_zerocopy (size_t size)
+ {
+ if (unlikely (in_error ())) return false;
+
+ if (unlikely (size > INT_MAX || this->tail - this->head < ptrdiff_t (size)))
+ {
+ err (HB_SERIALIZE_ERROR_OUT_OF_ROOM);
+ return false;
+ }
+
+ assert (!this->zerocopy);
+ this->zerocopy = this->head;
+
+ assert (this->current->head == this->head);
+ this->current->head = this->current->tail = this->head = this->tail - size;
+ return true;
+ }
+
template <typename Type>
- Type *allocate_size (size_t size)
+ Type *allocate_size (size_t size, bool clear = true)
{
if (unlikely (in_error ())) return nullptr;
@@ -562,7 +606,8 @@ struct hb_serialize_context_t
err (HB_SERIALIZE_ERROR_OUT_OF_ROOM);
return nullptr;
}
- hb_memset (this->head, 0, size);
+ if (clear)
+ hb_memset (this->head, 0, size);
char *ret = this->head;
this->head += size;
return reinterpret_cast<Type *> (ret);
@@ -576,14 +621,21 @@ struct hb_serialize_context_t
Type *embed (const Type *obj)
{
unsigned int size = obj->get_size ();
- Type *ret = this->allocate_size<Type> (size);
+ Type *ret = this->allocate_size<Type> (size, false);
if (unlikely (!ret)) return nullptr;
- memcpy (ret, obj, size);
+ hb_memcpy (ret, obj, size);
return ret;
}
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
@@ -599,7 +651,7 @@ struct hb_serialize_context_t
}
/* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data
- * instead of memcpy(). */
+ * instead of hb_memcpy(). */
template <typename Type, typename ...Ts>
Type *copy (const Type &src, Ts&&... ds)
{ return _copy (src, hb_prioritize, std::forward<Ts> (ds)...); }
@@ -617,7 +669,7 @@ struct hb_serialize_context_t
hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; }
template <typename Type>
- Type *extend_size (Type *obj, size_t size)
+ Type *extend_size (Type *obj, size_t size, bool clear = true)
{
if (unlikely (in_error ())) return nullptr;
@@ -625,12 +677,12 @@ struct hb_serialize_context_t
assert ((char *) obj <= this->head);
assert ((size_t) (this->head - (char *) obj) <= size);
if (unlikely (((char *) obj + size < (char *) obj) ||
- !this->allocate_size<Type> (((char *) obj) + size - this->head))) return nullptr;
+ !this->allocate_size<Type> (((char *) obj) + size - this->head, clear))) return nullptr;
return reinterpret_cast<Type *> (obj);
}
template <typename Type>
- Type *extend_size (Type &obj, size_t size)
- { return extend_size (std::addressof (obj), size); }
+ Type *extend_size (Type &obj, size_t size, bool clear = true)
+ { return extend_size (std::addressof (obj), size, clear); }
template <typename Type>
Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); }
@@ -659,8 +711,8 @@ struct hb_serialize_context_t
char *p = (char *) hb_malloc (len);
if (unlikely (!p)) return hb_bytes_t ();
- memcpy (p, this->start, this->head - this->start);
- memcpy (p + (this->head - this->start), this->tail, this->end - this->tail);
+ hb_memcpy (p, this->start, this->head - this->start);
+ hb_memcpy (p + (this->head - this->start), this->tail, this->end - this->tail);
return hb_bytes_t (p, len);
}
template <typename Type>
@@ -686,8 +738,8 @@ struct hb_serialize_context_t
check_assign (off, offset, HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
}
- public: /* TODO Make private. */
- char *start, *head, *tail, *end;
+ public:
+ char *start, *head, *tail, *end, *zerocopy;
unsigned int debug_depth;
hb_serialize_error_t errors;
@@ -710,9 +762,7 @@ struct hb_serialize_context_t
hb_vector_t<object_t *> packed;
/* Map view of packed objects. */
- hb_hashmap_t<const object_t *, objidx_t,
- const object_t *, objidx_t,
- nullptr, 0> packed_map;
+ hb_hashmap_t<const object_t *, objidx_t> packed_map;
};
#endif /* HB_SERIALIZE_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh
index 7d4979b73b..e8409111f2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set-digest.hh
@@ -28,9 +28,10 @@
#define HB_SET_DIGEST_HH
#include "hb.hh"
+#include "hb-machinery.hh"
/*
- * The set digests here implement various "filters" that support
+ * The set-digests here implement various "filters" that support
* "approximate member query". Conceptually these are like Bloom
* Filter and Quotient Filter, however, much smaller, faster, and
* designed to fit the requirements of our uses for glyph coverage
@@ -40,13 +41,25 @@
* set of glyphs, but fully flooded and ineffective if coverage is
* all over the place.
*
- * The frozen-set can be used instead of a digest, to trade more
- * memory for 100% accuracy, but in practice, that doesn't look like
- * an attractive trade-off.
+ * The way these are used is that the filter is first populated by
+ * a lookup's or subtable's Coverage table(s), and then when we
+ * want to apply the lookup or subtable to a glyph, before trying
+ * to apply, we ask the filter if the glyph may be covered. If it's
+ * not, we return early.
+ *
+ * We use these filters both at the lookup-level, and then again,
+ * at the subtable-level. Both have performance win.
+ *
+ * The main filter we use is a combination of three bits-pattern
+ * filters. A bits-pattern filter checks a number of bits (5 or 6)
+ * of the input number (glyph-id in this case) and checks whether
+ * its pattern is amongst the patterns of any of the accepted values.
+ * The accepted patterns are represented as a "long" integer. The
+ * check is done using four bitwise operations only.
*/
template <typename mask_t, unsigned int shift>
-struct hb_set_digest_lowest_bits_t
+struct hb_set_digest_bits_pattern_t
{
static constexpr unsigned mask_bytes = sizeof (mask_t);
static constexpr unsigned mask_bits = sizeof (mask_t) * 8;
@@ -63,6 +76,8 @@ struct hb_set_digest_lowest_bits_t
void init () { mask = 0; }
+ void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; }
+
void add (hb_codepoint_t g) { mask |= mask_for (g); }
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
@@ -83,7 +98,7 @@ struct hb_set_digest_lowest_bits_t
for (unsigned int i = 0; i < count; i++)
{
add (*array);
- array = (const T *) (stride + (const char *) array);
+ array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);
}
}
template <typename T>
@@ -91,18 +106,17 @@ struct hb_set_digest_lowest_bits_t
template <typename T>
bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
- for (unsigned int i = 0; i < count; i++)
- {
- add (*array);
- array = (const T *) (stride + (const char *) array);
- }
+ add_array (array, count, stride);
return true;
}
template <typename T>
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
+ bool may_have (const hb_set_digest_bits_pattern_t &o) const
+ { return mask & o.mask; }
+
bool may_have (hb_codepoint_t g) const
- { return !!(mask & mask_for (g)); }
+ { return mask & mask_for (g); }
private:
@@ -120,6 +134,12 @@ struct hb_set_digest_combiner_t
tail.init ();
}
+ void add (const hb_set_digest_combiner_t &o)
+ {
+ head.add (o.head);
+ tail.add (o.tail);
+ }
+
void add (hb_codepoint_t g)
{
head.add (g);
@@ -128,9 +148,8 @@ struct hb_set_digest_combiner_t
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
{
- head.add_range (a, b);
- tail.add_range (a, b);
- return true;
+ return head.add_range (a, b) &&
+ tail.add_range (a, b);
}
template <typename T>
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
@@ -143,13 +162,17 @@ struct hb_set_digest_combiner_t
template <typename T>
bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
- head.add_sorted_array (array, count, stride);
- tail.add_sorted_array (array, count, stride);
- return true;
+ return head.add_sorted_array (array, count, stride) &&
+ tail.add_sorted_array (array, count, stride);
}
template <typename T>
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
+ bool may_have (const hb_set_digest_combiner_t &o) const
+ {
+ return head.may_have (o.head) && tail.may_have (o.tail);
+ }
+
bool may_have (hb_codepoint_t g) const
{
return head.may_have (g) && tail.may_have (g);
@@ -171,11 +194,11 @@ struct hb_set_digest_combiner_t
using hb_set_digest_t =
hb_set_digest_combiner_t
<
- hb_set_digest_lowest_bits_t<unsigned long, 4>,
+ hb_set_digest_bits_pattern_t<unsigned long, 4>,
hb_set_digest_combiner_t
<
- hb_set_digest_lowest_bits_t<unsigned long, 0>,
- hb_set_digest_lowest_bits_t<unsigned long, 9>
+ hb_set_digest_bits_pattern_t<unsigned long, 0>,
+ hb_set_digest_bits_pattern_t<unsigned long, 9>
>
>
;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.cc b/src/3rdparty/harfbuzz-ng/src/hb-set.cc
index 0e2c1f77ef..97caddb226 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.cc
@@ -40,7 +40,7 @@
/**
- * hb_set_create: (Xconstructor)
+ * hb_set_create:
*
* Creates a new, initially empty set.
*
@@ -56,8 +56,6 @@ hb_set_create ()
if (!(set = hb_object_create<hb_set_t> ()))
return hb_set_get_empty ();
- set->init_shallow ();
-
return set;
}
@@ -107,8 +105,6 @@ hb_set_destroy (hb_set_t *set)
{
if (!hb_object_destroy (set)) return;
- set->fini_shallow ();
-
hb_free (set);
}
@@ -122,7 +118,7 @@ hb_set_destroy (hb_set_t *set)
*
* Attaches a user-data key/data pair to the specified set.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -149,7 +145,7 @@ hb_set_set_user_data (hb_set_t *set,
* Since: 0.9.2
**/
void *
-hb_set_get_user_data (hb_set_t *set,
+hb_set_get_user_data (const hb_set_t *set,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (set, key);
@@ -162,7 +158,7 @@ hb_set_get_user_data (hb_set_t *set,
*
* Tests whether memory allocation for a set was successful.
*
- * Return value: %true if allocation succeeded, %false otherwise
+ * Return value: `true` if allocation succeeded, `false` otherwise
*
* Since: 0.9.2
**/
@@ -178,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
**/
@@ -186,6 +182,9 @@ hb_set_t *
hb_set_copy (const hb_set_t *set)
{
hb_set_t *copy = hb_set_create ();
+ if (unlikely (copy->in_error ()))
+ return hb_set_get_empty ();
+
copy->set (*set);
return copy;
}
@@ -211,7 +210,7 @@ hb_set_clear (hb_set_t *set)
*
* Tests whether a set is empty (contains no elements).
*
- * Return value: %true if @set is empty
+ * Return value: `true` if @set is empty
*
* Since: 0.9.7
**/
@@ -228,7 +227,7 @@ hb_set_is_empty (const hb_set_t *set)
*
* Tests whether @codepoint belongs to @set.
*
- * Return value: %true if @codepoint is in @set, %false otherwise
+ * Return value: `true` if @codepoint is in @set, `false` otherwise
*
* Since: 0.9.2
**/
@@ -347,7 +346,7 @@ hb_set_del_range (hb_set_t *set,
* Tests whether @set and @other are equal (contain the same
* elements).
*
- * Return value: %true if the two sets are equal, %false otherwise.
+ * Return value: `true` if the two sets are equal, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -359,13 +358,30 @@ hb_set_is_equal (const hb_set_t *set,
}
/**
+ * hb_set_hash:
+ * @set: A set
+ *
+ * Creates a hash representing @set.
+ *
+ * Return value:
+ * A hash of @set.
+ *
+ * Since: 4.4.0
+ **/
+HB_EXTERN unsigned int
+hb_set_hash (const hb_set_t *set)
+{
+ return set->hash ();
+}
+
+/**
* hb_set_is_subset:
* @set: A set
* @larger_set: Another set
*
* Tests whether @set is a subset of @larger_set.
*
- * Return value: %true if the @set is a subset of (or equal to) @larger_set, %false otherwise.
+ * Return value: `true` if the @set is a subset of (or equal to) @larger_set, `false` otherwise.
*
* Since: 1.8.1
**/
@@ -478,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
*
@@ -535,7 +567,7 @@ hb_set_get_max (const hb_set_t *set)
*
* Set @codepoint to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a next value, %false otherwise
+ * Return value: `true` if there was a next value, `false` otherwise
*
* Since: 0.9.2
**/
@@ -556,7 +588,7 @@ hb_set_next (const hb_set_t *set,
*
* Set @codepoint to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a previous value, %false otherwise
+ * Return value: `true` if there was a previous value, `false` otherwise
*
* Since: 1.8.0
**/
@@ -579,7 +611,7 @@ hb_set_previous (const hb_set_t *set,
*
* Set @last to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a next range, %false otherwise
+ * Return value: `true` if there was a next range, `false` otherwise
*
* Since: 0.9.7
**/
@@ -603,7 +635,7 @@ hb_set_next_range (const hb_set_t *set,
*
* Set @first to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a previous range, %false otherwise
+ * Return value: `true` if there was a previous range, `false` otherwise
*
* Since: 1.8.0
**/
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.h b/src/3rdparty/harfbuzz-ng/src/hb-set.h
index 10ce7c10d4..de53231030 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.h
@@ -77,7 +77,7 @@ hb_set_set_user_data (hb_set_t *set,
hb_bool_t replace);
HB_EXTERN void *
-hb_set_get_user_data (hb_set_t *set,
+hb_set_get_user_data (const hb_set_t *set,
hb_user_data_key_t *key);
@@ -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);
@@ -128,6 +131,9 @@ HB_EXTERN hb_bool_t
hb_set_is_equal (const hb_set_t *set,
const hb_set_t *other);
+HB_EXTERN unsigned int
+hb_set_hash (const hb_set_t *set);
+
HB_EXTERN hb_bool_t
hb_set_is_subset (const hb_set_t *set,
const hb_set_t *larger_set);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-set.hh
index 1f05407869..604802381b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-set.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-set.hh
@@ -43,8 +43,8 @@ struct hb_sparseset_t
hb_sparseset_t (const hb_sparseset_t& other) : hb_sparseset_t () { set (other); }
hb_sparseset_t (hb_sparseset_t&& other) : hb_sparseset_t () { s = std::move (other.s); }
- hb_sparseset_t& operator= (const hb_sparseset_t& other) { set (other); return *this; }
- hb_sparseset_t& operator= (hb_sparseset_t&& other) { hb_swap (*this, other); return *this; }
+ hb_sparseset_t& operator = (const hb_sparseset_t& other) { set (other); return *this; }
+ hb_sparseset_t& operator = (hb_sparseset_t&& other) { s = std::move (other.s); return *this; }
friend void swap (hb_sparseset_t& a, hb_sparseset_t& b) { hb_swap (a.s, b.s); }
hb_sparseset_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t ()
@@ -53,23 +53,21 @@ struct hb_sparseset_t
add (item);
}
template <typename Iterable,
- hb_requires (hb_is_iterable (Iterable))>
+ hb_requires (hb_is_iterable (Iterable))>
hb_sparseset_t (const Iterable &o) : hb_sparseset_t ()
{
hb_copy (o, *this);
}
- void init_shallow () { s.init (); }
void init ()
{
hb_object_init (this);
- init_shallow ();
+ s.init ();
}
- void fini_shallow () { s.fini (); }
void fini ()
{
hb_object_fini (this);
- fini_shallow ();
+ s.fini ();
}
explicit operator bool () const { return !is_empty (); }
@@ -77,10 +75,13 @@ struct hb_sparseset_t
void err () { s.err (); }
bool in_error () const { return s.in_error (); }
+ void alloc (unsigned sz) { s.alloc (sz); }
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 (); }
void add (hb_codepoint_t g) { s.add (g); }
bool add_range (hb_codepoint_t a, hb_codepoint_t b) { return s.add_range (a, b); }
@@ -105,10 +106,8 @@ struct hb_sparseset_t
bool get (hb_codepoint_t g) const { return s.get (g); }
/* Has interface. */
- static constexpr bool SENTINEL = false;
- typedef bool value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ bool operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k]; }
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
@@ -125,6 +124,8 @@ struct hb_sparseset_t
void set (const hb_sparseset_t &other) { s.set (other.s); }
bool is_equal (const hb_sparseset_t &other) const { return s.is_equal (other.s); }
+ bool operator == (const hb_set_t &other) const { return is_equal (other); }
+ bool operator != (const hb_set_t &other) const { return !is_equal (other); }
bool is_subset (const hb_sparseset_t &larger_set) const { return s.is_subset (larger_set.s); }
@@ -158,15 +159,23 @@ struct hb_sparseset_t
struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t>
{
- hb_set_t () = default;
+ using sparseset = hb_sparseset_t<hb_bit_set_invertible_t>;
+
~hb_set_t () = default;
- hb_set_t (hb_set_t&) = default;
- hb_set_t& operator= (const hb_set_t&) = default;
- hb_set_t& operator= (hb_set_t&&) = default;
- hb_set_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t<hb_bit_set_invertible_t> (lst) {}
+ hb_set_t () : sparseset () {};
+ hb_set_t (const hb_set_t &o) : sparseset ((sparseset &) o) {};
+ hb_set_t (hb_set_t&& o) : sparseset (std::move ((sparseset &) o)) {}
+ hb_set_t& operator = (const hb_set_t&) = default;
+ hb_set_t& operator = (hb_set_t&&) = default;
+ hb_set_t (std::initializer_list<hb_codepoint_t> lst) : sparseset (lst) {}
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
- hb_set_t (const Iterable &o) : hb_sparseset_t<hb_bit_set_invertible_t> (o) {}
+ 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 66332165c3..312eeb653e 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc
@@ -31,6 +31,8 @@
#include "hb-buffer.hh"
+#ifndef HB_NO_SHAPER
+
/**
* SECTION:hb-shape-plan
* @title: hb-shape-plan
@@ -74,7 +76,7 @@ hb_shape_plan_key_t::init (bool copy,
this->user_features = copy ? features : user_features;
if (copy && num_user_features)
{
- memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+ hb_memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
/* Make start/end uniform to easier catch bugs. */
for (unsigned int i = 0; i < num_user_features; i++)
{
@@ -117,7 +119,7 @@ hb_shape_plan_key_t::init (bool copy,
}
else
{
- const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+ const HB_UNUSED hb_shaper_entry_t *shapers = _hb_shapers_get ();
for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
if (false)
;
@@ -170,7 +172,7 @@ hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other)
/**
- * hb_shape_plan_create: (Xconstructor)
+ * hb_shape_plan_create:
* @face: #hb_face_t to use
* @props: The #hb_segment_properties_t of the segment
* @user_features: (array length=num_user_features): The list of user-selected features
@@ -198,7 +200,7 @@ hb_shape_plan_create (hb_face_t *face,
}
/**
- * hb_shape_plan_create2: (Xconstructor)
+ * hb_shape_plan_create2:
* @face: #hb_face_t to use
* @props: The #hb_segment_properties_t of the segment
* @user_features: (array length=num_user_features): The list of user-selected features
@@ -225,13 +227,14 @@ 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,
shaper_list);
- assert (props->direction != HB_DIRECTION_INVALID);
+ if (unlikely (props->direction == HB_DIRECTION_INVALID))
+ return hb_shape_plan_get_empty ();
hb_shape_plan_t *shape_plan;
@@ -317,10 +320,6 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
{
if (!hb_object_destroy (shape_plan)) return;
-#ifndef HB_NO_OT_SHAPE
- shape_plan->ot.fini ();
-#endif
- shape_plan->key.fini ();
hb_free (shape_plan);
}
@@ -334,7 +333,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
*
* Attaches a user-data key/data pair to the given shaping plan.
*
- * Return value: %true if success, %false otherwise.
+ * Return value: `true` if success, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -361,8 +360,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
* Since: 0.9.7
**/
void *
-hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
- hb_user_data_key_t *key)
+hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan,
+ hb_user_data_key_t *key)
{
return hb_object_get_user_data (shape_plan, key);
}
@@ -392,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);
@@ -439,7 +438,7 @@ _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan,
* Executes the given shaping plan on the specified buffer, using
* the given @font and @features.
*
- * Return value: %true if success, %false otherwise.
+ * Return value: `true` if success, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -521,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);
@@ -577,3 +576,6 @@ retry:
return hb_shape_plan_reference (shape_plan);
}
+
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.h b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.h
index fc7c041899..aaf5cf9c45 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.h
@@ -102,8 +102,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
hb_bool_t replace);
HB_EXTERN void *
-hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
- hb_user_data_key_t *key);
+hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan,
+ hb_user_data_key_t *key);
HB_EXTERN hb_bool_t
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.hh b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.hh
index 8cb4ddb927..6fc73939b3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.hh
@@ -55,7 +55,7 @@ struct hb_shape_plan_key_t
unsigned int num_coords,
const char * const *shaper_list);
- HB_INTERNAL void fini () { hb_free ((void *) user_features); }
+ HB_INTERNAL void fini () { hb_free ((void *) user_features); user_features = nullptr; }
HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other);
@@ -64,6 +64,7 @@ struct hb_shape_plan_key_t
struct hb_shape_plan_t
{
+ ~hb_shape_plan_t () { key.fini (); }
hb_object_header_t header;
hb_face_t *face_unsafe; /* We don't carry a reference to face. */
hb_shape_plan_key_t key;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
index 3407e1af42..7b5bf2c5ef 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
@@ -35,6 +35,8 @@
#include "hb-machinery.hh"
+#ifndef HB_NO_SHAPER
+
/**
* SECTION:hb-shape
* @title: hb-shape
@@ -50,7 +52,7 @@
static inline void free_static_shaper_list ();
-static const char *nil_shaper_list[] = {nullptr};
+static const char * const nil_shaper_list[] = {nullptr};
static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
hb_shaper_list_lazy_loader_t>
@@ -73,7 +75,7 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
}
static void destroy (const char **l)
{ hb_free (l); }
- static const char ** get_null ()
+ static const char * const * get_null ()
{ return nil_shaper_list; }
} static_shaper_list;
@@ -106,12 +108,12 @@ hb_shape_list_shapers ()
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
* @features: (array length=num_features) (nullable): an array of user
- * specified #hb_feature_t or %NULL
+ * specified #hb_feature_t or `NULL`
* @num_features: the length of @features array
- * @shaper_list: (array zero-terminated=1) (nullable): a %NULL-terminated
- * array of shapers to use or %NULL
+ * @shaper_list: (array zero-terminated=1) (nullable): a `NULL`-terminated
+ * array of shapers to use or `NULL`
*
- * See hb_shape() for details. If @shaper_list is not %NULL, the specified
+ * See hb_shape() for details. If @shaper_list is not `NULL`, the specified
* shapers will be used in the given order, otherwise the default shapers list
* will be used.
*
@@ -126,6 +128,11 @@ hb_shape_full (hb_font_t *font,
unsigned int num_features,
const char * const *shaper_list)
{
+ if (unlikely (!buffer->len))
+ return true;
+
+ buffer->enter ();
+
hb_buffer_t *text_buffer = nullptr;
if (buffer->flags & HB_BUFFER_FLAG_VERIFY)
{
@@ -137,12 +144,19 @@ hb_shape_full (hb_font_t *font,
features, num_features,
font->coords, font->num_coords,
shaper_list);
+
hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
+
+ if (buffer->max_ops <= 0)
+ buffer->shaping_failed = true;
+
hb_shape_plan_destroy (shape_plan);
if (text_buffer)
{
- if (res && !buffer->verify (text_buffer,
+ if (res && buffer->successful && !buffer->shaping_failed
+ && text_buffer->successful
+ && !buffer->verify (text_buffer,
font,
features,
num_features,
@@ -151,6 +165,8 @@ hb_shape_full (hb_font_t *font,
hb_buffer_destroy (text_buffer);
}
+ buffer->leave ();
+
return res;
}
@@ -159,11 +175,11 @@ hb_shape_full (hb_font_t *font,
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
* @features: (array length=num_features) (nullable): an array of user
- * specified #hb_feature_t or %NULL
+ * specified #hb_feature_t or `NULL`
* @num_features: the length of @features array
*
* Shapes @buffer using @font turning its Unicode characters content to
- * positioned glyphs. If @features is not %NULL, it will be used to control the
+ * positioned glyphs. If @features is not `NULL`, it will be used to control the
* features applied during shaping. If two @features have the same tag but
* overlapping ranges the value of the feature with the higher index takes
* precedence.
@@ -178,3 +194,6 @@ hb_shape (hb_font_t *font,
{
hb_shape_full (font, buffer, features, num_features, nullptr);
}
+
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shaper.cc b/src/3rdparty/harfbuzz-ng/src/hb-shaper.cc
index a11ed83afd..c4885cda94 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-shaper.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-shaper.cc
@@ -29,18 +29,18 @@
#include "hb-machinery.hh"
-static const hb_shaper_entry_t all_shapers[] = {
+static const hb_shaper_entry_t _hb_all_shapers[] = {
#define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape},
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
};
#ifndef HB_NO_SHAPER
-static_assert (0 != ARRAY_LENGTH_CONST (all_shapers), "No shaper enabled.");
+static_assert (0 != ARRAY_LENGTH_CONST (_hb_all_shapers), "No shaper enabled.");
#endif
static inline void free_static_shapers ();
-static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_t,
+static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<hb_shaper_entry_t,
hb_shapers_lazy_loader_t>
{
static hb_shaper_entry_t *create ()
@@ -49,11 +49,11 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
if (!env || !*env)
return nullptr;
- hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) hb_calloc (1, sizeof (all_shapers));
+ hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) hb_calloc (1, sizeof (_hb_all_shapers));
if (unlikely (!shapers))
return nullptr;
- memcpy (shapers, all_shapers, sizeof (all_shapers));
+ hb_memcpy (shapers, _hb_all_shapers, sizeof (_hb_all_shapers));
/* Reorder shaper list to prefer requested shapers. */
unsigned int i = 0;
@@ -64,7 +64,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
if (!end)
end = p + strlen (p);
- for (unsigned int j = i; j < ARRAY_LENGTH (all_shapers); j++)
+ for (unsigned int j = i; j < ARRAY_LENGTH_CONST (_hb_all_shapers); j++)
if (end - p == (int) strlen (shapers[j].name) &&
0 == strncmp (shapers[j].name, p, end - p))
{
@@ -85,8 +85,8 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
return shapers;
}
- static void destroy (const hb_shaper_entry_t *p) { hb_free ((void *) p); }
- static const hb_shaper_entry_t *get_null () { return all_shapers; }
+ static void destroy (hb_shaper_entry_t *p) { hb_free (p); }
+ static const hb_shaper_entry_t *get_null () { return _hb_all_shapers; }
} static_shapers;
static inline
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-static.cc b/src/3rdparty/harfbuzz-ng/src/hb-static.cc
index 7cc51be611..5f647c6ad9 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-static.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-static.cc
@@ -33,12 +33,12 @@
#include "hb-aat-layout-feat-table.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-cmap-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)] = {};
@@ -46,17 +46,20 @@ uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof
DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF};
DEFINE_NULL_NAMESPACE_BYTES (OT, VarIdx) = {0xFF,0xFF,0xFF,0xFF};
DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
-DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x01};
+DEFINE_NULL_NAMESPACE_BYTES (OT, ClipRecord) = {0x01};
DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
-/* Hand-coded because Lookup is a template. Sad. */
-const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
+DEFINE_NULL_NAMESPACE_BYTES (AAT, Lookup) = {0xFF,0xFF};
+/* hb_map_t */
+
+const hb_codepoint_t minus_1 = -1;
/* hb_face_t */
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
static inline unsigned
load_num_glyphs_from_loca (const hb_face_t *face)
{
@@ -86,13 +89,13 @@ hb_face_t::load_num_glyphs () const
{
unsigned ret = 0;
-#ifndef HB_NO_BORING_EXPANSION
+#ifndef HB_NO_BEYOND_64K
ret = hb_max (ret, load_num_glyphs_from_loca (this));
#endif
ret = hb_max (ret, load_num_glyphs_from_maxp (this));
- num_glyphs.set_relaxed (ret);
+ num_glyphs = ret;
return ret;
}
@@ -100,41 +103,9 @@ unsigned int
hb_face_t::load_upem () const
{
unsigned int ret = table.head->get_upem ();
- upem.set_relaxed (ret);
+ upem = ret;
return ret;
}
-/* hb_user_data_array_t */
-
-bool
-hb_user_data_array_t::set (hb_user_data_key_t *key,
- void * data,
- hb_destroy_func_t destroy,
- hb_bool_t replace)
-{
- if (!key)
- return false;
-
- if (replace) {
- if (!data && !destroy) {
- items.remove (key, lock);
- return true;
- }
- }
- hb_user_data_item_t item = {key, data, destroy};
- bool ret = !!items.replace_or_insert (item, lock, (bool) replace);
-
- return ret;
-}
-
-void *
-hb_user_data_array_t::get (hb_user_data_key_t *key)
-{
- hb_user_data_item_t item = {nullptr, nullptr, nullptr};
-
- return items.find (key, &item, lock) ? item.data : nullptr;
-}
-
-
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh
new file mode 100644
index 0000000000..e523c25820
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-accelerator.hh
@@ -0,0 +1,132 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef HB_SUBSET_ACCELERATOR_HH
+#define HB_SUBSET_ACCELERATOR_HH
+
+
+#include "hb.hh"
+
+#include "hb-map.hh"
+#include "hb-multimap.hh"
+#include "hb-set.hh"
+
+extern HB_INTERNAL hb_user_data_key_t _hb_subset_accelerator_user_data_key;
+
+namespace CFF {
+struct cff_subset_accelerator_t;
+}
+
+namespace OT {
+struct SubtableUnicodesCache;
+};
+
+struct hb_subset_accelerator_t
+{
+ static hb_user_data_key_t* user_data_key()
+ {
+ return &_hb_subset_accelerator_user_data_key;
+ }
+
+ static hb_subset_accelerator_t* create(const hb_map_t& unicode_to_gid_,
+ const hb_multimap_t gid_to_unicodes_,
+ const hb_set_t& unicodes_,
+ bool has_seac_) {
+ hb_subset_accelerator_t* accel =
+ (hb_subset_accelerator_t*) hb_calloc (1, sizeof(hb_subset_accelerator_t));
+
+ new (accel) hb_subset_accelerator_t (unicode_to_gid_,
+ gid_to_unicodes_,
+ unicodes_,
+ has_seac_);
+
+ return accel;
+ }
+
+ static void destroy (void* p)
+ {
+ if (!p) return;
+
+ 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_,
+ 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 ()
+ {
+ 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
+
+ mutable hb_mutex_t sanitized_table_cache_lock;
+ mutable hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>> sanitized_table_cache;
+
+ const hb_map_t unicode_to_gid;
+ const hb_multimap_t gid_to_unicodes;
+ const hb_set_t unicodes;
+
+ // cmap
+ const OT::SubtableUnicodesCache* cmap_cache;
+ hb_destroy_func_t destroy_cmap_cache;
+
+ // CFF
+ bool has_seac;
+ const CFF::cff_subset_accelerator_t* cff_accelerator;
+ hb_destroy_func_t destroy_cff_accelerator;
+
+ // TODO(garretrieger): cumulative glyf checksum map
+
+ bool in_error () const
+ {
+ return unicode_to_gid.in_error () ||
+ gid_to_unicodes.in_error () ||
+ unicodes.in_error () ||
+ sanitized_table_cache.in_error ();
+ }
+};
+
+
+#endif /* HB_SUBSET_ACCELERATOR_HH */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc
index 711b2236d6..6e1b6f713d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.cc
@@ -66,8 +66,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
{
/* use hb_set to determine the subset of font dicts */
- hb_set_t *set = hb_set_create ();
- if (unlikely (set == &Null (hb_set_t))) return false;
+ hb_set_t set;
hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
{
@@ -79,7 +78,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
glyph = i;
}
fd = src.get_fd (glyph);
- set->add (fd);
+ set.add (fd);
if (fd != prev_fd)
{
@@ -90,12 +89,11 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
}
}
- subset_fd_count = set->get_population ();
+ subset_fd_count = set.get_population ();
if (subset_fd_count == fdCount)
{
/* all font dicts belong to the subset. no need to subset FDSelect & FDArray */
fdmap.identity (fdCount);
- hb_set_destroy (set);
}
else
{
@@ -103,9 +101,8 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
fdmap.reset ();
hb_codepoint_t fd = CFF_UNDEF_CODE;
- while (set->next (&fd))
+ while (set.next (&fd))
fdmap.add (fd);
- hb_set_destroy (set);
if (unlikely (fdmap.get_population () != subset_fd_count))
return false;
}
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 18657705fa..ff50b0e518 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff-common.hh
@@ -38,14 +38,16 @@ namespace CFF {
struct str_encoder_t
{
str_encoder_t (str_buff_t &buff_)
- : buff (buff_), error (false) {}
+ : buff (buff_) {}
- void reset () { buff.resize (0); }
+ void reset () { buff.reset (); }
void encode_byte (unsigned char b)
{
- if (unlikely (buff.push (b) == &Crap (unsigned char)))
- set_error ();
+ if (likely ((signed) buff.length < buff.allocated))
+ buff.arrayZ[buff.length++] = b;
+ else
+ buff.push (b);
}
void encode_int (int v)
@@ -79,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 ())
{
@@ -96,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))
@@ -107,29 +195,18 @@ struct str_encoder_t
encode_byte (op);
}
- void copy_str (const byte_str_t &str)
+ void copy_str (const unsigned char *str, unsigned length)
{
- unsigned int offset = buff.length;
- if (unlikely (!buff.resize (offset + str.length)))
- {
- set_error ();
- return;
- }
- if (unlikely (buff.length < offset + str.length))
- {
- set_error ();
- return;
- }
- memcpy (&buff[offset], &str[0], str.length);
+ assert ((signed) (buff.length + length) <= buff.allocated);
+ hb_memcpy (buff.arrayZ + buff.length, str, length);
+ buff.length += length;
}
- bool is_error () const { return error; }
+ bool in_error () const { return buff.in_error (); }
protected:
- void set_error () { error = true; }
str_buff_t &buff;
- bool error;
};
struct cff_sub_table_info_t {
@@ -188,47 +265,22 @@ struct cff_font_dict_op_serializer_t : op_serializer_t
}
else
{
- HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+ unsigned char *d = c->allocate_size<unsigned char> (opstr.length);
if (unlikely (!d)) return_trace (false);
- memcpy (d, &opstr.str[0], opstr.str.length);
+ /* Faster than hb_memcpy for small strings. */
+ for (unsigned i = 0; i < opstr.length; i++)
+ d[i] = opstr.ptr[i];
+ //hb_memcpy (d, opstr.ptr, opstr.length);
}
return_trace (true);
}
};
-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>
@@ -240,11 +292,10 @@ struct subr_flattener_t
bool flatten (str_buff_vec_t &flat_charstrings)
{
- if (!flat_charstrings.resize (plan->num_output_glyphs ()))
+ unsigned count = plan->num_output_glyphs ();
+ if (!flat_charstrings.resize_exact (count))
return false;
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
- flat_charstrings[i].init ();
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+ for (unsigned int i = 0; i < count; i++)
{
hb_codepoint_t glyph;
if (!plan->old_gid_for_new_gid (i, &glyph))
@@ -253,15 +304,19 @@ struct subr_flattener_t
if (endchar_op != OpCode_Invalid) flat_charstrings[i].push (endchar_op);
continue;
}
- const byte_str_t str = (*acc.charStrings)[glyph];
+ const hb_ubytes_t str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- cs_interpreter_t<ENV, OPSET, flatten_param_t> interp;
- interp.env.init (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[i],
- (bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ flat_charstrings.arrayZ[i],
+ (bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING),
+ plan
};
if (unlikely (!interp.interpret (param)))
return false;
@@ -275,11 +330,9 @@ struct subr_flattener_t
struct subr_closures_t
{
- subr_closures_t (unsigned int fd_count) : valid (false), global_closure (), local_closures ()
+ subr_closures_t (unsigned int fd_count) : global_closure (), local_closures ()
{
- valid = true;
- if (!local_closures.resize (fd_count))
- valid = false;
+ local_closures.resize_exact (fd_count);
}
void reset ()
@@ -289,47 +342,38 @@ struct subr_closures_t
local_closures[i].clear();
}
- bool is_valid () const { return valid; }
- bool valid;
+ bool in_error () const { return local_closures.in_error (); }
hb_set_t global_closure;
hb_vector_t<hb_set_t> local_closures;
};
struct parsed_cs_op_t : op_str_t
{
- void init (unsigned int subr_num_ = 0)
- {
- subr_num = subr_num_;
- drop_flag = false;
- keep_flag = false;
- skip_flag = false;
- }
+ parsed_cs_op_t (unsigned int subr_num_ = 0) :
+ subr_num (subr_num_) {}
- bool for_drop () const { return drop_flag; }
- void set_drop () { if (!for_keep ()) drop_flag = true; }
+ bool is_hinting () const { return hinting_flag; }
+ void set_hinting () { hinting_flag = true; }
- bool for_keep () const { return keep_flag; }
- void set_keep () { keep_flag = true; }
-
- bool for_skip () const { return skip_flag; }
- void set_skip () { skip_flag = true; }
-
- unsigned int subr_num;
+ /* The layout of this struct is designed to fit within the
+ * padding of op_str_t! */
protected:
- bool drop_flag : 1;
- bool keep_flag : 1;
- bool skip_flag : 1;
+ bool hinting_flag = false;
+
+ public:
+ uint16_t subr_num;
};
struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
{
- void init ()
+ parsed_cs_str_t () :
+ parsed (false),
+ hint_dropped (false),
+ has_prefix_ (false),
+ has_calls_ (false)
{
SUPER::init ();
- parsed = false;
- hint_dropped = false;
- has_prefix_ = false;
}
void add_op (op_code_t op, const byte_str_ref_t& str_ref)
@@ -342,13 +386,12 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
{
if (!is_parsed ())
{
- unsigned int parsed_len = get_count ();
- if (likely (parsed_len > 0))
- values[parsed_len-1].set_skip ();
+ has_calls_ = true;
+
+ /* Pop the subroutine number. */
+ values.pop ();
- parsed_cs_op_t val;
- val.init (subr_num);
- SUPER::add_op (op, str_ref, val);
+ SUPER::add_op (op, str_ref, {subr_num});
}
}
@@ -378,11 +421,43 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
op_code_t prefix_op () const { return prefix_op_; }
const number_t &prefix_num () const { return prefix_num_; }
+ 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;
- bool hint_dropped;
- bool vsindex_dropped;
- bool has_prefix_;
+ bool parsed : 1;
+ bool hint_dropped : 1;
+ bool vsindex_dropped : 1;
+ bool has_prefix_ : 1;
+ bool has_calls_ : 1;
op_code_t prefix_op_;
number_t prefix_num_;
@@ -396,22 +471,75 @@ struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
typedef hb_vector_t<parsed_cs_str_t> SUPER;
};
-struct subr_subset_param_t
+struct cff_subset_accelerator_t
{
- void init (parsed_cs_str_t *parsed_charstring_,
- parsed_cs_str_vec_t *parsed_global_subrs_, parsed_cs_str_vec_t *parsed_local_subrs_,
- hb_set_t *global_closure_, hb_set_t *local_closure_,
- bool drop_hints_)
+ static cff_subset_accelerator_t* create (
+ hb_blob_t* original_blob,
+ const parsed_cs_str_vec_t& parsed_charstrings,
+ const parsed_cs_str_vec_t& parsed_global_subrs,
+ const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs) {
+ cff_subset_accelerator_t* accel =
+ (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t));
+ new (accel) cff_subset_accelerator_t (original_blob,
+ parsed_charstrings,
+ parsed_global_subrs,
+ parsed_local_subrs);
+ return accel;
+ }
+
+ static void destroy (void* value) {
+ if (!value) return;
+
+ cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) value;
+ accel->~cff_subset_accelerator_t ();
+ hb_free (accel);
+ }
+
+ cff_subset_accelerator_t(
+ hb_blob_t* original_blob_,
+ const parsed_cs_str_vec_t& parsed_charstrings_,
+ const parsed_cs_str_vec_t& parsed_global_subrs_,
+ const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs_)
{
- parsed_charstring = parsed_charstring_;
- current_parsed_str = parsed_charstring;
+ parsed_charstrings = parsed_charstrings_;
parsed_global_subrs = parsed_global_subrs_;
parsed_local_subrs = parsed_local_subrs_;
- global_closure = global_closure_;
- local_closure = local_closure_;
- drop_hints = drop_hints_;
+
+ // the parsed charstrings point to memory in the original CFF table so we must hold a reference
+ // to it to keep the memory valid.
+ original_blob = hb_blob_reference (original_blob_);
+ }
+
+ ~cff_subset_accelerator_t() {
+ hb_blob_destroy (original_blob);
+ hb_map_destroy (glyph_to_sid_map.get_relaxed ());
}
+ parsed_cs_str_vec_t parsed_charstrings;
+ parsed_cs_str_vec_t parsed_global_subrs;
+ hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
+ mutable hb_atomic_ptr_t<hb_map_t> glyph_to_sid_map = nullptr;
+
+ private:
+ hb_blob_t* original_blob;
+};
+
+struct subr_subset_param_t
+{
+ subr_subset_param_t (parsed_cs_str_t *parsed_charstring_,
+ parsed_cs_str_vec_t *parsed_global_subrs_,
+ parsed_cs_str_vec_t *parsed_local_subrs_,
+ hb_set_t *global_closure_,
+ hb_set_t *local_closure_,
+ bool drop_hints_) :
+ current_parsed_str (parsed_charstring_),
+ parsed_charstring (parsed_charstring_),
+ parsed_global_subrs (parsed_global_subrs_),
+ parsed_local_subrs (parsed_local_subrs_),
+ global_closure (global_closure_),
+ local_closure (local_closure_),
+ drop_hints (drop_hints_) {}
+
parsed_cs_str_t *get_parsed_str_for_context (call_context_t &context)
{
switch (context.type)
@@ -447,7 +575,11 @@ struct subr_subset_param_t
if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
env.set_error ();
else
+ {
+ if (!parsed_str->is_parsed ())
+ parsed_str->alloc (env.str_ref.total_size ());
current_parsed_str = parsed_str;
+ }
}
parsed_cs_str_t *current_parsed_str;
@@ -468,6 +600,7 @@ struct subr_remap_t : hb_inc_bimap_t
* no optimization based on usage counts. fonttools doesn't appear doing that either.
*/
+ resize (closure->get_population ());
hb_codepoint_t old_num = HB_SET_VALUE_INVALID;
while (hb_set_next (closure, &old_num))
add (old_num);
@@ -506,7 +639,7 @@ struct subr_remaps_t
{
global_remap.create (&closures.global_closure);
for (unsigned int i = 0; i < local_remaps.length; i++)
- local_remaps[i].create (&closures.local_closures[i]);
+ local_remaps.arrayZ[i].create (&closures.local_closures[i]);
}
subr_remap_t global_remap;
@@ -517,7 +650,8 @@ template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typena
struct subr_subsetter_t
{
subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_)
- : acc (acc_), plan (plan_), closures(acc_.fdCount), remaps(acc_.fdCount)
+ : acc (acc_), plan (plan_), closures(acc_.fdCount),
+ remaps(acc_.fdCount)
{}
/* Subroutine subsetting with --no-desubroutinize runs in phases:
@@ -536,68 +670,94 @@ struct subr_subsetter_t
*/
bool subset (void)
{
- parsed_charstrings.resize (plan->num_output_glyphs ());
- parsed_global_subrs.resize (acc.globalSubrs->count);
-
- if (unlikely (remaps.in_error()
- || parsed_charstrings.in_error ()
- || parsed_global_subrs.in_error ())) {
- return false;
+ unsigned fd_count = acc.fdCount;
+ const cff_subset_accelerator_t* cff_accelerator = nullptr;
+ if (plan->accelerator && plan->accelerator->cff_accelerator) {
+ cff_accelerator = plan->accelerator->cff_accelerator;
+ fd_count = cff_accelerator->parsed_local_subrs.length;
}
- if (unlikely (!parsed_local_subrs.resize (acc.fdCount))) return false;
+ 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_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_exact (plan->num_output_glyphs ());
+ parsed_global_subrs_storage.resize_exact (acc.globalSubrs->count);
- for (unsigned int i = 0; i < acc.fdCount; i++)
- {
- parsed_local_subrs[i].resize (acc.privateDicts[i].localSubrs->count);
- if (unlikely (parsed_local_subrs[i].in_error ())) return false;
+ if (unlikely (!parsed_local_subrs_storage.resize (fd_count))) return false;
+
+ for (unsigned int i = 0; i < acc.fdCount; i++)
+ {
+ unsigned count = acc.privateDicts[i].localSubrs->count;
+ parsed_local_subrs_storage[i].resize (count);
+ if (unlikely (parsed_local_subrs_storage[i].in_error ())) return false;
+ }
+
+ parsed_global_subrs = &parsed_global_subrs_storage;
+ parsed_local_subrs = &parsed_local_subrs_storage;
}
- if (unlikely (!closures.valid))
+
+ if (unlikely (remaps.in_error()
+ || cached_charstrings.in_error ()
+ || parsed_charstrings.in_error ()
+ || parsed_global_subrs->in_error ()
+ || closures.in_error ())) {
return false;
+ }
/* phase 1 & 2 */
for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
{
hb_codepoint_t glyph;
if (!plan->old_gid_for_new_gid (i, &glyph))
- continue;
- const byte_str_t str = (*acc.charStrings)[glyph];
+ continue;
+
+ const hb_ubytes_t str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
- return false;
+ return false;
- cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp;
- interp.env.init (str, acc, fd);
+ if (cff_accelerator)
+ {
+ // parsed string already exists in accelerator, copy it and move
+ // on.
+ if (cached_charstrings)
+ cached_charstrings[i] = &cff_accelerator->parsed_charstrings[glyph];
+ else
+ parsed_charstrings[i] = cff_accelerator->parsed_charstrings[glyph];
+
+ continue;
+ }
- subr_subset_param_t param;
- param.init (&parsed_charstrings[i],
- &parsed_global_subrs, &parsed_local_subrs[fd],
- &closures.global_closure, &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ ENV env (str, acc, fd);
+ cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env);
+
+ parsed_charstrings[i].alloc (str.length);
+ subr_subset_param_t param (&parsed_charstrings[i],
+ &parsed_global_subrs_storage,
+ &parsed_local_subrs_storage[fd],
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
if (unlikely (!interp.interpret (param)))
- return false;
+ return false;
/* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
- }
- if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- {
/* 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;
- param.init (&parsed_charstrings[i],
- &parsed_global_subrs, &parsed_local_subrs[fd],
- &closures.global_closure, &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ subr_subset_param_t param (&parsed_charstrings[i],
+ &parsed_global_subrs_storage,
+ &parsed_local_subrs_storage[fd],
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
drop_hints_param_t drop;
if (drop_hints_in_str (parsed_charstrings[i], param, drop))
@@ -608,33 +768,36 @@ struct subr_subsetter_t
}
}
- /* after dropping hints recreate closures of actually used subrs */
- closures.reset ();
- for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
- {
- 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;
- param.init (&parsed_charstrings[i],
- &parsed_global_subrs, &parsed_local_subrs[fd],
- &closures.global_closure, &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
- collect_subr_refs_in_str (parsed_charstrings[i], param);
- }
+ /* 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++)
{
@@ -642,13 +805,13 @@ struct subr_subsetter_t
if (!plan->old_gid_for_new_gid (i, &glyph))
{
/* add an endchar only charstring for a missing glyph if CFF1 */
- if (endchar_op != OpCode_Invalid) buffArray[i].push (endchar_op);
+ if (endchar_op != OpCode_Invalid) buffArray.arrayZ[i].push (endchar_op);
continue;
}
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
+ if (unlikely (!encode_str (get_parsed_charstring (i), fd, buffArray.arrayZ[i], encode_prefix)))
return false;
}
return true;
@@ -658,28 +821,27 @@ 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 old_num = 0; old_num < subrs.length; old_num++)
+ for (unsigned int new_num = 0; new_num < count; new_num++)
{
- hb_codepoint_t new_num = remap[old_num];
- if (new_num != CFF_UNDEF_CODE)
- {
- if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
- return false;
- }
+ hb_codepoint_t old_num = remap.backward (new_num);
+ assert (old_num != CFF_UNDEF_CODE);
+
+ if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
+ return false;
}
return true;
}
bool encode_globalsubrs (str_buff_vec_t &buffArray)
{
- return encode_subrs (parsed_global_subrs, remaps.global_remap, 0, buffArray);
+ return encode_subrs (*parsed_global_subrs, remaps.global_remap, 0, buffArray);
}
bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const
{
- return encode_subrs (parsed_local_subrs[fd], remaps.local_remaps[fd], fd, buffArray);
+ return encode_subrs ((*parsed_local_subrs)[fd], remaps.local_remaps[fd], fd, buffArray);
}
protected:
@@ -708,7 +870,7 @@ struct subr_subsetter_t
* then this entire subroutine must be a hint. drop its call. */
if (drop.ends_in_hint)
{
- str.values[pos].set_drop ();
+ str.values[pos].set_hinting ();
/* if this subr call is at the end of the parent subr, propagate the flag
* otherwise reset the flag */
if (!str.at_end (pos))
@@ -716,7 +878,7 @@ struct subr_subsetter_t
}
else if (drop.all_dropped)
{
- str.values[pos].set_drop ();
+ str.values[pos].set_hinting ();
}
return has_hint;
@@ -727,20 +889,22 @@ struct subr_subsetter_t
{
bool seen_hint = false;
- for (unsigned int pos = 0; pos < str.values.length; pos++)
+ unsigned count = str.values.length;
+ auto *values = str.values.arrayZ;
+ for (unsigned int pos = 0; pos < count; pos++)
{
bool has_hint = false;
- switch (str.values[pos].op)
+ switch (values[pos].op)
{
case OpCode_callsubr:
has_hint = drop_hints_in_subr (str, pos,
- *param.parsed_local_subrs, str.values[pos].subr_num,
+ *param.parsed_local_subrs, values[pos].subr_num,
param, drop);
break;
case OpCode_callgsubr:
has_hint = drop_hints_in_subr (str, pos,
- *param.parsed_global_subrs, str.values[pos].subr_num,
+ *param.parsed_global_subrs, values[pos].subr_num,
param, drop);
break;
@@ -754,7 +918,7 @@ struct subr_subsetter_t
case OpCode_cntrmask:
if (drop.seen_moveto)
{
- str.values[pos].set_drop ();
+ values[pos].set_hinting ();
break;
}
HB_FALLTHROUGH;
@@ -764,13 +928,13 @@ struct subr_subsetter_t
case OpCode_hstem:
case OpCode_vstem:
has_hint = true;
- str.values[pos].set_drop ();
+ values[pos].set_hinting ();
if (str.at_end (pos))
drop.ends_in_hint = true;
break;
case OpCode_dotsection:
- str.values[pos].set_drop ();
+ values[pos].set_hinting ();
break;
default:
@@ -781,10 +945,10 @@ struct subr_subsetter_t
{
for (int i = pos - 1; i >= 0; i--)
{
- parsed_cs_op_t &csop = str.values[(unsigned)i];
- if (csop.for_drop ())
+ parsed_cs_op_t &csop = values[(unsigned)i];
+ if (csop.is_hinting ())
break;
- csop.set_drop ();
+ csop.set_hinting ();
if (csop.op == OpCode_vsindexcs)
drop.vsindex_dropped = true;
}
@@ -797,12 +961,12 @@ struct subr_subsetter_t
* only (usually one) hintmask operator, then calls to this subr can be dropped.
*/
drop.all_dropped = true;
- for (unsigned int pos = 0; pos < str.values.length; pos++)
+ for (unsigned int pos = 0; pos < count; pos++)
{
- parsed_cs_op_t &csop = str.values[pos];
+ parsed_cs_op_t &csop = values[pos];
if (csop.op == OpCode_return)
break;
- if (!csop.for_drop ())
+ if (!csop.is_hinting ())
{
drop.all_dropped = false;
break;
@@ -812,32 +976,62 @@ struct subr_subsetter_t
return seen_hint;
}
- void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos,
- unsigned int subr_num, parsed_cs_str_vec_t &subrs,
+ bool closure_subroutines (const parsed_cs_str_vec_t& global_subrs,
+ const hb_vector_t<parsed_cs_str_vec_t>& local_subrs)
+ {
+ closures.reset ();
+ for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
+ {
+ 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;
+
+ // Note: const cast is safe here because the collect_subr_refs_in_str only performs a
+ // closure and does not modify any of the charstrings.
+ subr_subset_param_t param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (i)),
+ const_cast<parsed_cs_str_vec_t*> (&global_subrs),
+ const_cast<parsed_cs_str_vec_t*> (&local_subrs[fd]),
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ collect_subr_refs_in_str (get_parsed_charstring (i), param);
+ }
+
+ return true;
+ }
+
+ void collect_subr_refs_in_subr (unsigned int subr_num, parsed_cs_str_vec_t &subrs,
hb_set_t *closure,
const subr_subset_param_t &param)
{
+ if (closure->has (subr_num))
+ return;
closure->add (subr_num);
collect_subr_refs_in_str (subrs[subr_num], param);
}
- void collect_subr_refs_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param)
+ void collect_subr_refs_in_str (const parsed_cs_str_t &str,
+ const subr_subset_param_t &param)
{
- for (unsigned int pos = 0; pos < str.values.length; pos++)
+ if (!str.has_calls ())
+ return;
+
+ for (auto &opstr : str.values)
{
- if (!str.values[pos].for_drop ())
+ if (!param.drop_hints || !opstr.is_hinting ())
{
- switch (str.values[pos].op)
+ switch (opstr.op)
{
case OpCode_callsubr:
- collect_subr_refs_in_subr (str, pos,
- str.values[pos].subr_num, *param.parsed_local_subrs,
+ collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_local_subrs,
param.local_closure, param);
break;
case OpCode_callgsubr:
- collect_subr_refs_in_subr (str, pos,
- str.values[pos].subr_num, *param.parsed_global_subrs,
+ collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_global_subrs,
param.global_closure, param);
break;
@@ -847,43 +1041,84 @@ 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
{
- buff.init ();
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 () && 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 ());
}
- for (unsigned int i = 0; i < str.get_count(); i++)
+
+ unsigned size = 0;
+ for (auto &opstr : str.values)
+ {
+ size += opstr.length;
+ if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr)
+ size += 3;
+ }
+ if (!buff.alloc (buff.length + size, true))
+ return false;
+
+ for (auto &opstr : str.values)
{
- const parsed_cs_op_t &opstr = str.values[i];
- if (!opstr.for_drop () && !opstr.for_skip ())
+ if (hinting || !opstr.is_hinting ())
{
switch (opstr.op)
{
case OpCode_callsubr:
encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num));
- encoder.encode_op (OpCode_callsubr);
+ encoder.copy_str (opstr.ptr, opstr.length);
break;
case OpCode_callgsubr:
encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num));
- encoder.encode_op (OpCode_callgsubr);
+ encoder.copy_str (opstr.ptr, opstr.length);
break;
default:
- encoder.copy_str (opstr.str);
+ encoder.copy_str (opstr.ptr, opstr.length);
break;
}
}
}
- return !encoder.is_error ();
+ return !encoder.in_error ();
+ }
+
+ void compact_parsed_subrs () const
+ {
+ for (auto &cs : parsed_global_subrs_storage)
+ cs.compact ();
+ for (auto &vec : parsed_local_subrs_storage)
+ for (auto &cs : vec)
+ cs.compact ();
+ }
+
+ void populate_subset_accelerator () const
+ {
+ if (!plan->inprogress_accelerator) return;
+
+ compact_parsed_subrs ();
+
+ plan->inprogress_accelerator->cff_accelerator =
+ cff_subset_accelerator_t::create(acc.blob,
+ parsed_charstrings,
+ parsed_global_subrs_storage,
+ parsed_local_subrs_storage);
+ plan->inprogress_accelerator->destroy_cff_accelerator =
+ cff_subset_accelerator_t::destroy;
+
+ }
+
+ const parsed_cs_str_t& get_parsed_charstring (unsigned i) const
+ {
+ if (cached_charstrings) return *(cached_charstrings[i]);
+ return parsed_charstrings[i];
}
protected:
@@ -892,13 +1127,17 @@ struct subr_subsetter_t
subr_closures_t closures;
- parsed_cs_str_vec_t parsed_charstrings;
- parsed_cs_str_vec_t parsed_global_subrs;
- hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
+ hb_vector_t<const parsed_cs_str_t*> cached_charstrings;
+ const parsed_cs_str_vec_t* parsed_global_subrs;
+ const hb_vector_t<parsed_cs_str_vec_t>* parsed_local_subrs;
subr_remaps_t remaps;
private:
+
+ parsed_cs_str_vec_t parsed_charstrings;
+ parsed_cs_str_vec_t parsed_global_subrs_storage;
+ hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs_storage;
typedef typename SUBRS::count_type subr_count_type;
};
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
index 35fecd67bc..1d7ed6444a 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
@@ -167,9 +167,10 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
* for supplement, the original byte string is copied along with the op code */
op_str_t supp_op;
supp_op.op = op;
- if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
+ if ( unlikely (!(opstr.length >= opstr.last_arg_offset + 3)))
return_trace (false);
- supp_op.str = byte_str_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+ supp_op.ptr = opstr.ptr + opstr.last_arg_offset;
+ supp_op.length = opstr.length - opstr.last_arg_offset;
return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
copy_opstr (c, supp_op));
@@ -233,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);
}
@@ -247,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)
@@ -270,13 +271,13 @@ struct range_list_t : hb_vector_t<code_pair_t>
/* replace the first glyph ID in the "glyph" field each range with a nLeft value */
bool complete (unsigned int last_glyph)
{
- bool two_byte = false;
- for (unsigned int i = (*this).length; i > 0; i--)
+ bool two_byte = false;
+ unsigned count = this->length;
+ for (unsigned int i = count; i; i--)
{
- code_pair_t &pair = (*this)[i - 1];
- unsigned int nLeft = last_glyph - pair.glyph - 1;
- if (nLeft >= 0x100)
- two_byte = true;
+ code_pair_t &pair = arrayZ[i - 1];
+ unsigned int nLeft = last_glyph - pair.glyph - 1;
+ two_byte |= nLeft >= 0x100;
last_glyph = pair.glyph;
pair.glyph = nLeft;
}
@@ -334,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_)
@@ -442,6 +473,18 @@ struct cff_subset_plan {
return;
}
+ hb_map_t *glyph_to_sid_map = (plan->accelerator && plan->accelerator->cff_accelerator) ?
+ plan->accelerator->cff_accelerator->glyph_to_sid_map :
+ nullptr;
+ bool created_map = false;
+ if (!glyph_to_sid_map &&
+ ((plan->accelerator && plan->accelerator->cff_accelerator) ||
+ plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.))
+ {
+ created_map = true;
+ glyph_to_sid_map = acc.create_glyph_to_sid_map ();
+ }
+
unsigned int glyph;
for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
{
@@ -451,7 +494,7 @@ struct cff_subset_plan {
/* Retain the SID for the old missing glyph ID */
old_glyph = glyph;
}
- sid = acc.glyph_to_sid (old_glyph);
+ sid = glyph_to_sid_map ? glyph_to_sid_map->get (old_glyph) : acc.glyph_to_sid (old_glyph);
if (!acc.is_CID ())
sid = sidmap.add (sid);
@@ -464,6 +507,13 @@ struct cff_subset_plan {
last_sid = sid;
}
+ if (created_map)
+ {
+ if (!(plan->accelerator && plan->accelerator->cff_accelerator) ||
+ !plan->accelerator->cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map))
+ hb_map_destroy (glyph_to_sid_map);
+ }
+
bool two_byte = subset_charset_ranges.complete (glyph);
size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1);
@@ -701,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)))
{
@@ -722,11 +772,17 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
/* CharStrings */
{
+ c->push<CFF1CharStrings> ();
+
+ unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings);
+ if (unlikely (!c->start_zerocopy (total_size)))
+ return false;
+
CFF1CharStrings *cs = c->start_embed<CFF1CharStrings> ();
if (unlikely (!cs)) return false;
- c->push ();
+
if (likely (cs->serialize (c, plan.subset_charstrings)))
- plan.info.char_strings_link = c->pop_pack ();
+ plan.info.char_strings_link = c->pop_pack (false);
else
{
c->pop_discard ();
@@ -809,7 +865,7 @@ static bool _serialize_cff1 (hb_serialize_context_t *c,
CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
if (unlikely (!dest)) return false;
if (likely (dest->serialize (c, plan.subset_globalsubrs)))
- c->pop_pack ();
+ c->pop_pack (false);
else
{
c->pop_discard ();
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff2.cc
index 92dd6b1d2c..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));
@@ -67,9 +70,9 @@ struct cff2_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<>
}
};
-struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t>
+struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t, blend_arg_t>
{
- static void flush_args_and_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flush_args_and_op (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
switch (op)
{
@@ -97,7 +100,7 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
}
}
- static void flush_args (cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flush_args (cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
for (unsigned int i = 0; i < env.argStack.get_count ();)
{
@@ -115,14 +118,14 @@ 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++;
}
}
SUPER::flush_args (env, param);
}
- static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
/* flatten the default values */
str_encoder_t encoder (param.flatStr);
@@ -135,21 +138,21 @@ 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);
encoder.encode_op (OpCode_blendcs);
}
- static void flush_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flush_op (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
switch (op)
{
@@ -162,14 +165,25 @@ 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> SUPER;
- typedef cs_opset_t<blend_arg_t, cff2_cs_opset_flatten_t, cff2_cs_opset_flatten_t, cff2_cs_interp_env_t, flatten_param_t> CSOPSET;
+ 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;
};
-struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t>
+struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t, blend_arg_t>
{
- static void process_op (op_code_t op, cff2_cs_interp_env_t &env, subr_subset_param_t& param)
+ static void process_op (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, subr_subset_param_t& param)
{
switch (op) {
@@ -201,7 +215,7 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t
protected:
static void process_call_subr (op_code_t op, cs_type_t type,
- cff2_cs_interp_env_t &env, subr_subset_param_t& param,
+ cff2_cs_interp_env_t<blend_arg_t> &env, subr_subset_param_t& param,
cff2_biased_subrs_t& subrs, hb_set_t *closure)
{
byte_str_ref_t str_ref = env.str_ref;
@@ -212,15 +226,15 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t
}
private:
- typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
+ typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t, blend_arg_t> SUPER;
};
-struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_subr_subset_t>
+struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t<blend_arg_t>, cff2_cs_opset_subr_subset_t>
{
cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
: subr_subsetter_t (acc_, plan_) {}
- static void complete_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+ static void complete_parsed_str (cff2_cs_interp_env_t<blend_arg_t> &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
{
/* vsindex is inserted at the beginning of the charstring as necessary */
if (env.seen_vsindex ())
@@ -232,20 +246,198 @@ 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)
{
/* Flatten global & local subrs */
- subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_flatten_t>
+ subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t<blend_arg_t>, cff2_cs_opset_flatten_t>
flattener(acc, plan);
if (!flattener.flatten (subset_charstrings))
return false;
@@ -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;
@@ -334,7 +528,7 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
if (unlikely (!dest)) return false;
c->push ();
if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
- subrs_link = c->pop_pack ();
+ subrs_link = c->pop_pack (false);
else
{
c->pop_discard ();
@@ -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];
@@ -361,11 +556,17 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
/* CharStrings */
{
+ c->push ();
+
+ unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings);
+ if (unlikely (!c->start_zerocopy (total_size)))
+ return false;
+
CFF2CharStrings *cs = c->start_embed<CFF2CharStrings> ();
if (unlikely (!cs)) return false;
- c->push ();
+
if (likely (cs->serialize (c, plan.subset_charstrings)))
- plan.info.char_strings_link = c->pop_pack ();
+ plan.info.char_strings_link = c->pop_pack (false);
else
{
c->pop_discard ();
@@ -377,9 +578,10 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
if (acc.fdSelect != &Null (CFF2FDSelect))
{
c->push ();
- if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect, plan.orig_fdcount,
- plan.subset_fdselect_format, plan.subset_fdselect_size,
- plan.subset_fdselect_ranges)))
+ if (likely (hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect,
+ plan.orig_fdcount,
+ plan.subset_fdselect_format, plan.subset_fdselect_size,
+ plan.subset_fdselect_ranges)))
plan.info.fd_select.link = c->pop_pack ();
else
{
@@ -401,16 +603,17 @@ static bool _serialize_cff2 (hb_serialize_context_t *c,
hb_iter (private_dict_infos))
;
if (unlikely (!fda->serialize (c, it, fontSzr))) return false;
- plan.info.fd_array_link = c->pop_pack ();
+ plan.info.fd_array_link = c->pop_pack (false);
}
/* variation store */
- if (acc.varStore != &Null (CFF2VariationStore))
+ if (acc.varStore != &Null (CFF2VariationStore) &&
+ !plan.pinned)
{
c->push ();
CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> ();
if (unlikely (!dest || !dest->serialize (c, acc.varStore))) return false;
- plan.info.var_store_link = c->pop_pack ();
+ plan.info.var_store_link = c->pop_pack (false);
}
OT::cff2 *cff2 = c->allocate_min<OT::cff2> ();
@@ -444,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 4885280996..ca59de79a2 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
@@ -26,38 +26,21 @@
#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 ();
+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->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
@@ -83,11 +66,10 @@ 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'),
- HB_TAG ('f', 'v', 'a', 'r'),
HB_TAG ('g', 'a', 's', 'p'),
HB_TAG ('c', 'v', 't', ' '),
HB_TAG ('f', 'p', 'g', 'm'),
@@ -96,10 +78,9 @@ hb_subset_input_create_or_fail (void)
HB_TAG ('D', 'S', 'I', 'G'),
HB_TAG ('M', 'V', 'A', 'R'),
HB_TAG ('c', 'v', 'a', 'r'),
- HB_TAG ('S', 'T', 'A', 'T'),
};
- 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[] = {
@@ -140,7 +121,20 @@ hb_subset_input_create_or_fail (void)
HB_TAG ('r', 't', 'l', 'a'),
HB_TAG ('r', 't', 'l', 'm'),
- //Complex shapers
+ //random
+ HB_TAG ('r', 'a', 'n', 'd'),
+
+ //justify
+ HB_TAG ('j', 'a', 'l', 't'), // HarfBuzz doesn't use; others might
+
+ //private
+ HB_TAG ('H', 'a', 'r', 'f'),
+ HB_TAG ('H', 'A', 'R', 'F'),
+ HB_TAG ('B', 'u', 'z', 'z'),
+ HB_TAG ('B', 'U', 'Z', 'Z'),
+
+ //shapers
+
//arabic
HB_TAG ('i', 'n', 'i', 't'),
HB_TAG ('m', 'e', 'd', 'i'),
@@ -188,13 +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>();
+
+ if (unlikely (!input))
+ return nullptr;
if (input->in_error ())
{
hb_subset_input_destroy (input);
return nullptr;
}
+
return input;
}
@@ -228,9 +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_free (input);
}
@@ -329,7 +342,7 @@ hb_subset_input_set_flags (hb_subset_input_t *input,
*
* Attaches a user-data key/data pair to the given subset input object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 2.9.0
**/
@@ -361,3 +374,219 @@ 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.
+ *
+ * All axes in a font must be pinned. Additionally, `CFF2` table, if present,
+ * will be de-subroutinized.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: 6.0.0
+ **/
+HB_EXTERN hb_bool_t
+hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag)
+{
+ hb_ot_var_axis_info_t axis_info;
+ 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);
+}
+
+/**
+ * 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.
+ *
+ * All axes in a font must be pinned. Additionally, `CFF2` table, if present,
+ * will be de-subroutinized.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: 6.0.0
+ **/
+HB_EXTERN hb_bool_t
+hb_subset_input_pin_axis_location (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag,
+ float axis_value)
+{
+ hb_ot_var_axis_info_t axis_info;
+ if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+ return false;
+
+ float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value);
+ return input->axes_location.set (axis_tag, val);
+}
+#endif
+
+/**
+ * hb_subset_preprocess:
+ * @source: a #hb_face_t object.
+ *
+ * Preprocesses the face and attaches data that will be needed by the
+ * subsetter. Future subsetting operations can then use the precomputed data
+ * to speed up the subsetting operation.
+ *
+ * See [subset-preprocessing](https://github.com/harfbuzz/harfbuzz/blob/main/docs/subset-preprocessing.md)
+ * for more information.
+ *
+ * Note: the preprocessed face may contain sub-blobs that reference the memory
+ * backing the source #hb_face_t. Therefore in the case that this memory is not
+ * owned by the source face you will need to ensure that memory lives
+ * as long as the returned #hb_face_t.
+ *
+ * Returns: a new #hb_face_t.
+ *
+ * Since: 6.0.0
+ **/
+
+HB_EXTERN hb_face_t *
+hb_subset_preprocess (hb_face_t *source)
+{
+ hb_subset_input_t* input = hb_subset_input_create_or_fail ();
+ if (!input)
+ 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
+ // us to store the glyph bytes unpadded which allows the future subset
+ // operation to run faster by skipping the trim padding step.
+ input->force_long_loca = true;
+
+ hb_face_t* new_source = hb_subset_or_fail (source, input);
+ hb_subset_input_destroy (input);
+
+ if (!new_source) {
+ DEBUG_MSG (SUBSET, nullptr, "Preprocessing failed due to subset failure.");
+ return hb_face_reference (source);
+ }
+
+ return new_source;
+}
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_subset_input_override_name_table:
+ * @input: a #hb_subset_input_t object.
+ * @name_id: name_id of a nameRecord
+ * @platform_id: platform ID of a nameRecord
+ * @encoding_id: encoding ID of a nameRecord
+ * @language_id: language ID of a nameRecord
+ * @name_str: pointer to name string new value or null to indicate should remove
+ * @str_len: the size of @name_str, or -1 if it is `NULL`-terminated
+ *
+ * Override the name string of the NameRecord identified by name_id,
+ * platform_id, encoding_id and language_id. If a record with that name_id
+ * doesn't exist, create it and insert to the name table.
+ *
+ * Note: for mac platform, we only support name_str with all ascii characters,
+ * name_str with non-ascii characters will be ignored.
+ *
+ * XSince: EXPERIMENTAL
+ **/
+HB_EXTERN hb_bool_t
+hb_subset_input_override_name_table (hb_subset_input_t *input,
+ hb_ot_name_id_t name_id,
+ unsigned platform_id,
+ unsigned encoding_id,
+ unsigned language_id,
+ const char *name_str,
+ int str_len /* -1 means nul-terminated */)
+{
+ if (!name_str)
+ {
+ str_len = 0;
+ }
+ else if (str_len == -1)
+ {
+ str_len = strlen (name_str);
+ }
+
+ hb_bytes_t name_bytes (nullptr, 0);
+ if (str_len)
+ {
+ if (platform_id == 1)
+ {
+ const uint8_t *src = reinterpret_cast<const uint8_t*> (name_str);
+ const uint8_t *src_end = src + str_len;
+
+ hb_codepoint_t unicode;
+ const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+ while (src < src_end)
+ {
+ src = hb_utf8_t::next (src, src_end, &unicode, replacement);
+ if (unicode >= 0x0080u)
+ {
+ printf ("Non-ascii character detected, ignored...This API supports acsii characters only for mac platform\n");
+ return false;
+ }
+ }
+ }
+ char *override_name = (char *) hb_malloc (str_len);
+ if (unlikely (!override_name)) return false;
+
+ 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);
+ return true;
+}
+
+#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
index 07c0e22676..1550e8b2c3 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-input.hh
@@ -33,40 +33,104 @@
#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
+{
+ hb_ot_name_record_ids_t () = default;
+ hb_ot_name_record_ids_t (unsigned platform_id_,
+ unsigned encoding_id_,
+ unsigned language_id_,
+ unsigned name_id_)
+ :platform_id (platform_id_),
+ encoding_id (encoding_id_),
+ language_id (language_id_),
+ name_id (name_id_) {}
+
+ bool operator != (const hb_ot_name_record_ids_t o) const
+ { return !(*this == o); }
+
+ inline bool operator == (const hb_ot_name_record_ids_t& o) const
+ {
+ return platform_id == o.platform_id &&
+ encoding_id == o.encoding_id &&
+ language_id == o.language_id &&
+ name_id == o.name_id;
+ }
+
+ inline uint32_t hash () const
+ {
+ uint32_t current = 0;
+ current = current * 31 + hb_hash (platform_id);
+ current = current * 31 + hb_hash (encoding_id);
+ current = current * 31 + hb_hash (language_id);
+ current = current * 31 + hb_hash (name_id);
+ return current;
+ }
+
+ unsigned platform_id;
+ unsigned encoding_id;
+ unsigned language_id;
+ unsigned name_id;
+};
+
+typedef struct hb_ot_name_record_ids_t hb_ot_name_record_ids_t;
+
+
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::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;
+ bool attach_accelerator_data = false;
+
+ // If set loca format will always be the long version.
+ bool force_long_loca = false;
+
+ 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;
+#endif
inline unsigned num_sets () const
{
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
@@ -76,7 +140,12 @@ struct hb_subset_input_t
if (unlikely (set_ptrs[i]->in_error ()))
return true;
}
- return false;
+
+ return axes_location.in_error ()
+#ifdef HB_EXPERIMENTAL_API
+ || 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 74b7e3977c..088fdca07b 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
@@ -25,7 +25,9 @@
*/
#include "hb-subset-plan.hh"
+#include "hb-subset-accelerator.hh"
#include "hb-map.hh"
+#include "hb-multimap.hh"
#include "hb-set.hh"
#include "hb-ot-cmap-table.hh"
@@ -34,18 +36,19 @@
#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"
#include "hb-ot-math-table.hh"
-using OT::Layout::GSUB::GSUB;
+using OT::Layout::GSUB;
+using OT::Layout::GPOS;
-
-typedef hb_hashmap_t<unsigned, hb_set_t *> script_langsys_map;
+typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
#ifndef HB_NO_SUBSET_CFF
-static inline void
+static inline bool
_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
hb_codepoint_t gid,
hb_set_t *gids_to_retain)
@@ -55,7 +58,9 @@ _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
{
gids_to_retain->add (base_gid);
gids_to_retain->add (accent_gid);
+ return true;
}
+ return false;
}
#endif
@@ -80,114 +85,233 @@ static void
_remap_indexes (const hb_set_t *indexes,
hb_map_t *mapping /* OUT */)
{
- unsigned count = indexes->get_population ();
-
- for (auto _ : + hb_zip (indexes->iter (), hb_range (count)))
- mapping->set (_.first, _.second);
+ for (auto _ : + hb_enumerate (indexes->iter ()))
+ mapping->set (_.second, _.first);
}
#ifndef HB_NO_SUBSET_LAYOUT
-typedef void (*layout_collect_func_t) (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, const hb_tag_t *languages, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */);
+/*
+ * Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates.
+ * Returns true if anything was removed (not including duplicates).
+ */
+static bool _filter_tag_list(hb_vector_t<hb_tag_t>* tags, /* IN/OUT */
+ const hb_set_t* filter)
+{
+ hb_vector_t<hb_tag_t> out;
+ out.alloc (tags->get_size() + 1); // +1 is to allocate room for the null terminator.
+
+ bool removed = false;
+ hb_set_t visited;
+
+ for (hb_tag_t tag : *tags)
+ {
+ if (!tag) continue;
+ if (visited.has (tag)) continue;
+
+ if (!filter->has (tag))
+ {
+ removed = true;
+ continue;
+ }
+
+ visited.add (tag);
+ out.push (tag);
+ }
+
+ // The collect function needs a null element to signal end of the array.
+ out.push (HB_TAG_NONE);
+
+ hb_swap (out, *tags);
+ return removed;
+}
template <typename T>
-static void _collect_layout_indices (hb_face_t *face,
+static void _collect_layout_indices (hb_subset_plan_t *plan,
const T& table,
- const hb_set_t *layout_features_to_retain,
- layout_collect_func_t layout_collect_func,
- hb_set_t *indices /* OUT */)
+ hb_set_t *lookup_indices, /* OUT */
+ hb_set_t *feature_indices, /* OUT */
+ hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */
+ hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map /* OUT */)
{
+ unsigned num_features = table.get_feature_count ();
hb_vector_t<hb_tag_t> features;
- if (!features.alloc (table.get_feature_count () + 1))
+ 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);
+
+ 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);
+
+ if (!plan->check_success (!features.in_error ()) || !features
+ || !plan->check_success (!scripts.in_error ()) || !scripts)
return;
- hb_set_t visited_features;
- bool retain_all_features = true;
- for (unsigned i = 0; i < table.get_feature_count (); i++)
+ hb_ot_layout_collect_features (plan->source,
+ T::tableTag,
+ retain_all_scripts ? nullptr : scripts.arrayZ,
+ nullptr,
+ retain_all_features ? nullptr : features.arrayZ,
+ feature_indices);
+
+#ifndef HB_NO_VAR
+ // collect feature substitutes with variations
+ if (!plan->user_axes_location.is_empty ())
{
- hb_tag_t tag = table.get_feature_tag (i);
- if (!tag) continue;
- if (!layout_features_to_retain->has (tag))
+ hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> conditionset_map;
+ OT::hb_collect_feature_substitutes_with_var_context_t c =
{
- retain_all_features = false;
- continue;
- }
+ &plan->axes_old_index_tag_map,
+ &plan->axes_location,
+ feature_record_cond_idx_map,
+ feature_substitutes_map,
+ feature_indices,
+ true,
+ 0,
+ &conditionset_map
+ };
+ table.collect_feature_substitutes_with_variations (&c);
+ }
+#endif
- if (visited_features.has (tag))
- continue;
+ for (unsigned feature_index : *feature_indices)
+ {
+ const OT::Feature* f = &(table.get_feature (feature_index));
+ const OT::Feature **p = nullptr;
+ if (feature_substitutes_map->has (feature_index, &p))
+ f = *p;
- features.push (tag);
- visited_features.add (tag);
+ f->add_lookup_indexes_to (lookup_indices);
}
- if (!features)
- return;
+ // 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);
+ }
+}
- // The collect function needs a null element to signal end of the array.
- features.push (0);
- if (retain_all_features)
+static inline void
+_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
+ const hb_map_t *lookup_indices,
+ const hb_set_t *feature_indices,
+ const hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
+ hb_map_t *duplicate_feature_map /* OUT */)
+{
+ if (feature_indices->is_empty ()) return;
+ hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features;
+ //find out duplicate features after subset
+ for (unsigned i : feature_indices->iter ())
{
- // Looking for all features, trigger the faster collection method.
- layout_collect_func (face,
- T::tableTag,
- nullptr,
- nullptr,
- nullptr,
- indices);
- return;
- }
+ hb_tag_t t = g.get_feature_tag (i);
+ if (t == HB_MAP_VALUE_INVALID) continue;
+ if (!unique_features.has (t))
+ {
+ if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
+ return;
+ if (unique_features.has (t))
+ unique_features.get (t)->add (i);
+ duplicate_feature_map->set (i, i);
+ continue;
+ }
+
+ bool found = false;
+
+ hb_set_t* same_tag_features = unique_features.get (t);
+ for (unsigned other_f_index : same_tag_features->iter ())
+ {
+ const OT::Feature* f = &(g.get_feature (i));
+ const OT::Feature **p = nullptr;
+ if (feature_substitutes_map->has (i, &p))
+ f = *p;
+
+ const OT::Feature* other_f = &(g.get_feature (other_f_index));
+ if (feature_substitutes_map->has (other_f_index, &p))
+ other_f = *p;
+
+ auto f_iter =
+ + hb_iter (f->lookupIndex)
+ | hb_filter (lookup_indices)
+ ;
+
+ auto other_f_iter =
+ + hb_iter (other_f->lookupIndex)
+ | hb_filter (lookup_indices)
+ ;
+
+ bool is_equal = true;
+ for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
+ {
+ unsigned a = *f_iter;
+ unsigned b = *other_f_iter;
+ if (a != b) { is_equal = false; break; }
+ }
- layout_collect_func (face,
- T::tableTag,
- nullptr,
- nullptr,
- features.arrayZ,
- indices);
+ if (is_equal == false || f_iter || other_f_iter) continue;
+
+ found = true;
+ duplicate_feature_map->set (i, other_f_index);
+ break;
+ }
+
+ if (found == false)
+ {
+ same_tag_features->add (i);
+ duplicate_feature_map->set (i, i);
+ }
+ }
}
template <typename T>
static inline void
-_closure_glyphs_lookups_features (hb_face_t *face,
+_closure_glyphs_lookups_features (hb_subset_plan_t *plan,
hb_set_t *gids_to_retain,
- const hb_set_t *layout_features_to_retain,
hb_map_t *lookups,
hb_map_t *features,
- script_langsys_map *langsys_map)
+ script_langsys_map *langsys_map,
+ hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
+ hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map)
{
- hb_blob_ptr_t<T> table = hb_sanitize_context_t ().reference_table<T> (face);
+ hb_blob_ptr_t<T> table = plan->source_table<T> ();
hb_tag_t table_tag = table->tableTag;
- hb_set_t lookup_indices;
- _collect_layout_indices<T> (face,
+ hb_set_t lookup_indices, feature_indices;
+ _collect_layout_indices<T> (plan,
*table,
- layout_features_to_retain,
- hb_ot_layout_collect_lookups,
- &lookup_indices);
+ &lookup_indices,
+ &feature_indices,
+ feature_record_cond_idx_map,
+ feature_substitutes_map);
if (table_tag == HB_OT_TAG_GSUB)
- hb_ot_layout_lookups_substitute_closure (face,
- &lookup_indices,
+ hb_ot_layout_lookups_substitute_closure (plan->source,
+ &lookup_indices,
gids_to_retain);
- table->closure_lookups (face,
+ table->closure_lookups (plan->source,
gids_to_retain,
- &lookup_indices);
+ &lookup_indices);
_remap_indexes (&lookup_indices, lookups);
- // Collect and prune features
- hb_set_t feature_indices;
- _collect_layout_indices<T> (face,
- *table,
- layout_features_to_retain,
- hb_ot_layout_collect_features,
- &feature_indices);
-
- table->prune_features (lookups, &feature_indices);
+ // prune features
+ table->prune_features (lookups,
+ plan->user_axes_location.is_empty () ? nullptr : feature_record_cond_idx_map,
+ feature_substitutes_map,
+ &feature_indices);
hb_map_t duplicate_feature_map;
- table->find_duplicate_features (lookups, &feature_indices, &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, langsys_map, &feature_indices);
+ table->prune_langsys (&duplicate_feature_map, &plan->layout_scripts, langsys_map, &feature_indices);
_remap_indexes (&feature_indices, features);
table.destroy ();
@@ -197,14 +321,51 @@ _closure_glyphs_lookups_features (hb_face_t *face,
#ifndef HB_NO_VAR
static inline void
- _collect_layout_variation_indices (hb_face_t *face,
- const hb_set_t *glyphset,
- const hb_map_t *gpos_lookups,
- hb_set_t *layout_variation_indices,
- hb_map_t *layout_variation_idx_map)
+_generate_varstore_inner_maps (const hb_set_t& varidx_set,
+ unsigned subtable_count,
+ hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */)
+{
+ if (varidx_set.is_empty () || subtable_count == 0) return;
+
+ inner_maps.resize (subtable_count);
+ for (unsigned idx : varidx_set)
+ {
+ uint16_t major = idx >> 16;
+ uint16_t minor = idx & 0xFFFF;
+
+ if (major >= subtable_count)
+ continue;
+ inner_maps[major].add (minor);
+ }
+}
+
+static inline hb_font_t*
+_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 ());
+
+ for (auto _ : plan->user_axes_location)
+ {
+ hb_variation_t var;
+ var.tag = _.first;
+ var.value = _.second;
+ vars.push (var);
+ }
+
+#ifndef HB_NO_VAR
+ hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
+#endif
+ return font;
+}
+
+static inline void
+_collect_layout_variation_indices (hb_subset_plan_t* plan)
{
- hb_blob_ptr_t<OT::GDEF> gdef = hb_sanitize_context_t ().reference_table<OT::GDEF> (face);
- hb_blob_ptr_t<OT::GPOS> gpos = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
+ hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
+ hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
if (!gdef->has_data ())
{
@@ -212,13 +373,40 @@ static inline void
gpos.destroy ();
return;
}
- OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups);
+
+ const OT::VariationStore *var_store = nullptr;
+ hb_set_t varidx_set;
+ hb_font_t *font = nullptr;
+ float *store_cache = nullptr;
+ bool collect_delta = plan->pinned_at_default ? false : true;
+ if (collect_delta)
+ {
+ font = _get_hb_font_with_variations (plan);
+ if (gdef->has_var_store ())
+ {
+ var_store = &(gdef->get_var_store ());
+ store_cache = var_store->create_cache ();
+ }
+ }
+
+ OT::hb_collect_variation_indices_context_t c (&varidx_set,
+ &plan->layout_variation_idx_delta_map,
+ font, var_store,
+ &plan->_glyphset_gsub,
+ &plan->gpos_lookups,
+ store_cache);
gdef->collect_variation_indices (&c);
- if (hb_ot_layout_has_positioning (face))
+ if (hb_ot_layout_has_positioning (plan->source))
gpos->collect_variation_indices (&c);
- gdef->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map);
+ hb_font_destroy (font);
+ var_store->destroy_cache (store_cache);
+
+ 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);
gdef.destroy ();
gpos.destroy ();
@@ -242,22 +430,16 @@ static void _colr_closure (hb_face_t *face,
OT::COLR::accelerator_t colr (face);
if (!colr.is_valid ()) return;
- unsigned iteration_count = 0;
hb_set_t palette_indices, layer_indices;
- unsigned glyphs_num;
- {
- glyphs_num = glyphs_colred->get_population ();
- // Collect all glyphs referenced by COLRv0
- hb_set_t glyphset_colrv0;
- for (hb_codepoint_t gid : glyphs_colred->iter ())
- colr.closure_glyphs (gid, &glyphset_colrv0);
+ // Collect all glyphs referenced by COLRv0
+ hb_set_t glyphset_colrv0;
+ for (hb_codepoint_t gid : *glyphs_colred)
+ colr.closure_glyphs (gid, &glyphset_colrv0);
- glyphs_colred->union_ (glyphset_colrv0);
+ glyphs_colred->union_ (glyphset_colrv0);
- //closure for COLRv1
- colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
- } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
- glyphs_num != glyphs_colred->get_population ());
+ //closure for COLRv1
+ colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
_remap_indexes (&layer_indices, layers_map);
@@ -265,10 +447,10 @@ static void _colr_closure (hb_face_t *face,
}
static inline void
-_math_closure (hb_face_t *face,
- hb_set_t *glyphset)
+_math_closure (hb_subset_plan_t *plan,
+ hb_set_t *glyphset)
{
- hb_blob_ptr_t<OT::MATH> math = hb_sanitize_context_t ().reference_table<OT::MATH> (face);
+ hb_blob_ptr_t<OT::MATH> math = plan->source_table<OT::MATH> ();
if (math->has_data ())
math->closure_glyphs (glyphset);
math.destroy ();
@@ -279,12 +461,7 @@ static inline void
_remove_invalid_gids (hb_set_t *glyphs,
unsigned int num_glyphs)
{
- hb_codepoint_t gid = HB_SET_VALUE_INVALID;
- while (glyphs->next (&gid))
- {
- if (gid >= num_glyphs)
- glyphs->del (gid);
- }
+ glyphs->del_range (num_glyphs, HB_SET_VALUE_INVALID);
}
static void
@@ -293,126 +470,253 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
hb_subset_plan_t *plan)
{
OT::cmap::accelerator_t cmap (plan->source);
-
- constexpr static const int size_threshold = 4096;
-
+ unsigned size_threshold = plan->source->get_num_glyphs ();
if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
{
- /* This is the fast path if it's anticipated that size of unicodes
- * is << than the number of codepoints in the font. */
- for (hb_codepoint_t cp : *unicodes)
- {
- hb_codepoint_t gid;
- if (!cmap.get_nominal_glyph (cp, &gid))
+
+ const hb_map_t* unicode_to_gid = nullptr;
+ if (plan->accelerator)
+ unicode_to_gid = &plan->accelerator->unicode_to_gid;
+
+ // This is approach to collection is faster, but can only be used if glyphs
+ // are not being explicitly added to the subset and the input unicodes set is
+ // not excessively large (eg. an inverted set).
+ plan->unicode_to_new_gid_list.alloc (unicodes->get_population ());
+ if (!unicode_to_gid) {
+ for (hb_codepoint_t cp : *unicodes)
{
- DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
- continue;
+ hb_codepoint_t gid;
+ if (!cmap.get_nominal_glyph (cp, &gid))
+ {
+ DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
+ continue;
+ }
+
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+ }
+ } else {
+ // Use in memory unicode to gid map it's faster then looking up from
+ // the map. This code is mostly duplicated from above to avoid doing
+ // conditionals on the presence of the unicode_to_gid map each
+ // iteration.
+ for (hb_codepoint_t cp : *unicodes)
+ {
+ hb_codepoint_t gid = unicode_to_gid->get (cp);
+ if (gid == HB_MAP_VALUE_INVALID)
+ {
+ DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
+ continue;
+ }
+
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
}
-
- plan->codepoint_to_glyph->set (cp, gid);
}
}
else
{
- hb_map_t unicode_glyphid_map;
- cmap.collect_mapping (hb_set_get_empty (), &unicode_glyphid_map);
+ // This approach is slower, but can handle adding in glyphs to the subset and will match
+ // them with cmap entries.
+
+ hb_map_t unicode_glyphid_map_storage;
+ hb_set_t cmap_unicodes_storage;
+ const hb_map_t* unicode_glyphid_map = &unicode_glyphid_map_storage;
+ const hb_set_t* cmap_unicodes = &cmap_unicodes_storage;
+
+ if (!plan->accelerator) {
+ cmap.collect_mapping (&cmap_unicodes_storage, &unicode_glyphid_map_storage);
+ plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population ()
+ + glyphs->get_population (),
+ cmap_unicodes->get_population ()));
+ } else {
+ unicode_glyphid_map = &plan->accelerator->unicode_to_gid;
+ cmap_unicodes = &plan->accelerator->unicodes;
+ }
- for (hb_pair_t<hb_codepoint_t, hb_codepoint_t> cp_gid :
- + unicode_glyphid_map.iter ())
+ if (plan->accelerator &&
+ unicodes->get_population () < cmap_unicodes->get_population () &&
+ glyphs->get_population () < cmap_unicodes->get_population ())
{
- if (!unicodes->has (cp_gid.first) && !glyphs->has (cp_gid.second))
- continue;
+ auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes;
+ for (hb_codepoint_t gid : *glyphs)
+ {
+ auto unicodes = gid_to_unicodes.get (gid);
- plan->codepoint_to_glyph->set (cp_gid.first, cp_gid.second);
+ for (hb_codepoint_t cp : unicodes)
+ {
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+ }
+ }
+ for (hb_codepoint_t cp : *unicodes)
+ {
+ /* Don't double-add entry. */
+ if (plan->codepoint_to_glyph->has (cp))
+ continue;
+
+ hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+ }
+ plan->unicode_to_new_gid_list.qsort ();
+ }
+ else
+ {
+ for (hb_codepoint_t cp : *cmap_unicodes)
+ {
+ hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
+ if (!unicodes->has (cp) && !glyphs->has (gid))
+ continue;
+
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+ }
}
/* Add gids which where requested, but not mapped in cmap */
- // TODO(garretrieger):
- // Once https://github.com/harfbuzz/harfbuzz/issues/3169
- // is implemented, this can be done with union and del_range
- for (hb_codepoint_t gid : glyphs->iter ())
+ for (hb_codepoint_t gid : *glyphs)
{
if (gid >= plan->source->get_num_glyphs ())
break;
- plan->_glyphset_gsub->add (gid);
+ plan->_glyphset_gsub.add (gid);
}
}
- + plan->codepoint_to_glyph->keys () | hb_sink (plan->unicodes);
- + plan->codepoint_to_glyph->values () | hb_sink (plan->_glyphset_gsub);
+ 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));
+ }
+}
+
+#ifndef HB_COMPOSITE_OPERATIONS_PER_GLYPH
+#define HB_COMPOSITE_OPERATIONS_PER_GLYPH 64
+#endif
+
+static unsigned
+_glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
+ hb_codepoint_t gid,
+ hb_set_t *gids_to_retain,
+ int operation_count,
+ unsigned depth = 0)
+{
+ if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
+ if (unlikely (--operation_count < 0)) return operation_count;
+ /* Check if is already visited */
+ if (gids_to_retain->has (gid)) return operation_count;
+
+ gids_to_retain->add (gid);
+
+ for (auto item : glyf.glyph_for_gid (gid).get_composite_iterator ())
+ operation_count =
+ _glyf_add_gid_and_children (glyf,
+ item.get_gid (),
+ gids_to_retain,
+ operation_count,
+ depth);
+
+ return operation_count;
}
static void
_populate_gids_to_retain (hb_subset_plan_t* plan,
- bool close_over_gsub,
- bool close_over_gpos,
- bool close_over_gdef)
+ hb_set_t* drop_tables)
{
- OT::glyf::accelerator_t glyf (plan->source);
+ OT::glyf_accelerator_t glyf (plan->source);
#ifndef HB_NO_SUBSET_CFF
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 (close_over_gsub)
+ if (!drop_tables->has (HB_OT_TAG_GSUB))
// closure all glyphs/lookups/features needed for GSUB substitutions.
_closure_glyphs_lookups_features<GSUB> (
- plan->source,
- plan->_glyphset_gsub,
- plan->layout_features,
- plan->gsub_lookups,
- plan->gsub_features,
- plan->gsub_langsys);
-
- if (close_over_gpos)
- _closure_glyphs_lookups_features<OT::GPOS> (
- plan->source,
- plan->_glyphset_gsub,
- plan->layout_features,
- plan->gpos_lookups,
- plan->gpos_features,
- plan->gpos_langsys);
+ 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);
+
+ 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);
#endif
- _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
-
- hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
- _math_closure (plan->source, plan->_glyphset_mathed);
- _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
+ _remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ());
- hb_set_t cur_glyphset = *plan->_glyphset_mathed;
- _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
- _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
+ 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 ());
+ }
- hb_set_set (plan->_glyphset_colred, &cur_glyphset);
- // Populate a full set of glyphs to retain by adding all referenced
- // composite glyphs.
- for (hb_codepoint_t gid : cur_glyphset.iter ())
+ hb_set_t cur_glyphset = plan->_glyphset_mathed;
+ if (!drop_tables->has (HB_OT_TAG_COLR))
{
- glyf.add_gid_and_children (gid, plan->_glyphset);
+ _colr_closure (plan->source, &plan->colrv1_layers, &plan->colr_palettes, &cur_glyphset);
+ _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
+ }
+
+ 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,
+ cur_glyphset.get_population () * HB_COMPOSITE_OPERATIONS_PER_GLYPH);
+ else
+ 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 ())
- _add_cff_seac_components (cff, gid, plan->_glyphset);
-#endif
+ for (hb_codepoint_t gid : cur_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
- if (close_over_gdef)
- _collect_layout_variation_indices (plan->source,
- plan->_glyphset_gsub,
- plan->gpos_lookups,
- plan->layout_variation_indices,
- plan->layout_variation_idx_map);
+ if (!drop_tables->has (HB_OT_TAG_GDEF))
+ _collect_layout_variation_indices (plan);
#endif
}
static void
+_create_glyph_map_gsub (const hb_set_t* glyph_set_gsub,
+ const hb_map_t* glyph_map,
+ hb_map_t* out)
+{
+ + hb_iter (glyph_set_gsub)
+ | hb_map ([&] (hb_codepoint_t gid) {
+ return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid,
+ glyph_map->get (gid));
+ })
+ | hb_sink (out)
+ ;
+}
+
+static void
_create_old_gid_to_new_gid_map (const hb_face_t *face,
bool retain_gids,
const hb_set_t *all_gids_to_retain,
@@ -420,13 +724,19 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
hb_map_t *reverse_glyph_map, /* OUT */
unsigned int *num_glyphs /* OUT */)
{
+ unsigned pop = all_gids_to_retain->get_population ();
+ reverse_glyph_map->resize (pop);
+ glyph_map->resize (pop);
+
if (!retain_gids)
{
+ hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0)
| hb_sink (reverse_glyph_map)
;
*num_glyphs = reverse_glyph_map->get_population ();
- } else {
+ }
+ else
+ {
+ hb_iter (all_gids_to_retain)
| hb_map ([] (hb_codepoint_t _) {
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, _);
@@ -434,10 +744,9 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
| hb_sink (reverse_glyph_map)
;
- unsigned max_glyph =
- + hb_iter (all_gids_to_retain)
- | hb_reduce (hb_max, 0u)
- ;
+ hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID;
+ hb_set_previous (all_gids_to_retain, &max_glyph);
+
*num_glyphs = max_glyph + 1;
}
@@ -449,14 +758,175 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
static void
_nameid_closure (hb_face_t *face,
- hb_set_t *nameids)
+ hb_set_t *nameids,
+ bool all_axes_pinned,
+ hb_hashmap_t<hb_tag_t, float> *user_axes_location)
{
#ifndef HB_NO_STYLE
- face->table.STAT->collect_name_ids (nameids);
+ face->table.STAT->collect_name_ids (user_axes_location, nameids);
+#endif
+#ifndef HB_NO_VAR
+ if (!all_axes_pinned)
+ face->table.fvar->collect_name_ids (user_axes_location, nameids);
+#endif
+}
+
+#ifndef HB_NO_VAR
+static void
+_normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
+{
+ 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;
+ if (has_avar)
+ seg_maps = face->table.avar->get_segment_maps ();
+
+ 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);
+
+ if (!plan->user_axes_location.has (axis_tag))
+ {
+ axis_not_pinned = true;
+ 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));
+ 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);
+ 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_t::hb_subset_plan_t (hb_face_t *face,
+ const hb_subset_input_t *input)
+{
+ successful = true;
+ flags = input->flags;
+
+ unicode_to_new_gid_list.init ();
+
+ 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
+ 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 (!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());
+
+ attach_accelerator_data = input->attach_accelerator_data;
+ force_long_loca = input->force_long_loca;
+ if (accel)
+ accelerator = (hb_subset_accelerator_t*) accel;
+
+
+ if (unlikely (in_error ()))
+ return;
+
#ifndef HB_NO_VAR
- face->table.fvar->collect_name_ids (nameids);
+ _normalize_axes_location (face, this);
#endif
+
+ _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this);
+
+ _populate_gids_to_retain (this, input->sets.drop_tables);
+
+ _create_old_gid_to_new_gid_map (face,
+ input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,
+ &_glyphset,
+ glyph_map,
+ reverse_glyph_map,
+ &_num_output_glyphs);
+
+ _create_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 < unicode_to_new_gid_list.length; i++)
+ {
+ // Use raw array access for performance.
+ 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 (attach_accelerator_data)
+ {
+ hb_multimap_t gid_to_unicodes;
+
+ hb_map_t &unicode_to_gid = *codepoint_to_glyph;
+
+ for (auto unicode : unicodes)
+ {
+ auto gid = unicode_to_gid[unicode];
+ gid_to_unicodes.add (gid, unicode);
+ }
+
+ inprogress_accelerator =
+ hb_subset_accelerator_t::create (*codepoint_to_glyph,
+ gid_to_unicodes,
+ unicodes,
+ has_seac);
+ }
}
/**
@@ -479,67 +949,15 @@ 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> ())))
+ if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> (face, input))))
return nullptr;
- plan->successful = true;
- plan->flags = input->flags;
- plan->unicodes = hb_set_create ();
- plan->name_ids = hb_set_copy (input->sets.name_ids);
- _nameid_closure (face, plan->name_ids);
- plan->name_languages = hb_set_copy (input->sets.name_languages);
- plan->layout_features = hb_set_copy (input->sets.layout_features);
- 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->gsub_lookups = hb_map_create ();
- plan->gpos_lookups = hb_map_create ();
-
- if (plan->check_success (plan->gsub_langsys = hb_object_create<script_langsys_map> ()))
- plan->gsub_langsys->init_shallow ();
- if (plan->check_success (plan->gpos_langsys = hb_object_create<script_langsys_map> ()))
- plan->gpos_langsys->init_shallow ();
-
- plan->gsub_features = hb_map_create ();
- plan->gpos_features = hb_map_create ();
- plan->colrv1_layers = hb_map_create ();
- plan->colr_palettes = hb_map_create ();
- plan->layout_variation_indices = hb_set_create ();
- plan->layout_variation_idx_map = hb_map_create ();
-
- if (unlikely (plan->in_error ())) {
+ if (unlikely (plan->in_error ()))
+ {
hb_subset_plan_destroy (plan);
return nullptr;
}
- _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
-
- _populate_gids_to_retain (plan,
- !input->sets.drop_tables->has (HB_OT_TAG_GSUB),
- !input->sets.drop_tables->has (HB_OT_TAG_GPOS),
- !input->sets.drop_tables->has (HB_OT_TAG_GDEF));
-
- _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);
-
- if (unlikely (plan->in_error ())) {
- hb_subset_plan_destroy (plan);
- return nullptr;
- }
return plan;
}
@@ -557,51 +975,6 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
{
if (!hb_object_destroy (plan)) return;
- hb_set_destroy (plan->unicodes);
- hb_set_destroy (plan->name_ids);
- hb_set_destroy (plan->name_languages);
- hb_set_destroy (plan->layout_features);
- hb_set_destroy (plan->glyphs_requested);
- hb_set_destroy (plan->drop_tables);
- hb_set_destroy (plan->no_subset_tables);
- hb_face_destroy (plan->source);
- hb_face_destroy (plan->dest);
- hb_map_destroy (plan->codepoint_to_glyph);
- hb_map_destroy (plan->glyph_map);
- hb_map_destroy (plan->reverse_glyph_map);
- hb_set_destroy (plan->_glyphset);
- hb_set_destroy (plan->_glyphset_gsub);
- hb_set_destroy (plan->_glyphset_mathed);
- hb_set_destroy (plan->_glyphset_colred);
- hb_map_destroy (plan->gsub_lookups);
- hb_map_destroy (plan->gpos_lookups);
- hb_map_destroy (plan->gsub_features);
- hb_map_destroy (plan->gpos_features);
- hb_map_destroy (plan->colrv1_layers);
- hb_map_destroy (plan->colr_palettes);
- hb_set_destroy (plan->layout_variation_indices);
- hb_map_destroy (plan->layout_variation_idx_map);
-
- if (plan->gsub_langsys)
- {
- for (auto _ : plan->gsub_langsys->iter ())
- hb_set_destroy (_.second);
-
- hb_object_destroy (plan->gsub_langsys);
- plan->gsub_langsys->fini_shallow ();
- hb_free (plan->gsub_langsys);
- }
-
- if (plan->gpos_langsys)
- {
- for (auto _ : plan->gpos_langsys->iter ())
- hb_set_destroy (_.second);
-
- hb_object_destroy (plan->gpos_langsys);
- plan->gpos_langsys->fini_shallow ();
- hb_free (plan->gpos_langsys);
- }
-
hb_free (plan);
}
@@ -617,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;
@@ -635,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;
@@ -653,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;
@@ -685,7 +1058,7 @@ hb_subset_plan_reference (hb_subset_plan_t *plan)
*
* Attaches a user-data key/data pair to the given subset plan object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 4.0.0
**/
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
index ab2c4c302c..c0a85e12dc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
@@ -31,78 +31,204 @@
#include "hb-subset.h"
#include "hb-subset-input.hh"
+#include "hb-subset-accelerator.hh"
#include "hb-map.hh"
+#include "hb-bimap.hh"
#include "hb-set.hh"
+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_INTERNAL hb_subset_plan_t (hb_face_t *,
+ const hb_subset_input_t *input);
+
+ ~hb_subset_plan_t()
+ {
+ hb_face_destroy (source);
+ hb_face_destroy (dest);
+
+ hb_map_destroy (codepoint_to_glyph);
+ hb_map_destroy (glyph_map);
+ hb_map_destroy (reverse_glyph_map);
+
+#ifdef HB_EXPERIMENTAL_API
+ for (auto _ : name_table_overrides)
+ _.second.fini ();
+#endif
+
+ if (inprogress_accelerator)
+ hb_subset_accelerator_t::destroy ((void*) inprogress_accelerator);
+ }
+
hb_object_header_t header;
bool successful;
unsigned flags;
+ bool attach_accelerator_data = false;
+ 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;
//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; // 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_set_t *> *gsub_langsys;
- hb_hashmap_t<unsigned, 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 layers/palettes we'd like to retain
- hb_map_t *colrv1_layers;
- hb_map_t *colr_palettes;
+ //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;
+
+ //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;
- //The set of layout item variation store delta set indices to be retained
- hb_set_t *layout_variation_indices;
- //Old -> New layout item variation store delta set index mapping
- hb_map_t *layout_variation_idx_map;
+ //active layers/palettes we'd like to retain
+ 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;
+
+ //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;
+ //normalized axes location map
+ 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;
+ //retained old axis index -> new axis index mapping in fvar axis array
+ hb_map_t axes_index_map;
+ //axis_index->axis_tag mapping in fvar axis array
+ 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)
+ mutable hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> hmtx_map;
+ //vmtx metrics map: new gid->(advance, lsb)
+ 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;
+#endif
+
+ const hb_subset_accelerator_t* accelerator;
+ hb_subset_accelerator_t* inprogress_accelerator;
public:
+ template<typename T>
+ hb_blob_ptr_t<T> source_table()
+ {
+ hb_lock_t (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
+
+ auto *cache = accelerator ? &accelerator->sanitized_table_cache : &sanitized_table_cache;
+ if (cache
+ && !cache->in_error ()
+ && cache->has (+T::tableTag)) {
+ return hb_blob_reference (cache->get (+T::tableTag).get ());
+ }
+
+ hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)};
+ hb_blob_t* ret = hb_blob_reference (table_blob.get ());
+
+ if (likely (cache))
+ cache->set (+T::tableTag, std::move (table_blob));
+
+ return ret;
+ }
+
bool in_error () const { return !successful; }
bool check_success(bool success)
@@ -119,7 +245,7 @@ struct hb_subset_plan_t
inline const hb_set_t *
glyphset () const
{
- return _glyphset;
+ return &_glyphset;
}
/*
@@ -128,7 +254,7 @@ struct hb_subset_plan_t
inline const hb_set_t *
glyphset_gsub () const
{
- return _glyphset_gsub;
+ return &_glyphset_gsub;
}
/*
@@ -146,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,
@@ -188,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 2447d296b8..6a29b35be7 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.cc
@@ -25,25 +25,34 @@
#include "hb-repacker.hh"
#ifdef HB_EXPERIMENTAL_API
+
/**
* hb_subset_repack_or_fail:
+ * @table_tag: tag of the table being packed, needed to allow table specific optimizations.
* @hb_objects: raw array of struct hb_object_t, which provides
* object graph info
* @num_hb_objs: number of hb_object_t in the hb_objects array.
*
* Given the input object graph info, repack a table to eliminate
* offset overflows. A nullptr is returned if the repacking attempt fails.
+ * 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_object_t* hb_objects, unsigned num_hb_objs)
+hb_blob_t* hb_subset_repack_or_fail (hb_tag_t table_tag,
+ hb_object_t* hb_objects,
+ unsigned num_hb_objs)
{
hb_vector_t<const hb_object_t *> packed;
packed.alloc (num_hb_objs + 1);
packed.push (nullptr);
for (unsigned i = 0 ; i < num_hb_objs ; i++)
packed.push (&(hb_objects[i]));
- return hb_resolve_overflows (packed, HB_OT_TAG_GSUB);
+
+ return hb_resolve_overflows (packed,
+ table_tag,
+ 20,
+ true);
}
#endif
-
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.h b/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.h
index f9a2383698..245cf60765 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-repacker.h
@@ -31,13 +31,13 @@
HB_BEGIN_DECLS
#ifdef HB_EXPERIMENTAL_API
-/**
+/*
* struct hb_link_t
* width: offsetSize in bytes
* position: position of the offset field in bytes
* from beginning of subtable
* objidx: index of subtable
- **/
+ */
struct hb_link_t
{
unsigned width;
@@ -47,7 +47,7 @@ struct hb_link_t
typedef struct hb_link_t hb_link_t;
-/**
+/*
* struct hb_object_t
* head: start of object data
* tail: end of object data
@@ -56,7 +56,7 @@ typedef struct hb_link_t hb_link_t;
* num_virtual_links: num of objects that must be packed
* after current object in the final serialized order
* virtual_links: array of virtual link info
- **/
+ */
struct hb_object_t
{
char *head;
@@ -70,7 +70,8 @@ struct hb_object_t
typedef struct hb_object_t hb_object_t;
HB_EXTERN hb_blob_t*
-hb_subset_repack_or_fail (hb_object_t* hb_objects,
+hb_subset_repack_or_fail (hb_tag_t table_tag,
+ hb_object_t* hb_objects,
unsigned num_hb_objs);
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc
index 4588268b76..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,15 +48,18 @@
#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"
#include "hb-ot-var-gvar-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-ot-math-table.hh"
+#include "hb-ot-stat-table.hh"
#include "hb-repacker.hh"
+#include "hb-subset-accelerator.hh"
-using OT::Layout::GSUB::GSUB;
+using OT::Layout::GSUB;
+using OT::Layout::GPOS;
/**
* SECTION:hb-subset
@@ -78,13 +82,121 @@ using OT::Layout::GSUB::GSUB;
* retain glyph ids option and configure the subset to pass through the layout tables untouched.
*/
+
+hb_user_data_key_t _hb_subset_accelerator_user_data_key = {};
+
+
+/*
+ * The list of tables in the open type spec. Used to check for tables that may need handling
+ * if we are unable to list the tables in a face.
+ */
+static hb_tag_t known_tables[] {
+ HB_TAG ('a', 'v', 'a', 'r'),
+ HB_OT_TAG_BASE,
+ HB_OT_TAG_CBDT,
+ HB_OT_TAG_CBLC,
+ HB_OT_TAG_cff1,
+ HB_OT_TAG_cff2,
+ HB_OT_TAG_cmap,
+ HB_OT_TAG_COLR,
+ HB_OT_TAG_CPAL,
+ HB_TAG ('c', 'v', 'a', 'r'),
+ HB_TAG ('c', 'v', 't', ' '),
+ HB_TAG ('D', 'S', 'I', 'G'),
+ HB_TAG ('E', 'B', 'D', 'T'),
+ HB_TAG ('E', 'B', 'L', 'C'),
+ HB_TAG ('E', 'B', 'S', 'C'),
+ HB_TAG ('f', 'p', 'g', 'm'),
+ HB_TAG ('f', 'v', 'a', 'r'),
+ HB_TAG ('g', 'a', 's', 'p'),
+ HB_OT_TAG_GDEF,
+ HB_OT_TAG_glyf,
+ HB_OT_TAG_GPOS,
+ HB_OT_TAG_GSUB,
+ HB_OT_TAG_gvar,
+ HB_OT_TAG_hdmx,
+ HB_OT_TAG_head,
+ HB_OT_TAG_hhea,
+ HB_OT_TAG_hmtx,
+ HB_OT_TAG_HVAR,
+ HB_OT_TAG_JSTF,
+ HB_TAG ('k', 'e', 'r', 'n'),
+ HB_OT_TAG_loca,
+ HB_TAG ('L', 'T', 'S', 'H'),
+ HB_OT_TAG_MATH,
+ HB_OT_TAG_maxp,
+ HB_TAG ('M', 'E', 'R', 'G'),
+ HB_TAG ('m', 'e', 't', 'a'),
+ HB_TAG ('M', 'V', 'A', 'R'),
+ HB_TAG ('P', 'C', 'L', 'T'),
+ HB_OT_TAG_post,
+ HB_TAG ('p', 'r', 'e', 'p'),
+ HB_OT_TAG_sbix,
+ HB_TAG ('S', 'T', 'A', 'T'),
+ HB_TAG ('S', 'V', 'G', ' '),
+ HB_TAG ('V', 'D', 'M', 'X'),
+ HB_OT_TAG_vhea,
+ HB_OT_TAG_vmtx,
+ HB_OT_TAG_VORG,
+ HB_OT_TAG_VVAR,
+ HB_OT_TAG_name,
+ HB_OT_TAG_OS2
+};
+
+static bool _table_is_empty (const hb_face_t *face, hb_tag_t tag)
+{
+ hb_blob_t* blob = hb_face_reference_table (face, tag);
+ bool result = (blob == hb_blob_get_empty ());
+ hb_blob_destroy (blob);
+ return result;
+}
+
+static unsigned int
+_get_table_tags (const hb_subset_plan_t* plan,
+ unsigned int start_offset,
+ unsigned int *table_count, /* IN/OUT */
+ hb_tag_t *table_tags /* OUT */)
+{
+ unsigned num_tables = hb_face_get_table_tags (plan->source, 0, nullptr, nullptr);
+ if (num_tables)
+ return hb_face_get_table_tags (plan->source, start_offset, table_count, table_tags);
+
+ // If face has 0 tables associated with it, assume that it was built from
+ // hb_face_create_tables and thus is unable to list its tables. Fallback to
+ // checking each table type we can handle for existence instead.
+ auto it =
+ 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);
+ })
+ | hb_map ([] (hb_tag_t tag) -> hb_tag_t { return tag; }),
+
+ plan->no_subset_tables.iter ()
+ | hb_filter([&] (hb_tag_t tag) {
+ return !_table_is_empty (plan->source, tag);
+ }));
+
+ it += start_offset;
+
+ unsigned num_written = 0;
+ while (bool (it) && num_written < *table_count)
+ table_tags[num_written++] = *it++;
+
+ *table_count = num_written;
+ return num_written;
+}
+
+
static unsigned
-_plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len)
+_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
+ unsigned table_len,
+ bool same_size)
{
unsigned src_glyphs = plan->source->get_num_glyphs ();
unsigned dst_glyphs = plan->glyphset ()->get_population ();
- if (unlikely (!src_glyphs))
+ if (unlikely (!src_glyphs) || same_size)
return 512 + table_len;
return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
@@ -96,13 +208,6 @@ _plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len)
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 ();
@@ -123,7 +228,6 @@ static
bool
_try_subset (const TableType *table,
hb_vector_t<char>* buf,
- unsigned buf_size,
hb_subset_context_t* c /* OUT */)
{
c->serializer->start_serialize<TableType> ();
@@ -136,57 +240,66 @@ _try_subset (const TableType *table,
return needed;
}
- buf_size += (buf_size >> 1) + 32;
+ unsigned buf_size = buf->allocated;
+ buf_size = buf_size * 2 + 16;
+
+
+
+
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
HB_UNTAG (c->table_tag), buf_size);
- if (unlikely (!buf->alloc (buf_size)))
+ if (unlikely (buf_size > c->source_blob->length * 16 ||
+ !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);
return needed;
}
- c->serializer->reset (buf->arrayZ, buf_size);
- return _try_subset (table, buf, buf_size, c);
+ c->serializer->reset (buf->arrayZ, buf->allocated);
+ return _try_subset (table, buf, c);
}
template<typename TableType>
static bool
-_subset (hb_subset_plan_t *plan)
+_subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
{
- hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
- const TableType *table = source_blob->as<TableType> ();
+ hb_blob_ptr_t<TableType> source_blob = plan->source_table<TableType> ();
+ const TableType *table = source_blob.get ();
hb_tag_t tag = TableType::tableTag;
- if (!source_blob->data)
+ if (!source_blob.get_blob()->data)
{
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
- hb_blob_destroy (source_blob);
+ source_blob.destroy ();
return false;
}
- hb_vector_t<char> buf;
- /* TODO Not all tables are glyph-related. 'name' table size for example should not be
- * affected by number of glyphs. Accommodate that. */
- unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
+ /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's
+ * because those are expensive to subset, so giving them more room is fine. */
+ bool same_size_table = TableType::tableTag == HB_OT_TAG_GSUB ||
+ TableType::tableTag == HB_OT_TAG_GPOS ||
+ TableType::tableTag == HB_OT_TAG_name;
+
+ unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob.get_length (), same_size_table);
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
- hb_blob_destroy (source_blob);
+ source_blob.destroy ();
return false;
}
bool needed = false;
- hb_serialize_context_t serializer (buf.arrayZ, buf_size);
+ hb_serialize_context_t serializer (buf.arrayZ, buf.allocated);
{
- hb_subset_context_t c (source_blob, plan, &serializer, tag);
- needed = _try_subset (table, &buf, buf_size, &c);
+ hb_subset_context_t c (source_blob.get_blob (), plan, &serializer, tag);
+ needed = _try_subset (table, &buf, &c);
}
- hb_blob_destroy (source_blob);
+ source_blob.destroy ();
if (serializer.in_error () && !serializer.only_offset_overflow ())
{
@@ -219,9 +332,17 @@ _subset (hb_subset_plan_t *plan)
static bool
_is_table_present (hb_face_t *source, hb_tag_t tag)
{
+
+ if (!hb_face_get_table_tags (source, 0, nullptr, nullptr)) {
+ // If face has 0 tables associated with it, assume that it was built from
+ // hb_face_create_tables and thus is unable to list its tables. Fallback to
+ // checking if the blob associated with tag is empty.
+ return !_table_is_empty (source, tag);
+ }
+
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
- while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
+ while (((void) hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
if (table_tags[i] == tag)
@@ -234,12 +355,14 @@ _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)
{
case HB_TAG ('c','v','a','r'): /* hint table, fallthrough */
+ return plan->all_axes_pinned || (plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+
case HB_TAG ('c','v','t',' '): /* hint table, fallthrough */
case HB_TAG ('f','p','g','m'): /* hint table, fallthrough */
case HB_TAG ('p','r','e','p'): /* hint table, fallthrough */
@@ -259,6 +382,14 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
return true;
#endif
+ case HB_TAG ('a','v','a','r'):
+ case HB_TAG ('f','v','a','r'):
+ case HB_TAG ('g','v','a','r'):
+ case HB_OT_TAG_HVAR:
+ case HB_OT_TAG_VVAR:
+ case HB_TAG ('M','V','A','R'):
+ return plan->all_axes_pinned;
+
default:
return false;
}
@@ -274,52 +405,78 @@ _passthrough (hb_subset_plan_t *plan, hb_tag_t tag)
}
static bool
-_subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
+_dependencies_satisfied (hb_subset_plan_t *plan, hb_tag_t tag,
+ const hb_set_t &subsetted_tags,
+ const hb_set_t &pending_subset_tags)
+{
+ switch (tag)
+ {
+ case HB_OT_TAG_hmtx:
+ case HB_OT_TAG_vmtx:
+ case HB_OT_TAG_maxp:
+ return !plan->normalized_coords || !pending_subset_tags.has (HB_OT_TAG_glyf);
+ default:
+ return true;
+ }
+}
+
+static bool
+_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);
}
DEBUG_MSG (SUBSET, nullptr, "subset %c%c%c%c", HB_UNTAG (tag));
switch (tag)
{
- case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan);
- case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan);
- case HB_OT_TAG_name: return _subset<const OT::name> (plan);
+ case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan, buf);
+ case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan, buf);
+ case HB_OT_TAG_name: return _subset<const OT::name> (plan, buf);
case HB_OT_TAG_head:
if (_is_table_present (plan->source, HB_OT_TAG_glyf) && !_should_drop_table (plan, HB_OT_TAG_glyf))
return true; /* skip head, handled by glyf */
- return _subset<const OT::head> (plan);
+ return _subset<const OT::head> (plan, buf);
case HB_OT_TAG_hhea: return true; /* skip hhea, handled by hmtx */
- case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan);
+ case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan, buf);
case HB_OT_TAG_vhea: return true; /* skip vhea, handled by vmtx */
- case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan);
- case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan);
- case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan);
+ case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan, buf);
+ case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan, buf);
+ case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan, buf);
case HB_OT_TAG_loca: return true; /* skip loca, handled by glyf */
- case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan);
- case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan);
- case HB_OT_TAG_post: return _subset<const OT::post> (plan);
- case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan);
- case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan);
- case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan);
+ case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan, buf);
+ case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan, buf);
+ case HB_OT_TAG_post: return _subset<const OT::post> (plan, buf);
+ case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan, buf);
+ case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan, buf);
+ case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan, buf);
case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
- case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan);
+ case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan, buf);
#ifndef HB_NO_SUBSET_CFF
- case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan);
- case HB_OT_TAG_cff2: return _subset<const OT::cff2> (plan);
- case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan);
+ case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan, buf);
+ case HB_OT_TAG_cff2: return _subset<const OT::cff2> (plan, buf);
+ case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan, buf);
#endif
#ifndef HB_NO_SUBSET_LAYOUT
- case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan);
- case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan);
- case HB_OT_TAG_GPOS: return _subset<const OT::GPOS> (plan);
- case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan);
- case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan);
- case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan);
+ case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan, buf);
+ case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan, buf);
+ case HB_OT_TAG_GPOS: return _subset<const GPOS> (plan, buf);
+ case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan, buf);
+ case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf);
+ 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);
+ return _subset<const OT::fvar> (plan, buf);
+ case HB_OT_TAG_STAT:
+ /*TODO(qxliu): change the condition as we support more complex
+ * instancing operation*/
+ if (plan->all_axes_pinned) return _subset<const OT::STAT> (plan, buf);
+ else return _passthrough (plan, tag);
default:
if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED)
@@ -330,6 +487,34 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
}
}
+static void _attach_accelerator_data (hb_subset_plan_t* plan,
+ hb_face_t* face /* IN/OUT */)
+{
+ if (!plan->inprogress_accelerator) return;
+
+ // Transfer the accelerator from the plan to us.
+ hb_subset_accelerator_t* accel = plan->inprogress_accelerator;
+ plan->inprogress_accelerator = nullptr;
+
+ if (accel->in_error ())
+ {
+ hb_subset_accelerator_t::destroy (accel);
+ return;
+ }
+
+ // Populate caches that need access to the final tables.
+ hb_blob_ptr_t<OT::cmap> cmap_ptr (hb_sanitize_context_t ().reference_table<OT::cmap> (face));
+ accel->cmap_cache = OT::cmap::create_filled_cache (cmap_ptr);
+ accel->destroy_cmap_cache = OT::SubtableUnicodesCache::destroy;
+
+ if (!hb_face_set_user_data(face,
+ hb_subset_accelerator_t::user_data_key(),
+ accel,
+ hb_subset_accelerator_t::destroy,
+ true))
+ hb_subset_accelerator_t::destroy (accel);
+}
+
/**
* hb_subset_or_fail:
* @source: font face data to be subset.
@@ -375,23 +560,74 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
return nullptr;
}
- hb_set_t tags_set;
- bool success = true;
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
- while ((hb_face_get_table_tags (plan->source, offset, &num_tables, table_tags), num_tables))
+
+ hb_set_t subsetted_tags, pending_subset_tags;
+ while (((void) _get_table_tags (plan, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
{
hb_tag_t tag = table_tags[i];
- if (_should_drop_table (plan, tag) && !tags_set.has (tag)) continue;
- tags_set.add (tag);
- success = _subset_table (plan, tag);
- if (unlikely (!success)) goto end;
+ if (_should_drop_table (plan, tag)) continue;
+ pending_subset_tags.add (tag);
}
+
offset += num_tables;
}
-end:
+ hb_vector_t<char> buf;
+ buf.alloc (4096 - 16);
+
+
+ bool success = true;
+
+ while (!pending_subset_tags.is_empty ())
+ {
+ if (subsetted_tags.in_error ()
+ || pending_subset_tags.in_error ()) {
+ success = false;
+ goto end;
+ }
+
+ bool made_changes = false;
+ for (hb_tag_t tag : pending_subset_tags)
+ {
+ if (!_dependencies_satisfied (plan, tag,
+ subsetted_tags,
+ pending_subset_tags))
+ {
+ // delayed subsetting for some tables since they might have dependency on other tables
+ // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated
+ // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values
+ continue;
+ }
+
+ pending_subset_tags.del (tag);
+ subsetted_tags.add (tag);
+ made_changes = true;
+
+ success = _subset_table (plan, buf, tag);
+ if (unlikely (!success)) goto end;
+ }
+
+ if (!made_changes)
+ {
+ DEBUG_MSG (SUBSET, nullptr, "Table dependencies unable to be satisfied. Subset failed.");
+ success = false;
+ goto end;
+ }
+ }
+
+ if (success && plan->attach_accelerator_data) {
+ _attach_accelerator_data (plan, plan->dest);
+ }
+
+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 a2799d91e8..c14b1b1803 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.h
@@ -28,6 +28,7 @@
#define HB_SUBSET_H
#include "hb.h"
+#include "hb-ot.h"
HB_BEGIN_DECLS
@@ -100,6 +101,8 @@ typedef enum { /*< flags >*/
* @HB_SUBSET_SETS_NAME_LANG_ID: the set of name lang ids that will be retained.
* @HB_SUBSET_SETS_LAYOUT_FEATURE_TAG: the set of layout feature tags that will be retained
* in the subset.
+ * @HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG: the set of layout script tags that will be retained
+ * in the subset. Defaults to all tags. Since: 5.0.0
*
* List of sets that can be configured on the subset input.
*
@@ -113,6 +116,7 @@ typedef enum {
HB_SUBSET_SETS_NAME_ID,
HB_SUBSET_SETS_NAME_LANG_ID,
HB_SUBSET_SETS_LAYOUT_FEATURE_TAG,
+ HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG,
} hb_subset_sets_t;
HB_EXTERN hb_subset_input_t *
@@ -135,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);
@@ -151,6 +158,32 @@ HB_EXTERN void
hb_subset_input_set_flags (hb_subset_input_t *input,
unsigned value);
+HB_EXTERN hb_bool_t
+hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag);
+
+HB_EXTERN hb_bool_t
+hb_subset_input_pin_axis_location (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag,
+ float axis_value);
+
+#ifdef HB_EXPERIMENTAL_API
+HB_EXTERN hb_bool_t
+hb_subset_input_override_name_table (hb_subset_input_t *input,
+ hb_ot_name_id_t name_id,
+ unsigned platform_id,
+ unsigned encoding_id,
+ unsigned language_id,
+ const char *name_str,
+ int str_len);
+
+#endif
+
+HB_EXTERN hb_face_t *
+hb_subset_preprocess (hb_face_t *source);
+
HB_EXTERN hb_face_t *
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
@@ -164,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-ucd-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ucd-table.hh
index 1a4c89c17f..f7d76eee18 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ucd-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ucd-table.hh
@@ -4,7 +4,7 @@
*
* ./gen-ucd-table.py ucd.nounihan.grouped.xml
*
- * on file with this description: Unicode 14.0.0
+ * on file with this description: Unicode 15.0.0
*/
#ifndef HB_UCD_TABLE_HH
@@ -13,7 +13,7 @@
#include "hb.hh"
static const hb_script_t
-_hb_ucd_sc_map[162] =
+_hb_ucd_sc_map[165] =
{
HB_SCRIPT_COMMON, HB_SCRIPT_INHERITED,
HB_SCRIPT_UNKNOWN, HB_SCRIPT_ARABIC,
@@ -96,6 +96,8 @@ _hb_ucd_sc_map[162] =
HB_SCRIPT_YEZIDI, HB_SCRIPT_CYPRO_MINOAN,
HB_SCRIPT_OLD_UYGHUR, HB_SCRIPT_TANGSA,
HB_SCRIPT_TOTO, HB_SCRIPT_VITHKUQI,
+ HB_SCRIPT_MATH, HB_SCRIPT_KAWI,
+ HB_SCRIPT_NAG_MUNDARI,
};
static const uint16_t
_hb_ucd_dm1_p0_map[825] =
@@ -1067,2081 +1069,1128 @@ _hb_ucd_dm2_u64_map[388] =
#ifndef HB_OPTIMIZE_SIZE
static const uint8_t
-_hb_ucd_u8[33120] =
+_hb_ucd_u8[17868] =
{
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 27, 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, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 28, 26, 29, 30, 31, 32, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 33, 34, 34, 34, 34,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 26, 56, 57, 58, 58, 58, 58, 59, 26, 26, 60, 58, 58, 58, 58, 58,
- 58, 58, 26, 61, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 26, 62, 58, 63, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 64, 26, 26, 65, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 66, 67, 68, 58, 58, 58, 58, 69, 58,
- 58, 58, 58, 58, 58, 58, 58, 70, 71, 72, 73, 74, 75, 76, 58, 77,
- 78, 79, 58, 80, 81, 58, 82, 83, 84, 85, 75, 86, 87, 88, 58, 58,
- 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, 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, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 89, 26, 26, 26, 26, 26, 26, 26, 90, 91, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 92, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 93, 58, 58, 58, 58, 58, 58, 26, 94, 58, 58,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 95, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 96, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 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, 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, 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, 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, 35, 35, 35, 35, 35, 35, 35, 97,
- 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, 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, 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, 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, 35, 35, 35, 35, 35, 35, 35, 98,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 29, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 25, 25, 25, 21,
- 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 21, 18, 24, 16,
- 24, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 25, 18, 25, 0,
- 29, 21, 23, 23, 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24,
- 26, 25, 15, 15, 24, 5, 21, 21, 24, 15, 7, 19, 15, 15, 15, 21,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 25, 9, 9, 9, 9, 9, 9, 9, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 5, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9,
- 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 9, 5, 5,
- 5, 9, 9, 5, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 9, 9,
- 9, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 5, 9, 9, 5, 9,
- 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 5, 9, 5, 9, 9,
- 5, 9, 9, 9, 5, 9, 5, 9, 9, 5, 5, 7, 9, 5, 5, 5,
- 7, 7, 7, 7, 9, 8, 5, 9, 8, 5, 9, 8, 5, 9, 5, 9,
- 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5,
- 5, 9, 8, 5, 9, 5, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 9, 9, 5, 9, 9, 5,
- 5, 9, 5, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 6, 6, 6, 6, 6, 24, 24, 24, 24, 24, 24, 24, 6, 24, 6, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 9, 5, 9, 5, 6, 24, 9, 5, 2, 2, 6, 5, 5, 5, 21, 9,
- 2, 2, 2, 2, 24, 24, 9, 21, 9, 9, 9, 2, 9, 2, 9, 9,
- 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9,
- 5, 5, 9, 9, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 5, 5, 5, 5, 9, 5, 25, 9, 5, 9, 9, 5, 5, 9, 9, 9,
- 9, 5, 26, 12, 12, 12, 12, 12, 11, 11, 9, 5, 9, 5, 9, 5,
- 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5,
- 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 2, 2, 6, 21, 21, 21, 21, 21, 21,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 17, 2, 2, 26, 26, 23,
- 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 17, 12,
- 21, 12, 12, 21, 12, 12, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 11, 12, 13, 13, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24, 7, 7,
+ 25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7,
- 7, 7, 7, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 25, 25, 25, 21, 21, 23, 21, 21, 26, 26,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 1, 21, 21, 21,
- 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 7, 7,
- 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 21, 7, 12, 12, 12, 12, 12, 12, 12, 1, 26, 12,
- 12, 12, 12, 12, 12, 6, 6, 12, 12, 26, 12, 12, 12, 12, 7, 7,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 26, 26, 7,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 1,
- 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 6, 6, 26, 21, 21, 21, 6, 2, 2, 12, 23, 23,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 6, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 6, 12, 12, 12, 6, 12, 12, 12, 12, 12, 2, 2,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 2, 2, 21, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 24, 7, 7, 7, 7, 7, 7, 2,
- 1, 1, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 12, 12, 12, 12, 12, 12,
- 12, 12, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 12, 10, 10,
- 7, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 12, 12, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 21, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7,
- 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7,
- 7, 2, 7, 2, 2, 2, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 7, 2,
- 2, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 7, 7, 2, 7,
- 7, 7, 12, 12, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 7, 7, 23, 23, 15, 15, 15, 15, 15, 15, 26, 23, 7, 21, 12, 2,
- 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7,
- 7, 2, 7, 7, 2, 7, 7, 2, 7, 7, 2, 2, 12, 2, 10, 10,
- 10, 12, 12, 2, 2, 2, 2, 12, 12, 2, 2, 12, 12, 12, 2, 2,
- 2, 12, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 2, 7, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 12, 12, 7, 7, 7, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7,
- 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 12, 2, 12, 12, 10, 2, 10, 10, 12, 2, 2,
- 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 21, 23, 2, 2, 2, 2, 2, 2, 2, 7, 12, 12, 12, 12, 12, 12,
- 2, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7,
- 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12,
- 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 2, 2,
- 2, 2, 2, 2, 2, 12, 12, 10, 2, 2, 2, 2, 7, 7, 2, 7,
- 26, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 12, 7, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7,
- 7, 2, 7, 7, 7, 7, 2, 2, 2, 7, 7, 2, 7, 2, 7, 7,
- 2, 2, 2, 7, 7, 2, 2, 2, 7, 7, 7, 2, 2, 2, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 10, 10,
- 12, 10, 10, 2, 2, 2, 10, 10, 10, 2, 10, 10, 10, 12, 2, 2,
- 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 26, 26, 26, 26, 26, 26, 23, 26, 2, 2, 2, 2, 2,
- 12, 10, 10, 10, 12, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 7, 12, 12,
- 12, 10, 10, 10, 10, 2, 12, 12, 12, 2, 12, 12, 12, 12, 2, 2,
- 2, 2, 2, 2, 2, 12, 12, 2, 7, 7, 7, 2, 2, 7, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 21, 15, 15, 15, 15, 15, 15, 15, 26,
- 7, 12, 10, 10, 21, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12,
- 10, 10, 10, 10, 10, 2, 12, 10, 10, 2, 10, 10, 12, 12, 2, 2,
- 2, 2, 2, 2, 2, 10, 10, 2, 2, 2, 2, 2, 2, 7, 7, 2,
- 2, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 2, 10, 10, 10, 2, 10, 10, 10, 12, 7, 26,
- 2, 2, 2, 2, 7, 7, 7, 10, 15, 15, 15, 15, 15, 15, 15, 7,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 7, 7, 7, 7, 7, 7,
- 2, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7, 7, 7, 7, 7,
- 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 12, 2, 2, 2, 2, 10,
- 10, 10, 12, 12, 12, 2, 12, 2, 10, 10, 10, 10, 10, 10, 10, 10,
- 2, 2, 10, 10, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 23,
- 7, 7, 7, 7, 7, 7, 6, 12, 12, 12, 12, 12, 12, 12, 12, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7,
- 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 2, 2,
- 7, 7, 7, 7, 7, 2, 6, 2, 12, 12, 12, 12, 12, 12, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 7, 7, 7, 7,
- 7, 26, 26, 26, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 26, 21, 26, 26, 26, 12, 12, 26, 26, 26, 26, 26, 26,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 26, 12, 26, 12, 26, 12, 22, 18, 22, 18, 10, 10,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2,
- 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
- 12, 12, 12, 12, 12, 21, 12, 12, 7, 7, 7, 7, 7, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 26, 26,
- 26, 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 2, 26, 26,
- 21, 21, 21, 21, 21, 26, 26, 26, 26, 21, 21, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 12,
- 12, 10, 12, 12, 12, 12, 12, 12, 10, 12, 12, 10, 10, 12, 12, 7,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 21, 21,
- 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 7, 7, 7, 7, 12, 12,
- 12, 7, 10, 10, 10, 7, 7, 10, 10, 10, 10, 10, 10, 10, 7, 7,
- 7, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 12, 10, 10, 12, 12, 10, 10, 10, 10, 10, 10, 12, 7, 10,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 12, 26, 26,
- 9, 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 2, 2, 9, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 6, 5, 5, 5,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 2,
- 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 2,
- 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 2, 2, 5, 5, 5, 5, 5, 5, 2, 2,
- 17, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 26, 21, 7,
- 29, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 22, 18, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 21, 21, 14, 14,
- 14, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 12, 12, 12, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7,
- 7, 7, 12, 12, 10, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 2, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, 10, 10,
- 10, 10, 10, 10, 10, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 21, 21, 21, 6, 21, 21, 21, 23, 7, 12, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2,
- 21, 21, 21, 21, 21, 21, 17, 21, 21, 21, 21, 12, 12, 12, 1, 12,
- 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 7, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2,
- 12, 12, 12, 10, 10, 10, 10, 12, 12, 10, 10, 10, 2, 2, 2, 2,
- 10, 10, 12, 10, 10, 10, 10, 10, 10, 12, 12, 12, 2, 2, 2, 2,
- 26, 2, 2, 2, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2,
- 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 2, 2, 2, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 7, 7, 7, 7, 7, 7, 7, 12, 12, 10, 10, 12, 2, 2, 21, 21,
- 7, 7, 7, 7, 7, 10, 12, 10, 12, 12, 12, 12, 12, 12, 12, 2,
- 12, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12,
- 21, 21, 21, 21, 21, 21, 21, 6, 21, 21, 21, 21, 21, 21, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2,
- 12, 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 12, 10, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10,
- 10, 10, 12, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2,
- 21, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 21, 21, 2,
- 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 12, 12, 12, 7, 7,
- 7, 7, 7, 7, 7, 7, 12, 10, 12, 12, 10, 10, 10, 12, 10, 12,
- 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21,
- 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12,
- 12, 12, 12, 12, 10, 10, 12, 12, 2, 2, 2, 21, 21, 21, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 21, 21,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9,
- 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 10, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 12, 7, 7,
- 7, 7, 7, 7, 12, 7, 7, 10, 12, 12, 7, 2, 2, 2, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
- 9, 5, 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9,
- 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 2, 9, 2, 9, 2, 9, 2, 9,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 8,
- 5, 5, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 5, 24,
- 24, 24, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 24,
- 5, 5, 5, 5, 2, 2, 5, 5, 9, 9, 9, 9, 2, 24, 24, 24,
- 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 24, 24, 24,
- 2, 2, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 2,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 1, 1, 1, 1, 1,
- 17, 17, 17, 17, 17, 17, 21, 21, 20, 19, 22, 20, 20, 19, 22, 20,
- 21, 21, 21, 21, 21, 21, 21, 21, 27, 28, 1, 1, 1, 1, 1, 29,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 21, 21, 21, 21, 16,
- 16, 21, 21, 21, 25, 22, 18, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 25, 21, 16, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 29,
- 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 15, 6, 2, 2, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 6,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 2,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
- 11, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 9, 26, 26, 26, 26, 9, 26, 26, 5, 9, 9, 9, 5, 5,
- 9, 9, 9, 5, 26, 9, 26, 26, 25, 9, 9, 9, 9, 9, 26, 26,
- 26, 26, 26, 26, 9, 26, 9, 26, 9, 26, 9, 9, 9, 9, 26, 5,
- 9, 9, 9, 9, 5, 7, 7, 7, 7, 5, 26, 26, 5, 5, 9, 9,
- 25, 25, 25, 25, 25, 9, 5, 5, 5, 5, 26, 25, 26, 26, 5, 26,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 9, 5, 14, 14, 14, 14, 15, 26, 26, 2, 2, 2, 2,
- 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 25, 25, 26, 26, 26, 26,
- 25, 26, 26, 25, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 25, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25,
- 26, 26, 25, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 26, 26, 26, 26,
- 25, 25, 26, 26, 26, 26, 26, 26, 26, 22, 18, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25,
- 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15,
- 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25,
- 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18,
- 22, 18, 22, 18, 22, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 25, 25, 25, 25, 25, 22, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18,
- 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
- 18, 22, 18, 22, 18, 22, 18, 22, 18, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 25, 25,
- 25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 26, 26, 26,
- 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 9, 5, 9, 9, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9,
- 9, 5, 9, 5, 5, 9, 5, 5, 5, 5, 5, 5, 6, 6, 9, 9,
- 9, 5, 9, 5, 5, 26, 26, 26, 26, 26, 26, 9, 5, 9, 5, 12,
- 12, 12, 9, 5, 2, 2, 2, 2, 2, 21, 21, 21, 21, 15, 21, 21,
- 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 2, 2, 5, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 6,
- 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 2,
- 21, 21, 20, 19, 20, 19, 21, 21, 21, 20, 19, 21, 20, 19, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 17, 21, 21, 17, 21, 20, 19, 21, 21,
- 20, 19, 22, 18, 22, 18, 22, 18, 22, 18, 21, 21, 21, 21, 21, 6,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 17, 17, 21, 21, 21, 21,
- 17, 21, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 26, 26, 21, 21, 21, 22, 18, 22, 18, 22, 18, 22, 18, 17, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2,
- 29, 21, 21, 21, 26, 6, 7, 14, 22, 18, 22, 18, 22, 18, 22, 18,
- 22, 18, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18, 17, 22, 18, 18,
- 26, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 10, 10,
- 17, 6, 6, 6, 6, 6, 26, 26, 14, 14, 14, 6, 7, 21, 26, 26,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 24, 24, 6, 6, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 6, 6, 6, 7,
- 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 26, 26, 15, 15, 15, 15, 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, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15, 15, 15,
- 26, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 21, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 2, 2, 2, 2,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 7, 12,
- 11, 11, 11, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 6,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 6, 6, 12, 12,
- 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 12, 12, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2,
- 24, 24, 24, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 24, 24, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 6, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5, 9, 5, 9, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 6, 24, 24, 9, 5, 9, 5, 7,
- 9, 5, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9, 9, 9, 5,
- 9, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 9, 9, 9, 5, 9, 5, 2, 2, 2, 2, 2,
- 9, 5, 2, 5, 2, 5, 9, 5, 9, 5, 2, 2, 2, 2, 2, 2,
- 2, 2, 6, 6, 6, 9, 5, 7, 6, 6, 5, 7, 7, 7, 7, 7,
- 7, 7, 12, 7, 7, 7, 12, 7, 7, 7, 7, 12, 7, 7, 7, 7,
- 7, 7, 7, 10, 10, 12, 12, 10, 26, 26, 26, 26, 12, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 26, 26, 23, 26, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2,
- 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21,
- 12, 12, 7, 7, 7, 7, 7, 7, 21, 21, 21, 7, 21, 7, 7, 12,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 21, 21,
- 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
- 7, 7, 7, 12, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 10,
- 10, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 6,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 21, 21,
- 7, 7, 7, 7, 7, 12, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 10,
- 10, 12, 12, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 21, 21, 21, 21,
- 6, 7, 7, 7, 7, 7, 7, 26, 26, 26, 7, 10, 12, 10, 7, 7,
- 12, 7, 12, 12, 12, 7, 7, 12, 12, 7, 7, 7, 7, 7, 12, 12,
- 7, 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 6, 21, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 12, 12, 10, 10,
- 21, 21, 7, 6, 6, 10, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 2,
- 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 6, 6, 6, 6,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 24, 24, 2, 2, 2, 2,
- 7, 7, 7, 10, 10, 12, 10, 10, 12, 10, 10, 21, 10, 12, 2, 2,
- 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 7, 12, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 25, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 2,
- 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18, 22,
- 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 26,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 23, 26, 26, 26,
- 21, 21, 21, 21, 21, 21, 21, 22, 18, 21, 2, 2, 2, 2, 2, 2,
- 21, 17, 17, 16, 16, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
- 18, 22, 18, 22, 18, 21, 21, 22, 18, 21, 21, 21, 21, 16, 16, 16,
- 21, 21, 21, 2, 21, 21, 21, 21, 17, 22, 18, 22, 18, 22, 18, 21,
- 21, 21, 25, 17, 25, 25, 25, 2, 21, 23, 21, 21, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 1,
- 2, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 25, 18, 25, 22,
- 18, 21, 22, 18, 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6,
- 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7,
- 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 2, 2, 2,
- 23, 23, 25, 24, 26, 23, 23, 2, 26, 25, 25, 25, 25, 26, 26, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 26, 26, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7,
- 21, 21, 21, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 14, 14, 14, 14, 14, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 26, 26, 26, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2,
- 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 2, 2,
- 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2,
- 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7,
- 7, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 21,
- 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 21, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5,
- 9, 9, 9, 9, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9,
- 9, 9, 9, 2, 9, 9, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 2, 2, 2,
- 6, 6, 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 2, 2, 7, 2, 2, 7,
- 7, 7, 7, 7, 7, 7, 2, 21, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 7, 7, 7, 26, 26, 15, 15, 15, 15, 15, 15, 15,
- 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 2, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 15, 15, 7, 7,
- 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 12, 12, 12, 2, 12, 12, 2, 2, 2, 2, 2, 12, 12, 12, 12,
- 7, 7, 7, 7, 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12, 2, 2, 2, 2, 12,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15,
- 7, 7, 7, 7, 7, 7, 7, 7, 26, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 12, 12, 2, 2, 2, 2, 15, 15, 15, 15, 15,
- 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 2, 2, 21, 21, 21, 21, 21, 21, 21,
- 7, 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15,
- 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 12, 12, 17, 2, 2,
- 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 15, 15, 15, 15, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2,
- 7, 7, 12, 12, 12, 12, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2,
- 10, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 21, 21, 2, 2,
- 15, 15, 15, 15, 15, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 12, 7, 7, 12, 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12,
- 10, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 21, 21, 1, 21, 21,
- 21, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
- 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 10, 12, 12, 12,
- 12, 12, 12, 12, 12, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 21, 21, 21, 21, 7, 10, 10, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 12, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
- 10, 7, 7, 7, 7, 21, 21, 21, 21, 12, 12, 12, 12, 21, 10, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 21, 7, 21, 21, 21,
- 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 12,
- 12, 12, 10, 10, 12, 10, 12, 12, 21, 21, 21, 21, 21, 21, 12, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
- 12, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7,
- 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 12, 12, 7, 10, 10,
- 12, 10, 10, 10, 10, 2, 2, 10, 10, 2, 2, 10, 10, 10, 2, 2,
- 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 7, 7, 7,
- 7, 7, 10, 10, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2,
- 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12,
- 10, 10, 12, 12, 12, 10, 12, 7, 7, 7, 7, 21, 21, 21, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 2, 21, 12, 7,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10, 10, 12,
- 12, 10, 12, 12, 7, 7, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10,
- 10, 10, 12, 12, 12, 12, 2, 2, 10, 10, 10, 10, 12, 12, 10, 12,
- 12, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 7, 7, 7, 7, 12, 12, 2, 2,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 12, 10, 12,
- 12, 21, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 10, 10,
- 12, 12, 12, 12, 12, 12, 10, 12, 7, 21, 2, 2, 2, 2, 2, 2,
- 10, 10, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 21, 21, 21, 26,
- 12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 2, 2, 2, 2,
- 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, 2, 2, 7, 7, 7, 7,
- 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 2, 12, 12, 10, 12, 7,
- 10, 7, 10, 12, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7,
- 7, 10, 10, 10, 12, 12, 12, 12, 2, 2, 12, 12, 10, 10, 10, 10,
- 12, 7, 21, 7, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7,
- 7, 7, 7, 12, 12, 12, 12, 12, 12, 10, 7, 12, 12, 12, 12, 21,
- 21, 21, 21, 21, 21, 21, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 12, 12, 12, 12, 12, 12, 10, 10, 12, 12, 12, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 21, 21, 7, 21, 21,
- 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 10, 12,
- 7, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 2, 10, 12, 12, 12, 12, 12, 12,
- 12, 10, 12, 12, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7,
- 7, 12, 12, 12, 12, 12, 12, 2, 2, 2, 12, 2, 12, 12, 2, 12,
- 12, 12, 12, 12, 12, 12, 7, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10, 2,
- 12, 12, 2, 10, 10, 12, 10, 12, 7, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 12, 12, 10, 10, 21, 21, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 23, 23, 23,
- 23, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2,
- 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 26, 26, 26, 26,
- 6, 6, 6, 6, 21, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 15, 15, 15, 15, 15,
- 15, 15, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 7, 7, 7,
- 15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 12,
- 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 12,
- 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 21, 6, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 2, 6, 6, 2,
- 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 26, 12, 12, 21,
- 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 10, 10, 12, 12, 12, 26, 26, 26, 10, 10, 10,
- 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12,
- 12, 12, 12, 26, 26, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 26, 26,
- 26, 26, 12, 12, 12, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5,
- 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 2, 9, 9,
- 2, 2, 9, 2, 2, 9, 9, 2, 2, 9, 9, 9, 9, 2, 9, 9,
- 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 2, 5, 2, 5, 5, 5,
- 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2, 2, 9, 9, 9,
- 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 2, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2,
- 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 9, 9, 9, 9, 9, 9,
- 9, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5,
- 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25,
- 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 5, 2, 2, 13, 13,
+ 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 22, 42,
+ 7, 7, 43, 7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26,
- 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 12, 26, 26, 21, 21, 21, 21, 21, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
- 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12,
- 12, 12, 2, 12, 12, 2, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 7, 26,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 23,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 7, 2,
- 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 5, 5, 5, 5, 12, 12, 12, 12, 12, 12, 12, 6, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15, 15, 15,
- 23, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2,
- 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2, 7, 2, 2, 2, 2,
- 2, 2, 7, 2, 2, 2, 2, 7, 2, 7, 2, 7, 2, 7, 7, 7,
- 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 2, 7, 2, 7, 2, 7,
- 2, 7, 7, 2, 7, 2, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7,
- 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7,
- 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7,
- 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2,
- 2, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 24, 24, 24, 24, 24,
- 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 2, 2, 2, 26, 26, 26, 26, 26, 2, 2, 2,
- 26, 26, 26, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 12, 12, 13, 14, 12, 15, 16, 17, 18, 19, 20,
- 21, 22, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 24, 25,
- 0, 26, 27, 0, 28, 29, 30, 31, 32, 33, 0, 34, 0, 0, 0, 0,
- 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 38, 0, 0, 0, 0,
- 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0,
- 43, 44, 45, 46, 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 50, 0, 0, 0,
- 0, 0, 0, 51, 0, 52, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 54, 55, 0, 0, 0, 0, 56, 0, 0, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 0, 67, 68, 0, 69, 70, 71, 72, 0,
- 61, 0, 73, 74, 75, 76, 0, 0, 70, 0, 77, 78, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 79, 80, 0, 0, 0, 0, 0, 0, 0, 0, 81,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 83, 84, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 86, 0, 80, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 1, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 21, 0, 0, 0, 0, 0, 22, 23, 24,
- 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27,
- 28, 29, 0, 0, 0, 0, 30, 0, 0, 0, 31, 32, 33, 34, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 13, 35, 36, 0, 0, 26, 37, 38, 39, 0, 0, 0, 0, 0, 40,
- 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 42, 43, 1,
- 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 50, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0,
- 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 52, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 49, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 56, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 58, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, 0, 0, 0, 0,
- 0, 0, 62, 63, 64, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 67, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,
- 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 70, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 71,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 74, 75, 0, 0, 0, 0, 0, 0, 0, 0,
- 76, 0, 68, 77, 0, 0, 0, 0, 0, 0, 78, 79, 80, 81, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 70, 0, 0, 0,
- 0, 82, 83, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0,
- 85, 0, 84, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 87,
- 88, 89, 90, 91, 0, 0, 0, 0, 0, 0, 0, 0, 92, 93, 94, 1,
- 1, 1, 95, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 98,
- 99,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 74, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0, 0, 0, 0, 0,103, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 74,105,106, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 91, 0,107, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0,
- 1, 1, 91, 0, 0, 0, 0, 0, 0,108, 0, 0, 0, 0,109, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 0, 76, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111,112,113, 0, 0, 0,
- 0, 0,107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 49, 0, 0, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,115,116, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 26,117, 0,118, 0, 0, 0, 0, 0,119, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 120, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,121, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122,123, 75, 0,
- 0, 0, 0, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0, 0, 0,
- 0, 0, 76,102, 0, 0, 0, 0, 0, 0, 0,125, 0, 0, 0, 0,
- 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0,
- 0, 0,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,126, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0,129, 0, 49, 0, 0,
- 26,130,130, 0, 0, 0, 0, 0, 0, 0, 0, 0,131, 0, 0, 51,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,132, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,133, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,134, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,109, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,110, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0,102, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,136, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,137, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,138, 0, 0, 0, 0, 0, 0, 0,139, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,140, 0, 0, 0, 0,141, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 142,143,144,145,146,147, 0, 0, 0,148, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,149, 0, 0, 0,
- 0, 0, 0, 0,139, 1, 1,150,151,117, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0,
- 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,153, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,
- 230,230,230,230,230,230,230,230,230,232,220,220,220,220,232,216,
- 220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
- 220,220,220,220,220,220,220,220, 1, 1, 1, 1, 1,220,220,220,
- 220,230,230,230,230,230,230,230,230,240,230,220,220,220,230,230,
- 230,220,220, 0,230,230,230,220,220,220,220,230,232,220,220,230,
- 233,234,234,233,234,234,233,230,230,230,230,230, 0, 0, 0,230,
- 230,230,230,230, 0,220,230,230,230,230,220,230,230,230,222,220,
- 230,230,230,230,230,230,220,220,220,220,220,220,230,230,220,230,
- 230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
- 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0,
- 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,
- 230,220,220,230,230,230,230,230,220,230,230,220, 35, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,230,230,
- 230, 0, 0,230,230,230,230,220,230, 0, 0,230,230, 0,220,230,
- 230,220, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0,230,220,230,230,
- 220,230,230,220,220,220,230,220,220,230,220,230,230,230,220,230,
- 220,230,220,230,220,230,230, 0, 0, 0, 0, 0,230,230,220,230,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0, 0,230,230, 0,230,
- 230,230,230,230,230,230,230,230, 0,230,230,230, 0,230,230,230,
- 230,230, 0, 0, 0,220,220,220, 0, 0, 0, 0,230,220,220,220,
- 230,230,230,230, 0, 0,230,230,230,230,230,220,220,220,220,220,
- 230,230,230,230,230,230, 0,220,230,230,220,230,230,220,230,230,
- 230,220,220,220, 27, 28, 29,230,230,230,220,230,230,220,220,230,
- 230,230,230,230, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,
- 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,230, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 9,
- 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,103,103, 9, 0,
- 0, 0, 0, 0,107,107,107,107, 0, 0, 0, 0,118,118, 9, 0,
- 0, 0, 0, 0,122,122,122,122, 0, 0, 0, 0,220,220, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,220, 0,216, 0, 0,
- 0, 0, 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130,
- 130,130, 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0, 0, 0,
- 0, 0,220, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230, 0, 0, 0, 0,
- 9, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
- 0,230, 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0,222,230,220,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,220, 0, 0, 0,
- 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,
- 230, 0, 0,220,230,230,230,230,230,220,220,220,220,220,220,230,
- 230,220, 0,220,220,230,230,220,220,230,230,230,230,230,220,230,
- 230,230,230, 0, 0, 0, 0,230,220,230,230,230,230,230,230,230,
- 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 7, 0,230,230,230, 0, 1,220,220,220,220,220,230,230,
- 220,220,220,220,230, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- 0,220, 0, 0, 0, 0, 0, 0,230, 0, 0, 0,230,230, 0, 0,
- 0, 0, 0, 0,230,230,220,230,230,230,230,230,230,230,220,230,
- 230,234,214,220,202,230,230,230,230,230,230,230,230,230,230,230,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
+ 69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
+ 84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
+ 91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96,
+ 97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105,
+ 106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+ 107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117,
+ 118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
+ 132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
+ 147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
+ 160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173,
+ 34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177,
+ 34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122,
+ 34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191,
+ 34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197,
+ 69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211,
+ 69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122,
+ 215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220,
+ 34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122,
+ 228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236,
+ 237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34,
+ 244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34,246,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34,247,122,122,122,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34, 34, 34,248, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34,249,122,122,122,122,122,122,122,122,
+ 250,122,251,252,122,122,122,122,122,122,122,122,122,122,122,122,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,253,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2,
+ 7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 17, 18, 19, 1, 20, 20, 21, 22, 23, 24, 25,
+ 26, 27, 15, 2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32,
+ 32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11,
+ 11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11,
+ 34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34,
+ 34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32,
+ 32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32,
+ 16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41,
+ 40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41,
+ 43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 44, 45, 16, 10,
+ 44, 44, 41, 46, 11, 47, 47, 11, 34, 11, 11, 11, 11, 11, 11, 11,
+ 11, 48, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34,
+ 16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 49, 34, 32, 34, 11,
+ 32, 50, 43, 43, 51, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16,
+ 48, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 47, 52, 2, 2, 2,
+ 16, 16, 16, 16, 53, 54, 55, 56, 57, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 58, 59, 60, 43, 59, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 62,
+ 36, 63, 64, 44, 44, 44, 44, 44, 65, 65, 65, 8, 9, 66, 2, 67,
+ 43, 43, 43, 43, 43, 60, 68, 2, 69, 36, 36, 36, 36, 70, 43, 43,
+ 7, 7, 7, 7, 7, 2, 2, 36, 71, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 72, 43, 43, 43, 73, 50, 43, 43, 74, 75, 76, 43, 43, 36,
+ 7, 7, 7, 7, 7, 36, 77, 78, 2, 2, 2, 2, 2, 2, 2, 79,
+ 70, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 80, 62, 36,
+ 36, 36, 36, 43, 43, 43, 43, 43, 71, 44, 44, 44, 44, 44, 44, 44,
+ 7, 7, 7, 7, 7, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43,
+ 43, 43, 40, 21, 2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
+ 43, 43, 75, 43, 75, 43, 43, 44, 2, 2, 2, 2, 2, 2, 2, 64,
+ 36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
+ 36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43,
+ 36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43,
+ 43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86,
+ 87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36,
+ 36, 43, 2, 7, 7, 7, 7, 7, 88, 36, 36, 36, 36, 36, 36, 36,
+ 70, 86, 62, 36, 36, 36, 61, 62, 61, 62, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 61, 36, 36, 36, 61, 61, 44, 36, 36, 44, 71, 86,
+ 87, 43, 80, 89, 90, 89, 87, 61, 44, 44, 44, 89, 44, 44, 36, 62,
+ 36, 43, 44, 7, 7, 7, 7, 7, 36, 20, 27, 27, 27, 56, 63, 80,
+ 57, 85, 62, 36, 36, 61, 44, 62, 61, 36, 62, 61, 36, 44, 80, 86,
+ 87, 80, 44, 57, 80, 57, 43, 44, 57, 44, 44, 44, 62, 36, 61, 61,
+ 44, 44, 44, 7, 7, 7, 7, 7, 43, 36, 70, 64, 44, 44, 44, 44,
+ 57, 85, 62, 36, 36, 36, 36, 62, 36, 62, 36, 36, 36, 36, 36, 36,
+ 61, 36, 62, 36, 36, 44, 71, 86, 87, 43, 43, 57, 85, 89, 87, 44,
+ 61, 44, 44, 44, 44, 44, 44, 44, 66, 44, 44, 44, 62, 43, 43, 43,
+ 57, 86, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 44, 71, 87,
+ 87, 43, 80, 89, 90, 89, 87, 44, 44, 44, 57, 85, 44, 44, 36, 62,
+ 78, 27, 27, 27, 44, 44, 44, 44, 44, 71, 62, 36, 36, 61, 44, 36,
+ 61, 36, 36, 44, 62, 61, 61, 36, 44, 62, 61, 44, 36, 61, 44, 36,
+ 36, 36, 36, 36, 36, 44, 44, 86, 85, 90, 44, 86, 90, 86, 87, 44,
+ 61, 44, 44, 89, 44, 44, 44, 44, 27, 91, 67, 67, 56, 92, 44, 44,
+ 85, 86, 71, 36, 36, 36, 61, 36, 61, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 44, 71, 43, 85, 86, 90, 43, 80, 43, 43, 44,
+ 44, 44, 57, 80, 36, 61, 62, 44, 44, 44, 44, 93, 27, 27, 27, 91,
+ 70, 86, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 87,
+ 86, 86, 90, 85, 90, 86, 43, 44, 44, 44, 89, 90, 44, 44, 62, 61,
+ 62, 94, 44, 44, 44, 44, 44, 44, 43, 86, 36, 36, 36, 36, 61, 36,
+ 36, 36, 36, 36, 36, 70, 71, 86, 87, 43, 80, 86, 90, 86, 87, 77,
+ 44, 44, 36, 94, 27, 27, 27, 95, 27, 27, 27, 27, 91, 36, 36, 36,
+ 57, 86, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36,
+ 36, 62, 36, 36, 36, 36, 62, 44, 36, 36, 36, 61, 44, 80, 44, 89,
+ 86, 43, 80, 80, 86, 86, 86, 86, 44, 86, 64, 44, 44, 44, 44, 44,
+ 62, 36, 36, 36, 36, 36, 36, 36, 70, 36, 43, 43, 43, 80, 44, 96,
+ 36, 36, 36, 75, 43, 43, 43, 60, 7, 7, 7, 7, 7, 2, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 61, 36, 36, 61, 36, 36,
+ 36, 36, 62, 62, 36, 36, 36, 36, 70, 36, 43, 43, 43, 43, 71, 44,
+ 36, 36, 61, 81, 43, 43, 43, 80, 7, 7, 7, 7, 7, 44, 36, 36,
+ 77, 67, 2, 2, 2, 2, 2, 2, 2, 97, 97, 67, 43, 67, 67, 67,
+ 7, 7, 7, 7, 7, 27, 27, 27, 27, 27, 50, 50, 50, 4, 4, 86,
+ 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44,
+ 57, 43, 43, 43, 43, 43, 43, 85, 43, 43, 60, 43, 36, 36, 70, 43,
+ 43, 43, 43, 43, 57, 43, 43, 43, 43, 43, 43, 43, 43, 43, 80, 67,
+ 67, 67, 67, 76, 67, 67, 92, 67, 2, 2, 97, 67, 21, 64, 44, 44,
+ 36, 36, 36, 36, 36, 94, 87, 43, 85, 43, 43, 43, 87, 85, 87, 71,
+ 7, 7, 7, 7, 7, 2, 2, 2, 36, 36, 36, 86, 43, 36, 36, 43,
+ 71, 86, 98, 94, 86, 86, 86, 36, 70, 43, 71, 36, 36, 36, 36, 36,
+ 36, 85, 87, 85, 86, 86, 87, 94, 7, 7, 7, 7, 7, 86, 87, 67,
+ 11, 11, 11, 48, 44, 44, 48, 44, 16, 16, 16, 16, 16, 53, 45, 16,
+ 36, 36, 36, 36, 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44,
+ 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44, 36, 36, 36, 36,
+ 36, 36, 36, 61, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 57, 43,
+ 2, 2, 2, 2, 99, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44,
+ 67, 67, 67, 67, 67, 44, 44, 44, 11, 11, 11, 44, 16, 16, 16, 44,
+ 101, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 77, 72,
+ 102, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,103,104, 44,
+ 36, 36, 36, 36, 36, 63, 2,105,106, 36, 36, 36, 61, 44, 44, 44,
+ 36, 43, 85, 44, 44, 44, 44, 62, 36, 43,107, 64, 44, 44, 44, 44,
+ 36, 43, 44, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 61, 36,
+ 61, 43, 44, 44, 44, 44, 44, 44, 36, 36, 43, 87, 43, 43, 43, 86,
+ 86, 86, 86, 85, 87, 43, 43, 43, 43, 43, 2, 88, 2, 66, 70, 44,
+ 7, 7, 7, 7, 7, 44, 44, 44, 27, 27, 27, 27, 27, 44, 44, 44,
+ 2, 2, 2,108, 2, 59, 43, 84, 36, 83, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 61, 44, 44, 44, 36, 36, 70, 71, 36, 36, 36, 36,
+ 36, 36, 36, 36, 70, 61, 44, 44, 36, 36, 36, 44, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 61, 43, 85, 86, 87, 85, 86, 44, 44,
+ 86, 85, 86, 86, 87, 43, 44, 44, 92, 44, 2, 7, 7, 7, 7, 7,
+ 36, 36, 36, 36, 36, 36, 36, 44, 36, 36, 61, 44, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 44, 44, 36, 36, 36, 36, 36, 44, 44, 44,
+ 7, 7, 7, 7, 7,100, 44, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 36, 36, 36, 70, 85, 87, 44, 2, 36, 36, 94, 85, 43, 43, 43, 80,
+ 85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57,
+ 2, 2, 2, 88, 2, 2, 2, 44, 43, 43, 43, 43, 43, 43, 43,109,
+ 43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36,
+ 36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44,
+ 97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64,
+ 43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36,
+ 36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44, 2, 2,
+ 36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93, 2, 2,
+ 7, 7, 7, 7, 7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40, 2,
+ 16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
+ 2, 2, 2, 2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
+ 85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44,
+ 16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
+ 16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16,111, 40, 40,
+ 32, 32, 32, 16, 16, 16, 16, 32, 16, 16, 16, 16, 11, 11, 11, 11,
+ 16, 16, 16, 44, 11, 11, 11, 44, 16, 16, 16, 16, 48, 48, 48, 48,
+ 16, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16, 16,112,112,112,112,
+ 16, 16,110, 16, 11, 11,113,114, 41, 16,110, 16, 11, 11,113, 41,
+ 16, 16, 44, 16, 11, 11,115, 41, 16, 16, 16, 16, 11, 11,116, 41,
+ 44, 16,110, 16, 11, 11,113,117,118,118,118,118,118,119, 65, 65,
+ 120,120,120, 2,121,122,121,122, 2, 2, 2, 2,123, 65, 65,124,
+ 2, 2, 2, 2,125,126, 2,127,128, 2,129,130, 2, 2, 2, 2,
+ 2, 9,128, 2, 2, 2, 2,131, 65, 65,132, 65, 65, 65, 65, 65,
+ 133, 44, 27, 27, 27, 8,129,134, 27, 27, 27, 27, 27, 8,129,104,
+ 40, 40, 40, 40, 40, 40, 81, 44, 20, 20, 20, 20, 20, 20, 20, 20,
+ 135, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43,136, 51,
+ 109, 51,109, 43, 43, 43, 43, 43, 80, 44, 44, 44, 44, 44, 44, 44,
+ 67,137, 67,138, 67, 34, 11, 16, 11, 32,138, 67, 49, 11, 11, 67,
+ 67, 67,137,137,137, 11, 11,139, 11, 11, 35, 36, 39, 67, 16, 11,
+ 8, 8, 49, 16, 16, 26, 67,140, 27, 27, 27, 27, 27, 27, 27, 27,
+ 105,105,105,105,105,105,105,105,105,141,142,105,143, 67, 44, 44,
+ 8, 8,144, 67, 67, 8, 67, 67,144, 26, 67,144, 67, 67, 67,144,
+ 67, 67, 67, 67, 67, 67, 67, 8, 67,144,144, 67, 67, 67, 67, 67,
+ 67, 67, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 67, 67, 67, 67, 4, 4, 67, 67, 8, 67, 67, 67,145,146, 67, 67,
+ 67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26, 8, 8,
+ 8, 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8,
+ 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
+ 67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
+ 26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, 8, 8,
+ 67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67, 4, 4, 4, 4,
+ 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
+ 8, 8,129,147, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4,
+ 8,129,148,148,148,148,148,148,148,148,148,148,147, 8, 8, 8,
+ 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8,
+ 8, 8,144, 26, 8, 8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67,
+ 67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11,
+ 32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149,
+ 43, 32, 44, 44, 93, 2, 99, 2, 16, 16, 16,150, 44, 44,150, 44,
+ 36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
+ 36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
+ 2,121,121, 2,125,126,121, 2, 2, 2, 2, 6, 2,108,121, 2,
+ 121, 4, 4, 4, 4, 2, 2, 88, 2, 2, 2, 2, 2,120, 2, 2,
+ 108,151, 2, 2, 2, 2, 2, 2, 67, 2,152,148,148,148,153, 44,
+ 67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44,
+ 1, 2,154,155, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4,156,157,
+ 158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67,
+ 36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69,
+ 44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67,
+ 67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27,
+ 36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164, 2,
+ 7, 7, 7, 7, 7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70,
+ 51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43,
+ 36, 36, 36,105,105,105,105,105, 43, 2, 2, 2, 44, 44, 44, 44,
+ 41, 41, 41,162, 40, 40, 40, 40, 41, 32, 32, 32, 32, 32, 32, 32,
+ 16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32,
+ 32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
+ 32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44,
+ 44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
+ 36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44,
+ 36, 36, 2, 2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 86, 86, 86, 86, 86, 86, 86, 86, 43, 44, 44, 44, 44, 2,
+ 43, 36, 36, 36, 2, 72, 72, 70, 36, 36, 36, 43, 43, 43, 43, 2,
+ 36, 36, 36, 70, 43, 43, 43, 43, 43, 86, 44, 44, 44, 44, 44, 93,
+ 36, 70, 86, 43, 43, 86, 43, 86,107, 2, 2, 2, 2, 2, 2, 52,
+ 7, 7, 7, 7, 7, 44, 44, 2, 36, 36, 70, 69, 36, 36, 36, 36,
+ 7, 7, 7, 7, 7, 36, 36, 61, 36, 36, 36, 36, 70, 43, 43, 85,
+ 87, 85, 87, 80, 44, 44, 44, 44, 36, 70, 36, 36, 36, 36, 85, 44,
+ 7, 7, 7, 7, 7, 44, 2, 2, 69, 36, 36, 77, 67, 94, 85, 36,
+ 71, 43, 71, 70, 71, 36, 36, 43, 70, 61, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 62, 83, 2, 36, 36, 36, 36, 36, 94, 43, 86,
+ 2, 83,169, 80, 44, 44, 44, 44, 62, 36, 36, 61, 62, 36, 36, 61,
+ 62, 36, 36, 61, 44, 44, 44, 44, 16, 16, 16, 16, 16,114, 40, 40,
+ 16, 16, 16, 16,111, 41, 44, 44, 36, 94, 87, 86, 85,107, 87, 44,
+ 36, 36, 44, 44, 44, 44, 44, 44, 36, 36, 36, 61, 44, 62, 36, 36,
+ 170,170,170,170,170,170,170,170,171,171,171,171,171,171,171,171,
+ 16, 16, 16,110, 44, 44, 44, 44, 44,150, 16, 16, 44, 44, 62, 71,
+ 36, 36, 36, 36,172, 36, 36, 36, 36, 36, 36, 61, 36, 36, 61, 61,
+ 36, 62, 61, 36, 36, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
+ 41,117, 44, 44, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36,148, 44, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 44, 44, 44, 55, 36, 36, 36, 36, 36, 36,168, 67,
+ 2, 2, 2,152,130, 44, 44, 44, 6,173,174,148,148,148,148,148,
+ 148,148,130,152,130, 2,127,175, 2, 64, 2, 2,156,148,148,130,
+ 2,176, 8,177, 66, 2, 44, 44, 36, 36, 61, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 61, 79, 93, 2, 3, 2, 4, 5, 6, 2,
+ 16, 16, 16, 16, 16, 17, 18,129,130, 4, 2, 36, 36, 36, 36, 36,
+ 69, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40,
+ 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 61, 44,
+ 20,178, 56,135, 26, 8,144, 92, 44, 44, 44, 44, 79, 65, 67, 44,
+ 36, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 61, 36, 62,
+ 2, 64, 44,179, 27, 27, 27, 27, 27, 27, 44, 55, 67, 67, 67, 67,
+ 105,105,143, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 27, 67, 92,
+ 67, 67, 67, 67, 67, 67, 92, 44, 92, 44, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 67, 50, 44,180, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 44, 44, 27, 27, 44, 44, 44, 44, 62, 36,
+ 155, 36, 36, 36, 36,181, 44, 44, 36, 36, 36, 43, 43, 80, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 93, 36, 36, 44, 44, 36, 36, 36, 36,
+ 182,105,105, 44, 44, 44, 44, 44, 11, 11, 11, 11, 16, 16, 16, 16,
+ 11, 11, 44, 44, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 44, 44,
+ 36, 36, 36, 36, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44, 44, 93,
+ 11, 11, 11, 11, 11, 47, 11, 11, 11, 47, 11,150, 16, 16, 16, 16,
+ 16,150, 16, 16, 16, 16, 16, 16, 16,150, 16, 16, 16,150,110, 44,
+ 40, 40, 40, 52, 40, 40, 40, 40, 81, 40, 40, 40, 40, 81, 44, 44,
+ 36, 36, 36, 44, 61, 36, 36, 36, 36, 36, 36, 62, 61, 44, 61, 62,
+ 36, 36, 36, 93, 27, 27, 27, 27, 36, 36, 36, 77,163, 27, 27, 27,
+ 44, 44, 44,179, 27, 27, 27, 27, 36, 61, 36, 44, 44,179, 27, 27,
+ 36, 36, 36, 27, 27, 27, 44, 93, 36, 36, 36, 36, 36, 44, 44, 93,
+ 36, 36, 36, 36, 44, 44, 27, 36, 44, 27, 27, 27, 27, 27, 27, 27,
+ 70, 43, 57, 80, 44, 44, 43, 43, 36, 36, 62, 36, 62, 36, 36, 36,
+ 36, 36, 36, 44, 43, 80, 44, 57, 27, 27, 27, 27,100, 44, 44, 44,
+ 2, 2, 2, 2, 64, 44, 44, 44, 36, 36, 36, 36, 36, 36,183, 30,
+ 36, 36, 36, 36, 36, 36,183, 27, 36, 36, 36, 36, 78, 36, 36, 36,
+ 36, 36, 70, 80, 44,179, 27, 27, 2, 2, 2, 64, 44, 44, 44, 44,
+ 36, 36, 36, 44, 93, 2, 2, 2, 36, 36, 36, 44, 27, 27, 27, 27,
+ 36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93, 2, 64, 44,
+ 44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
+ 16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
+ 27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
+ 36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43,
+ 27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30, 2, 2, 44, 44, 44,
+ 36, 43, 43, 2, 2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44,
+ 87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43,
+ 43, 43, 43, 60, 2, 2, 2, 44, 27, 27, 27, 7, 7, 7, 7, 7,
+ 71, 70, 71, 44, 44, 44, 44, 57, 86, 87, 43, 85, 87, 60,185, 2,
+ 2, 80, 44, 44, 44, 44, 79, 44, 43, 71, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 70, 43, 43, 87, 43, 43, 43, 80, 7, 7, 7, 7, 7,
+ 2, 2, 94, 98, 44, 44, 44, 44, 36, 70, 2, 61, 44, 44, 44, 44,
+ 36, 94, 86, 43, 43, 43, 43, 85, 98, 36, 63, 2, 59, 43, 60, 87,
+ 7, 7, 7, 7, 7, 63, 63, 2,179, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27,100, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 86, 87,
+ 43, 86, 85, 43, 2, 2, 2, 71, 70, 44, 44, 44, 44, 44, 44, 44,
+ 36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62,
+ 36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70,
+ 86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
+ 61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44,
+ 61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44,
+ 43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43,
+ 86, 43, 85, 71, 36, 63, 2, 2, 7, 7, 7, 7, 7, 2, 93, 71,
+ 86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87,
+ 60, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 43, 44,
+ 86, 87, 43, 43, 43, 85, 87, 87, 60, 2, 61, 44, 44, 44, 44, 44,
+ 2, 2, 2, 2, 2, 2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86,
+ 43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44,
+ 7, 7, 7, 7, 7, 27, 2, 97, 43, 43, 43, 43, 87, 60, 44, 44,
+ 27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36,
+ 36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71,
+ 98, 87, 2, 64, 44, 44, 44, 44, 36, 36, 36, 36, 44, 36, 36, 36,
+ 94, 86, 43, 43, 44, 43, 86, 86, 71, 72, 90, 44, 44, 44, 44, 44,
+ 70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 85, 70, 43, 60,
+ 2, 2, 2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
+ 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43, 2, 72, 2,
+ 2, 64, 44, 44, 44, 44, 44, 44, 2, 2, 2, 2, 2, 44, 44, 44,
+ 43, 43, 43, 80, 43, 43, 43, 87, 63, 2, 2, 44, 44, 44, 44, 44,
+ 2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44,
+ 36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57,
+ 43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36,
+ 36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44,
+ 36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36,
+ 36, 36, 86, 43, 43, 80, 44, 86, 85, 60, 2, 2, 2, 2, 2, 2,
+ 27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
+ 67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
+ 2, 2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
+ 65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43,
+ 43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
+ 43, 43, 43, 60, 2, 2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
+ 7, 7, 7, 7, 7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30, 2, 64, 44, 44,
+ 36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
+ 43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
+ 86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
+ 36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44,
+ 36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
+ 43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
+ 67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
+ 86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67,
+ 67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44,
+ 27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
+ 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
+ 16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
+ 11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16,
+ 16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
+ 16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
+ 47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
+ 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
+ 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
+ 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
+ 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
+ 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 43, 43, 43, 76, 67, 50, 43, 43,
+ 43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
+ 67, 67, 76, 21, 2, 2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
+ 16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
+ 44, 44,150, 16, 16,110, 44, 44, 43, 43, 43, 80, 43, 43, 43, 43,
+ 43, 43, 43, 43, 80, 57, 43, 43, 43, 57, 80, 43, 43, 80, 44, 44,
+ 40, 40, 40, 40, 40, 40, 40, 44, 44, 44, 44, 44, 44, 44, 44, 57,
+ 43, 43, 43, 74, 40, 40, 40, 44, 7, 7, 7, 7, 7, 44, 44, 77,
+ 36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43,
+ 7, 7, 7, 7, 7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43,
+ 36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
+ 16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
+ 188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
+ 27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36,
+ 62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44,
+ 44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62,
+ 62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61,
+ 36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36,
+ 8, 44, 44, 44, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67,
+ 27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
+ 44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67,
+ 67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 44, 44, 44, 44, 67,
+ 67, 92, 67, 67, 67, 67, 67, 67, 79, 44, 44, 44, 44, 44, 44, 44,
+ 171,171,171,171,171,171,171, 44,171,171,171,171,171,171,171, 0,
+ 0, 0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13,
+ 25, 25, 25, 21, 21, 9, 9, 9, 9, 22, 21, 18, 24, 16, 24, 5,
+ 5, 5, 5, 22, 25, 18, 25, 0, 23, 23, 26, 21, 24, 26, 7, 20,
+ 25, 1, 26, 24, 26, 25, 15, 15, 24, 15, 7, 19, 15, 21, 9, 25,
+ 9, 5, 5, 25, 5, 9, 5, 7, 7, 7, 9, 8, 8, 5, 7, 5,
+ 6, 6, 24, 24, 6, 24, 12, 12, 2, 2, 6, 5, 9, 21, 9, 2,
+ 2, 9, 25, 9, 26, 12, 11, 11, 2, 6, 5, 21, 17, 2, 2, 26,
+ 26, 23, 2, 12, 17, 12, 21, 12, 12, 21, 7, 2, 2, 7, 7, 21,
+ 21, 2, 1, 1, 21, 23, 26, 26, 1, 21, 6, 7, 7, 12, 12, 7,
+ 21, 7, 12, 1, 12, 6, 6, 12, 12, 26, 7, 26, 26, 7, 2, 1,
+ 12, 2, 6, 2, 24, 7, 7, 6, 1, 12, 12, 10, 10, 10, 10, 12,
+ 21, 6, 2, 10, 10, 2, 15, 26, 26, 2, 2, 21, 7, 10, 15, 7,
+ 2, 23, 21, 26, 10, 7, 21, 15, 15, 2, 17, 7, 29, 7, 7, 22,
+ 18, 2, 14, 14, 14, 7, 10, 21, 17, 21, 11, 12, 5, 2, 5, 6,
+ 8, 8, 8, 24, 5, 24, 2, 24, 9, 24, 24, 2, 29, 29, 29, 1,
+ 17, 17, 20, 19, 22, 20, 27, 28, 1, 29, 21, 20, 19, 21, 21, 16,
+ 16, 21, 25, 22, 18, 21, 21, 29, 1, 2, 15, 6, 18, 6, 23, 2,
+ 12, 11, 9, 26, 26, 9, 26, 5, 5, 26, 14, 9, 5, 14, 14, 15,
+ 25, 26, 26, 22, 18, 26, 18, 25, 18, 22, 5, 12, 2, 5, 22, 21,
+ 21, 22, 18, 17, 26, 6, 7, 14, 17, 22, 18, 18, 26, 14, 17, 6,
+ 14, 6, 12, 24, 24, 6, 26, 15, 6, 21, 11, 21, 24, 9, 6, 9,
+ 23, 26, 6, 10, 4, 4, 3, 3, 7, 25, 17, 16, 16, 22, 16, 16,
+ 25, 17, 25, 2, 25, 24, 2, 15, 12, 15, 14, 2, 21, 14, 7, 15,
+ 12, 17, 21, 1, 26, 10, 10, 1, 23, 15, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 0, 10, 11, 12, 13, 0, 14, 0, 0, 0, 0, 0,
+ 15, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 19,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 20, 0, 21, 22, 23, 0, 0, 0, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35,
+ 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 38, 39, 0, 0, 0, 0, 0, 0, 40, 41, 42, 0, 43, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0,
+ 0, 0, 3, 0, 0, 0, 4, 5, 6, 7, 0, 8, 9, 10, 0, 11,
+ 12, 13, 14, 15, 16, 17, 16, 18, 16, 19, 16, 19, 16, 19, 0, 19,
+ 16, 20, 16, 19, 21, 19, 0, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0,
+ 0, 0, 0, 0, 34, 0, 0, 35, 0, 0, 36, 0, 37, 0, 0, 0,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 0, 0, 47, 0, 0, 0, 48,
+ 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 50, 0, 51, 0, 52,
+ 53, 0, 54, 0, 0, 0, 0, 0, 0, 55, 56, 57, 0, 0, 0, 0,
+ 58, 0, 0, 59, 60, 61, 62, 63, 0, 0, 64, 65, 0, 0, 0, 66,
+ 0, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 70, 0, 71, 0, 0,
+ 72, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0,
+ 0, 0, 75, 76, 0, 77, 78, 0, 0, 79, 80, 0, 81, 62, 0, 82,
+ 83, 0, 0, 84, 85, 86, 0, 0, 0, 87, 0, 88, 0, 0, 51, 89,
+ 51, 0, 90, 0, 91, 0, 0, 0, 80, 0, 0, 0, 92, 93, 0, 94,
+ 95, 96, 97, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 98, 99, 0,
+ 0, 0, 0, 0, 0,100, 0, 0, 0, 0, 0,101,102, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,103, 0, 0,104, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,105,106, 0, 0,107, 0, 0, 0, 0, 0, 0,
+ 108, 0,109, 0,102, 0, 0, 0, 0, 0,110,111, 0, 0, 0, 0,
+ 0, 0, 0,112, 0, 0, 0, 0, 0, 0, 0,113, 0,114, 0, 0,
+ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 8, 0, 0, 0,
+ 0, 9, 10, 11, 12, 0, 0, 0, 0, 13, 0, 0, 14, 15, 0, 16,
+ 0, 17, 18, 0, 0, 19, 0, 20, 21, 0, 0, 0, 0, 0, 22, 23,
+ 0, 24, 25, 0, 0, 26, 0, 0, 0, 27, 0, 0, 28, 29, 30, 31,
+ 0, 0, 0, 32, 33, 34, 0, 0, 33, 0, 0, 35, 33, 0, 0, 0,
+ 33, 36, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0, 0, 0, 39,
+ 40, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 43, 0, 44,
+ 0, 0, 0, 45, 46, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 48,
+ 49, 0, 0, 0, 0, 50, 0, 0, 0, 51, 0, 52, 0, 53, 0, 0,
+ 0, 0, 54, 0, 0, 0, 0, 55, 0, 56, 0, 0, 0, 0, 57, 58,
+ 0, 0, 0, 59, 60, 0, 0, 0, 0, 0, 0, 61, 52, 0, 62, 63,
+ 0, 0, 64, 0, 0, 0, 65, 66, 0, 0, 0, 67, 0, 68, 69, 70,
+ 71, 72, 1, 73, 0, 74, 75, 76, 0, 0, 77, 78, 0, 0, 0, 79,
+ 0, 0, 1, 1, 0, 0, 80, 0, 0, 81, 0, 0, 0, 0, 77, 82,
+ 0, 83, 0, 0, 0, 0, 0, 78, 84, 0, 85, 0, 52, 0, 1, 78,
+ 0, 0, 86, 0, 0, 87, 0, 0, 0, 0, 0, 88, 57, 0, 0, 0,
+ 0, 0, 0, 89, 90, 0, 0, 84, 0, 0, 33, 0, 0, 91, 0, 0,
+ 0, 0, 92, 0, 0, 0, 0, 49, 0, 0, 93, 0, 0, 0, 0, 94,
+ 95, 0, 0, 96, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99, 0,
+ 0, 0, 0,100,101, 93, 0, 0,102, 0, 0, 0, 84, 0, 0,103,
+ 0, 0, 0,104,105, 0, 0,106,107, 0, 0, 0, 0, 0, 0,108,
+ 0, 0,109, 0, 0, 0, 0,110, 33, 0,111,112,113, 35, 0, 0,
+ 114, 0, 0, 0,115, 0, 0, 0, 0, 0, 0,116, 0, 0,117, 0,
+ 0, 0, 0,118, 88, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 52,
+ 119, 0, 0, 0, 0,120, 0, 0,121, 0, 0, 0, 0,119, 0, 0,
+ 122, 0, 0, 0, 0, 0, 0,123, 0, 0, 0,124, 0, 0, 0,125,
+ 0,126, 0, 0, 0, 0,127,128,129, 0,130, 0,131, 0, 0, 0,
+ 132,133,134, 0, 77, 0, 0, 0, 0, 0, 35, 0, 0, 0,135, 0,
+ 0, 0,136, 0, 0,137, 0, 0,138, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 4, 4, 8, 9, 10,
+ 1, 11, 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, 19, 1, 0, 0,
+ 20, 21, 22, 1, 23, 4, 21, 24, 25, 26, 27, 28, 29, 30, 0, 0,
+ 1, 1, 31, 0, 0, 0, 32, 33, 34, 35, 1, 36, 37, 0, 0, 0,
+ 0, 38, 1, 39, 14, 39, 40, 41, 42, 0, 0, 0, 43, 36, 44, 45,
+ 21, 45, 46, 0, 0, 0, 19, 1, 21, 0, 0, 47, 0, 38, 48, 1,
+ 1, 49, 49, 50, 0, 0, 51, 0, 0, 0, 52, 1, 0, 0, 38, 14,
+ 4, 1, 1, 1, 53, 21, 43, 52, 54, 21, 35, 1, 0, 0, 0, 55,
+ 0, 0, 0, 56, 57, 58, 0, 0, 0, 0, 0, 59, 0, 60, 0, 0,
+ 0, 0, 61, 62, 0, 0, 63, 0, 0, 0, 64, 0, 0, 0, 65, 0,
+ 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 69, 70, 0,
+ 71, 72, 73, 74, 75, 76, 0, 0, 0, 77, 0, 0, 0, 78, 79, 0,
+ 0, 0, 0, 47, 0, 0, 0, 49, 0, 80, 0, 0, 0, 62, 0, 0,
+ 63, 0, 0, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 19, 84, 0,
+ 62, 0, 0, 0, 0, 49, 1, 85, 1, 52, 15, 86, 36, 10, 21, 87,
+ 0, 55, 0, 0, 0, 0, 19, 10, 1, 0, 0, 0, 0, 0, 88, 0,
+ 0, 89, 0, 0, 88, 0, 0, 0, 0, 78, 0, 0, 87, 9, 12, 4,
+ 90, 8, 91, 47, 0, 58, 50, 0, 21, 1, 21, 92, 93, 1, 1, 1,
+ 1, 94, 95, 96, 97, 1, 98, 58, 81, 99,100, 4, 58, 0, 0, 0,
+ 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, 0, 61, 0, 0,101,102,
+ 0, 0,103, 0, 0, 1, 1, 50, 0, 0, 0, 38, 0, 63, 0, 0,
+ 0, 0, 0, 62, 0, 0,104, 68, 61, 0, 0, 0, 78, 0, 0, 0,
+ 105,106, 58, 38, 81, 0, 0, 0, 0, 0, 0,107, 1, 14, 4, 12,
+ 84, 0, 0, 0, 0, 38, 87, 0, 0, 0, 0,108, 0, 0,109, 61,
+ 0,110, 0, 0, 0, 1, 0, 0, 0, 0, 19, 58, 0, 0, 0, 51,
+ 0,111, 14, 52,112, 41, 0, 0, 62, 0, 0, 61, 0, 0,113, 0,
+ 87, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, 0,113, 0, 0,
+ 0, 0,114, 0, 0, 0, 78, 55, 0, 38, 1, 58, 1, 58, 0, 0,
+ 63, 89, 0, 0,115, 0, 0, 0, 55, 0, 0, 0, 0,115, 0, 0,
+ 0, 0, 61, 0, 0, 0, 0, 79, 0, 61, 0, 0, 0, 0, 56, 0,
+ 89, 80, 0, 0, 79, 0, 0, 0, 8, 91, 0, 0, 1, 87, 0, 0,
+ 116, 0, 0, 0, 0, 0, 0,117, 0,118,119,120,121, 0,104, 4,
+ 122, 49, 23, 0, 0, 0, 38, 50, 38, 58, 0, 0, 1, 87, 1, 1,
+ 1, 1, 39, 1, 48,105, 87, 0, 0, 0, 0, 1, 0, 0, 0,123,
+ 4,122, 0, 0, 0, 1,124, 0, 0, 0, 0, 0,230,230,230,230,
+ 230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220,
+ 220,220,220,202,202,220,220,220, 1, 1, 1, 1, 1,220,220,220,
+ 220,230,230,230,230,240,230,220,220,220,230,230,230,220,220, 0,
+ 230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233,
+ 234,234,233,230, 0, 0, 0,230, 0,220,230,230,230,230,220,230,
+ 230,230,222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0,
+ 230,220, 0, 18, 30, 31, 32, 0, 0, 0, 0, 27, 28, 29, 30, 31,
+ 32, 33, 34,230,230,220,220,230,220,230,230,220, 35, 0, 0, 0,
+ 0, 0,230,230,230, 0, 0,230,230, 0,220,230,230,220, 0, 0,
+ 0, 36, 0, 0,230,220,230,230,220,220,230,220,220,230,220,230,
+ 220,230,230, 0, 0,220, 0, 0,230,230, 0,230, 0,230,230,230,
+ 230,230, 0, 0, 0,220,220,220,230,220,220,220,230,230, 0,220,
+ 27, 28, 29,230, 7, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230,
+ 230, 0, 0, 0, 0, 0,230, 0, 0, 84, 91, 0, 0, 0, 0, 9,
+ 9, 0, 0, 0, 0, 0, 9, 0,103,103, 9, 0,107,107,107,107,
+ 118,118, 9, 0,122,122,122,122,220,220, 0, 0, 0,220, 0,220,
+ 0,216, 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130,
+ 130,130, 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0,220, 0,
+ 0, 0, 0, 7, 0, 9, 9, 0, 9, 9, 0, 0, 0,230, 0, 0,
+ 0,228, 0, 0, 0,222,230,220,220, 0, 0, 0,230, 0, 0,220,
+ 230,220, 0,220,230,230,230, 0, 0, 0, 9, 9, 0, 0, 7, 0,
+ 230, 0, 1, 1, 1, 0, 0, 0,230,234,214,220,202,230,230,230,
230,230,232,228,228,220,218,230,233,220,230,220,230,230, 1, 1,
- 230,230,230,230, 1, 1, 1,230,230, 0, 0, 0, 0,230, 0, 0,
- 0, 1, 1,230,220,230, 1, 1,220,220,220,220,230, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,218,228,
- 232,222,224,224, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 230,230,230,230,230,230,230,230,230,230, 0, 0, 0, 0, 0, 0,
- 0, 0, 9, 0, 0, 0, 0,220,220,220, 0, 0, 0, 0, 0, 9,
- 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,230, 0,230,230,
- 220, 0, 0,230,230, 0, 0, 0, 0, 0,230,230, 0,230, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0,230,230,230,230,
- 230,230,230,220,220,220,220,220,220,220,230,230,230,230,230, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,230,230, 1,220, 0,
- 0, 0, 0, 9, 0, 0, 0, 0, 0,230,220, 0, 0, 0, 0,230,
- 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,220,220,230,230,230,220,
- 230,220,220,220, 0, 0,230,220,230,220, 0, 0, 0, 9, 7, 0,
- 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7,
- 7, 0, 0, 0,230,230,230,230,230, 0, 0, 0, 0, 0, 9, 0,
- 0, 0, 7, 0, 0, 0, 9, 7, 0, 0, 0, 0, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0,
- 0, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
- 9, 9, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,230,230,230,230,
- 230,230,230, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0, 0, 0, 0,216,216, 1, 1, 1, 0, 0,
- 0,226,216,216,216,216,216, 0, 0, 0, 0, 0, 0, 0, 0,220,
- 220,220,220,220,220,220,220, 0, 0,230,230,230,230,230,220,220,
- 0, 0, 0, 0, 0, 0,230,230,230,230, 0, 0, 0, 0,230,230,
- 230, 0, 0, 0,230, 0, 0,230,230,230,230,230,230,230, 0,230,
- 230, 0,230,230,220,220,220,220,220,220,220, 0,230,230, 7, 0,
- 0, 0, 0, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
- 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 1, 1, 1,230, 0, 1, 1,230,220,230, 1, 1, 0, 0,218,228,
+ 232,222,224,224, 0, 8, 8, 0, 0, 0, 0,220,230, 0,230,230,
+ 220, 0, 0,230, 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0,
+ 0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0,
+ 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0,
+ 0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,216, 0,
+ 220,220,220, 0,232,232,220,230,230,230, 7, 0, 16, 17, 17, 17,
+ 17, 17, 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,
+ 129,169, 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17,237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0,
- 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0,
- 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,237, 0, 1, 2, 2,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 7, 8,
+ 9, 0, 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 21, 22, 0, 0, 0, 0,
+ 23, 24, 25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 0, 0, 0, 0,
+ 0, 0, 0, 33, 34, 35, 36, 0, 0, 0, 0, 0, 37, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 1, 2, 40, 41,
+ 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 5, 0,
+ 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0,
+ 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10,
0, 0, 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0,
0, 0, 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7,
20, 20, 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0,
20, 20, 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1,
28, 29, 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20,
- 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20,
- 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0,
- 0, 40, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 21,
- 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
- 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45,
- 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 20, 20, 20, 1, 0, 0, 8, 21, 32, 4,
+ 0, 10, 0, 33, 7, 20, 20, 20, 0, 0, 0, 0, 8, 34, 34, 35,
+ 36, 34, 37, 0, 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8,
+ 21, 1, 20, 0, 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 8, 21,
+ 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 21, 0, 42, 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0,
0, 0, 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 20, 20, 1, 20, 20, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0,
- 0, 0, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 17, 19, 20, 21, 22, 23, 24, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 27, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
- 51, 52, 53, 54, 55, 56, 57, 34, 34, 34, 34, 58, 59, 59, 60, 34,
- 34, 34, 34, 34, 34, 34, 61, 62, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 63, 64, 34, 65, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 67, 66, 68, 69, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 70, 71, 72, 34, 34,
- 34, 34, 73, 34, 34, 34, 34, 34, 34, 34, 34, 74, 75, 76, 77, 78,
- 79, 80, 34, 81, 82, 83, 34, 84, 85, 34, 86, 87, 88, 89, 17, 90,
- 91, 92, 34, 34, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 93, 25, 25, 25, 25, 25, 25, 25, 94,
- 95, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 96, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 97, 34, 34, 34, 34, 34, 34,
- 25, 98, 34, 34, 25, 25, 25, 25, 25, 25, 25, 25, 25, 99, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 20, 20,
+ 1, 20, 20, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 12, 13,
+ 13, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 13, 22, 13, 13, 13,
+ 13, 23, 24, 24, 25, 26, 13, 13, 13, 27, 28, 29, 13, 30, 31, 32,
+ 33, 34, 35, 36, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7,
+ 7, 41, 13, 42, 7, 7, 43, 7, 44, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 45, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37,
+ 37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 2, 2, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59,
+ 59, 59, 59, 59, 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 79, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81,
+ 82, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 70, 70, 97, 98, 99,100,101,101,
+ 102,103,104,105,106,107,108,109,110,111, 96,112,113,114,115,116,
+ 117,118,119,119,120,121,122,123,124,125,126,127,128,129,130,131,
+ 132, 96,133,134,135,136,137,138,139,140,141,142,143, 96,144,145,
+ 96,146,147,148,149, 96,150,151,152,153,154,155,156, 96,157,158,
+ 159,160, 96,161,162,163,164,164,164,164,164,164,164,165,166,164,
+ 167, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96,168,169,169,169,169,169,169,169,169,170, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,171,171,
+ 171,171,172, 96, 96, 96,173,173,173,173,174,175,176,177, 96, 96,
+ 96, 96,178,179,180,181,182,182,182,182,182,182,182,182,182,182,
+ 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+ 182,182,182,182,182,183,182,182,182,182,182,182,184,184,184,185,
+ 186, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96,187,188,189,190,191,191,192, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96,195,196, 59,197,198,199,200,201,202, 96,203,204,
+ 205, 59, 59,206, 59,207,208,208,208,208,208,209, 96, 96, 96, 96,
+ 96, 96, 96, 96,210, 96,211,212,213, 96, 96,214, 96, 96, 96,215,
+ 96, 96, 96, 96, 96,216,217,218,219, 96, 96, 96, 96, 96,220,221,
+ 222, 96,223,224, 96, 96,225,226, 59,227,228, 96, 59, 59, 59, 59,
+ 59, 59, 59,229,230,231,232,233, 59, 59,234,235, 59,236, 96, 96,
+ 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70,237, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70,238, 70,239, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70,240, 70, 70, 70, 70, 70, 70, 70, 70, 70,241, 96, 96,
+ 96, 96, 96, 96, 96, 96, 70, 70, 70, 70,242, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70,243, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,244, 96, 96,
+ 96, 96, 96, 96, 96, 96,245, 96,246,247, 0, 1, 2, 2, 0, 1,
+ 2, 2, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
- 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0,
- 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 19, 19,
+ 19, 19, 19, 19, 19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19,
+ 19, 19, 19, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2,
9, 9, 9, 9, 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9,
9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55,
+ 2, 9, 9, 9, 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 6, 6, 6, 1, 1, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4,
4, 2, 2, 4, 4, 4, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2,
- 2, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,
- 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 0, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 0, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 2, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 14, 14,
+ 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 0, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 2, 37, 37, 37,
37, 2, 2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 2, 2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 2, 2, 95, 2, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, 90, 90, 90, 2, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 2, 2, 95, 2, 37, 37,
+ 37, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3,
+ 2, 2, 2, 2, 2, 2, 3, 3, 0, 3, 3, 3, 3, 3, 7, 7,
7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5,
+ 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5,
5, 5, 5, 2, 2, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
- 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5,
- 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2,
+ 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2,
+ 5, 2, 2, 2, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 2,
2, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2,
2, 2, 5, 5, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 2, 2, 11, 11, 11, 2, 11, 11, 11, 11, 11,
11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2,
- 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11,
- 2, 2, 11, 2, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2,
+ 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 11, 11, 11, 11, 11, 2,
+ 11, 11, 2, 11, 11, 2, 11, 11, 2, 2, 11, 2, 11, 11, 11, 2,
2, 11, 11, 11, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11,
11, 11, 11, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 2, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10,
10, 10, 10, 10, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2,
- 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10,
- 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10,
- 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 10,
+ 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 2,
+ 10, 10, 2, 10, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, 10, 10,
+ 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 10, 10,
+ 10, 10, 2, 2, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 10,
10, 10, 10, 10, 10, 10, 2, 21, 21, 21, 2, 21, 21, 21, 21, 21,
21, 21, 21, 2, 2, 21, 21, 2, 2, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2,
- 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21,
- 2, 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2,
+ 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 2,
+ 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 21, 21, 2,
2, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 2, 2,
- 2, 2, 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22,
- 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22,
- 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22,
- 22, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 2, 2, 2, 2, 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2,
- 22, 22, 22, 22, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2,
+ 2, 2, 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, 2,
+ 22, 22, 2, 22, 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2,
+ 22, 22, 22, 22, 2, 2, 2, 22, 22, 2, 22, 2, 22, 22, 2, 2,
+ 2, 22, 22, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 2, 2, 2, 2, 22, 22, 22, 2, 2, 2, 2, 2, 2, 22, 2, 2,
+ 2, 2, 2, 2, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2,
+ 23, 23, 23, 23, 23, 23, 23, 23, 2, 2, 23, 23, 23, 23, 23, 2,
23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 2, 23, 23,
- 23, 2, 2, 23, 2, 2, 23, 23, 23, 23, 2, 2, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 23, 2, 2, 23, 2, 2, 23, 23, 23, 23, 2, 2, 23, 23, 2, 2,
+ 2, 2, 2, 2, 2, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 2, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16,
- 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2,
- 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 2, 2,
- 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 2, 16, 16, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 16, 16, 2, 16, 16, 16, 16, 16, 2, 2, 16, 16, 16, 16, 16, 2,
+ 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 16, 16,
+ 16, 16, 2, 2, 16, 16, 2, 16, 16, 16, 2, 2, 2, 2, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2,
20, 20, 20, 20, 20, 20, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 2, 36, 36, 36, 2, 36, 36, 36, 36, 36,
+ 20, 20, 2, 2, 20, 20, 2, 36, 36, 36, 2, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 2, 36, 2, 2, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,
- 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 36, 36,
- 36, 36, 36, 36, 36, 36, 2, 2, 2, 2, 2, 2, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18,
+ 36, 36, 2, 36, 2, 2, 2, 2, 36, 2, 2, 2, 2, 36, 36, 36,
+ 36, 36, 36, 2, 36, 2, 2, 2, 2, 2, 2, 2, 36, 36, 2, 2,
+ 36, 36, 36, 2, 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 0, 24, 24,
+ 24, 24, 2, 2, 2, 2, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18,
18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18,
- 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 2, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 18, 18, 2, 18, 2, 18, 18, 18, 18, 18, 18, 18, 2, 2, 18, 18,
+ 18, 18, 18, 2, 18, 2, 18, 18, 18, 18, 18, 18, 18, 2, 18, 18,
+ 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 25, 25,
25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25,
- 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2,
- 2, 2, 2, 8, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 0, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2,
- 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 2,
- 30, 30, 30, 30, 2, 2, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30,
- 30, 30, 30, 30, 30, 2, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 2, 2, 2, 8, 2, 2, 8, 8, 8, 0, 8, 8, 8, 8, 12, 12,
+ 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2,
+ 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
+ 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, 30, 30,
2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 2, 2, 29, 29,
- 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 2, 2, 2, 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, 0, 0, 0, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 2,
+ 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 2,
2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 2, 46, 46, 46, 2, 46, 46, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 2, 2, 2, 2, 2, 2, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2,
- 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 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, 48, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 2, 2, 52, 52, 52, 52, 52, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 45, 45, 45, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 46, 46, 46, 2,
+ 46, 46, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 2, 2, 31, 31, 2, 2, 2, 2, 2, 2, 32, 32,
+ 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 2, 2, 2, 2, 2, 2, 32, 2, 2, 2, 2, 2, 2, 2, 32, 32,
+ 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 2, 48, 48,
+ 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 2, 2, 52, 52,
+ 52, 52, 52, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 2, 2, 2, 2, 58, 58, 2, 2, 2, 2, 2, 2, 58, 58,
58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 2, 2, 91, 91, 91,
+ 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 2, 2, 1, 1,
1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 2, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 2, 76, 76,
76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 2, 2, 2, 2, 2, 2,
- 2, 2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 2, 2,
- 2, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2,
- 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 2, 2, 8, 8, 8, 76, 76, 76, 76, 76, 76, 76, 76, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
+ 93, 93, 2, 2, 2, 2, 2, 2, 2, 2, 93, 93, 93, 93, 70, 70,
+ 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 70, 70, 70, 70,
+ 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 6, 2,
+ 2, 2, 2, 2, 2, 2, 8, 8, 8, 2, 2, 8, 8, 8, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9,
- 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 9, 9, 9, 9,
- 9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 6, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9,
- 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9,
- 2, 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9,
+ 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, 9,
+ 19, 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 19, 6, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9,
+ 9, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 2, 9, 9, 9,
+ 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9,
9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 2, 19, 19,
+ 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2,
2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
- 19, 19, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
- 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 2, 2, 2, 2, 2, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0,
+ 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 27, 27,
27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 2, 2, 2, 2, 2, 55,
- 55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 2, 2,
- 2, 2, 2, 2, 2, 61, 61, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 61, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
- 30, 30, 30, 30, 30, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 1, 1, 1, 1, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13,
+ 0, 0, 0, 0, 2, 0, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55,
+ 55, 55, 2, 2, 2, 2, 2, 55, 55, 55, 55, 55, 55, 55, 61, 61,
+ 61, 61, 61, 61, 61, 61, 2, 2, 2, 2, 2, 2, 2, 61, 61, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 2, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 0, 0,
+ 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 13, 13,
13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1,
1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 0, 0, 17, 17, 17, 2, 2, 2, 2, 2, 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, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0,
- 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 2, 2, 2, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
- 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0,
- 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 2, 2, 2, 2, 2, 19, 19, 2, 19, 2, 19, 19, 19, 19, 19,
- 2, 2, 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 19,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 2, 2,
+ 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12,
+ 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 0, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39,
+ 39, 39, 39, 39, 39, 2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 2, 2, 2, 2, 79, 79,
+ 79, 79, 79, 79, 79, 79, 0, 0, 19, 19, 19, 19, 19, 19, 0, 0,
+ 0, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 19, 19,
+ 2, 19, 2, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2,
19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 2, 2, 2, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 2, 2,
- 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2,
- 2, 2, 2, 2, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+ 60, 60, 60, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 65, 65,
+ 65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+ 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75,
2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
- 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 74, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 74, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 12, 12,
12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 2, 0, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 2, 2, 2, 2, 84, 84, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2, 84, 84, 33, 33,
33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 2, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 2, 68, 68, 68, 68, 68, 68, 2, 2, 68, 68,
2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 92, 92, 92, 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 2, 2, 30,
- 30, 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 19, 19, 19, 19,
- 0, 0, 2, 2, 2, 2, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 2, 2, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2,
- 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 92, 2, 2, 2, 2, 2, 2, 2, 2, 92, 92, 92, 92, 92, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 30,
+ 30, 30, 30, 30, 30, 2, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 9, 19, 19, 19, 19, 0, 0, 2, 2, 2, 2, 87, 87,
+ 87, 87, 87, 87, 2, 2, 87, 87, 2, 2, 2, 2, 2, 2, 12, 12,
+ 12, 12, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 13, 13,
2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2,
- 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 14, 14,
- 14, 14, 14, 2, 14, 2, 14, 14, 2, 14, 14, 2, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2,
- 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
- 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 2, 14, 14, 14, 14, 14, 2, 14, 2, 14, 14,
+ 2, 14, 14, 2, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 2,
+ 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 1, 1,
+ 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 3, 3,
+ 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2,
- 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2,
- 12, 12, 12, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
- 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
- 0, 0, 0, 0, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 2, 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49,
+ 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0,
+ 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0,
0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 2,
+ 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2,
2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118,
- 118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,
118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 2, 2, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 59, 59, 2, 2, 2, 2, 59, 59, 59, 59, 59, 59, 2, 2, 40, 40,
+ 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 2, 2, 50, 50,
2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135,
- 135,135,135,135,135,135,135,135,135,135, 2, 2, 2, 2,135,135,
- 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
- 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,106,106,
- 106,106,106,106,106,106,106,106,106,106,106,106,106,106, 2, 2,
- 2, 2, 2, 2, 2, 2,104,104,104,104,104,104,104,104,104,104,
+ 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,104,104,
104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161,
161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161,
- 161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161,161,
- 161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161,161,
- 2,161,161, 2, 2, 2,110,110,110,110,110,110,110,110,110,110,
- 110,110,110,110,110,110,110,110,110,110,110,110,110, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,110,110,110,110,110,110, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,110,110,110,110,110,110,110,110, 2, 2,
- 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 2, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 2, 2, 2, 2, 2, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2,
+ 2,161,161,161,161,161,161,161, 2,161,161, 2, 2, 2,110,110,
+ 110,110,110,110,110,110,110,110,110,110,110,110,110, 2,110,110,
+ 110,110,110,110, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 2,
+ 19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2,
47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 2, 47, 47, 2,
- 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81, 81, 81,
- 81, 81, 81, 81, 81, 81,120,120,120,120,120,120,120,120,120,120,
+ 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81,120,120,
120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116,
- 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
- 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,116,116,
- 116,116,116,116,116,116,128,128,128,128,128,128,128,128,128,128,
+ 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,128,128,
128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2,
2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
- 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
- 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
- 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 2, 2,
- 2, 2, 97, 97, 97, 97, 2, 2, 97, 97, 97, 97, 97, 97, 97, 97,
+ 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97,
+ 97, 97, 97, 97, 97, 97, 2, 2, 2, 2, 97, 97, 97, 97, 2, 2,
97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2,
2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57,
57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2, 2, 57, 57,
- 57, 2, 2, 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2,
- 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88,117,117,117,117,117,117,117,117,117,117,
+ 57, 57, 57, 57, 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2,
+ 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88,117,117,
117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112,
- 112,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2,
- 2,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 112,112,112,112,112, 2, 2, 2, 2,112,112,112,112,112, 78, 78,
78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78,
78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 2, 2, 83, 83,
- 83, 83, 83, 83, 83, 83, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 2, 2, 2, 2, 2, 82, 82,
- 82, 82, 82, 82, 82, 82,122,122,122,122,122,122,122,122,122,122,
- 122,122,122,122,122,122,122,122, 2, 2, 2, 2, 2, 2, 2,122,
- 122,122,122, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,122,
- 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
- 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2,
+ 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
+ 82, 2, 2, 2, 2, 2,122,122,122,122,122,122,122,122,122,122,
+ 2, 2, 2, 2, 2, 2, 2,122,122,122,122, 2, 2, 2, 2,122,
+ 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2,
2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130,
- 130,130,130,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,130,130,130, 2, 2, 2, 2, 2, 2, 2,
- 130,130,130,130,130,130,144,144,144,144,144,144,144,144,144,144,
- 144,144,144,144,144,144,144,144,144,144,144,144,144,144, 2, 2,
- 2, 2, 2, 2, 2, 2,144,144,144,144,144,144,144,144,144,144,
- 2, 2, 2, 2, 2, 2,156,156,156,156,156,156,156,156,156,156,
- 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
- 2,156,156,156, 2, 2,156,156, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,147,147,147,147,147,147,147,147,147,147,
- 147,147,147,147,147,147,147,147,147,147,147,147,147,147, 2, 2,
- 2, 2, 2, 2, 2, 2,148,148,148,148,148,148,148,148,148,148,
- 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
+ 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,144,144,
+ 144,144,144,144,144,144,144,144, 2, 2, 2, 2, 2, 2,156,156,
+ 156,156,156,156,156,156,156,156, 2,156,156,156, 2, 2,156,156,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,147,147,
+ 147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148,
2, 2, 2, 2, 2, 2,158,158,158,158,158,158,158,158,158,158,
- 158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,
2, 2, 2, 2, 2, 2,153,153,153,153,153,153,153,153,153,153,
- 153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
153,153, 2, 2, 2, 2,149,149,149,149,149,149,149,149,149,149,
- 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2,
+ 149,149,149,149,149, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 2, 2,
2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101,101,
- 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, 2,
- 2, 2, 2, 2, 2, 2,101,101,101,101,101,101,101,101,101,101,
+ 85, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 2, 2,101,101,
+ 101,101,101,101,101,101,101, 2, 2, 2, 2, 2, 2, 2,101,101,
2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 2,
- 2, 2, 2, 2, 2, 2,111,111,111,111,111,111,111,111,111,111,
- 111,111,111,111,111,111,111,111,111,111,111,111,111, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,100,100,100,100,100,100,100,100,100,100,
- 100,100,100,100,100,100, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,108,108,108,108,108,108,108,108,108,108,
+ 96, 96, 96, 2, 96, 96,111,111,111,111,111,111,111,111,111,111,
+ 111,111,111,111,111, 2,100,100,100,100,100,100,100,100, 2, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,108,108,
108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108,
- 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
- 108,108,108,108,108, 2,129,129,129,129,129,129,129, 2,129, 2,
- 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129,
+ 2, 2, 2, 2, 2, 2,129,129,129,129,129,129,129, 2,129, 2,
129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129,
- 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109,
- 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
- 109, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109,
+ 129,129,129,129, 2,129,129,129, 2, 2, 2, 2, 2, 2,109,109,
+ 109,109,109,109,109,109,109,109,109, 2, 2, 2, 2, 2,109,109,
2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107,
107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107,
- 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2,
- 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107,
- 2, 1,107,107,107,107,107,107,107,107,107, 2, 2,107,107, 2,
+ 107,107,107,107,107,107,107, 2,107,107,107,107,107,107,107, 2,
+ 107,107, 2,107,107,107,107,107, 2, 1,107,107,107,107,107, 2,
2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2,
2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107,
- 107,107,107, 2, 2, 2,107,107,107,107,107, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,137,137,137,137,137,137,137,137,137,137,
- 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
- 137,137, 2,137,137,137,137,137, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124,
- 124,124,124,124,124,124,124,124,124,124,124,124,124,124, 2, 2,
- 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124,
- 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123,
- 123,123,123,123,123,123,123,123,123,123,123,123, 2, 2,123,123,
- 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,
- 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114,
- 114,114,114,114,114,114,114,114,114,114,114, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,114,114,114,114,114,114,114,114,114,114,
- 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102,102,
- 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
- 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126,
- 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
- 126, 2, 2,126,126,126,126,126,126,126,126,126,126,126,126,126,
- 126,126, 2, 2, 2, 2,126,126,126,126,126,126,126, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,142,142,142,142,142,142,142,142,142,142,
- 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
- 142,142, 2, 2, 2, 2,125,125,125,125,125,125,125,125,125,125,
+ 107,107,107, 2, 2, 2,137,137,137,137,137,137,137,137,137,137,
+ 137,137, 2,137,137,137,137,137, 2, 2, 2, 2, 2, 2,124,124,
+ 124,124,124,124,124,124,124,124, 2, 2, 2, 2, 2, 2,123,123,
+ 123,123,123,123,123,123,123,123,123,123,123,123, 2, 2,114,114,
+ 114,114,114,114,114,114,114,114,114,114,114, 2, 2, 2,114,114,
+ 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 2, 2, 2,102,102,
+ 102,102,102,102,102,102,102,102, 2, 2, 2, 2, 2, 2,126,126,
+ 126,126,126,126,126,126,126,126,126, 2, 2,126,126,126,126,126,
+ 126,126, 2, 2, 2, 2,126,126,126,126,126,126,126, 2,142,142,
+ 142,142,142,142,142,142,142,142,142,142, 2, 2, 2, 2,125,125,
125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2,125,154,154,154,154,154,154,154, 2, 2,154,
2, 2,154,154,154,154,154,154,154,154, 2,154,154, 2,154,154,
- 154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
154,154,154,154,154,154,154,154,154,154,154,154, 2,154,154, 2,
- 2,154,154,154,154,154,154,154,154,154,154,154,154, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,154,154,154,154,154,154,154,154,154,154,
- 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,150,150, 2, 2,
- 150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
- 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,141,141,141,141,141,141,141,141,141,141,
- 141,141,141,141,141,141,141,141,141,141,141,141,141,141, 2, 2,
- 2, 2, 2, 2, 2, 2,140,140,140,140,140,140,140,140,140,140,
- 140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121,121,
- 121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, 2,
+ 2,154,154,154,154,154,154,154, 2, 2, 2, 2, 2, 2,150,150,
+ 150,150,150,150,150,150, 2, 2,150,150,150,150,150,150,150,150,
+ 150,150,150, 2, 2, 2,141,141,141,141,141,141,141,141,140,140,
+ 140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2,121,121,
+ 121,121,121,121,121,121,121, 2, 2, 2, 2, 2, 2, 2, 7, 7,
2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2,
- 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133,
- 133,133,133,133,133,133,133,133,133,133,133,133, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133,133,
- 133,133,133, 2, 2, 2,134,134,134,134,134,134,134,134,134,134,
- 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134,134,134,
- 134,134,134,134,134,134,134,134,134,134,134,134,134,134, 2,134,
- 134,134,134,134,134,134,134,134,134,134,134,134,134, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,138,138,138,138,138,138,138, 2,138,138,
- 2,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,
- 138,138,138,138,138,138,138,138,138,138,138,138,138, 2, 2, 2,
- 138, 2,138,138, 2,138,138,138,138,138,138,138,138,138, 2, 2,
- 2, 2, 2, 2, 2, 2,138,138,138,138,138,138,138,138,138,138,
+ 133,133,133,133, 2, 2,133,133,133,133,133, 2, 2, 2,134,134,
+ 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134, 2,134,
+ 134,134,134,134,134,134,134,134,134,134,134,134,134, 2,138,138,
+ 138,138,138,138,138, 2,138,138, 2,138,138,138,138,138,138,138,
+ 138,138,138,138,138,138, 2, 2,138, 2,138,138, 2,138,138,138,
2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2,
143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
- 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2,
- 2, 2, 2, 2, 2, 2,143,143,143,143,143,143,143,143,143,143,
- 2, 2, 2, 2, 2, 2,145,145,145,145,145,145,145,145,145,145,
- 145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, 2,
- 2, 2, 2, 2, 2, 2, 86, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2, 2, 2,145,145,
+ 145,145,145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2,163,163,
+ 163,163,163,163,163,163,163, 2,163,163,163,163,163,163,163,163,
+ 163, 2, 2, 2,163,163,163,163, 2, 2, 2, 2, 2, 2, 86, 2,
+ 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 2, 63, 63, 63, 63, 63, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,157,157,157,157,157,157,157,157,157,157,
- 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 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, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2,
- 2, 2, 2, 2, 2, 2,127,127,127,127,127,127,127,127,127,127,
- 127,127,127,127,127,127,127,127,127,127,127,127,127, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 79, 2,
+ 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63,
+ 63, 63, 63, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2,157,157,
+ 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, 2,127,127,
+ 127,127,127,127,127,127,127,127,127,127,127,127,127, 2, 79, 2,
2, 2, 2, 2, 2, 2,115,115,115,115,115,115,115,115,115,115,
- 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 115,115,115,115,115, 2,115,115,115,115,115,115,115,115,115,115,
- 2, 2, 2, 2,115,115,159,159,159,159,159,159,159,159,159,159,
- 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,
- 159,159,159,159,159, 2,159,159,159,159,159,159,159,159,159,159,
+ 115,115,115,115,115, 2,115,115, 2, 2, 2, 2,115,115,159,159,
+ 159,159,159,159,159,159,159,159,159,159,159,159,159, 2,159,159,
2, 2, 2, 2, 2, 2,103,103,103,103,103,103,103,103,103,103,
- 103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,
- 103,103,103,103, 2, 2,103,103,103,103,103,103, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,119,119,119,119,119,119,119,119,119,119,
- 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,119,119,119,119,119,119,119,119,119,119,
- 2,119,119,119,119,119,119,119, 2,119,119,119,119,119,119,119,
- 119,119,119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,
+ 103,103,103,103, 2, 2,119,119,119,119,119,119,119,119,119,119,
+ 119,119,119,119, 2, 2,119,119, 2,119,119,119,119,119, 2, 2,
2, 2, 2,119,119,119,146,146,146,146,146,146,146,146,146,146,
- 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,
146, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2,
- 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136,136,
- 136,136,136,136,136,136,136,136,136,136,136,136,136,136, 2, 2,
- 2, 2, 2, 2, 2, 2,155,155,155,155,155,155,155,155,155,155,
- 155,155,155,155,155,155,155,155,155,155,155,155, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136, 2,
+ 99, 2, 2, 2, 2, 99, 2, 2, 2, 2, 2, 2, 2, 99,136,139,
+ 13, 13,155, 2, 2, 2,136,136,136,136,136,136,136,136,155,155,
+ 155,155,155,155,155,155,155,155,155,155,155,155, 2, 2,136, 2,
2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 17, 17, 17, 17, 17,
- 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 2,
- 2, 2, 2, 2, 2, 2,139,139,139,139,139,139,139,139,139,139,
- 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,
- 139,139, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105,
- 105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
- 105, 2, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105,
- 105,105,105, 2, 2, 2,105,105,105,105,105,105,105,105,105, 2,
- 2, 2, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105,
- 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17,
+ 17, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 2, 2, 2, 15, 15,
+ 15, 2, 2, 17, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,139,139,
+ 139,139,139,139,139,139,139,139,139,139, 2, 2, 2, 2,105,105,
+ 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105,
+ 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105,
+ 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0, 0, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 2, 0, 0, 2, 2, 0, 2, 2, 0, 0, 2, 2, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2,
+ 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0,
2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
- 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2,
- 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 2, 2, 0, 0,131,131,131,131,131,131,131,131,131,131,
- 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
- 131,131, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2,131,131,131,131,131, 2,131,131,131,131,131,131,131,131,131,
- 131,131,131,131,131,131, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 2,
- 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56,
- 56, 2, 2, 2, 2, 2,151,151,151,151,151,151,151,151,151,151,
- 151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,
- 151,151,151, 2, 2, 2,151,151,151,151,151,151,151,151,151,151,
- 151,151,151,151, 2, 2,151,151,151,151,151,151,151,151,151,151,
- 2, 2, 2, 2,151,151,160,160,160,160,160,160,160,160,160,160,
- 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
- 160,160,160,160,160, 2,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 2, 2, 2, 2, 2,152, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
- 30, 30, 2, 30, 30, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 2,113,113,113,113,113,113,113,113,113,113,
- 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113,
- 113,113,113,113,113,113,113,113,113,113,113,113,113, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,132,132,132,132,132,132,132,132,132,132,
- 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
- 132,132, 2, 2, 2, 2,132,132,132,132,132,132,132,132,132,132,
- 2, 2, 2, 2,132,132, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
- 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3,
- 2, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3,
- 2, 3, 2, 3, 2, 3, 2, 3, 3, 2, 3, 2, 2, 3, 3, 3,
- 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
- 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3,
- 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
- 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0,
- 0, 0, 0, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2,
- 2, 2, 2, 2, 2, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 2, 3, 4, 5, 6, 0,
- 0, 0, 0, 7, 8, 9, 10, 11, 0, 12, 0, 0, 0, 0, 13, 0,
- 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 0, 17, 18, 19,
- 0, 0, 0, 20, 21, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 0,
- 0, 0, 0, 27, 28, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,131,131,131,131,
+ 131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131,
+ 131,131,131,131,131,131, 2, 2, 2, 2, 2, 19, 19, 19, 56, 56,
+ 56, 56, 56, 56, 56, 2, 56, 2, 2, 56, 56, 56, 56, 56, 56, 56,
+ 2, 56, 56, 2, 56, 56, 56, 56, 56, 2, 2, 2, 2, 2, 6, 6,
+ 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,151,151,
+ 151,151,151,151,151,151,151,151,151,151,151, 2, 2, 2,151,151,
+ 151,151,151,151, 2, 2,151,151, 2, 2, 2, 2,151,151,160,160,
+ 160,160,160,160,160,160,160,160,160,160,160,160,160, 2,152,152,
+ 152,152,152,152,152,152,152,152, 2, 2, 2, 2, 2,152,164,164,
+ 164,164,164,164,164,164,164,164, 2, 2, 2, 2, 2, 2, 30, 30,
+ 30, 30, 2, 30, 30, 2,113,113,113,113,113,113,113,113,113,113,
+ 113,113,113, 2, 2,113,113,113,113,113,113,113,113, 2,132,132,
+ 132,132,132,132,132,132,132,132,132,132, 2, 2, 2, 2,132,132,
+ 2, 2, 2, 2,132,132, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3,
+ 3, 2, 3, 2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2,
+ 3, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3,
+ 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3,
+ 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3,
+ 3, 3, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 15, 0,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2,
+ 2, 0, 0, 0, 0, 0, 13, 2, 2, 2, 2, 2, 2, 2, 13, 13,
+ 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13,
+ 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33,
- 34, 35, 36, 37, 38, 39, 40, 0, 0, 0, 41, 0, 42, 43, 44, 45,
- 46, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33,
+ 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44,
+ 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48,
0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 64, 0, 0, 0, 0, 0,
- 0, 0, 0, 65, 0, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 71, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69,
+ 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0,
+ 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0,
+ 110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131,
+ 132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,
+ 148,149,150,151,152,153,154,155,156,157, 0, 0, 0,158,159,160,
+ 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,175,176,
+ 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
+ 193,194,195,196,197,198,199,200,201,202,203,204,205,206, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 72, 73, 74, 75, 76, 77, 78, 79, 80, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
};
static const uint16_t
-_hb_ucd_u16[11584] =
+_hb_ucd_u16[9320] =
{
0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12,
13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23,
@@ -3160,11 +2209,9 @@ _hb_ucd_u16[11584] =
136, 48, 48, 137, 138, 139, 140, 140, 141, 48, 142, 143, 144, 145, 140, 140,
146, 147, 148, 149, 150, 48, 151, 152, 153, 154, 32, 155, 156, 157, 140, 140,
48, 48, 158, 159, 160, 161, 162, 163, 164, 165, 9, 9, 166, 11, 11, 167,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 168, 169, 48, 48, 168, 48, 48, 170, 171, 172, 48, 48,
- 48, 171, 48, 48, 48, 173, 174, 175, 48, 176, 9, 9, 9, 9, 9, 177,
- 178, 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, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 168, 169, 48, 48,
+ 168, 48, 48, 170, 171, 172, 48, 48, 48, 171, 48, 48, 48, 173, 174, 175,
+ 48, 176, 9, 9, 9, 9, 9, 177, 178, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 179, 48, 180, 181, 48, 48, 48, 48, 182, 183,
48, 184, 48, 185, 48, 186, 187, 188, 48, 48, 48, 189, 190, 191, 192, 193,
194, 192, 48, 48, 195, 48, 48, 196, 197, 48, 198, 48, 48, 48, 48, 199,
@@ -3177,49 +2224,30 @@ _hb_ucd_u16[11584] =
241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
- 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
- 280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209,
- 209, 209, 287, 140, 288, 140, 271, 271, 271, 289, 209, 209, 209, 209, 290, 271,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 291, 292, 209, 209, 293,
- 209, 209, 209, 209, 209, 209, 294, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+ 279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282,
+ 209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271,
+ 271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209,
+ 209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209,
209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 279, 279, 279, 279, 279, 279, 279, 279, 300, 301, 279, 279, 279, 302, 279, 303,
- 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
- 209, 209, 209, 279, 304, 209, 209, 305, 209, 306, 209, 209, 209, 209, 209, 209,
- 9, 9, 9, 11, 11, 11, 307, 308, 13, 13, 13, 13, 13, 13, 309, 310,
- 11, 11, 311, 48, 48, 48, 312, 313, 48, 314, 315, 315, 315, 315, 32, 32,
- 316, 317, 318, 319, 320, 321, 140, 140, 209, 322, 209, 209, 209, 209, 209, 323,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 324, 140, 325,
+ 300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305,
+ 209, 306, 209, 209, 209, 209, 209, 209, 9, 9, 9, 11, 11, 11, 307, 308,
+ 13, 13, 13, 13, 13, 13, 309, 310, 11, 11, 311, 48, 48, 48, 312, 313,
+ 48, 314, 315, 315, 315, 315, 32, 32, 316, 317, 318, 319, 320, 321, 140, 140,
+ 209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 325,
326, 327, 328, 329, 136, 48, 48, 48, 48, 330, 178, 48, 48, 48, 48, 331,
332, 48, 48, 136, 48, 48, 48, 48, 200, 333, 48, 48, 209, 209, 323, 48,
209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 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, 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, 209, 209, 209, 209,
- 48, 338, 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,
- 48, 48, 48, 48, 48, 48, 48, 48, 151, 209, 209, 209, 287, 48, 48, 229,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 339, 48, 340, 140, 13, 13, 341, 342, 13, 343, 48, 48, 48, 48, 344, 345,
- 31, 346, 347, 348, 13, 13, 13, 349, 350, 351, 352, 353, 354, 355, 140, 356,
- 357, 48, 358, 359, 48, 48, 48, 360, 361, 48, 48, 362, 363, 192, 32, 364,
- 64, 48, 365, 48, 366, 367, 48, 151, 76, 48, 48, 368, 369, 370, 371, 372,
- 48, 48, 373, 374, 375, 376, 48, 377, 48, 48, 48, 378, 379, 380, 381, 382,
- 383, 384, 315, 11, 11, 385, 386, 11, 11, 11, 11, 11, 48, 48, 387, 192,
- 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, 388, 48, 389, 48, 48, 206,
- 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
- 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 209, 209, 209, 209, 48, 338, 48, 48, 48, 48, 48, 48,
+ 151, 209, 209, 209, 287, 48, 48, 229, 339, 48, 340, 140, 13, 13, 341, 342,
+ 13, 343, 48, 48, 48, 48, 344, 345, 31, 346, 347, 348, 13, 13, 13, 349,
+ 350, 351, 352, 353, 354, 355, 140, 356, 357, 48, 358, 359, 48, 48, 48, 360,
+ 361, 48, 48, 362, 363, 192, 32, 364, 64, 48, 365, 48, 366, 367, 48, 151,
+ 76, 48, 48, 368, 369, 370, 371, 372, 48, 48, 373, 374, 375, 376, 48, 377,
+ 48, 48, 48, 378, 379, 380, 381, 382, 383, 384, 315, 11, 11, 385, 386, 11,
+ 11, 11, 11, 11, 48, 48, 387, 192, 48, 48, 388, 48, 389, 48, 48, 206,
+ 390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391,
48, 48, 48, 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 207, 140, 140,
392, 393, 394, 395, 396, 48, 48, 48, 48, 48, 48, 397, 398, 399, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 400, 209, 48, 48, 48, 48, 401, 48, 48, 402, 140, 140, 403,
32, 404, 32, 405, 406, 407, 408, 409, 48, 48, 48, 48, 48, 48, 48, 410,
411, 2, 3, 4, 5, 412, 413, 414, 48, 415, 48, 200, 416, 417, 418, 419,
@@ -3229,644 +2257,524 @@ _hb_ucd_u16[11584] =
48, 48, 431, 48, 432, 48, 48, 433, 48, 434, 48, 48, 435, 436, 140, 140,
9, 9, 437, 11, 11, 48, 48, 48, 48, 204, 192, 9, 9, 438, 11, 439,
48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 314, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140,
448, 48, 48, 449, 48, 450, 48, 451, 48, 200, 452, 140, 140, 140, 48, 453,
48, 454, 48, 455, 140, 140, 140, 140, 48, 48, 48, 456, 271, 457, 271, 271,
458, 459, 48, 460, 461, 462, 48, 463, 48, 464, 140, 140, 465, 48, 466, 467,
48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140,
48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474,
- 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 271, 476, 48, 48, 477, 478, 140, 140, 140, 140,
- 48, 464, 479, 48, 62, 480, 140, 48, 481, 140, 140, 48, 482, 140, 48, 314,
- 483, 48, 48, 484, 485, 457, 486, 487, 222, 48, 48, 488, 489, 48, 196, 192,
- 490, 48, 491, 492, 493, 48, 48, 494, 222, 48, 48, 495, 496, 497, 498, 499,
- 48, 97, 500, 501, 140, 140, 140, 140, 502, 503, 504, 48, 48, 505, 506, 192,
- 507, 83, 84, 508, 509, 510, 511, 512, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 513, 514, 515, 478, 140, 48, 48, 48, 516, 517, 192, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 518, 519, 520, 521, 140, 140,
- 48, 48, 48, 522, 523, 192, 524, 140, 48, 48, 525, 526, 192, 140, 140, 140,
- 48, 173, 527, 528, 314, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 500, 529, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 530,
- 531, 532, 48, 533, 534, 192, 140, 140, 140, 140, 535, 48, 48, 536, 537, 140,
- 538, 48, 48, 539, 540, 541, 48, 48, 542, 543, 544, 48, 48, 48, 48, 196,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 84, 48, 518, 545, 546, 148, 175, 547, 48, 548, 549, 550, 140, 140, 140, 140,
- 551, 48, 48, 552, 553, 192, 554, 48, 555, 556, 192, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 557,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 100, 271, 558, 559, 560,
- 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, 207, 140, 140, 140, 140, 140, 140,
- 272, 272, 272, 272, 272, 272, 561, 562, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 563,
- 48, 48, 200, 564, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 314, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 565,
- 48, 48, 48, 566, 567, 568, 569, 570, 48, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 9, 9, 11, 11, 271, 571, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 572, 573, 574, 574, 575, 576, 140, 140, 140, 140, 577, 578,
- 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, 48, 440,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 199, 140, 140,
- 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 579,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 580, 140, 140, 580, 581, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 206,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 48, 48, 71, 151, 196, 582, 583, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 32, 32, 584, 32, 585, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 324,
- 209, 209, 586, 209, 209, 209, 587, 588, 589, 209, 590, 209, 209, 209, 288, 140,
- 209, 209, 209, 209, 591, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 592,
- 209, 209, 209, 209, 209, 287, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140,
- 9, 593, 11, 594, 595, 596, 241, 9, 597, 598, 599, 600, 601, 9, 593, 11,
- 602, 603, 11, 604, 605, 606, 607, 9, 608, 11, 9, 593, 11, 594, 595, 11,
- 241, 9, 597, 607, 9, 608, 11, 9, 593, 11, 609, 9, 610, 611, 612, 613,
- 11, 614, 9, 615, 616, 617, 618, 11, 619, 9, 620, 11, 621, 622, 622, 622,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 32, 32, 32, 623, 32, 32, 624, 625, 626, 627, 45, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 628, 629, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 630, 631, 632, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 151, 633, 634, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 635, 140, 48, 48, 636, 637,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 638, 200,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 639, 585, 140, 140,
- 9, 9, 597, 11, 640, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 498, 271, 271, 641, 642, 140, 140, 140, 140,
- 498, 271, 643, 644, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 645, 48, 646, 647, 648, 649, 650, 651, 652, 206, 653, 206, 140, 140, 140, 654,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 655, 655, 655, 209, 324,
- 656, 209, 209, 209, 209, 209, 209, 209, 209, 209, 657, 140, 140, 140, 658, 209,
- 659, 209, 209, 325, 660, 661, 324, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 662,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 663, 426, 426,
- 209, 209, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 660, 325, 427,
- 325, 209, 209, 209, 664, 176, 209, 209, 664, 209, 657, 661, 140, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 323, 657, 665, 287, 209, 426, 288, 324, 176, 664, 287,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 666, 209, 209, 288, 140, 140, 192,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 140, 140,
- 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, 48, 48,
- 48, 48, 48, 196, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 204, 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,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 478, 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, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 100, 140,
- 48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 71, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 667, 140, 668, 668, 668, 668, 668, 668, 140, 140, 140, 140, 140, 140, 140, 140,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 669,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 670,
- 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, 4, 5, 4, 5,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0,
- 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 11, 11, 11, 13, 11,
- 14, 14, 14, 14, 14, 14, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 16, 17, 18, 17, 17, 19, 20, 21, 21, 22, 21, 23, 24,
- 25, 26, 27, 27, 28, 29, 27, 30, 27, 27, 27, 27, 27, 31, 27, 27,
- 32, 33, 33, 33, 34, 27, 27, 27, 35, 35, 35, 36, 37, 37, 37, 38,
- 39, 39, 40, 41, 42, 43, 44, 27, 45, 46, 27, 27, 27, 27, 47, 27,
- 48, 48, 48, 48, 48, 49, 50, 48, 51, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
- 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
- 107, 108, 109, 109, 110, 111, 112, 109, 113, 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 122, 123, 122, 124, 125, 125, 126, 127, 128, 129, 130, 131, 125, 125,
- 132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137, 125, 125,
- 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143,
- 143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153,
- 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170,
- 171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176,
- 177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168,
- 188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194, 8, 195, 125, 125, 125,
- 196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201,
- 202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211,
- 4, 4, 212, 4, 4, 213, 214, 215, 4, 4, 4, 216, 8, 8, 8, 8,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 11, 217, 11, 11, 217, 218, 11, 219, 11, 11, 11, 220, 220, 221, 11, 222,
- 223, 0, 0, 0, 0, 0, 224, 225, 226, 227, 0, 0, 228, 8, 8, 229,
- 0, 0, 230, 231, 232, 0, 4, 4, 233, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 234, 125, 235, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 237, 0, 238, 0, 0, 0, 0, 0, 0,
- 239, 239, 239, 239, 239, 239, 4, 4, 240, 240, 240, 240, 240, 240, 240, 241,
- 139, 139, 140, 242, 242, 242, 243, 244, 143, 245, 246, 246, 246, 246, 14, 14,
- 0, 0, 0, 0, 0, 247, 125, 125, 248, 249, 248, 248, 248, 248, 248, 250,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 125, 252,
- 253, 0, 254, 255, 256, 257, 257, 257, 257, 258, 259, 260, 260, 260, 260, 261,
- 262, 263, 263, 264, 142, 142, 142, 142, 265, 0, 263, 263, 0, 0, 266, 260,
- 142, 265, 0, 0, 0, 0, 142, 267, 0, 0, 0, 0, 0, 260, 260, 268,
- 260, 260, 260, 260, 260, 269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 0, 0, 0, 0,
- 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,
- 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,
- 270, 270, 270, 270, 270, 270, 270, 270, 271, 270, 270, 270, 272, 273, 273, 273,
- 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274,
- 274, 274, 275, 125, 14, 14, 14, 14, 14, 14, 276, 276, 276, 276, 276, 277,
- 0, 0, 278, 4, 4, 4, 4, 4, 279, 4, 4, 4, 280, 281, 125, 282,
- 283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290, 48, 48,
- 291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299,
- 300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308,
- 309, 310, 246, 4, 4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 315, 142, 316, 142, 142, 317,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319, 125, 125,
- 320, 321, 21, 322, 323, 27, 27, 27, 27, 27, 27, 27, 324, 325, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 326, 27, 27, 27, 27, 27, 327, 27, 27, 328, 125, 125, 27,
- 8, 285, 329, 0, 0, 330, 331, 332, 27, 27, 27, 27, 27, 27, 27, 333,
- 334, 0, 1, 2, 1, 2, 335, 259, 260, 336, 142, 265, 337, 338, 339, 340,
- 341, 342, 343, 344, 345, 345, 125, 125, 342, 342, 342, 342, 342, 342, 342, 346,
- 347, 0, 0, 348, 11, 11, 11, 11, 349, 350, 351, 125, 125, 0, 0, 352,
- 125, 125, 125, 125, 125, 125, 125, 125, 353, 354, 355, 355, 355, 356, 357, 252,
- 358, 358, 359, 360, 361, 362, 362, 363, 364, 365, 366, 366, 367, 368, 125, 125,
- 369, 369, 369, 369, 369, 370, 370, 370, 371, 372, 373, 374, 374, 375, 374, 376,
- 377, 377, 378, 379, 379, 379, 380, 381, 381, 382, 383, 384, 125, 125, 125, 125,
- 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385,
- 385, 385, 385, 386, 385, 387, 388, 125, 389, 4, 4, 390, 125, 125, 125, 125,
- 391, 392, 392, 393, 394, 395, 396, 396, 397, 398, 399, 125, 125, 125, 400, 401,
- 402, 403, 404, 405, 125, 125, 125, 125, 406, 406, 407, 408, 407, 409, 407, 407,
- 410, 411, 412, 413, 414, 414, 415, 415, 416, 416, 125, 125, 417, 417, 418, 419,
- 420, 420, 420, 421, 422, 423, 424, 425, 426, 427, 428, 125, 125, 125, 125, 125,
- 429, 429, 429, 429, 430, 125, 125, 125, 431, 431, 431, 432, 431, 431, 431, 433,
- 434, 434, 435, 436, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 27, 45, 437, 437, 438, 439, 125, 125, 125, 125,
- 440, 440, 441, 442, 442, 443, 125, 444, 445, 125, 125, 446, 447, 125, 448, 449,
- 450, 450, 450, 450, 451, 452, 450, 453, 454, 454, 454, 454, 455, 456, 457, 458,
- 459, 459, 459, 460, 461, 462, 462, 463, 464, 464, 464, 464, 464, 464, 465, 466,
- 467, 468, 467, 469, 125, 125, 125, 125, 470, 471, 472, 473, 473, 473, 474, 475,
- 476, 477, 478, 479, 480, 481, 482, 483, 125, 125, 125, 125, 125, 125, 125, 125,
- 484, 484, 484, 484, 484, 485, 486, 125, 487, 487, 487, 487, 488, 489, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 490, 490, 490, 491, 490, 492, 125, 125,
- 493, 493, 493, 493, 494, 495, 496, 125, 497, 497, 497, 498, 498, 125, 125, 125,
- 499, 500, 501, 499, 502, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 503, 503, 503, 504, 125, 125, 125, 125, 125, 125, 505, 505, 505, 505, 505, 506,
- 507, 508, 509, 510, 511, 512, 125, 125, 125, 125, 513, 514, 514, 513, 515, 125,
- 516, 516, 516, 516, 517, 518, 518, 518, 518, 518, 519, 154, 520, 520, 520, 521,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 522, 523, 523, 524, 525, 523, 526, 527, 527, 528, 529, 530, 125, 125, 125, 125,
- 531, 532, 532, 533, 534, 535, 536, 537, 538, 539, 540, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 541, 542,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 543, 544, 544, 544, 545,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 547, 125, 125, 125, 125, 125, 125,
- 546, 546, 546, 546, 546, 546, 548, 549, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 550, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 551, 551, 551, 551, 551, 551, 552,
- 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553,
- 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553,
- 553, 553, 554, 555, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556,
- 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556,
- 556, 556, 556, 556, 557, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 558, 559, 560, 561, 562, 562, 562, 562, 563, 564, 565, 566, 567,
- 568, 568, 568, 568, 569, 570, 571, 572, 568, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 573, 573, 573, 573, 573, 574, 125, 125, 125, 125, 125, 125,
- 575, 575, 575, 575, 576, 575, 575, 575, 577, 575, 125, 125, 125, 125, 578, 579,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 581,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582,
- 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, 125, 125,
- 584, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 585,
- 586, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 587, 125, 125, 588, 589, 590, 590, 590, 590, 590, 590, 590, 590, 590,
- 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 591,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 592, 592, 592, 592, 592, 592, 593, 594, 595, 596, 266, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 8, 8, 597, 8, 598, 0, 0, 0, 0, 0, 0, 0, 266, 125, 125, 125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 599,
- 0, 0, 600, 0, 0, 0, 601, 602, 603, 0, 604, 0, 0, 0, 235, 125,
- 11, 11, 11, 11, 605, 125, 125, 125, 125, 125, 125, 125, 125, 125, 0, 266,
- 0, 0, 0, 0, 0, 234, 0, 606, 125, 125, 125, 125, 125, 125, 125, 125,
- 0, 0, 0, 0, 0, 224, 0, 0, 0, 607, 608, 609, 610, 0, 0, 0,
- 611, 612, 0, 613, 614, 615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 616, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 617, 0, 0, 0,
- 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618,
- 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618,
- 618, 618, 618, 618, 618, 618, 618, 618, 619, 620, 621, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 4, 622, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 623, 624, 625, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 626, 626, 627, 628, 629, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 630, 631, 125, 632, 632, 632, 633,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 634, 635,
- 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 637, 638, 125, 125,
- 639, 639, 639, 639, 640, 641, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 334, 0, 0, 0, 642, 125, 125, 125, 125,
- 334, 0, 0, 247, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 643, 27, 644, 645, 646, 647, 648, 649, 650, 651, 652, 651, 125, 125, 125, 653,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 0, 0, 252, 0, 0, 0, 0, 0, 0, 266, 226, 334, 334, 334, 0, 599,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 125, 125, 125, 654, 0,
- 655, 0, 0, 252, 606, 656, 599, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 657, 350, 350,
- 0, 0, 0, 0, 0, 0, 0, 266, 0, 0, 0, 0, 0, 606, 252, 228,
- 252, 0, 0, 0, 658, 285, 0, 0, 658, 0, 247, 656, 125, 125, 125, 125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 266, 247, 659, 234, 0, 350, 235, 599, 285, 658, 234,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 330, 0, 0, 235, 125, 125, 285,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 125, 125,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 660, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 579, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 661, 125,
- 248, 318, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 662, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 663, 125, 0, 0, 0, 0, 0, 0, 125, 125, 125, 125, 125, 125, 125, 125,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
- 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0,
- 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
- 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303,
- 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
- 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
- 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199,
- 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0,
- 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231,
- 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
- 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275,
- 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093,
- 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010,
- 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347,
- 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
- 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365,
- 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
- 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182,
- 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
- 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461,
- 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486,
- 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0,
- 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553,
- 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560,
- 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0,
- 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0,
- 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0,
- 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0,
- 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0,
- 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0,
- 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
- 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
- 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
- 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
- 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
- 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
- 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
- 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
- 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
- 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0,
- 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
- 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
- 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
- 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
- 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
- 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0,
- 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
- 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0,
- 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
- 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
- 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0,
- 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793,
- 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
- 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0,
- 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
- 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
- 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
- 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0,
- 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828,
- 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833,
- 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3,
- 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0,
- 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938,
- 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0,
- 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0,
- 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0,
- 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0,
- 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0,
- 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0,
- 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0,
- 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0,
- 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
- 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
- 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
- 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
- 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
- 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
- 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
- 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
- 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
- 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
- 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
- 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
- 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
- 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
- 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
- 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
- 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0,
- 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0,
- 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773,
- 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
- 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
- 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
- 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0,
- 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
- 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
- 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
- 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
- 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
- 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
- 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575,
- 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0,
- 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950,
- 1951,1952,1953,1954,1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
+ 48, 48, 477, 478, 140, 140, 140, 479, 48, 464, 480, 48, 62, 481, 140, 48,
+ 482, 140, 140, 48, 483, 140, 48, 314, 484, 48, 48, 485, 486, 457, 487, 488,
+ 222, 48, 48, 489, 490, 48, 196, 192, 491, 48, 492, 493, 494, 48, 48, 495,
+ 222, 48, 48, 496, 497, 498, 499, 500, 48, 97, 501, 502, 503, 140, 140, 140,
+ 504, 505, 506, 48, 48, 507, 508, 192, 509, 83, 84, 510, 511, 512, 513, 514,
+ 48, 48, 48, 515, 516, 517, 478, 140, 48, 48, 48, 518, 519, 192, 140, 140,
+ 48, 48, 520, 521, 522, 523, 140, 140, 48, 48, 48, 524, 525, 192, 526, 140,
+ 48, 48, 527, 528, 192, 140, 140, 140, 48, 173, 529, 530, 314, 140, 140, 140,
+ 48, 48, 501, 531, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 532,
+ 533, 534, 48, 535, 536, 192, 140, 140, 140, 140, 537, 48, 48, 538, 539, 140,
+ 540, 48, 48, 541, 542, 543, 48, 48, 544, 545, 546, 48, 48, 48, 48, 196,
+ 547, 140, 140, 140, 140, 140, 140, 140, 84, 48, 520, 548, 549, 148, 175, 550,
+ 48, 551, 552, 553, 140, 140, 140, 140, 554, 48, 48, 555, 556, 192, 557, 48,
+ 558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 560,
+ 561, 115, 48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566,
+ 48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568,
+ 48, 48, 48, 48, 388, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 569,
+ 48, 48, 48, 570, 571, 572, 140, 140, 48, 48, 48, 48, 314, 140, 140, 140,
+ 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 573,
+ 48, 48, 48, 574, 575, 576, 577, 578, 48, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 9, 9, 11, 11, 271, 579, 140, 140, 140, 140, 140, 140,
+ 48, 48, 48, 48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586,
+ 48, 48, 48, 48, 48, 48, 48, 440, 48, 48, 48, 48, 48, 199, 140, 140,
+ 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587,
+ 48, 48, 588, 589, 140, 590, 591, 48, 48, 48, 48, 48, 48, 48, 48, 206,
+ 48, 48, 48, 48, 48, 48, 71, 151, 196, 592, 593, 140, 140, 140, 140, 140,
+ 32, 32, 594, 32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
+ 209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598,
+ 599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140,
+ 140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461,
+ 9, 603, 11, 604, 605, 606, 241, 9, 607, 608, 609, 610, 611, 9, 603, 11,
+ 612, 613, 11, 614, 615, 616, 617, 9, 618, 11, 9, 603, 11, 604, 605, 11,
+ 241, 9, 607, 617, 9, 618, 11, 9, 603, 11, 619, 9, 620, 621, 622, 623,
+ 11, 624, 9, 625, 626, 627, 628, 11, 629, 9, 630, 11, 631, 632, 632, 632,
+ 32, 32, 32, 633, 32, 32, 634, 635, 636, 637, 45, 140, 140, 140, 140, 140,
+ 638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643, 27, 27, 27, 644, 140,
+ 645, 140, 140, 140, 140, 140, 140, 140, 48, 48, 151, 646, 647, 140, 140, 140,
+ 140, 48, 648, 140, 48, 48, 649, 650, 140, 140, 140, 140, 140, 48, 651, 192,
+ 140, 140, 140, 140, 140, 140, 652, 200, 48, 48, 48, 48, 653, 595, 140, 140,
+ 9, 9, 607, 11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499,
+ 271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140,
+ 659, 48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668,
+ 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 669, 669, 669, 209, 324,
+ 670, 209, 209, 209, 209, 209, 209, 209, 209, 209, 671, 140, 140, 140, 672, 209,
+ 673, 209, 209, 325, 674, 675, 324, 140, 209, 209, 209, 209, 209, 209, 209, 676,
+ 209, 209, 209, 209, 209, 677, 426, 426, 209, 209, 209, 209, 209, 209, 209, 678,
+ 209, 209, 209, 209, 209, 176, 325, 427, 325, 209, 209, 209, 679, 176, 209, 209,
+ 679, 209, 671, 675, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 671, 426,
+ 674, 209, 209, 680, 681, 325, 674, 674, 209, 682, 209, 209, 288, 140, 140, 192,
+ 48, 48, 48, 48, 48, 48, 140, 140, 48, 48, 48, 207, 48, 48, 48, 48,
+ 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 478, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 100, 140, 48, 204, 140, 140, 140, 140, 140, 140,
+ 48, 48, 48, 48, 71, 48, 48, 48, 48, 48, 48, 140, 140, 140, 140, 140,
+ 683, 140, 570, 570, 570, 570, 570, 570, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 140, 391, 391, 391, 391, 391, 391, 391, 684,
+ 391, 391, 391, 391, 391, 391, 391, 685, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 2, 2, 3, 1, 2, 2, 3, 0, 0, 0, 0, 0, 4, 0, 4,
+ 2, 2, 5, 2, 2, 2, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,
+ 0, 0, 0, 0, 7, 8, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 10, 11, 12, 13, 14, 14, 15, 14, 14, 14,
+ 14, 14, 14, 14, 16, 17, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 19, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 20, 21,
+ 21, 21, 22, 20, 21, 21, 21, 21, 21, 23, 24, 25, 25, 25, 25, 25,
+ 25, 26, 25, 25, 25, 27, 28, 26, 29, 30, 31, 32, 31, 31, 31, 31,
+ 33, 34, 35, 31, 31, 31, 36, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 29, 31, 31, 31, 31, 37, 38, 37, 37, 37, 37, 37, 37,
+ 37, 39, 31, 31, 31, 31, 31, 31, 40, 40, 40, 40, 40, 40, 41, 26,
+ 42, 42, 42, 42, 42, 42, 42, 43, 44, 44, 44, 44, 44, 45, 44, 46,
+ 47, 47, 47, 48, 37, 49, 31, 31, 31, 50, 51, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 52, 31, 31, 31, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 54, 53, 55, 53, 53, 53, 56, 57, 58, 59, 59, 60, 61, 62,
+ 57, 63, 64, 65, 66, 59, 59, 67, 68, 69, 70, 71, 71, 72, 73, 74,
+ 69, 75, 76, 77, 78, 71, 79, 26, 80, 81, 82, 83, 83, 84, 85, 86,
+ 81, 87, 88, 26, 89, 83, 90, 91, 92, 93, 94, 95, 95, 96, 97, 98,
+ 93, 99, 100, 101, 102, 95, 95, 26, 103, 104, 105, 106, 107, 104, 108, 109,
+ 104, 105, 110, 26, 111, 108, 108, 112, 113, 114, 115, 113, 113, 115, 113, 116,
+ 114, 117, 118, 119, 120, 113, 121, 113, 122, 123, 124, 122, 122, 124, 125, 126,
+ 123, 127, 128, 128, 129, 122, 130, 26, 131, 132, 133, 131, 131, 131, 131, 131,
+ 132, 133, 134, 131, 135, 131, 131, 131, 136, 137, 138, 139, 137, 137, 140, 141,
+ 138, 142, 143, 137, 144, 137, 145, 26, 146, 147, 147, 147, 147, 147, 147, 148,
+ 147, 147, 147, 149, 26, 26, 26, 26, 150, 151, 152, 152, 153, 152, 152, 154,
+ 155, 156, 152, 157, 26, 26, 26, 26, 158, 158, 158, 158, 158, 158, 158, 158,
+ 158, 159, 158, 158, 158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161,
+ 158, 161, 162, 163, 26, 26, 26, 26, 164, 164, 164, 164, 164, 164, 164, 164,
+ 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 165, 165, 165, 165,
+ 166, 167, 165, 165, 165, 165, 165, 168, 169, 169, 169, 169, 169, 169, 169, 169,
+ 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, 170, 170,
+ 170, 171, 172, 171, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 171, 172,
+ 171, 170, 172, 170, 170, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 170,
+ 170, 170, 170, 173, 170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176,
+ 176, 176, 176, 176, 176, 176, 177, 177, 178, 178, 178, 178, 178, 178, 178, 178,
+ 178, 178, 178, 178, 178, 178, 178, 178, 179, 179, 179, 180, 181, 181, 181, 181,
+ 181, 181, 181, 181, 181, 182, 181, 183, 184, 184, 185, 186, 187, 187, 188, 26,
+ 189, 189, 190, 26, 191, 192, 193, 26, 194, 194, 194, 194, 194, 194, 194, 194,
+ 194, 194, 194, 195, 194, 196, 194, 196, 197, 198, 198, 199, 198, 198, 198, 198,
+ 198, 198, 198, 198, 198, 198, 198, 200, 198, 198, 198, 198, 198, 201, 178, 178,
+ 178, 178, 178, 178, 178, 178, 202, 26, 203, 203, 203, 204, 203, 205, 203, 205,
+ 206, 203, 207, 207, 207, 208, 209, 26, 210, 210, 210, 210, 210, 211, 210, 210,
+ 210, 212, 210, 213, 194, 194, 194, 194, 214, 214, 214, 215, 216, 216, 216, 216,
+ 216, 216, 216, 217, 216, 216, 216, 218, 216, 219, 216, 219, 216, 220, 9, 9,
+ 9, 221, 26, 26, 26, 26, 26, 26, 222, 222, 222, 222, 222, 222, 222, 222,
+ 222, 223, 222, 222, 222, 222, 222, 224, 225, 225, 225, 225, 225, 225, 225, 225,
+ 226, 226, 226, 226, 226, 226, 227, 228, 229, 229, 229, 229, 229, 229, 229, 230,
+ 229, 231, 232, 232, 232, 232, 232, 232, 18, 233, 165, 165, 165, 165, 165, 234,
+ 225, 26, 235, 9, 236, 237, 238, 239, 2, 2, 2, 2, 240, 241, 2, 2,
+ 2, 2, 2, 242, 243, 244, 2, 245, 2, 2, 2, 2, 2, 2, 2, 246,
+ 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 247, 247, 14, 14, 14, 14,
+ 247, 247, 14, 248, 14, 14, 14, 247, 14, 14, 14, 14, 14, 14, 249, 14,
+ 249, 14, 250, 251, 14, 14, 252, 253, 0, 254, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 255, 0, 256, 257, 0, 258, 2, 259, 0, 0, 0, 0,
+ 260, 26, 9, 9, 9, 9, 261, 26, 0, 0, 0, 0, 262, 263, 4, 0,
+ 0, 264, 0, 0, 2, 2, 2, 2, 2, 265, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 258, 26, 26, 26,
+ 0, 266, 26, 26, 0, 0, 0, 0, 267, 267, 267, 267, 267, 267, 267, 267,
+ 267, 267, 267, 267, 267, 267, 267, 267, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, 269, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 270, 270, 270, 270, 270, 270, 270, 270,
+ 270, 270, 270, 270, 2, 2, 2, 2, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 271, 272, 165, 165, 165, 165, 166, 167, 273, 273,
+ 273, 273, 273, 273, 273, 274, 275, 274, 170, 170, 172, 26, 172, 172, 172, 172,
+ 172, 172, 172, 172, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 276, 26, 26, 26, 26, 277, 277, 277, 278, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 279, 26, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 280, 26, 26, 26, 0, 281, 282, 0, 0, 0, 283, 284, 0, 285,
+ 286, 287, 287, 287, 287, 287, 287, 287, 287, 287, 288, 289, 290, 291, 291, 291,
+ 291, 291, 291, 291, 291, 291, 291, 292, 293, 294, 294, 294, 294, 294, 295, 169,
+ 169, 169, 169, 169, 169, 169, 169, 169, 169, 296, 0, 0, 294, 294, 294, 294,
+ 0, 0, 0, 0, 281, 26, 291, 291, 169, 169, 169, 296, 0, 0, 0, 0,
+ 0, 0, 0, 0, 169, 169, 169, 297, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 291, 291, 291, 291, 291, 298, 291, 291, 291, 291, 291, 291, 291, 291,
+ 291, 291, 291, 0, 0, 0, 0, 0, 277, 277, 277, 277, 277, 277, 277, 277,
+ 0, 0, 0, 0, 0, 0, 0, 0, 299, 299, 299, 299, 299, 299, 299, 299,
+ 299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 299, 299, 299, 299, 299, 299,
+ 301, 26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 303, 303, 303,
+ 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 304, 26, 26,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 305, 305, 305, 305,
+ 305, 305, 305, 305, 305, 305, 305, 26, 0, 0, 0, 0, 306, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 307, 2, 2, 2, 2, 2, 2,
+ 2, 308, 309, 310, 26, 26, 311, 2, 312, 312, 312, 312, 312, 313, 0, 314,
+ 315, 315, 315, 315, 315, 315, 315, 26, 316, 316, 316, 316, 316, 316, 316, 316,
+ 317, 318, 316, 319, 53, 53, 53, 53, 320, 320, 320, 320, 320, 321, 322, 322,
+ 322, 322, 323, 324, 169, 169, 169, 325, 326, 326, 326, 326, 326, 326, 326, 326,
+ 326, 327, 326, 328, 164, 164, 164, 329, 330, 330, 330, 330, 330, 330, 331, 26,
+ 330, 332, 330, 333, 164, 164, 164, 164, 334, 334, 334, 334, 334, 334, 334, 334,
+ 335, 26, 26, 336, 337, 337, 338, 26, 339, 339, 339, 26, 172, 172, 2, 2,
+ 2, 2, 2, 340, 341, 342, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
+ 337, 337, 337, 337, 337, 343, 337, 344, 169, 169, 169, 169, 345, 26, 169, 169,
+ 296, 346, 169, 169, 169, 169, 169, 345, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 347, 26, 26, 26, 26, 348, 26, 349, 350, 25, 25, 351, 352,
+ 353, 25, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 354, 26, 355, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 356,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 357, 31, 31, 31, 31, 31,
+ 31, 358, 26, 26, 26, 26, 31, 31, 9, 9, 0, 314, 9, 359, 0, 0,
+ 0, 0, 360, 0, 258, 281, 361, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 362, 363, 0, 0, 0, 1, 2, 2, 3,
+ 1, 2, 2, 3, 364, 291, 290, 291, 291, 291, 291, 365, 169, 169, 169, 296,
+ 366, 366, 366, 367, 258, 258, 26, 368, 369, 370, 369, 369, 371, 369, 369, 372,
+ 369, 373, 369, 373, 26, 26, 26, 26, 369, 369, 369, 369, 369, 369, 369, 369,
+ 369, 369, 369, 369, 369, 369, 369, 374, 375, 0, 0, 0, 0, 0, 376, 0,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 253, 0, 377, 378, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 0, 379, 380, 380, 380, 381, 382, 382, 382, 382,
+ 382, 382, 383, 26, 384, 0, 0, 281, 385, 385, 385, 385, 386, 387, 388, 388,
+ 388, 389, 390, 390, 390, 390, 390, 391, 392, 392, 392, 393, 394, 394, 394, 394,
+ 395, 394, 396, 26, 26, 26, 26, 26, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 397, 398, 398, 398, 398, 398, 398, 399, 399, 399, 400, 399, 401, 402, 402,
+ 402, 402, 403, 402, 402, 402, 402, 403, 404, 404, 404, 404, 404, 26, 405, 405,
+ 405, 405, 405, 405, 406, 407, 408, 409, 408, 409, 410, 408, 411, 408, 411, 412,
+ 26, 26, 26, 26, 26, 26, 26, 26, 413, 413, 413, 413, 413, 413, 413, 413,
+ 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 413, 414, 26,
+ 413, 413, 415, 26, 413, 26, 26, 26, 416, 2, 2, 2, 2, 2, 417, 308,
+ 26, 26, 26, 26, 26, 26, 26, 26, 418, 419, 420, 420, 420, 420, 421, 422,
+ 423, 423, 424, 423, 425, 425, 425, 425, 426, 426, 426, 427, 428, 426, 26, 26,
+ 26, 26, 26, 26, 429, 429, 430, 431, 432, 432, 432, 433, 434, 434, 434, 435,
+ 26, 26, 26, 26, 26, 26, 26, 26, 436, 436, 436, 436, 437, 437, 437, 438,
+ 437, 437, 439, 437, 437, 437, 437, 437, 440, 441, 442, 443, 444, 444, 445, 446,
+ 444, 447, 444, 447, 448, 448, 448, 448, 449, 449, 449, 449, 26, 26, 26, 26,
+ 450, 450, 450, 450, 451, 452, 451, 26, 453, 453, 453, 453, 453, 453, 454, 455,
+ 456, 456, 457, 456, 458, 458, 459, 458, 460, 460, 461, 462, 26, 463, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 464, 464, 464, 464, 464, 464, 464, 464,
+ 464, 465, 26, 26, 26, 26, 26, 26, 466, 466, 466, 466, 466, 466, 467, 26,
+ 466, 466, 466, 466, 466, 466, 467, 468, 469, 469, 469, 469, 469, 26, 469, 470,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 31, 31, 31, 50, 471, 471, 471, 471, 471, 472, 473, 26,
+ 26, 26, 26, 26, 26, 26, 26, 474, 475, 475, 475, 475, 475, 26, 476, 476,
+ 476, 476, 476, 477, 26, 26, 478, 478, 478, 479, 26, 26, 26, 26, 480, 480,
+ 480, 481, 26, 26, 482, 482, 483, 26, 484, 484, 484, 484, 484, 484, 484, 484,
+ 484, 485, 486, 484, 484, 484, 485, 487, 488, 488, 488, 488, 488, 488, 488, 488,
+ 489, 490, 491, 491, 491, 492, 491, 493, 494, 494, 494, 494, 494, 494, 495, 494,
+ 494, 26, 496, 496, 496, 496, 497, 26, 498, 498, 498, 498, 498, 498, 498, 498,
+ 498, 498, 498, 498, 499, 137, 500, 26, 501, 501, 502, 501, 501, 501, 501, 501,
+ 503, 26, 26, 26, 26, 26, 26, 26, 504, 505, 506, 507, 506, 508, 509, 509,
+ 509, 509, 509, 509, 509, 510, 509, 511, 512, 513, 514, 515, 515, 516, 517, 518,
+ 513, 519, 520, 521, 522, 523, 523, 26, 524, 524, 524, 524, 524, 524, 524, 524,
+ 524, 524, 524, 525, 526, 26, 26, 26, 527, 527, 527, 527, 527, 527, 527, 527,
+ 527, 26, 527, 528, 26, 26, 26, 26, 529, 529, 529, 529, 529, 529, 530, 529,
+ 529, 529, 529, 530, 26, 26, 26, 26, 531, 531, 531, 531, 531, 531, 531, 531,
+ 532, 26, 531, 533, 198, 534, 26, 26, 535, 535, 535, 535, 535, 535, 535, 536,
+ 535, 536, 26, 26, 26, 26, 26, 26, 537, 537, 537, 538, 537, 539, 537, 537,
+ 540, 26, 26, 26, 26, 26, 26, 26, 541, 541, 541, 541, 541, 541, 541, 542,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 543, 543, 543, 543,
+ 543, 543, 543, 543, 543, 543, 544, 545, 546, 547, 548, 549, 549, 549, 550, 551,
+ 546, 26, 549, 552, 26, 26, 26, 26, 26, 26, 26, 26, 553, 554, 553, 553,
+ 553, 553, 553, 554, 555, 26, 26, 26, 556, 556, 556, 556, 556, 556, 556, 556,
+ 556, 26, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 558, 26, 178, 178,
+ 559, 559, 559, 559, 559, 559, 559, 560, 53, 561, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 562, 563, 562, 562, 562, 562, 564, 562,
+ 565, 26, 562, 562, 562, 566, 567, 567, 567, 567, 568, 567, 567, 569, 570, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 571, 572, 573, 573, 573, 573, 571, 574,
+ 573, 26, 573, 575, 576, 577, 578, 578, 578, 579, 580, 581, 578, 582, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 583, 583, 583, 584, 585, 585, 586, 585, 585, 585, 585, 587,
+ 585, 585, 585, 588, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 589, 26,
+ 108, 108, 108, 108, 108, 108, 590, 591, 592, 592, 592, 592, 592, 592, 592, 592,
+ 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 593, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 592, 592, 592, 592, 592, 592, 592, 592,
+ 592, 592, 592, 592, 592, 594, 595, 26, 592, 592, 592, 592, 592, 592, 592, 592,
+ 596, 26, 26, 26, 26, 26, 26, 26, 26, 26, 597, 597, 597, 597, 597, 597,
+ 597, 597, 597, 597, 597, 597, 598, 26, 599, 599, 599, 599, 599, 599, 599, 599,
+ 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599,
+ 599, 599, 600, 26, 26, 26, 26, 26, 601, 601, 601, 601, 601, 601, 601, 601,
+ 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601,
+ 602, 26, 26, 26, 26, 26, 26, 26, 305, 305, 305, 305, 305, 305, 305, 305,
+ 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 603,
+ 604, 604, 604, 605, 604, 606, 607, 607, 607, 607, 607, 607, 607, 607, 607, 608,
+ 607, 609, 610, 610, 610, 611, 611, 26, 612, 612, 612, 612, 612, 612, 612, 612,
+ 613, 26, 612, 614, 614, 612, 612, 615, 612, 612, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 617, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 618, 618, 618, 618, 618, 618, 618, 618,
+ 618, 619, 618, 618, 618, 618, 618, 618, 618, 620, 618, 618, 26, 26, 26, 26,
+ 26, 26, 26, 26, 621, 26, 347, 26, 622, 622, 622, 622, 622, 622, 622, 622,
+ 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622,
+ 622, 622, 622, 622, 622, 622, 622, 26, 623, 623, 623, 623, 623, 623, 623, 623,
+ 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623,
+ 623, 623, 624, 26, 26, 26, 26, 26, 622, 625, 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, 626, 627, 628, 287, 287, 287, 287, 287, 287, 287,
+ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
+ 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 629, 26, 630, 26,
+ 26, 26, 631, 26, 632, 26, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633,
+ 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633,
+ 633, 633, 633, 633, 633, 633, 633, 634, 635, 635, 635, 635, 635, 635, 635, 635,
+ 635, 635, 635, 635, 635, 636, 635, 637, 635, 638, 635, 639, 281, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 9, 9, 9, 9, 9, 640, 9, 9,
+ 221, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 281, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 276, 26, 0, 0, 0, 0, 258, 363, 0, 0,
+ 0, 0, 0, 0, 641, 642, 0, 643, 644, 645, 0, 0, 0, 646, 0, 0,
+ 0, 0, 0, 0, 0, 266, 26, 26, 14, 14, 14, 14, 14, 14, 14, 14,
+ 247, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 281, 26, 0, 0, 281, 26, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 258, 26, 0, 0, 0, 260, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 647, 648, 0, 649,
+ 650, 0, 0, 0, 0, 0, 0, 0, 269, 651, 255, 255, 0, 0, 0, 652,
+ 653, 654, 655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 276, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 268, 0, 0, 0, 0, 0, 0, 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656, 656, 657, 26, 658, 659, 656, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 348, 660, 308, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 661, 270, 270, 662, 663, 664, 18, 18,
+ 18, 18, 18, 18, 18, 665, 26, 26, 26, 666, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 667, 667, 667, 667, 667, 668, 667, 669,
+ 667, 670, 26, 26, 26, 26, 26, 26, 26, 26, 671, 671, 671, 672, 26, 26,
+ 673, 673, 673, 673, 673, 673, 673, 674, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 675, 675, 675, 675, 675, 676, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 172, 677, 170, 172, 678, 678, 678, 678, 678, 678, 678, 678,
+ 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678, 678,
+ 679, 678, 680, 26, 26, 26, 26, 26, 681, 681, 681, 681, 681, 681, 681, 681,
+ 681, 682, 681, 683, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 363, 0, 0, 0, 0, 0, 0, 0, 377, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 363, 0, 0, 0, 0, 0, 0, 276,
+ 26, 26, 26, 26, 26, 26, 26, 26, 684, 31, 31, 31, 685, 686, 687, 688,
+ 689, 690, 685, 691, 685, 687, 687, 692, 31, 693, 31, 694, 695, 693, 31, 694,
+ 26, 26, 26, 26, 26, 26, 51, 26, 0, 0, 0, 0, 0, 281, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 281, 26, 0, 258, 363, 0,
+ 363, 0, 363, 0, 0, 0, 276, 26, 0, 0, 0, 0, 0, 276, 26, 26,
+ 26, 26, 26, 26, 696, 0, 0, 0, 697, 26, 0, 0, 0, 0, 0, 281,
+ 0, 260, 314, 26, 276, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 698, 0, 377, 0, 377, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 258, 699, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 314, 0, 281, 260, 26, 0, 281, 0, 0, 0, 0, 0, 0,
+ 0, 26, 0, 314, 0, 0, 0, 0, 0, 26, 0, 0, 0, 276, 314, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 281, 26, 0, 276, 0, 377, 0, 260, 0, 0, 0, 0, 0, 269,
+ 276, 696, 0, 281, 0, 260, 0, 260, 0, 0, 360, 0, 0, 0, 0, 0,
+ 0, 266, 26, 26, 26, 26, 0, 314, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 347,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 347, 26, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 700, 26, 26, 26, 277, 277, 277, 280, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 701, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 702, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 939, 940, 941, 942, 946, 948, 0, 962,
+ 969, 970, 971, 976,1001,1002,1003,1008, 0,1033,1040,1041,1042,1043,1047, 0,
+ 0,1080,1081,1082,1086,1110, 0, 0,1124,1125,1126,1127,1131,1133, 0,1147,
+ 1154,1155,1156,1161,1187,1188,1189,1193, 0,1219,1226,1227,1228,1229,1233, 0,
+ 0,1267,1268,1269,1273,1298, 0,1303, 943,1128, 944,1129, 954,1139, 958,1143,
+ 959,1144, 960,1145, 961,1146, 964,1149, 0, 0, 973,1158, 974,1159, 975,1160,
+ 983,1168, 978,1163, 988,1173, 990,1175, 991,1176, 993,1178, 994,1179, 0, 0,
+ 1004,1190,1005,1191,1006,1192,1014,1199,1007, 0, 0, 0,1016,1201,1020,1206,
+ 0,1022,1208,1025,1211,1023,1209, 0, 0, 0, 0,1032,1218,1037,1223,1035,
+ 1221, 0, 0, 0,1044,1230,1045,1231,1049,1235, 0, 0,1058,1244,1064,1250,
+ 1060,1246,1066,1252,1067,1253,1072,1258,1069,1255,1077,1264,1074,1261, 0, 0,
+ 1083,1270,1084,1271,1085,1272,1088,1275,1089,1276,1096,1283,1103,1290,1111,1299,
+ 1115,1118,1307,1120,1309,1121,1310, 0,1053,1239, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,1093,1280, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 949,1134,1010,1195,1050,1236,1090,1277,1341,1368,1340,
+ 1367,1342,1369,1339,1366, 0,1320,1347,1418,1419,1323,1350, 0, 0, 992,1177,
+ 1018,1204,1055,1241,1416,1417,1415,1424,1202, 0, 0, 0, 987,1172, 0, 0,
+ 1031,1217,1321,1348,1322,1349,1338,1365, 950,1135, 951,1136, 979,1164, 980,1165,
+ 1011,1196,1012,1197,1051,1237,1052,1238,1061,1247,1062,1248,1091,1278,1092,1279,
+ 1071,1257,1076,1263, 0, 0, 997,1182, 0, 0, 0, 0, 0, 0, 945,1130,
+ 982,1167,1337,1364,1335,1362,1046,1232,1422,1423,1113,1301, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 10,1425, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,1314,1427, 5,
+ 1434,1438,1443, 0,1450, 0,1455,1461,1514, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1446,1458,1468,1476,1480,1486,1517, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1489,1503,1494,1500,1508, 0, 0, 0, 0,1520,1521, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1526,1528, 0,1525, 0, 0, 0,1522,
+ 0, 0, 0, 0,1536,1532,1539, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1556, 0, 0, 0, 0, 0, 0,1548,1550, 0,1547, 0, 0, 0,1567,
+ 0, 0, 0, 0,1558,1554,1561, 0, 0, 0, 0, 0, 0, 0,1568,1569,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1529,1551, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1523,1545,1524,1546, 0, 0,1527,1549,
+ 0, 0,1570,1571,1530,1552,1531,1553, 0, 0,1533,1555,1535,1557,1537,1559,
+ 0, 0,1572,1573,1544,1566,1538,1560,1540,1562,1541,1563,1542,1564, 0, 0,
+ 1543,1565, 0, 0, 0, 0, 0, 0, 0, 0,1606,1607,1609,1608,1610, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1613, 0,1611, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1612, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959,
- 1961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1620, 0, 0, 0, 0, 0, 0, 0,1623, 0, 0,1624, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1614,1615,1616,1617,1618,1619,1621,1622, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1628,1629, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1625,1626, 0,1627, 0, 0, 0,1634, 0, 0,1635, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1630,1631,1632, 0, 0,1633, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1639, 0, 0,1638,1640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1636,1637, 0, 0, 0, 0, 0, 0,1641, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131,
- 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37,
- 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
- 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
- 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
- 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
- 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259,
- 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
- 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934,
- 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312,
- 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
- 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
- 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381,
- 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399,
- 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417,
- 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
- 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460,
- 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
- 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505,
- 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64,
- 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538,
- 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567,
- 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592,
- 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
- 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627,
- 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
- 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83,
- 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85,
- 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696,
- 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
- 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90,
- 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787,
- 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807,
- 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0,
+ 0, 0,1642,1644,1643, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1645, 0, 0, 0, 0, 0, 0, 0,1646, 0, 0, 0, 0, 0, 0,1648,
+ 1649, 0,1647,1650, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1651,1653,1652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1654, 0,1655,1657,1656, 0, 0, 0, 0,1659, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1660, 0, 0, 0, 0,1661, 0, 0, 0, 0,1662,
+ 0, 0, 0, 0,1663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1658, 0, 0, 0, 0, 0, 0, 0, 0, 0,1664, 0,1665,1673, 0,
+ 1674, 0, 0, 0, 0, 0, 0, 0, 0,1666, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1668, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1669, 0, 0, 0, 0,1670, 0, 0, 0, 0,1671,
+ 0, 0, 0, 0,1672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1675, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1676, 0,
+ 1677, 0,1678, 0,1679, 0,1680, 0, 0, 0,1681, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1682, 0,1683, 0, 0,1684,1685, 0,1686, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 953,1138, 955,1140, 956,1141, 957,1142,
+ 1324,1351, 963,1148, 965,1150, 968,1153, 966,1151, 967,1152,1378,1380,1379,1381,
+ 984,1169, 985,1170,1420,1421, 986,1171, 989,1174, 995,1180, 998,1183, 996,1181,
+ 999,1184,1000,1185,1015,1200,1329,1356,1017,1203,1019,1205,1021,1207,1024,1210,
+ 1687,1688,1027,1213,1026,1212,1028,1214,1029,1215,1030,1216,1034,1220,1036,1222,
+ 1039,1225,1038,1224,1334,1361,1336,1363,1382,1384,1383,1385,1056,1242,1057,1243,
+ 1059,1245,1063,1249,1689,1690,1065,1251,1068,1254,1070,1256,1386,1387,1388,1389,
+ 1691,1692,1073,1259,1075,1262,1079,1266,1078,1265,1095,1282,1098,1285,1097,1284,
+ 1390,1391,1392,1393,1099,1286,1100,1287,1101,1288,1102,1289,1105,1292,1104,1291,
+ 1106,1294,1107,1295,1108,1296,1114,1302,1119,1308,1122,1311,1123,1312,1186,1260,
+ 1293,1305, 0,1394, 0, 0, 0, 0, 952,1137, 947,1132,1317,1344,1316,1343,
+ 1319,1346,1318,1345,1693,1695,1371,1375,1370,1374,1373,1377,1372,1376,1694,1696,
+ 981,1166, 977,1162, 972,1157,1326,1353,1325,1352,1328,1355,1327,1354,1697,1698,
+ 1009,1194,1013,1198,1054,1240,1048,1234,1331,1358,1330,1357,1333,1360,1332,1359,
+ 1699,1700,1396,1401,1395,1400,1398,1403,1397,1402,1399,1404,1094,1281,1087,1274,
+ 1406,1411,1405,1410,1408,1413,1407,1412,1409,1414,1109,1297,1117,1306,1116,1304,
+ 1112,1300, 0, 0, 0, 0, 0, 0,1471,1472,1701,1705,1702,1706,1703,1707,
+ 1430,1431,1715,1719,1716,1720,1717,1721,1477,1478,1729,1731,1730,1732, 0, 0,
+ 1435,1436,1733,1735,1734,1736, 0, 0,1481,1482,1737,1741,1738,1742,1739,1743,
+ 1439,1440,1751,1755,1752,1756,1753,1757,1490,1491,1765,1768,1766,1769,1767,1770,
+ 1447,1448,1771,1774,1772,1775,1773,1776,1495,1496,1777,1779,1778,1780, 0, 0,
+ 1451,1452,1781,1783,1782,1784, 0, 0,1504,1505,1785,1788,1786,1789,1787,1790,
+ 0,1459, 0,1791, 0,1792, 0,1793,1509,1510,1794,1798,1795,1799,1796,1800,
+ 1462,1463,1808,1812,1809,1813,1810,1814,1467, 21,1475, 22,1479, 23,1485, 24,
+ 1493, 27,1499, 28,1507, 29, 0, 0,1704,1708,1709,1710,1711,1712,1713,1714,
+ 1718,1722,1723,1724,1725,1726,1727,1728,1740,1744,1745,1746,1747,1748,1749,1750,
+ 1754,1758,1759,1760,1761,1762,1763,1764,1797,1801,1802,1803,1804,1805,1806,1807,
+ 1811,1815,1816,1817,1818,1819,1820,1821,1470,1469,1822,1474,1465, 0,1473,1825,
+ 1429,1428,1426, 12,1432, 0, 26, 0, 0,1315,1823,1484,1466, 0,1483,1829,
+ 1433, 13,1437, 14,1441,1826,1827,1828,1488,1487,1513, 19, 0, 0,1492,1515,
+ 1445,1444,1442, 15, 0,1831,1832,1833,1502,1501,1516, 25,1497,1498,1506,1518,
+ 1457,1456,1454, 17,1453,1313, 11, 3, 0, 0,1824,1512,1519, 0,1511,1830,
+ 1449, 16,1460, 18,1464, 4, 0, 0, 30, 31, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0,
+ 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1834,1835, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1836, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1837,1839,1838, 0, 0, 0, 0,1840, 0, 0, 0,
+ 0,1841, 0, 0,1842, 0, 0, 0, 0, 0, 0, 0,1843, 0,1844, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1845, 0, 0,1846, 0, 0,1847,
+ 0,1848, 0, 0, 0, 0, 0, 0, 937, 0,1850, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1849, 936, 938,1851,1852, 0, 0,1853,1854, 0, 0,
+ 1855,1856, 0, 0, 0, 0, 0, 0,1857,1858, 0, 0,1861,1862, 0, 0,
+ 1863,1864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1867,1868,1869,1870,1859,1860,1865,1866, 0, 0, 0, 0,
+ 0, 0,1871,1872,1873,1874, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1875, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1877, 0,1878, 0,1879, 0,1880, 0,1881, 0,1882, 0,
+ 1883, 0,1884, 0,1885, 0,1886, 0,1887, 0,1888, 0, 0,1889, 0,1890,
+ 0,1891, 0, 0, 0, 0, 0, 0,1892,1893, 0,1894,1895, 0,1896,1897,
+ 0,1898,1899, 0,1900,1901, 0, 0, 0, 0, 0, 0,1876, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1902, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1904, 0,1905, 0,1906, 0,1907, 0,1908, 0,1909, 0,
+ 1910, 0,1911, 0,1912, 0,1913, 0,1914, 0,1915, 0, 0,1916, 0,1917,
+ 0,1918, 0, 0, 0, 0, 0, 0,1919,1920, 0,1921,1922, 0,1923,1924,
+ 0,1925,1926, 0,1927,1928, 0, 0, 0, 0, 0, 0,1903, 0, 0,1929,
+ 1930,1931,1932, 0, 0, 0,1933, 0, 710, 385, 724, 715, 455, 103, 186, 825,
+ 825, 242, 751, 205, 241, 336, 524, 601, 663, 676, 688, 738, 411, 434, 474, 500,
+ 649, 746, 799, 108, 180, 416, 482, 662, 810, 275, 462, 658, 692, 344, 618, 679,
+ 293, 388, 440, 492, 740, 116, 146, 168, 368, 414, 481, 527, 606, 660, 665, 722,
+ 781, 803, 809, 538, 553, 588, 642, 758, 811, 701, 233, 299, 573, 612, 487, 540,
+ 714, 779, 232, 267, 412, 445, 457, 585, 594, 766, 167, 613, 149, 148, 560, 589,
+ 648, 768, 708, 345, 411, 704, 105, 259, 313, 496, 518, 174, 542, 120, 307, 101,
+ 430, 372, 584, 183, 228, 529, 650, 697, 424, 732, 428, 349, 632, 355, 517, 110,
+ 135, 147, 403, 580, 624, 700, 750, 170, 193, 245, 297, 374, 463, 543, 763, 801,
+ 812, 815, 162, 384, 420, 730, 287, 330, 337, 366, 459, 476, 509, 558, 591, 610,
+ 726, 652, 734, 759, 154, 163, 198, 473, 683, 697, 292, 311, 353, 423, 572, 494,
+ 113, 217, 259, 280, 314, 499, 506, 603, 608, 752, 778, 782, 788, 117, 557, 748,
+ 774, 320, 109, 126, 260, 265, 373, 411, 479, 523, 655, 737, 823, 380, 765, 161,
+ 395, 398, 438, 451, 502, 516, 537, 583, 791, 136, 340, 769, 122, 273, 446, 727,
+ 305, 322, 400, 496, 771, 155, 190, 269, 377, 391, 406, 432, 501, 519, 599, 684,
+ 687, 749, 776, 175, 452, 191, 480, 510, 659, 772, 805, 813, 397, 444, 619, 566,
+ 568, 575, 491, 471, 707, 111, 636, 156, 153, 288, 346, 578, 256, 435, 383, 729,
+ 680, 767, 694, 295, 128, 210, 0, 0, 227, 0, 379, 0, 0, 150, 493, 525,
+ 544, 551, 552, 556, 783, 576, 604, 0, 661, 0, 703, 0, 0, 735, 743, 0,
+ 0, 0, 793, 794, 795, 808, 741, 773, 118, 127, 130, 166, 169, 177, 207, 213,
+ 215, 226, 229, 268, 270, 317, 327, 329, 335, 369, 375, 381, 404, 441, 448, 458,
+ 477, 484, 503, 539, 545, 547, 546, 548, 549, 550, 554, 555, 561, 564, 569, 591,
+ 593, 595, 598, 607, 620, 625, 625, 651, 690, 695, 705, 706, 716, 717, 733, 735,
+ 777, 786, 790, 315, 869, 623, 0, 0, 102, 145, 134, 115, 129, 138, 165, 171,
+ 207, 202, 206, 212, 227, 231, 240, 243, 250, 254, 294, 296, 303, 308, 319, 325,
+ 321, 329, 326, 335, 341, 357, 360, 362, 370, 379, 388, 389, 393, 421, 424, 438,
+ 456, 454, 458, 465, 477, 535, 485, 490, 493, 507, 512, 514, 521, 522, 525, 526,
+ 528, 533, 532, 541, 565, 569, 574, 586, 591, 597, 607, 637, 647, 674, 691, 693,
+ 695, 698, 703, 699, 705, 704, 702, 706, 709, 717, 728, 736, 747, 754, 770, 777,
+ 783, 784, 786, 787, 790, 802, 825, 848, 847, 857, 55, 65, 66, 883, 892, 916,
+ 822, 824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1586, 0,1605, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584, 0,
+ 1585,1587,1588,1589,1591, 0,1592, 0,1593,1594, 0,1595,1596, 0,1598,1599,
+ 1600,1601,1604,1582,1578,1590,1597, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1936, 0,1937, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1938, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1939,1940, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1941,1942, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1944,1943, 0,1945, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1946,1947, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1949,1950,1951,1952,1953,1954,1955, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1956,1957,1958,1960,1959,1961, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 106, 104, 107, 826, 114, 118, 119, 121,
+ 123, 124, 127, 125, 34, 830, 130, 131, 132, 137, 827, 35, 133, 139, 829, 142,
+ 143, 112, 144, 145, 924, 151, 152, 37, 157, 158, 159, 160, 38, 165, 166, 169,
+ 171, 172, 173, 174, 176, 177, 178, 179, 181, 182, 182, 182, 833, 468, 184, 185,
+ 834, 187, 188, 189, 196, 192, 194, 195, 197, 199, 200, 201, 203, 204, 204, 206,
+ 208, 209, 211, 218, 213, 219, 214, 216, 153, 234, 221, 222, 223, 220, 225, 224,
+ 230, 835, 235, 236, 237, 238, 239, 244, 836, 837, 247, 248, 249, 246, 251, 39,
+ 40, 253, 255, 255, 838, 257, 258, 259, 261, 839, 262, 263, 301, 264, 41, 266,
+ 270, 272, 271, 841, 274, 842, 277, 276, 278, 281, 282, 42, 283, 284, 285, 286,
+ 43, 843, 44, 289, 290, 291, 293, 934, 298, 845, 845, 621, 300, 300, 45, 852,
+ 894, 302, 304, 46, 306, 309, 310, 312, 316, 48, 47, 317, 846, 318, 323, 324,
+ 325, 324, 328, 329, 333, 331, 332, 334, 335, 336, 338, 339, 342, 343, 347, 351,
+ 849, 350, 348, 352, 354, 359, 850, 361, 358, 356, 49, 363, 365, 367, 364, 50,
+ 369, 371, 851, 376, 386, 378, 53, 381, 52, 51, 140, 141, 387, 382, 614, 78,
+ 388, 389, 390, 394, 392, 856, 54, 399, 396, 402, 404, 858, 405, 401, 407, 55,
+ 408, 409, 410, 413, 859, 415, 56, 417, 860, 418, 57, 419, 422, 424, 425, 861,
+ 840, 862, 426, 863, 429, 431, 427, 433, 437, 441, 438, 439, 442, 443, 864, 436,
+ 449, 450, 58, 454, 453, 865, 447, 460, 866, 867, 461, 466, 465, 464, 59, 467,
+ 470, 469, 472, 828, 475, 868, 478, 870, 483, 485, 486, 871, 488, 489, 872, 873,
+ 495, 497, 60, 498, 61, 61, 504, 505, 507, 508, 511, 62, 513, 874, 515, 875,
+ 518, 844, 520, 876, 877, 878, 63, 64, 528, 880, 879, 881, 882, 530, 531, 531,
+ 533, 66, 534, 67, 68, 884, 536, 538, 541, 69, 885, 549, 886, 887, 556, 559,
+ 70, 561, 562, 563, 888, 889, 889, 567, 71, 890, 570, 571, 72, 891, 577, 73,
+ 581, 579, 582, 893, 587, 74, 590, 592, 596, 75, 895, 896, 76, 897, 600, 898,
+ 602, 605, 607, 899, 900, 609, 901, 611, 853, 77, 615, 616, 79, 617, 252, 902,
+ 903, 854, 855, 621, 622, 731, 80, 627, 626, 628, 164, 629, 630, 631, 633, 904,
+ 632, 634, 639, 640, 635, 641, 646, 651, 638, 643, 644, 645, 905, 907, 906, 81,
+ 653, 654, 656, 911, 657, 908, 82, 83, 909, 910, 84, 664, 665, 666, 667, 669,
+ 668, 671, 670, 674, 672, 673, 675, 85, 677, 678, 86, 681, 682, 912, 685, 686,
+ 87, 689, 36, 913, 914, 88, 89, 696, 702, 709, 711, 915, 712, 713, 718, 719,
+ 917, 831, 721, 720, 723, 832, 725, 728, 918, 919, 739, 742, 744, 920, 745, 753,
+ 756, 757, 755, 760, 761, 921, 762, 90, 764, 922, 91, 775, 279, 780, 923, 925,
+ 92, 93, 785, 926, 94, 927, 787, 787, 789, 928, 792, 95, 796, 797, 798, 800,
+ 96, 929, 802, 804, 806, 97, 98, 807, 930, 99, 931, 932, 933, 814, 100, 816,
+ 817, 818, 819, 820, 821, 935, 0, 0,
};
static const int16_t
_hb_ucd_i16[196] =
@@ -3889,12 +2797,12 @@ _hb_ucd_i16[196] =
static inline uint_fast8_t
_hb_ucd_gc (unsigned u)
{
- return u<1114110u?_hb_ucd_u8[2176+(((_hb_ucd_u16[((_hb_ucd_u8[u>>4>>5])<<5)+((u>>4)&31u)])<<4)+((u)&15u))]:2;
+ return u<1114110u?_hb_ucd_u8[6800+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
}
static inline uint_fast8_t
_hb_ucd_ccc (unsigned u)
{
- return u<125259u?_hb_ucd_u8[15332+(((_hb_ucd_u8[13892+(((_hb_ucd_u8[12912+(u>>3>>4)])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:0;
+ return u<125259u?_hb_ucd_u8[8792+(((_hb_ucd_u8[8236+(((_hb_ucd_u8[7776+(((_hb_ucd_u8[7424+(((_hb_ucd_u8[7178+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
}
static inline unsigned
_hb_ucd_b4 (const uint8_t* a, unsigned i)
@@ -3904,24 +2812,24 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i)
static inline int_fast16_t
_hb_ucd_bmg (unsigned u)
{
- return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[16692+(((_hb_ucd_b4(16564+_hb_ucd_u8,u>>2>>6))<<6)+((u>>2)&63u))])<<2)+((u)&3u)]:0;
+ return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9540+(((_hb_ucd_u8[9420+(((_hb_ucd_b4(9292+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
}
static inline uint_fast8_t
_hb_ucd_sc (unsigned u)
{
- return u<918000u?_hb_ucd_u8[19446+(((_hb_ucd_u16[3168+(((_hb_ucd_u8[17652+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:2;
+ return u<918000u?_hb_ucd_u8[11062+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10326+(((_hb_ucd_u8[9876+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
}
static inline uint_fast16_t
_hb_ucd_dm (unsigned u)
{
- return u<195102u?_hb_ucd_u16[6400+(((_hb_ucd_u8[30070+(u>>6)])<<6)+((u)&63u))]:0;
+ return u<195102u?_hb_ucd_u16[6008+(((_hb_ucd_u8[17068+(((_hb_ucd_u8[16686+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
}
#elif !defined(HB_NO_UCD_UNASSIGNED)
static const uint8_t
-_hb_ucd_u8[17936] =
+_hb_ucd_u8[14744] =
{
0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 11, 12, 13, 13, 13, 14,
@@ -3929,7 +2837,7 @@ _hb_ucd_u8[17936] =
25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 22, 42,
- 7, 7, 43, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 7, 7, 43, 7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
@@ -3951,12 +2859,12 @@ _hb_ucd_u8[17936] =
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
@@ -3975,35 +2883,36 @@ _hb_ucd_u8[17936] =
118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
- 160,161,162,163,164,165,122,122,166,167,168,169,122,170,122,171,
- 34, 34, 34, 34, 34, 34, 34,172,173, 34,174,122,122,122,122,122,
- 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,175,
- 34, 34, 34, 34, 34, 34, 34, 34,176,122,122,122,122,122,122,122,
+ 160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173,
+ 34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177,
+ 34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122,
122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
- 122,122,122,122,122,122,122,122, 34, 34, 34, 34,177,122,122,122,
- 34, 34, 34, 34,178,179,180,181,122,122,122,122,182,183,184,185,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,186,
- 34, 34, 34, 34, 34, 34, 34, 34, 34,187,188,122,122,122,122,122,
- 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,189,
- 34, 34,190, 34, 34,191,122,122,122,122,122,122,122,122,122,122,
- 122,122,122,122,122,122,122,122,192,193,122,122,122,122,122,122,
- 122,122,122,122,122,122,122,122,122,122,122,122,122,122,194,195,
- 69,196,197,198,199,200,201,122,202,203,204,205,206,207,208,209,
- 69, 69, 69, 69,210,211,122,122,122,122,122,122,122,122,212,122,
- 213,122,214,122,122,215,122,122,122,122,122,122,122,122,122,216,
- 34,217,218,122,122,122,122,122,219,220,221,122,222,223,122,122,
- 224,225,226,227,228,122, 69,229, 69, 69, 69, 69, 69,230,231,232,
- 233,234, 69, 69,235,236, 69,237,122,122,122,122,122,122,122,122,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,238, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,239, 34,
- 240, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,241, 34, 34,
- 34, 34, 34, 34, 34, 34, 34,242,122,122,122,122,122,122,122,122,
- 34, 34, 34, 34,243,122,122,122,122,122,122,122,122,122,122,122,
- 34, 34, 34, 34, 34, 34,244,122,122,122,122,122,122,122,122,122,
- 245,122,246,247,122,122,122,122,122,122,122,122,122,122,122,122,
- 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,248,
- 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,249,
+ 122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122,
+ 34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191,
+ 34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197,
+ 69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211,
+ 69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122,
+ 215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220,
+ 34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122,
+ 228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236,
+ 237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34,
+ 244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34,246,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34,247,122,122,122,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34, 34, 34,248, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34,249,122,122,122,122,122,122,122,122,
+ 250,122,251,252,122,122,122,122,122,122,122,122,122,122,122,122,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,253,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254,
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2,
7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
@@ -4066,7 +2975,7 @@ _hb_ucd_u8[17936] =
44, 44, 57, 80, 36, 61, 62, 44, 44, 44, 44, 93, 27, 27, 27, 91,
70, 86, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 87,
86, 86, 90, 85, 90, 86, 43, 44, 44, 44, 89, 90, 44, 44, 62, 61,
- 62, 61, 44, 44, 44, 44, 44, 44, 43, 86, 36, 36, 36, 36, 61, 36,
+ 62, 94, 44, 44, 44, 44, 44, 44, 43, 86, 36, 36, 36, 36, 61, 36,
36, 36, 36, 36, 36, 70, 71, 86, 87, 43, 80, 86, 90, 86, 87, 77,
44, 44, 36, 94, 27, 27, 27, 95, 27, 27, 27, 27, 91, 36, 36, 36,
57, 86, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36,
@@ -4076,7 +2985,7 @@ _hb_ucd_u8[17936] =
36, 36, 36, 75, 43, 43, 43, 60, 7, 7, 7, 7, 7, 2, 44, 44,
44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 61, 36, 36, 61, 36, 36,
36, 36, 62, 62, 36, 36, 36, 36, 70, 36, 43, 43, 43, 43, 71, 44,
- 36, 36, 61, 81, 43, 43, 43, 44, 7, 7, 7, 7, 7, 44, 36, 36,
+ 36, 36, 61, 81, 43, 43, 43, 80, 7, 7, 7, 7, 7, 44, 36, 36,
77, 67, 2, 2, 2, 2, 2, 2, 2, 97, 97, 67, 43, 67, 67, 67,
7, 7, 7, 7, 7, 27, 27, 27, 27, 27, 50, 50, 50, 4, 4, 86,
36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44,
@@ -4243,18 +3152,19 @@ _hb_ucd_u8[17936] =
44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
- 36, 44, 44, 44, 44, 44, 44, 44, 27, 27, 27, 95, 44, 44, 44, 44,
- 180, 27, 30, 2, 2, 44, 44, 44, 36, 43, 43, 2, 2, 44, 44, 44,
- 36, 36,183, 27, 27, 27, 44, 44, 87, 98, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 43, 60, 2, 2, 2, 44,
- 27, 27, 27, 7, 7, 7, 7, 7, 71, 70, 71, 44, 44, 44, 44, 57,
- 86, 87, 43, 85, 87, 60,185, 2, 2, 80, 44, 44, 44, 44, 79, 44,
- 43, 71, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43, 87, 43,
- 43, 43, 80, 7, 7, 7, 7, 7, 2, 2, 94, 98, 44, 44, 44, 44,
- 36, 70, 2, 61, 44, 44, 44, 44, 36, 94, 86, 43, 43, 43, 43, 85,
- 98, 36, 63, 2, 59, 43, 60, 87, 7, 7, 7, 7, 7, 63, 63, 2,
- 179, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44, 44, 44, 44, 44,
- 36, 36, 36, 36, 36, 36, 86, 87, 43, 86, 85, 43, 2, 2, 2, 80,
+ 36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43,
+ 27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30, 2, 2, 44, 44, 44,
+ 36, 43, 43, 2, 2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44,
+ 87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43,
+ 43, 43, 43, 60, 2, 2, 2, 44, 27, 27, 27, 7, 7, 7, 7, 7,
+ 71, 70, 71, 44, 44, 44, 44, 57, 86, 87, 43, 85, 87, 60,185, 2,
+ 2, 80, 44, 44, 44, 44, 79, 44, 43, 71, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 70, 43, 43, 87, 43, 43, 43, 80, 7, 7, 7, 7, 7,
+ 2, 2, 94, 98, 44, 44, 44, 44, 36, 70, 2, 61, 44, 44, 44, 44,
+ 36, 94, 86, 43, 43, 43, 43, 85, 98, 36, 63, 2, 59, 43, 60, 87,
+ 7, 7, 7, 7, 7, 63, 63, 2,179, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27,100, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 86, 87,
+ 43, 86, 85, 43, 2, 2, 2, 71, 70, 44, 44, 44, 44, 44, 44, 44,
36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62,
36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70,
86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
@@ -4276,17 +3186,20 @@ _hb_ucd_u8[17936] =
70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 85, 70, 43, 60,
2, 2, 2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43, 2, 72, 2,
- 2, 64, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87,
- 63, 2, 2, 44, 44, 44, 44, 44, 2, 36, 36, 36, 36, 36, 36, 36,
- 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43,
- 85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36,
- 70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44,
- 36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90,
- 43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44,
+ 2, 64, 44, 44, 44, 44, 44, 44, 2, 2, 2, 2, 2, 44, 44, 44,
+ 43, 43, 43, 80, 43, 43, 43, 87, 63, 2, 2, 44, 44, 44, 44, 44,
+ 2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44,
+ 36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57,
+ 43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36,
+ 36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44,
+ 36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36,
+ 36, 36, 86, 43, 43, 80, 44, 86, 85, 60, 2, 2, 2, 2, 2, 2,
27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
2, 2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
- 65, 65, 65, 65,132, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
+ 65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43,
+ 43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
43, 43, 43, 60, 2, 2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
7, 7, 7, 7, 7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30, 2, 64, 44, 44,
@@ -4294,7 +3207,8 @@ _hb_ucd_u8[17936] =
86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
- 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
+ 36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44,
+ 36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
@@ -4319,10 +3233,12 @@ _hb_ucd_u8[17936] =
43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
67, 67, 76, 21, 2, 2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
- 43, 43, 43, 80, 43, 43, 43, 43, 43, 43, 43, 43, 80, 57, 43, 43,
- 43, 57, 80, 43, 43, 80, 44, 44, 43, 43, 43, 74, 40, 40, 40, 44,
- 7, 7, 7, 7, 7, 44, 44, 77, 36, 36, 36, 36, 36, 36, 36, 80,
- 36, 36, 36, 36, 36, 36, 43, 43, 7, 7, 7, 7, 7, 44, 44, 96,
+ 44, 44,150, 16, 16,110, 44, 44, 43, 43, 43, 80, 43, 43, 43, 43,
+ 43, 43, 43, 43, 80, 57, 43, 43, 43, 57, 80, 43, 43, 80, 44, 44,
+ 40, 40, 40, 40, 40, 40, 40, 44, 44, 44, 44, 44, 44, 44, 44, 57,
+ 43, 43, 43, 74, 40, 40, 40, 44, 7, 7, 7, 7, 7, 44, 44, 77,
+ 36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43,
+ 7, 7, 7, 7, 7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43,
36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
@@ -4335,156 +3251,136 @@ _hb_ucd_u8[17936] =
27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
- 67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 55, 67,
- 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 44, 67, 67, 92, 44,
+ 67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67,
+ 67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 44, 44, 44, 44, 67,
67, 92, 67, 67, 67, 67, 67, 67, 79, 44, 44, 44, 44, 44, 44, 44,
- 65, 65, 65, 65, 65, 65, 65, 65,171,171,171,171,171,171,171, 44,
- 171,171,171,171,171,171,171, 0, 0, 0, 29, 21, 21, 21, 23, 21,
- 22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21, 9, 9, 9,
- 9, 22, 21, 18, 24, 16, 24, 5, 5, 5, 5, 22, 25, 18, 25, 0,
- 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24, 26, 25, 15, 15,
- 24, 15, 7, 19, 15, 21, 9, 25, 9, 5, 5, 25, 5, 9, 5, 7,
- 7, 7, 9, 8, 8, 5, 7, 5, 6, 6, 24, 24, 6, 24, 12, 12,
- 2, 2, 6, 5, 9, 21, 9, 2, 2, 9, 25, 9, 26, 12, 11, 11,
- 2, 6, 5, 21, 17, 2, 2, 26, 26, 23, 2, 12, 17, 12, 21, 12,
- 12, 21, 7, 2, 2, 7, 7, 21, 21, 2, 1, 1, 21, 23, 26, 26,
- 1, 21, 6, 7, 7, 12, 12, 7, 21, 7, 12, 1, 12, 6, 6, 12,
- 12, 26, 7, 26, 26, 7, 2, 1, 12, 2, 6, 2, 24, 7, 7, 6,
- 1, 12, 12, 10, 10, 10, 10, 12, 21, 6, 2, 10, 10, 2, 15, 26,
- 26, 2, 2, 21, 7, 10, 15, 7, 2, 23, 21, 26, 10, 7, 21, 15,
- 15, 2, 17, 7, 29, 7, 7, 22, 18, 2, 14, 14, 14, 7, 10, 21,
- 17, 21, 11, 12, 5, 2, 5, 6, 8, 8, 8, 24, 5, 24, 2, 24,
- 9, 24, 24, 2, 29, 29, 29, 1, 17, 17, 20, 19, 22, 20, 27, 28,
- 1, 29, 21, 20, 19, 21, 21, 16, 16, 21, 25, 22, 18, 21, 21, 29,
- 1, 2, 15, 6, 18, 6, 23, 2, 12, 11, 9, 26, 26, 9, 26, 5,
- 5, 26, 14, 9, 5, 14, 14, 15, 25, 26, 26, 22, 18, 26, 18, 25,
- 18, 22, 5, 12, 2, 5, 22, 21, 21, 22, 18, 17, 26, 6, 7, 14,
- 17, 22, 18, 18, 26, 14, 17, 6, 14, 6, 12, 24, 24, 6, 26, 15,
- 6, 21, 11, 21, 24, 9, 6, 9, 23, 26, 6, 10, 4, 4, 3, 3,
- 7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25, 2, 25, 24, 2, 15,
- 12, 15, 14, 2, 21, 14, 7, 15, 12, 17, 21, 1, 26, 10, 10, 1,
- 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12,
- 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20,
- 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32,
- 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 34, 0, 35, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0,
- 0, 0, 39, 40, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0,
- 0, 0, 0, 0, 6, 7, 8, 0, 9, 0, 10, 11, 0, 0, 12, 13,
- 14, 15, 16, 0, 0, 0, 0, 17, 18, 19, 20, 0, 21, 0, 22, 23,
- 0, 24, 25, 0, 0, 24, 26, 27, 0, 24, 26, 0, 0, 24, 26, 0,
- 0, 24, 26, 0, 0, 0, 26, 0, 0, 24, 28, 0, 0, 24, 26, 0,
- 0, 29, 26, 0, 0, 0, 30, 0, 0, 31, 32, 0, 0, 33, 34, 0,
- 35, 36, 0, 37, 38, 0, 39, 0, 0, 40, 0, 0, 41, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 43, 44, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 46, 0, 0,
- 0, 47, 0, 0, 0, 0, 0, 0, 48, 0, 0, 49, 0, 50, 51, 0,
- 0, 52, 53, 54, 0, 55, 0, 56, 0, 57, 0, 0, 0, 0, 58, 59,
- 0, 0, 0, 0, 0, 0, 60, 61, 0, 0, 0, 0, 0, 0, 62, 63,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,
- 0, 0, 0, 65, 0, 0, 0, 66, 0, 67, 0, 0, 68, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 0, 0, 71,
- 0, 0, 0, 0, 0, 0, 0, 0, 72, 73, 0, 0, 0, 0, 53, 74,
- 0, 75, 76, 0, 0, 77, 78, 0, 0, 0, 0, 0, 0, 79, 80, 81,
- 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0,
- 82, 0, 0, 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 85,
- 0, 0, 0, 86, 0, 0, 0, 0, 87, 88, 0, 0, 0, 0, 0, 89,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 0,
- 0, 0, 92, 0, 93, 0, 0, 0, 0, 0, 72, 94, 0, 95, 0, 0,
- 96, 97, 0, 77, 0, 0, 98, 0, 0, 99, 0, 0, 0, 0, 0,100,
- 0,101, 26,102, 0, 0, 0, 0, 0, 0,103, 0, 0, 0,104, 0,
- 0, 0, 0, 0, 0, 65,105, 0, 0, 65, 0, 0, 0,106, 0, 0,
- 0,107, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0,
- 0,108,109, 0, 0, 0, 0, 78, 0, 44,110, 0,111, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0,
- 0, 0,112, 0,113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,
- 0,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,116, 0, 0, 0, 0,117, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,118,119,120, 0, 0, 0, 0,121, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,122,123, 0, 0, 0, 0, 0, 0,
- 0,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 0,125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0,
- 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 171,171,171,171,171,171,171, 44,171,171,171,171,171,171,171, 0,
+ 0, 0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13,
+ 25, 25, 25, 21, 21, 9, 9, 9, 9, 22, 21, 18, 24, 16, 24, 5,
+ 5, 5, 5, 22, 25, 18, 25, 0, 23, 23, 26, 21, 24, 26, 7, 20,
+ 25, 1, 26, 24, 26, 25, 15, 15, 24, 15, 7, 19, 15, 21, 9, 25,
+ 9, 5, 5, 25, 5, 9, 5, 7, 7, 7, 9, 8, 8, 5, 7, 5,
+ 6, 6, 24, 24, 6, 24, 12, 12, 2, 2, 6, 5, 9, 21, 9, 2,
+ 2, 9, 25, 9, 26, 12, 11, 11, 2, 6, 5, 21, 17, 2, 2, 26,
+ 26, 23, 2, 12, 17, 12, 21, 12, 12, 21, 7, 2, 2, 7, 7, 21,
+ 21, 2, 1, 1, 21, 23, 26, 26, 1, 21, 6, 7, 7, 12, 12, 7,
+ 21, 7, 12, 1, 12, 6, 6, 12, 12, 26, 7, 26, 26, 7, 2, 1,
+ 12, 2, 6, 2, 24, 7, 7, 6, 1, 12, 12, 10, 10, 10, 10, 12,
+ 21, 6, 2, 10, 10, 2, 15, 26, 26, 2, 2, 21, 7, 10, 15, 7,
+ 2, 23, 21, 26, 10, 7, 21, 15, 15, 2, 17, 7, 29, 7, 7, 22,
+ 18, 2, 14, 14, 14, 7, 10, 21, 17, 21, 11, 12, 5, 2, 5, 6,
+ 8, 8, 8, 24, 5, 24, 2, 24, 9, 24, 24, 2, 29, 29, 29, 1,
+ 17, 17, 20, 19, 22, 20, 27, 28, 1, 29, 21, 20, 19, 21, 21, 16,
+ 16, 21, 25, 22, 18, 21, 21, 29, 1, 2, 15, 6, 18, 6, 23, 2,
+ 12, 11, 9, 26, 26, 9, 26, 5, 5, 26, 14, 9, 5, 14, 14, 15,
+ 25, 26, 26, 22, 18, 26, 18, 25, 18, 22, 5, 12, 2, 5, 22, 21,
+ 21, 22, 18, 17, 26, 6, 7, 14, 17, 22, 18, 18, 26, 14, 17, 6,
+ 14, 6, 12, 24, 24, 6, 26, 15, 6, 21, 11, 21, 24, 9, 6, 9,
+ 23, 26, 6, 10, 4, 4, 3, 3, 7, 25, 17, 16, 16, 22, 16, 16,
+ 25, 17, 25, 2, 25, 24, 2, 15, 12, 15, 14, 2, 21, 14, 7, 15,
+ 12, 17, 21, 1, 26, 10, 10, 1, 23, 15, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 0, 10, 11, 12, 13, 0, 14, 0, 0, 0, 0, 0,
+ 15, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 19,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 20, 0, 21, 22, 23, 0, 0, 0, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35,
+ 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 38, 39, 0, 0, 0, 0, 0, 0, 40, 41, 42, 0, 43, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0,
+ 0, 0, 3, 0, 0, 0, 4, 5, 6, 7, 0, 8, 9, 10, 0, 11,
+ 12, 13, 14, 15, 16, 17, 16, 18, 16, 19, 16, 19, 16, 19, 0, 19,
+ 16, 20, 16, 19, 21, 19, 0, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0,
+ 0, 0, 0, 0, 34, 0, 0, 35, 0, 0, 36, 0, 37, 0, 0, 0,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 0, 0, 47, 0, 0, 0, 48,
+ 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 50, 0, 51, 0, 52,
+ 53, 0, 54, 0, 0, 0, 0, 0, 0, 55, 56, 57, 0, 0, 0, 0,
+ 58, 0, 0, 59, 60, 61, 62, 63, 0, 0, 64, 65, 0, 0, 0, 66,
+ 0, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 70, 0, 71, 0, 0,
+ 72, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0,
+ 0, 0, 75, 76, 0, 77, 78, 0, 0, 79, 80, 0, 81, 62, 0, 82,
+ 83, 0, 0, 84, 85, 86, 0, 0, 0, 87, 0, 88, 0, 0, 51, 89,
+ 51, 0, 90, 0, 91, 0, 0, 0, 80, 0, 0, 0, 92, 93, 0, 94,
+ 95, 96, 97, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 98, 99, 0,
+ 0, 0, 0, 0, 0,100, 0, 0, 0, 0, 0,101,102, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,103, 0, 0,104, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,105,106, 0, 0,107, 0, 0, 0, 0, 0, 0,
+ 108, 0,109, 0,102, 0, 0, 0, 0, 0,110,111, 0, 0, 0, 0,
+ 0, 0, 0,112, 0, 0, 0, 0, 0, 0, 0,113, 0,114, 0, 0,
+ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 8, 0, 0, 0,
+ 0, 9, 10, 11, 12, 0, 0, 0, 0, 13, 0, 0, 14, 15, 0, 16,
+ 0, 17, 18, 0, 0, 19, 0, 20, 21, 0, 0, 0, 0, 0, 22, 23,
+ 0, 24, 25, 0, 0, 26, 0, 0, 0, 27, 0, 0, 28, 29, 30, 31,
+ 0, 0, 0, 32, 33, 34, 0, 0, 33, 0, 0, 35, 33, 0, 0, 0,
+ 33, 36, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0, 0, 0, 39,
+ 40, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 43, 0, 44,
+ 0, 0, 0, 45, 46, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 48,
+ 49, 0, 0, 0, 0, 50, 0, 0, 0, 51, 0, 52, 0, 53, 0, 0,
+ 0, 0, 54, 0, 0, 0, 0, 55, 0, 56, 0, 0, 0, 0, 57, 58,
+ 0, 0, 0, 59, 60, 0, 0, 0, 0, 0, 0, 61, 52, 0, 62, 63,
+ 0, 0, 64, 0, 0, 0, 65, 66, 0, 0, 0, 67, 0, 68, 69, 70,
+ 71, 72, 1, 73, 0, 74, 75, 76, 0, 0, 77, 78, 0, 0, 0, 79,
+ 0, 0, 1, 1, 0, 0, 80, 0, 0, 81, 0, 0, 0, 0, 77, 82,
+ 0, 83, 0, 0, 0, 0, 0, 78, 84, 0, 85, 0, 52, 0, 1, 78,
+ 0, 0, 86, 0, 0, 87, 0, 0, 0, 0, 0, 88, 57, 0, 0, 0,
+ 0, 0, 0, 89, 90, 0, 0, 84, 0, 0, 33, 0, 0, 91, 0, 0,
+ 0, 0, 92, 0, 0, 0, 0, 49, 0, 0, 93, 0, 0, 0, 0, 94,
+ 95, 0, 0, 96, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99, 0,
+ 0, 0, 0,100,101, 93, 0, 0,102, 0, 0, 0, 84, 0, 0,103,
+ 0, 0, 0,104,105, 0, 0,106,107, 0, 0, 0, 0, 0, 0,108,
+ 0, 0,109, 0, 0, 0, 0,110, 33, 0,111,112,113, 35, 0, 0,
+ 114, 0, 0, 0,115, 0, 0, 0, 0, 0, 0,116, 0, 0,117, 0,
+ 0, 0, 0,118, 88, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 52,
+ 119, 0, 0, 0, 0,120, 0, 0,121, 0, 0, 0, 0,119, 0, 0,
+ 122, 0, 0, 0, 0, 0, 0,123, 0, 0, 0,124, 0, 0, 0,125,
+ 0,126, 0, 0, 0, 0,127,128,129, 0,130, 0,131, 0, 0, 0,
+ 132,133,134, 0, 77, 0, 0, 0, 0, 0, 35, 0, 0, 0,135, 0,
+ 0, 0,136, 0, 0,137, 0, 0,138, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 4, 4, 8, 9, 10,
- 1, 11, 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, 0, 0, 0, 0,
- 19, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 1,
- 23, 4, 21, 24, 25, 26, 27, 28, 29, 30, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, 34, 35, 1, 36,
- 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 38, 1, 39,
- 14, 39, 40, 41, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0,
- 0, 0, 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 0, 0,
- 0, 0, 19, 1, 21, 0, 0, 47, 0, 0, 0, 0, 0, 38, 48, 1,
- 1, 49, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0,
- 0, 0, 0, 0, 0, 0, 52, 1, 0, 0, 38, 14, 4, 1, 1, 1,
- 53, 21, 43, 52, 54, 21, 35, 1, 0, 0, 0, 0, 0, 0, 0, 55,
- 0, 0, 0, 56, 57, 58, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 56, 0, 60, 0, 0,
- 0, 0, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 69, 70, 0,
- 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, 0, 0, 0, 0, 0, 0,
- 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 79, 0,
- 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49,
- 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0,
- 0, 0, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 19, 84, 0,
- 62, 0, 0, 0, 0, 49, 1, 85, 0, 0, 0, 0, 1, 52, 15, 86,
- 36, 10, 21, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0,
- 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 19, 10, 1, 0, 0, 0,
- 0, 0, 88, 0, 0, 0, 0, 0, 0, 89, 0, 0, 88, 0, 0, 0,
- 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 87, 9, 12, 4,
+ 1, 11, 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, 19, 1, 0, 0,
+ 20, 21, 22, 1, 23, 4, 21, 24, 25, 26, 27, 28, 29, 30, 0, 0,
+ 1, 1, 31, 0, 0, 0, 32, 33, 34, 35, 1, 36, 37, 0, 0, 0,
+ 0, 38, 1, 39, 14, 39, 40, 41, 42, 0, 0, 0, 43, 36, 44, 45,
+ 21, 45, 46, 0, 0, 0, 19, 1, 21, 0, 0, 47, 0, 38, 48, 1,
+ 1, 49, 49, 50, 0, 0, 51, 0, 0, 0, 52, 1, 0, 0, 38, 14,
+ 4, 1, 1, 1, 53, 21, 43, 52, 54, 21, 35, 1, 0, 0, 0, 55,
+ 0, 0, 0, 56, 57, 58, 0, 0, 0, 0, 0, 59, 0, 60, 0, 0,
+ 0, 0, 61, 62, 0, 0, 63, 0, 0, 0, 64, 0, 0, 0, 65, 0,
+ 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 69, 70, 0,
+ 71, 72, 73, 74, 75, 76, 0, 0, 0, 77, 0, 0, 0, 78, 79, 0,
+ 0, 0, 0, 47, 0, 0, 0, 49, 0, 80, 0, 0, 0, 62, 0, 0,
+ 63, 0, 0, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 19, 84, 0,
+ 62, 0, 0, 0, 0, 49, 1, 85, 1, 52, 15, 86, 36, 10, 21, 87,
+ 0, 55, 0, 0, 0, 0, 19, 10, 1, 0, 0, 0, 0, 0, 88, 0,
+ 0, 89, 0, 0, 88, 0, 0, 0, 0, 78, 0, 0, 87, 9, 12, 4,
90, 8, 91, 47, 0, 58, 50, 0, 21, 1, 21, 92, 93, 1, 1, 1,
- 1, 1, 1, 1, 1, 94, 95, 96, 0, 0, 0, 0, 97, 1, 98, 58,
- 81, 99,100, 4, 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 61, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0,101,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,103, 0,
- 0, 0, 0, 19, 0, 1, 1, 50, 0, 0, 0, 0, 0, 0, 0, 38,
- 0, 0, 0, 0, 50, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 62, 0, 0, 0, 0, 1, 1, 1, 1, 50, 0, 0, 0,
- 0, 0,104, 68, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0,
- 0, 0, 0, 0, 78, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,
- 1, 14, 4, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47,
- 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 87, 0,
- 0, 0, 0,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,109, 61,
- 0,110, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 19, 58, 0, 0, 0, 0, 0,111, 14, 52, 84, 0, 0, 0,
- 112, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 61,
- 0, 0, 0, 0, 0, 0,113, 0, 87, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,113, 0, 0, 0, 0,114, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 78, 55, 0, 38, 1, 58, 1, 58, 0, 0,
- 63, 89, 0, 0, 0, 0, 0, 59,115, 0, 0, 0, 0, 0, 0, 0,
- 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,115, 0, 0,
- 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79,
- 78, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 8, 91, 0, 0,
- 0, 0, 0, 0, 1, 87, 0, 0, 0, 0, 0, 0,116, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,117, 0,118,119,120,121, 0,104, 4,
- 122, 49, 23, 0, 0, 0, 0, 0, 0, 0, 38, 50, 0, 0, 0, 0,
- 38, 58, 0, 0, 0, 0, 0, 0, 1, 87, 1, 1, 1, 1, 39, 1,
- 48,105, 87, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0,
- 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4,122, 0, 0,
- 0, 1,123, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,
+ 1, 94, 95, 96, 97, 1, 98, 58, 81, 99,100, 4, 58, 0, 0, 0,
+ 0, 0, 0, 19, 50, 0, 0, 0, 0, 0, 0, 61, 0, 0,101,102,
+ 0, 0,103, 0, 0, 1, 1, 50, 0, 0, 0, 38, 0, 63, 0, 0,
+ 0, 0, 0, 62, 0, 0,104, 68, 61, 0, 0, 0, 78, 0, 0, 0,
+ 105,106, 58, 38, 81, 0, 0, 0, 0, 0, 0,107, 1, 14, 4, 12,
+ 84, 0, 0, 0, 0, 38, 87, 0, 0, 0, 0,108, 0, 0,109, 61,
+ 0,110, 0, 0, 0, 1, 0, 0, 0, 0, 19, 58, 0, 0, 0, 51,
+ 0,111, 14, 52,112, 41, 0, 0, 62, 0, 0, 61, 0, 0,113, 0,
+ 87, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0, 0,113, 0, 0,
+ 0, 0,114, 0, 0, 0, 78, 55, 0, 38, 1, 58, 1, 58, 0, 0,
+ 63, 89, 0, 0,115, 0, 0, 0, 55, 0, 0, 0, 0,115, 0, 0,
+ 0, 0, 61, 0, 0, 0, 0, 79, 0, 61, 0, 0, 0, 0, 56, 0,
+ 89, 80, 0, 0, 79, 0, 0, 0, 8, 91, 0, 0, 1, 87, 0, 0,
+ 116, 0, 0, 0, 0, 0, 0,117, 0,118,119,120,121, 0,104, 4,
+ 122, 49, 23, 0, 0, 0, 38, 50, 38, 58, 0, 0, 1, 87, 1, 1,
+ 1, 1, 39, 1, 48,105, 87, 0, 0, 0, 0, 1, 0, 0, 0,123,
+ 4,122, 0, 0, 0, 1,124, 0, 0, 0, 0, 0,230,230,230,230,
230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220,
220,220,220,202,202,220,220,220, 1, 1, 1, 1, 1,220,220,220,
220,230,230,230,230,240,230,220,220,220,230,230,230,220,220, 0,
@@ -4515,51 +3411,54 @@ _hb_ucd_u8[17936] =
0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0,
0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0,
0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,216, 0,
- 220,220,220, 0,230,230, 7, 0, 16, 17, 17, 17, 17, 17, 17, 33,
- 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27,
- 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 220,220,220, 0,232,232,220,230,230,230, 7, 0, 16, 17, 17, 33,
+ 17, 49, 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17,237, 0, 1, 2, 2, 0, 3, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 7, 8, 9, 0, 0, 0,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 20, 0, 0, 21, 22, 0, 0, 0, 0, 23, 24, 25, 26,
- 0, 27, 0, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 33,
- 34, 35, 36, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 38, 39, 0, 0, 0, 0, 1, 2, 40, 41, 0, 1, 2, 2,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2,
- 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 5, 0, 0, 0, 6, 0,
- 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 8, 9,
- 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0,
- 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0, 0, 0, 0, 1,
- 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7, 20, 20, 20, 20,
- 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0, 20, 20, 25, 0,
- 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1, 28, 29, 30, 31,
- 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0,
- 0, 0, 20, 20, 20, 1, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33,
- 7, 20, 20, 20, 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0,
- 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0,
- 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 8, 21, 0, 1, 0, 1,
- 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42,
- 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 46,
- 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 20, 20, 1, 20, 20, 0,
- 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24,
- 25, 26, 13, 13, 13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,177, 0, 1, 2, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 6, 7, 8, 3,
+ 3, 3, 3, 3, 9, 10, 11, 12, 13, 3, 3, 3, 3, 3, 3, 3,
+ 3, 14, 3, 15, 3, 3, 3, 3, 3, 3, 16, 17, 18, 19, 20, 21,
+ 3, 3, 3, 22, 23, 24, 3, 3, 3, 3, 3, 3, 25, 3, 3, 3,
+ 3, 3, 3, 3, 3, 26, 3, 3, 27, 28, 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0, 0,
+ 0, 0, 0, 0, 0, 10, 11, 12, 13, 0, 0, 14, 15, 16, 6, 0,
+ 17, 18, 19, 19, 19, 20, 21, 22, 23, 24, 19, 25, 0, 26, 27, 19,
+ 19, 28, 29, 30, 0, 31, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,
+ 0, 19, 28, 0, 32, 33, 9, 34, 35, 19, 0, 0, 36, 37, 38, 39,
+ 40, 19, 0, 41, 42, 43, 44, 31, 0, 1, 45, 42, 0, 0, 0, 0,
+ 0, 32, 14, 14, 0, 0, 0, 0, 14, 0, 0, 46, 47, 47, 47, 47,
+ 48, 49, 47, 47, 47, 47, 50, 51, 52, 53, 43, 21, 0, 0, 0, 0,
+ 0, 0, 0, 54, 6, 55, 0, 14, 19, 1, 0, 0, 0, 0, 56, 57,
+ 0, 0, 0, 0, 0, 19, 58, 31, 0, 0, 0, 0, 0, 0, 0, 59,
+ 14, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 60,
+ 61, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3,
+ 0, 4, 5, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 1, 1, 0,
+ 0, 8, 9, 0, 8, 9, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0,
+ 0, 0, 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 1, 0,
+ 0, 18, 19, 0, 0, 0, 20, 0, 0, 0, 1, 1, 1, 1, 0, 1,
+ 1, 1, 1, 1, 1, 1, 0, 8, 21, 9, 0, 0, 22, 0, 0, 0,
+ 0, 1, 0, 23, 24, 25, 0, 0, 26, 0, 0, 0, 8, 21, 27, 0,
+ 1, 0, 0, 1, 1, 1, 1, 0, 1, 28, 29, 30, 0, 31, 32, 20,
+ 1, 1, 0, 0, 0, 8, 21, 9, 1, 4, 5, 0, 0, 0, 33, 9,
+ 0, 1, 1, 1, 0, 8, 21, 21, 21, 21, 34, 1, 35, 21, 21, 21,
+ 9, 36, 0, 0, 37, 38, 1, 0, 39, 0, 0, 0, 1, 0, 1, 0,
+ 0, 0, 0, 8, 21, 9, 1, 0, 0, 0, 40, 0, 8, 21, 21, 21,
+ 21, 21, 21, 21, 21, 9, 0, 1, 1, 1, 1, 8, 21, 21, 21, 9,
+ 0, 0, 0, 41, 0, 42, 43, 0, 0, 0, 1, 44, 0, 0, 0, 45,
+ 8, 9, 1, 0, 0, 0, 8, 21, 21, 21, 9, 0, 1, 0, 1, 1,
+ 8, 21, 21, 9, 0, 4, 5, 8, 9, 1, 0, 0, 0, 1, 2, 3,
+ 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13,
+ 13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 13, 42,
- 7, 7, 43, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 13, 42, 7, 7, 43, 7,
+ 44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
@@ -4580,411 +3479,221 @@ _hb_ucd_u8[17936] =
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 44, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 2, 2,
- 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59,
- 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69,
- 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45, 0, 0, 1,
+ 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 2, 2, 53, 54, 55, 56,
+ 57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61,
+ 59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70,
- 70, 70, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84,
- 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 70, 70, 97, 98, 99,100,101,101,102,103,104,105,
- 106,107,108,109,110,111, 96,112,113,114,115,116,117,118,119,119,
- 120,121,122,123,124,125,126,127,128,129,130,131,132, 96,133,134,
- 135,136,137,138,139,140,141,142,143, 96,144,145, 96,146,147,148,
- 149, 96,150,151,152,153,154,155, 96, 96,156,157,158,159, 96,160,
- 96,161,162,162,162,162,162,162,162,163,164,162,165, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96,166,167,167,167,167,167,167,167,167,168, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,169,169,169,169,170, 96,
- 96, 96,171,171,171,171,172,173,174,175, 96, 96, 96, 96,176,177,
- 178,179,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
- 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
- 180,181,180,180,180,180,180,180,182,182,182,183,184, 96, 96, 96,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96,
96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96,185,186,187,188,189,189,190, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,191,192, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 193,194, 59,195,196,197,198,199,200, 96,201,202,203, 59, 59,204,
- 59,205,206,206,206,206,206,207, 96, 96, 96, 96, 96, 96, 96, 96,
- 208, 96,209, 96,210, 96, 96,211, 96, 96, 96, 96, 96, 96, 96, 96,
- 96,212,213,214,215, 96, 96, 96, 96, 96,216,217,218, 96,219,220,
- 96, 96,221,222, 59,223,224, 96, 59, 59, 59, 59, 59, 59, 59,225,
- 226,227,228,229, 59, 59,230,231, 59,232, 96, 96, 96, 96, 96, 96,
- 96, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,233,
+ 70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109,
+ 110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123,
+ 124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138,
+ 139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151,
+ 152,153,154,155,156, 96,157,158,159,160, 96,161,162,163,164,164,
+ 164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169,
+ 169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173,
+ 173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182,
+ 182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+ 182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182,
+ 182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189,
+ 190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197,
+ 198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208,
+ 208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212,
+ 213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218,
+ 219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226,
+ 59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233,
+ 59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 70,
70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 234, 70,235, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,236,
- 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 96, 96, 96, 96, 96, 96,
- 96, 96, 70, 70, 70, 70,238, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 70, 70, 70, 70, 70, 70,239, 96, 96, 96, 96, 96, 96, 96,
- 96, 96,240, 96,241,242, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3,
- 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0,
- 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19,
- 19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0,
- 0, 0, 0, 0, 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
- 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2, 9, 9, 9, 9,
- 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9, 9, 2, 9, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9,
- 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1,
- 1, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 2, 2, 4,
- 4, 4, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 14, 14, 14, 2, 2, 2,
- 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 3, 3, 3, 3, 3, 0,
- 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37,
- 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2,
- 2, 2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64,
- 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 2, 2, 90, 90, 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 2, 2, 95, 2, 37, 37, 37, 2, 2, 2,
- 2, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2,
- 2, 2, 3, 3, 0, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 0, 0,
- 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 2,
- 2, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2,
- 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5,
- 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5, 5,
- 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 2, 2, 11, 11, 11, 2, 11, 11, 11, 11, 11, 11, 2, 2, 2,
- 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 2, 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11,
- 11, 2, 11, 11, 2, 2, 11, 2, 11, 11, 11, 2, 2, 11, 11, 11,
- 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, 2,
- 11, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 2, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10,
- 10, 10, 10, 10, 2, 2, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10,
- 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2,
- 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10,
- 10, 10, 2, 21, 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2,
- 2, 21, 21, 2, 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21,
- 21, 21, 21, 21, 2, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21,
- 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 2, 2, 2, 2, 21, 21,
- 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2, 2, 22, 22, 2, 22,
- 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22,
- 2, 2, 2, 22, 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2,
- 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2,
- 22, 22, 22, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2,
- 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23,
- 23, 23, 23, 23, 2, 2, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23,
- 2, 2, 2, 2, 2, 2, 2, 23, 23, 2, 23, 23, 23, 2, 2, 23,
- 2, 2, 23, 23, 23, 23, 2, 2, 23, 23, 2, 2, 2, 2, 2, 2,
- 2, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2,
- 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16,
- 16, 16, 16, 16, 2, 2, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16,
- 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2,
- 16, 16, 2, 16, 16, 2, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20,
- 20, 20, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2,
- 20, 20, 2, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, 36, 36, 36, 36,
- 36, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36,
- 2, 2, 2, 2, 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2,
- 36, 2, 2, 2, 2, 2, 2, 2, 36, 36, 2, 2, 36, 36, 36, 2,
- 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 2, 2,
- 2, 2, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18,
- 2, 18, 18, 18, 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2,
- 18, 2, 18, 18, 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25,
- 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2,
- 2, 2, 25, 25, 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0,
- 0, 0, 0, 25, 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33,
- 33, 33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 2, 8, 2, 2, 2, 2, 2, 8, 2, 2, 8, 8, 8, 0, 8, 8,
- 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30,
- 30, 2, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 2,
- 2, 2, 30, 30, 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28,
- 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 2,
- 2, 2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0,
- 35, 35, 35, 2, 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0,
- 0, 2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2,
- 2, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 2,
- 46, 46, 46, 2, 46, 46, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 2, 2, 31, 31, 2, 2, 2, 2,
- 2, 2, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 2, 2, 2, 2, 2, 2, 32, 2, 2, 2, 2, 2,
- 2, 2, 32, 32, 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28,
- 2, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 2, 48, 48, 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48,
- 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 2, 2, 52, 52, 52, 52, 52, 2, 2, 2, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 2, 2, 2, 2, 58, 58, 2, 2, 2, 2,
- 2, 2, 58, 58, 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 2,
- 2, 91, 91, 91, 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91,
- 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62,
- 62, 2, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 2, 2, 2, 2, 2, 2, 2, 2, 93, 93,
- 93, 93, 70, 70, 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70,
- 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73,
- 73, 73, 6, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 2, 2, 8,
- 8, 8, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
- 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19,
- 9, 9, 9, 9, 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9,
- 9, 9, 9, 9, 19, 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19,
- 19, 19, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9,
- 2, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 2, 2,
- 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0,
- 0, 2, 19, 19, 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2,
- 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
- 9, 0, 0, 0, 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 19, 0, 19, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
- 2, 2, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2,
- 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 56, 56, 56, 56, 56, 56,
- 56, 56, 55, 55, 55, 55, 2, 2, 2, 2, 2, 55, 55, 55, 55, 55,
- 55, 55, 61, 61, 61, 61, 61, 61, 61, 61, 2, 2, 2, 2, 2, 2,
- 2, 61, 61, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
- 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13,
- 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13,
- 0, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1,
- 12, 12, 13, 13, 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,240, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70,241, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70,242, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70, 70, 70,243, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70,244, 96, 96, 96, 96, 96, 96, 96, 96,245, 96,
+ 246,247, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 0, 0,
+ 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0,
+ 19, 0, 19, 0, 0, 0, 0, 0, 26, 26, 1, 1, 1, 1, 9, 9,
+ 9, 9, 0, 9, 9, 9, 2, 2, 9, 9, 9, 9, 0, 9, 2, 2,
+ 2, 2, 9, 0, 9, 0, 9, 9, 9, 2, 9, 2, 9, 9, 9, 9,
+ 2, 9, 9, 9, 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 1,
+ 1, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 14, 14, 2,
+ 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 3, 3, 3, 3,
+ 3, 0, 3, 3, 3, 1, 1, 1, 3, 3, 1, 3, 3, 3, 37, 37,
+ 37, 37, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38,
+ 38, 38, 38, 38, 2, 2, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64,
+ 64, 64, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90, 90, 2, 95, 95,
+ 95, 95, 2, 2, 95, 2, 3, 3, 3, 2, 3, 3, 2, 2, 3, 3,
+ 0, 3, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 0, 0,
+ 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 2, 2, 5, 5, 2,
+ 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, 2, 2, 5, 5,
+ 5, 2, 2, 2, 2, 5, 5, 5, 2, 5, 2, 11, 11, 11, 11, 11,
+ 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 2,
+ 11, 11, 2, 11, 11, 2, 11, 11, 2, 2, 2, 11, 2, 2, 11, 2,
+ 11, 2, 2, 2, 11, 11, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 2, 10, 10, 2, 10, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2,
+ 10, 10, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2,
+ 21, 21, 21, 21, 2, 2, 21, 21, 2, 21, 2, 2, 21, 21, 2, 2,
+ 22, 22, 2, 22, 22, 22, 22, 22, 22, 2, 22, 2, 22, 22, 22, 22,
+ 2, 2, 2, 22, 22, 2, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22,
+ 22, 22, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 23,
+ 23, 2, 23, 23, 23, 2, 2, 23, 2, 2, 2, 2, 23, 23, 2, 2,
+ 2, 23, 16, 16, 16, 16, 16, 2, 16, 16, 2, 16, 16, 16, 16, 16,
+ 2, 2, 2, 16, 16, 2, 2, 2, 16, 16, 20, 20, 20, 20, 20, 2,
+ 20, 20, 2, 2, 20, 20, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 2, 2, 2, 36, 36, 36, 36, 2, 36, 2, 36, 2, 2, 2, 2,
+ 36, 2, 2, 2, 2, 36, 36, 2, 36, 2, 36, 2, 2, 2, 2, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 0, 2, 18,
+ 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 2, 18,
+ 2, 18, 18, 18, 2, 2, 18, 2, 18, 2, 25, 25, 25, 25, 2, 25,
+ 25, 25, 25, 2, 2, 2, 25, 2, 25, 25, 25, 0, 0, 0, 0, 25,
+ 25, 2, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 2, 8, 2, 8,
+ 2, 2, 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, 30, 2,
+ 30, 30, 30, 30, 2, 2, 30, 30, 30, 2, 2, 30, 30, 30, 30, 2,
+ 2, 2, 29, 29, 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 34, 34,
+ 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0,
+ 35, 35, 35, 2, 2, 2, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2,
+ 2, 45, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43, 43, 43, 46, 46,
+ 46, 46, 46, 2, 46, 46, 31, 31, 31, 31, 31, 31, 2, 2, 32, 32,
+ 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 2, 2, 32, 2,
+ 2, 2, 32, 32, 32, 2, 28, 28, 2, 2, 48, 48, 48, 48, 48, 48,
+ 48, 2, 48, 2, 2, 2, 52, 52, 52, 52, 52, 52, 2, 2, 52, 2,
+ 2, 2, 58, 58, 58, 58, 58, 58, 2, 2, 58, 58, 58, 2, 2, 2,
+ 58, 58, 54, 54, 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91,
+ 91, 2, 91, 2, 2, 91, 91, 91, 2, 2, 1, 1, 1, 2, 62, 62,
+ 62, 62, 62, 2, 2, 2, 62, 62, 62, 2, 76, 76, 76, 76, 93, 93,
+ 93, 93, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 2, 2, 2, 70,
+ 70, 70, 73, 73, 73, 73, 6, 2, 2, 2, 8, 8, 8, 2, 2, 8,
+ 8, 8, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1,
+ 0, 0, 1, 1, 0, 2, 19, 19, 9, 9, 9, 9, 9, 6, 19, 9,
+ 9, 9, 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19, 19, 19,
+ 19, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 9, 9, 1, 1,
+ 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 19, 0, 0,
+ 0, 2, 19, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2, 0, 0,
+ 9, 0, 0, 0, 19, 19, 27, 27, 27, 27, 2, 2, 0, 0, 0, 0,
+ 2, 0, 56, 56, 56, 56, 2, 55, 55, 55, 61, 61, 61, 61, 2, 2,
+ 2, 61, 61, 2, 2, 2, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13,
+ 2, 13, 13, 13, 2, 2, 0, 13, 0, 13, 0, 13, 13, 13, 13, 13,
+ 1, 1, 1, 1, 12, 12, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 2, 2, 1, 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17,
- 17, 17, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 2, 12, 12, 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17,
- 17, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 2,
- 2, 2, 39, 39, 39, 39, 39, 39, 39, 2, 86, 86, 86, 86, 86, 86,
- 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 2, 2,
- 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 19, 19, 19, 19,
- 19, 19, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2,
- 2, 2, 19, 19, 2, 19, 2, 19, 19, 19, 19, 19, 2, 2, 2, 2,
- 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 2, 2, 2, 0, 0, 2, 2, 2, 2,
- 2, 2, 65, 65, 65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 2, 2,
- 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74,
- 74, 74, 74, 74, 74, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 74, 12, 12, 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2,
- 84, 84, 33, 33, 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 68, 68, 68, 68, 68, 68,
- 2, 2, 68, 68, 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 2, 2, 2, 2, 2, 2, 2, 2, 92, 92, 92,
- 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 2, 2, 30, 30, 30, 30, 30, 30, 2, 19, 19, 19, 0, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 9, 19, 19, 19, 19, 0, 0, 2, 2,
- 2, 2, 87, 87, 87, 87, 87, 87, 2, 2, 87, 87, 2, 2, 2, 2,
- 2, 2, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12,
- 12, 12, 13, 13, 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19,
- 19, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 14, 14, 14, 14, 14, 2,
- 14, 2, 14, 14, 2, 14, 14, 2, 14, 14, 3, 3, 3, 2, 2, 2,
- 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2,
- 2, 3, 1, 1, 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0,
- 0, 0, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2,
- 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12,
- 12, 12, 2, 2, 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0,
- 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49,
- 2, 49, 49, 49, 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2,
- 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2,
- 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2,
- 2, 2, 0, 0, 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
- 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,
- 118,118,118,118,118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 2, 2, 2, 2, 59, 59, 59, 59, 59, 59,
- 2, 2, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51,
- 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 2, 2, 50, 50, 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,
- 135,135,135,135,135,135, 2, 2, 2, 2,106,106,106,106,106,106,
- 106,106,104,104,104,104,104,104,104,104,104,104,104,104, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2,104,161,161,161,161,161,161,
- 161,161,161,161,161, 2,161,161,161,161,161,161,161, 2,161,161,
- 2,161,161,161, 2,161,161,161,161,161,161,161, 2,161,161, 2,
- 2, 2,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
- 110, 2,110,110,110,110,110,110, 2, 2, 19, 19, 19, 19, 19, 19,
- 2, 19, 19, 2, 19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47,
- 2, 2, 47, 2, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2,
- 2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
- 2, 81,120,120,120,120,120,120,120,120,116,116,116,116,116,116,
- 116,116,116,116,116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2,
- 2,116,128,128,128,128,128,128,128,128,128,128,128, 2,128,128,
- 2, 2, 2, 2, 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72,
- 72, 72, 72, 72, 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98,
- 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 2, 2, 2, 2, 97, 97,
- 97, 97, 2, 2, 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57,
- 57, 2, 2, 2, 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57,
- 57, 57, 2, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 2, 2, 57, 57, 57, 2, 2, 2,
- 2, 57, 57, 2, 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88,
- 88, 88,117,117,117,117,117,117,117,117,112,112,112,112,112,112,
- 112,112,112,112,112,112,112,112,112, 2, 2, 2, 2,112,112,112,
- 112,112, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
- 2, 2, 2, 78, 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 2, 2, 2, 2, 2,122,122,122,122,122,122,
- 122,122,122,122, 2, 2, 2, 2, 2, 2, 2,122,122,122,122, 2,
- 2, 2, 2,122,122,122,122,122,122,122, 89, 89, 89, 89, 89, 89,
- 89, 89, 89, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,
- 130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,
- 130,130,144,144,144,144,144,144,144,144,144,144, 2, 2, 2, 2,
- 2, 2,156,156,156,156,156,156,156,156,156,156, 2,156,156,156,
- 2, 2,156,156, 2, 2, 2, 2, 2, 2,147,147,147,147,147,147,
- 147,147,148,148,148,148,148,148,148,148,148,148, 2, 2, 2, 2,
- 2, 2,158,158,158,158,158,158,158,158,158,158, 2, 2, 2, 2,
- 2, 2,153,153,153,153,153,153,153,153,153,153,153,153, 2, 2,
- 2, 2,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
- 149, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 2, 2,
- 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,
- 101,101,101, 2, 2, 2, 2, 2, 2, 2,101,101, 2, 2, 2, 2,
- 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2,
- 96, 96,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
- 111, 2,100,100,100,100,100,100,100,100, 2, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,108,108,108,108,108,108,
- 108,108,108,108, 2,108,108,108,108,108,108,108,108,108,108,108,
- 108, 2,129,129,129,129,129,129,129, 2,129, 2,129,129,129,129,
- 2,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
- 2,129,129,129, 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,
- 109,109,109,109,109, 2, 2, 2, 2, 2,109,109, 2, 2, 2, 2,
- 2, 2,107,107,107,107, 2,107,107,107,107,107,107,107,107, 2,
- 2,107,107, 2, 2,107,107,107,107,107,107,107,107,107,107,107,
- 107,107,107, 2,107,107,107,107,107,107,107, 2,107,107, 2,107,
- 107,107,107,107, 2, 1,107,107,107,107,107, 2, 2,107,107,107,
- 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2, 2, 2, 2,107,
- 107,107,107,107,107,107, 2, 2,107,107,107,107,107,107,107, 2,
- 2, 2,137,137,137,137,137,137,137,137,137,137,137,137, 2,137,
- 137,137,137,137, 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,
- 124,124,124,124, 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,
- 123,123,123,123,123,123,123,123, 2, 2,114,114,114,114,114,114,
- 114,114,114,114,114,114,114, 2, 2, 2,114,114, 2, 2, 2, 2,
- 2, 2, 32, 32, 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,
- 102,102,102,102, 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,
- 126,126,126,126,126, 2, 2,126,126,126,126,126,126,126, 2, 2,
- 2, 2,126,126,126,126,126,126,126, 2,142,142,142,142,142,142,
- 142,142,142,142,142,142, 2, 2, 2, 2,125,125,125,125,125,125,
- 125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2,125,154,154,154,154,154,154,154, 2, 2,154, 2, 2,154,154,
- 154,154,154,154,154,154, 2,154,154, 2,154,154,154,154,154,154,
- 154,154,154,154,154,154,154,154, 2,154,154, 2, 2,154,154,154,
- 154,154,154,154, 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,
- 150,150, 2, 2,150,150,150,150,150,150,150,150,150,150,150, 2,
- 2, 2,141,141,141,141,141,141,141,141,140,140,140,140,140,140,
- 140,140,140,140,140, 2, 2, 2, 2, 2,121,121,121,121,121,121,
- 121,121,121, 2, 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,
- 133,133,133, 2,133,133,133,133,133,133,133,133,133,133,133,133,
- 133, 2,133,133,133,133,133,133, 2, 2,133,133,133,133,133, 2,
- 2, 2,134,134,134,134,134,134,134,134, 2, 2,134,134,134,134,
- 134,134, 2,134,134,134,134,134,134,134,134,134,134,134,134,134,
- 134, 2,138,138,138,138,138,138,138, 2,138,138, 2,138,138,138,
- 138,138,138,138,138,138,138,138,138,138, 2, 2,138, 2,138,138,
- 2,138,138,138, 2, 2, 2, 2, 2, 2,143,143,143,143,143,143,
- 2,143,143, 2,143,143,143,143,143,143,143,143,143,143,143,143,
- 143,143,143,143,143,143,143,143,143, 2,143,143, 2,143,143,143,
- 143,143,143, 2, 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2,
- 2, 2,145,145,145,145,145,145,145,145,145, 2, 2, 2, 2, 2,
- 2, 2, 86, 2, 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63,
- 63, 2, 63, 63, 63, 63, 63, 2, 2, 2, 63, 63, 63, 63, 2, 2,
- 2, 2,157,157,157,157,157,157,157,157,157,157,157, 2, 2, 2,
- 2, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 2, 80, 2, 2, 2, 2, 2, 2, 2,127,127,127,127,127,127,
- 127,127,127,127,127,127,127,127,127, 2, 79, 2, 2, 2, 2, 2,
- 2, 2,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 115, 2,115,115, 2, 2, 2, 2,115,115,159,159,159,159,159,159,
- 159,159,159,159,159,159,159,159,159, 2,159,159, 2, 2, 2, 2,
- 2, 2,103,103,103,103,103,103,103,103,103,103,103,103,103,103,
- 2, 2,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
- 2, 2,119,119, 2,119,119,119,119,119, 2, 2, 2, 2, 2,119,
- 119,119,146,146,146,146,146,146,146,146,146,146,146, 2, 2, 2,
- 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2,
- 2, 99, 2, 2, 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2,
- 2, 2,136,136,136,136,136,136,136,136,155,155,155,155,155,155,
- 155,155,155,155,155,155,155,155, 2, 2,136, 2, 2, 2, 2, 2,
- 2, 2, 17, 17, 17, 17, 2, 17, 17, 17, 17, 17, 17, 17, 2, 17,
- 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2,
- 2, 2, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17,
- 17, 17,139,139,139,139,139,139,139,139,139,139,139,139, 2, 2,
- 2, 2,105,105,105,105,105,105,105,105,105,105,105, 2, 2, 2,
- 2, 2,105,105,105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2,
- 2, 2,105,105, 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1,
- 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1,
- 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
- 0, 0, 2, 2, 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2,
- 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0,
- 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0,
- 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,
- 131,131,131,131,131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,
- 131,131, 2,131,131,131,131,131,131,131, 56, 56, 56, 56, 56, 56,
- 56, 2, 56, 2, 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2,
- 56, 56, 56, 56, 56, 2, 2, 2, 2, 2,151,151,151,151,151,151,
- 151,151,151,151,151,151,151, 2, 2, 2,151,151,151,151,151,151,
+ 17, 17, 17, 17, 17, 0, 2, 26, 26, 26, 26, 26, 26, 26, 2, 12,
+ 12, 12, 12, 12, 12, 2, 12, 12, 12, 0, 39, 39, 39, 39, 39, 2,
+ 2, 2, 39, 39, 39, 2, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79,
+ 79, 79, 19, 19, 19, 2, 19, 19, 2, 19, 2, 19, 19, 19, 19, 19,
+ 2, 2, 2, 2, 19, 19, 60, 60, 60, 60, 60, 2, 2, 2, 65, 65,
+ 65, 65, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2, 75, 75, 69, 69,
+ 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 2, 2, 2, 74, 12, 2,
+ 2, 2, 84, 84, 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2,
+ 84, 84, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 2, 68, 68,
+ 2, 2, 92, 92, 92, 92, 92, 92, 92, 2, 2, 2, 2, 92, 87, 87,
+ 87, 87, 87, 87, 87, 2, 19, 9, 19, 19, 19, 19, 0, 0, 87, 87,
+ 2, 2, 2, 2, 2, 12, 2, 2, 2, 4, 14, 2, 14, 2, 14, 14,
+ 2, 14, 14, 2, 14, 14, 2, 2, 2, 3, 3, 3, 0, 0, 2, 2,
+ 3, 3, 1, 1, 6, 6, 3, 2, 3, 3, 3, 2, 2, 0, 2, 0,
+ 0, 0, 0, 0, 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 49, 49,
+ 49, 49, 2, 49, 49, 49, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49,
+ 2, 2, 9, 2, 2, 2, 0, 1, 2, 2, 71, 71, 71, 71, 71, 2,
+ 2, 2, 67, 67, 67, 67, 67, 2, 2, 2, 42, 42, 42, 42, 2, 42,
+ 42, 42, 41, 41, 41, 41, 41, 41, 41, 2,118,118,118,118,118,118,
+ 118, 2, 53, 53, 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59,
+ 2, 2, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50,
+ 2, 2,135,135,135,135,106,106,106,106,104,104,104,104, 2, 2,
+ 2,104,161,161,161,161,161,161,161, 2,161,161, 2,161,161, 2,
+ 2, 2,110,110,110,110,110,110,110, 2,110,110, 2, 2, 19, 2,
+ 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2, 47, 47, 47, 47,
+ 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81,
+ 2, 81,120,120,120,120,116,116,116,116,116,116,116, 2, 2, 2,
+ 2,116,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2,
+ 2,128, 66, 66, 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72,
+ 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 97, 97, 97, 97, 2, 2,
+ 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 57, 57, 57, 57, 57,
+ 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2, 2, 2, 88, 88,
+ 88, 88,117,117,117,117,112,112,112,112,112,112,112, 2, 2, 2,
+ 2,112, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78, 78, 78, 83, 83,
+ 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 2,122,122,
+ 122,122,122,122, 2, 2, 2,122,122,122,122, 2, 2, 2, 89, 89,
+ 89, 89, 89, 2, 2, 2,130,130,130,130,130,130,130, 2, 2, 2,
+ 130,130,144,144,144,144,144,144, 2, 2,156,156,156,156,156,156,
+ 2,156,156,156, 2, 2, 2, 3, 3, 3,147,147,147,147,148,148,
+ 148,148,148,148, 2, 2,158,158,158,158,158,158, 2, 2,153,153,
+ 153,153,149,149,149,149,149,149,149, 2, 94, 94, 94, 94, 94, 94,
+ 2, 2, 2, 2, 94, 94, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85,
+ 85, 2, 2, 85, 2, 2,101,101,101,101,101, 2, 2, 2,101,101,
+ 2, 2, 96, 96, 96, 96, 96, 2, 96, 96,111,111,111,111,111,111,
+ 111, 2,100,100,100,100,108,108,108,108,108,108, 2,108,108,108,
+ 2, 2,129,129,129,129,129,129,129, 2,129, 2,129,129,129,129,
+ 2,129,129,129, 2, 2,109,109,109,109,109,109,109, 2,109,109,
+ 2, 2,107,107,107,107, 2,107,107,107,107, 2, 2,107,107, 2,
+ 107,107,107,107, 2, 1,107,107, 2, 2,107, 2, 2, 2, 2, 2,
+ 2,107, 2, 2,107,107,137,137,137,137, 2,137,137,137,137,137,
+ 2, 2,124,124,124,124,124,124, 2, 2,123,123,123,123,123,123,
+ 2, 2,114,114,114,114,114, 2, 2, 2,114,114, 2, 2,102,102,
+ 102,102,102,102, 2, 2,126,126,126,126,126,126,126, 2, 2,126,
+ 126,126,142,142,142,142,125,125,125,125,125,125,125, 2, 2, 2,
+ 2,125,154,154,154,154,154,154,154, 2, 2,154, 2, 2, 2,154,
+ 154, 2,154,154, 2,154,154, 2, 2,154,154,154, 2, 2,150,150,
+ 150,150, 2, 2,150,150,150, 2, 2, 2,141,141,141,141,140,140,
+ 140,140,140,140,140, 2,121,121,121,121,121, 2, 2, 2, 7, 7,
+ 2, 2,133,133,133,133,133, 2,133,133,133,133,133, 2,133,133,
+ 2, 2,133, 2, 2, 2,134,134,134,134, 2, 2,134,134, 2,134,
+ 134,134,134,134,134, 2,138,138,138,138,138,138,138, 2,138,138,
+ 2,138, 2, 2,138, 2,138,138, 2, 2,143,143,143,143,143,143,
+ 2,143,143, 2,143,143,143,143,143, 2,143, 2, 2, 2,143,143,
+ 2, 2,145,145,145,145,145, 2, 2, 2,163,163,163,163,163, 2,
+ 163,163,163,163,163, 2, 2, 2,163,163,163,163, 2, 2, 86, 2,
+ 2, 2, 63, 63, 63, 63, 63, 63, 2, 2, 63, 63, 63, 2, 63, 2,
+ 2, 2,157,157,157,157,157,157,157, 2, 80, 80, 80, 80, 80, 80,
+ 2, 2,127,127,127,127,127,127,127, 2, 79, 2, 2, 2,115,115,
+ 115,115,115,115,115, 2,115,115, 2, 2, 2, 2,115,115,159,159,
+ 159,159,159,159,159, 2,159,159, 2, 2,103,103,103,103,103,103,
+ 2, 2,119,119,119,119,119,119, 2, 2,119,119, 2,119, 2,119,
+ 119,119,146,146,146,146,146,146,146, 2, 99, 99, 99, 99, 99, 99,
+ 99, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2,136,136,
+ 136,136,155,155,155,155,155,155, 2, 2,136, 2, 2, 2, 2, 17,
+ 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 17, 17, 17, 2, 2, 2,
+ 15, 2, 2, 17, 2, 2,139,139,139,139,105,105,105,105,105,105,
+ 105, 2,105, 2, 2, 2,105,105, 2, 2, 1, 1, 2, 2, 0, 0,
+ 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 2, 2, 0, 2, 2, 0,
+ 0, 2, 0, 2, 0, 2,131,131,131,131, 2, 2, 2,131, 2,131,
+ 131,131, 56, 56, 56, 2, 56, 2, 2, 56, 56, 56, 2, 56, 56, 2,
+ 56, 56, 6, 6, 2, 2, 2, 2, 2, 6,151,151,151,151,151, 2,
2, 2,151,151, 2, 2, 2, 2,151,151,160,160,160,160,160,160,
- 160,160,160,160,160,160,160,160,160, 2,152,152,152,152,152,152,
- 152,152,152,152, 2, 2, 2, 2, 2,152, 30, 30, 30, 30, 2, 30,
- 30, 2,113,113,113,113,113,113,113,113,113,113,113,113,113, 2,
- 2,113,113,113,113,113,113,113,113, 2,132,132,132,132,132,132,
- 132,132,132,132,132,132, 2, 2, 2, 2,132,132, 2, 2, 2, 2,
- 132,132, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2,
- 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3,
- 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2,
- 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 3,
- 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, 2, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3,
- 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 15, 0, 0, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 13, 2, 2, 2, 2, 2,
- 2, 2, 13, 13, 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
- 2, 2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10,
- 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9,
+ 160, 2,152,152,152,152,152,152, 2, 2, 2, 2, 2,152,164,164,
+ 164,164,164,164, 2, 2, 2, 30, 30, 2,113,113,113,113,113, 2,
+ 2,113,113,113,113, 2,132,132,132,132,132,132, 2, 2, 2, 2,
+ 132,132, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3, 2, 3, 2, 2,
+ 3, 2, 3, 2, 3, 2, 3, 3, 2, 3, 15, 0, 0, 2, 13, 2,
+ 2, 2, 13, 13, 13, 2, 2, 0, 2, 2, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13, 9, 9, 9, 14,
+ 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9,
+ 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9,
+ 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
@@ -4993,60 +3702,60 @@ _hb_ucd_u8[17936] =
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0,
- 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 24,
+ 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, 0, 34, 0, 35,
+ 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0,
- 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0,
- 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0,
- 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 45, 0, 0,
+ 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0,
+ 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
+ 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 61,
+ 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0,
- 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, 70, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0,
+ 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0,110, 0,111,112,
+ 113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
- 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,
- 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,
- 108, 0,109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,115, 0,
- 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0,
+ 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118,119,120,121,
+ 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,118,119,120,121, 0,122,123,124,125,126, 0,127,
+ 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131,132,133,134,135,
+ 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,
+ 152,153,154,155,156,157, 0, 0, 0,158,159,160,161, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157, 0, 0,
- 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0,
- 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,165, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0,
+ 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,169,170, 0,
+ 0, 0, 0,171,172, 0, 0, 0,173,174,175,176,177,178,179,180,
+ 181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,
+ 197,198,199,200,201,202,203,204,205,206, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,
- 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,
- 189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,
- 205,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
+ 0, 0, 0, 0, 1, 2, 3, 4,
};
static const uint16_t
-_hb_ucd_u16[9200] =
+_hb_ucd_u16[10040] =
{
0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12,
13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23,
@@ -5120,537 +3829,583 @@ _hb_ucd_u16[9200] =
48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140,
48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474,
48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
- 48, 48, 477, 478, 140, 140, 140, 140, 48, 464, 479, 48, 62, 480, 140, 48,
- 481, 140, 140, 48, 482, 140, 48, 314, 483, 48, 48, 484, 485, 457, 486, 487,
- 222, 48, 48, 488, 489, 48, 196, 192, 490, 48, 491, 492, 493, 48, 48, 494,
- 222, 48, 48, 495, 496, 497, 498, 499, 48, 97, 500, 501, 140, 140, 140, 140,
- 502, 503, 504, 48, 48, 505, 506, 192, 507, 83, 84, 508, 509, 510, 511, 512,
- 48, 48, 48, 513, 514, 515, 478, 140, 48, 48, 48, 516, 517, 192, 140, 140,
- 48, 48, 518, 519, 520, 521, 140, 140, 48, 48, 48, 522, 523, 192, 524, 140,
- 48, 48, 525, 526, 192, 140, 140, 140, 48, 173, 527, 528, 314, 140, 140, 140,
- 48, 48, 500, 529, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 530,
- 531, 532, 48, 533, 534, 192, 140, 140, 140, 140, 535, 48, 48, 536, 537, 140,
- 538, 48, 48, 539, 540, 541, 48, 48, 542, 543, 544, 48, 48, 48, 48, 196,
- 84, 48, 518, 545, 546, 148, 175, 547, 48, 548, 549, 550, 140, 140, 140, 140,
- 551, 48, 48, 552, 553, 192, 554, 48, 555, 556, 192, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 48, 557, 140, 140, 140, 100, 271, 558, 559, 560,
- 48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 561, 562,
- 48, 48, 48, 48, 388, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 563,
- 48, 48, 200, 564, 140, 140, 140, 140, 48, 48, 48, 48, 314, 140, 140, 140,
- 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 565,
- 48, 48, 48, 566, 567, 568, 569, 570, 48, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 9, 9, 11, 11, 271, 571, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 572, 573, 574, 574, 575, 576, 140, 140, 140, 140, 577, 578,
+ 48, 48, 477, 478, 140, 140, 140, 479, 48, 464, 480, 48, 62, 481, 140, 48,
+ 482, 140, 140, 48, 483, 140, 48, 314, 484, 48, 48, 485, 486, 457, 487, 488,
+ 222, 48, 48, 489, 490, 48, 196, 192, 491, 48, 492, 493, 494, 48, 48, 495,
+ 222, 48, 48, 496, 497, 498, 499, 500, 48, 97, 501, 502, 503, 140, 140, 140,
+ 504, 505, 506, 48, 48, 507, 508, 192, 509, 83, 84, 510, 511, 512, 513, 514,
+ 48, 48, 48, 515, 516, 517, 478, 140, 48, 48, 48, 518, 519, 192, 140, 140,
+ 48, 48, 520, 521, 522, 523, 140, 140, 48, 48, 48, 524, 525, 192, 526, 140,
+ 48, 48, 527, 528, 192, 140, 140, 140, 48, 173, 529, 530, 314, 140, 140, 140,
+ 48, 48, 501, 531, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 532,
+ 533, 534, 48, 535, 536, 192, 140, 140, 140, 140, 537, 48, 48, 538, 539, 140,
+ 540, 48, 48, 541, 542, 543, 48, 48, 544, 545, 546, 48, 48, 48, 48, 196,
+ 547, 140, 140, 140, 140, 140, 140, 140, 84, 48, 520, 548, 549, 148, 175, 550,
+ 48, 551, 552, 553, 140, 140, 140, 140, 554, 48, 48, 555, 556, 192, 557, 48,
+ 558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 560,
+ 561, 115, 48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566,
+ 48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568,
+ 48, 48, 48, 48, 388, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 569,
+ 48, 48, 48, 570, 571, 572, 140, 140, 48, 48, 48, 48, 314, 140, 140, 140,
+ 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 573,
+ 48, 48, 48, 574, 575, 576, 577, 578, 48, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 9, 9, 11, 11, 271, 579, 140, 140, 140, 140, 140, 140,
+ 48, 48, 48, 48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586,
48, 48, 48, 48, 48, 48, 48, 440, 48, 48, 48, 48, 48, 199, 140, 140,
- 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 579,
- 48, 48, 580, 140, 140, 580, 581, 48, 48, 48, 48, 48, 48, 48, 48, 206,
- 48, 48, 48, 48, 48, 48, 71, 151, 196, 582, 583, 140, 140, 140, 140, 140,
- 32, 32, 584, 32, 585, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 586, 209, 209, 209, 587, 588,
- 589, 209, 590, 209, 209, 209, 288, 140, 209, 209, 209, 209, 591, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 271, 592, 209, 209, 209, 209, 209, 287, 271, 461,
- 9, 593, 11, 594, 595, 596, 241, 9, 597, 598, 599, 600, 601, 9, 593, 11,
- 602, 603, 11, 604, 605, 606, 607, 9, 608, 11, 9, 593, 11, 594, 595, 11,
- 241, 9, 597, 607, 9, 608, 11, 9, 593, 11, 609, 9, 610, 611, 612, 613,
- 11, 614, 9, 615, 616, 617, 618, 11, 619, 9, 620, 11, 621, 622, 622, 622,
- 32, 32, 32, 623, 32, 32, 624, 625, 626, 627, 45, 140, 140, 140, 140, 140,
- 628, 629, 140, 140, 140, 140, 140, 140, 630, 631, 632, 140, 140, 140, 140, 140,
- 48, 48, 151, 633, 634, 140, 140, 140, 140, 48, 635, 140, 48, 48, 636, 637,
- 140, 140, 140, 140, 140, 140, 638, 200, 48, 48, 48, 48, 639, 585, 140, 140,
- 9, 9, 597, 11, 640, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 498,
- 271, 271, 641, 642, 140, 140, 140, 140, 498, 271, 643, 644, 140, 140, 140, 140,
- 645, 48, 646, 647, 648, 649, 650, 651, 652, 206, 653, 206, 140, 140, 140, 654,
- 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 655, 655, 655, 209, 324,
- 656, 209, 209, 209, 209, 209, 209, 209, 209, 209, 657, 140, 140, 140, 658, 209,
- 659, 209, 209, 325, 660, 661, 324, 140, 209, 209, 209, 209, 209, 209, 209, 662,
- 209, 209, 209, 209, 209, 663, 426, 426, 209, 209, 209, 209, 209, 209, 209, 323,
- 209, 209, 209, 209, 209, 660, 325, 427, 325, 209, 209, 209, 664, 176, 209, 209,
- 664, 209, 657, 661, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 657, 665,
- 287, 209, 426, 288, 324, 176, 664, 287, 209, 666, 209, 209, 288, 140, 140, 192,
- 48, 48, 48, 48, 48, 48, 140, 140, 48, 48, 48, 196, 48, 48, 48, 48,
+ 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587,
+ 48, 48, 588, 589, 140, 590, 591, 48, 48, 48, 48, 48, 48, 48, 48, 206,
+ 48, 48, 48, 48, 48, 48, 71, 151, 196, 592, 593, 140, 140, 140, 140, 140,
+ 32, 32, 594, 32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
+ 209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598,
+ 599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140,
+ 140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461,
+ 9, 603, 11, 604, 605, 606, 241, 9, 607, 608, 609, 610, 611, 9, 603, 11,
+ 612, 613, 11, 614, 615, 616, 617, 9, 618, 11, 9, 603, 11, 604, 605, 11,
+ 241, 9, 607, 617, 9, 618, 11, 9, 603, 11, 619, 9, 620, 621, 622, 623,
+ 11, 624, 9, 625, 626, 627, 628, 11, 629, 9, 630, 11, 631, 632, 632, 632,
+ 32, 32, 32, 633, 32, 32, 634, 635, 636, 637, 45, 140, 140, 140, 140, 140,
+ 638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643, 27, 27, 27, 644, 140,
+ 645, 140, 140, 140, 140, 140, 140, 140, 48, 48, 151, 646, 647, 140, 140, 140,
+ 140, 48, 648, 140, 48, 48, 649, 650, 140, 140, 140, 140, 140, 48, 651, 192,
+ 140, 140, 140, 140, 140, 140, 652, 200, 48, 48, 48, 48, 653, 595, 140, 140,
+ 9, 9, 607, 11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499,
+ 271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140,
+ 659, 48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668,
+ 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 669, 669, 669, 209, 324,
+ 670, 209, 209, 209, 209, 209, 209, 209, 209, 209, 671, 140, 140, 140, 672, 209,
+ 673, 209, 209, 325, 674, 675, 324, 140, 209, 209, 209, 209, 209, 209, 209, 676,
+ 209, 209, 209, 209, 209, 677, 426, 426, 209, 209, 209, 209, 209, 209, 209, 678,
+ 209, 209, 209, 209, 209, 176, 325, 427, 325, 209, 209, 209, 679, 176, 209, 209,
+ 679, 209, 671, 675, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 671, 426,
+ 674, 209, 209, 680, 681, 325, 674, 674, 209, 682, 209, 209, 288, 140, 140, 192,
+ 48, 48, 48, 48, 48, 48, 140, 140, 48, 48, 48, 207, 48, 48, 48, 48,
48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 478, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 100, 140, 48, 204, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 71, 140, 140, 140, 667, 140, 668, 668, 668, 668, 668, 668,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140,
- 391, 391, 391, 391, 391, 391, 391, 669, 391, 391, 391, 391, 391, 391, 391, 670,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3,
- 0, 0, 0, 0, 0, 4, 0, 4, 2, 2, 5, 2, 2, 2, 5, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 6, 0, 0, 0, 0, 7, 8, 0, 0,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 11,
- 12, 13, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, 16, 17, 14, 14,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 20, 21, 21, 21, 22, 20, 21, 21, 21, 21,
- 21, 23, 24, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 27, 28, 26,
- 29, 30, 31, 32, 31, 31, 31, 31, 33, 34, 35, 31, 31, 31, 36, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 29, 31, 31, 31, 31,
- 37, 38, 37, 37, 37, 37, 37, 37, 37, 39, 31, 31, 31, 31, 31, 31,
- 40, 40, 40, 40, 40, 40, 41, 26, 42, 42, 42, 42, 42, 42, 42, 43,
- 44, 44, 44, 44, 44, 45, 44, 46, 47, 47, 47, 48, 37, 49, 31, 31,
- 31, 50, 51, 31, 31, 31, 31, 31, 31, 31, 31, 31, 52, 31, 31, 31,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 53, 55, 53, 53, 53,
- 56, 57, 58, 59, 59, 60, 61, 62, 57, 63, 64, 65, 66, 59, 59, 67,
- 68, 69, 70, 71, 71, 72, 73, 74, 69, 75, 76, 77, 78, 71, 79, 26,
- 80, 81, 82, 83, 83, 84, 85, 86, 81, 87, 88, 26, 89, 83, 90, 91,
- 92, 93, 94, 95, 95, 96, 97, 98, 93, 99, 100, 101, 102, 95, 95, 26,
- 103, 104, 105, 106, 107, 104, 108, 109, 104, 105, 110, 26, 111, 108, 108, 112,
- 113, 114, 115, 113, 113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113,
- 122, 123, 124, 122, 122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130, 26,
- 131, 132, 133, 131, 131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131,
- 136, 137, 138, 139, 137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145, 26,
- 146, 147, 147, 147, 147, 147, 147, 148, 147, 147, 147, 149, 26, 26, 26, 26,
- 150, 151, 152, 152, 153, 152, 152, 154, 155, 154, 152, 156, 26, 26, 26, 26,
- 157, 157, 157, 157, 157, 157, 157, 157, 157, 158, 157, 157, 157, 159, 158, 157,
- 157, 157, 157, 158, 157, 157, 157, 160, 157, 160, 161, 162, 26, 26, 26, 26,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 164, 164, 164, 164, 165, 166, 164, 164, 164, 164, 164, 167,
- 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
- 169, 169, 169, 169, 169, 169, 169, 169, 169, 170, 171, 170, 169, 169, 169, 169,
- 169, 170, 169, 169, 169, 169, 170, 171, 170, 169, 171, 169, 169, 169, 169, 169,
- 169, 169, 170, 169, 169, 169, 169, 169, 169, 169, 169, 172, 169, 169, 169, 173,
- 169, 169, 169, 174, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 176,
- 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
- 178, 178, 178, 179, 180, 180, 180, 180, 180, 180, 180, 180, 180, 181, 180, 182,
- 183, 183, 184, 185, 186, 186, 187, 26, 188, 188, 189, 26, 190, 191, 192, 26,
- 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 194, 193, 195, 193, 195,
- 196, 197, 197, 198, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 199,
- 197, 197, 197, 197, 197, 200, 177, 177, 177, 177, 177, 177, 177, 177, 201, 26,
- 202, 202, 202, 203, 202, 204, 202, 204, 205, 202, 206, 206, 206, 207, 208, 26,
- 209, 209, 209, 209, 209, 210, 209, 209, 209, 211, 209, 212, 193, 193, 193, 193,
- 213, 213, 213, 214, 215, 215, 215, 215, 215, 215, 215, 216, 215, 215, 215, 217,
- 215, 218, 215, 218, 215, 219, 9, 9, 9, 220, 26, 26, 26, 26, 26, 26,
- 221, 221, 221, 221, 221, 221, 221, 221, 221, 222, 221, 221, 221, 221, 221, 223,
- 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227,
- 228, 228, 228, 228, 228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231,
- 18, 232, 164, 164, 164, 164, 164, 233, 224, 26, 234, 9, 235, 236, 237, 238,
- 2, 2, 2, 2, 239, 240, 2, 2, 2, 2, 2, 241, 242, 243, 2, 244,
- 2, 2, 2, 2, 2, 2, 2, 245, 9, 9, 9, 9, 9, 9, 9, 9,
- 14, 14, 246, 246, 14, 14, 14, 14, 246, 246, 14, 247, 14, 14, 14, 246,
- 14, 14, 14, 14, 14, 14, 248, 14, 248, 14, 249, 250, 14, 14, 251, 252,
- 0, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 255, 256,
- 0, 257, 2, 258, 0, 0, 0, 0, 259, 26, 9, 9, 9, 9, 260, 26,
- 0, 0, 0, 0, 261, 262, 4, 0, 0, 263, 0, 0, 2, 2, 2, 2,
- 2, 264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 48, 48, 48, 48, 71, 48, 48, 48, 48, 48, 48, 140, 140, 140, 140, 140,
+ 683, 140, 570, 570, 570, 570, 570, 570, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 140, 391, 391, 391, 391, 391, 391, 391, 684,
+ 391, 391, 391, 391, 391, 391, 391, 685, 0, 0, 0, 0, 1, 2, 1, 2,
+ 0, 0, 3, 3, 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 6, 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9,
+ 10, 11, 12, 11, 11, 11, 13, 11, 14, 14, 14, 14, 14, 14, 14, 14,
+ 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 16, 17, 18, 17, 17,
+ 19, 20, 21, 21, 22, 21, 23, 24, 25, 26, 27, 27, 28, 29, 27, 30,
+ 27, 27, 27, 27, 27, 31, 27, 27, 32, 33, 33, 33, 34, 27, 27, 27,
+ 35, 35, 35, 36, 37, 37, 37, 38, 39, 39, 40, 41, 42, 43, 44, 27,
+ 45, 46, 27, 27, 27, 27, 47, 27, 48, 48, 48, 48, 48, 49, 50, 48,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 109, 110, 111, 112, 109,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 122, 123, 122, 124, 125, 125,
+ 126, 127, 128, 129, 130, 131, 125, 125, 132, 132, 132, 132, 133, 132, 134, 135,
+ 132, 133, 132, 136, 136, 137, 125, 125, 138, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 139, 139, 140, 139, 139, 141, 142, 142, 142, 142, 142, 142, 142, 142,
+ 143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143,
+ 143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153,
+ 154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170,
+ 171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176,
+ 177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168,
+ 188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194, 8, 195, 125, 125, 125,
+ 196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201,
+ 202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211,
+ 4, 4, 212, 4, 4, 213, 214, 215, 4, 4, 4, 216, 8, 8, 8, 8,
+ 11, 217, 11, 11, 217, 218, 11, 219, 11, 11, 11, 220, 220, 221, 11, 222,
+ 223, 0, 0, 0, 0, 0, 224, 225, 226, 227, 0, 0, 228, 8, 8, 229,
+ 0, 0, 230, 231, 232, 0, 4, 4, 233, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 125, 235, 125, 0, 0,
+ 236, 236, 236, 236, 236, 236, 236, 236, 0, 0, 0, 0, 0, 0, 0, 237,
+ 0, 238, 0, 0, 0, 0, 0, 0, 239, 239, 239, 239, 239, 239, 4, 4,
+ 240, 240, 240, 240, 240, 240, 240, 241, 139, 139, 140, 242, 242, 242, 243, 244,
+ 143, 245, 246, 246, 246, 246, 14, 14, 0, 0, 0, 0, 0, 247, 125, 125,
+ 248, 249, 248, 248, 248, 248, 248, 250, 248, 248, 248, 248, 248, 248, 248, 248,
+ 248, 248, 248, 248, 248, 251, 125, 252, 253, 0, 254, 255, 256, 257, 257, 257,
+ 257, 258, 259, 260, 260, 260, 260, 261, 262, 263, 263, 264, 142, 142, 142, 142,
+ 265, 0, 263, 263, 0, 0, 266, 260, 142, 265, 0, 0, 0, 0, 142, 267,
+ 0, 0, 0, 0, 0, 260, 260, 268, 260, 260, 260, 260, 260, 269, 0, 0,
+ 248, 248, 248, 248, 0, 0, 0, 0, 270, 270, 270, 270, 270, 270, 270, 270,
+ 271, 270, 270, 270, 272, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274,
+ 274, 274, 275, 125, 14, 14, 14, 14, 14, 14, 276, 276, 276, 276, 276, 277,
+ 0, 0, 278, 4, 4, 4, 4, 4, 279, 4, 4, 4, 280, 281, 125, 282,
+ 283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290, 48, 48,
+ 291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299,
+ 300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308,
+ 309, 310, 246, 4, 4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314,
+ 142, 142, 315, 142, 316, 142, 142, 317, 125, 125, 125, 125, 125, 125, 125, 125,
+ 248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319, 125, 125,
+ 320, 321, 21, 322, 323, 27, 27, 27, 27, 27, 27, 27, 324, 325, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 326, 27, 27, 27, 27,
+ 27, 327, 27, 27, 328, 125, 125, 27, 8, 285, 329, 0, 0, 330, 331, 332,
+ 27, 27, 27, 27, 27, 27, 27, 333, 334, 0, 1, 2, 1, 2, 335, 259,
+ 260, 336, 142, 265, 337, 338, 339, 340, 341, 342, 343, 344, 345, 345, 125, 125,
+ 342, 342, 342, 342, 342, 342, 342, 346, 347, 0, 0, 348, 11, 11, 11, 11,
+ 349, 350, 351, 125, 125, 0, 0, 352, 353, 354, 355, 355, 355, 356, 357, 252,
+ 358, 358, 359, 360, 361, 362, 362, 363, 364, 365, 366, 366, 367, 368, 125, 125,
+ 369, 369, 369, 369, 369, 370, 370, 370, 371, 372, 373, 374, 374, 375, 374, 376,
+ 377, 377, 378, 379, 379, 379, 380, 381, 381, 382, 383, 384, 125, 125, 125, 125,
+ 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 386, 385, 387, 388, 125,
+ 389, 4, 4, 390, 125, 125, 125, 125, 391, 392, 392, 393, 394, 395, 396, 396,
+ 397, 398, 399, 125, 125, 125, 400, 401, 402, 403, 404, 405, 125, 125, 125, 125,
+ 406, 406, 407, 408, 407, 409, 407, 407, 410, 411, 412, 413, 414, 414, 415, 415,
+ 416, 416, 125, 125, 417, 417, 418, 419, 420, 420, 420, 421, 422, 423, 424, 425,
+ 426, 427, 428, 125, 125, 125, 125, 125, 429, 429, 429, 429, 430, 125, 125, 125,
+ 431, 431, 431, 432, 431, 431, 431, 433, 434, 434, 435, 436, 125, 125, 125, 125,
+ 125, 125, 125, 125, 125, 125, 27, 45, 437, 437, 438, 439, 125, 125, 125, 440,
+ 441, 441, 442, 443, 443, 444, 125, 445, 446, 125, 125, 447, 448, 125, 449, 450,
+ 451, 451, 451, 451, 452, 453, 451, 454, 455, 455, 455, 455, 456, 457, 458, 459,
+ 460, 460, 460, 461, 462, 463, 463, 464, 465, 465, 465, 465, 465, 465, 466, 467,
+ 468, 469, 468, 468, 470, 125, 125, 125, 471, 472, 473, 474, 474, 474, 475, 476,
+ 477, 478, 479, 480, 481, 482, 483, 484, 485, 485, 485, 485, 485, 486, 487, 125,
+ 488, 488, 488, 488, 489, 490, 125, 125, 491, 491, 491, 492, 491, 493, 125, 125,
+ 494, 494, 494, 494, 495, 496, 497, 125, 498, 498, 498, 499, 499, 125, 125, 125,
+ 500, 501, 502, 500, 503, 125, 125, 125, 504, 504, 504, 505, 125, 125, 125, 125,
+ 125, 125, 506, 506, 506, 506, 506, 507, 508, 509, 510, 511, 512, 513, 125, 125,
+ 125, 125, 514, 515, 515, 514, 516, 125, 517, 517, 517, 517, 518, 519, 519, 519,
+ 519, 519, 520, 154, 521, 521, 521, 522, 523, 125, 125, 125, 125, 125, 125, 125,
+ 524, 525, 525, 526, 527, 525, 528, 529, 529, 530, 531, 532, 125, 125, 125, 125,
+ 533, 534, 534, 535, 536, 537, 538, 539, 540, 541, 542, 125, 125, 125, 125, 125,
+ 125, 125, 125, 125, 125, 125, 543, 544, 545, 546, 545, 547, 545, 548, 125, 125,
+ 125, 125, 125, 549, 550, 550, 550, 551, 552, 552, 552, 552, 552, 552, 552, 552,
+ 552, 553, 125, 125, 125, 125, 125, 125, 552, 552, 552, 552, 552, 552, 554, 555,
+ 552, 552, 552, 552, 556, 125, 125, 125, 125, 557, 557, 557, 557, 557, 557, 558,
+ 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 560, 125, 125,
+ 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 562, 125, 125, 125,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 563, 564, 565, 566, 567,
+ 567, 567, 567, 568, 569, 570, 571, 572, 573, 573, 573, 573, 574, 575, 576, 577,
+ 573, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 578, 578, 578, 578,
+ 578, 579, 125, 125, 125, 125, 125, 125, 580, 580, 580, 580, 581, 580, 580, 580,
+ 582, 580, 125, 125, 125, 125, 583, 584, 585, 585, 585, 585, 585, 585, 585, 585,
+ 585, 585, 585, 585, 585, 585, 585, 586, 587, 587, 587, 587, 587, 587, 587, 587,
+ 587, 587, 587, 587, 587, 588, 125, 125, 589, 125, 125, 125, 125, 125, 125, 125,
+ 125, 125, 125, 125, 125, 125, 125, 590, 591, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 592, 593, 125, 594, 595, 596,
+ 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 597,
+ 598, 598, 598, 598, 598, 598, 599, 600, 601, 602, 266, 125, 125, 125, 125, 125,
+ 8, 8, 603, 8, 604, 0, 0, 0, 0, 0, 0, 0, 266, 125, 125, 125,
+ 0, 0, 0, 0, 0, 0, 0, 605, 0, 0, 606, 0, 0, 0, 607, 608,
+ 609, 0, 610, 0, 0, 0, 235, 125, 11, 11, 11, 11, 611, 125, 125, 125,
+ 125, 125, 125, 125, 0, 266, 0, 266, 0, 0, 0, 0, 0, 234, 0, 612,
+ 0, 0, 0, 0, 0, 224, 0, 0, 0, 613, 614, 615, 616, 0, 0, 0,
+ 617, 618, 0, 619, 620, 621, 0, 0, 0, 0, 622, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 623, 0, 0, 0, 624, 624, 624, 624, 624, 624, 624, 624,
+ 625, 626, 627, 125, 125, 125, 125, 125, 4, 628, 629, 125, 125, 125, 125, 125,
+ 630, 631, 632, 14, 14, 14, 633, 125, 634, 125, 125, 125, 125, 125, 125, 125,
+ 635, 635, 636, 637, 638, 125, 125, 125, 125, 639, 640, 125, 641, 641, 641, 642,
+ 125, 125, 125, 125, 125, 643, 643, 644, 125, 125, 125, 125, 125, 125, 645, 646,
+ 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 648, 649, 125, 125,
+ 650, 650, 650, 650, 651, 652, 125, 125, 125, 125, 125, 125, 125, 125, 125, 334,
+ 0, 0, 0, 653, 125, 125, 125, 125, 334, 0, 0, 247, 125, 125, 125, 125,
+ 654, 27, 655, 656, 657, 658, 659, 660, 661, 662, 663, 662, 125, 125, 125, 664,
+ 0, 0, 252, 0, 0, 0, 0, 0, 0, 266, 226, 334, 334, 334, 0, 605,
+ 0, 0, 247, 125, 125, 125, 665, 0, 666, 0, 0, 252, 612, 667, 605, 125,
+ 0, 0, 0, 0, 0, 668, 350, 350, 0, 0, 0, 0, 0, 0, 0, 669,
+ 0, 0, 0, 0, 0, 285, 252, 228, 252, 0, 0, 0, 670, 285, 0, 0,
+ 670, 0, 247, 667, 125, 125, 125, 125, 0, 0, 0, 0, 0, 266, 247, 350,
+ 612, 0, 0, 671, 672, 252, 612, 612, 0, 330, 0, 0, 235, 125, 125, 285,
+ 248, 248, 248, 248, 248, 248, 125, 125, 248, 248, 248, 319, 248, 248, 248, 248,
+ 248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 584, 248, 248, 248, 248, 248,
+ 248, 248, 248, 248, 248, 248, 673, 125, 248, 318, 125, 125, 125, 125, 125, 125,
+ 248, 248, 248, 248, 674, 248, 248, 248, 248, 248, 248, 125, 125, 125, 125, 125,
+ 675, 125, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 1, 2, 2, 2,
+ 2, 2, 3, 0, 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2,
+ 2, 2, 5, 0, 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 8, 8, 8, 8, 16, 8, 8, 8, 17, 18, 18, 18,
+ 19, 19, 19, 19, 19, 20, 19, 19, 21, 22, 22, 22, 22, 22, 22, 22,
+ 22, 23, 21, 22, 22, 22, 23, 21, 24, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 12, 12, 25, 25, 26, 27, 25, 28, 12, 12, 29, 30, 29, 31,
+ 29, 29, 32, 32, 29, 29, 29, 29, 31, 29, 33, 7, 7, 34, 29, 29,
+ 35, 29, 29, 29, 29, 29, 29, 30, 36, 36, 36, 37, 36, 36, 36, 36,
+ 36, 36, 38, 39, 40, 40, 40, 40, 41, 12, 12, 12, 42, 42, 42, 42,
+ 42, 42, 43, 44, 45, 45, 45, 45, 45, 45, 45, 46, 45, 45, 45, 47,
+ 48, 48, 48, 48, 48, 48, 48, 49, 36, 36, 38, 12, 29, 29, 29, 50,
+ 51, 12, 29, 29, 52, 29, 29, 29, 53, 53, 53, 53, 54, 55, 53, 53,
+ 53, 56, 53, 53, 57, 58, 57, 59, 59, 57, 57, 57, 57, 57, 60, 57,
+ 61, 62, 63, 57, 57, 59, 59, 64, 12, 65, 12, 66, 57, 62, 57, 57,
+ 57, 57, 57, 64, 67, 67, 68, 69, 70, 71, 71, 71, 71, 71, 72, 71,
+ 72, 73, 74, 72, 68, 69, 70, 74, 75, 12, 67, 76, 12, 77, 71, 71,
+ 71, 68, 12, 12, 78, 78, 79, 80, 80, 79, 79, 79, 79, 79, 81, 79,
+ 81, 78, 82, 79, 79, 80, 80, 82, 83, 12, 12, 12, 79, 84, 79, 79,
+ 82, 12, 78, 79, 85, 85, 86, 87, 87, 86, 86, 86, 86, 86, 88, 86,
+ 88, 85, 89, 86, 86, 87, 87, 89, 12, 85, 12, 90, 86, 91, 86, 86,
+ 86, 86, 12, 12, 92, 93, 94, 92, 95, 96, 97, 95, 98, 99, 94, 92,
+ 100, 100, 96, 92, 94, 92, 95, 96, 99, 98, 12, 12, 12, 92, 100, 100,
+ 100, 100, 94, 12, 101, 101, 101, 102, 102, 101, 101, 101, 101, 101, 102, 101,
+ 101, 101, 103, 101, 101, 102, 102, 103, 12, 104, 105, 106, 101, 107, 101, 101,
+ 12, 108, 101, 101, 109, 109, 109, 110, 110, 109, 109, 109, 109, 109, 110, 109,
+ 109, 111, 112, 109, 109, 110, 110, 112, 12, 113, 12, 113, 109, 114, 109, 109,
+ 111, 12, 12, 12, 115, 115, 115, 116, 116, 115, 115, 115, 115, 115, 115, 115,
+ 115, 116, 116, 115, 12, 115, 115, 115, 115, 117, 115, 115, 118, 118, 119, 119,
+ 119, 120, 121, 119, 119, 119, 119, 119, 122, 119, 119, 123, 119, 120, 124, 125,
+ 119, 126, 119, 119, 12, 121, 119, 119, 121, 127, 12, 12, 128, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 130, 131, 129, 129, 129, 12, 12, 12, 12, 12,
+ 132, 133, 134, 135, 135, 135, 135, 135, 135, 136, 135, 135, 135, 135, 135, 137,
+ 135, 138, 135, 134, 135, 135, 137, 135, 139, 139, 139, 139, 139, 139, 140, 139,
+ 139, 139, 139, 141, 140, 139, 139, 139, 139, 139, 139, 142, 139, 143, 144, 12,
+ 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 12, 148, 146, 146, 149, 146,
+ 150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 152, 153, 151, 154, 152, 153,
+ 152, 153, 151, 154, 152, 153, 151, 151, 151, 154, 151, 151, 151, 151, 154, 155,
+ 151, 151, 151, 156, 151, 151, 153, 12, 157, 157, 157, 157, 157, 158, 157, 158,
+ 159, 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 161, 162, 162, 162, 162,
+ 162, 162, 163, 164, 162, 162, 165, 12, 166, 166, 166, 166, 166, 167, 12, 168,
+ 169, 169, 169, 169, 169, 170, 12, 12, 171, 171, 171, 171, 171, 12, 12, 12,
+ 172, 172, 172, 173, 173, 12, 12, 12, 174, 174, 174, 174, 174, 174, 174, 175,
+ 174, 174, 175, 12, 176, 177, 178, 178, 178, 178, 179, 12, 178, 178, 178, 178,
+ 178, 178, 180, 12, 178, 178, 181, 12, 159, 182, 12, 12, 183, 183, 183, 183,
+ 183, 183, 183, 184, 183, 183, 183, 12, 185, 183, 183, 183, 186, 186, 186, 186,
+ 186, 186, 186, 187, 186, 188, 12, 12, 189, 189, 189, 189, 189, 189, 189, 12,
+ 189, 189, 190, 12, 189, 189, 191, 192, 193, 193, 193, 193, 193, 193, 193, 194,
+ 195, 195, 195, 195, 195, 195, 195, 196, 195, 195, 195, 197, 195, 195, 198, 12,
+ 195, 195, 195, 198, 7, 7, 7, 199, 200, 200, 200, 200, 200, 200, 200, 201,
+ 200, 200, 200, 202, 203, 203, 203, 203, 204, 204, 204, 204, 204, 12, 12, 204,
+ 205, 205, 205, 205, 205, 205, 206, 205, 205, 205, 207, 208, 209, 209, 209, 209,
+ 19, 19, 210, 12, 146, 146, 211, 212, 203, 203, 12, 12, 213, 7, 7, 7,
+ 214, 7, 215, 216, 0, 215, 217, 12, 2, 218, 219, 2, 2, 2, 2, 220,
+ 221, 218, 222, 2, 2, 2, 223, 2, 2, 2, 2, 224, 8, 225, 8, 225,
+ 8, 8, 226, 226, 8, 8, 8, 225, 8, 15, 8, 8, 8, 10, 8, 227,
+ 10, 15, 8, 14, 0, 0, 0, 228, 0, 229, 0, 0, 230, 0, 0, 231,
+ 0, 0, 0, 232, 2, 2, 2, 233, 234, 12, 12, 12, 235, 12, 12, 12,
+ 0, 236, 237, 0, 4, 0, 0, 0, 0, 0, 0, 4, 2, 2, 5, 12,
+ 0, 232, 12, 12, 0, 0, 232, 12, 238, 238, 238, 238, 0, 239, 0, 0,
+ 0, 240, 0, 0, 241, 241, 241, 241, 18, 18, 18, 18, 18, 12, 242, 18,
+ 243, 243, 243, 243, 243, 243, 12, 244, 245, 12, 12, 244, 151, 154, 12, 12,
+ 151, 154, 151, 154, 0, 0, 0, 246, 247, 247, 247, 247, 247, 247, 248, 247,
+ 247, 12, 12, 12, 247, 249, 12, 12, 0, 0, 0, 12, 0, 250, 0, 0,
+ 251, 247, 252, 253, 0, 0, 247, 0, 254, 255, 255, 255, 255, 255, 255, 255,
+ 255, 256, 257, 258, 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 261, 259,
+ 12, 262, 263, 263, 263, 263, 263, 263, 264, 150, 150, 150, 150, 150, 150, 265,
+ 0, 12, 12, 12, 150, 150, 150, 266, 260, 260, 260, 261, 260, 260, 0, 0,
+ 267, 267, 267, 267, 267, 267, 267, 268, 267, 269, 12, 12, 270, 270, 270, 270,
+ 271, 271, 271, 271, 271, 271, 271, 12, 272, 272, 272, 272, 272, 272, 12, 12,
+ 237, 2, 2, 2, 2, 2, 231, 2, 2, 2, 273, 12, 274, 275, 276, 12,
+ 277, 2, 2, 2, 278, 278, 278, 278, 278, 278, 278, 279, 0, 0, 246, 12,
+ 280, 280, 280, 280, 280, 280, 12, 12, 281, 281, 281, 281, 281, 282, 12, 283,
+ 281, 281, 282, 12, 284, 284, 284, 284, 284, 284, 284, 285, 286, 286, 286, 286,
+ 286, 12, 12, 287, 150, 150, 150, 288, 289, 289, 289, 289, 289, 289, 289, 290,
+ 289, 289, 291, 292, 145, 145, 145, 293, 294, 294, 294, 294, 294, 295, 12, 12,
+ 294, 294, 294, 296, 294, 294, 296, 294, 297, 297, 297, 297, 298, 12, 12, 12,
+ 12, 12, 299, 297, 300, 300, 300, 300, 300, 301, 12, 12, 155, 154, 155, 154,
+ 155, 154, 12, 12, 2, 2, 3, 2, 2, 302, 303, 12, 300, 300, 300, 304,
+ 300, 300, 304, 12, 150, 12, 12, 12, 150, 265, 305, 150, 150, 150, 150, 12,
+ 247, 247, 247, 249, 247, 247, 249, 12, 2, 273, 12, 12, 306, 22, 12, 24,
+ 25, 26, 25, 307, 308, 309, 25, 25, 50, 12, 12, 12, 310, 29, 29, 29,
+ 29, 29, 29, 311, 312, 29, 29, 29, 29, 29, 12, 310, 7, 7, 7, 313,
+ 232, 0, 0, 0, 0, 232, 0, 12, 29, 314, 29, 29, 29, 29, 29, 315,
+ 316, 0, 0, 0, 0, 317, 260, 260, 260, 260, 260, 318, 319, 150, 319, 150,
+ 319, 150, 319, 288, 0, 232, 0, 232, 12, 12, 316, 246, 320, 320, 320, 321,
+ 320, 320, 320, 320, 320, 322, 320, 320, 320, 320, 322, 323, 320, 320, 320, 324,
+ 320, 320, 322, 12, 232, 131, 0, 0, 0, 131, 0, 0, 8, 8, 8, 14,
+ 0, 0, 0, 234, 325, 12, 12, 12, 0, 0, 0, 326, 327, 327, 327, 327,
+ 327, 327, 327, 328, 329, 329, 329, 329, 330, 12, 12, 12, 215, 0, 0, 0,
+ 331, 331, 331, 331, 331, 12, 12, 332, 333, 333, 333, 333, 333, 333, 334, 12,
+ 335, 335, 335, 335, 335, 335, 336, 12, 337, 337, 337, 337, 337, 337, 337, 338,
+ 339, 339, 339, 339, 339, 12, 339, 339, 339, 340, 12, 12, 341, 341, 341, 341,
+ 342, 342, 342, 342, 343, 343, 343, 343, 343, 343, 343, 344, 343, 343, 344, 12,
+ 345, 345, 345, 345, 345, 12, 345, 345, 345, 345, 345, 12, 346, 346, 346, 346,
+ 346, 346, 12, 12, 347, 347, 347, 347, 347, 12, 12, 348, 349, 349, 350, 349,
+ 350, 351, 349, 349, 351, 349, 349, 349, 351, 349, 351, 352, 353, 353, 353, 353,
+ 353, 354, 12, 12, 353, 355, 12, 12, 353, 353, 12, 12, 2, 274, 2, 2,
+ 356, 2, 273, 12, 357, 358, 359, 357, 357, 357, 357, 357, 357, 360, 361, 362,
+ 363, 363, 363, 363, 363, 364, 363, 363, 365, 365, 365, 365, 366, 366, 366, 366,
+ 366, 366, 366, 367, 12, 368, 366, 366, 369, 369, 369, 369, 370, 371, 372, 369,
+ 373, 373, 373, 373, 373, 373, 373, 374, 375, 375, 375, 375, 375, 375, 376, 377,
+ 378, 378, 378, 378, 379, 379, 379, 379, 379, 379, 12, 379, 380, 379, 379, 379,
+ 381, 382, 12, 381, 381, 383, 383, 381, 381, 381, 381, 381, 381, 384, 385, 386,
+ 381, 381, 387, 12, 388, 388, 388, 388, 389, 389, 389, 389, 390, 390, 390, 390,
+ 390, 391, 392, 390, 390, 391, 12, 12, 393, 393, 393, 393, 393, 394, 395, 393,
+ 396, 396, 396, 396, 396, 397, 396, 396, 398, 398, 398, 398, 399, 12, 398, 398,
+ 400, 400, 400, 400, 401, 12, 402, 403, 12, 12, 402, 400, 404, 404, 404, 404,
+ 404, 404, 405, 12, 406, 406, 406, 406, 407, 12, 12, 12, 407, 12, 408, 406,
+ 409, 409, 409, 409, 409, 409, 12, 12, 409, 409, 410, 12, 411, 411, 411, 411,
+ 411, 411, 412, 413, 413, 12, 12, 12, 12, 12, 12, 414, 415, 415, 415, 415,
+ 415, 415, 12, 12, 416, 416, 416, 416, 416, 416, 417, 12, 418, 418, 418, 418,
+ 418, 418, 419, 12, 420, 420, 420, 420, 420, 420, 420, 12, 421, 421, 421, 421,
+ 421, 422, 12, 12, 423, 423, 423, 423, 423, 423, 423, 424, 425, 423, 423, 423,
+ 423, 424, 12, 426, 427, 427, 427, 427, 428, 12, 12, 429, 430, 430, 430, 430,
+ 430, 430, 431, 12, 430, 430, 432, 12, 433, 433, 433, 433, 433, 434, 433, 433,
+ 433, 433, 12, 12, 435, 435, 435, 435, 435, 436, 12, 12, 437, 437, 437, 437,
+ 118, 119, 119, 119, 119, 127, 12, 12, 438, 438, 438, 438, 439, 438, 438, 438,
+ 440, 12, 12, 12, 441, 442, 443, 444, 441, 441, 441, 444, 441, 441, 445, 12,
+ 446, 446, 446, 446, 446, 446, 447, 12, 446, 446, 448, 12, 449, 450, 449, 451,
+ 451, 449, 449, 449, 449, 449, 452, 449, 452, 450, 453, 449, 449, 451, 451, 454,
+ 455, 456, 12, 450, 449, 457, 449, 455, 449, 455, 12, 12, 458, 458, 458, 458,
+ 458, 458, 458, 459, 460, 12, 12, 12, 461, 461, 461, 461, 461, 461, 12, 12,
+ 461, 461, 462, 12, 463, 463, 463, 463, 463, 464, 463, 463, 463, 463, 463, 464,
+ 465, 465, 465, 465, 465, 466, 12, 12, 465, 465, 467, 12, 178, 178, 178, 180,
+ 468, 468, 468, 468, 468, 468, 469, 12, 470, 470, 470, 470, 470, 470, 471, 472,
+ 470, 470, 470, 12, 470, 471, 12, 12, 473, 473, 473, 473, 473, 473, 473, 12,
+ 474, 474, 474, 474, 475, 12, 12, 476, 477, 478, 479, 477, 477, 480, 477, 477,
+ 477, 477, 477, 477, 477, 481, 482, 477, 477, 478, 12, 12, 477, 477, 483, 12,
+ 484, 484, 485, 484, 484, 484, 484, 484, 484, 486, 12, 12, 487, 487, 487, 487,
+ 487, 487, 12, 12, 488, 488, 488, 488, 489, 12, 12, 12, 490, 490, 490, 490,
+ 490, 490, 491, 12, 53, 53, 492, 12, 493, 493, 494, 493, 493, 493, 493, 493,
+ 493, 495, 493, 493, 493, 496, 12, 12, 493, 493, 493, 497, 498, 498, 498, 498,
+ 499, 498, 498, 498, 498, 498, 500, 498, 498, 501, 12, 12, 502, 503, 504, 502,
+ 502, 502, 502, 502, 502, 503, 505, 504, 502, 502, 12, 12, 502, 502, 506, 12,
+ 507, 508, 509, 507, 507, 507, 507, 507, 507, 507, 507, 510, 508, 507, 511, 12,
+ 507, 507, 512, 12, 513, 513, 513, 513, 513, 513, 514, 12, 515, 515, 515, 515,
+ 516, 515, 515, 515, 515, 515, 517, 518, 515, 515, 519, 12, 520, 12, 12, 12,
+ 100, 100, 100, 100, 96, 12, 12, 98, 521, 521, 521, 521, 521, 521, 522, 12,
+ 521, 521, 521, 523, 521, 524, 12, 12, 521, 12, 12, 12, 525, 525, 525, 525,
+ 526, 12, 12, 12, 527, 527, 527, 527, 527, 528, 12, 12, 529, 529, 529, 529,
+ 529, 530, 12, 12, 272, 272, 531, 12, 532, 532, 532, 532, 532, 532, 532, 533,
+ 532, 532, 534, 535, 536, 536, 536, 536, 536, 536, 536, 537, 536, 536, 538, 12,
+ 539, 539, 539, 539, 539, 539, 539, 540, 539, 540, 12, 12, 541, 541, 541, 541,
+ 541, 542, 12, 12, 541, 541, 543, 541, 543, 541, 541, 541, 541, 541, 12, 544,
+ 545, 545, 545, 545, 545, 545, 546, 12, 547, 547, 547, 547, 547, 547, 548, 549,
+ 547, 547, 12, 549, 550, 551, 12, 12, 249, 12, 12, 12, 552, 552, 552, 552,
+ 552, 552, 12, 12, 553, 553, 553, 553, 553, 554, 12, 12, 552, 552, 555, 12,
+ 260, 556, 260, 557, 558, 255, 255, 255, 559, 12, 12, 12, 560, 12, 12, 12,
+ 256, 561, 12, 12, 12, 260, 12, 12, 562, 562, 562, 562, 562, 562, 562, 12,
+ 563, 563, 563, 563, 563, 563, 564, 12, 563, 563, 563, 565, 563, 563, 565, 12,
+ 563, 563, 566, 563, 7, 7, 7, 567, 7, 199, 12, 12, 0, 246, 12, 12,
+ 0, 232, 316, 0, 0, 568, 228, 0, 0, 0, 568, 7, 213, 569, 7, 0,
+ 0, 0, 570, 228, 8, 225, 12, 12, 0, 0, 234, 12, 0, 0, 0, 229,
+ 571, 572, 316, 229, 0, 0, 240, 316, 0, 316, 0, 0, 0, 240, 232, 316,
+ 0, 229, 0, 229, 0, 0, 240, 232, 0, 573, 239, 0, 229, 0, 0, 0,
+ 0, 246, 0, 0, 0, 0, 0, 239, 574, 574, 574, 574, 574, 574, 574, 12,
+ 12, 12, 575, 574, 576, 574, 574, 574, 2, 2, 2, 273, 12, 275, 273, 12,
+ 241, 577, 241, 241, 241, 241, 578, 241, 579, 580, 577, 12, 19, 19, 19, 581,
+ 12, 12, 12, 582, 583, 583, 583, 583, 583, 583, 583, 584, 583, 583, 583, 585,
+ 583, 583, 585, 586, 587, 587, 587, 587, 587, 587, 587, 588, 589, 589, 589, 589,
+ 589, 589, 590, 591, 592, 592, 592, 592, 592, 592, 593, 12, 151, 154, 151, 594,
+ 151, 151, 151, 154, 595, 595, 595, 595, 595, 596, 595, 595, 595, 597, 12, 12,
+ 598, 598, 598, 598, 598, 598, 598, 12, 598, 598, 599, 600, 0, 234, 12, 12,
+ 29, 414, 29, 29, 601, 602, 414, 29, 50, 29, 603, 12, 604, 310, 603, 414,
+ 601, 602, 603, 603, 601, 602, 50, 29, 50, 29, 414, 605, 29, 29, 606, 29,
+ 29, 29, 29, 12, 414, 414, 606, 29, 51, 12, 12, 12, 12, 239, 0, 0,
+ 607, 12, 12, 12, 246, 12, 12, 12, 0, 0, 12, 0, 0, 232, 131, 0,
+ 0, 0, 12, 12, 0, 0, 0, 240, 0, 246, 12, 239, 608, 12, 12, 12,
+ 247, 247, 609, 12, 610, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 939, 940, 941, 942, 946, 948, 0, 962,
+ 969, 970, 971, 976,1001,1002,1003,1008, 0,1033,1040,1041,1042,1043,1047, 0,
+ 0,1080,1081,1082,1086,1110, 0, 0,1124,1125,1126,1127,1131,1133, 0,1147,
+ 1154,1155,1156,1161,1187,1188,1189,1193, 0,1219,1226,1227,1228,1229,1233, 0,
+ 0,1267,1268,1269,1273,1298, 0,1303, 943,1128, 944,1129, 954,1139, 958,1143,
+ 959,1144, 960,1145, 961,1146, 964,1149, 0, 0, 973,1158, 974,1159, 975,1160,
+ 983,1168, 978,1163, 988,1173, 990,1175, 991,1176, 993,1178, 994,1179, 0, 0,
+ 1004,1190,1005,1191,1006,1192,1014,1199,1007, 0, 0, 0,1016,1201,1020,1206,
+ 0,1022,1208,1025,1211,1023,1209, 0, 0, 0, 0,1032,1218,1037,1223,1035,
+ 1221, 0, 0, 0,1044,1230,1045,1231,1049,1235, 0, 0,1058,1244,1064,1250,
+ 1060,1246,1066,1252,1067,1253,1072,1258,1069,1255,1077,1264,1074,1261, 0, 0,
+ 1083,1270,1084,1271,1085,1272,1088,1275,1089,1276,1096,1283,1103,1290,1111,1299,
+ 1115,1118,1307,1120,1309,1121,1310, 0,1053,1239, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,1093,1280, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 257, 26, 26, 26, 0, 265, 26, 26, 0, 0, 0, 0,
- 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 0,
- 0, 0, 268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 2, 2, 2, 2,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 270, 271,
- 164, 164, 164, 164, 165, 166, 272, 272, 272, 272, 272, 272, 272, 273, 274, 273,
- 169, 169, 171, 26, 171, 171, 171, 171, 171, 171, 171, 171, 18, 18, 18, 18,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 26, 26, 26, 26,
- 276, 276, 276, 277, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 278, 26,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 279, 26, 26, 26, 0, 280,
- 281, 0, 0, 0, 282, 283, 0, 284, 285, 286, 286, 286, 286, 286, 286, 286,
- 286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291,
- 292, 293, 293, 293, 293, 293, 294, 168, 168, 168, 168, 168, 168, 168, 168, 168,
- 168, 295, 0, 0, 293, 293, 293, 293, 0, 0, 0, 0, 280, 26, 290, 290,
- 168, 168, 168, 295, 0, 0, 0, 0, 0, 0, 0, 0, 168, 168, 168, 296,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 290, 290, 290, 290, 297,
- 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 0, 0, 0, 0, 0,
- 276, 276, 276, 276, 276, 276, 276, 276, 0, 0, 0, 0, 0, 0, 0, 0,
- 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298,
- 298, 299, 298, 298, 298, 298, 298, 298, 300, 26, 301, 301, 301, 301, 301, 301,
- 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
- 302, 302, 302, 302, 302, 303, 26, 26, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 26,
- 0, 0, 0, 0, 305, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 306, 2, 2, 2, 2, 2, 2, 2, 307, 308, 309, 26, 26, 310, 2,
- 311, 311, 311, 311, 311, 312, 0, 313, 314, 314, 314, 314, 314, 314, 314, 26,
- 315, 315, 315, 315, 315, 315, 315, 315, 316, 317, 315, 318, 53, 53, 53, 53,
- 319, 319, 319, 319, 319, 320, 321, 321, 321, 321, 322, 323, 168, 168, 168, 324,
- 325, 325, 325, 325, 325, 325, 325, 325, 325, 326, 325, 327, 163, 163, 163, 328,
- 329, 329, 329, 329, 329, 329, 330, 26, 329, 331, 329, 332, 163, 163, 163, 163,
- 333, 333, 333, 333, 333, 333, 333, 333, 334, 26, 26, 335, 336, 336, 337, 26,
- 338, 338, 338, 26, 171, 171, 2, 2, 2, 2, 2, 339, 340, 341, 175, 175,
- 175, 175, 175, 175, 175, 175, 175, 175, 336, 336, 336, 336, 336, 342, 336, 343,
- 168, 168, 168, 168, 344, 26, 168, 168, 295, 345, 168, 168, 168, 168, 168, 344,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 279, 276, 276,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 346, 26, 26, 26, 26,
- 347, 26, 348, 349, 25, 25, 350, 351, 352, 25, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 353, 26, 354, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 355, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 356, 31, 31, 31, 31, 31, 31, 357, 26, 26, 26, 26, 31, 31,
- 9, 9, 0, 313, 9, 358, 0, 0, 0, 0, 359, 0, 257, 280, 360, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 361,
- 362, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, 363, 290, 289, 290,
- 290, 290, 290, 364, 168, 168, 168, 295, 365, 365, 365, 366, 257, 257, 26, 367,
- 368, 369, 368, 368, 370, 368, 368, 371, 368, 372, 368, 372, 26, 26, 26, 26,
- 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 373,
- 374, 0, 0, 0, 0, 0, 375, 0, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 252, 0, 376, 377, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 378,
- 379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382, 26, 383, 0, 0, 280,
- 384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390,
- 391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395, 26, 26, 26, 26, 26,
- 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, 397,
- 398, 398, 398, 399, 398, 400, 401, 401, 401, 401, 402, 401, 401, 401, 401, 402,
- 403, 403, 403, 403, 403, 26, 404, 404, 404, 404, 404, 404, 405, 406, 407, 408,
- 407, 408, 409, 407, 410, 407, 410, 411, 26, 26, 26, 26, 26, 26, 26, 26,
- 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412,
- 412, 412, 412, 412, 412, 412, 413, 26, 412, 412, 414, 26, 412, 26, 26, 26,
- 415, 2, 2, 2, 2, 2, 416, 307, 26, 26, 26, 26, 26, 26, 26, 26,
- 417, 418, 419, 419, 419, 419, 420, 421, 422, 422, 423, 422, 424, 424, 424, 424,
- 425, 425, 425, 426, 427, 425, 26, 26, 26, 26, 26, 26, 428, 428, 429, 430,
- 431, 431, 431, 432, 433, 433, 433, 434, 26, 26, 26, 26, 26, 26, 26, 26,
- 435, 435, 435, 435, 436, 436, 436, 437, 436, 436, 438, 436, 436, 436, 436, 436,
- 439, 440, 441, 442, 443, 443, 444, 445, 443, 446, 443, 446, 447, 447, 447, 447,
- 448, 448, 448, 448, 26, 26, 26, 26, 449, 449, 449, 449, 450, 451, 450, 26,
- 452, 452, 452, 452, 452, 452, 453, 454, 455, 455, 456, 455, 457, 457, 458, 457,
- 459, 459, 460, 461, 26, 462, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 463, 463, 463, 463, 463, 463, 463, 463, 463, 464, 26, 26, 26, 26, 26, 26,
- 465, 465, 465, 465, 465, 465, 466, 26, 465, 465, 465, 465, 465, 465, 466, 467,
- 468, 468, 468, 468, 468, 26, 468, 469, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 50,
- 470, 470, 470, 470, 470, 471, 472, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 473, 473, 473, 473, 473, 26, 474, 474, 474, 474, 474, 475, 26, 26, 476, 476,
- 476, 477, 26, 26, 26, 26, 478, 478, 478, 479, 26, 26, 480, 480, 481, 26,
- 482, 482, 482, 482, 482, 482, 482, 482, 482, 483, 484, 482, 482, 482, 483, 485,
- 486, 486, 486, 486, 486, 486, 486, 486, 487, 488, 489, 489, 489, 490, 489, 491,
- 492, 492, 492, 492, 492, 492, 493, 492, 492, 26, 494, 494, 494, 494, 495, 26,
- 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 497, 137, 498, 26,
- 499, 499, 500, 499, 499, 499, 499, 501, 26, 26, 26, 26, 26, 26, 26, 26,
- 502, 503, 504, 505, 504, 506, 507, 507, 507, 507, 507, 507, 507, 508, 507, 509,
- 510, 511, 512, 513, 513, 514, 515, 516, 511, 517, 518, 519, 520, 521, 521, 26,
- 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 523, 524, 26, 26, 26,
- 525, 525, 525, 525, 525, 525, 525, 525, 525, 26, 525, 526, 26, 26, 26, 26,
- 527, 527, 527, 527, 527, 527, 528, 527, 527, 527, 527, 528, 26, 26, 26, 26,
- 529, 529, 529, 529, 529, 529, 529, 529, 530, 26, 529, 531, 197, 532, 26, 26,
- 533, 533, 533, 533, 533, 533, 533, 534, 533, 534, 26, 26, 26, 26, 26, 26,
- 535, 535, 535, 536, 535, 537, 535, 535, 538, 26, 26, 26, 26, 26, 26, 26,
- 539, 539, 539, 539, 539, 539, 539, 540, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 542, 543,
- 544, 545, 546, 547, 547, 547, 548, 549, 544, 26, 547, 550, 26, 26, 26, 26,
- 26, 26, 26, 26, 551, 552, 551, 551, 551, 551, 551, 552, 553, 26, 26, 26,
- 554, 554, 554, 554, 554, 554, 554, 554, 554, 26, 555, 555, 555, 555, 555, 555,
- 555, 555, 555, 555, 556, 26, 177, 177, 557, 557, 557, 557, 557, 557, 557, 558,
- 559, 560, 559, 559, 559, 559, 561, 559, 562, 26, 559, 559, 559, 563, 564, 564,
- 564, 564, 565, 564, 564, 566, 567, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 568, 569, 570, 570, 570, 570, 568, 571, 570, 26, 570, 572, 573, 574, 575, 575,
- 575, 576, 577, 578, 575, 579, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 580, 580, 580, 581,
- 26, 26, 26, 26, 26, 26, 582, 26, 108, 108, 108, 108, 108, 108, 583, 584,
- 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585,
- 585, 585, 585, 586, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 587, 588, 26,
- 585, 585, 585, 585, 585, 585, 585, 585, 589, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 591, 26,
- 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592,
- 592, 592, 592, 592, 592, 593, 592, 594, 26, 26, 26, 26, 26, 26, 26, 26,
- 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595,
- 595, 595, 595, 595, 595, 595, 595, 595, 596, 26, 26, 26, 26, 26, 26, 26,
- 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304,
- 304, 304, 304, 304, 304, 304, 304, 597, 598, 598, 598, 599, 598, 600, 601, 601,
- 601, 601, 601, 601, 601, 601, 601, 602, 601, 603, 604, 604, 604, 605, 605, 26,
- 606, 606, 606, 606, 606, 606, 606, 606, 607, 26, 606, 608, 608, 606, 606, 609,
- 606, 606, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 610, 610, 610, 610, 610, 610, 610, 610,
- 610, 610, 610, 611, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 612, 612, 612, 612, 612, 612, 612, 612, 612, 613, 612, 612, 612, 612, 612, 612,
- 612, 614, 612, 612, 26, 26, 26, 26, 26, 26, 26, 26, 615, 26, 346, 26,
- 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616,
- 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 26,
- 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617,
- 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 618, 26, 26, 26, 26, 26,
- 616, 619, 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, 620, 621,
- 622, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
- 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
- 286, 286, 286, 286, 623, 26, 26, 26, 26, 26, 624, 26, 625, 26, 626, 626,
- 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626,
- 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 627,
- 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 629, 628, 630,
- 628, 631, 628, 632, 280, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 9, 9, 9, 9, 9, 633, 9, 9, 220, 26, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 280, 26, 26, 26, 26, 26, 26, 26,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 26,
- 0, 0, 0, 0, 257, 362, 0, 0, 0, 0, 0, 0, 634, 635, 0, 636,
- 637, 638, 0, 0, 0, 639, 0, 0, 0, 0, 0, 0, 0, 265, 26, 26,
- 14, 14, 14, 14, 14, 14, 14, 14, 246, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 280, 26,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 257, 26, 0, 0, 0, 259,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0,
- 0, 0, 0, 254, 640, 641, 0, 642, 643, 0, 0, 0, 0, 0, 0, 0,
- 268, 644, 254, 254, 0, 0, 0, 645, 646, 647, 648, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 0, 0, 0, 0, 0, 0,
- 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649,
- 649, 650, 26, 651, 652, 649, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 2, 2, 2, 347, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 653, 269, 269, 654, 655, 656, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 657, 657, 657, 657, 657, 658, 657, 659, 657, 660, 26, 26, 26, 26, 26, 26,
- 26, 26, 661, 661, 661, 662, 26, 26, 663, 663, 663, 663, 663, 663, 663, 664,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 171, 665, 169, 171,
- 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
- 666, 666, 666, 666, 666, 666, 666, 666, 667, 666, 668, 26, 26, 26, 26, 26,
- 669, 669, 669, 669, 669, 669, 669, 669, 669, 670, 669, 671, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 362, 0,
- 0, 0, 0, 0, 0, 0, 376, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 362, 0, 0, 0, 0, 0, 0, 275, 26, 26, 26, 26, 26, 26, 26, 26,
- 672, 31, 31, 31, 673, 674, 675, 676, 677, 678, 673, 679, 673, 675, 675, 680,
- 31, 681, 31, 682, 683, 681, 31, 682, 26, 26, 26, 26, 26, 26, 51, 26,
- 0, 0, 0, 0, 0, 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 280, 26, 0, 257, 362, 0, 362, 0, 362, 0, 0, 0, 275, 26,
- 0, 0, 0, 0, 0, 275, 26, 26, 26, 26, 26, 26, 684, 0, 0, 0,
- 685, 26, 0, 0, 0, 0, 0, 280, 0, 259, 313, 26, 275, 26, 26, 26,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 686, 0, 376, 0, 376,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280, 26,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259, 0, 280, 259, 26,
- 0, 280, 0, 0, 0, 0, 0, 0, 0, 26, 0, 313, 0, 0, 0, 0,
- 0, 26, 0, 0, 0, 275, 313, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280, 26, 0, 275, 376, 376,
- 257, 26, 0, 0, 0, 376, 0, 265, 275, 26, 0, 313, 0, 26, 257, 26,
- 0, 0, 359, 0, 0, 0, 0, 0, 0, 265, 26, 26, 26, 26, 0, 313,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 26, 26, 26, 26,
- 276, 276, 276, 276, 276, 276, 276, 687, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 279, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 276, 346, 26, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 687, 26, 26, 26,
- 276, 276, 276, 279, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 688, 26, 26, 26, 26, 26, 26,
- 689, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
+ 0, 0, 0, 0, 0, 949,1134,1010,1195,1050,1236,1090,1277,1341,1368,1340,
+ 1367,1342,1369,1339,1366, 0,1320,1347,1418,1419,1323,1350, 0, 0, 992,1177,
+ 1018,1204,1055,1241,1416,1417,1415,1424,1202, 0, 0, 0, 987,1172, 0, 0,
+ 1031,1217,1321,1348,1322,1349,1338,1365, 950,1135, 951,1136, 979,1164, 980,1165,
+ 1011,1196,1012,1197,1051,1237,1052,1238,1061,1247,1062,1248,1091,1278,1092,1279,
+ 1071,1257,1076,1263, 0, 0, 997,1182, 0, 0, 0, 0, 0, 0, 945,1130,
+ 982,1167,1337,1364,1335,1362,1046,1232,1422,1423,1113,1301, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 10,1425, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,1314,1427, 5,
+ 1434,1438,1443, 0,1450, 0,1455,1461,1514, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1446,1458,1468,1476,1480,1486,1517, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1489,1503,1494,1500,1508, 0, 0, 0, 0,1520,1521, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1526,1528, 0,1525, 0, 0, 0,1522,
+ 0, 0, 0, 0,1536,1532,1539, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1556, 0, 0, 0, 0, 0, 0,1548,1550, 0,1547, 0, 0, 0,1567,
+ 0, 0, 0, 0,1558,1554,1561, 0, 0, 0, 0, 0, 0, 0,1568,1569,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1529,1551, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1523,1545,1524,1546, 0, 0,1527,1549,
+ 0, 0,1570,1571,1530,1552,1531,1553, 0, 0,1533,1555,1535,1557,1537,1559,
+ 0, 0,1572,1573,1544,1566,1538,1560,1540,1562,1541,1563,1542,1564, 0, 0,
+ 1543,1565, 0, 0, 0, 0, 0, 0, 0, 0,1606,1607,1609,1608,1610, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1613, 0,1611, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1612, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1620, 0, 0, 0, 0, 0, 0, 0,1623, 0, 0,1624, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1614,1615,1616,1617,1618,1619,1621,1622, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1628,1629, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1625,1626, 0,1627, 0, 0, 0,1634, 0, 0,1635, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1630,1631,1632, 0, 0,1633, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1639, 0, 0,1638,1640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1636,1637, 0, 0, 0, 0, 0, 0,1641, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1642,1644,1643, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1645, 0, 0, 0, 0, 0, 0, 0,1646, 0, 0, 0, 0, 0, 0,1648,
+ 1649, 0,1647,1650, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1651,1653,1652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1654, 0,1655,1657,1656, 0, 0, 0, 0,1659, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1660, 0, 0, 0, 0,1661, 0, 0, 0, 0,1662,
+ 0, 0, 0, 0,1663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1658, 0, 0, 0, 0, 0, 0, 0, 0, 0,1664, 0,1665,1673, 0,
+ 1674, 0, 0, 0, 0, 0, 0, 0, 0,1666, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1668, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1669, 0, 0, 0, 0,1670, 0, 0, 0, 0,1671,
+ 0, 0, 0, 0,1672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1675, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1676, 0,
+ 1677, 0,1678, 0,1679, 0,1680, 0, 0, 0,1681, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1682, 0,1683, 0, 0,1684,1685, 0,1686, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 953,1138, 955,1140, 956,1141, 957,1142,
+ 1324,1351, 963,1148, 965,1150, 968,1153, 966,1151, 967,1152,1378,1380,1379,1381,
+ 984,1169, 985,1170,1420,1421, 986,1171, 989,1174, 995,1180, 998,1183, 996,1181,
+ 999,1184,1000,1185,1015,1200,1329,1356,1017,1203,1019,1205,1021,1207,1024,1210,
+ 1687,1688,1027,1213,1026,1212,1028,1214,1029,1215,1030,1216,1034,1220,1036,1222,
+ 1039,1225,1038,1224,1334,1361,1336,1363,1382,1384,1383,1385,1056,1242,1057,1243,
+ 1059,1245,1063,1249,1689,1690,1065,1251,1068,1254,1070,1256,1386,1387,1388,1389,
+ 1691,1692,1073,1259,1075,1262,1079,1266,1078,1265,1095,1282,1098,1285,1097,1284,
+ 1390,1391,1392,1393,1099,1286,1100,1287,1101,1288,1102,1289,1105,1292,1104,1291,
+ 1106,1294,1107,1295,1108,1296,1114,1302,1119,1308,1122,1311,1123,1312,1186,1260,
+ 1293,1305, 0,1394, 0, 0, 0, 0, 952,1137, 947,1132,1317,1344,1316,1343,
+ 1319,1346,1318,1345,1693,1695,1371,1375,1370,1374,1373,1377,1372,1376,1694,1696,
+ 981,1166, 977,1162, 972,1157,1326,1353,1325,1352,1328,1355,1327,1354,1697,1698,
+ 1009,1194,1013,1198,1054,1240,1048,1234,1331,1358,1330,1357,1333,1360,1332,1359,
+ 1699,1700,1396,1401,1395,1400,1398,1403,1397,1402,1399,1404,1094,1281,1087,1274,
+ 1406,1411,1405,1410,1408,1413,1407,1412,1409,1414,1109,1297,1117,1306,1116,1304,
+ 1112,1300, 0, 0, 0, 0, 0, 0,1471,1472,1701,1705,1702,1706,1703,1707,
+ 1430,1431,1715,1719,1716,1720,1717,1721,1477,1478,1729,1731,1730,1732, 0, 0,
+ 1435,1436,1733,1735,1734,1736, 0, 0,1481,1482,1737,1741,1738,1742,1739,1743,
+ 1439,1440,1751,1755,1752,1756,1753,1757,1490,1491,1765,1768,1766,1769,1767,1770,
+ 1447,1448,1771,1774,1772,1775,1773,1776,1495,1496,1777,1779,1778,1780, 0, 0,
+ 1451,1452,1781,1783,1782,1784, 0, 0,1504,1505,1785,1788,1786,1789,1787,1790,
+ 0,1459, 0,1791, 0,1792, 0,1793,1509,1510,1794,1798,1795,1799,1796,1800,
+ 1462,1463,1808,1812,1809,1813,1810,1814,1467, 21,1475, 22,1479, 23,1485, 24,
+ 1493, 27,1499, 28,1507, 29, 0, 0,1704,1708,1709,1710,1711,1712,1713,1714,
+ 1718,1722,1723,1724,1725,1726,1727,1728,1740,1744,1745,1746,1747,1748,1749,1750,
+ 1754,1758,1759,1760,1761,1762,1763,1764,1797,1801,1802,1803,1804,1805,1806,1807,
+ 1811,1815,1816,1817,1818,1819,1820,1821,1470,1469,1822,1474,1465, 0,1473,1825,
+ 1429,1428,1426, 12,1432, 0, 26, 0, 0,1315,1823,1484,1466, 0,1483,1829,
+ 1433, 13,1437, 14,1441,1826,1827,1828,1488,1487,1513, 19, 0, 0,1492,1515,
+ 1445,1444,1442, 15, 0,1831,1832,1833,1502,1501,1516, 25,1497,1498,1506,1518,
+ 1457,1456,1454, 17,1453,1313, 11, 3, 0, 0,1824,1512,1519, 0,1511,1830,
+ 1449, 16,1460, 18,1464, 4, 0, 0, 30, 31, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0,
+ 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1834,1835, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1836, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1837,1839,1838, 0, 0, 0, 0,1840, 0, 0, 0,
+ 0,1841, 0, 0,1842, 0, 0, 0, 0, 0, 0, 0,1843, 0,1844, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1845, 0, 0,1846, 0, 0,1847,
+ 0,1848, 0, 0, 0, 0, 0, 0, 937, 0,1850, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1849, 936, 938,1851,1852, 0, 0,1853,1854, 0, 0,
+ 1855,1856, 0, 0, 0, 0, 0, 0,1857,1858, 0, 0,1861,1862, 0, 0,
+ 1863,1864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1867,1868,1869,1870,1859,1860,1865,1866, 0, 0, 0, 0,
+ 0, 0,1871,1872,1873,1874, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1875, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1877, 0,1878, 0,1879, 0,1880, 0,1881, 0,1882, 0,
+ 1883, 0,1884, 0,1885, 0,1886, 0,1887, 0,1888, 0, 0,1889, 0,1890,
+ 0,1891, 0, 0, 0, 0, 0, 0,1892,1893, 0,1894,1895, 0,1896,1897,
+ 0,1898,1899, 0,1900,1901, 0, 0, 0, 0, 0, 0,1876, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1902, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,1904, 0,1905, 0,1906, 0,1907, 0,1908, 0,1909, 0,
+ 1910, 0,1911, 0,1912, 0,1913, 0,1914, 0,1915, 0, 0,1916, 0,1917,
+ 0,1918, 0, 0, 0, 0, 0, 0,1919,1920, 0,1921,1922, 0,1923,1924,
+ 0,1925,1926, 0,1927,1928, 0, 0, 0, 0, 0, 0,1903, 0, 0,1929,
+ 1930,1931,1932, 0, 0, 0,1933, 0, 710, 385, 724, 715, 455, 103, 186, 825,
+ 825, 242, 751, 205, 241, 336, 524, 601, 663, 676, 688, 738, 411, 434, 474, 500,
+ 649, 746, 799, 108, 180, 416, 482, 662, 810, 275, 462, 658, 692, 344, 618, 679,
+ 293, 388, 440, 492, 740, 116, 146, 168, 368, 414, 481, 527, 606, 660, 665, 722,
+ 781, 803, 809, 538, 553, 588, 642, 758, 811, 701, 233, 299, 573, 612, 487, 540,
+ 714, 779, 232, 267, 412, 445, 457, 585, 594, 766, 167, 613, 149, 148, 560, 589,
+ 648, 768, 708, 345, 411, 704, 105, 259, 313, 496, 518, 174, 542, 120, 307, 101,
+ 430, 372, 584, 183, 228, 529, 650, 697, 424, 732, 428, 349, 632, 355, 517, 110,
+ 135, 147, 403, 580, 624, 700, 750, 170, 193, 245, 297, 374, 463, 543, 763, 801,
+ 812, 815, 162, 384, 420, 730, 287, 330, 337, 366, 459, 476, 509, 558, 591, 610,
+ 726, 652, 734, 759, 154, 163, 198, 473, 683, 697, 292, 311, 353, 423, 572, 494,
+ 113, 217, 259, 280, 314, 499, 506, 603, 608, 752, 778, 782, 788, 117, 557, 748,
+ 774, 320, 109, 126, 260, 265, 373, 411, 479, 523, 655, 737, 823, 380, 765, 161,
+ 395, 398, 438, 451, 502, 516, 537, 583, 791, 136, 340, 769, 122, 273, 446, 727,
+ 305, 322, 400, 496, 771, 155, 190, 269, 377, 391, 406, 432, 501, 519, 599, 684,
+ 687, 749, 776, 175, 452, 191, 480, 510, 659, 772, 805, 813, 397, 444, 619, 566,
+ 568, 575, 491, 471, 707, 111, 636, 156, 153, 288, 346, 578, 256, 435, 383, 729,
+ 680, 767, 694, 295, 128, 210, 0, 0, 227, 0, 379, 0, 0, 150, 493, 525,
+ 544, 551, 552, 556, 783, 576, 604, 0, 661, 0, 703, 0, 0, 735, 743, 0,
+ 0, 0, 793, 794, 795, 808, 741, 773, 118, 127, 130, 166, 169, 177, 207, 213,
+ 215, 226, 229, 268, 270, 317, 327, 329, 335, 369, 375, 381, 404, 441, 448, 458,
+ 477, 484, 503, 539, 545, 547, 546, 548, 549, 550, 554, 555, 561, 564, 569, 591,
+ 593, 595, 598, 607, 620, 625, 625, 651, 690, 695, 705, 706, 716, 717, 733, 735,
+ 777, 786, 790, 315, 869, 623, 0, 0, 102, 145, 134, 115, 129, 138, 165, 171,
+ 207, 202, 206, 212, 227, 231, 240, 243, 250, 254, 294, 296, 303, 308, 319, 325,
+ 321, 329, 326, 335, 341, 357, 360, 362, 370, 379, 388, 389, 393, 421, 424, 438,
+ 456, 454, 458, 465, 477, 535, 485, 490, 493, 507, 512, 514, 521, 522, 525, 526,
+ 528, 533, 532, 541, 565, 569, 574, 586, 591, 597, 607, 637, 647, 674, 691, 693,
+ 695, 698, 703, 699, 705, 704, 702, 706, 709, 717, 728, 736, 747, 754, 770, 777,
+ 783, 784, 786, 787, 790, 802, 825, 848, 847, 857, 55, 65, 66, 883, 892, 916,
+ 822, 824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,1586, 0,1605, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584, 0,
+ 1585,1587,1588,1589,1591, 0,1592, 0,1593,1594, 0,1595,1596, 0,1598,1599,
+ 1600,1601,1604,1582,1578,1590,1597, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1936, 0,1937, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1938, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1939,1940, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1941,1942, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1944,1943, 0,1945, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,1946,1947, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1949,1950,1951,1952,1953,1954,1955, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
- 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0,
- 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
- 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303,
- 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
- 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
- 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199,
- 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0,
- 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231,
- 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
- 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275,
- 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0,
- 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093,
- 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010,
- 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347,
- 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
- 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365,
- 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
- 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182,
- 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
- 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461,
- 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486,
- 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0,
- 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0,
- 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0,
- 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553,
- 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560,
- 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0,
- 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0,
- 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627,
- 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0,
- 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0,
- 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0,
- 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0,
- 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0,
- 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0,
- 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0,
- 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0,
- 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
- 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
- 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
- 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
- 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
- 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
- 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
- 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
- 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
- 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0,
- 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
- 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
- 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
- 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
- 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
- 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0,
- 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
- 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0,
- 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
- 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
- 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0,
- 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793,
- 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
- 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0,
- 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
- 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
- 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
- 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0,
- 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828,
- 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833,
- 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3,
- 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0,
- 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838,
- 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0,
- 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0,
- 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938,
- 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0,
- 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870,
- 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0,
- 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0,
- 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0,
- 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0,
- 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0,
- 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0,
- 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0,
- 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0,
- 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0,
- 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
- 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
- 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
- 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
- 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
- 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
- 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
- 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
- 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
- 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
- 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
- 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
- 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
- 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
- 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
- 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
- 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0,
- 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0,
- 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773,
- 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
- 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
- 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
- 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0,
- 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
- 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
- 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
- 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
- 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
- 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
- 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575,
- 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0,
- 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950,
- 1951,1952,1953,1954,1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959,
- 1961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131,
- 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37,
- 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
- 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
- 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
- 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
- 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259,
- 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
- 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934,
- 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312,
- 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
- 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
- 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381,
- 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399,
- 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417,
- 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
- 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460,
- 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
- 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505,
- 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64,
- 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538,
- 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567,
- 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592,
- 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
- 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627,
- 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
- 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83,
- 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85,
- 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696,
- 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
- 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90,
- 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787,
- 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807,
- 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0,
+ 0, 0, 0,1956,1957,1958,1960,1959,1961, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 106, 104, 107, 826, 114, 118, 119, 121,
+ 123, 124, 127, 125, 34, 830, 130, 131, 132, 137, 827, 35, 133, 139, 829, 142,
+ 143, 112, 144, 145, 924, 151, 152, 37, 157, 158, 159, 160, 38, 165, 166, 169,
+ 171, 172, 173, 174, 176, 177, 178, 179, 181, 182, 182, 182, 833, 468, 184, 185,
+ 834, 187, 188, 189, 196, 192, 194, 195, 197, 199, 200, 201, 203, 204, 204, 206,
+ 208, 209, 211, 218, 213, 219, 214, 216, 153, 234, 221, 222, 223, 220, 225, 224,
+ 230, 835, 235, 236, 237, 238, 239, 244, 836, 837, 247, 248, 249, 246, 251, 39,
+ 40, 253, 255, 255, 838, 257, 258, 259, 261, 839, 262, 263, 301, 264, 41, 266,
+ 270, 272, 271, 841, 274, 842, 277, 276, 278, 281, 282, 42, 283, 284, 285, 286,
+ 43, 843, 44, 289, 290, 291, 293, 934, 298, 845, 845, 621, 300, 300, 45, 852,
+ 894, 302, 304, 46, 306, 309, 310, 312, 316, 48, 47, 317, 846, 318, 323, 324,
+ 325, 324, 328, 329, 333, 331, 332, 334, 335, 336, 338, 339, 342, 343, 347, 351,
+ 849, 350, 348, 352, 354, 359, 850, 361, 358, 356, 49, 363, 365, 367, 364, 50,
+ 369, 371, 851, 376, 386, 378, 53, 381, 52, 51, 140, 141, 387, 382, 614, 78,
+ 388, 389, 390, 394, 392, 856, 54, 399, 396, 402, 404, 858, 405, 401, 407, 55,
+ 408, 409, 410, 413, 859, 415, 56, 417, 860, 418, 57, 419, 422, 424, 425, 861,
+ 840, 862, 426, 863, 429, 431, 427, 433, 437, 441, 438, 439, 442, 443, 864, 436,
+ 449, 450, 58, 454, 453, 865, 447, 460, 866, 867, 461, 466, 465, 464, 59, 467,
+ 470, 469, 472, 828, 475, 868, 478, 870, 483, 485, 486, 871, 488, 489, 872, 873,
+ 495, 497, 60, 498, 61, 61, 504, 505, 507, 508, 511, 62, 513, 874, 515, 875,
+ 518, 844, 520, 876, 877, 878, 63, 64, 528, 880, 879, 881, 882, 530, 531, 531,
+ 533, 66, 534, 67, 68, 884, 536, 538, 541, 69, 885, 549, 886, 887, 556, 559,
+ 70, 561, 562, 563, 888, 889, 889, 567, 71, 890, 570, 571, 72, 891, 577, 73,
+ 581, 579, 582, 893, 587, 74, 590, 592, 596, 75, 895, 896, 76, 897, 600, 898,
+ 602, 605, 607, 899, 900, 609, 901, 611, 853, 77, 615, 616, 79, 617, 252, 902,
+ 903, 854, 855, 621, 622, 731, 80, 627, 626, 628, 164, 629, 630, 631, 633, 904,
+ 632, 634, 639, 640, 635, 641, 646, 651, 638, 643, 644, 645, 905, 907, 906, 81,
+ 653, 654, 656, 911, 657, 908, 82, 83, 909, 910, 84, 664, 665, 666, 667, 669,
+ 668, 671, 670, 674, 672, 673, 675, 85, 677, 678, 86, 681, 682, 912, 685, 686,
+ 87, 689, 36, 913, 914, 88, 89, 696, 702, 709, 711, 915, 712, 713, 718, 719,
+ 917, 831, 721, 720, 723, 832, 725, 728, 918, 919, 739, 742, 744, 920, 745, 753,
+ 756, 757, 755, 760, 761, 921, 762, 90, 764, 922, 91, 775, 279, 780, 923, 925,
+ 92, 93, 785, 926, 94, 927, 787, 787, 789, 928, 792, 95, 796, 797, 798, 800,
+ 96, 929, 802, 804, 806, 97, 98, 807, 930, 99, 931, 932, 933, 814, 100, 816,
+ 817, 818, 819, 820, 821, 935, 0, 0,
};
static const int16_t
-_hb_ucd_i16[196] =
+_hb_ucd_i16[92] =
{
- 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2,
- 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1,
- 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3,
- -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0,
- 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0,
- 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0,
- 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0,
- 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0,
- 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1,
- -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0,
- 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106,
- -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1,
- -1, 0, 1, -1,
+ 0, 0, 1, -1, 2, 0, -2, 0, 0, 2, 0, -2, 0, 16, 0, -16,
+ 0, 1, -1, 0, 3, 3, 3, -3, -3, -3, 0, 2016, 0, 2527, 1923, 1914,
+ 1918, 0, 2250, 0, 0, 138, 0, 7, -7, 0, -1, 1, 1824, 0, 2104, 0,
+ 2108, 2106, 0, 2106, 1316, 0, -1, -138, 8, 8, 8, 0, 7, 7, -8, -8,
+ -8, -7,-1316, 1, -1, 3, -3, 1, 0,-1914,-1918, 0, 0,-1923,-1824, 0,
+ 0,-2016,-2104, 0, 0,-2106,-2108,-2106,-2250, 0,-2527, 0,
};
static inline uint_fast8_t
_hb_ucd_gc (unsigned u)
{
- return u<1114110u?_hb_ucd_u8[6664+(((_hb_ucd_u8[1296+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+ return u<1114110u?_hb_ucd_u8[6800+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
}
static inline uint_fast8_t
_hb_ucd_ccc (unsigned u)
{
- return u<125259u?_hb_ucd_u8[8984+(((_hb_ucd_u8[7960+(((_hb_ucd_u8[7288+(((_hb_ucd_u8[7042+(u>>2>>3>>4)])<<4)+((u>>2>>3)&15u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u))]:0;
+ return u<125259u?_hb_ucd_u8[8792+(((_hb_ucd_u8[8236+(((_hb_ucd_u8[7776+(((_hb_ucd_u8[7424+(((_hb_ucd_u8[7178+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
}
static inline unsigned
_hb_ucd_b4 (const uint8_t* a, unsigned i)
@@ -5660,24 +4415,24 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i)
static inline int_fast16_t
_hb_ucd_bmg (unsigned u)
{
- return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9728+(((_hb_ucd_u8[9608+(((_hb_ucd_b4(9480+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
+ return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9684+(((_hb_ucd_u8[9452+(((_hb_ucd_u8[9356+(((_hb_ucd_b4(9292+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
}
static inline uint_fast8_t
_hb_ucd_sc (unsigned u)
{
- return u<918000u?_hb_ucd_u8[11234+(((_hb_ucd_u16[2000+(((_hb_ucd_u8[10514+(((_hb_ucd_u8[10064+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
+ return u<918000u?_hb_ucd_u8[11118+(((_hb_ucd_u16[4024+(((_hb_ucd_u16[2040+(((_hb_ucd_u8[10382+(((_hb_ucd_u8[9932+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
}
static inline uint_fast16_t
_hb_ucd_dm (unsigned u)
{
- return u<195102u?_hb_ucd_u16[5888+(((_hb_ucd_u8[17136+(((_hb_ucd_u8[16754+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+ return u<195102u?_hb_ucd_u16[6728+(((_hb_ucd_u8[13944+(((_hb_ucd_u8[13562+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
}
#else
static const uint8_t
-_hb_ucd_u8[13602] =
+_hb_ucd_u8[13370] =
{
0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 7, 11, 12, 12, 12, 13,
@@ -5685,7 +4440,7 @@ _hb_ucd_u8[13602] =
7, 24, 21, 21, 21, 25, 26, 27, 21, 28, 29, 30, 31, 32, 33, 34,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 35, 21, 36,
- 7, 7, 37, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 7, 7, 7, 7, 35, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
@@ -5707,7 +4462,7 @@ _hb_ucd_u8[13602] =
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 38, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 37, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
@@ -5730,28 +4485,27 @@ _hb_ucd_u8[13602] =
34, 34,109,110,111,112,113,114,115,116,117,118, 34, 34, 34,119,
120,121,122,123,124,125,126,127, 34,128,129,111,130,131,132,133,
134,135,136,137,138,139,140,111,141,142,111,143,144,145,146,111,
- 147,148,149,150,151,152,111,111,153,154,155,156,111,157,111,158,
- 34, 34, 34, 34, 34, 34, 34, 34,159, 34, 34,111,111,111,111,111,
- 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,160,
- 34, 34, 34, 34, 34, 34, 34, 34,161,111,111,111,111,111,111,111,
+ 147,148,149,150,151,152,153,111,154,155,156,157,111,158,159,160,
+ 34, 34, 34, 34, 34, 34, 34, 34,161, 34, 34,111,111,111,111,111,
+ 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,162,
+ 34, 34, 34, 34, 34, 34, 34, 34,163,111,111,111,111,111,111,111,
111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
111,111,111,111,111,111,111,111, 34, 34, 34, 34, 34,111,111,111,
- 34, 34, 34, 34,162,163,164, 34,111,111,111,111,165,166,167,168,
+ 34, 34, 34, 34,164,165,166, 34,111,111,111,111,167,168,169,170,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,
111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,119,
34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,
- 111,111,111,111,111,111,111,111, 34,169,111,111,111,111,111,111,
- 111,111,111,111,111,111,111,111,111,111,111,111,111,111,170, 67,
- 67, 67,171,172,173,130, 65,111,174,175,176,177,178,179,180,181,
- 67, 67, 67, 67,182,183,111,111,111,111,111,111,111,111,184,111,
- 185,111,186,111,111,187,111,111,111,111,111,111,111,111,111, 34,
- 34,188,189,111,111,111,111,111,130,190,191,111, 34,192,111,111,
- 67, 67,193, 67, 67,111, 67,194, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67,195,111,111,111,111,111,111,111,111,
+ 111,111,111,111,111,111,111,111, 34,171,111,111,111,111,111,111,
+ 111,111,111,111,111,111,111,111,111,111,111,111,111,111,172, 67,
+ 67, 67,173,174,175,130, 65,111,176,177,178,179,180,181,182,183,
+ 67, 67, 67, 67,184,185,111,111,111,111,111,111,111,111,186,111,
+ 187,188,189,111,111,190,111,111,111,191,111,111,111,111,111, 34,
+ 34,192,193,111,111,111,111,111,130,194,195,111, 34,196,111,111,
+ 67, 67,197, 67, 67,111, 67,198, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67,199,111,111,111,111,111,111,111,111,
34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,
34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,111,
- 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,
- 196,111,185,185,111,111,111,111,111,111,111,111,111,111,111,111,
+ 200,111,188,188,111,111,111,111,111,111,111,111,111,111,111,111,
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2,
7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
@@ -5807,7 +4561,7 @@ _hb_ucd_u8[13602] =
36, 36, 36, 36, 36, 36, 65, 43, 77, 78, 78, 43, 43, 43, 43, 43,
43, 43, 43, 43, 36, 36, 36, 36, 7, 7, 7, 85, 27, 27, 27, 84,
64, 78, 66, 36, 36, 36, 36, 36, 78, 78, 78, 77, 78, 78, 43, 43,
- 43, 43, 77, 78, 78, 78, 81, 36, 86, 36, 36, 36, 36, 36, 36, 36,
+ 43, 43, 77, 78, 78, 78, 81, 36, 86, 82, 78, 78, 78, 78, 78, 78,
43, 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64, 65, 78,
79, 43, 43, 78, 78, 78, 79, 71, 61, 61, 36, 82, 27, 27, 27, 87,
27, 27, 27, 27, 84, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 77,
@@ -5947,7 +4701,7 @@ _hb_ucd_u8[13602] =
36, 64, 2, 36, 36, 36, 36, 36, 36, 82, 78, 43, 43, 43, 43, 77,
81, 36, 58, 2, 56, 43, 57, 79, 7, 7, 7, 7, 7, 58, 58, 2,
90, 27, 27, 27, 27, 27, 27, 27, 36, 36, 36, 36, 36, 36, 78, 79,
- 43, 78, 77, 43, 2, 2, 2, 43, 36, 36, 36, 36, 36, 36, 36, 64,
+ 43, 78, 77, 43, 2, 2, 2, 65, 36, 36, 36, 36, 36, 36, 36, 64,
77, 78, 78, 78, 78, 78, 78, 78, 36, 36, 36, 82, 78, 78, 81, 36,
36, 78, 78, 43, 43, 43, 43, 43, 36, 36, 82, 78, 43, 43, 43, 43,
78, 43, 77, 65, 36, 58, 2, 2, 7, 7, 7, 7, 7, 2, 2, 65,
@@ -5968,8 +4722,10 @@ _hb_ucd_u8[13602] =
43, 43, 43, 43, 77, 43, 43, 43, 77, 43, 79, 43, 43, 43, 43, 43,
43, 43, 43, 64, 43, 43, 43, 43, 36, 36, 36, 36, 36, 78, 78, 78,
43, 77, 79, 79, 36, 36, 36, 36, 36, 64, 77, 97, 2, 2, 2, 2,
- 27, 27, 84, 61, 61, 61, 53, 20,150, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 21, 43, 43, 57, 2, 2, 2, 2, 2,
+ 43, 82, 36, 36, 36, 36, 36, 36, 36, 36, 78, 43, 43, 43, 43, 78,
+ 77, 57, 2, 2, 2, 2, 2, 2, 27, 27, 84, 61, 61, 61, 53, 20,
+ 150, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 21,
+ 65, 36, 36, 64, 43, 43, 43, 43, 43, 43, 57, 2, 2, 2, 2, 2,
43, 43, 43, 57, 2, 2, 61, 61, 40, 40, 89, 61, 61, 61, 61, 61,
7, 7, 7, 7, 7,167, 27, 27, 27, 87, 36, 36, 36, 36, 36, 36,
27, 27, 27, 30, 2, 2, 2, 2, 82, 78, 78, 78, 78, 78, 78, 78,
@@ -5992,485 +4748,469 @@ _hb_ucd_u8[13602] =
16, 16, 16, 16, 16, 39, 16, 16, 43, 43, 43, 68, 40, 40, 40, 40,
7, 7, 7, 7, 7, 7, 7, 71, 36, 36, 36, 36, 36, 36, 36, 43,
36, 36, 36, 36, 36, 36, 43, 43, 7, 7, 7, 7, 7, 7, 7,170,
- 16, 16, 43, 43, 43, 68, 40, 40, 27, 27, 27, 27, 27, 27,145, 27,
- 171, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,145,
- 27, 27, 27, 27, 27, 27, 84, 61, 61, 61, 61, 61, 61, 25, 41, 41,
- 0, 0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13,
- 25, 25, 25, 21, 21, 9, 9, 9, 9, 22, 21, 18, 24, 16, 24, 5,
- 5, 5, 5, 22, 25, 18, 25, 0, 23, 23, 26, 21, 24, 26, 7, 20,
- 25, 1, 26, 24, 26, 25, 15, 15, 24, 15, 7, 19, 15, 21, 9, 25,
- 9, 5, 5, 25, 5, 9, 5, 7, 7, 7, 9, 8, 8, 5, 7, 5,
- 6, 6, 24, 24, 6, 24, 12, 12, 6, 5, 9, 21, 25, 9, 26, 12,
- 11, 11, 9, 6, 5, 21, 17, 17, 17, 26, 26, 23, 23, 12, 17, 12,
- 21, 12, 12, 21, 7, 21, 1, 1, 21, 23, 26, 26, 1, 21, 6, 7,
- 7, 12, 12, 7, 21, 7, 12, 1, 12, 6, 6, 12, 12, 26, 7, 26,
- 26, 7, 21, 1, 24, 7, 7, 6, 1, 12, 12, 10, 10, 10, 10, 12,
- 21, 6, 10, 7, 7, 10, 23, 7, 15, 26, 13, 21, 13, 7, 15, 7,
- 12, 23, 21, 26, 21, 15, 17, 7, 29, 7, 7, 22, 18, 18, 14, 14,
- 14, 7, 10, 21, 17, 21, 11, 12, 5, 6, 8, 8, 8, 24, 5, 24,
- 9, 24, 29, 29, 29, 1, 20, 19, 22, 20, 27, 28, 1, 29, 21, 20,
- 19, 21, 21, 16, 16, 21, 25, 22, 18, 21, 21, 29, 15, 6, 18, 6,
- 12, 11, 9, 26, 26, 9, 26, 5, 5, 26, 14, 9, 5, 14, 14, 15,
- 25, 26, 26, 22, 18, 26, 18, 25, 18, 22, 5, 12, 22, 21, 21, 22,
- 18, 17, 26, 6, 7, 14, 17, 22, 26, 14, 17, 6, 14, 6, 12, 24,
- 24, 6, 26, 15, 6, 21, 11, 21, 24, 9, 6, 9, 23, 26, 6, 10,
- 4, 4, 3, 3, 7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 7, 1,
- 25, 24, 26, 1, 2, 2, 12, 15, 21, 14, 7, 15, 12, 17, 13, 15,
- 26, 10, 10, 1, 13, 23, 23, 15, 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 0, 10, 11, 12, 13, 0, 14, 0, 0, 0, 0, 0, 15, 0,
- 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 19, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 20, 0, 21, 22, 23, 0, 0, 0, 24, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 35,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 37, 38, 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, 41, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0,
- 3, 0, 0, 0, 4, 5, 6, 7, 0, 8, 9, 10, 0, 11, 12, 13,
- 14, 15, 16, 17, 16, 18, 16, 19, 16, 19, 16, 19, 0, 19, 16, 20,
- 16, 19, 21, 19, 0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0,
- 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0,
- 0, 0, 34, 0, 0, 35, 0, 0, 36, 0, 37, 0, 0, 0, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 0, 0, 47, 0, 0, 0, 48, 0, 0,
- 0, 49, 0, 0, 0, 0, 0, 0, 0, 50, 0, 51, 0, 52, 53, 0,
- 54, 0, 0, 0, 0, 0, 0, 55, 56, 57, 0, 0, 0, 0, 58, 0,
- 0, 59, 60, 61, 62, 63, 0, 0, 64, 65, 0, 0, 0, 66, 0, 0,
- 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 69, 0, 0, 0, 70, 0, 71, 0, 0, 72, 0,
- 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0,
- 75, 0, 0, 76, 77, 0, 0, 78, 79, 0, 80, 62, 0, 81, 82, 0,
- 0, 83, 84, 85, 0, 0, 0, 86, 0, 87, 0, 0, 51, 88, 51, 0,
- 89, 0, 90, 0, 0, 0, 79, 0, 0, 0, 91, 92, 0, 93, 94, 95,
- 96, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 97, 98, 0, 0, 0,
- 0, 99,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,101, 0, 0,
- 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,103,104, 0, 0,105,
- 0, 0, 0, 0, 0, 0,106, 0, 0, 0,100, 0, 0, 0, 0, 0,
- 107,108, 0, 0, 0, 0, 0, 0, 0,109, 0,110, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 8, 0, 0, 0, 0, 9,
- 10, 11, 12, 0, 0, 0, 0, 13, 0, 0, 14, 15, 0, 16, 0, 17,
- 18, 0, 0, 19, 0, 20, 21, 0, 0, 0, 0, 0, 22, 23, 0, 24,
- 25, 0, 0, 26, 0, 0, 0, 27, 0, 0, 28, 29, 30, 31, 0, 0,
- 0, 32, 33, 34, 0, 0, 33, 0, 0, 35, 33, 0, 0, 0, 33, 36,
- 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0, 0, 0, 39, 40, 0,
- 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 43, 0, 44, 0, 0,
- 0, 45, 46, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 48, 49, 0,
- 0, 0, 0, 50, 0, 0, 0, 51, 0, 52, 0, 53, 0, 0, 0, 0,
- 54, 0, 0, 0, 0, 55, 0, 56, 0, 0, 0, 0, 57, 58, 0, 0,
- 0, 59, 60, 0, 0, 0, 0, 0, 0, 61, 52, 0, 62, 63, 0, 0,
- 64, 0, 0, 0, 65, 66, 0, 0, 0, 67, 0, 68, 69, 70, 71, 72,
- 1, 73, 0, 74, 75, 76, 0, 0, 77, 78, 0, 0, 0, 79, 0, 0,
- 1, 1, 0, 0, 80, 0, 0, 81, 0, 0, 0, 0, 77, 82, 0, 83,
- 0, 0, 0, 0, 0, 78, 84, 0, 85, 0, 52, 0, 1, 78, 0, 0,
- 86, 0, 0, 87, 0, 0, 0, 0, 0, 88, 57, 0, 0, 0, 0, 0,
- 0, 89, 90, 0, 0, 84, 0, 0, 33, 0, 0, 91, 0, 0, 0, 0,
- 92, 0, 0, 0, 0, 49, 0, 0, 93, 0, 0, 0, 0, 94, 95, 0,
- 0, 96, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99, 0,100, 93,
- 0, 0,101, 0, 0, 0, 84, 0, 0,102, 0, 0, 0,103,104, 0,
- 0,105,106, 0, 0, 0, 0, 0, 0,107, 0, 0,108, 0, 0, 0,
- 0,109, 33, 0,110,111,112, 35, 0, 0,113, 0, 0, 0,114, 0,
- 0, 0, 0, 0, 0,115, 0, 0,116, 0, 0, 0, 0,117, 88, 0,
- 0, 0, 0, 0, 57, 0, 0, 0, 0, 52,118, 0, 0, 0, 0,119,
- 0, 0,120, 0, 0, 0, 0,118, 0, 0, 0, 0, 0,121, 0, 0,
- 0,122, 0, 0, 0,123, 0,124, 0, 0, 0, 0,125,126,127, 0,
- 128, 0,129, 0, 0, 0,130,131,132, 0, 0, 0, 35, 0, 0, 0,
- 133, 0, 0,134, 0, 0,135, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 1, 2, 3, 4, 5, 6, 7, 4, 4, 8, 9, 10, 1, 11,
- 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, 19, 1, 0, 0, 20, 21,
- 22, 1, 23, 4, 21, 24, 25, 26, 27, 28, 29, 30, 0, 0, 1, 1,
- 31, 0, 0, 0, 32, 33, 34, 35, 1, 36, 37, 0, 0, 0, 0, 38,
- 1, 39, 14, 39, 40, 41, 42, 0, 0, 0, 43, 36, 44, 45, 21, 45,
- 46, 0, 0, 0, 19, 1, 21, 0, 0, 47, 0, 38, 48, 1, 1, 49,
- 49, 50, 0, 0, 51, 0, 0, 0, 52, 1, 0, 0, 38, 14, 4, 1,
- 1, 1, 53, 21, 43, 52, 54, 21, 35, 1, 0, 0, 0, 55, 0, 0,
- 0, 56, 57, 58, 0, 0, 0, 0, 0, 59, 0, 60, 0, 0, 0, 0,
- 61, 62, 0, 0, 63, 0, 0, 0, 64, 0, 0, 0, 65, 0, 0, 0,
- 66, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 69, 70, 0, 71, 72,
- 73, 74, 75, 76, 0, 0, 0, 77, 0, 0, 0, 78, 79, 0, 0, 0,
- 0, 47, 0, 0, 0, 49, 0, 80, 0, 0, 0, 62, 0, 0, 63, 0,
- 0, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 19, 84, 0, 62, 0,
- 0, 0, 0, 49, 1, 85, 1, 52, 15, 86, 36, 10, 21, 87, 0, 55,
- 0, 0, 0, 0, 19, 10, 1, 0, 0, 0, 0, 0, 88, 0, 0, 89,
- 0, 0, 88, 0, 0, 0, 0, 78, 0, 0, 87, 9, 12, 4, 90, 8,
- 91, 47, 0, 58, 50, 0, 21, 1, 21, 92, 93, 1, 1, 1, 1, 94,
- 95, 96, 97, 1, 98, 58, 81, 99,100, 4, 58, 0, 0, 0, 0, 0,
- 0, 19, 50, 0, 0, 0, 0, 0, 0, 61, 0, 0,101,102, 0, 0,
- 103, 0, 0, 1, 1, 50, 0, 0, 0, 38, 0, 63, 0, 0, 0, 0,
- 0, 62, 0, 0,104, 68, 61, 0, 0, 0, 78, 0, 0, 0,105,106,
- 58, 38, 81, 0, 0, 0, 0, 0, 0,107, 1, 14, 4, 12, 84, 0,
- 0, 0, 0, 38, 87, 0, 0, 0, 0,108, 0, 0,109, 61, 0,110,
- 0, 0, 0, 1, 0, 0, 0, 0, 19, 58, 0,111, 14, 52,112, 41,
- 0, 0, 62, 0, 0, 61, 0, 0,113, 0, 87, 0, 0, 0, 61, 62,
- 0, 0, 62, 0, 89, 0, 0,113, 0, 0, 0, 0,114, 0, 0, 0,
- 78, 55, 0, 38, 1, 58, 1, 58, 0, 0, 63, 89, 0, 0,115, 0,
- 0, 0, 55, 0, 0, 0, 0,115, 0, 0, 0, 0, 61, 0, 0, 0,
- 0, 79, 0, 61, 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, 8, 91,
+ 36, 36, 36, 36, 36, 75, 43, 43, 16, 16, 43, 43, 43, 68, 40, 40,
+ 27, 27, 27, 27, 27, 27,145, 27,171, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27,145, 27, 27, 27, 27, 27, 27, 84, 61,
+ 61, 61, 61, 61, 61, 25, 41, 41, 0, 0, 29, 21, 21, 21, 23, 21,
+ 22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21, 9, 9, 9,
+ 9, 22, 21, 18, 24, 16, 24, 5, 5, 5, 5, 22, 25, 18, 25, 0,
+ 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24, 26, 25, 15, 15,
+ 24, 15, 7, 19, 15, 21, 9, 25, 9, 5, 5, 25, 5, 9, 5, 7,
+ 7, 7, 9, 8, 8, 5, 7, 5, 6, 6, 24, 24, 6, 24, 12, 12,
+ 6, 5, 9, 21, 25, 9, 26, 12, 11, 11, 9, 6, 5, 21, 17, 17,
+ 17, 26, 26, 23, 23, 12, 17, 12, 21, 12, 12, 21, 7, 21, 1, 1,
+ 21, 23, 26, 26, 1, 21, 6, 7, 7, 12, 12, 7, 21, 7, 12, 1,
+ 12, 6, 6, 12, 12, 26, 7, 26, 26, 7, 21, 1, 24, 7, 7, 6,
+ 1, 12, 12, 10, 10, 10, 10, 12, 21, 6, 10, 7, 7, 10, 23, 7,
+ 15, 26, 13, 21, 13, 7, 15, 7, 12, 23, 21, 26, 21, 15, 17, 7,
+ 29, 7, 7, 22, 18, 18, 14, 14, 14, 7, 10, 21, 17, 21, 11, 12,
+ 5, 6, 8, 8, 8, 24, 5, 24, 9, 24, 29, 29, 29, 1, 20, 19,
+ 22, 20, 27, 28, 1, 29, 21, 20, 19, 21, 21, 16, 16, 21, 25, 22,
+ 18, 21, 21, 29, 15, 6, 18, 6, 12, 11, 9, 26, 26, 9, 26, 5,
+ 5, 26, 14, 9, 5, 14, 14, 15, 25, 26, 26, 22, 18, 26, 18, 25,
+ 18, 22, 5, 12, 22, 21, 21, 22, 18, 17, 26, 6, 7, 14, 17, 22,
+ 26, 14, 17, 6, 14, 6, 12, 24, 24, 6, 26, 15, 6, 21, 11, 21,
+ 24, 9, 6, 9, 23, 26, 6, 10, 4, 4, 3, 3, 7, 25, 17, 16,
+ 16, 22, 16, 16, 25, 17, 7, 1, 25, 24, 26, 1, 2, 2, 12, 15,
+ 21, 14, 7, 15, 12, 17, 13, 15, 26, 10, 10, 1, 13, 23, 23, 15,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 0,
+ 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 21,
+ 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 35, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 0, 0,
+ 40, 41, 42, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 5, 6, 7,
+ 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, 16, 17, 16, 18, 16, 19,
+ 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, 21, 19, 0, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35, 0, 0,
+ 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, 42, 43, 44, 45, 46, 0,
+ 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0,
+ 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, 0, 0, 0, 0, 0, 55,
+ 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, 60, 61, 62, 63, 0, 0,
+ 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, 67, 0, 0, 0, 68, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0,
+ 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, 0, 0, 0, 0, 0, 0,
+ 0, 0, 74, 0, 0, 0, 0, 0, 75, 76, 0, 77, 78, 0, 0, 79,
+ 80, 0, 81, 62, 0, 82, 83, 0, 0, 84, 85, 86, 0, 0, 0, 87,
+ 0, 88, 0, 0, 51, 89, 51, 0, 90, 0, 91, 0, 0, 0, 80, 0,
+ 0, 0, 92, 93, 0, 94, 95, 96, 97, 0, 0, 0, 0, 0, 51, 0,
+ 0, 0, 0, 98, 99, 0, 0, 0, 0, 0, 0,100, 0, 0, 0, 0,
+ 0,101,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,103, 0, 0,
+ 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,106, 0, 0,107,
+ 0, 0, 0, 0, 0, 0,108, 0,109, 0,102, 0, 0, 0, 0, 0,
+ 110,111, 0, 0, 0, 0, 0, 0, 0,112, 0, 0, 0, 0, 0, 0,
+ 0,113, 0,114, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
+ 7, 0, 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0, 0, 13,
+ 0, 0, 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, 0, 20, 21, 0,
+ 0, 0, 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, 0, 0, 0, 27,
+ 0, 0, 28, 29, 30, 31, 0, 0, 0, 32, 33, 34, 0, 0, 33, 0,
+ 0, 35, 33, 0, 0, 0, 33, 36, 0, 0, 0, 0, 0, 37, 38, 0,
+ 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 41, 42, 0,
+ 0, 0, 0, 43, 0, 44, 0, 0, 0, 45, 46, 0, 0, 0, 47, 0,
+ 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 50, 0, 0, 0, 51,
+ 0, 52, 0, 53, 0, 0, 0, 0, 54, 0, 0, 0, 0, 55, 0, 56,
+ 0, 0, 0, 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0, 0, 0,
+ 0, 61, 52, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 66, 0, 0,
+ 0, 67, 0, 68, 69, 70, 71, 72, 1, 73, 0, 74, 75, 76, 0, 0,
+ 77, 78, 0, 0, 0, 79, 0, 0, 1, 1, 0, 0, 80, 0, 0, 81,
+ 0, 0, 0, 0, 77, 82, 0, 83, 0, 0, 0, 0, 0, 78, 84, 0,
+ 85, 0, 52, 0, 1, 78, 0, 0, 86, 0, 0, 87, 0, 0, 0, 0,
+ 0, 88, 57, 0, 0, 0, 0, 0, 0, 89, 90, 0, 0, 84, 0, 0,
+ 33, 0, 0, 91, 0, 0, 0, 0, 92, 0, 0, 0, 0, 49, 0, 0,
+ 93, 0, 0, 0, 0, 94, 95, 0, 0, 96, 0, 0, 97, 0, 0, 0,
+ 98, 0, 0, 0, 99, 0, 0, 0, 0,100,101, 93, 0, 0,102, 0,
+ 0, 0, 84, 0, 0,103, 0, 0, 0,104,105, 0, 0,106,107, 0,
+ 0, 0, 0, 0, 0,108, 0, 0,109, 0, 0, 0, 0,110, 33, 0,
+ 111,112,113, 35, 0, 0,114, 0, 0, 0,115, 0, 0, 0, 0, 0,
+ 0,116, 0, 0,117, 0, 0, 0, 0,118, 88, 0, 0, 0, 0, 0,
+ 57, 0, 0, 0, 0, 52,119, 0, 0, 0, 0,120, 0, 0,121, 0,
+ 0, 0, 0,119, 0, 0,122, 0, 0, 0, 0, 0, 0,123, 0, 0,
+ 0,124, 0, 0, 0,125, 0,126, 0, 0, 0, 0,127,128,129, 0,
+ 130, 0,131, 0, 0, 0,132,133,134, 0, 77, 0, 0, 0, 0, 0,
+ 35, 0, 0, 0,135, 0, 0, 0,136, 0, 0,137, 0, 0,138, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6,
+ 7, 4, 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, 18, 1,
+ 1, 1, 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24, 25, 26,
+ 27, 28, 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33, 34, 35,
+ 1, 36, 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41, 42, 0,
+ 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 19, 1, 21, 0,
+ 0, 47, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 51, 0, 0, 0,
+ 52, 1, 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52, 54, 21,
+ 35, 1, 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0, 0, 0,
+ 0, 59, 0, 60, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0, 0, 0,
+ 64, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0,
+ 68, 0, 0, 69, 70, 0, 71, 72, 73, 74, 75, 76, 0, 0, 0, 77,
+ 0, 0, 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 49, 0, 80,
+ 0, 0, 0, 62, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0, 0, 0,
+ 83, 0, 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85, 1, 52,
+ 15, 86, 36, 10, 21, 87, 0, 55, 0, 0, 0, 0, 19, 10, 1, 0,
+ 0, 0, 0, 0, 88, 0, 0, 89, 0, 0, 88, 0, 0, 0, 0, 78,
+ 0, 0, 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0, 21, 1,
+ 21, 92, 93, 1, 1, 1, 1, 94, 95, 96, 97, 1, 98, 58, 81, 99,
+ 100, 4, 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0, 0, 0,
+ 0, 61, 0, 0,101,102, 0, 0,103, 0, 0, 1, 1, 50, 0, 0,
+ 0, 38, 0, 63, 0, 0, 0, 0, 0, 62, 0, 0,104, 68, 61, 0,
+ 0, 0, 78, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0, 0, 0,
+ 0,107, 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 87, 0, 0, 0,
+ 0,108, 0, 0,109, 61, 0,110, 0, 0, 0, 1, 0, 0, 0, 0,
+ 19, 58, 0, 0, 0, 51, 0,111, 14, 52,112, 41, 0, 0, 62, 0,
+ 0, 61, 0, 0,113, 0, 87, 0, 0, 0, 61, 62, 0, 0, 62, 0,
+ 89, 0, 0,113, 0, 0, 0, 0,114, 0, 0, 0, 78, 55, 0, 38,
+ 1, 58, 1, 58, 0, 0, 63, 89, 0, 0,115, 0, 0, 0, 55, 0,
+ 0, 0, 0,115, 0, 0, 0, 0, 61, 0, 0, 0, 0, 79, 0, 61,
+ 0, 0, 0, 0, 56, 0, 89, 80, 0, 0, 79, 0, 0, 0, 8, 91,
0, 0, 1, 87, 0, 0,116, 0, 0, 0, 0, 0, 0,117, 0,118,
119,120,121, 0,104, 4,122, 49, 23, 0, 0, 0, 38, 50, 38, 58,
0, 0, 1, 87, 1, 1, 1, 1, 39, 1, 48,105, 87, 0, 0, 0,
- 0, 1, 4,122, 0, 0, 0, 1,123, 0, 0, 0, 0, 0,230,230,
- 230,230,230,232,220,220,220,220,232,216,220,220,220,220,220,202,
- 202,220,220,220,220,202,202,220,220,220, 1, 1, 1, 1, 1,220,
- 220,220,220,230,230,230,230,240,230,220,220,220,230,230,230,220,
- 220, 0,230,230,230,220,220,220,220,230,232,220,220,230,233,234,
- 234,233,234,234,233,230, 0, 0, 0,230, 0,220,230,230,230,230,
- 220,230,230,230,222,220,230,230,220,220,230,222,228,230, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 0, 23, 0, 24,
- 25, 0,230,220, 0, 18, 30, 31, 32, 0, 0, 0, 0, 27, 28, 29,
- 30, 31, 32, 33, 34,230,230,220,220,230,220,230,230,220, 35, 0,
- 0, 0, 0, 0,230,230,230, 0, 0,230,230, 0,220,230,230,220,
- 0, 0, 0, 36, 0, 0,230,220,230,230,220,220,230,220,220,230,
- 220,230,220,230,230, 0, 0,220, 0, 0,230,230, 0,230, 0,230,
- 230,230,230,230, 0, 0, 0,220,220,220,230,220,220,220,230,230,
- 0,220, 27, 28, 29,230, 7, 0, 0, 0, 0, 9, 0, 0, 0,230,
- 220,230,230, 0, 0, 0, 0, 0,230, 0, 0, 84, 91, 0, 0, 0,
- 0, 9, 9, 0, 0, 0, 0, 0, 9, 0,103,103, 9, 0,107,107,
- 107,107,118,118, 9, 0,122,122,122,122,220,220, 0, 0, 0,220,
- 0,220, 0,216, 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,
- 130,130,130,130, 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0,
- 220, 0, 0, 0, 0, 7, 0, 9, 9, 0, 9, 9, 0, 0, 0,230,
- 0, 0, 0,228, 0, 0, 0,222,230,220,220, 0, 0, 0,230, 0,
- 0,220,230,220, 0,220,230,230,230, 0, 0, 0, 9, 9, 0, 0,
- 7, 0,230, 0, 1, 1, 1, 0, 0, 0,230,234,214,220,202,230,
- 230,230,230,230,232,228,228,220,218,230,233,220,230,220,230,230,
- 1, 1, 1, 1, 1,230, 0, 1, 1,230,220,230, 1, 1, 0, 0,
- 218,228,232,222,224,224, 0, 8, 8, 0, 0, 0, 0,220,230, 0,
- 230,230,220, 0, 0,230, 0, 0, 26, 0, 0,220, 0,230,230, 1,
- 220, 0, 0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9,
- 7, 0, 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0,
- 1, 0, 0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,
- 216, 0,220,220,220, 0,230,230, 7, 0, 16, 17, 17, 17, 17, 17,
- 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,129,169,
- 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 0, 1, 0, 0, 0,123, 4,122, 0, 0, 0, 1,124, 0, 0, 0,
+ 0, 0,230,230,230,230,230,232,220,220,220,220,232,216,220,220,
+ 220,220,220,202,202,220,220,220,220,202,202,220,220,220, 1, 1,
+ 1, 1, 1,220,220,220,220,230,230,230,230,240,230,220,220,220,
+ 230,230,230,220,220, 0,230,230,230,220,220,220,220,230,232,220,
+ 220,230,233,234,234,233,234,234,233,230, 0, 0, 0,230, 0,220,
+ 230,230,230,230,220,230,230,230,222,220,230,230,220,220,230,222,
+ 228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22,
+ 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0, 0, 0,
+ 0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,220,230,
+ 230,220, 35, 0, 0, 0, 0, 0,230,230,230, 0, 0,230,230, 0,
+ 220,230,230,220, 0, 0, 0, 36, 0, 0,230,220,230,230,220,220,
+ 230,220,220,230,220,230,220,230,230, 0, 0,220, 0, 0,230,230,
+ 0,230, 0,230,230,230,230,230, 0, 0, 0,220,220,220,230,220,
+ 220,220,230,230, 0,220, 27, 28, 29,230, 7, 0, 0, 0, 0, 9,
+ 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0,230, 0, 0, 84,
+ 91, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 9, 0,103,103,
+ 9, 0,107,107,107,107,118,118, 9, 0,122,122,122,122,220,220,
+ 0, 0, 0,220, 0,220, 0,216, 0, 0, 0,129,130, 0,132, 0,
+ 0, 0, 0, 0,130,130,130,130, 0, 0,130, 0,230,230, 9, 0,
+ 230,230, 0, 0,220, 0, 0, 0, 0, 7, 0, 9, 9, 0, 9, 9,
+ 0, 0, 0,230, 0, 0, 0,228, 0, 0, 0,222,230,220,220, 0,
+ 0, 0,230, 0, 0,220,230,220, 0,220,230,230,230, 0, 0, 0,
+ 9, 9, 0, 0, 7, 0,230, 0, 1, 1, 1, 0, 0, 0,230,234,
+ 214,220,202,230,230,230,230,230,232,228,228,220,218,230,233,220,
+ 230,220,230,230, 1, 1, 1, 1, 1,230, 0, 1, 1,230,220,230,
+ 1, 1, 0, 0,218,228,232,222,224,224, 0, 8, 8, 0, 0, 0,
+ 0,220,230, 0,230,230,220, 0, 0,230, 0, 0, 26, 0, 0,220,
+ 0,230,230, 1,220, 0, 0,230,220, 0, 0, 0,220,220, 0, 0,
+ 230,220, 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 9, 7, 6, 6,
+ 0, 0, 0, 0, 1, 0, 0,216,216, 1, 1, 1, 0, 0, 0,226,
+ 216,216,216,216,216, 0,220,220,220, 0,232,232,220,230,230,230,
+ 7, 0, 16, 17, 17, 33, 17, 49, 17, 17, 84, 97,135,145, 26, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17,177, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 5, 3, 3, 3,
+ 3, 3, 6, 7, 8, 3, 3, 3, 3, 3, 9, 10, 11, 12, 13, 3,
+ 3, 3, 3, 3, 3, 3, 3, 14, 3, 15, 3, 3, 3, 3, 3, 3,
+ 16, 17, 18, 19, 20, 21, 3, 3, 3, 22, 23, 24, 3, 3, 3, 3,
+ 3, 3, 25, 3, 3, 3, 3, 3, 3, 3, 3, 26, 3, 3, 27, 28,
+ 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0,
+ 0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 0,
+ 0, 14, 15, 16, 6, 0, 17, 18, 19, 19, 19, 20, 21, 22, 23, 24,
+ 19, 25, 0, 26, 27, 19, 19, 28, 29, 30, 0, 31, 0, 0, 0, 8,
+ 0, 0, 0, 0, 0, 0, 0, 19, 28, 0, 32, 33, 9, 34, 35, 19,
+ 0, 0, 36, 37, 38, 39, 40, 19, 0, 41, 42, 43, 44, 31, 0, 1,
+ 45, 42, 0, 0, 0, 0, 0, 32, 14, 14, 0, 0, 0, 0, 14, 0,
+ 0, 46, 47, 47, 47, 47, 48, 49, 47, 47, 47, 47, 50, 51, 52, 53,
+ 43, 21, 0, 0, 0, 0, 0, 0, 0, 54, 6, 55, 0, 14, 19, 1,
+ 0, 0, 0, 0, 56, 57, 0, 0, 0, 0, 0, 19, 58, 31, 0, 0,
+ 0, 0, 0, 0, 0, 59, 14, 0, 0, 0, 0, 1, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 60, 61, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 2, 3, 0, 4, 5, 0, 0, 6, 0, 0, 0, 7,
+ 0, 0, 0, 1, 1, 0, 0, 8, 9, 0, 8, 9, 0, 0, 0, 0,
+ 8, 9, 10, 11, 12, 0, 0, 0, 13, 0, 0, 0, 0, 14, 15, 16,
+ 17, 0, 0, 0, 1, 0, 0, 18, 19, 0, 0, 0, 20, 0, 0, 0,
+ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 8, 21, 9,
+ 0, 0, 22, 0, 0, 0, 0, 1, 0, 23, 24, 25, 0, 0, 26, 0,
+ 0, 0, 8, 21, 27, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 28,
+ 29, 30, 0, 31, 32, 20, 1, 1, 0, 0, 0, 8, 21, 9, 1, 4,
+ 5, 0, 0, 0, 33, 9, 0, 1, 1, 1, 0, 8, 21, 21, 21, 21,
+ 34, 1, 35, 21, 21, 21, 9, 36, 0, 0, 37, 38, 1, 0, 39, 0,
+ 0, 0, 1, 0, 1, 0, 0, 0, 0, 8, 21, 9, 1, 0, 0, 0,
+ 40, 0, 8, 21, 21, 21, 21, 21, 21, 21, 21, 9, 0, 1, 1, 1,
+ 1, 8, 21, 21, 21, 9, 0, 0, 0, 41, 0, 42, 43, 0, 0, 0,
+ 1, 44, 0, 0, 0, 45, 8, 9, 1, 0, 0, 0, 8, 21, 21, 21,
+ 9, 0, 1, 0, 1, 1, 8, 21, 21, 9, 0, 4, 5, 8, 9, 1,
+ 0, 0, 0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 3, 3, 3, 3, 3, 3, 3, 15, 3, 16, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17,237, 0, 1, 2, 2, 0, 3,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 7, 8, 9, 0,
- 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 20, 0, 0, 21, 22, 0, 0, 0, 0, 23, 24,
- 25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0,
- 0, 33, 34, 35, 36, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 1, 2, 40, 41, 0, 1,
- 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
- 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 5, 0, 0, 0,
- 6, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0,
- 8, 9, 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0,
- 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0, 0, 0,
- 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7, 20, 20,
- 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0, 20, 20,
- 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1, 28, 29,
- 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0,
- 0, 0, 0, 0, 20, 20, 20, 1, 0, 0, 8, 21, 32, 4, 0, 10,
- 0, 33, 7, 20, 20, 20, 0, 0, 0, 0, 8, 34, 34, 35, 36, 34,
- 37, 0, 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8, 21, 1,
- 20, 0, 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 8, 21, 0, 1,
- 0, 1, 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,
- 0, 42, 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0, 0, 0,
- 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 20, 20, 1, 20,
- 20, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 11, 12, 12, 12,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 12, 21, 12, 12, 12, 12, 22,
- 23, 23, 23, 24, 12, 12, 12, 25, 26, 27, 12, 28, 29, 30, 31, 32,
- 33, 34, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 35,
- 12, 36, 7, 7, 37, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 38, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 29, 30, 31, 32, 32, 33, 33, 33, 34, 35, 35, 35, 35,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
- 2, 2, 51, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 57, 57, 56, 56, 56, 56, 56, 56, 58, 59, 60, 61,
- 56, 62, 62, 63, 64, 65, 66, 67, 68, 69, 70, 56, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 71,
- 62, 62, 62, 62, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 74, 74,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 62, 62, 62, 62, 88, 89, 89, 89, 90, 89,
- 91, 92, 93, 94, 95, 95, 96, 97, 87, 98, 99,100,101,102,103,104,
- 105,105,105, 2,106,107,108,109,110,111,112,113,114,115,116, 87,
- 89,117,118,119,120,121,122,123,124,125,126, 87,127,128, 87,129,
- 130,131,132, 87,133,134,135,136,137,138, 87, 87,139,140,141,142,
- 87,143, 87,144,145,145,145,145,145,145,145,145,145,145,145, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87,146,147,147,147,147,147,147,147,147,147, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,148,148,148,148,
- 148, 87, 87, 87,149,149,149,149,150,151,152,152, 87, 87, 87, 87,
- 153,153,154,155,156,156,156,156,156,156,156,156,156,156,156,156,
- 156,156,156,156,156,156,156,156,156,156,157,157,157,157,156, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87,158,159,160,161,162,162,162, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,163,164, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87,165, 56, 56, 56,166,167, 51, 56, 56, 87, 56, 56, 56, 56,
- 56, 56, 56, 56,168,168,168,168,168,168, 87, 87, 87, 87, 87, 87,
- 87, 87, 2, 87,169, 87,170, 87, 87,171, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 33,172,172,173, 87, 87, 87, 87, 87, 56, 56, 56, 87,
- 89, 89, 87, 87, 56, 56, 56, 56,174, 87, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 87, 87, 87, 87,
- 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87,
- 87, 87, 87, 87, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 56, 87,175,175, 0, 1, 2, 2, 0, 1, 2, 2,
- 2, 3, 4, 5, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3,
- 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6,
- 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11,
- 11, 11, 12, 11, 13, 13, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 15, 16, 16, 16, 16, 16, 17, 18, 18,
- 18, 18, 18, 18, 19, 20, 21, 21, 22, 23, 21, 24, 21, 21, 21, 21,
- 21, 25, 21, 21, 26, 26, 26, 26, 26, 21, 21, 21, 27, 27, 27, 27,
- 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 26, 21, 21, 21, 21, 21,
- 21, 21, 31, 21, 32, 32, 32, 32, 32, 33, 34, 32, 35, 35, 35, 35,
- 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37,
- 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39,
- 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41,
- 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43,
- 43, 43, 43, 43, 44, 44, 44, 45, 44, 44, 44, 44, 46, 46, 46, 46,
- 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 48, 47, 47, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50,
- 50, 50, 50, 51, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55,
- 55, 55, 55, 55, 56, 56, 57, 57, 57, 57, 58, 57, 59, 59, 60, 61,
- 62, 62, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 65, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 55, 55, 55, 55, 55, 67, 67, 67, 67,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 18, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 17, 17, 18, 17, 19, 20, 21, 22, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 25, 25, 26, 27, 28, 29, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 52, 53, 31, 31, 31, 31, 54, 55, 55, 56, 31,
+ 31, 31, 31, 31, 31, 31, 57, 58, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 59, 60, 31, 61, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 64, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 65, 66, 67, 31, 31,
+ 31, 31, 68, 31, 31, 31, 31, 31, 31, 31, 31, 69, 70, 71, 17, 17,
+ 72, 73, 31, 74, 75, 76, 77, 78, 79, 31, 80, 81, 17, 82, 17, 17,
+ 17, 17, 31, 31, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31,
+ 23, 83, 31, 31, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 84, 0, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3,
+ 4, 5, 6, 7, 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 5, 6,
+ 7, 8, 9, 10, 11, 11, 12, 11, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 19, 27, 28, 29, 30, 30, 31, 31, 32, 32,
+ 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 40, 41, 41,
+ 42, 42, 42, 43, 44, 44, 45, 46, 47, 47, 47, 47, 48, 48, 48, 48,
+ 48, 48, 49, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 53,
+ 54, 55, 56, 56, 57, 58, 59, 51, 60, 61, 62, 63, 64, 65, 66, 7,
+ 67, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 7, 4, 4, 4, 4,
+ 77, 77, 77, 77, 78, 79, 80, 81, 82, 83, 84, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 85, 85, 85, 85, 0, 0, 0, 0, 86, 87, 88, 88,
+ 89, 90, 48, 91, 0, 0, 92, 92, 92, 92, 92, 93, 94, 95, 96, 97,
+ 98, 47, 99,100,101,102, 0,103,104,105, 0, 0, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0,106,106,106,106,
+ 106,106,106,106,106,106,106,107,108,108,108,108,108, 11,109,110,
+ 111, 4,112, 4,113,114,115,116,117,118,119,120,121,122,123,124,
+ 125,126, 50,127, 47, 47, 47, 47, 47, 47, 47, 47,128,128,128,128,
+ 128,128,128,128,128,128,128,128, 92, 92, 92, 92, 92, 92, 92, 92,
+ 129,130, 19, 19, 19, 19, 19, 19,131, 19, 19, 19,132,133, 19,134,
+ 135,136,137,101,138,138,138,138, 0, 77,139,140,128,128,141,142,
+ 143,144,145,146,147,148,149,150,151,152,153,153,154,154,154,154,
+ 154,154, 4, 4,155,156,157,158,159,160,161,162,163,164,165,166,
+ 167,168,169,169,170,170,171,171,172,172,128,128, 19, 19,173,174,
+ 175,176,177,178,179,179,180,181,182,183,184,185,186,186,187,188,
+ 189,190,128,128,191,191,192,192,128,128,193,193,194,195,196,196,
+ 197,197,128,128,198,198,199,199,200,200,201,201,202,203,204,205,
+ 28, 28,128,128,206,207,208,208,209,210,211,211,128,128,212,212,
+ 213,213,214, 34,215,215,215,215,215,215,215,215,215,215,215,215,
+ 215,215,128,128,128,128,128,128,128,128,216,216,217,217,217,217,
+ 217,217,217,217,217,217,128,128,128,128,128,128,218,218,218,218,
+ 218,218,218,218,218,218,128,128,128,128,128,128,110,110,110,110,
+ 110,110,110,110,110,219,220,221,222,222,222,222,223,223,223,223,
+ 224,224,224,225,226,226,226,226,226,226,226,226,226,226,226,226,
+ 227,227,227,227,227,227,227,227,226,226,128,128,128,128,128,128,
+ 128,128,104,104,228,229,229,229,230,231,232,232,232,232,232,232,
+ 128,128,128,128,233,233,234, 0,128,128,128,128,128,128,128,128,
+ 7,235, 0, 0, 0, 0, 0, 0, 0,236,237, 0, 77, 77, 0, 0,
+ 0, 0,128,128,238,238,238,238,238,238,238,238,238,238,238,238,
+ 128,128,128,128,128,128,128,128, 4, 4,128,128,239, 11, 11, 11,
+ 240,240,128,128,128,128,241,242,128,128,128,128,128,128,243,243,
+ 128,128,128,128,128,128,128,128,128,128, 48, 48,244,244,244,244,
+ 245,245,128,128, 0, 0, 0, 0, 0, 0,128,128, 19, 19, 19, 19,
+ 128,128,128,128,246, 0,128,128, 0, 0, 0, 0, 92, 92,128,128,
+ 128,128,128,128, 0, 0,128,128, 7, 7, 7, 7, 0, 0, 0, 0,
+ 1, 2, 1, 2, 0, 0, 3, 3, 4, 5, 4, 5, 4, 4, 4, 4,
+ 4, 4, 4, 6, 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9,
+ 10, 11, 11, 11, 11, 11, 12, 11, 13, 13, 13, 13, 14, 13, 13, 13,
+ 13, 13, 13, 15, 16, 16, 16, 16, 16, 17, 18, 18, 18, 18, 18, 18,
+ 19, 20, 21, 21, 22, 23, 21, 24, 21, 21, 21, 21, 21, 25, 21, 21,
+ 26, 26, 26, 26, 26, 21, 21, 21, 27, 27, 27, 27, 28, 28, 28, 28,
+ 29, 29, 29, 29, 30, 30, 26, 21, 21, 21, 31, 21, 32, 32, 32, 32,
+ 32, 33, 34, 32, 35, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
+ 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41,
+ 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 45, 44, 44, 44, 44,
+ 46, 46, 46, 46, 47, 47, 47, 47, 47, 48, 47, 47, 49, 49, 49, 49,
+ 49, 49, 50, 50, 50, 50, 50, 51, 52, 52, 52, 52, 53, 53, 53, 53,
+ 53, 53, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, 57, 57,
+ 57, 57, 58, 57, 59, 59, 60, 61, 62, 62, 63, 63, 64, 64, 64, 64,
+ 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 55, 67, 67, 67, 67,
67, 68, 68, 68, 69, 69, 69, 69, 69, 69, 64, 64, 70, 70, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 8, 8, 8, 8, 8, 72, 72, 72, 72,
- 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75,
- 75, 76, 76, 76, 13, 50, 50, 50, 73, 77, 78, 79, 4, 4, 80, 4,
- 4, 81, 82, 83, 4, 4, 4, 84, 8, 8, 8, 8, 11, 11, 11, 11,
+ 71, 71, 71, 71, 71, 71, 71, 8, 72, 72, 72, 72, 73, 73, 73, 73,
+ 74, 74, 74, 74, 75, 75, 75, 75, 75, 76, 76, 76, 13, 50, 50, 50,
+ 73, 77, 78, 79, 4, 4, 80, 4, 4, 81, 82, 83, 4, 4, 4, 84,
11, 11, 11, 11, 85, 0, 0, 0, 0, 0, 0, 86, 0, 4, 0, 0,
0, 8, 8, 8, 0, 0, 87, 88, 89, 0, 4, 4, 6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 90, 90, 90,
90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 4, 4, 92, 92, 92, 92,
- 92, 92, 92, 92, 50, 50, 50, 93, 93, 93, 93, 93, 53, 53, 53, 53,
- 53, 53, 13, 13, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 50, 50, 50, 93, 93, 93, 93, 93, 53, 53, 13, 13, 94, 94, 94, 94,
94, 94, 94, 0, 95, 0, 96, 97, 98, 99, 99, 99, 99,100,101,102,
- 102,102,102,103,104,104,104,105, 52, 52, 52, 52, 52, 0,104,104,
- 0, 0, 0,102, 52, 52, 0, 0, 0, 0, 52,106, 0, 0, 0, 0,
- 0,102,102,107,102,102,102,102,102,108, 0, 0, 94, 94, 94, 94,
- 0, 0, 0, 0,109,109,109,109,109,109,109,109,109,109,109,109,
- 109,110,110,110,111,111,111,111,111,111,111,111,111,111,111,111,
- 13, 13, 13, 13, 13, 13,112,112,112,112,112,112, 0, 0,113, 4,
- 4, 4, 4, 4,114, 4, 4, 4, 4, 4, 4, 4,115,115,115, 0,
- 116,116,116,116,117,117,117,117,117,117, 32, 32,118,118,119,120,
- 120,120, 52, 52,121,121,121,121,122,121, 49, 49,123,123,123,123,
- 123,123, 49, 49,124,124,124,124,124,124,125,125, 53, 53, 53, 4,
- 4,126,127, 54, 54, 54, 54, 54,125,125,125,125,128,128,128,128,
- 128,128,128,128, 4,129, 18, 18, 18, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21,130, 21, 21, 21, 21, 8, 0,131, 0,
- 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21,132, 0, 0, 1, 2,
- 1, 2,133,101,102,134, 52, 52, 52, 52, 0, 0,135,135,135,135,
- 135,135,135,135, 0, 0, 0, 0, 11, 11, 11, 11, 11, 0, 11, 11,
- 11, 0, 0,136,137,137,138,138,138,138,139, 0,140,140,140,141,
- 141,142,142,142,143,143,144,144,144,144,144,144,145,145,145,145,
- 145,146,146,146,147,147,147,148,148,148,148,148,149,149,149,150,
- 150,150,150,151,151,151,151,151,151,151,151,151,152,152,152,152,
- 152,152,152,152,153,153,153,153,154,154,155,155,156,156,156,156,
- 156,156,157,157,158,158,159,159,159,159,159,159,160,160,161,161,
- 161,161,161,161,162,162,162,162,162,162,163,163,164,164,164,164,
- 165,165,165,165,166,166,166,166,167,167,168,168,169,169,169,169,
- 169,169,169,169,170,170,170,170,170,170,170,170,171,171,171,171,
- 171,171,171,171,172,172,172,172,172,172,172,172,173,173,173,173,
- 173,173,173,173,174,174,174,175,175,175,175,176,176,176,176,177,
- 177,177,178,178,179,179,179,179,179,179,179,179,180,180,180,180,
- 180,181,181,181,182,182,182,182,182,183,183,183,184,184,184,184,
- 184,184,185, 43,186,186,186,186,186,186,186,186,187,187,187,188,
- 188,188,188,188,189,189,189,190,189,189,189,189,191,191,191,191,
- 191,191,191,191,192,192,192,192,192,192,192,192,193,193,193,193,
- 193,193,193,193,194,194,194,194,194,194, 66, 66,195,195,195,195,
- 195,195,195,195,196,196,196,196,196,196,196,196,197,197,197,197,
- 197,197,197,197,198,198,198,198,198,198,198,198,199,199,199,199,
- 199,199,199,199,200,200,200,200,200,200,200,200,201,201,201,201,
- 201,202,202,202,202,202,202, 55,203,203,203,203,204,204,204,204,
- 204,204,204,205,205,205,205,205,205,205,205,205,206,206,206,206,
- 206,206,207,207,207,207,207,207,207,207,207,207,208,208,208,208,
- 208,208,208,208,110,110,110,110, 39, 39, 39, 39,209,209,209,209,
- 209,209,209,209,210,210,210,210,210,210,210,210,211,211,211,211,
- 211,211,211,211,212,212,212,212,212,212,212,212,112,112,112,112,
- 112,112,112,112,112,112,112,112,213,213,213,214,214,214,214,214,
- 214,215,215,215,216,216,216,216,216,216,216,216,217,217,217,217,
- 217,217,217,217,218,218,218,218,218,218,218,218,218,218,218,218,
- 218,218,219, 94,220,220,220,220,220,220,220,220,221,221,221,221,
- 221,221,221,221,102,102,102,102,102,102,102,102,222, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,102,102,
- 102, 99,223,224,224,224,224,224,224,224,224,224,225,225,225,225,
- 225,225,225,225,225,225, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
- 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,226,227,228, 0,229, 0,
- 0, 0, 0, 0,230,230,230,230,230,230,230,230, 91, 91, 91, 91,
- 91, 91, 91, 91,231,231,231,231,231,231,231,231,232,232,232,232,
- 233,233,233,233,234,234,234,234,234,234,234,234,235,235,235,235,
- 235,235,235,235,236, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
- 8, 8, 8, 8, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0,
- 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0,
- 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8,
- 8, 8, 8, 8, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 14, 14,
- 16, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 19, 19, 19, 19, 19,
- 20, 21, 20, 22, 20, 20, 23, 23, 20, 20, 20, 20, 22, 20, 24, 7,
- 7, 25, 20, 20, 26, 20, 20, 20, 20, 20, 20, 21, 27, 27, 27, 27,
- 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,
- 32, 20, 20, 20, 33, 33, 33, 33, 34, 35, 33, 33, 33, 36, 33, 33,
- 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40,
- 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44,
- 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 47, 48, 48, 48, 48,
- 49, 49, 49, 49, 49, 50, 51, 49, 52, 52, 52, 52, 53, 53, 53, 53,
- 53, 53, 54, 53, 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57,
- 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 61, 62,
- 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 0, 0, 66, 66, 66, 66,
- 67, 67, 67, 67, 68, 68, 68, 68, 69, 70, 71, 71, 71, 71, 71, 71,
- 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75,
- 76, 76, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79,
- 80, 80, 80, 80, 81, 81, 81, 81, 82, 7, 7, 7, 83, 7, 84, 85,
- 0, 84, 86, 0, 2, 87, 88, 2, 2, 2, 2, 89, 90, 87, 91, 2,
- 2, 2, 92, 2, 2, 2, 2, 93, 0, 0, 0, 86, 1, 0, 0, 94,
- 0, 95, 96, 0, 4, 0, 0, 0, 0, 0, 0, 4, 97, 97, 97, 97,
- 98, 98, 98, 98, 13, 13, 13, 13, 99, 99, 99, 99,100,100,100,100,
- 0,101, 0, 0,102,100,103,104, 0, 0,100, 0,105,106,106,106,
- 106,106,106,106,106,106,107,105,108,109,109,109,109,109,109,109,
- 109,109,110,108,111,111,111,111,112, 55, 55, 55, 55, 55, 55,113,
- 109,109,109,110,109,109, 0, 0,114,114,114,114,115,115,115,115,
- 116,116,116,116,117,117,117,117, 96, 2, 2, 2, 2, 2, 94, 2,
- 118,118,118,118,119,119,119,119,120,120,120,120,121,121,121,121,
- 121,121,121,122,123,123,123,123,124,124,124,124,124,124,124,125,
- 126,126,126,126,127,127,127,127,128,128,128,128, 2, 2, 3, 2,
- 2,129,130, 0,131,131,131,131,132, 17, 17, 18, 20, 20, 20,133,
- 7, 7, 7,134, 20, 20, 20, 23, 0,135,109,109,109,109,109,136,
- 137,137,137,137, 0, 0, 0,138,139,139,139,139,140,140,140,140,
- 84, 0, 0, 0,141,141,141,141,142,142,142,142,143,143,143,143,
- 144,144,144,144,145,145,145,145,146,146,146,146,147,147,147,147,
- 148,148,148,148,149,149,149,149,150,150,150,150,151,151,151,151,
- 152,152,152,152,153,153,153,153,154,154,154,154,155,155,155,155,
- 156,156,156,156,157,157,157,157,158,158,158,158,159,159,159,159,
- 160,160,160,160,161,161,161,161,162,162,162,162,163,163,163,163,
- 164,164,164,164,165,165,165,165,166,166,166,166,167,167,167,167,
- 168,168,168,168,169,169,169,169,170,170,170,170,171,171,171,171,
- 172,172,172,172,173,173,173,173,174,174,174,174,175,175,175,175,
- 176,176,176,176,177,177,177,177,178,178,178,178,179,179,179,179,
- 180,180,180,180,181,181,181,181,182,182,182,182,183,183,183,183,
- 184,184,184,184,185,185,185,185,186, 45, 45, 45,187,187,187,187,
- 188,188,188,188,189,189,189,189,190,190,190,190,190,190,191,190,
- 192,192,192,192,193,193,193,193,194,194,194,194,195,195,195,195,
- 196,196,196,196,197,197,197,197,198,198,198,198,199,199,199,199,
- 200,200,200,200,201,201,201,201,202,202,202,202,203,203,203,203,
- 204,204,204,204,205,205,205,205,206,206,206,206,207,207,207,207,
- 208,208,208,208,209,209,209,209,210,210,210,210,211,211,211,211,
- 212,212,212,212,213,213,213,213,214,214,214,214,215,215,215,215,
- 216,216,216,216,217,217,217,217,218,218,218,218,219,219,219,219,
- 220,221,221,221,222,222,222,222,221,221,221,221,223,106,106,106,
- 106,109,109,109,224,224,224,224,225,225,225,225, 0,226, 86, 0,
- 0, 0,226, 7, 82,138, 7, 0, 0, 0,227, 86,228,228,228,228,
- 229,229,229,229,230,230,230,230,231,231,231,231,232,232,232,232,
- 233,233,233,233,234, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0,
- 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9,
- 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55, 55, 55, 55, 55,
- 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4, 4, 4, 4, 4,
- 4, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 0, 3, 3,
- 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 1, 1, 1, 3, 3,
- 1, 3, 3, 3, 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64,
- 90, 90, 90, 90, 95, 95, 95, 95, 3, 3, 0, 3, 7, 7, 7, 7,
- 7, 1, 1, 1, 1, 7, 7, 7, 0, 0, 7, 7, 5, 5, 5, 5,
- 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22,
- 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36,
- 24, 24, 24, 24, 24, 24, 24, 0, 18, 18, 18, 18, 25, 25, 25, 25,
- 25, 0, 0, 0, 0, 25, 25, 25, 33, 33, 33, 33, 8, 8, 8, 8,
- 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29,
- 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 0,
- 0, 0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44, 44, 0, 0, 0,
- 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31, 32, 32, 0, 0,
- 32, 0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52,
- 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62,
- 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73,
- 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0,
- 1, 1, 0, 0, 19, 19, 9, 9, 9, 9, 9, 6, 19, 9, 9, 9,
- 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19, 19, 19, 19, 9,
- 0, 0, 0, 19, 0, 0, 9, 0, 0, 0, 19, 19, 27, 27, 27, 27,
- 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13, 0, 13, 0, 13,
- 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 0, 15, 15, 15,
- 15, 15, 15, 15, 15, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 0, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12, 0,
- 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79,
- 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69,
- 69, 69, 0, 69, 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84, 0,
- 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87, 19, 9, 19, 19,
- 19, 19, 0, 0, 2, 2, 2, 2, 19, 19, 19, 4, 3, 3, 0, 0,
- 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0, 49, 49, 49, 49,
- 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42,
- 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59,
- 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135,
- 106,106,106,106,104,104,104,104,161,161,161,161,110,110,110,110,
- 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120,116,116,116,116,
- 128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98,
- 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117,
- 112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82,
- 122,122,122,122, 89, 89, 89, 89,130,130,130,130,144,144,144,144,
- 156,156,156,156,147,147,147,147,148,148,148,148,158,158,158,158,
- 153,153,153,153,149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,
- 101,101,101,101, 96, 96, 96, 96,111,111,111,111,100,100,100,100,
- 100, 36, 36, 36,108,108,108,108,129,129,129,129,109,109,109,109,
- 107,107,107,107,107,107,107, 1,137,137,137,137,124,124,124,124,
- 123,123,123,123,114,114,114,114,102,102,102,102,126,126,126,126,
- 142,142,142,142,125,125,125,125,154,154,154,154,150,150,150,150,
- 141,141,141,141,140,140,140,140,121,121,121,121,133,133,133,133,
- 134,134,134,134,138,138,138,138,143,143,143,143,145,145,145,145,
- 63, 63, 63, 63,157,157,157,157, 80, 80, 80, 80,127,127,127,127,
- 115,115,115,115,159,159,159,159,103,103,103,103,119,119,119,119,
- 146,146,146,146, 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,
- 136,136,136,136, 17, 15, 15, 15,139,139,139,139,105,105,105,105,
- 0, 0, 0, 1, 0, 0, 1, 1,131,131,131,131,151,151,151,151,
- 160,160,160,160,152,152,152,152,113,113,113,113,132,132,132,132,
- 15, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9,
- 9, 10, 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 102,102,102,103,104,104,104,105, 52, 0,104,104, 0, 0, 0,102,
+ 52, 52, 0, 0, 0, 0, 52,106, 0,102,102,107,102,102,102,102,
+ 102,108, 0, 0,109,109,109,109,109,110,110,110,111,111,111,111,
+ 13, 13,112,112,112,112,112,112, 0, 0,113, 4,114, 4, 4, 4,
+ 115,115,115, 0,116,116,116,116,117,117,117,117,117,117, 32, 32,
+ 118,118,119,120,120,120, 52, 52,121,121,121,121,122,121, 49, 49,
+ 123,123,123,123,123,123, 49, 49,124,124,124,124,124,124,125,125,
+ 53, 53, 53, 4, 4,126,127, 54,125,125,125,125,128,128,128,128,
+ 4,129, 18, 18, 18, 21, 21, 21, 21, 21, 21,130, 8, 0,131, 0,
+ 0, 0, 0, 21, 21, 21, 21,132, 0, 0, 1, 2, 1, 2,133,101,
+ 102,134, 52, 52,135,135,135,135, 11, 0, 11, 11, 11, 0, 0,136,
+ 137,137,138,138,138,138,139, 0,140,140,140,141,141,142,142,142,
+ 143,143,144,144,144,144,144,144,145,145,145,145,145,146,146,146,
+ 147,147,147,148,148,148,148,148,149,149,149,150,150,150,150,151,
+ 151,151,151,151,152,152,152,152,153,153,153,153,154,154,155,155,
+ 156,156,156,156,156,156,157,157,158,158,159,159,159,159,159,159,
+ 160,160,161,161,161,161,161,161,162,162,162,162,162,162,163,163,
+ 164,164,164,164,165,165,165,165,166,166,166,166,167,167,168,168,
+ 169,169,169,169,170,170,170,170,171,171,171,171,172,172,172,172,
+ 173,173,173,173,173,173,173,174,175,175,175,176,176,176,176,177,
+ 177,177,177,178,178,178,179,179,180,180,180,180,181,181,181,181,
+ 181,182,182,182,183,183,183,183,183,184,184,184,185,185,185,185,
+ 185,185,186, 43,187,187,187,187,188,188,188,189,189,189,189,189,
+ 190,190,190,191,190,190,190,190,192,192,192,192,193,193,193,193,
+ 194,194,194,194,195,195,195,195,195,195, 66, 66,196,196,196,196,
+ 197,197,197,197,198,198,198,198,199,199,199,199,200,200,200,200,
+ 201,201,201,201,202,202,202,202,202,203,203,203,203,203,203, 55,
+ 204,204,204,204,205,205,205,205,205,205,205,206,206,206,206,206,
+ 207,207,207,207,207,207,208,208,208,208,208,208,209,209,209,209,
+ 210,210,210,210,110,110,110,110,211,211,211,211,212,212,212,212,
+ 213,213,213,213,214,214,214,214,215,215,215,216,216,216,216,216,
+ 216,217,217,217,218,218,218,218,219,219,219,219,220,220,220,220,
+ 220,220,221, 94,222,222,222,222,223,223,223,223,224, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99,102,225, 99,226,102,227,227,227,227,227,
+ 228,228,228,228,228,228, 0, 0, 8, 0, 0, 0, 0, 0,229,230,
+ 231, 0,232, 0,233,233,233,233, 91, 91, 91, 13,234,234,234,234,
+ 235,235,235,235,236,236,236,236,237,237,237,237,238,238,238,238,
+ 239,239,239,239,240, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2,
+ 2, 2, 3, 0, 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2,
+ 2, 2, 5, 0, 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 8, 10,
+ 8, 11, 8, 8, 8, 8, 8, 8, 12, 13, 13, 13, 14, 14, 14, 14,
+ 14, 15, 14, 14, 16, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 19,
+ 19, 19, 19, 19, 20, 21, 20, 22, 20, 20, 23, 23, 20, 20, 20, 20,
+ 22, 20, 24, 7, 7, 25, 20, 20, 26, 20, 20, 20, 20, 20, 20, 21,
+ 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30,
+ 31, 31, 31, 31, 32, 20, 20, 20, 33, 33, 33, 33, 34, 35, 33, 33,
+ 33, 36, 33, 33, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39,
+ 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43,
+ 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 47,
+ 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, 51, 49, 52, 52, 52, 52,
+ 53, 53, 53, 53, 53, 53, 54, 53, 55, 55, 55, 55, 56, 56, 56, 56,
+ 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60,
+ 60, 60, 61, 62, 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 0, 0,
+ 66, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, 68, 69, 70, 71, 71,
+ 71, 71, 71, 71, 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74,
+ 75, 75, 75, 75, 76, 76, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78,
+ 79, 79, 79, 79, 80, 80, 80, 80, 81, 81, 81, 81, 82, 7, 7, 7,
+ 83, 7, 84, 85, 0, 84, 86, 0, 2, 87, 88, 2, 2, 2, 2, 89,
+ 90, 87, 91, 2, 2, 2, 92, 2, 2, 2, 2, 93, 0, 0, 0, 86,
+ 1, 0, 0, 94, 0, 95, 96, 0, 4, 0, 0, 0, 0, 0, 0, 4,
+ 97, 97, 97, 97, 98, 98, 98, 98, 13, 13, 13, 13, 99, 99, 99, 99,
+ 100,100,100,100, 0,101, 0, 0,102,100,103,104, 0, 0,100, 0,
+ 105,106,106,106,106,106,106,106,106,106,107,105,108,109,109,109,
+ 109,109,109,109,109,109,110,108,111,111,111,111,112, 55, 55, 55,
+ 55, 55, 55,113,109,109,109,110,109,109, 0, 0,114,114,114,114,
+ 115,115,115,115,116,116,116,116,117,117,117,117, 96, 2, 2, 2,
+ 2, 2, 94, 2,118,118,118,118,119,119,119,119,120,120,120,120,
+ 121,121,121,121,121,121,121,122,123,123,123,123,124,124,124,124,
+ 124,124,124,125,126,126,126,126,127,127,127,127,128,128,128,128,
+ 2, 2, 3, 2, 2,129,130, 0,131,131,131,131,132, 17, 17, 18,
+ 20, 20, 20,133, 7, 7, 7,134, 20, 20, 20, 23, 0,135,109,109,
+ 109,109,109,136,137,137,137,137, 0, 0, 0,138,139,139,139,139,
+ 140,140,140,140, 84, 0, 0, 0,141,141,141,141,142,142,142,142,
+ 143,143,143,143,144,144,144,144,145,145,145,145,146,146,146,146,
+ 147,147,147,147,148,148,148,148,149,149,149,149,150,150,150,150,
+ 151,151,151,151,152,152,152,152,153,153,153,153,154,154,154,154,
+ 155,155,155,155,156,156,156,156,157,157,157,157,158,158,158,158,
+ 159,159,159,159,160,160,160,160,161,161,161,161,162,162,162,162,
+ 163,163,163,163,164,164,164,164,165,165,165,165,166,166,166,166,
+ 167,167,167,167,168,168,168,168,169,169,169,169,170,170,170,170,
+ 171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,174,
+ 174,174,174,175,176,176,176,176,177,177,177,177,178,178,178,178,
+ 179,179,179,179,180,180,180,180,181,181,181,181,182,182,182,182,
+ 183,183,183,183,184,184,184,184,185,185,185,185,186,186,186,186,
+ 187, 45, 45, 45,188,188,188,188,189,189,189,189,190,190,190,190,
+ 191,191,191,191,191,191,192,191,193,193,193,193,194,194,194,194,
+ 195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198,
+ 199,199,199,199,200,200,200,200,201,201,201,201,202,202,202,202,
+ 203,203,203,203,204,204,204,204,205,205,205,205,206,206,206,206,
+ 207,207,207,207,208,208,208,208,209,209,209,209,210,210,210,210,
+ 211,211,211,211,212,212,212,212,213,213,213,213,214,214,214,214,
+ 215,215,215,215,216,216,216,216,217,217,217,217,218,218,218,218,
+ 219,219,219,219,220,220,220,220,221,221,221,221,222,223,223,223,
+ 224,224,224,224,223,223,223,223,225,106,106,106,226,106,106,106,
+ 106,227,109,109,228,228,228,228,229,229,229,229, 0,230, 86, 0,
+ 0, 0,230, 7, 82,138, 7, 0, 0, 0,231, 86,232,232,232,232,
+ 233,233,233,233,234,234,234,234,235,235,235,235,236,236,236,236,
+ 237,237,237,237,238,238,238,238,239, 0, 0, 0, 0, 0, 0, 0,
+ 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0,
+ 19, 0, 0, 0, 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9,
+ 0, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55,
+ 55, 55, 55, 55, 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4,
+ 4, 4, 4, 4, 4, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3,
+ 3, 0, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 1,
+ 1, 1, 3, 3, 1, 3, 3, 3, 37, 37, 37, 37, 38, 38, 38, 38,
+ 64, 64, 64, 64, 90, 90, 90, 90, 95, 95, 95, 95, 3, 3, 0, 3,
+ 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 0, 0, 7, 7,
+ 5, 5, 5, 5, 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21,
+ 22, 22, 22, 22, 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20,
+ 36, 36, 36, 36, 24, 24, 24, 24, 24, 24, 24, 0, 18, 18, 18, 18,
+ 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, 25, 25, 33, 33, 33, 33,
+ 8, 8, 8, 8, 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30,
+ 29, 29, 29, 29, 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35,
+ 35, 35, 35, 0, 0, 0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44,
+ 44, 0, 0, 0, 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31,
+ 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48,
+ 52, 52, 52, 52, 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91,
+ 62, 62, 62, 62, 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70,
+ 73, 73, 73, 73, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0,
+ 0, 1, 0, 0, 1, 1, 0, 0, 19, 19, 9, 9, 9, 9, 9, 6,
+ 19, 9, 9, 9, 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19,
+ 19, 19, 19, 9, 0, 0, 0, 19, 0, 0, 9, 0, 0, 0, 19, 19,
+ 27, 27, 27, 27, 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13,
+ 0, 13, 0, 13, 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12,
+ 0, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, 0, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 0, 26, 26, 26, 26, 26, 12, 12, 12,
+ 12, 12, 12, 0, 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77,
+ 79, 79, 79, 79, 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75,
+ 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 84, 84, 84, 84,
+ 84, 84, 84, 0, 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87,
+ 19, 9, 19, 19, 19, 19, 0, 0, 2, 2, 2, 2, 19, 19, 19, 4,
+ 3, 3, 0, 0, 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0,
+ 49, 49, 49, 49, 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67,
+ 42, 42, 42, 42, 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53,
+ 59, 59, 59, 59, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,
+ 135,135,135,135,106,106,106,106,104,104,104,104,161,161,161,161,
+ 110,110,110,110, 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120,
+ 116,116,116,116,128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72,
+ 98, 98, 98, 98, 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88,
+ 117,117,117,117,112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83,
+ 82, 82, 82, 82,122,122,122,122, 89, 89, 89, 89,130,130,130,130,
+ 144,144,144,144,156,156,156,156,156, 3, 3, 3,147,147,147,147,
+ 148,148,148,148,158,158,158,158,153,153,153,153,149,149,149,149,
+ 94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101, 96, 96, 96, 96,
+ 111,111,111,111,100,100,100,100,100, 36, 36, 36,108,108,108,108,
+ 129,129,129,129,109,109,109,109,107,107,107,107,107,107,107, 1,
+ 137,137,137,137,124,124,124,124,123,123,123,123,114,114,114,114,
+ 102,102,102,102,126,126,126,126,142,142,142,142,125,125,125,125,
+ 154,154,154,154,150,150,150,150,141,141,141,141,140,140,140,140,
+ 121,121,121,121,133,133,133,133,134,134,134,134,138,138,138,138,
+ 143,143,143,143,145,145,145,145,163,163,163,163, 63, 63, 63, 63,
+ 157,157,157,157, 80, 80, 80, 80,127,127,127,127,115,115,115,115,
+ 159,159,159,159,103,103,103,103,119,119,119,119,146,146,146,146,
+ 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,136,136,136,136,
+ 17, 15, 15, 15, 17, 17, 15, 15, 15, 17, 17, 17,139,139,139,139,
+ 105,105,105,105, 0, 0, 0, 1, 0, 0, 1, 1,131,131,131,131,
+ 151,151,151,151,160,160,160,160,152,152,152,152,164,164,164,164,
+ 113,113,113,113,132,132,132,132, 15, 0, 0, 0, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13, 9, 9,
+ 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 16, 17, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, 20, 9,
- 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
@@ -6479,60 +5219,60 @@ _hb_ucd_u8[13602] =
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30,
- 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37,
- 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42,
+ 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0,
+ 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, 0, 34,
+ 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 45,
+ 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, 0, 49,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51,
+ 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59,
+ 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47,
- 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0,
- 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0,
- 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0,
- 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, 70, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0,
+ 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0,110, 0,
+ 111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118,119,
+ 120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,
- 101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0,
- 0, 0,108, 0,109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,
- 115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131,132,133,
+ 134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,
+ 150,151,152,153,154,155,156,157, 0, 0, 0,158,159,160,161, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,118,119,120,121, 0,122,123,124,125,126,
- 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,128,129,130,131,132,133,134,135,136,137,138,139,140,141,
- 142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,
- 0, 0, 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0,
- 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,165, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0,
+ 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,169,
+ 170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,175,176,177,178,
+ 179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,
+ 195,196,197,198,199,200,201,202,203,204,205,206, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,169,170, 0, 0, 0, 0,171,172, 0,
- 0, 0,173,174,175,176,177,178,179,180,181,182,183,184,185,186,
- 187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,
- 203,204,205,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
- 3, 4,
+ 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
};
static const uint16_t
-_hb_ucd_u16[4888] =
+_hb_ucd_u16[4920] =
{
0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12,
13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23,
@@ -6599,39 +5339,41 @@ _hb_ucd_u16[4888] =
359, 47, 47, 360, 145, 66, 47, 361, 47, 362, 145, 145, 363, 47, 364, 66,
47, 47, 47, 365, 47, 366, 47, 366, 47, 365, 144, 145, 145, 145, 145, 145,
9, 9, 9, 9, 11, 11, 11, 367, 47, 47, 368, 160, 160, 160, 160, 160,
- 145, 145, 145, 145, 145, 145, 145, 145, 47, 47, 369, 47, 47, 47, 47, 47,
+ 145, 145, 145, 145, 145, 145, 145, 145, 47, 47, 369, 47, 47, 47, 47, 143,
47, 362, 370, 47, 60, 371, 66, 47, 372, 66, 66, 47, 373, 145, 47, 47,
374, 47, 47, 360, 375, 376, 377, 378, 180, 47, 47, 379, 380, 47, 47, 160,
97, 47, 381, 382, 383, 47, 47, 384, 180, 47, 47, 385, 386, 387, 388, 145,
- 47, 47, 389, 390, 32, 32, 32, 32, 47, 47, 365, 47, 47, 391, 172, 160,
+ 47, 47, 389, 390, 359, 32, 32, 32, 47, 47, 365, 47, 47, 391, 172, 160,
92, 47, 47, 113, 392, 393, 394, 32, 47, 47, 47, 395, 396, 397, 47, 47,
47, 47, 47, 398, 399, 160, 160, 160, 47, 47, 400, 401, 402, 403, 32, 32,
47, 47, 47, 404, 405, 160, 66, 66, 47, 47, 406, 407, 160, 160, 160, 160,
47, 143, 408, 409, 47, 47, 47, 47, 47, 47, 389, 410, 66, 66, 66, 66,
9, 9, 9, 9, 11, 11, 128, 411, 47, 47, 47, 412, 413, 160, 160, 160,
47, 47, 47, 47, 47, 414, 415, 416, 417, 47, 47, 418, 419, 420, 47, 47,
- 421, 422, 66, 47, 47, 47, 47, 47, 47, 47, 400, 423, 424, 128, 145, 425,
- 47, 156, 426, 427, 32, 32, 32, 32, 47, 47, 47, 359, 428, 160, 47, 47,
- 429, 430, 160, 160, 160, 160, 160, 160, 47, 47, 47, 47, 47, 47, 47, 431,
- 47, 47, 47, 47, 145, 432, 433, 434, 219, 219, 219, 219, 219, 219, 219, 66,
- 47, 47, 47, 47, 47, 47, 47, 424, 47, 47, 47, 208, 208, 208, 208, 208,
- 47, 47, 47, 47, 47, 47, 305, 47, 47, 47, 47, 47, 160, 47, 47, 435,
- 47, 47, 47, 436, 437, 438, 439, 47, 9, 9, 9, 9, 9, 9, 11, 11,
- 145, 440, 66, 66, 66, 66, 66, 66, 47, 47, 47, 47, 391, 441, 416, 416,
- 442, 443, 27, 27, 27, 27, 444, 416, 47, 445, 208, 208, 208, 208, 208, 208,
- 32, 32, 32, 32, 32, 146, 146, 146, 146, 146, 146, 146, 146, 146, 446, 447,
- 448, 146, 449, 146, 146, 146, 146, 146, 146, 146, 146, 146, 450, 146, 146, 146,
- 9, 451, 11, 452, 453, 11, 196, 9, 454, 455, 9, 456, 11, 9, 451, 11,
- 452, 453, 11, 196, 9, 454, 455, 9, 456, 11, 9, 451, 11, 452, 453, 11,
- 196, 9, 454, 455, 9, 456, 11, 9, 451, 11, 196, 9, 457, 458, 459, 460,
- 11, 461, 9, 462, 463, 464, 465, 11, 466, 9, 467, 11, 468, 160, 160, 160,
- 32, 32, 32, 469, 32, 32, 470, 471, 472, 473, 32, 32, 32, 32, 32, 32,
- 474, 11, 11, 11, 11, 11, 11, 11, 32, 32, 32, 32, 32, 32, 32, 32,
- 47, 47, 47, 475, 476, 146, 146, 146, 47, 47, 477, 32, 47, 47, 478, 479,
- 47, 47, 47, 47, 355, 32, 32, 32, 9, 9, 454, 11, 480, 305, 66, 66,
- 145, 145, 481, 482, 145, 145, 145, 145, 145, 145, 483, 145, 145, 145, 145, 145,
- 47, 47, 47, 47, 47, 47, 47, 226, 484, 146, 146, 146, 146, 146, 146, 146,
- 146, 146, 146, 146, 146, 146, 146, 485, 146, 146, 146, 146, 146, 146, 146, 160,
+ 421, 422, 66, 47, 47, 47, 47, 47, 66, 66, 66, 66, 66, 66, 66, 66,
+ 47, 47, 400, 423, 424, 128, 145, 425, 47, 156, 426, 427, 32, 32, 32, 32,
+ 47, 47, 47, 359, 428, 160, 47, 47, 429, 430, 160, 160, 160, 160, 160, 160,
+ 47, 47, 47, 47, 47, 47, 47, 431, 432, 47, 47, 433, 434, 160, 160, 160,
+ 47, 47, 47, 47, 145, 435, 436, 437, 219, 219, 219, 219, 219, 219, 219, 66,
+ 47, 47, 47, 47, 47, 47, 47, 424, 47, 47, 47, 208, 438, 32, 32, 32,
+ 47, 47, 47, 47, 47, 47, 305, 47, 47, 47, 47, 47, 160, 47, 47, 439,
+ 47, 47, 47, 440, 441, 442, 443, 47, 9, 9, 9, 9, 9, 9, 11, 11,
+ 145, 444, 66, 66, 66, 66, 66, 66, 47, 47, 47, 47, 391, 445, 416, 416,
+ 446, 447, 27, 27, 27, 27, 448, 416, 47, 449, 208, 208, 208, 208, 208, 208,
+ 32, 32, 32, 32, 32, 146, 146, 146, 146, 146, 146, 146, 146, 146, 450, 451,
+ 452, 146, 453, 146, 146, 146, 146, 146, 146, 146, 146, 146, 454, 146, 146, 146,
+ 9, 455, 11, 456, 457, 11, 196, 9, 458, 459, 9, 460, 11, 9, 455, 11,
+ 456, 457, 11, 196, 9, 458, 459, 9, 460, 11, 9, 455, 11, 456, 457, 11,
+ 196, 9, 458, 459, 9, 460, 11, 9, 455, 11, 196, 9, 461, 462, 463, 464,
+ 11, 465, 9, 466, 467, 468, 469, 11, 470, 9, 471, 11, 472, 160, 160, 160,
+ 32, 32, 32, 473, 32, 32, 474, 475, 476, 477, 32, 32, 32, 32, 32, 32,
+ 478, 11, 11, 11, 11, 11, 11, 11, 32, 32, 32, 27, 27, 27, 27, 27,
+ 32, 32, 32, 32, 32, 32, 32, 32, 47, 47, 47, 479, 480, 146, 146, 146,
+ 47, 47, 481, 32, 47, 47, 482, 483, 47, 47, 47, 47, 47, 47, 484, 160,
+ 47, 47, 47, 47, 355, 32, 32, 32, 9, 9, 458, 11, 485, 305, 66, 66,
+ 145, 145, 486, 487, 145, 145, 145, 145, 145, 145, 488, 145, 145, 145, 145, 145,
+ 47, 47, 47, 47, 47, 47, 47, 226, 489, 146, 146, 146, 146, 146, 146, 146,
+ 146, 146, 146, 146, 146, 146, 146, 490, 146, 146, 146, 146, 146, 146, 146, 160,
208, 208, 208, 208, 208, 208, 208, 208, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 939, 940, 941, 942, 946, 948, 0, 962,
969, 970, 971, 976,1001,1002,1003,1008, 0,1033,1040,1041,1042,1043,1047, 0,
@@ -6842,32 +5584,25 @@ _hb_ucd_u16[4888] =
817, 818, 819, 820, 821, 935, 0, 0,
};
static const int16_t
-_hb_ucd_i16[196] =
+_hb_ucd_i16[92] =
{
- 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2,
- 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1,
- 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3,
- -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0,
- 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0,
- 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0,
- 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0,
- 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0,
- 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1,
- -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0,
- 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106,
- -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1,
- -1, 0, 1, -1,
+ 0, 0, 1, -1, 2, 0, -2, 0, 0, 2, 0, -2, 0, 16, 0, -16,
+ 0, 1, -1, 0, 3, 3, 3, -3, -3, -3, 0, 2016, 0, 2527, 1923, 1914,
+ 1918, 0, 2250, 0, 0, 138, 0, 7, -7, 0, -1, 1, 1824, 0, 2104, 0,
+ 2108, 2106, 0, 2106, 1316, 0, -1, -138, 8, 8, 8, 0, 7, 7, -8, -8,
+ -8, -7,-1316, 1, -1, 3, -3, 1, 0,-1914,-1918, 0, 0,-1923,-1824, 0,
+ 0,-2016,-2104, 0, 0,-2106,-2108,-2106,-2250, 0,-2527, 0,
};
static inline uint_fast8_t
_hb_ucd_gc (unsigned u)
{
- return u<1114112u?_hb_ucd_u8[5056+(((_hb_ucd_u8[1168+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+ return u<1114112u?_hb_ucd_u8[5080+(((_hb_ucd_u8[1152+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
}
static inline uint_fast8_t
_hb_ucd_ccc (unsigned u)
{
- return u<125259u?_hb_ucd_u8[6970+(((_hb_ucd_u8[6426+(((_hb_ucd_u8[5982+(((_hb_ucd_u8[5646+(((_hb_ucd_u8[5400+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+ return u<125259u?_hb_ucd_u8[7038+(((_hb_ucd_u8[6482+(((_hb_ucd_u8[6022+(((_hb_ucd_u8[5670+(((_hb_ucd_u8[5424+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
}
static inline unsigned
_hb_ucd_b4 (const uint8_t* a, unsigned i)
@@ -6877,17 +5612,17 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i)
static inline int_fast16_t
_hb_ucd_bmg (unsigned u)
{
- return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7714+(((_hb_ucd_u8[7594+(((_hb_ucd_b4(7466+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
+ return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7930+(((_hb_ucd_u8[7698+(((_hb_ucd_u8[7602+(((_hb_ucd_b4(7538+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
}
static inline uint_fast8_t
_hb_ucd_sc (unsigned u)
{
- return u<918016u?_hb_ucd_u8[11480+(((_hb_ucd_u8[10532+(((_hb_ucd_u8[9124+(((_hb_ucd_u8[8500+(((_hb_ucd_u8[8050+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
+ return u<918016u?_hb_ucd_u8[11228+(((_hb_ucd_u8[10264+(((_hb_ucd_u8[9276+(((_hb_ucd_u8[8596+(((_hb_ucd_u8[8292+(((_hb_ucd_u8[8178+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
}
static inline uint_fast16_t
_hb_ucd_dm (unsigned u)
{
- return u<195102u?_hb_ucd_u16[1576+(((_hb_ucd_u8[12802+(((_hb_ucd_u8[12420+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+ return u<195102u?_hb_ucd_u16[1608+(((_hb_ucd_u8[12570+(((_hb_ucd_u8[12188+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
}
#endif
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ucd.cc b/src/3rdparty/harfbuzz-ng/src/hb-ucd.cc
index baea224a25..4c8b1ee5e6 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ucd.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ucd.cc
@@ -129,12 +129,16 @@ hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
void *user_data HB_UNUSED)
{
+ // Hangul is handled algorithmically.
if (_hb_ucd_compose_hangul (a, b, ab)) return true;
hb_codepoint_t u = 0;
if ((a & 0xFFFFF800u) == 0x0000u && (b & 0xFFFFFF80) == 0x0300u)
{
+ /* If "a" is small enough and "b" is in the U+0300 range,
+ * the composition data is encoded in a 32bit array sorted
+ * by "a,b" pair. */
uint32_t k = HB_CODEPOINT_ENCODE3_11_7_14 (a, b, 0);
const uint32_t *v = hb_bsearch (k,
_hb_ucd_dm2_u32_map,
@@ -146,6 +150,8 @@ hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
}
else
{
+ /* Otherwise it is stored in a 64bit array sorted by
+ * "a,b" pair. */
uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0);
const uint64_t *v = hb_bsearch (k,
_hb_ucd_dm2_u64_map,
@@ -170,15 +176,22 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
unsigned i = _hb_ucd_dm (ab);
+ /* If no data, there's no decomposition. */
if (likely (!i)) return false;
i--;
+ /* Check if it's a single-character decomposition. */
if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map))
{
+ /* Single-character decompositions currently are only in plane 0 or plane 2. */
if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map))
+ {
+ /* Plane 0. */
*a = _hb_ucd_dm1_p0_map[i];
+ }
else
{
+ /* Plane 2. */
i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map);
*a = 0x20000 | _hb_ucd_dm1_p2_map[i];
}
@@ -187,8 +200,10 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
}
i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map);
+ /* Otherwise they are encoded either in a 32bit array or a 64bit array. */
if (i < ARRAY_LENGTH (_hb_ucd_dm2_u32_map))
{
+ /* 32bit array. */
uint32_t v = _hb_ucd_dm2_u32_map[i];
*a = HB_CODEPOINT_DECODE3_11_7_14_1 (v);
*b = HB_CODEPOINT_DECODE3_11_7_14_2 (v);
@@ -196,6 +211,7 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
}
i -= ARRAY_LENGTH (_hb_ucd_dm2_u32_map);
+ /* 64bit array. */
uint64_t v = _hb_ucd_dm2_u64_map[i];
*a = HB_CODEPOINT_DECODE3_1 (v);
*b = HB_CODEPOINT_DECODE3_2 (v);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode-emoji-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-unicode-emoji-table.hh
index c216379201..13b1c4b1d4 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-unicode-emoji-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode-emoji-table.hh
@@ -6,16 +6,16 @@
*
* on file with this header:
*
- * # emoji-data-14.0.0.txt
- * # Date: 2021-08-26, 17:22:22 GMT
- * # © 2021 Unicode®, Inc.
+ * # emoji-data.txt
+ * # Date: 2022-08-02, 00:26:10 GMT
+ * # © 2022 Unicode®, Inc.
* # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
- * # For terms of use, see http://www.unicode.org/terms_of_use.html
+ * # For terms of use, see https://www.unicode.org/terms_of_use.html
* #
* # Emoji Data for UTS #51
- * # Used with Emoji Version 14.0 and subsequent minor revisions (if any)
+ * # Used with Emoji Version 15.0 and subsequent minor revisions (if any)
* #
- * # For documentation and usage, see http://www.unicode.org/reports/tr51
+ * # For documentation and usage, see https://www.unicode.org/reports/tr51
*/
#ifndef HB_UNICODE_EMOJI_TABLE_HH
@@ -24,42 +24,37 @@
#include "hb-unicode.hh"
static const uint8_t
-_hb_emoji_u8[544] =
+_hb_emoji_u8[464] =
{
16, 17, 17, 17, 50, 20, 21, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,118,152,
- 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 3, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 6, 0, 7, 8,
- 0, 0, 0, 9, 0, 0, 10, 11, 12, 13, 14, 13, 15, 16, 17, 0,
- 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 19, 20, 0, 0,
- 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0,
- 13, 13, 13, 13, 23, 24, 25, 26, 27, 28, 13, 13, 13, 13, 13, 29,
- 13, 13, 13, 13, 30, 31, 13, 13, 13, 32, 13, 13, 0, 33, 0, 34,
- 35, 36, 37, 13, 38, 39, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 30,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 16, 0, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 4, 0, 0, 2, 0, 0,240, 3, 0, 6, 0, 0,
- 0, 0, 0, 12, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
- 0,128, 0, 0, 0,254, 15, 7, 4, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0, 0, 0, 0,120,
- 191,255,247,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 63, 0,255,255,255,255,255,255, 63,255, 87, 32, 2, 1, 24, 0,
- 144, 80,184, 0,248, 0, 0, 0, 0, 0,224, 0, 2, 0, 1,128,
- 0, 0, 0, 0, 0, 0, 48, 0,224, 0, 0, 24, 0, 0, 0, 0,
- 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32,
- 0, 0,128, 2, 0, 0, 0, 0, 0,224, 0, 0, 0,128, 0, 0,
- 0, 0, 0, 0, 0,240, 3,192, 0, 64,254, 7, 0,224,255,255,
- 255,255,255,255, 63, 0, 0, 0,254,255, 0, 4, 0,128,252,247,
- 0,254,255,255,255,255,255,255,255,255,255,255,255,255,255, 7,
- 255,255,255,255,255,255,255, 63,192,255,255,255,255,255,255,255,
- 255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,255,
- 0, 0,224,255,255,255,255,255, 0,240, 0, 0, 0, 0, 0, 0,
- 0,255, 0,252, 0, 0, 0, 0, 0,255, 0, 0, 0,192,255,255,
- 0,240,255,255,255,255,255,247,191,255,255,255,255,255,255,255,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 3, 4, 0, 0, 5, 6, 0, 7, 0, 8, 9, 10, 11, 12,
+ 0, 0, 13, 0, 0, 0, 14, 0, 15, 0, 0, 0, 0, 16, 0, 0,
+ 17, 17, 18, 19, 20, 17, 17, 21, 17, 17, 22, 17, 23, 17, 24, 25,
+ 26, 27, 28, 17, 17, 17, 0, 0, 17, 17, 17, 17, 17, 17, 17, 29,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 4, 0, 0,
+ 5, 6, 0, 0, 7, 8, 0, 0, 8, 0, 9, 10, 0, 0, 11, 0,
+ 0, 12, 13, 14, 15, 16, 16, 16, 17, 16, 16, 16, 18, 19, 20, 21,
+ 22, 23, 0, 0, 0, 24, 0, 0, 25, 0, 26, 0, 0, 27, 0, 0,
+ 28, 0, 0, 0, 16, 16, 16, 16, 29, 9, 0, 30, 31, 32, 16, 33,
+ 34, 35, 36, 16, 16, 16, 16, 37, 16, 38, 39, 16, 16, 16, 40, 0,
+ 0, 0, 0, 41, 0, 0, 42, 16, 43, 0, 44, 0, 45, 46, 16, 16,
+ 47, 48, 49, 16, 16, 16, 16, 38, 0, 0, 0, 0, 0, 66, 0, 0,
+ 0, 0, 0, 16, 0, 2, 0, 0, 4, 0, 0, 2, 0, 0,240, 3,
+ 0, 6, 0, 0, 0, 0, 0, 12, 0, 1, 0, 0, 0,128, 0, 0,
+ 0,254, 15, 7, 4, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0,
+ 0, 0, 0,120,191,255,247,255,255,255,255,255, 63, 0,255,255,
+ 63,255, 87, 32, 2, 1, 24, 0,144, 80,184, 0,248, 0, 0, 0,
+ 0, 0,224, 0, 2, 0, 1,128, 0, 0, 48, 0,224, 0, 0, 24,
+ 0, 0, 33, 0, 0, 0, 1, 32, 0, 0,128, 2, 0,224, 0, 0,
+ 0,240, 3,192, 0, 64,254, 7, 0,224,255,255, 63, 0, 0, 0,
+ 254,255, 0, 4, 0,128,252,247, 0,254,255,255,255,255,255, 7,
+ 255,255,255, 63,192,255,255,255,255,255, 0, 0, 0, 0,240,255,
+ 0, 0,224,255, 0,240, 0, 0, 0,255, 0,252, 0,255, 0, 0,
+ 0,192,255,255, 0,240,255,255,255,255,255,247,191,255,255,255,
};
static inline unsigned
@@ -75,7 +70,7 @@ _hb_emoji_b1 (const uint8_t* a, unsigned i)
static inline uint_fast8_t
_hb_emoji_is_Extended_Pictographic (unsigned u)
{
- return u<131070u?_hb_emoji_b1(224+_hb_emoji_u8,((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>6>>4))<<4)+((u>>6)&15u))])<<6)+((u)&63u)):0;
+ return u<131070u?_hb_emoji_b1(264+_hb_emoji_u8,((_hb_emoji_u8[144+(((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>5>>2>>3))<<3)+((u>>5>>2)&7u))])<<2)+((u>>5)&3u))])<<5)+((u)&31u)):0;
}
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
index 83ead6398b..aa2735bedb 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc
@@ -165,11 +165,11 @@ 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
/**
- * hb_unicode_funcs_create: (Xconstructor)
+ * hb_unicode_funcs_create:
* @parent: (nullable): Parent Unicode-functions structure
*
* Creates a new #hb_unicode_funcs_t structure of Unicode functions.
@@ -281,7 +281,7 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
*
* Attaches a user-data key/data pair to the specified Unicode-functions structure.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -308,8 +308,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
* Since: 0.9.2
**/
void *
-hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
- hb_user_data_key_t *key)
+hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key)
{
return hb_object_get_user_data (ufuncs, key);
}
@@ -340,7 +340,7 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
* Tests whether the specified Unicode-functions structure
* is immutable.
*
- * Return value: %true if @ufuncs is immutable, %false otherwise
+ * Return value: `true` if @ufuncs is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -377,20 +377,30 @@ hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t *ufuncs, \
hb_destroy_func_t destroy) \
{ \
if (hb_object_is_immutable (ufuncs)) \
- return; \
+ goto fail; \
+ \
+ if (!func) \
+ { \
+ if (destroy) \
+ destroy (user_data); \
+ destroy = nullptr; \
+ user_data = ufuncs->parent->user_data.name; \
+ } \
\
if (ufuncs->destroy.name) \
ufuncs->destroy.name (ufuncs->user_data.name); \
\
- if (func) { \
+ if (func) \
ufuncs->func.name = func; \
- ufuncs->user_data.name = user_data; \
- ufuncs->destroy.name = destroy; \
- } else { \
+ else \
ufuncs->func.name = ufuncs->parent->func.name; \
- ufuncs->user_data.name = ufuncs->parent->user_data.name; \
- ufuncs->destroy.name = nullptr; \
- } \
+ ufuncs->user_data.name = user_data; \
+ ufuncs->destroy.name = destroy; \
+ return; \
+ \
+fail: \
+ if (destroy) \
+ destroy (user_data); \
}
HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
@@ -421,7 +431,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
* Calls the composition function of the specified
* Unicode-functions structure @ufuncs.
*
- * Return value: %true if @a and @b composed, %false otherwise
+ * Return value: `true` if @a and @b composed, `false` otherwise
*
* Since: 0.9.2
**/
@@ -446,7 +456,7 @@ hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
* Calls the decomposition function of the specified
* Unicode-functions structure @ufuncs.
*
- * Return value: %true if @ab was decomposed, %false otherwise
+ * Return value: `true` if @ab was decomposed, `false` otherwise
*
* Since: 0.9.2
**/
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode.h b/src/3rdparty/harfbuzz-ng/src/hb-unicode.h
index c04ee15a09..faa8d67924 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-unicode.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode.h
@@ -317,8 +317,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
HB_EXTERN void *
-hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
- hb_user_data_key_t *key);
+hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key);
HB_EXTERN void
@@ -429,7 +429,7 @@ typedef hb_script_t (*hb_unicode_script_func_t) (hb_unicode_funcs_t *ufuncs,
* The method must return an #hb_bool_t indicating the success
* of the composition.
*
- * Return value: %true is @a,@b composed, %false otherwise
+ * Return value: `true` is @a,@b composed, `false` otherwise
*
**/
typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs,
@@ -453,7 +453,7 @@ typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs,
* output parameters (if successful). The method must return an
* #hb_bool_t indicating the success of the composition.
*
- * Return value: %true if @ab decomposed, %false otherwise
+ * Return value: `true` if @ab decomposed, `false` otherwise
*
**/
typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs,
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode.hh b/src/3rdparty/harfbuzz-ng/src/hb-unicode.hh
index 4c28bb0cdf..39aaee5baa 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-unicode.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode.hh
@@ -105,12 +105,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
unsigned int
modified_combining_class (hb_codepoint_t u)
{
- /* XXX This hack belongs to the USE shaper (for Tai Tham):
- * Reorder SAKOT to ensure it comes after any tone marks. */
+ /* Reorder SAKOT to ensure it comes after any tone marks. */
if (unlikely (u == 0x1A60u)) return 254;
-
- /* XXX This hack belongs to the Tibetan shaper:
- * Reorder PADMA to ensure it comes after any vowel marks. */
+ /* Reorder PADMA to ensure it comes after any vowel marks. */
if (unlikely (u == 0x0FC6u)) return 254;
/* Reorder TSA -PHRU to reorder before U+0F74 */
if (unlikely (u == 0x0F39u)) return 127;
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc b/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc
index 50f71ce9ce..9648e02663 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-uniscribe.cc
@@ -355,7 +355,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
return nullptr;
}
- memcpy(new_sfnt_data, orig_sfnt_data, length);
+ hb_memcpy(new_sfnt_data, orig_sfnt_data, length);
OT::name &name = StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
name.format = 0;
@@ -478,11 +478,11 @@ populate_log_font (LOGFONTW *lf,
hb_font_t *font,
unsigned int font_size)
{
- memset (lf, 0, sizeof (*lf));
+ hb_memset (lf, 0, sizeof (*lf));
lf->lfHeight = - (int) font_size;
lf->lfCharSet = DEFAULT_CHARSET;
- memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName));
+ hb_memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName));
return true;
}
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 6c7d32e49d..58d467a405 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-vector.hh
@@ -29,12 +29,13 @@
#include "hb.hh"
#include "hb-array.hh"
+#include "hb-meta.hh"
#include "hb-null.hh"
template <typename Type,
bool sorted=false>
-struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty_t>::type
+struct hb_vector_t
{
typedef Type item_t;
static constexpr unsigned item_size = hb_static_size (Type);
@@ -44,7 +45,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
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);
}
@@ -52,14 +53,16 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
hb_requires (hb_is_iterable (Iterable))>
hb_vector_t (const Iterable &o) : hb_vector_t ()
{
- if (hb_iter (o).is_random_access_iterator)
- alloc (hb_len (hb_iter (o)));
- hb_copy (o, *this);
+ auto iter = hb_iter (o);
+ if (iter.is_random_access_iterator)
+ alloc (hb_len (iter), true);
+ hb_copy (iter, *this);
}
hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
{
- alloc (o.length);
- hb_copy (o, *this);
+ alloc (o.length, true);
+ if (unlikely (in_error ())) return;
+ copy_vector (o);
}
hb_vector_t (hb_vector_t &&o)
{
@@ -70,9 +73,8 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
~hb_vector_t () { fini (); }
- private:
- int allocated = 0; /* == -1 means allocation failed. */
public:
+ int allocated = 0; /* == -1 means allocation failed. */
unsigned int length = 0;
public:
Type *arrayZ = nullptr;
@@ -82,6 +84,9 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
allocated = length = 0;
arrayZ = nullptr;
}
+ void init0 ()
+ {
+ }
void fini ()
{
@@ -93,7 +98,11 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
void reset ()
{
if (unlikely (in_error ()))
- allocated = length; // Big hack!
+ /* Big Hack! We don't know the true allocated size before
+ * an allocation failure happened. But we know it was at
+ * least as big as length. Restore it to that and continue
+ * as if error did not happen. */
+ allocated = length;
resize (0);
}
@@ -107,8 +116,11 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
hb_vector_t& operator = (const hb_vector_t &o)
{
reset ();
- alloc (o.length);
- hb_copy (o, *this);
+ alloc (o.length, true);
+ if (unlikely (in_error ())) return *this;
+
+ copy_vector (o);
+
return *this;
}
hb_vector_t& operator = (hb_vector_t &&o)
@@ -118,7 +130,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
hb_bytes_t as_bytes () const
- { return hb_bytes_t ((const char *) arrayZ, length * item_size); }
+ { return hb_bytes_t ((const char *) arrayZ, get_size ()); }
bool operator == (const hb_vector_t &o) const { return as_array () == o.as_array (); }
bool operator != (const hb_vector_t &o) const { return !(*this == o); }
@@ -160,14 +172,10 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
- c_array_t sub_array (unsigned int start_offset, unsigned int count) const
- { return as_array ().sub_array (start_offset, count); }
- c_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
- { return as_array ().sub_array (start_offset, count); }
- array_t sub_array (unsigned int start_offset, unsigned int count)
- { return as_array ().sub_array (start_offset, count); }
- array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
- { return as_array ().sub_array (start_offset, count); }
+ /* Faster range-based for loop. */
+ Type *begin () const { return arrayZ; }
+ Type *end () const { return arrayZ + length; }
+
hb_sorted_array_t<Type> as_sorted_array ()
{ return hb_sorted_array (arrayZ, length); }
@@ -184,12 +192,14 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
{
if (unlikely (!resize (length + 1)))
return &Crap (Type);
- return &arrayZ[length - 1];
+ return std::addressof (arrayZ[length - 1]);
}
- template <typename T>
+ template <typename T,
+ typename T2 = Type,
+ hb_enable_if (!std::is_copy_constructible<T2>::value &&
+ std::is_copy_assignable<T>::value)>
Type *push (T&& v)
{
- /* TODO Emplace? */
Type *p = push ();
if (p == &Crap (Type))
// If push failed to allocate then don't copy v, since this may cause
@@ -199,39 +209,63 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
*p = std::forward<T> (v);
return p;
}
+ template <typename T,
+ typename T2 = Type,
+ hb_enable_if (std::is_copy_constructible<T2>::value)>
+ Type *push (T&& v)
+ {
+ if (unlikely (!alloc (length + 1)))
+ // If push failed to allocate then don't copy v, since this may cause
+ // the created copy to leak memory since we won't have stored a
+ // reference to it.
+ return &Crap (Type);
+
+ /* Emplace. */
+ length++;
+ Type *p = std::addressof (arrayZ[length - 1]);
+ return new (p) Type (std::forward<T> (v));
+ }
bool in_error () const { return allocated < 0; }
template <typename T = Type,
- hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (hb_is_trivially_copy_assignable(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,
- hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (!hb_is_trivially_copy_assignable(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))
{
for (unsigned i = 0; i < length; i++)
+ {
new (std::addressof (new_array[i])) Type ();
- for (unsigned i = 0; i < (unsigned) length; i++)
new_array[i] = std::move (arrayZ[i]);
- unsigned old_length = length;
- shrink_vector (0);
- length = old_length;
+ arrayZ[i].~Type ();
+ }
hb_free (arrayZ);
}
return new_array;
}
template <typename T = Type,
- hb_enable_if (std::is_trivially_constructible<T>::value ||
- !std::is_default_constructible<T>::value)>
+ hb_enable_if (hb_is_trivially_constructible(T))>
void
grow_vector (unsigned size)
{
@@ -239,8 +273,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
length = size;
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_constructible<T>::value &&
- std::is_default_constructible<T>::value)>
+ hb_enable_if (!hb_is_trivially_constructible(T))>
void
grow_vector (unsigned size)
{
@@ -252,14 +285,50 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
template <typename T = Type,
- hb_enable_if (std::is_trivially_destructible<T>::value)>
+ hb_enable_if (hb_is_trivially_copyable (T))>
void
- shrink_vector (unsigned size)
+ copy_vector (const hb_vector_t &other)
{
- length = size;
+ length = other.length;
+#ifndef HB_OPTIMIZE_SIZE
+ if (sizeof (T) >= sizeof (long long))
+ /* This runs faster because of alignment. */
+ for (unsigned i = 0; i < length; i++)
+ arrayZ[i] = other.arrayZ[i];
+ else
+#endif
+ hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_destructible<T>::value)>
+ hb_enable_if (!hb_is_trivially_copyable (T) &&
+ std::is_copy_constructible<T>::value)>
+ void
+ copy_vector (const hb_vector_t &other)
+ {
+ length = 0;
+ while (length < other.length)
+ {
+ length++;
+ new (std::addressof (arrayZ[length - 1])) Type (other.arrayZ[length - 1]);
+ }
+ }
+ template <typename T = Type,
+ hb_enable_if (!hb_is_trivially_copyable (T) &&
+ !std::is_copy_constructible<T>::value &&
+ std::is_default_constructible<T>::value &&
+ std::is_copy_assignable<T>::value)>
+ void
+ copy_vector (const hb_vector_t &other)
+ {
+ length = 0;
+ while (length < other.length)
+ {
+ length++;
+ new (std::addressof (arrayZ[length - 1])) Type ();
+ arrayZ[length - 1] = other.arrayZ[length - 1];
+ }
+ }
+
void
shrink_vector (unsigned size)
{
@@ -270,17 +339,6 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
}
- template <typename T = Type,
- hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
- void
- shift_down_vector (unsigned i)
- {
- memmove (static_cast<void *> (&arrayZ[i - 1]),
- static_cast<void *> (&arrayZ[i]),
- (length - i) * sizeof (Type));
- }
- template <typename T = Type,
- hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
void
shift_down_vector (unsigned i)
{
@@ -289,88 +347,134 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
/* 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;
+
+ new_allocated = size;
+ }
+ else
+ {
+ if (likely (size <= (unsigned) allocated))
+ return true;
- /* Reallocate */
+ 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;
+ }
+
arrayZ = new_array;
allocated = new_allocated;
return true;
}
- bool resize (int size_)
+ 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)
- grow_vector (size);
+ {
+ if (initialize)
+ grow_vector (size);
+ }
else if (size < length)
- shrink_vector (size);
+ {
+ if (initialize)
+ shrink_vector (size);
+ }
length = size;
return true;
}
+ bool resize_exact (int size_, bool initialize = true)
+ {
+ return resize (size_, initialize, true);
+ }
Type pop ()
{
if (!length) return Null (Type);
- Type v = std::move (arrayZ[length - 1]);
+ Type v {std::move (arrayZ[length - 1])};
arrayZ[length - 1].~Type ();
length--;
return v;
}
- void remove (unsigned int i)
+ void remove_ordered (unsigned int i)
{
if (unlikely (i >= length))
return;
- arrayZ[i].~Type ();
shift_down_vector (i + 1);
+ arrayZ[length - 1].~Type ();
length--;
}
- void shrink (int size_)
+ template <bool Sorted = sorted,
+ hb_enable_if (!Sorted)>
+ void remove_unordered (unsigned int i)
+ {
+ if (unlikely (i >= length))
+ return;
+ if (i != length - 1)
+ arrayZ[i] = std::move (arrayZ[length - 1]);
+ arrayZ[length - 1].~Type ();
+ length--;
+ }
+
+ 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. */
}
/* Sorting API. */
- void qsort (int (*cmp)(const void*, const void*))
+ void qsort (int (*cmp)(const void*, const void*) = Type::cmp)
{ as_array ().qsort (cmp); }
- void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
- { as_array ().qsort (start, end); }
/* Unsorted search API. */
template <typename T>
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-version.h b/src/3rdparty/harfbuzz-ng/src/hb-version.h
index 94c73e15bf..e7efeb395c 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-version.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-version.h
@@ -41,13 +41,13 @@ HB_BEGIN_DECLS
*
* The major component of the library version available at compile-time.
*/
-#define HB_VERSION_MAJOR 4
+#define HB_VERSION_MAJOR 7
/**
* HB_VERSION_MINOR:
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 2
+#define HB_VERSION_MINOR 0
/**
* HB_VERSION_MICRO:
*
@@ -60,7 +60,7 @@ HB_BEGIN_DECLS
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "4.2.1"
+#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 b9f5f71415..857571b42f 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb.hh
@@ -29,7 +29,6 @@
#ifndef HB_HH
#define HB_HH
-
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC
#ifdef _MSC_VER
#pragma warning( disable: 4068 ) /* Unknown pragma */
@@ -65,6 +64,7 @@
#pragma GCC diagnostic error "-Wbitwise-instead-of-logical"
#pragma GCC diagnostic error "-Wcast-align"
#pragma GCC diagnostic error "-Wcast-function-type"
+#pragma GCC diagnostic error "-Wcomma"
#pragma GCC diagnostic error "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic error "-Wembedded-directive"
#pragma GCC diagnostic error "-Wextra-semi-stmt"
@@ -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
@@ -126,6 +126,8 @@
/* Ignored intentionally. */
#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"
@@ -141,6 +143,7 @@
#include "hb-config.hh"
+#include "hb-limits.hh"
/*
@@ -183,7 +186,7 @@
#include <cassert>
#include <cfloat>
#include <climits>
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
# define _USE_MATH_DEFINES
#endif
#include <cmath>
@@ -460,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), "");
@@ -470,6 +504,7 @@ static_assert ((sizeof (hb_var_int_t) == 4), "");
/* Headers we include for everyone. Keep topologically sorted by dependency.
* They express dependency amongst themselves, but no other file should include
* them directly.*/
+#include "hb-cplusplus.hh"
#include "hb-meta.hh"
#include "hb-mutex.hh"
#include "hb-number.hh"
diff --git a/src/3rdparty/harfbuzz-ng/src/main.cc b/src/3rdparty/harfbuzz-ng/src/main.cc
index 7a7614f7b6..edc9872eed 100644
--- a/src/3rdparty/harfbuzz-ng/src/main.cc
+++ b/src/3rdparty/harfbuzz-ng/src/main.cc
@@ -58,7 +58,8 @@ svg_dump (hb_face_t *face, unsigned face_index)
const char *data = hb_blob_get_data (blob, &length);
char output_path[255];
- sprintf (output_path, "out/svg-%u-%u.svg%s",
+ snprintf (output_path, sizeof output_path,
+ "out/svg-%u-%u.svg%s",
glyph_id,
face_index,
// append "z" if the content is gzipped, https://stackoverflow.com/a/6059405
@@ -112,7 +113,7 @@ png_dump (hb_face_t *face, unsigned face_index)
const char *data = hb_blob_get_data (blob, &length);
char output_path[255];
- sprintf (output_path, "out/png-%u-%u-%u.png", glyph_id, strike, face_index);
+ snprintf (output_path, sizeof output_path, "out/png-%u-%u-%u.png", glyph_id, strike, face_index);
FILE *f = fopen (output_path, "wb");
fwrite (data, 1, length, f);
@@ -219,12 +220,12 @@ 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;
}
char output_path[255];
- sprintf (output_path, "out/colr-%u-%u-%u.svg", gid, palette, face_index);
+ snprintf (output_path, sizeof output_path, "out/colr-%u-%u-%u.svg", gid, palette, face_index);
FILE *f = fopen (output_path, "wb");
fprintf (f, "<svg xmlns=\"http://www.w3.org/2000/svg\""
" viewBox=\"%d %d %d %d\">\n",
@@ -269,12 +270,12 @@ 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;
}
char output_path[255];
- sprintf (output_path, "out/%u-%u.svg", face_index, gid);
+ snprintf (output_path, sizeof output_path, "out/%u-%u.svg", face_index, gid);
FILE *f = fopen (output_path, "wb");
fprintf (f, "<svg xmlns=\"http://www.w3.org/2000/svg\""
" viewBox=\"%d %d %d %d\"><path d=\"",
@@ -392,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);
@@ -418,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 ())
@@ -442,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 ());
}
@@ -492,12 +493,12 @@ print_layout_info_using_private_api (hb_blob_t *blob)
gdef.has_glyph_classes () ? "" : "no ");
printf (" Has %smark attachment types\n",
gdef.has_mark_attachment_types () ? "" : "no ");
- printf (" Has %sattach points\n",
- gdef.has_attach_points () ? "" : "no ");
+ printf (" Has %sattach list\n",
+ gdef.has_attach_list () ? "" : "no ");
printf (" Has %slig carets\n",
gdef.has_lig_carets () ? "" : "no ");
- printf (" Has %smark sets\n",
- gdef.has_mark_sets () ? "" : "no ");
+ printf (" Has %smark glyph sets\n",
+ gdef.has_mark_glyph_sets () ? "" : "no ");
break;
}
}
@@ -518,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 f8b8ff6668..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-algs.cc
+++ /dev/null
@@ -1,95 +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"
-
-
-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);
-
- return 0;
-}
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 8d5a694275..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-buffer-serialize.cc
+++ /dev/null
@@ -1,97 +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) {
- 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 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_JSON))
- ;
- 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_JSON,
- HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
- 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 dc85b72147..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-iter.cc
+++ /dev/null
@@ -1,360 +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::Coverage> ();
-
- 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);
-
- unsigned int temp3 = 0;
- + hb_iter(src)
- | hb_map([&] (int i) { return ++temp3; })
- | hb_reduce([&] (float acc, int value) { return acc + value; }, 0)
- ;
- hb_map_destroy (result);
-
- + 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-map.cc b/src/3rdparty/harfbuzz-ng/src/test-map.cc
deleted file mode 100644
index fd2b2f0e64..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-map.cc
+++ /dev/null
@@ -1,139 +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 <string>
-
-static const std::string invalid{"invalid"};
-
-int
-main (int argc, char **argv)
-{
-
- /* Test copy constructor. */
- {
- hb_map_t v1;
- v1.set (1, 2);
- hb_map_t v2 {v1};
- assert (v1.get_population () == 1);
- assert (v2.get_population () == 1);
- assert (v1[1] == 2);
- assert (v2[1] == 2);
- }
-
- /* Test copy assignment. */
- {
- hb_map_t v1;
- v1.set (1, 2);
- hb_map_t v2 = v1;
- assert (v1.get_population () == 1);
- assert (v2.get_population () == 1);
- assert (v1[1] == 2);
- assert (v2[1] == 2);
- }
-
- /* Test move constructor. */
- {
- hb_map_t v {hb_map_t {}};
- }
-
- /* Test move assignment. */
- {
- hb_map_t v;
- v = hb_map_t {};
- }
-
- /* Test initializing from iterable. */
- {
- hb_map_t s;
-
- s.set (1, 2);
- s.set (3, 4);
-
- hb_map_t v (s);
-
- assert (v.get_population () == 2);
- }
-
- /* Test call fini() twice. */
- {
- hb_map_t s;
- for (int i = 0; i < 16; i++)
- s.set(i, i+1);
- s.fini();
- }
-
- /* Test initializing from iterator. */
- {
- hb_map_t s;
-
- s.set (1, 2);
- s.set (3, 4);
-
- hb_map_t v (hb_iter (s));
-
- assert (v.get_population () == 2);
- }
-
- /* Test initializing from initializer list and swapping. */
- {
- using pair_t = hb_pair_t<hb_codepoint_t, hb_codepoint_t>;
- hb_map_t v1 {pair_t{1,2}, pair_t{4,5}};
- hb_map_t v2 {pair_t{3,4}};
- hb_swap (v1, v2);
- assert (v1.get_population () == 1);
- assert (v2.get_population () == 2);
- }
-
- /* Test class key / value types. */
- {
- hb_hashmap_t<hb_bytes_t, int, std::nullptr_t, int, nullptr, 0> m1;
- hb_hashmap_t<int, hb_bytes_t, int, std::nullptr_t, 0, nullptr> m2;
- hb_hashmap_t<hb_bytes_t, hb_bytes_t, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m3;
- assert (m1.get_population () == 0);
- assert (m2.get_population () == 0);
- assert (m3.get_population () == 0);
- }
-
- {
- hb_hashmap_t<int, int, int, int, 0, 0> m0;
- hb_hashmap_t<std::string, int, const std::string*, int, &invalid, 0> m1;
- hb_hashmap_t<int, std::string, int, const std::string*, 0, &invalid> m2;
- hb_hashmap_t<std::string, std::string, const std::string*, const std::string*, &invalid, &invalid> m3;
-
- std::string s;
- for (unsigned i = 1; i < 1000; i++)
- {
- s += "x";
- m0.set (i, i);
- m1.set (s, i);
- m2.set (i, s);
- m3.set (s, s);
- }
- }
-
- return 0;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-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 50d023166f..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 fab63acb63..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-priority-queue.cc
+++ /dev/null
@@ -1,89 +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 ());
-}
-
-static void
-test_extract_empty ()
-{
- hb_priority_queue_t queue;
- assert (queue.pop_minimum () == hb_pair (0, 0));
-}
-
-int
-main (int argc, char **argv)
-{
- test_insert ();
- test_extract ();
- test_extract_empty ();
-}
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 3a2536a29a..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-repacker.cc
+++ /dev/null
@@ -1,1360 +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"
-
-static void start_object(const char* tag,
- unsigned len,
- hb_serialize_context_t* c)
-{
- c->push ();
- char* obj = c->allocate_size<char> (len);
- strncpy (obj, tag, len);
-}
-
-
-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_wide_offset (unsigned id,
- hb_serialize_context_t* c)
-{
- OT::Offset32* offset = c->start_embed<OT::Offset32> ();
- c->extend_min (offset);
- c->add_link (*offset, id);
-}
-
-static void run_resolve_overflow_test (const char* name,
- hb_serialize_context_t& overflowing,
- hb_serialize_context_t& expected,
- unsigned num_iterations = 0)
-{
- printf (">>> Testing overflowing resolution for %s\n",
- name);
-
- graph_t graph (overflowing.object_graph ());
-
-
- assert (overflowing.offset_overflow ());
- hb_blob_t* out = hb_resolve_overflows (overflowing.object_graph (),
- HB_TAG ('G', 'S', 'U', 'B'), num_iterations);
- assert (out);
-
- hb_bytes_t result = out->as_bytes ();
-
- assert (!expected.offset_overflow ());
- hb_bytes_t expected_result = expected.copy_bytes ();
-
- assert (result.length == expected_result.length);
- for (unsigned i = 0; i < expected_result.length; i++)
- {
- assert (result[i] == expected_result[i]);
- }
-
- expected_result.fini ();
- hb_blob_destroy (out);
-}
-
-static void add_virtual_offset (unsigned id,
- hb_serialize_context_t* c)
-{
- c->add_virtual_link (id);
-}
-
-static void
-populate_serializer_simple (hb_serialize_context_t* c)
-{
- 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_1 (hb_serialize_context_t* c)
-{
- c->start_serialize<char> ();
-
- unsigned obj_4 = add_object ("jkl", 3, c);
- unsigned obj_3 = add_object ("ghi", 3, c);
-
- 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);
- 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 test_sort_kahn_1 ()
-{
- size_t buffer_size = 100;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_complex_1 (&c);
-
- graph_t graph (c.object_graph ());
- graph.sort_kahn ();
-
- assert(strncmp (graph.object (3).head, "abc", 3) == 0);
- assert(graph.object (3).real_links.length == 2);
- assert(graph.object (3).real_links[0].objidx == 2);
- assert(graph.object (3).real_links[1].objidx == 1);
-
- assert(strncmp (graph.object (2).head, "def", 3) == 0);
- assert(graph.object (2).real_links.length == 1);
- assert(graph.object (2).real_links[0].objidx == 0);
-
- assert(strncmp (graph.object (1).head, "jkl", 3) == 0);
- assert(graph.object (1).real_links.length == 0);
-
- assert(strncmp (graph.object (0).head, "ghi", 3) == 0);
- assert(graph.object (0).real_links.length == 0);
-
- free (buffer);
-}
-
-static void test_sort_kahn_2 ()
-{
- 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_kahn ();
-
-
- 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 == 3);
- assert(graph.object (4).real_links[1].objidx == 0);
- assert(graph.object (4).real_links[2].objidx == 2);
-
- assert(strncmp (graph.object (3).head, "def", 3) == 0);
- assert(graph.object (3).real_links.length == 1);
- assert(graph.object (3).real_links[0].objidx == 1);
-
- assert(strncmp (graph.object (2).head, "mn", 2) == 0);
- assert(graph.object (2).real_links.length == 0);
-
- 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_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(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 ();
- 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 (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 (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 (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_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_kahn_1 ();
- test_sort_kahn_2 ();
- 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_duplicate_leaf ();
- test_duplicate_interior ();
- test_virtual_link ();
- test_shared_node_with_virtual_links ();
-}
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 286f1a9976..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-set.cc
+++ /dev/null
@@ -1,97 +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 (v2.get_population () == 2);
- }
-
- /* Test copy assignment. */
- {
- hb_set_t v1 {1, 2};
- hb_set_t v2 = v1;
- assert (v1.get_population () == 2);
- assert (v2.get_population () == 2);
- }
-
- /* Test move constructor. */
- {
- hb_set_t v {hb_set_t {1, 2}};
- assert (v.get_population () == 2);
- }
-
- /* Test move assignment. */
- {
- hb_set_t v;
- v = hb_set_t {1, 2};
- assert (v.get_population () == 2);
- }
-
- /* Test initializing from iterable. */
- {
- hb_set_t s;
-
- s.add (18);
- s.add (12);
-
- hb_set_t v (s);
-
- assert (v.get_population () == 2);
- }
-
- /* Test initializing from iterator. */
- {
- hb_set_t s;
-
- s.add (18);
- s.add (12);
-
- hb_set_t v (hb_iter (s));
-
- assert (v.get_population () == 2);
- }
-
- /* Test initializing from initializer list and swapping. */
- {
- hb_set_t v1 {1, 2, 3};
- hb_set_t v2 {4, 5};
- hb_swap (v1, v2);
- assert (v1.get_population () == 2);
- assert (v2.get_population () == 3);
- }
-
- return 0;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test-vector.cc b/src/3rdparty/harfbuzz-ng/src/test-vector.cc
deleted file mode 100644
index 521f2a171d..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test-vector.cc
+++ /dev/null
@@ -1,154 +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 <string>
-
-
-int
-main (int argc, char **argv)
-{
-
- /* Test copy constructor. */
- {
- hb_vector_t<int> v1 {1, 2};
- hb_vector_t<int> v2 {v1};
- hb_vector_t<int> V2 {v1};
- assert (v1.length == 2);
- assert (v1[0] == 1);
- assert (v1[1] == 2);
- assert (v2.length == 2);
- assert (v2[0] == 1);
- assert (v2[1] == 2);
- }
-
- /* Test copy assignment. */
- {
- hb_vector_t<int> v1 {1, 2};
- hb_vector_t<int> v2 = v1;
- hb_vector_t<int> V2 = v1;
- assert (v1.length == 2);
- assert (v1[0] == 1);
- assert (v1[1] == 2);
- assert (v2.length == 2);
- assert (v2[0] == 1);
- assert (v2[1] == 2);
- }
-
- /* Test move constructor. */
- {
- hb_vector_t<int> v {hb_vector_t<int> {1, 2}};
- hb_vector_t<int> V {hb_vector_t<int> {1, 2}};
- assert (v.length == 2);
- assert (v[0] == 1);
- assert (v[1] == 2);
- }
-
- /* Test move assignment. */
- {
- hb_vector_t<int> v;
- hb_sorted_vector_t<int> V;
- v = hb_vector_t<int> {1, 2};
- V = hb_sorted_vector_t<int> {1, 2};
- assert (v.length == 2);
- assert (v[0] == 1);
- assert (v[1] == 2);
- }
-
- /* Test initializing from iterable. */
- {
- hb_set_t s;
-
- s.add (18);
- s.add (12);
-
- hb_vector_t<int> v (s);
- hb_sorted_vector_t<int> V (s);
-
- assert (v.length == 2);
- assert (V.length == 2);
- assert (v[0] == 12);
- assert (V[0] == 12);
- assert (v[1] == 18);
- assert (V[1] == 18);
- }
-
- /* Test initializing from iterator. */
- {
- hb_set_t s;
-
- s.add (18);
- s.add (12);
-
- hb_vector_t<int> v (hb_iter (s));
- hb_vector_t<int> V (hb_iter (s));
-
- assert (v.length == 2);
- assert (V.length == 2);
- assert (v[0] == 12);
- assert (V[0] == 12);
- assert (v[1] == 18);
- assert (V[1] == 18);
- }
-
- /* Test initializing from initializer list and swapping. */
- {
- hb_vector_t<int> v1 {1, 2, 3};
- hb_vector_t<int> v2 {4, 5};
- hb_swap (v1, v2);
- assert (v1.length == 2);
- assert (v1[0] == 4);
- assert (v2.length == 3);
- assert (v2[2] == 3);
- }
-
- /* Test initializing sorted-vector from initializer list and swapping. */
- {
- hb_sorted_vector_t<int> v1 {1, 2, 3};
- hb_sorted_vector_t<int> v2 {4, 5};
- hb_swap (v1, v2);
- assert (v1.length == 2);
- assert (v1[0] == 4);
- assert (v2.length == 3);
- assert (v2[2] == 3);
- }
-
-#if 0
- {
- hb_vector_t<std::string> v;
-
- std::string s;
- for (unsigned i = 1; i < 100; i++)
- {
- s += "x";
- v.push (s);
- }
- }
-#endif
-
- return 0;
-}
diff --git a/src/3rdparty/harfbuzz-ng/src/test.cc b/src/3rdparty/harfbuzz-ng/src/test.cc
deleted file mode 100644
index d848cf1062..0000000000
--- a/src/3rdparty/harfbuzz-ng/src/test.cc
+++ /dev/null
@@ -1,95 +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"
-
-#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 != 2) {
- fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
- exit (1);
- }
-
- hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
- assert (blob);
- printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob));
-
- /* Create the face */
- 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_font_set_scale (font, upem, upem);
-
-#ifdef HAVE_FREETYPE
- hb_ft_font_set_funcs (font);
-#endif
-
- hb_buffer_t *buffer = hb_buffer_create ();
-
- hb_buffer_add_utf8 (buffer, "\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\x95", -1, 0, -1);
- hb_buffer_guess_segment_properties (buffer);
-
- hb_shape (font, buffer, nullptr, 0);
-
- unsigned int count = hb_buffer_get_length (buffer);
- hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, nullptr);
- hb_glyph_position_t *positions = hb_buffer_get_glyph_positions (buffer, nullptr);
-
- for (unsigned int i = 0; i < count; i++)
- {
- 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",
- info->cluster,
- info->codepoint,
- pos->x_offset,
- pos->y_offset,
- pos->x_advance,
- pos->y_advance);
-
- }
-
- hb_buffer_destroy (buffer);
- hb_font_destroy (font);
- hb_face_destroy (face);
-
- return 0;
-}
-
-
diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
index def7c88593..a8b42b8869 100644
--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
@@ -720,29 +720,29 @@ void tst_QTextLayout::cursorToXForBidiBoundaries_data()
QTest::addColumn<Qt::LayoutDirection>("textDirection");
QTest::addColumn<QString>("text");
QTest::addColumn<int>("cursorPosition");
- QTest::addColumn<int>("expectedX");
+ QTest::addColumn<int>("runsToInclude");
QTest::addRow("LTR, abcشزذabc, 0") << Qt::LeftToRight << "abcشزذabc"
<< 0 << 0;
QTest::addRow("RTL, abcشزذabc, 9") << Qt::RightToLeft << "abcشزذabc"
- << 9 << TESTFONT_SIZE * 3;
+ << 9 << 1;
QTest::addRow("LTR, abcشزذabc, 3") << Qt::LeftToRight << "abcشزذabc"
<< 0 << 0;
QTest::addRow("RTL, abcشزذabc, 6") << Qt::RightToLeft << "abcشزذabc"
- << 9 << TESTFONT_SIZE * 3;
+ << 9 << 1;
QTest::addRow("LTR, شزذabcشزذ, 0") << Qt::LeftToRight << "شزذabcشزذ"
- << 0 << TESTFONT_SIZE * 2;
+ << 0 << 1;
QTest::addRow("RTL, شزذabcشزذ, 9") << Qt::RightToLeft << "شزذabcشزذ"
<< 9 << 0;
QTest::addRow("LTR, شزذabcشزذ, 3") << Qt::LeftToRight << "شزذabcشزذ"
- << 3 << TESTFONT_SIZE * 2;
+ << 3 << 1;
QTest::addRow("RTL, شزذabcشزذ, 3") << Qt::RightToLeft << "شزذabcشزذ"
- << 3 << TESTFONT_SIZE * 5;
+ << 3 << 2;
QTest::addRow("LTR, شزذabcشزذ, 6") << Qt::LeftToRight << "شزذabcشزذ"
- << 6 << TESTFONT_SIZE * 5;
+ << 6 << 2;
QTest::addRow("RTL, شزذabcشزذ, 6") << Qt::RightToLeft << "شزذabcشزذ"
- << 6 << TESTFONT_SIZE * 2;
+ << 6 << 1;
}
void tst_QTextLayout::cursorToXForBidiBoundaries()
@@ -750,7 +750,7 @@ void tst_QTextLayout::cursorToXForBidiBoundaries()
QFETCH(Qt::LayoutDirection, textDirection);
QFETCH(QString, text);
QFETCH(int, cursorPosition);
- QFETCH(int, expectedX);
+ QFETCH(int, runsToInclude);
QTextOption option;
option.setTextDirection(textDirection);
@@ -759,12 +759,27 @@ void tst_QTextLayout::cursorToXForBidiBoundaries()
layout.setTextOption(option);
layout.beginLayout();
- QTextLine line = layout.createLine();
- line.setLineWidth(0x10000);
+ {
+ QTextLine line = layout.createLine();
+ line.setLineWidth(0x10000);
+ }
+ layout.endLayout();
- QCOMPARE(line.cursorToX(cursorPosition), expectedX);
+ QTextLine line = layout.lineAt(0);
+ QList<QGlyphRun> glyphRuns = line.glyphRuns();
+ QVERIFY(runsToInclude <= glyphRuns.size());
- layout.endLayout();
+ std::sort(glyphRuns.begin(), glyphRuns.end(),
+ [](const QGlyphRun &first, const QGlyphRun &second) {
+ return first.positions().first().x() < second.positions().first().x();
+ });
+
+ qreal expectedX = 0.0;
+ for (int i = 0; i < runsToInclude; ++i) {
+ expectedX += glyphRuns.at(i).boundingRect().width();
+ }
+
+ QCOMPARE(line.cursorToX(cursorPosition), expectedX);
}
void tst_QTextLayout::horizontalAlignment_data()