summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/harfbuzz/src')
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh110
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh51
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh128
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh18
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh21
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh18
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh22
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh58
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh135
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh118
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh59
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh165
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh53
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh120
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh36
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh228
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh103
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh75
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh122
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh120
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh224
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh77
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-page.hh72
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set-invertible.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set.hh102
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-coretext.cc18
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.cc1
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cmap-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-font.cc38
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-glyf-table.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-common.hh61
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh1721
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh41
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.cc131
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.hh21
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-map.cc8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-map.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-metrics.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc40
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh1
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc22
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh891
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh28
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc17
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.cc10
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-set.cc48
-rw-r--r--thirdparty/harfbuzz/src/hb-set.h11
-rw-r--r--thirdparty/harfbuzz/src/hb-set.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-static.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-version.h6
56 files changed, 3042 insertions, 2369 deletions
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
new file mode 100644
index 0000000000..484f347468
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
@@ -0,0 +1,110 @@
+#ifndef OT_LAYOUT_GSUB_ALTERNATESET_HH
+#define OT_LAYOUT_GSUB_ALTERNATESET_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct AlternateSet
+{
+ protected:
+ Array16Of<HBGlyphID16>
+ alternates; /* Array of alternate GlyphIDs--in
+ * arbitrary order */
+ public:
+ DEFINE_SIZE_ARRAY (2, alternates);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (alternates.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return hb_any (alternates, glyphs); }
+
+ void closure (hb_closure_context_t *c) const
+ { c->output->add_array (alternates.arrayZ, alternates.len); }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { c->output->add_array (alternates.arrayZ, alternates.len); }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int count = alternates.len;
+
+ if (unlikely (!count)) return_trace (false);
+
+ hb_mask_t glyph_mask = c->buffer->cur().mask;
+ hb_mask_t lookup_mask = c->lookup_mask;
+
+ /* Note: This breaks badly if two features enabled this lookup together. */
+ unsigned int shift = hb_ctz (lookup_mask);
+ unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
+
+ /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
+ if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
+ {
+ /* Maybe we can do better than unsafe-to-break all; but since we are
+ * changing random state, it would be hard to track that. Good 'nough. */
+ c->buffer->unsafe_to_break (0, c->buffer->len);
+ alt_index = c->random_number () % count + 1;
+ }
+
+ if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
+
+ c->replace_glyph (alternates[alt_index - 1]);
+
+ return_trace (true);
+ }
+
+ unsigned
+ get_alternates (unsigned start_offset,
+ unsigned *alternate_count /* IN/OUT. May be NULL. */,
+ hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
+ {
+ if (alternates.len && alternate_count)
+ {
+ + alternates.sub_array (start_offset, alternate_count)
+ | hb_sink (hb_array (alternate_glyphs, *alternate_count))
+ ;
+ }
+ return alternates.len;
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator alts)
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (alternates.serialize (c, alts));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (alternates)
+ | hb_filter (glyphset)
+ | hb_map (glyph_map)
+ ;
+
+ auto *out = c->serializer->start_embed (*this);
+ return_trace (out->serialize (c->serializer, it) &&
+ out->alternates);
+ }
+};
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_ALTERNATESET_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
new file mode 100644
index 0000000000..e5d999261f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
@@ -0,0 +1,51 @@
+#ifndef OT_LAYOUT_GSUB_ALTERNATESUBST_HH
+#define OT_LAYOUT_GSUB_ALTERNATESUBST_HH
+
+#include "AlternateSubstFormat1.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct AlternateSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ AlternateSubstFormat1 format1;
+ } u;
+ public:
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> alternate_len_list,
+ hb_array_t<const HBGlyphID16> alternate_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned int format = 1;
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
+ default:return_trace (false);
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_ALTERNATESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
new file mode 100644
index 0000000000..af1cd7bedb
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
@@ -0,0 +1,128 @@
+#ifndef OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
+
+#include "AlternateSet.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct AlternateSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16OfOffset16To<AlternateSet>
+ alternateSet; /* Array of AlternateSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (6, alternateSet);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, alternateSet)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ + hb_zip (this+coverage, alternateSet)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ unsigned
+ get_glyph_alternates (hb_codepoint_t gid,
+ unsigned start_offset,
+ unsigned *alternate_count /* IN/OUT. May be NULL. */,
+ hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
+ { return (this+alternateSet[(this+coverage).get_coverage (gid)])
+ .get_alternates (start_offset, alternate_count, alternate_glyphs); }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ return_trace ((this+alternateSet[index]).apply (c));
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> alternate_len_list,
+ hb_array_t<const HBGlyphID16> alternate_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
+ for (unsigned int i = 0; i < glyphs.length; i++)
+ {
+ unsigned int alternate_len = alternate_len_list[i];
+ if (unlikely (!alternateSet[i]
+ .serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
+ return_trace (false);
+ alternate_glyphs_list += alternate_len;
+ }
+ return_trace (coverage.serialize_serialize (c, glyphs));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, alternateSet)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
+ return_trace (bool (new_coverage));
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh
new file mode 100644
index 0000000000..bbb88b222f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh
@@ -0,0 +1,18 @@
+#ifndef OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH
+#define OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ChainContextSubst : ChainContext {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh
new file mode 100644
index 0000000000..f4c78a9f02
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh
@@ -0,0 +1,21 @@
+#ifndef OT_LAYOUT_GSUB_COMMON_HH
+#define OT_LAYOUT_GSUB_COMMON_HH
+
+#include "../../../hb-serialize.hh"
+#include "../../../hb-ot-layout-gsubgpos.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
+
+template<typename Iterator>
+static void SingleSubst_serialize (hb_serialize_context_t *c,
+ Iterator it);
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_COMMON_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh
new file mode 100644
index 0000000000..2af54e8ff4
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh
@@ -0,0 +1,18 @@
+#ifndef OT_LAYOUT_GSUB_CONTEXTSUBST_HH
+#define OT_LAYOUT_GSUB_CONTEXTSUBST_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ContextSubst : Context {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_CONTEXTSUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh
new file mode 100644
index 0000000000..40a3ff439f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh
@@ -0,0 +1,22 @@
+#ifndef OT_LAYOUT_GSUB_EXTENSIONSUBST_HH
+#define OT_LAYOUT_GSUB_EXTENSIONSUBST_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ExtensionSubst : Extension<ExtensionSubst>
+{
+ typedef struct SubstLookupSubTable SubTable;
+ bool is_reverse () const;
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_EXTENSIONSUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
new file mode 100644
index 0000000000..ad153ce8d7
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
@@ -0,0 +1,58 @@
+#ifndef OT_LAYOUT_GSUB_GSUB_HH
+#define OT_LAYOUT_GSUB_GSUB_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+#include "SubstLookup.hh"
+
+using OT::Layout::GSUB::SubstLookup;
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+/*
+ * GSUB -- Glyph Substitution
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
+ */
+
+struct GSUB : GSUBGPOS
+{
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
+
+ const SubstLookup& get_lookup (unsigned int i) const
+ { return static_cast<const SubstLookup &> (GSUBGPOS::get_lookup (i)); }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
+ return GSUBGPOS::subset<SubstLookup> (&l);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return GSUBGPOS::sanitize<SubstLookup> (c); }
+
+ HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
+ void closure_lookups (hb_face_t *face,
+ const hb_set_t *glyphs,
+ hb_set_t *lookup_indexes /* IN/OUT */) const
+ { GSUBGPOS::closure_lookups<SubstLookup> (face, glyphs, lookup_indexes); }
+
+ typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
+};
+
+
+}
+}
+
+struct GSUB_accelerator_t : Layout::GSUB::GSUB::accelerator_t {
+ GSUB_accelerator_t (hb_face_t *face) : Layout::GSUB::GSUB::accelerator_t (face) {}
+};
+
+
+}
+
+#endif /* OT_LAYOUT_GSUB_GSUB_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
new file mode 100644
index 0000000000..0448d925d1
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
@@ -0,0 +1,135 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURE_HH
+#define OT_LAYOUT_GSUB_LIGATURE_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct Ligature
+{
+ protected:
+ HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */
+ HeadlessArrayOf<HBGlyphID16>
+ component; /* Array of component GlyphIDs--start
+ * with the second component--ordered
+ * in writing direction */
+ public:
+ DEFINE_SIZE_ARRAY (4, component);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return hb_all (component, glyphs); }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ if (!intersects (c->glyphs)) return;
+ c->output->add (ligGlyph);
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ c->input->add_array (component.arrayZ, component.get_length ());
+ c->output->add (ligGlyph);
+ }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ {
+ if (c->len != component.lenP1)
+ return false;
+
+ for (unsigned int i = 1; i < c->len; i++)
+ if (likely (c->glyphs[i] != component[i]))
+ return false;
+
+ return true;
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int count = component.lenP1;
+
+ if (unlikely (!count)) return_trace (false);
+
+ /* Special-case to make it in-place and not consider this
+ * as a "ligated" substitution. */
+ if (unlikely (count == 1))
+ {
+ c->replace_glyph (ligGlyph);
+ return_trace (true);
+ }
+
+ unsigned int total_component_count = 0;
+
+ unsigned int match_end = 0;
+ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+
+ if (likely (!match_input (c, count,
+ &component[1],
+ match_glyph,
+ nullptr,
+ &match_end,
+ match_positions,
+ &total_component_count)))
+ {
+ c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
+ return_trace (false);
+ }
+
+ ligate_input (c,
+ count,
+ match_positions,
+ match_end,
+ ligGlyph,
+ total_component_count);
+
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ hb_codepoint_t ligature,
+ Iterator components /* Starting from second */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ ligGlyph = ligature;
+ if (unlikely (!component.serialize (c, components))) return_trace (false);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
+ // Ensure Coverage table is always packed after this.
+ c->serializer->add_virtual_link (coverage_idx);
+
+ auto it =
+ + hb_iter (component)
+ | hb_map (glyph_map)
+ ;
+
+ auto *out = c->serializer->start_embed (*this);
+ return_trace (out->serialize (c->serializer,
+ glyph_map[ligGlyph],
+ it)); }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURE_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh
new file mode 100644
index 0000000000..185b324b35
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh
@@ -0,0 +1,118 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURESET_HH
+#define OT_LAYOUT_GSUB_LIGATURESET_HH
+
+#include "Common.hh"
+#include "Ligature.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct LigatureSet
+{
+ protected:
+ Array16OfOffset16To<Ligature>
+ ligature; /* Array LigatureSet tables
+ * ordered by preference */
+ public:
+ DEFINE_SIZE_ARRAY (2, ligature);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (ligature.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
+ | hb_any
+ ;
+ }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Ligature &_) { _.closure (c); })
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ {
+ return
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_map ([c] (const Ligature &_) { return _.would_apply (c); })
+ | hb_any
+ ;
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int num_ligs = ligature.len;
+ for (unsigned int i = 0; i < num_ligs; i++)
+ {
+ const Ligature &lig = this+ligature[i];
+ if (lig.apply (c)) return_trace (true);
+ }
+
+ return_trace (false);
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_array_t<const HBGlyphID16> ligatures,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> &component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
+ for (unsigned int i = 0; i < ligatures.length; i++)
+ {
+ unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
+ if (unlikely (!ligature[i].serialize_serialize (c,
+ ligatures[i],
+ component_list.sub_array (0, component_count))))
+ return_trace (false);
+ component_list += component_count;
+ }
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ + hb_iter (ligature)
+ | hb_filter (subset_offset_array (c, out->ligature, this, coverage_idx))
+ | hb_drain
+ ;
+
+ if (bool (out->ligature))
+ // Ensure Coverage table is always packed after this.
+ c->serializer->add_virtual_link (coverage_idx);
+
+ return_trace (bool (out->ligature));
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURESET_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
new file mode 100644
index 0000000000..a029bf5e9f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
@@ -0,0 +1,59 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURESUBST_HH
+#define OT_LAYOUT_GSUB_LIGATURESUBST_HH
+
+#include "Common.hh"
+#include "LigatureSubstFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct LigatureSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ LigatureSubstFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> first_glyphs,
+ hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+ hb_array_t<const HBGlyphID16> ligatures_list,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned int format = 1;
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c,
+ first_glyphs,
+ ligature_per_first_glyph_count_list,
+ ligatures_list,
+ component_count_list,
+ component_list));
+ default:return_trace (false);
+ }
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
new file mode 100644
index 0000000000..19dfe98469
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
@@ -0,0 +1,165 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH
+
+#include "Common.hh"
+#include "LigatureSet.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct LigatureSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16OfOffset16To<LigatureSet>
+ ligatureSet; /* Array LigatureSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (6, ligatureSet);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_filter (*glyphs, hb_first)
+ | hb_map (hb_second)
+ | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
+ { return (this+_).intersects (glyphs); })
+ | hb_any
+ ;
+ }
+
+ bool may_have_non_1to1 () const
+ { return true; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ {
+ unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
+ if (likely (index == NOT_COVERED)) return false;
+
+ const LigatureSet &lig_set = this+ligatureSet[index];
+ return lig_set.would_apply (c);
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ const LigatureSet &lig_set = this+ligatureSet[index];
+ return_trace (lig_set.apply (c));
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> first_glyphs,
+ hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+ hb_array_t<const HBGlyphID16> ligatures_list,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
+ for (unsigned int i = 0; i < first_glyphs.length; i++)
+ {
+ unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
+ if (unlikely (!ligatureSet[i]
+ .serialize_serialize (c,
+ ligatures_list.sub_array (0, ligature_count),
+ component_count_list.sub_array (0, ligature_count),
+ component_list))) return_trace (false);
+ ligatures_list += ligature_count;
+ component_count_list += ligature_count;
+ }
+ return_trace (coverage.serialize_serialize (c, first_glyphs));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ // Due to a bug in some older versions of windows 7 the Coverage table must be
+ // packed after the LigatureSet and Ligature tables, so serialize Coverage first
+ // which places it last in the packed order.
+ hb_set_t new_coverage;
+ + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
+ | hb_filter (glyphset, hb_first)
+ | hb_filter ([&] (const LigatureSet& _) {
+ return _.intersects (&glyphset);
+ }, hb_second)
+ | hb_map (hb_first)
+ | hb_sink (new_coverage);
+
+ if (!c->serializer->push<Coverage> ()
+ ->serialize (c->serializer,
+ + new_coverage.iter () | hb_map_retains_sorting (glyph_map)))
+ {
+ c->serializer->pop_discard ();
+ return_trace (false);
+ }
+
+ unsigned coverage_idx = c->serializer->pop_pack ();
+ c->serializer->add_link (out->coverage, coverage_idx);
+
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_filter (new_coverage, hb_first)
+ | hb_map (hb_second)
+ // to ensure that the repacker always orders the coverage table after the LigatureSet
+ // and LigatureSubtable's they will be linked to the Coverage table via a virtual link
+ // the coverage table object idx is passed down to facilitate this.
+ | hb_apply (subset_offset_array (c, out->ligatureSet, this, coverage_idx))
+ ;
+
+ return_trace (bool (new_coverage));
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
new file mode 100644
index 0000000000..b289175504
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
@@ -0,0 +1,53 @@
+#ifndef OT_LAYOUT_GSUB_MULTIPLESUBST_HH
+#define OT_LAYOUT_GSUB_MULTIPLESUBST_HH
+
+#include "Common.hh"
+#include "MultipleSubstFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct MultipleSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MultipleSubstFormat1 format1;
+ } u;
+
+ public:
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> substitute_len_list,
+ hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned int format = 1;
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
+ default:return_trace (false);
+ }
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_MULTIPLESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
new file mode 100644
index 0000000000..54c6dc8478
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
@@ -0,0 +1,120 @@
+#ifndef OT_LAYOUT_GSUB_MULTIPLESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_MULTIPLESUBSTFORMAT1_HH
+
+#include "Common.hh"
+#include "Sequence.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct MultipleSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16OfOffset16To<Sequence>
+ sequence; /* Array of Sequence tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (6, sequence);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return true; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, sequence)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Sequence &_) { _.closure (c); })
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ + hb_zip (this+coverage, sequence)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ return_trace ((this+sequence[index]).apply (c));
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> substitute_len_list,
+ hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
+ for (unsigned int i = 0; i < glyphs.length; i++)
+ {
+ unsigned int substitute_len = substitute_len_list[i];
+ if (unlikely (!sequence[i]
+ .serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
+ return_trace (false);
+ substitute_glyphs_list += substitute_len;
+ }
+ return_trace (coverage.serialize_serialize (c, glyphs));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, sequence)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (subset_offset_array (c, out->sequence, this), hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
+ return_trace (bool (new_coverage));
+ }
+};
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_MULTIPLESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
new file mode 100644
index 0000000000..435d80fd31
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
@@ -0,0 +1,36 @@
+#ifndef OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBST_HH
+#define OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBST_HH
+
+#include "Common.hh"
+#include "ReverseChainSingleSubstFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ReverseChainSingleSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ ReverseChainSingleSubstFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
new file mode 100644
index 0000000000..7a79a9df25
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
@@ -0,0 +1,228 @@
+#ifndef OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct ReverseChainSingleSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of table */
+ Array16OfOffset16To<Coverage>
+ backtrack; /* Array of coverage tables
+ * in backtracking sequence, in glyph
+ * sequence order */
+ Array16OfOffset16To<Coverage>
+ lookaheadX; /* Array of coverage tables
+ * in lookahead sequence, in glyph
+ * sequence order */
+ Array16Of<HBGlyphID16>
+ substituteX; /* Array of substitute
+ * GlyphIDs--ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_MIN (10);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
+ return_trace (false);
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ if (!lookahead.sanitize (c, this))
+ return_trace (false);
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ return_trace (substitute.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ if (!(this+coverage).intersects (glyphs))
+ return false;
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+
+ unsigned int count;
+
+ count = backtrack.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+backtrack[i]).intersects (glyphs))
+ return false;
+
+ count = lookahead.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+lookahead[i]).intersects (glyphs))
+ return false;
+
+ return true;
+ }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ if (!intersects (c->glyphs)) return;
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_sink (c->output)
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+
+ unsigned int count;
+
+ count = backtrack.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ count = lookahead.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
+
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+ count = substitute.len;
+ c->output->add_array (substitute.arrayZ, substitute.len);
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
+ return_trace (false); /* No chaining to this type */
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+
+ if (unlikely (index >= substitute.len)) return_trace (false);
+
+ unsigned int start_index = 0, end_index = 0;
+ if (match_backtrack (c,
+ backtrack.len, (HBUINT16 *) backtrack.arrayZ,
+ match_coverage, this,
+ &start_index) &&
+ match_lookahead (c,
+ lookahead.len, (HBUINT16 *) lookahead.arrayZ,
+ match_coverage, this,
+ c->buffer->idx + 1, &end_index))
+ {
+ c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
+ c->replace_glyph_inplace (substitute[index]);
+ /* Note: We DON'T decrease buffer->idx. The main loop does it
+ * for us. This is useful for preventing surprises if someone
+ * calls us through a Context lookup. */
+ return_trace (true);
+ }
+ else
+ {
+ c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
+ return_trace (false);
+ }
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
+
+ if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
+ return_trace (false);
+
+ for (auto& offset : it) {
+ auto *o = out->serialize_append (c->serializer);
+ if (unlikely (!o) || !o->serialize_subset (c, offset, this))
+ return_trace (false);
+ }
+
+ return_trace (true);
+ }
+
+ template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
+ hb_requires (hb_is_iterator (BacktrackIterator)),
+ hb_requires (hb_is_iterator (LookaheadIterator))>
+ bool serialize (hb_subset_context_t *c,
+ Iterator coverage_subst_iter,
+ BacktrackIterator backtrack_iter,
+ LookaheadIterator lookahead_iter) const
+ {
+ TRACE_SERIALIZE (this);
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->check_success (out))) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
+
+ if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
+ if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
+
+ auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID16>> ();
+ auto substitutes =
+ + coverage_subst_iter
+ | hb_map (hb_second)
+ ;
+
+ auto glyphs =
+ + coverage_subst_iter
+ | hb_map_retains_sorting (hb_first)
+ ;
+ if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
+ return_trace (false);
+
+ if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs)))
+ return_trace (false);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
+
+ auto it =
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (glyphset, hb_second)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
+ { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+ ;
+
+ return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
+ }
+};
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
new file mode 100644
index 0000000000..ebd451e6ba
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
@@ -0,0 +1,103 @@
+#ifndef OT_LAYOUT_GSUB_SEQUENCE_HH
+#define OT_LAYOUT_GSUB_SEQUENCE_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct Sequence
+{
+ protected:
+ Array16Of<HBGlyphID16>
+ substitute; /* String of GlyphIDs to substitute */
+ public:
+ DEFINE_SIZE_ARRAY (2, substitute);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (substitute.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return hb_all (substitute, glyphs); }
+
+ void closure (hb_closure_context_t *c) const
+ { c->output->add_array (substitute.arrayZ, substitute.len); }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { c->output->add_array (substitute.arrayZ, substitute.len); }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int count = substitute.len;
+
+ /* Special-case to make it in-place and not consider this
+ * as a "multiplied" substitution. */
+ if (unlikely (count == 1))
+ {
+ c->replace_glyph (substitute.arrayZ[0]);
+ return_trace (true);
+ }
+ /* Spec disallows this, but Uniscribe allows it.
+ * https://github.com/harfbuzz/harfbuzz/issues/253 */
+ else if (unlikely (count == 0))
+ {
+ c->buffer->delete_glyph ();
+ return_trace (true);
+ }
+
+ unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
+ HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
+ unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ /* If is attached to a ligature, don't disturb that.
+ * https://github.com/harfbuzz/harfbuzz/issues/3069 */
+ if (!lig_id)
+ _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
+ c->output_glyph_for_component (substitute.arrayZ[i], klass);
+ }
+ c->buffer->skip_glyph ();
+
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator subst)
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (substitute.serialize (c, subst));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ if (!intersects (&glyphset)) return_trace (false);
+
+ auto it =
+ + hb_iter (substitute)
+ | hb_map (glyph_map)
+ ;
+
+ auto *out = c->serializer->start_embed (*this);
+ return_trace (out->serialize (c->serializer, it));
+ }
+};
+
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_SEQUENCE_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
new file mode 100644
index 0000000000..786428fe45
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
@@ -0,0 +1,75 @@
+#ifndef OT_LAYOUT_GSUB_SINGLESUBST_HH
+#define OT_LAYOUT_GSUB_SINGLESUBST_HH
+
+#include "Common.hh"
+#include "SingleSubstFormat1.hh"
+#include "SingleSubstFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SingleSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ SingleSubstFormat1 format1;
+ SingleSubstFormat2 format2;
+ } u;
+
+ public:
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator,
+ const hb_codepoint_pair_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned format = 2;
+ unsigned delta = 0;
+ if (glyphs)
+ {
+ format = 1;
+ auto get_delta = [=] (hb_codepoint_pair_t _)
+ { return (unsigned) (_.second - _.first) & 0xFFFF; };
+ delta = get_delta (*glyphs);
+ if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
+ }
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c,
+ + glyphs
+ | hb_map_retains_sorting (hb_first),
+ delta));
+ case 2: return_trace (u.format2.serialize (c, glyphs));
+ default:return_trace (false);
+ }
+ }
+};
+
+template<typename Iterator>
+static void
+SingleSubst_serialize (hb_serialize_context_t *c,
+ Iterator it)
+{ c->start_embed<SingleSubst> ()->serialize (c, it); }
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_SINGLESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
new file mode 100644
index 0000000000..3c6b2954ce
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
@@ -0,0 +1,122 @@
+#ifndef OT_LAYOUT_GSUB_SINGLESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_SINGLESUBSTFORMAT1_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SingleSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ HBUINT16 deltaGlyphID; /* Add to original GlyphID to get
+ * substitute GlyphID, modulo 0x10000 */
+
+ public:
+ DEFINE_SIZE_STATIC (6);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ unsigned d = deltaGlyphID;
+
+ + hb_iter (this+coverage)
+ | hb_filter (c->parent_active_glyphs ())
+ | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
+ | hb_sink (c->output)
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ unsigned d = deltaGlyphID;
+ + hb_iter (this+coverage)
+ | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
+ | hb_sink (c->output)
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
+ unsigned int index = (this+coverage).get_coverage (glyph_id);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ /* According to the Adobe Annotated OpenType Suite, result is always
+ * limited to 16bit. */
+ glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
+ c->replace_glyph (glyph_id);
+
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator glyphs,
+ unsigned delta)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
+ c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ hb_codepoint_t delta = deltaGlyphID;
+
+ auto it =
+ + hb_iter (this+coverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting ([&] (hb_codepoint_t g) {
+ return hb_codepoint_pair_t (g,
+ (g + delta) & 0xFFFF); })
+ | hb_filter (glyphset, hb_second)
+ | hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t
+ { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+ ;
+
+ bool ret = bool (it);
+ SingleSubst_serialize (c->serializer, it);
+ return_trace (ret);
+ }
+};
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_SINGLESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
new file mode 100644
index 0000000000..df75bb52bb
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
@@ -0,0 +1,120 @@
+#ifndef OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH
+#define OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SingleSubstFormat2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16Of<HBGlyphID16>
+ substitute; /* Array of substitute
+ * GlyphIDs--ordered by Coverage Index */
+
+ public:
+ DEFINE_SIZE_ARRAY (6, substitute);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_sink (c->output)
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ + hb_zip (this+coverage, substitute)
+ | hb_map (hb_second)
+ | hb_sink (c->output)
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ if (unlikely (index >= substitute.len)) return_trace (false);
+
+ c->replace_glyph (substitute[index]);
+
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator,
+ hb_codepoint_pair_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator it)
+ {
+ TRACE_SERIALIZE (this);
+ auto substitutes =
+ + it
+ | hb_map (hb_second)
+ ;
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
+ if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (glyphset, hb_second)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
+ { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+ ;
+
+ bool ret = bool (it);
+ SingleSubst_serialize (c->serializer, it);
+ return_trace (ret);
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
new file mode 100644
index 0000000000..3419b5a734
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
@@ -0,0 +1,224 @@
+#ifndef OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
+#define OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
+
+#include "Common.hh"
+#include "SubstLookupSubTable.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SubstLookup : Lookup
+{
+ typedef SubstLookupSubTable SubTable;
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return Lookup::sanitize<SubTable> (c); }
+
+ const SubTable& get_subtable (unsigned int i) const
+ { return Lookup::get_subtable<SubTable> (i); }
+
+ static inline bool lookup_type_is_reverse (unsigned int lookup_type)
+ { return lookup_type == SubTable::ReverseChainSingle; }
+
+ bool is_reverse () const
+ {
+ unsigned int type = get_type ();
+ if (unlikely (type == SubTable::Extension))
+ return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse ();
+ return lookup_type_is_reverse (type);
+ }
+
+ bool may_have_non_1to1 () const
+ {
+ hb_have_non_1to1_context_t c;
+ return dispatch (&c);
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ return_trace (dispatch (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c);
+ }
+
+ hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
+ {
+ if (!c->should_visit_lookup (this_index))
+ return hb_closure_context_t::default_return_value ();
+
+ c->set_recurse_func (dispatch_closure_recurse_func);
+
+ hb_closure_context_t::return_t ret = dispatch (c);
+
+ c->flush ();
+
+ return ret;
+ }
+
+ hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
+ {
+ if (c->is_lookup_visited (this_index))
+ return hb_closure_lookups_context_t::default_return_value ();
+
+ c->set_lookup_visited (this_index);
+ if (!intersects (c->glyphs))
+ {
+ c->set_lookup_inactive (this_index);
+ return hb_closure_lookups_context_t::default_return_value ();
+ }
+
+ c->set_recurse_func (dispatch_closure_lookups_recurse_func);
+
+ hb_closure_lookups_context_t::return_t ret = dispatch (c);
+ return ret;
+ }
+
+ hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
+ return dispatch (c);
+ }
+
+ template <typename set_t>
+ void collect_coverage (set_t *glyphs) const
+ {
+ hb_collect_coverage_context_t<set_t> c (glyphs);
+ dispatch (&c);
+ }
+
+ bool would_apply (hb_would_apply_context_t *c,
+ const hb_ot_layout_lookup_accelerator_t *accel) const
+ {
+ if (unlikely (!c->len)) return false;
+ if (!accel->may_have (c->glyphs[0])) return false;
+ return dispatch (c);
+ }
+
+ static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
+
+ bool serialize_single (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const HBGlyphID16> substitutes)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
+ if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ bool serialize_multiple (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> substitute_len_list,
+ hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
+ if (c->push<SubTable> ()->u.multiple.
+ serialize (c,
+ glyphs,
+ substitute_len_list,
+ substitute_glyphs_list))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ bool serialize_alternate (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> alternate_len_list,
+ hb_array_t<const HBGlyphID16> alternate_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
+
+ if (c->push<SubTable> ()->u.alternate.
+ serialize (c,
+ glyphs,
+ alternate_len_list,
+ alternate_glyphs_list))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ bool serialize_ligature (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> first_glyphs,
+ hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+ hb_array_t<const HBGlyphID16> ligatures_list,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
+ if (c->push<SubTable> ()->u.ligature.
+ serialize (c,
+ first_glyphs,
+ ligature_per_first_glyph_count_list,
+ ligatures_list,
+ component_count_list,
+ component_list))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ template <typename context_t>
+ static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+
+ static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
+
+ static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
+ {
+ if (!c->should_visit_lookup (lookup_index))
+ return hb_empty_t ();
+
+ hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
+
+ /* While in theory we should flush here, it will cause timeouts because a recursive
+ * lookup can keep growing the glyph set. Skip, and outer loop will retry up to
+ * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
+ //c->flush ();
+
+ return ret;
+ }
+
+ HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
+
+ bool subset (hb_subset_context_t *c) const
+ { return Lookup::subset<SubTable> (c); }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_SUBSTLOOKUP_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh
new file mode 100644
index 0000000000..53e963e2a2
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh
@@ -0,0 +1,77 @@
+#ifndef OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH
+#define OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH
+
+#include "Common.hh"
+#include "SingleSubst.hh"
+#include "MultipleSubst.hh"
+#include "AlternateSubst.hh"
+#include "LigatureSubst.hh"
+#include "ContextSubst.hh"
+#include "ChainContextSubst.hh"
+#include "ExtensionSubst.hh"
+#include "ReverseChainSingleSubst.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB {
+
+struct SubstLookupSubTable
+{
+ friend struct ::OT::Lookup;
+ friend struct SubstLookup;
+
+ protected:
+ union {
+ SingleSubst single;
+ MultipleSubst multiple;
+ AlternateSubst alternate;
+ LigatureSubst ligature;
+ ContextSubst context;
+ ChainContextSubst chainContext;
+ ExtensionSubst extension;
+ ReverseChainSingleSubst reverseChainContextSingle;
+ } u;
+ public:
+ DEFINE_SIZE_MIN (0);
+
+ enum Type {
+ Single = 1,
+ Multiple = 2,
+ Alternate = 3,
+ Ligature = 4,
+ Context = 5,
+ ChainContext = 6,
+ Extension = 7,
+ ReverseChainSingle = 8
+ };
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, lookup_type);
+ switch (lookup_type) {
+ case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
+ case Multiple: return_trace (u.multiple.dispatch (c, std::forward<Ts> (ds)...));
+ case Alternate: return_trace (u.alternate.dispatch (c, std::forward<Ts> (ds)...));
+ case Ligature: return_trace (u.ligature.dispatch (c, std::forward<Ts> (ds)...));
+ case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
+ case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
+ case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
+ case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, std::forward<Ts> (ds)...));
+ default: return_trace (c->default_return_value ());
+ }
+ }
+
+ bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c, lookup_type);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-bit-page.hh b/thirdparty/harfbuzz/src/hb-bit-page.hh
index 263be3d044..9759836654 100644
--- a/thirdparty/harfbuzz/src/hb-bit-page.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-page.hh
@@ -86,6 +86,72 @@ struct hb_bit_page_t
void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
{ if (v) add_range (a, b); else del_range (a, b); }
+
+ // Writes out page values to the array p. Returns the number of values
+ // written. At most size codepoints will be written.
+ unsigned int write (uint32_t base,
+ unsigned int start_value,
+ hb_codepoint_t *p,
+ unsigned int size) const
+ {
+ unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_bit = start_value & ELT_MASK;
+ unsigned int count = 0;
+ for (unsigned i = start_v; i < len () && count < size; i++)
+ {
+ elt_t bits = v[i];
+ uint32_t v_base = base | (i << ELT_BITS_LOG_2);
+ for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
+ {
+ if ((elt_t(1) << j) & bits) {
+ *p++ = v_base | j;
+ count++;
+ }
+ }
+ start_bit = 0;
+ }
+ return count;
+ }
+
+ // Writes out the values NOT in this page to the array p. Returns the
+ // number of values written. At most size codepoints will be written.
+ // Returns the number of codepoints written. next_value holds the next value
+ // that should be written (if not present in this page). This is used to fill
+ // any missing value gaps between this page and the previous page, if any.
+ // next_value is updated to one more than the last value present in this page.
+ unsigned int write_inverted (uint32_t base,
+ unsigned int start_value,
+ hb_codepoint_t *p,
+ unsigned int size,
+ hb_codepoint_t *next_value) const
+ {
+ unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_bit = start_value & ELT_MASK;
+ unsigned int count = 0;
+ for (unsigned i = start_v; i < len () && count < size; i++)
+ {
+ elt_t bits = v[i];
+ uint32_t v_offset = i << ELT_BITS_LOG_2;
+ for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
+ {
+ if ((elt_t(1) << j) & bits)
+ {
+ hb_codepoint_t value = base | v_offset | j;
+ // Emit all the missing values from next_value up to value - 1.
+ for (hb_codepoint_t k = *next_value; k < value && count < size; k++)
+ {
+ *p++ = k;
+ count++;
+ }
+ // Skip over this value;
+ *next_value = value + 1;
+ }
+ }
+ start_bit = 0;
+ }
+ return count;
+ }
+
bool is_equal (const hb_bit_page_t &other) const
{
return 0 == hb_memcmp (&v, &other.v, sizeof (v));
@@ -179,6 +245,9 @@ struct hb_bit_page_t
typedef unsigned long long elt_t;
static constexpr unsigned PAGE_BITS = 512;
static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
+ static constexpr unsigned PAGE_BITS_LOG_2 = 9;
+ static_assert (1 << PAGE_BITS_LOG_2 == PAGE_BITS, "");
+ static constexpr unsigned PAGE_BITMASK = PAGE_BITS - 1;
static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
@@ -186,7 +255,10 @@ struct hb_bit_page_t
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
+ static constexpr unsigned ELT_BITS_LOG_2 = 6;
+ static_assert (1 << ELT_BITS_LOG_2 == ELT_BITS, "");
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
+
static constexpr unsigned BITS = sizeof (vector_t) * 8;
static constexpr unsigned MASK = BITS - 1;
static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
diff --git a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
index 0832b0fc23..4a4ce34053 100644
--- a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
@@ -323,6 +323,14 @@ struct hb_bit_set_invertible_t
return true;
}
+ unsigned int next_many (hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size) const
+ {
+ return inverted ? s.next_many_inverted (codepoint, out, size)
+ : s.next_many (codepoint, out, size);
+ }
+
static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID;
/*
diff --git a/thirdparty/harfbuzz/src/hb-bit-set.hh b/thirdparty/harfbuzz/src/hb-bit-set.hh
index a471ee48b5..fcaff9f3be 100644
--- a/thirdparty/harfbuzz/src/hb-bit-set.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-set.hh
@@ -203,7 +203,7 @@ struct hb_bit_set_t
bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
- if (!count) return true;
+ if (unlikely (!count)) return true;
dirty ();
hb_codepoint_t g = *array;
hb_codepoint_t last_g = g;
@@ -222,7 +222,7 @@ struct hb_bit_set_t
if (v || page) /* The v check is to optimize out the page check if v is true. */
page->add (g);
- array = (const T *) ((const char *) array + stride);
+ array = &StructAtOffsetUnaligned<T> (array, stride);
count--;
}
while (count && (g = *array, g < end));
@@ -700,6 +700,99 @@ struct hb_bit_set_t
return true;
}
+ unsigned int next_many (hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size) const
+ {
+ // By default, start at the first bit of the first page of values.
+ unsigned int start_page = 0;
+ unsigned int start_page_value = 0;
+ if (unlikely (codepoint != INVALID))
+ {
+ const auto* page_map_array = page_map.arrayZ;
+ unsigned int major = get_major (codepoint);
+ unsigned int i = last_page_lookup;
+ if (unlikely (i >= page_map.length || page_map_array[i].major != major))
+ {
+ page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
+ if (i >= page_map.length)
+ return 0; // codepoint is greater than our max element.
+ }
+ start_page = i;
+ start_page_value = page_remainder (codepoint + 1);
+ if (unlikely (start_page_value == 0))
+ {
+ // The export-after value was last in the page. Start on next page.
+ start_page++;
+ start_page_value = 0;
+ }
+ }
+
+ unsigned int initial_size = size;
+ for (unsigned int i = start_page; i < page_map.length && size; i++)
+ {
+ uint32_t base = major_start (page_map[i].major);
+ unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size);
+ out += n;
+ size -= n;
+ start_page_value = 0;
+ }
+ return initial_size - size;
+ }
+
+ unsigned int next_many_inverted (hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size) const
+ {
+ unsigned int initial_size = size;
+ // By default, start at the first bit of the first page of values.
+ unsigned int start_page = 0;
+ unsigned int start_page_value = 0;
+ if (unlikely (codepoint != INVALID))
+ {
+ const auto* page_map_array = page_map.arrayZ;
+ unsigned int major = get_major (codepoint);
+ unsigned int i = last_page_lookup;
+ if (unlikely (i >= page_map.length || page_map_array[i].major != major))
+ {
+ page_map.bfind(major, &i, HB_NOT_FOUND_STORE_CLOSEST);
+ if (unlikely (i >= page_map.length))
+ {
+ // codepoint is greater than our max element.
+ while (++codepoint != INVALID && size)
+ {
+ *out++ = codepoint;
+ size--;
+ }
+ return initial_size - size;
+ }
+ }
+ start_page = i;
+ start_page_value = page_remainder (codepoint + 1);
+ if (unlikely (start_page_value == 0))
+ {
+ // The export-after value was last in the page. Start on next page.
+ start_page++;
+ start_page_value = 0;
+ }
+ }
+
+ hb_codepoint_t next_value = codepoint + 1;
+ for (unsigned int i=start_page; i<page_map.length && size; i++)
+ {
+ uint32_t base = major_start (page_map[i].major);
+ unsigned int n = pages[page_map[i].index].write_inverted (base, start_page_value, out, size, &next_value);
+ out += n;
+ size -= n;
+ start_page_value = 0;
+ }
+ while (next_value < HB_SET_VALUE_INVALID && size) {
+ *out++ = next_value++;
+ size--;
+ }
+ return initial_size - size;
+ }
+
bool has_population () const { return population != UINT_MAX; }
unsigned int get_population () const
{
@@ -809,8 +902,9 @@ struct hb_bit_set_t
}
page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
- unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
- hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
+ unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; }
+ unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; }
+ hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; }
};
diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc
index d36fcfde39..6a9ee3ccc8 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer.cc
@@ -295,7 +295,6 @@ hb_buffer_t::clear ()
idx = 0;
len = 0;
out_len = 0;
-
out_info = info;
memset (context, 0, sizeof context);
@@ -405,6 +404,7 @@ hb_buffer_t::sync ()
reset:
have_output = false;
out_len = 0;
+ out_info = info;
idx = 0;
}
diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc
index 5f383064c4..6ccc1b0a2b 100644
--- a/thirdparty/harfbuzz/src/hb-coretext.cc
+++ b/thirdparty/harfbuzz/src/hb-coretext.cc
@@ -897,7 +897,7 @@ resize_and_retry:
DEBUG_MSG (CORETEXT, nullptr, "Num runs: %d", num_runs);
buffer->len = 0;
- uint32_t status_and = ~0, status_or = 0;
+ uint32_t status_or = 0;
CGFloat advances_so_far = 0;
/* For right-to-left runs, CoreText returns the glyphs positioned such that
* any trailing whitespace is to the left of (0,0). Adjust coordinate system
@@ -918,7 +918,6 @@ resize_and_retry:
CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex (glyph_runs, i));
CTRunStatus run_status = CTRunGetStatus (run);
status_or |= run_status;
- status_and &= run_status;
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
CGFloat run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr);
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
@@ -1140,21 +1139,6 @@ resize_and_retry:
buffer->len += num_glyphs;
}
- /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
- * or if it does, it doesn't respect it. So we get runs with wrong
- * directions. As such, disable the assert... It wouldn't crash, but
- * cursoring will be off...
- *
- * https://crbug.com/419769
- */
- if (false)
- {
- /* Make sure all runs had the expected direction. */
- HB_UNUSED bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
- assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
- assert (bool (status_or & kCTRunStatusRightToLeft) == backward);
- }
-
buffer->clear_positions ();
unsigned int count = buffer->len;
diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc
index 40311e1b91..0cfbb22e31 100644
--- a/thirdparty/harfbuzz/src/hb-ft.cc
+++ b/thirdparty/harfbuzz/src/hb-ft.cc
@@ -382,6 +382,7 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
/* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
* have a Y growing upward. Hence the extra negation. */
+
return (-v + (1<<9)) >> 10;
}
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
index fde57cdc5b..a8747ee5a1 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
@@ -714,7 +714,7 @@ struct CmapSubtableLongSegmented
if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
end = start + (hb_codepoint_t) num_glyphs - gid;
- out->add_range (start, end);
+ out->add_range (start, hb_min (end, 0x10FFFFu));
}
}
@@ -883,7 +883,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
hb_codepoint_t first = arrayZ[i].startUnicodeValue;
hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
(hb_codepoint_t) HB_UNICODE_MAX);
- out->add_range (first, last);
+ out->add_range (first, hb_min (last, 0x10FFFFu));
}
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc
index 77d3f639db..0f44ee4d5f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-font.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-font.cc
@@ -131,11 +131,25 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
- for (unsigned int i = 0; i < count; i++)
+ if (vmtx.has_data ())
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ else
{
- *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
- first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
- first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ hb_font_extents_t font_extents;
+ font->get_h_extents_with_fallback (&font_extents);
+ hb_position_t advance = -(font_extents.ascender - font_extents.descender);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = advance;
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
}
}
#endif
@@ -163,9 +177,19 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
hb_glyph_extents_t extents = {0};
if (ot_face->glyf->get_extents (font, glyph, &extents))
{
- const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
- hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
- *y = extents.y_bearing + font->em_scale_y (tsb);
+ if (ot_face->vmtx->has_data ())
+ {
+ const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+ hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
+ *y = extents.y_bearing + font->em_scale_y (tsb);
+ return true;
+ }
+
+ hb_font_extents_t font_extents;
+ font->get_h_extents_with_fallback (&font_extents);
+ hb_position_t advance = font_extents.ascender - font_extents.descender;
+ int diff = advance - -extents.height;
+ *y = extents.y_bearing + (diff >> 1);
return true;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
index 066e152da3..b4ac688344 100644
--- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
@@ -820,8 +820,7 @@ struct glyf
}
#ifndef HB_NO_VAR
- if (unlikely (!glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ())))
- return false;
+ glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
#endif
switch (type) {
diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
index 7487e40e6d..d5e1fc91d2 100644
--- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -170,13 +170,12 @@ struct hmtxvmtx
{
friend struct hmtxvmtx;
- accelerator_t (hb_face_t *face,
- unsigned int default_advance_ = 0)
+ 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);
- default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
+ default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face);
/* Populate count variables and sort them out as we go */
@@ -220,6 +219,8 @@ struct hmtxvmtx
var_table.destroy ();
}
+ bool has_data () const { return (bool) num_bearings; }
+
int get_side_bearing (hb_codepoint_t glyph) const
{
if (glyph < num_long_metrics)
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
index 60a1906155..f2a58028e3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
@@ -37,7 +37,7 @@
#ifndef HB_MAX_NESTING_LEVEL
-#define HB_MAX_NESTING_LEVEL 6
+#define HB_MAX_NESTING_LEVEL 64
#endif
#ifndef HB_MAX_CONTEXT_LENGTH
#define HB_MAX_CONTEXT_LENGTH 64
@@ -60,6 +60,10 @@
#define HB_MAX_LANGSYS 2000
#endif
+#ifndef HB_MAX_LANGSYS_FEATURE_COUNT
+#define HB_MAX_LANGSYS_FEATURE_COUNT 50000
+#endif
+
#ifndef HB_MAX_FEATURES
#define HB_MAX_FEATURES 750
#endif
@@ -105,34 +109,15 @@ struct hb_prune_langsys_context_t
script_langsys_map (script_langsys_map_),
duplicate_feature_map (duplicate_feature_map_),
new_feature_indexes (new_collected_feature_indexes_),
- script_count (0),langsys_count (0) {}
+ script_count (0),langsys_feature_count (0) {}
- bool visitedScript (const void *s)
- {
- if (script_count++ > HB_MAX_SCRIPTS)
- return true;
-
- return visited (s, visited_script);
- }
+ bool visitScript ()
+ { return script_count++ < HB_MAX_SCRIPTS; }
- bool visitedLangsys (const void *l)
+ bool visitLangsys (unsigned feature_count)
{
- if (langsys_count++ > HB_MAX_LANGSYS)
- return true;
-
- return visited (l, visited_langsys);
- }
-
- private:
- template <typename T>
- bool visited (const T *p, hb_set_t &visited_set)
- {
- hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) p - (uintptr_t) table);
- if (visited_set.in_error () || visited_set.has (delta))
- return true;
-
- visited_set.add (delta);
- return false;
+ langsys_feature_count += feature_count;
+ return langsys_feature_count < HB_MAX_LANGSYS_FEATURE_COUNT;
}
public:
@@ -142,10 +127,8 @@ struct hb_prune_langsys_context_t
hb_set_t *new_feature_indexes;
private:
- hb_set_t visited_script;
- hb_set_t visited_langsys;
unsigned script_count;
- unsigned langsys_count;
+ unsigned langsys_feature_count;
};
struct hb_subset_layout_context_t :
@@ -643,11 +626,14 @@ struct LangSys
| hb_map (feature_index_map)
;
- if (iter.len () != o_iter.len ())
- return false;
+ for (; iter && o_iter; iter++, o_iter++)
+ {
+ unsigned a = *iter;
+ unsigned b = *o_iter;
+ if (a != b) return false;
+ }
- for (const auto _ : + hb_zip (iter, o_iter))
- if (_.first != _.second) return false;
+ if (iter || o_iter) return false;
return true;
}
@@ -732,7 +718,7 @@ struct Script
unsigned script_index) const
{
if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
- if (c->visitedScript (this)) return;
+ if (!c->visitScript ()) return;
if (!c->script_langsys_map->has (script_index))
{
@@ -749,15 +735,14 @@ struct Script
{
//only collect features from non-redundant langsys
const LangSys& d = get_default_lang_sys ();
- if (!c->visitedLangsys (&d)) {
+ 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->visitedLangsys (&l)) continue;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
if (l.compare (d, c->duplicate_feature_map)) continue;
l.collect_features (c);
@@ -769,7 +754,7 @@ struct Script
for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
{
const LangSys& l = this+_.first.offset;
- if (c->visitedLangsys (&l)) continue;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
l.collect_features (c);
c->script_langsys_map->get (script_index)->add (_.second);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
index 0b0bc547bd..bef381430b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -29,1727 +29,14 @@
#ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
#define HB_OT_LAYOUT_GSUB_TABLE_HH
-#include "hb-ot-layout-gsubgpos.hh"
-
+#include "OT/Layout/GSUB/GSUB.hh"
namespace OT {
-typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
-
-template<typename Iterator>
-static void SingleSubst_serialize (hb_serialize_context_t *c,
- Iterator it);
-
-
-struct SingleSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- unsigned d = deltaGlyphID;
-
- + hb_iter (this+coverage)
- | hb_filter (c->parent_active_glyphs ())
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
- | hb_sink (c->output)
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- unsigned d = deltaGlyphID;
- + hb_iter (this+coverage)
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
- | hb_sink (c->output)
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
- unsigned int index = (this+coverage).get_coverage (glyph_id);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- /* According to the Adobe Annotated OpenType Suite, result is always
- * limited to 16bit. */
- glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
- c->replace_glyph (glyph_id);
-
- return_trace (true);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator glyphs,
- unsigned delta)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
- c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- hb_codepoint_t delta = deltaGlyphID;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting ([&] (hb_codepoint_t g) {
- return hb_codepoint_pair_t (g,
- (g + delta) & 0xFFFF); })
- | hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t
- { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
- ;
-
- bool ret = bool (it);
- SingleSubst_serialize (c->serializer, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- HBUINT16 deltaGlyphID; /* Add to original GlyphID to get
- * substitute GlyphID, modulo 0x10000 */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-
-struct SingleSubstFormat2
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, substitute)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_sink (c->output)
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- + hb_zip (this+coverage, substitute)
- | hb_map (hb_second)
- | hb_sink (c->output)
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- if (unlikely (index >= substitute.len)) return_trace (false);
-
- c->replace_glyph (substitute[index]);
-
- return_trace (true);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator,
- hb_codepoint_pair_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator it)
- {
- TRACE_SERIALIZE (this);
- auto substitutes =
- + it
- | hb_map (hb_second)
- ;
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
- if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_zip (this+coverage, substitute)
- | hb_filter (glyphset, hb_first)
- | hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
- { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
- ;
-
- bool ret = bool (it);
- SingleSubst_serialize (c->serializer, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16Of<HBGlyphID16>
- substitute; /* Array of substitute
- * GlyphIDs--ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, substitute);
-};
-
-struct SingleSubst
-{
-
- template<typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator,
- const hb_codepoint_pair_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned format = 2;
- unsigned delta = 0;
- if (glyphs)
- {
- format = 1;
- auto get_delta = [=] (hb_codepoint_pair_t _)
- { return (unsigned) (_.second - _.first) & 0xFFFF; };
- delta = get_delta (*glyphs);
- if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
- }
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c,
- + glyphs
- | hb_map_retains_sorting (hb_first),
- delta));
- case 2: return_trace (u.format2.serialize (c, glyphs));
- default:return_trace (false);
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, 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 */
- SingleSubstFormat1 format1;
- SingleSubstFormat2 format2;
- } u;
-};
-
-template<typename Iterator>
-static void
-SingleSubst_serialize (hb_serialize_context_t *c,
- Iterator it)
-{ c->start_embed<SingleSubst> ()->serialize (c, it); }
-
-struct Sequence
-{
- bool intersects (const hb_set_t *glyphs) const
- { return hb_all (substitute, glyphs); }
-
- void closure (hb_closure_context_t *c) const
- { c->output->add_array (substitute.arrayZ, substitute.len); }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { c->output->add_array (substitute.arrayZ, substitute.len); }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int count = substitute.len;
-
- /* Special-case to make it in-place and not consider this
- * as a "multiplied" substitution. */
- if (unlikely (count == 1))
- {
- c->replace_glyph (substitute.arrayZ[0]);
- return_trace (true);
- }
- /* Spec disallows this, but Uniscribe allows it.
- * https://github.com/harfbuzz/harfbuzz/issues/253 */
- else if (unlikely (count == 0))
- {
- c->buffer->delete_glyph ();
- return_trace (true);
- }
-
- unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
- HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
- unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
-
- for (unsigned int i = 0; i < count; i++)
- {
- /* If is attached to a ligature, don't disturb that.
- * https://github.com/harfbuzz/harfbuzz/issues/3069 */
- if (!lig_id)
- _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
- c->output_glyph_for_component (substitute.arrayZ[i], klass);
- }
- c->buffer->skip_glyph ();
-
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator subst)
- {
- TRACE_SERIALIZE (this);
- return_trace (substitute.serialize (c, subst));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- if (!intersects (&glyphset)) return_trace (false);
-
- auto it =
- + hb_iter (substitute)
- | hb_map (glyph_map)
- ;
-
- auto *out = c->serializer->start_embed (*this);
- return_trace (out->serialize (c->serializer, it));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (substitute.sanitize (c));
- }
-
- protected:
- Array16Of<HBGlyphID16>
- substitute; /* String of GlyphIDs to substitute */
- public:
- DEFINE_SIZE_ARRAY (2, substitute);
-};
-
-struct MultipleSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return true; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, sequence)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.closure (c); })
- ;
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- + hb_zip (this+coverage, sequence)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- return_trace ((this+sequence[index]).apply (c));
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID16> substitute_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < glyphs.length; i++)
- {
- unsigned int substitute_len = substitute_len_list[i];
- if (unlikely (!sequence[i]
- .serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
- return_trace (false);
- substitute_glyphs_list += substitute_len;
- }
- return_trace (coverage.serialize_serialize (c, glyphs));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + hb_zip (this+coverage, sequence)
- | hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->sequence, this), hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
- return_trace (bool (new_coverage));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16OfOffset16To<Sequence>
- sequence; /* Array of Sequence tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, sequence);
-};
-
-struct MultipleSubst
-{
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID16> substitute_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 1;
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
- default:return_trace (false);
- }
- }
-
- 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 */
- MultipleSubstFormat1 format1;
- } u;
-};
-
-struct AlternateSet
-{
- bool intersects (const hb_set_t *glyphs) const
- { return hb_any (alternates, glyphs); }
-
- void closure (hb_closure_context_t *c) const
- { c->output->add_array (alternates.arrayZ, alternates.len); }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { c->output->add_array (alternates.arrayZ, alternates.len); }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int count = alternates.len;
-
- if (unlikely (!count)) return_trace (false);
-
- hb_mask_t glyph_mask = c->buffer->cur().mask;
- hb_mask_t lookup_mask = c->lookup_mask;
-
- /* Note: This breaks badly if two features enabled this lookup together. */
- unsigned int shift = hb_ctz (lookup_mask);
- unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
-
- /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
- if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
- {
- /* Maybe we can do better than unsafe-to-break all; but since we are
- * changing random state, it would be hard to track that. Good 'nough. */
- c->buffer->unsafe_to_break (0, c->buffer->len);
- alt_index = c->random_number () % count + 1;
- }
-
- if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
-
- c->replace_glyph (alternates[alt_index - 1]);
-
- return_trace (true);
- }
-
- unsigned
- get_alternates (unsigned start_offset,
- unsigned *alternate_count /* IN/OUT. May be NULL. */,
- hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
- {
- if (alternates.len && alternate_count)
- {
- + alternates.sub_array (start_offset, alternate_count)
- | hb_sink (hb_array (alternate_glyphs, *alternate_count))
- ;
- }
- return alternates.len;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator alts)
- {
- TRACE_SERIALIZE (this);
- return_trace (alternates.serialize (c, alts));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_iter (alternates)
- | hb_filter (glyphset)
- | hb_map (glyph_map)
- ;
-
- auto *out = c->serializer->start_embed (*this);
- return_trace (out->serialize (c->serializer, it) &&
- out->alternates);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (alternates.sanitize (c));
- }
-
- protected:
- Array16Of<HBGlyphID16>
- alternates; /* Array of alternate GlyphIDs--in
- * arbitrary order */
- public:
- DEFINE_SIZE_ARRAY (2, alternates);
-};
-
-struct AlternateSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, alternateSet)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- + hb_zip (this+coverage, alternateSet)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- unsigned
- get_glyph_alternates (hb_codepoint_t gid,
- unsigned start_offset,
- unsigned *alternate_count /* IN/OUT. May be NULL. */,
- hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
- { return (this+alternateSet[(this+coverage).get_coverage (gid)])
- .get_alternates (start_offset, alternate_count, alternate_glyphs); }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- return_trace ((this+alternateSet[index]).apply (c));
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> alternate_len_list,
- hb_array_t<const HBGlyphID16> alternate_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < glyphs.length; i++)
- {
- unsigned int alternate_len = alternate_len_list[i];
- if (unlikely (!alternateSet[i]
- .serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
- return_trace (false);
- alternate_glyphs_list += alternate_len;
- }
- return_trace (coverage.serialize_serialize (c, glyphs));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + hb_zip (this+coverage, alternateSet)
- | hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
- return_trace (bool (new_coverage));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16OfOffset16To<AlternateSet>
- alternateSet; /* Array of AlternateSet tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, alternateSet);
-};
-
-struct AlternateSubst
-{
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> alternate_len_list,
- hb_array_t<const HBGlyphID16> alternate_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 1;
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
- default:return_trace (false);
- }
- }
-
- 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 */
- AlternateSubstFormat1 format1;
- } u;
-};
-
-
-struct Ligature
-{
- bool intersects (const hb_set_t *glyphs) const
- { return hb_all (component, glyphs); }
-
- void closure (hb_closure_context_t *c) const
- {
- if (!intersects (c->glyphs)) return;
- c->output->add (ligGlyph);
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- c->input->add_array (component.arrayZ, component.get_length ());
- c->output->add (ligGlyph);
- }
-
- bool would_apply (hb_would_apply_context_t *c) const
- {
- if (c->len != component.lenP1)
- return false;
-
- for (unsigned int i = 1; i < c->len; i++)
- if (likely (c->glyphs[i] != component[i]))
- return false;
-
- return true;
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int count = component.lenP1;
-
- if (unlikely (!count)) return_trace (false);
-
- /* Special-case to make it in-place and not consider this
- * as a "ligated" substitution. */
- if (unlikely (count == 1))
- {
- c->replace_glyph (ligGlyph);
- return_trace (true);
- }
-
- unsigned int total_component_count = 0;
-
- unsigned int match_end = 0;
- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-
- if (likely (!match_input (c, count,
- &component[1],
- match_glyph,
- nullptr,
- &match_end,
- match_positions,
- &total_component_count)))
- {
- c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
- return_trace (false);
- }
-
- ligate_input (c,
- count,
- match_positions,
- match_end,
- ligGlyph,
- total_component_count);
-
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- hb_codepoint_t ligature,
- Iterator components /* Starting from second */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- ligGlyph = ligature;
- if (unlikely (!component.serialize (c, components))) return_trace (false);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
- // Ensure Coverage table is always packed after this.
- c->serializer->add_virtual_link (coverage_idx);
-
- auto it =
- + hb_iter (component)
- | hb_map (glyph_map)
- ;
-
- auto *out = c->serializer->start_embed (*this);
- return_trace (out->serialize (c->serializer,
- glyph_map[ligGlyph],
- it));
- }
-
- public:
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
- }
-
- protected:
- HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */
- HeadlessArrayOf<HBGlyphID16>
- component; /* Array of component GlyphIDs--start
- * with the second component--ordered
- * in writing direction */
- public:
- DEFINE_SIZE_ARRAY (4, component);
-};
-
-struct LigatureSet
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
- | hb_any
- ;
- }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.closure (c); })
- ;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); })
- ;
- }
-
- bool would_apply (hb_would_apply_context_t *c) const
- {
- return
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_map ([c] (const Ligature &_) { return _.would_apply (c); })
- | hb_any
- ;
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int num_ligs = ligature.len;
- for (unsigned int i = 0; i < num_ligs; i++)
- {
- const Ligature &lig = this+ligature[i];
- if (lig.apply (c)) return_trace (true);
- }
-
- return_trace (false);
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_array_t<const HBGlyphID16> ligatures,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID16> &component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
- for (unsigned int i = 0; i < ligatures.length; i++)
- {
- unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
- if (unlikely (!ligature[i].serialize_serialize (c,
- ligatures[i],
- component_list.sub_array (0, component_count))))
- return_trace (false);
- component_list += component_count;
- }
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- + hb_iter (ligature)
- | hb_filter (subset_offset_array (c, out->ligature, this, coverage_idx))
- | hb_drain
- ;
-
- if (bool (out->ligature))
- // Ensure Coverage table is always packed after this.
- c->serializer->add_virtual_link (coverage_idx);
-
- return_trace (bool (out->ligature));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (ligature.sanitize (c, this));
- }
-
- protected:
- Array16OfOffset16To<Ligature>
- ligature; /* Array LigatureSet tables
- * ordered by preference */
- public:
- DEFINE_SIZE_ARRAY (2, ligature);
-};
-
-struct LigatureSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return
- + hb_zip (this+coverage, ligatureSet)
- | hb_filter (*glyphs, hb_first)
- | hb_map (hb_second)
- | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
- { return (this+_).intersects (glyphs); })
- | hb_any
- ;
- }
-
- bool may_have_non_1to1 () const
- { return true; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, ligatureSet)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
-
- + hb_zip (this+coverage, ligatureSet)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); })
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- {
- unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
- if (likely (index == NOT_COVERED)) return false;
-
- const LigatureSet &lig_set = this+ligatureSet[index];
- return lig_set.would_apply (c);
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- const LigatureSet &lig_set = this+ligatureSet[index];
- return_trace (lig_set.apply (c));
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> first_glyphs,
- hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- hb_array_t<const HBGlyphID16> ligatures_list,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < first_glyphs.length; i++)
- {
- unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
- if (unlikely (!ligatureSet[i]
- .serialize_serialize (c,
- ligatures_list.sub_array (0, ligature_count),
- component_count_list.sub_array (0, ligature_count),
- component_list))) return_trace (false);
- ligatures_list += ligature_count;
- component_count_list += ligature_count;
- }
- return_trace (coverage.serialize_serialize (c, first_glyphs));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- // Due to a bug in some older versions of windows 7 the Coverage table must be
- // packed after the LigatureSet and Ligature tables, so serialize Coverage first
- // which places it last in the packed order.
- hb_set_t new_coverage;
- + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
- | hb_filter (glyphset, hb_first)
- | hb_filter ([&] (const LigatureSet& _) {
- return _.intersects (&glyphset);
- }, hb_second)
- | hb_map (hb_first)
- | hb_sink (new_coverage);
-
- if (!c->serializer->push<Coverage> ()
- ->serialize (c->serializer,
- + new_coverage.iter () | hb_map_retains_sorting (glyph_map)))
- {
- c->serializer->pop_discard ();
- return_trace (false);
- }
-
- unsigned coverage_idx = c->serializer->pop_pack ();
- c->serializer->add_link (out->coverage, coverage_idx);
-
- + hb_zip (this+coverage, ligatureSet)
- | hb_filter (new_coverage, hb_first)
- | hb_map (hb_second)
- // to ensure that the repacker always orders the coverage table after the LigatureSet
- // and LigatureSubtable's they will be linked to the Coverage table via a virtual link
- // the coverage table object idx is passed down to facilitate this.
- | hb_apply (subset_offset_array (c, out->ligatureSet, this, coverage_idx))
- ;
-
- return_trace (bool (new_coverage));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16OfOffset16To<LigatureSet>
- ligatureSet; /* Array LigatureSet tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, ligatureSet);
-};
-
-struct LigatureSubst
-{
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> first_glyphs,
- hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- hb_array_t<const HBGlyphID16> ligatures_list,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 1;
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c,
- first_glyphs,
- ligature_per_first_glyph_count_list,
- ligatures_list,
- component_count_list,
- component_list));
- default:return_trace (false);
- }
- }
-
- 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 */
- LigatureSubstFormat1 format1;
- } u;
-};
-
-
-struct ContextSubst : Context {};
-
-struct ChainContextSubst : ChainContext {};
-
-struct ExtensionSubst : Extension<ExtensionSubst>
-{
- typedef struct SubstLookupSubTable SubTable;
- bool is_reverse () const;
-};
-
-
-struct ReverseChainSingleSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- if (!(this+coverage).intersects (glyphs))
- return false;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
-
- unsigned int count;
-
- count = backtrack.len;
- for (unsigned int i = 0; i < count; i++)
- if (!(this+backtrack[i]).intersects (glyphs))
- return false;
-
- count = lookahead.len;
- for (unsigned int i = 0; i < count; i++)
- if (!(this+lookahead[i]).intersects (glyphs))
- return false;
-
- return true;
- }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- if (!intersects (c->glyphs)) return;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
-
- + hb_zip (this+coverage, substitute)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_sink (c->output)
- ;
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
-
- unsigned int count;
-
- count = backtrack.len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- count = lookahead.len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
-
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
- count = substitute.len;
- c->output->add_array (substitute.arrayZ, substitute.len);
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
- return_trace (false); /* No chaining to this type */
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
-
- if (unlikely (index >= substitute.len)) return_trace (false);
-
- unsigned int start_index = 0, end_index = 0;
- if (match_backtrack (c,
- backtrack.len, (HBUINT16 *) backtrack.arrayZ,
- match_coverage, this,
- &start_index) &&
- match_lookahead (c,
- lookahead.len, (HBUINT16 *) lookahead.arrayZ,
- match_coverage, this,
- c->buffer->idx + 1, &end_index))
- {
- c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
- c->replace_glyph_inplace (substitute[index]);
- /* Note: We DON'T decrease buffer->idx. The main loop does it
- * for us. This is useful for preventing surprises if someone
- * calls us through a Context lookup. */
- return_trace (true);
- }
- else
- {
- c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
- return_trace (false);
- }
- }
-
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
-
- if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
- return_trace (false);
-
- for (auto& offset : it) {
- auto *o = out->serialize_append (c->serializer);
- if (unlikely (!o) || !o->serialize_subset (c, offset, this))
- return_trace (false);
- }
-
- return_trace (true);
- }
-
- template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
- hb_requires (hb_is_iterator (BacktrackIterator)),
- hb_requires (hb_is_iterator (LookaheadIterator))>
- bool serialize (hb_subset_context_t *c,
- Iterator coverage_subst_iter,
- BacktrackIterator backtrack_iter,
- LookaheadIterator lookahead_iter) const
- {
- TRACE_SERIALIZE (this);
-
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->check_success (out))) return_trace (false);
- if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
- if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
-
- if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
- if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
-
- auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID16>> ();
- auto substitutes =
- + coverage_subst_iter
- | hb_map (hb_second)
- ;
-
- auto glyphs =
- + coverage_subst_iter
- | hb_map_retains_sorting (hb_first)
- ;
- if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
- return_trace (false);
-
- if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs)))
- return_trace (false);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
-
- auto it =
- + hb_zip (this+coverage, substitute)
- | hb_filter (glyphset, hb_first)
- | hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
- { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
- ;
-
- return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
- return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- if (!lookahead.sanitize (c, this))
- return_trace (false);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
- return_trace (substitute.sanitize (c));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of table */
- Array16OfOffset16To<Coverage>
- backtrack; /* Array of coverage tables
- * in backtracking sequence, in glyph
- * sequence order */
- Array16OfOffset16To<Coverage>
- lookaheadX; /* Array of coverage tables
- * in lookahead sequence, in glyph
- * sequence order */
- Array16Of<HBGlyphID16>
- substituteX; /* Array of substitute
- * GlyphIDs--ordered by Coverage Index */
- public:
- DEFINE_SIZE_MIN (10);
-};
-
-struct ReverseChainSingleSubst
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- ReverseChainSingleSubstFormat1 format1;
- } u;
-};
-
-
-
-/*
- * SubstLookup
- */
-
-struct SubstLookupSubTable
-{
- friend struct Lookup;
- friend struct SubstLookup;
-
- enum Type {
- Single = 1,
- Multiple = 2,
- Alternate = 3,
- Ligature = 4,
- Context = 5,
- ChainContext = 6,
- Extension = 7,
- ReverseChainSingle = 8
- };
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, lookup_type);
- switch (lookup_type) {
- case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
- case Multiple: return_trace (u.multiple.dispatch (c, std::forward<Ts> (ds)...));
- case Alternate: return_trace (u.alternate.dispatch (c, std::forward<Ts> (ds)...));
- case Ligature: return_trace (u.ligature.dispatch (c, std::forward<Ts> (ds)...));
- case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
- case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
- case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
- case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, std::forward<Ts> (ds)...));
- default: return_trace (c->default_return_value ());
- }
- }
-
- bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c, lookup_type);
- }
-
- protected:
- union {
- SingleSubst single;
- MultipleSubst multiple;
- AlternateSubst alternate;
- LigatureSubst ligature;
- ContextSubst context;
- ChainContextSubst chainContext;
- ExtensionSubst extension;
- ReverseChainSingleSubst reverseChainContextSingle;
- } u;
- public:
- DEFINE_SIZE_MIN (0);
-};
-
-
-struct SubstLookup : Lookup
-{
- typedef SubstLookupSubTable SubTable;
-
- const SubTable& get_subtable (unsigned int i) const
- { return Lookup::get_subtable<SubTable> (i); }
-
- static inline bool lookup_type_is_reverse (unsigned int lookup_type)
- { return lookup_type == SubTable::ReverseChainSingle; }
-
- bool is_reverse () const
- {
- unsigned int type = get_type ();
- if (unlikely (type == SubTable::Extension))
- return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse ();
- return lookup_type_is_reverse (type);
- }
-
- bool may_have_non_1to1 () const
- {
- hb_have_non_1to1_context_t c;
- return dispatch (&c);
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- return_trace (dispatch (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c);
- }
-
- hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
- {
- if (!c->should_visit_lookup (this_index))
- return hb_closure_context_t::default_return_value ();
-
- c->set_recurse_func (dispatch_closure_recurse_func);
-
- hb_closure_context_t::return_t ret = dispatch (c);
-
- c->flush ();
-
- return ret;
- }
-
- hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
- {
- if (c->is_lookup_visited (this_index))
- return hb_closure_lookups_context_t::default_return_value ();
-
- c->set_lookup_visited (this_index);
- if (!intersects (c->glyphs))
- {
- c->set_lookup_inactive (this_index);
- return hb_closure_lookups_context_t::default_return_value ();
- }
-
- c->set_recurse_func (dispatch_closure_lookups_recurse_func);
-
- hb_closure_lookups_context_t::return_t ret = dispatch (c);
- return ret;
- }
-
- hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
- return dispatch (c);
- }
-
- template <typename set_t>
- void collect_coverage (set_t *glyphs) const
- {
- hb_collect_coverage_context_t<set_t> c (glyphs);
- dispatch (&c);
- }
-
- bool would_apply (hb_would_apply_context_t *c,
- const hb_ot_layout_lookup_accelerator_t *accel) const
- {
- if (unlikely (!c->len)) return false;
- if (!accel->may_have (c->glyphs[0])) return false;
- return dispatch (c);
- }
-
- static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
- bool serialize_single (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const HBGlyphID16> substitutes)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
- if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- bool serialize_multiple (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID16> substitute_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
- if (c->push<SubTable> ()->u.multiple.
- serialize (c,
- glyphs,
- substitute_len_list,
- substitute_glyphs_list))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- bool serialize_alternate (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> alternate_len_list,
- hb_array_t<const HBGlyphID16> alternate_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
-
- if (c->push<SubTable> ()->u.alternate.
- serialize (c,
- glyphs,
- alternate_len_list,
- alternate_glyphs_list))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- bool serialize_ligature (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> first_glyphs,
- hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- hb_array_t<const HBGlyphID16> ligatures_list,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
- if (c->push<SubTable> ()->u.ligature.
- serialize (c,
- first_glyphs,
- ligature_per_first_glyph_count_list,
- ligatures_list,
- component_count_list,
- component_list))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- template <typename context_t>
- static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
-
- static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
-
- static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
- {
- if (!c->should_visit_lookup (lookup_index))
- return hb_empty_t ();
-
- hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
-
- /* While in theory we should flush here, it will cause timeouts because a recursive
- * lookup can keep growing the glyph set. Skip, and outer loop will retry up to
- * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
- //c->flush ();
-
- return ret;
- }
-
- HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
-
- bool subset (hb_subset_context_t *c) const
- { return Lookup::subset<SubTable> (c); }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return Lookup::sanitize<SubTable> (c); }
-};
-
-/*
- * GSUB -- Glyph Substitution
- * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
- */
-
-struct GSUB : GSUBGPOS
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
-
- const SubstLookup& get_lookup (unsigned int i) const
- { return static_cast<const SubstLookup &> (GSUBGPOS::get_lookup (i)); }
-
- bool subset (hb_subset_context_t *c) const
- {
- hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
- return GSUBGPOS::subset<SubstLookup> (&l);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return GSUBGPOS::sanitize<SubstLookup> (c); }
-
- HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
- hb_face_t *face) const;
-
- void closure_lookups (hb_face_t *face,
- const hb_set_t *glyphs,
- hb_set_t *lookup_indexes /* IN/OUT */) const
- { GSUBGPOS::closure_lookups<SubstLookup> (face, glyphs, lookup_indexes); }
-
- typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
-};
-
-
-struct GSUB_accelerator_t : GSUB::accelerator_t {
- GSUB_accelerator_t (hb_face_t *face) : GSUB::accelerator_t (face) {}
-};
-
+using Layout::GSUB::SubstLookup;
+using Layout::GSUB::ExtensionSubst;
+// TODO(garretrieger): Move into the new layout directory.
/* Out-of-class implementation for methods recursing */
#ifndef HB_NO_OT_LAYOUT
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
index 65de131f85..3faa1e53d5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
@@ -408,12 +408,11 @@ struct hb_ot_apply_context_t :
{
matcher_t () :
lookup_props (0),
+ mask (-1),
ignore_zwnj (false),
ignore_zwj (false),
- mask (-1),
-#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
- syllable arg1(0),
-#undef arg1
+ per_syllable (false),
+ syllable {0},
match_func (nullptr),
match_data (nullptr) {}
@@ -423,7 +422,8 @@ struct hb_ot_apply_context_t :
void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
void set_mask (hb_mask_t mask_) { mask = mask_; }
- void set_syllable (uint8_t syllable_) { syllable = syllable_; }
+ void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; }
+ void set_syllable (uint8_t syllable_) { syllable = per_syllable ? syllable_ : 0; }
void set_match_func (match_func_t match_func_,
const void *match_data_)
{ match_func = match_func_; match_data = match_data_; }
@@ -469,9 +469,10 @@ struct hb_ot_apply_context_t :
protected:
unsigned int lookup_props;
+ hb_mask_t mask;
bool ignore_zwnj;
bool ignore_zwj;
- hb_mask_t mask;
+ bool per_syllable;
uint8_t syllable;
match_func_t match_func;
const void *match_data;
@@ -490,6 +491,7 @@ struct hb_ot_apply_context_t :
/* Ignore ZWJ if we are matching context, or asked to. */
matcher.set_ignore_zwj (context_match || c->auto_zwj);
matcher.set_mask (context_match ? -1 : c->lookup_mask);
+ matcher.set_per_syllable (c->per_syllable);
}
void set_lookup_props (unsigned int lookup_props)
{
@@ -636,6 +638,7 @@ struct hb_ot_apply_context_t :
bool has_glyph_classes;
bool auto_zwnj;
bool auto_zwj;
+ bool per_syllable;
bool random;
uint32_t random_state;
@@ -664,6 +667,7 @@ struct hb_ot_apply_context_t :
has_glyph_classes (gdef.has_glyph_classes ()),
auto_zwnj (true),
auto_zwj (true),
+ per_syllable (false),
random (false),
random_state (1) { init_iters (); }
@@ -676,6 +680,7 @@ struct hb_ot_apply_context_t :
void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); }
void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); }
+ void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; init_iters (); }
void set_random (bool random_) { random = random_; }
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
@@ -1415,13 +1420,18 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
if (unlikely (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index))
continue;
+ unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
+
+ /* This can happen if earlier recursed lookups deleted many entries. */
+ if (unlikely (match_positions[idx] >= orig_len))
+ continue;
+
if (unlikely (!buffer->move_to (match_positions[idx])))
break;
if (unlikely (buffer->max_ops <= 0))
break;
- unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
if (!c->recurse (lookupRecord[i].lookupListIndex))
continue;
@@ -1457,15 +1467,18 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
*/
end += delta;
- if (end <= int (match_positions[idx]))
+ if (end < int (match_positions[idx]))
{
/* End might end up being smaller than match_positions[idx] if the recursed
- * lookup ended up removing many items, more than we have had matched.
- * Just never rewind end back and get out of here.
- * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
+ * lookup ended up removing many items.
+ * Just never rewind end beyond start of current position, since that is
+ * not possible in the recursed lookup. Also adjust delta as such.
+ *
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=659496
+ * https://github.com/harfbuzz/harfbuzz/issues/1611
+ */
+ delta += match_positions[idx] - end;
end = match_positions[idx];
- /* There can't be any further changes. */
- break;
}
unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
@@ -1477,7 +1490,7 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
}
else
{
- /* NOTE: delta is negative. */
+ /* NOTE: delta is non-positive. */
delta = hb_max (delta, (int) next - (int) count);
next -= delta;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc
index 01053ab737..f4ea21a4f9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc
@@ -54,6 +54,8 @@
#include "hb-aat-layout-morx-table.hh"
#include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise.
+using OT::Layout::GSUB::GSUB;
+
/**
* SECTION:hb-ot-layout
* @title: hb-ot-layout
@@ -389,7 +391,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
*/
bool
-OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
+GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
hb_face_t *face) const
{
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
@@ -1006,7 +1008,7 @@ struct hb_collect_features_context_t
hb_collect_features_context_t (hb_face_t *face,
hb_tag_t table_tag,
hb_set_t *feature_indices_,
- const hb_tag_t *features)
+ const hb_tag_t *features)
: g (get_gsubgpos_table (face, table_tag)),
feature_indices (feature_indices_),
@@ -1033,7 +1035,7 @@ struct hb_collect_features_context_t
{
hb_tag_t tag = g.get_feature_tag (i);
if (features_set.has (tag))
- feature_indices_filter.add(i);
+ feature_indices_filter.add(i);
}
}
@@ -1529,7 +1531,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_map_t done_lookups_glyph_count;
hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
- const OT::GSUB& gsub = *face->table.GSUB->table;
+ const GSUB& gsub = *face->table.GSUB->table;
unsigned int iteration_count = 0;
unsigned int glyphs_length;
@@ -1808,7 +1810,7 @@ struct GSUBProxy
table (*face->table.GSUB->table),
accels (face->table.GSUB->accels) {}
- const OT::GSUB &table;
+ const GSUB &table;
const OT::hb_ot_layout_lookup_accelerator_t *accels;
};
@@ -1929,6 +1931,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
c.set_random (lookups[table_index][i].random);
+ c.set_per_syllable (lookups[table_index][i].per_syllable);
apply_string<Proxy> (&c,
proxy.table.get_lookup (lookup_index),
@@ -2086,11 +2089,11 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
hb_position_t *coord /* OUT */)
{
if (hb_ot_layout_get_baseline (font,
- baseline_tag,
- direction,
- script_tag,
- language_tag,
- coord))
+ baseline_tag,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
return;
/* Synthesize missing baselines.
@@ -2107,17 +2110,19 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
hb_codepoint_t glyph;
hb_glyph_extents_t extents;
if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
- (hb_font_get_nominal_glyph (font, 0x2212u, &glyph) ||
- hb_font_get_nominal_glyph (font, '-', &glyph)) &&
- hb_font_get_glyph_extents (font, glyph, &extents))
+ (hb_font_get_nominal_glyph (font, 0x2212u, &glyph) ||
+ hb_font_get_nominal_glyph (font, '-', &glyph)) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
{
- *coord = extents.y_bearing + extents.height / 2;
+ *coord = extents.y_bearing + extents.height / 2;
}
else
{
- hb_position_t x_height = 0;
- hb_ot_metrics_get_position (font, HB_OT_METRICS_TAG_X_HEIGHT, &x_height);
- *coord = x_height / 2;
+ hb_position_t x_height = font->y_scale / 2;
+#ifndef HB_NO_METRICS
+ hb_ot_metrics_get_position_with_fallback (font, HB_OT_METRICS_TAG_X_HEIGHT, &x_height);
+#endif
+ *coord = x_height / 2;
}
}
break;
@@ -2128,32 +2133,32 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
hb_position_t embox_top, embox_bottom;
hb_ot_layout_get_baseline_with_fallback (font,
- HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
- direction,
- script_tag,
- language_tag,
- &embox_top);
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_top);
hb_ot_layout_get_baseline_with_fallback (font,
- HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
- direction,
- script_tag,
- language_tag,
- &embox_bottom);
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_bottom);
if (baseline_tag == HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT)
- *coord = embox_top + (embox_bottom - embox_top) / 10;
+ *coord = embox_top + (embox_bottom - embox_top) / 10;
else
- *coord = embox_bottom + (embox_top - embox_bottom) / 10;
+ *coord = embox_bottom + (embox_top - embox_bottom) / 10;
}
break;
case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT:
if (hb_ot_layout_get_baseline (font,
- HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
- direction,
- script_tag,
- language_tag,
- coord))
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
*coord += HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
else
{
@@ -2165,11 +2170,11 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT:
if (hb_ot_layout_get_baseline (font,
- HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
- direction,
- script_tag,
- language_tag,
- coord))
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
*coord -= HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
else
{
@@ -2226,11 +2231,11 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
}
if (ch &&
- hb_font_get_nominal_glyph (font, ch, &glyph) &&
- hb_font_get_glyph_extents (font, glyph, &extents))
- *coord = extents.y_bearing;
+ hb_font_get_nominal_glyph (font, ch, &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *coord = extents.y_bearing;
else
- *coord = font->y_scale * 6 / 10; // FIXME makes assumptions about origin
+ *coord = font->y_scale * 6 / 10; // FIXME makes assumptions about origin
}
else
*coord = font->x_scale * 6 / 10; // FIXME makes assumptions about origin
@@ -2240,17 +2245,17 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
{
hb_position_t top, bottom;
hb_ot_layout_get_baseline_with_fallback (font,
- HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
- direction,
- script_tag,
- language_tag,
- &top);
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
hb_ot_layout_get_baseline_with_fallback (font,
- HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
- direction,
- script_tag,
- language_tag,
- &bottom);
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
*coord = (top + bottom) / 2;
}
@@ -2260,17 +2265,17 @@ hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
{
hb_position_t top, bottom;
hb_ot_layout_get_baseline_with_fallback (font,
- HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT,
- direction,
- script_tag,
- language_tag,
- &top);
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
hb_ot_layout_get_baseline_with_fallback (font,
- HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT,
- direction,
- script_tag,
- language_tag,
- &bottom);
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
*coord = (top + bottom) / 2;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh
index ede8f007db..75bba0bc50 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh
@@ -108,13 +108,17 @@ hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
namespace OT {
struct hb_ot_apply_context_t;
- struct SubstLookup;
struct hb_ot_layout_lookup_accelerator_t;
+namespace Layout {
+namespace GSUB {
+ struct SubstLookup;
+}
+}
}
HB_INTERNAL void
hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
- const OT::SubstLookup &lookup,
+ const OT::Layout::GSUB::SubstLookup &lookup,
const OT::hb_ot_layout_lookup_accelerator_t &accel);
@@ -168,17 +172,6 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
return start;
}
-static inline void
-_hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- hb_glyph_info_t *info = buffer->info;
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- info[i].syllable() = 0;
-}
-
/* unicode_props */
@@ -485,6 +478,8 @@ static inline uint8_t
_hb_allocate_lig_id (hb_buffer_t *buffer)
{
uint8_t lig_id = buffer->next_serial () & 0x07;
+ if (unlikely (!lig_id))
+ lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
return lig_id;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-map.cc b/thirdparty/harfbuzz/src/hb-ot-map.cc
index 12ceea5785..f085c78ff8 100644
--- a/thirdparty/harfbuzz/src/hb-ot-map.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-map.cc
@@ -117,7 +117,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
hb_mask_t mask,
bool auto_zwnj,
bool auto_zwj,
- bool random)
+ bool random,
+ bool per_syllable)
{
unsigned int lookup_indices[32];
unsigned int offset, len;
@@ -145,6 +146,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
lookup->auto_zwnj = auto_zwnj;
lookup->auto_zwj = auto_zwj;
lookup->random = random;
+ lookup->per_syllable = per_syllable;
}
offset += len;
@@ -277,6 +279,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ);
map->auto_zwj = !(info->flags & F_MANUAL_ZWJ);
map->random = !!(info->flags & F_RANDOM);
+ map->per_syllable = !!(info->flags & F_PER_SYLLABLE);
if ((info->flags & F_GLOBAL) && info->max_value == 1) {
/* Uses the global bit */
map->shift = global_bit_shift;
@@ -319,7 +322,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
m.features[i].mask,
m.features[i].auto_zwnj,
m.features[i].auto_zwj,
- m.features[i].random);
+ m.features[i].random,
+ m.features[i].per_syllable);
/* Sort lookups and merge duplicates */
if (last_num_lookups < m.lookups[table_index].length)
diff --git a/thirdparty/harfbuzz/src/hb-ot-map.hh b/thirdparty/harfbuzz/src/hb-ot-map.hh
index 5f2afae281..f1cbf752fc 100644
--- a/thirdparty/harfbuzz/src/hb-ot-map.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-map.hh
@@ -56,6 +56,7 @@ struct hb_ot_map_t
unsigned int auto_zwnj : 1;
unsigned int auto_zwj : 1;
unsigned int random : 1;
+ unsigned int per_syllable : 1;
int cmp (const hb_tag_t tag_) const
{ return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
@@ -66,6 +67,7 @@ struct hb_ot_map_t
unsigned short auto_zwnj : 1;
unsigned short auto_zwj : 1;
unsigned short random : 1;
+ unsigned short per_syllable : 1;
hb_mask_t mask;
HB_INTERNAL static int cmp (const void *pa, const void *pb)
@@ -183,7 +185,8 @@ enum hb_ot_map_feature_flags_t
F_GLOBAL_MANUAL_JOINERS= F_GLOBAL | F_MANUAL_JOINERS,
F_GLOBAL_HAS_FALLBACK = F_GLOBAL | F_HAS_FALLBACK,
F_GLOBAL_SEARCH = 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */
- F_RANDOM = 0x0020u /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
+ F_RANDOM = 0x0020u, /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
+ F_PER_SYLLABLE = 0x0040u /* Contain lookup application to within syllable. */
};
HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
@@ -237,7 +240,8 @@ struct hb_ot_map_builder_t
hb_mask_t mask,
bool auto_zwnj = true,
bool auto_zwj = true,
- bool random = false);
+ bool random = false,
+ bool per_syllable = false);
struct feature_info_t {
hb_tag_t tag;
diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.cc b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
index 43c3cbd41f..f9c4b96fff 100644
--- a/thirdparty/harfbuzz/src/hb-ot-metrics.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
@@ -316,9 +316,9 @@ hb_ot_metrics_get_position_with_fallback (hb_font_t *font,
break;
case HB_OT_METRICS_TAG_X_HEIGHT:
- if (hb_font_get_nominal_glyph (font, 'o', &glyph) &&
+ if (hb_font_get_nominal_glyph (font, 'x', &glyph) &&
hb_font_get_glyph_extents (font, glyph, &extents))
- *position = extents.height + 2 * extents.y_bearing;
+ *position = extents.y_bearing;
else
*position = font->y_scale / 2;
break;
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
index 4a8781c8f8..c80f7df6a9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
@@ -109,17 +109,17 @@ indic_features[] =
* These features are applied in order, one at a time, after initial_reordering,
* constrained to the syllable.
*/
- {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('r','p','h','f'), F_MANUAL_JOINERS},
- {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
- {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
- {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS},
- {HB_TAG('h','a','l','f'), F_MANUAL_JOINERS},
- {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS},
- {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
+ {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('r','p','h','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('h','a','l','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
/*
* Other features.
* These features are applied all at once, after final_reordering, constrained
@@ -127,12 +127,12 @@ indic_features[] =
* Default Bengali font in Windows for example has intermixed
* lookups for init,pres,abvs,blws features.
*/
- {HB_TAG('i','n','i','t'), F_MANUAL_JOINERS},
- {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS},
+ {HB_TAG('i','n','i','t'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
};
/*
@@ -183,10 +183,10 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables_indic);
- map->enable_feature (HB_TAG('l','o','c','l'));
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
/* The Indic specs do not require ccmp, but we apply it here since if
* there is a use of it, it's typically at the beginning. */
- map->enable_feature (HB_TAG('c','c','m','p'));
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
unsigned int i = 0;
@@ -201,8 +201,6 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
for (; i < INDIC_NUM_FEATURES; i++)
map->add_feature (indic_features[i]);
-
- map->add_gsub_pause (_hb_clear_syllables);
}
static void
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
index dcb28a4e84..da77a2887c 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
@@ -368,6 +368,7 @@ set_indic_properties (hb_glyph_info_t &info)
else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */
else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
+ else if (unlikely (u == 0x0D04u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/3511 */
else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
cat = OT_PLACEHOLDER;
else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc
index 7787886857..d7ec1632ea 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc
@@ -45,11 +45,11 @@ khmer_features[] =
* These features are applied all at once, before reordering, constrained
* to the syllable.
*/
- {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
- {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
- {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS},
- {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS},
- {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS},
+ {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
/*
* Other features.
* These features are applied all at once after clearing syllables.
@@ -107,16 +107,10 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
*
* https://github.com/harfbuzz/harfbuzz/issues/974
*/
- map->enable_feature (HB_TAG('l','o','c','l'));
- map->enable_feature (HB_TAG('c','c','m','p'));
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
- unsigned int i = 0;
- for (; i < KHMER_BASIC_FEATURES; i++)
- map->add_feature (khmer_features[i]);
-
- map->add_gsub_pause (_hb_clear_syllables);
-
- for (; i < KHMER_NUM_FEATURES; i++)
+ for (unsigned i = 0; i < KHMER_NUM_FEATURES; i++)
map->add_feature (khmer_features[i]);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
index e6ae75e8f2..c7aa80a79a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
@@ -79,22 +79,20 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables_myanmar);
- map->enable_feature (HB_TAG('l','o','c','l'));
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
/* The Indic specs do not require ccmp, but we apply it here since if
* there is a use of it, it's typically at the beginning. */
- map->enable_feature (HB_TAG('c','c','m','p'));
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
map->add_gsub_pause (reorder_myanmar);
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_basic_features); i++)
{
- map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ);
+ map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (nullptr);
}
- map->add_gsub_pause (_hb_clear_syllables);
-
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
index 54f69c8284..468bd95c3f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
@@ -69,7 +69,7 @@ enum use_syllable_type_t {
#define use_syllable_machine_ex_GB 5u
#define use_syllable_machine_ex_H 12u
#define use_syllable_machine_ex_HN 13u
-#define use_syllable_machine_ex_HVM 44u
+#define use_syllable_machine_ex_IS 44u
#define use_syllable_machine_ex_J 50u
#define use_syllable_machine_ex_MAbv 27u
#define use_syllable_machine_ex_MBlw 28u
@@ -98,406 +98,443 @@ enum use_syllable_type_t {
#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, 1u, 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u,
- 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u,
- 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 11u, 48u, 1u, 48u,
- 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u,
+ 0u, 51u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u,
+ 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u,
+ 23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u,
+ 1u, 1u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u,
24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
- 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u,
- 11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u,
- 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u,
- 24u, 48u, 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u,
- 22u, 48u, 11u, 48u, 1u, 48u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u,
- 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
- 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u,
- 11u, 48u, 1u, 48u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u, 41u, 42u, 42u, 42u,
- 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0
+ 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u,
+ 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u,
+ 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
+ 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
+ 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 11u, 48u, 11u, 48u,
+ 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
+ 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
+ 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 4u, 4u, 13u, 13u,
+ 1u, 48u, 11u, 48u, 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u,
+ 0
};
static const char _use_syllable_machine_key_spans[] = {
- 52, 38, 38, 1, 27, 26, 24, 23,
- 22, 2, 1, 25, 25, 25, 1, 25,
- 26, 26, 26, 27, 27, 27, 38, 48,
- 38, 2, 1, 38, 38, 1, 27, 26,
- 24, 23, 22, 2, 1, 25, 25, 25,
- 1, 25, 26, 26, 26, 27, 27, 27,
- 38, 48, 1, 1, 38, 38, 1, 27,
- 26, 24, 23, 22, 2, 1, 25, 25,
- 25, 1, 25, 26, 26, 26, 27, 27,
- 27, 38, 48, 38, 38, 1, 27, 26,
+ 52, 38, 38, 48, 26, 24, 23, 22,
+ 2, 1, 25, 25, 25, 1, 25, 27,
+ 26, 26, 26, 37, 37, 37, 37, 38,
+ 1, 38, 2, 1, 38, 38, 48, 26,
24, 23, 22, 2, 1, 25, 25, 25,
- 1, 25, 26, 26, 26, 27, 27, 27,
- 38, 48, 1, 1, 48, 38, 2, 1,
- 5, 3, 4, 3
+ 1, 25, 27, 26, 26, 26, 37, 37,
+ 37, 37, 38, 1, 1, 1, 38, 38,
+ 48, 26, 24, 23, 22, 2, 1, 25,
+ 25, 25, 1, 25, 27, 26, 26, 26,
+ 37, 37, 37, 37, 38, 1, 38, 38,
+ 48, 26, 24, 23, 22, 2, 1, 25,
+ 25, 25, 1, 25, 27, 26, 26, 26,
+ 37, 37, 37, 37, 38, 1, 1, 1,
+ 48, 38, 2, 1, 5, 3, 4, 3
};
static const short _use_syllable_machine_index_offsets[] = {
- 0, 53, 92, 131, 133, 161, 188, 213,
- 237, 260, 263, 265, 291, 317, 343, 345,
- 371, 398, 425, 452, 480, 508, 536, 575,
- 624, 663, 666, 668, 707, 746, 748, 776,
- 803, 828, 852, 875, 878, 880, 906, 932,
- 958, 960, 986, 1013, 1040, 1067, 1095, 1123,
- 1151, 1190, 1239, 1241, 1243, 1282, 1321, 1323,
- 1351, 1378, 1403, 1427, 1450, 1453, 1455, 1481,
- 1507, 1533, 1535, 1561, 1588, 1615, 1642, 1670,
- 1698, 1726, 1765, 1814, 1853, 1892, 1894, 1922,
- 1949, 1974, 1998, 2021, 2024, 2026, 2052, 2078,
- 2104, 2106, 2132, 2159, 2186, 2213, 2241, 2269,
- 2297, 2336, 2385, 2387, 2389, 2438, 2477, 2480,
- 2482, 2488, 2492, 2497
+ 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, 9, 16, 17,
- 18, 19, 20, 21, 2, 22, 23, 24,
- 2, 25, 26, 27, 28, 29, 30, 31,
- 6, 32, 2, 33, 2, 35, 36, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 37, 38, 39, 40, 41, 42, 43, 37,
- 44, 45, 46, 47, 48, 49, 34, 50,
- 51, 52, 34, 53, 54, 34, 55, 56,
- 57, 58, 36, 34, 35, 36, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 37,
- 38, 39, 40, 41, 42, 43, 37, 44,
- 46, 46, 47, 48, 49, 34, 50, 51,
- 52, 34, 34, 34, 34, 55, 56, 57,
- 58, 36, 34, 35, 34, 37, 38, 39,
- 40, 41, 34, 34, 34, 34, 34, 34,
- 47, 48, 49, 34, 50, 51, 52, 34,
- 34, 34, 34, 38, 56, 57, 58, 59,
- 34, 38, 39, 40, 41, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 50,
- 51, 52, 34, 34, 34, 34, 34, 56,
- 57, 58, 59, 34, 39, 40, 41, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 56, 57, 58, 34, 40, 41, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 56, 57, 58, 34, 41, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 56, 57, 58, 34, 56, 57, 34, 57,
- 34, 39, 40, 41, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 50, 51,
- 52, 34, 34, 34, 34, 34, 56, 57,
- 58, 59, 34, 39, 40, 41, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 51, 52, 34, 34, 34, 34, 34,
- 56, 57, 58, 59, 34, 39, 40, 41,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 52, 34, 34, 34,
- 34, 34, 56, 57, 58, 59, 34, 60,
- 34, 39, 40, 41, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 56, 57,
- 58, 59, 34, 38, 39, 40, 41, 34,
- 34, 34, 34, 34, 34, 47, 48, 49,
- 34, 50, 51, 52, 34, 34, 34, 34,
- 38, 56, 57, 58, 59, 34, 38, 39,
- 40, 41, 34, 34, 34, 34, 34, 34,
- 34, 48, 49, 34, 50, 51, 52, 34,
- 34, 34, 34, 38, 56, 57, 58, 59,
- 34, 38, 39, 40, 41, 34, 34, 34,
- 34, 34, 34, 34, 34, 49, 34, 50,
- 51, 52, 34, 34, 34, 34, 38, 56,
- 57, 58, 59, 34, 37, 38, 39, 40,
- 41, 34, 43, 37, 34, 34, 34, 47,
- 48, 49, 34, 50, 51, 52, 34, 34,
- 34, 34, 38, 56, 57, 58, 59, 34,
- 37, 38, 39, 40, 41, 34, 34, 37,
- 34, 34, 34, 47, 48, 49, 34, 50,
- 51, 52, 34, 34, 34, 34, 38, 56,
- 57, 58, 59, 34, 37, 38, 39, 40,
- 41, 42, 43, 37, 34, 34, 34, 47,
- 48, 49, 34, 50, 51, 52, 34, 34,
- 34, 34, 38, 56, 57, 58, 59, 34,
- 35, 36, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 37, 38, 39, 40, 41,
- 42, 43, 37, 44, 34, 46, 47, 48,
- 49, 34, 50, 51, 52, 34, 34, 34,
- 34, 55, 56, 57, 58, 36, 34, 35,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 38, 39, 40,
- 41, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 50, 51, 52, 34, 34,
- 34, 34, 34, 56, 57, 58, 59, 34,
- 35, 36, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 37, 38, 39, 40, 41,
- 42, 43, 37, 44, 45, 46, 47, 48,
- 49, 34, 50, 51, 52, 34, 34, 34,
- 34, 55, 56, 57, 58, 36, 34, 53,
- 54, 34, 54, 34, 62, 63, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 64,
- 65, 66, 67, 68, 69, 70, 64, 71,
- 1, 72, 73, 74, 75, 61, 76, 77,
- 78, 61, 61, 61, 61, 79, 80, 81,
- 82, 63, 61, 62, 63, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 64, 65,
- 66, 67, 68, 69, 70, 64, 71, 72,
- 72, 73, 74, 75, 61, 76, 77, 78,
- 61, 61, 61, 61, 79, 80, 81, 82,
- 63, 61, 62, 83, 64, 65, 66, 67,
- 68, 61, 61, 61, 61, 61, 61, 73,
- 74, 75, 61, 76, 77, 78, 61, 61,
- 61, 61, 65, 80, 81, 82, 84, 61,
- 65, 66, 67, 68, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 76, 77,
- 78, 61, 61, 61, 61, 61, 80, 81,
- 82, 84, 61, 66, 67, 68, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 80, 81, 82, 61, 67, 68, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 80, 81, 82, 61, 68, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 80,
- 81, 82, 61, 80, 81, 61, 81, 61,
- 66, 67, 68, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 76, 77, 78,
- 61, 61, 61, 61, 61, 80, 81, 82,
- 84, 61, 66, 67, 68, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 77, 78, 61, 61, 61, 61, 61, 80,
- 81, 82, 84, 61, 66, 67, 68, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 78, 61, 61, 61, 61,
- 61, 80, 81, 82, 84, 61, 86, 85,
- 66, 67, 68, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 80, 81, 82,
- 84, 61, 65, 66, 67, 68, 61, 61,
- 61, 61, 61, 61, 73, 74, 75, 61,
- 76, 77, 78, 61, 61, 61, 61, 65,
- 80, 81, 82, 84, 61, 65, 66, 67,
- 68, 61, 61, 61, 61, 61, 61, 61,
- 74, 75, 61, 76, 77, 78, 61, 61,
- 61, 61, 65, 80, 81, 82, 84, 61,
- 65, 66, 67, 68, 61, 61, 61, 61,
- 61, 61, 61, 61, 75, 61, 76, 77,
- 78, 61, 61, 61, 61, 65, 80, 81,
- 82, 84, 61, 64, 65, 66, 67, 68,
- 61, 70, 64, 61, 61, 61, 73, 74,
- 75, 61, 76, 77, 78, 61, 61, 61,
- 61, 65, 80, 81, 82, 84, 61, 64,
- 65, 66, 67, 68, 61, 61, 64, 61,
- 61, 61, 73, 74, 75, 61, 76, 77,
- 78, 61, 61, 61, 61, 65, 80, 81,
- 82, 84, 61, 64, 65, 66, 67, 68,
- 69, 70, 64, 61, 61, 61, 73, 74,
- 75, 61, 76, 77, 78, 61, 61, 61,
- 61, 65, 80, 81, 82, 84, 61, 62,
- 63, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 64, 65, 66, 67, 68, 69,
- 70, 64, 71, 61, 72, 73, 74, 75,
- 61, 76, 77, 78, 61, 61, 61, 61,
- 79, 80, 81, 82, 63, 61, 62, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 65, 66, 67, 68,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 76, 77, 78, 83, 83, 83,
- 83, 83, 80, 81, 82, 84, 83, 88,
- 87, 3, 89, 90, 91, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 92, 93,
- 94, 95, 96, 97, 98, 92, 99, 100,
- 101, 102, 103, 104, 61, 105, 106, 107,
- 61, 53, 54, 61, 108, 109, 110, 82,
- 91, 61, 90, 91, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 92, 93, 94,
- 95, 96, 97, 98, 92, 99, 101, 101,
- 102, 103, 104, 61, 105, 106, 107, 61,
- 61, 61, 61, 108, 109, 110, 82, 91,
- 61, 90, 83, 92, 93, 94, 95, 96,
- 61, 61, 61, 61, 61, 61, 102, 103,
- 104, 61, 105, 106, 107, 61, 61, 61,
- 61, 93, 109, 110, 82, 111, 61, 93,
- 94, 95, 96, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 105, 106, 107,
- 61, 61, 61, 61, 61, 109, 110, 82,
- 111, 61, 94, 95, 96, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 109,
- 110, 82, 61, 95, 96, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 109,
- 110, 82, 61, 96, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 109, 110,
- 82, 61, 109, 110, 61, 110, 61, 94,
- 95, 96, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 105, 106, 107, 61,
- 61, 61, 61, 61, 109, 110, 82, 111,
- 61, 94, 95, 96, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 106,
- 107, 61, 61, 61, 61, 61, 109, 110,
- 82, 111, 61, 94, 95, 96, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 107, 61, 61, 61, 61, 61,
- 109, 110, 82, 111, 61, 112, 85, 94,
- 95, 96, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 109, 110, 82, 111,
- 61, 93, 94, 95, 96, 61, 61, 61,
- 61, 61, 61, 102, 103, 104, 61, 105,
- 106, 107, 61, 61, 61, 61, 93, 109,
- 110, 82, 111, 61, 93, 94, 95, 96,
- 61, 61, 61, 61, 61, 61, 61, 103,
- 104, 61, 105, 106, 107, 61, 61, 61,
- 61, 93, 109, 110, 82, 111, 61, 93,
- 94, 95, 96, 61, 61, 61, 61, 61,
- 61, 61, 61, 104, 61, 105, 106, 107,
- 61, 61, 61, 61, 93, 109, 110, 82,
- 111, 61, 92, 93, 94, 95, 96, 61,
- 98, 92, 61, 61, 61, 102, 103, 104,
- 61, 105, 106, 107, 61, 61, 61, 61,
- 93, 109, 110, 82, 111, 61, 92, 93,
- 94, 95, 96, 61, 61, 92, 61, 61,
- 61, 102, 103, 104, 61, 105, 106, 107,
- 61, 61, 61, 61, 93, 109, 110, 82,
- 111, 61, 92, 93, 94, 95, 96, 97,
- 98, 92, 61, 61, 61, 102, 103, 104,
- 61, 105, 106, 107, 61, 61, 61, 61,
- 93, 109, 110, 82, 111, 61, 90, 91,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 92, 93, 94, 95, 96, 97, 98,
- 92, 99, 61, 101, 102, 103, 104, 61,
- 105, 106, 107, 61, 61, 61, 61, 108,
- 109, 110, 82, 91, 61, 90, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 93, 94, 95, 96, 83,
- 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 105, 106, 107, 83, 83, 83, 83,
- 83, 109, 110, 82, 111, 83, 90, 91,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 92, 93, 94, 95, 96, 97, 98,
- 92, 99, 100, 101, 102, 103, 104, 61,
- 105, 106, 107, 61, 61, 61, 61, 108,
- 109, 110, 82, 91, 61, 5, 6, 113,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 9, 10, 11, 12, 13, 14, 15, 9,
- 16, 18, 18, 19, 20, 21, 113, 22,
- 23, 24, 113, 113, 113, 113, 28, 29,
- 30, 31, 6, 113, 5, 113, 9, 10,
- 11, 12, 13, 113, 113, 113, 113, 113,
- 113, 19, 20, 21, 113, 22, 23, 24,
- 113, 113, 113, 113, 10, 29, 30, 31,
- 114, 113, 10, 11, 12, 13, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 22, 23, 24, 113, 113, 113, 113, 113,
- 29, 30, 31, 114, 113, 11, 12, 13,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 29, 30, 31, 113, 12, 13,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 29, 30, 31, 113, 13, 113,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 29, 30, 31, 113, 29, 30, 113,
- 30, 113, 11, 12, 13, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 22,
- 23, 24, 113, 113, 113, 113, 113, 29,
- 30, 31, 114, 113, 11, 12, 13, 113,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 23, 24, 113, 113, 113, 113,
- 113, 29, 30, 31, 114, 113, 11, 12,
- 13, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 24, 113, 113,
- 113, 113, 113, 29, 30, 31, 114, 113,
- 115, 113, 11, 12, 13, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 29,
- 30, 31, 114, 113, 10, 11, 12, 13,
- 113, 113, 113, 113, 113, 113, 19, 20,
- 21, 113, 22, 23, 24, 113, 113, 113,
- 113, 10, 29, 30, 31, 114, 113, 10,
- 11, 12, 13, 113, 113, 113, 113, 113,
- 113, 113, 20, 21, 113, 22, 23, 24,
- 113, 113, 113, 113, 10, 29, 30, 31,
- 114, 113, 10, 11, 12, 13, 113, 113,
- 113, 113, 113, 113, 113, 113, 21, 113,
- 22, 23, 24, 113, 113, 113, 113, 10,
- 29, 30, 31, 114, 113, 9, 10, 11,
- 12, 13, 113, 15, 9, 113, 113, 113,
- 19, 20, 21, 113, 22, 23, 24, 113,
- 113, 113, 113, 10, 29, 30, 31, 114,
- 113, 9, 10, 11, 12, 13, 113, 113,
- 9, 113, 113, 113, 19, 20, 21, 113,
- 22, 23, 24, 113, 113, 113, 113, 10,
- 29, 30, 31, 114, 113, 9, 10, 11,
- 12, 13, 14, 15, 9, 113, 113, 113,
- 19, 20, 21, 113, 22, 23, 24, 113,
- 113, 113, 113, 10, 29, 30, 31, 114,
- 113, 5, 6, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 9, 10, 11, 12,
- 13, 14, 15, 9, 16, 113, 18, 19,
- 20, 21, 113, 22, 23, 24, 113, 113,
- 113, 113, 28, 29, 30, 31, 6, 113,
- 5, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 10, 11,
- 12, 13, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 22, 23, 24, 113,
- 113, 113, 113, 113, 29, 30, 31, 114,
- 113, 116, 113, 7, 113, 1, 113, 113,
- 113, 1, 113, 113, 113, 113, 113, 5,
- 6, 7, 113, 113, 113, 113, 113, 113,
- 113, 113, 9, 10, 11, 12, 13, 14,
- 15, 9, 16, 17, 18, 19, 20, 21,
- 113, 22, 23, 24, 113, 25, 26, 113,
- 28, 29, 30, 31, 6, 113, 5, 6,
- 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 9, 10, 11, 12, 13, 14, 15,
- 9, 16, 17, 18, 19, 20, 21, 113,
- 22, 23, 24, 113, 113, 113, 113, 28,
- 29, 30, 31, 6, 113, 25, 26, 113,
- 26, 113, 1, 117, 117, 117, 1, 117,
- 119, 118, 32, 118, 32, 119, 118, 119,
- 118, 32, 118, 33, 118, 0
+ 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, 27, 0, 50, 52, 76, 77, 98,
- 100, 78, 79, 80, 81, 82, 93, 94,
- 95, 101, 96, 90, 91, 92, 85, 86,
- 87, 102, 103, 104, 97, 83, 84, 0,
- 105, 107, 0, 2, 3, 4, 5, 6,
- 7, 8, 19, 20, 21, 24, 22, 16,
- 17, 18, 11, 12, 13, 25, 26, 23,
- 9, 10, 0, 14, 15, 0, 28, 29,
- 30, 31, 32, 33, 34, 45, 46, 47,
- 48, 42, 43, 44, 37, 38, 39, 49,
- 35, 36, 0, 0, 40, 0, 41, 0,
- 51, 0, 53, 54, 55, 56, 57, 58,
- 59, 70, 71, 72, 75, 73, 67, 68,
- 69, 62, 63, 64, 74, 60, 61, 65,
- 66, 0, 88, 89, 99, 0, 0, 106
+ 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, 4,
- 0, 0, 5, 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, 6, 0, 0, 7, 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, 8, 9, 0, 10, 0, 11,
- 0, 12, 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, 13, 0, 0, 0, 14, 15, 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[] = {
@@ -514,7 +551,7 @@ static const char _use_syllable_machine_to_state_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0
};
static const char _use_syllable_machine_from_state_actions[] = {
@@ -531,24 +568,24 @@ static const char _use_syllable_machine_from_state_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0
};
static const short _use_syllable_machine_eof_trans[] = {
- 0, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 62, 62, 84, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62,
- 86, 62, 62, 62, 62, 62, 62, 62,
- 62, 84, 88, 90, 62, 62, 84, 62,
- 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 86, 62, 62, 62, 62, 62, 62,
- 62, 62, 84, 62, 114, 114, 114, 114,
- 114, 114, 114, 114, 114, 114, 114, 114,
- 114, 114, 114, 114, 114, 114, 114, 114,
- 114, 114, 114, 114, 114, 114, 114, 114,
- 118, 119, 119, 119
+ 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;
@@ -583,7 +620,7 @@ struct machine_index_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) {}
+ 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;
@@ -595,14 +632,28 @@ struct machine_index_t :
void __forward__ (unsigned n) { it += n; }
void __prev__ () { --it; }
void __rewind__ (unsigned n) { it -= n; }
+
void operator = (unsigned n)
- { unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; }
- void operator = (const machine_index_t& o) { *this = (*o.it).first; }
- bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; }
+ {
+ assert (n == 0);
+ is_null = true;
+ }
+ explicit operator bool () { return !is_null; }
+
+ void operator = (const machine_index_t& o)
+ {
+ is_null = o.is_null;
+ unsigned index = (*it).first;
+ unsigned n = (*o.it).first;
+ if (index < n) it += n - index; else if (index > n) it -= index - n;
+ }
+ bool operator == (const machine_index_t& o) const
+ { return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
bool operator != (const machine_index_t& o) const { return !(*this == o); }
private:
Iter it;
+ bool is_null = false;
};
struct
{
@@ -647,7 +698,7 @@ find_syllables_use (hb_buffer_t *buffer)
unsigned int act HB_UNUSED;
int cs;
-#line 651 "hb-ot-shape-complex-use-machine.hh"
+#line 702 "hb-ot-shape-complex-use-machine.hh"
{
cs = use_syllable_machine_start;
ts = 0;
@@ -655,12 +706,12 @@ find_syllables_use (hb_buffer_t *buffer)
act = 0;
}
-#line 267 "hb-ot-shape-complex-use-machine.rl"
+#line 281 "hb-ot-shape-complex-use-machine.rl"
unsigned int syllable_serial = 1;
-#line 664 "hb-ot-shape-complex-use-machine.hh"
+#line 715 "hb-ot-shape-complex-use-machine.hh"
{
int _slen;
int _trans;
@@ -674,7 +725,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
-#line 678 "hb-ot-shape-complex-use-machine.hh"
+#line 729 "hb-ot-shape-complex-use-machine.hh"
}
_keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -692,7 +743,7 @@ _eof_trans:
goto _again;
switch ( _use_syllable_machine_trans_actions[_trans] ) {
- case 8:
+ case 9:
#line 171 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (use_standard_cluster); }}
break;
@@ -708,11 +759,7 @@ _eof_trans:
#line 177 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (use_non_cluster); }}
break;
- case 9:
-#line 169 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_virama_terminated_cluster); }}
- break;
- case 10:
+ case 11:
#line 170 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
break;
@@ -720,11 +767,11 @@ _eof_trans:
#line 171 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_standard_cluster); }}
break;
- case 12:
+ case 14:
#line 172 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
break;
- case 11:
+ case 13:
#line 173 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_numeral_cluster); }}
break;
@@ -732,19 +779,43 @@ _eof_trans:
#line 174 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_symbol_cluster); }}
break;
- case 15:
+ case 17:
#line 175 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
break;
- case 13:
+ case 15:
#line 176 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_broken_cluster); }}
break;
- case 14:
+ case 16:
#line 177 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_non_cluster); }}
break;
-#line 748 "hb-ot-shape-complex-use-machine.hh"
+ 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:
@@ -753,7 +824,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
-#line 757 "hb-ot-shape-complex-use-machine.hh"
+#line 828 "hb-ot-shape-complex-use-machine.hh"
}
if ( ++p != pe )
@@ -769,7 +840,7 @@ _again:
}
-#line 272 "hb-ot-shape-complex-use-machine.rl"
+#line 286 "hb-ot-shape-complex-use-machine.rl"
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
index 951fb28377..ea627cd27e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
@@ -53,7 +53,7 @@
#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 */
@@ -278,7 +278,7 @@ static const uint8_t use_table[] = {
/* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1020 */ B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VAbv, VAbv, VBlw,
- /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, H, VAbv, MPst, MPre, MBlw, MBlw, B,
+ /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B,
/* 1040 */ B, B, B, B, B, B, B, B, B, B, O, GB, O, O, GB, O,
/* 1050 */ B, B, B, B, B, B, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw,
/* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B,
@@ -316,7 +316,7 @@ static const uint8_t use_table[] = {
/* 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, H, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, WJ, WJ,
+ /* 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,
@@ -396,7 +396,7 @@ static const uint8_t use_table[] = {
/* 1B80 */ VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, H, SUB, SUB, B, B,
+ /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, IS, SUB, SUB, B, B,
/* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* Batak */
@@ -555,7 +555,7 @@ static const uint8_t use_table[] = {
/* Meetei Mayek Extensions */
/* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst,
- /* AAF0 */ O, O, O, O, O, VMPst, H, WJ,
+ /* AAF0 */ O, O, O, O, O, VMPst, IS, WJ,
#define use_offset_0xabc0u 4040
@@ -606,7 +606,7 @@ static const uint8_t use_table[] = {
/* 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, H,
+ /* 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
@@ -699,7 +699,7 @@ static const uint8_t use_table[] = {
/* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11120 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VBlw, VAbv, VAbv,
- /* 11130 */ VBlw, VAbv, VAbv, H, CMAbv, WJ, B, B, B, B, B, B, B, B, B, B,
+ /* 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 */
@@ -752,7 +752,7 @@ static const uint8_t use_table[] = {
/* 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, HVM, WJ, WJ,
+ /* 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,
@@ -842,7 +842,7 @@ static const uint8_t use_table[] = {
/* 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, H, R,
+ /* 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,
@@ -864,7 +864,7 @@ static const uint8_t use_table[] = {
/* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A30 */ B, B, B, FMBlw, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB,
- /* 11A40 */ O, O, O, O, O, GB, O, H, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 11A40 */ O, O, O, O, O, GB, O, IS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
/* Soyombo */
@@ -872,7 +872,7 @@ static const uint8_t use_table[] = {
/* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11A80 */ B, B, B, B, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw,
- /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, B, O, O,
+ /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, IS, O, O, O, B, O, O,
#define use_offset_0x11c00u 6592
@@ -904,7 +904,7 @@ static const uint8_t use_table[] = {
/* 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, H, R, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
+ /* 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 */
@@ -912,7 +912,7 @@ static const uint8_t use_table[] = {
/* 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, H, O, WJ, WJ, WJ, WJ, WJ, WJ, 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
@@ -1531,7 +1531,7 @@ hb_use_get_category (hb_glyph_info_t info)
#undef GB
#undef H
#undef HN
-#undef HVM
+#undef IS
#undef J
#undef N
#undef O
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc
index 95ef3fd6ec..1d13c8a126 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc
@@ -115,25 +115,24 @@ collect_features_use (hb_ot_shape_planner_t *plan)
map->add_gsub_pause (setup_syllables_use);
/* "Default glyph pre-processing group" */
- map->enable_feature (HB_TAG('l','o','c','l'));
- map->enable_feature (HB_TAG('c','c','m','p'));
- map->enable_feature (HB_TAG('n','u','k','t'));
- map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('n','u','k','t'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ | F_PER_SYLLABLE);
/* "Reordering group" */
map->add_gsub_pause (_hb_clear_substitution_flags);
- map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ);
+ map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (record_rphf_use);
map->add_gsub_pause (_hb_clear_substitution_flags);
- map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (record_pref_use);
/* "Orthographic unit shaping group" */
for (unsigned int i = 0; i < ARRAY_LENGTH (use_basic_features); i++)
- map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ);
+ map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (reorder_use);
- map->add_gsub_pause (_hb_clear_syllables);
/* "Topographical features" */
for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)
@@ -350,7 +349,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
static inline bool
is_halant_use (const hb_glyph_info_t &info)
{
- return (info.use_category() == USE(H) || info.use_category() == USE(HVM)) &&
+ return (info.use_category() == USE(H) || info.use_category() == USE(IS)) &&
!_hb_glyph_info_ligated (&info);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc
index 4bd8aaf03b..298cf47786 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc
@@ -935,17 +935,23 @@ hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
_hb_buffer_allocate_gsubgpos_vars (c->buffer);
hb_ot_substitute_complex (c);
+
+#ifndef HB_NO_AAT_SHAPE
+ if (c->plan->apply_morx && c->plan->apply_gpos)
+ hb_aat_layout_remove_deleted_glyphs (c->buffer);
+#endif
}
static inline void
hb_ot_substitute_post (const hb_ot_shape_context_t *c)
{
- hb_ot_hide_default_ignorables (c->buffer, c->font);
#ifndef HB_NO_AAT_SHAPE
- if (c->plan->apply_morx)
+ if (c->plan->apply_morx && !c->plan->apply_gpos)
hb_aat_layout_remove_deleted_glyphs (c->buffer);
#endif
+ hb_ot_hide_default_ignorables (c->buffer, c->font);
+
if (c->plan->shaper->postprocess_glyphs &&
c->buffer->message(c->font, "start postprocess-glyphs")) {
c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
index 539213c339..618cec08fb 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
@@ -577,10 +577,11 @@ struct gvar
hb_bytes_t bytes ((const char *) p, length);
hb_vector_t<unsigned int> private_indices;
- if (iterator.current_tuple->has_private_points () &&
+ bool has_private_points = iterator.current_tuple->has_private_points ();
+ if (has_private_points &&
!GlyphVariationData::unpack_points (p, private_indices, bytes))
return false;
- const hb_array_t<unsigned int> &indices = private_indices.length ? private_indices : shared_indices;
+ const hb_array_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
bool apply_to_all = (indices.length == 0);
unsigned int num_deltas = apply_to_all ? points.length : indices.length;
diff --git a/thirdparty/harfbuzz/src/hb-set.cc b/thirdparty/harfbuzz/src/hb-set.cc
index 204dbb5645..0e2c1f77ef 100644
--- a/thirdparty/harfbuzz/src/hb-set.cc
+++ b/thirdparty/harfbuzz/src/hb-set.cc
@@ -257,6 +257,29 @@ hb_set_add (hb_set_t *set,
}
/**
+ * hb_set_add_sorted_array:
+ * @set: A set
+ * @sorted_codepoints: (array length=num_codepoints): Array of codepoints to add
+ * @num_codepoints: Length of @sorted_codepoints
+ *
+ * Adds @num_codepoints codepoints to a set at once.
+ * The codepoints array must be in increasing order,
+ * with size at least @num_codepoints.
+ *
+ * Since: 4.1.0
+ */
+HB_EXTERN void
+hb_set_add_sorted_array (hb_set_t *set,
+ const hb_codepoint_t *sorted_codepoints,
+ unsigned int num_codepoints)
+{
+ /* Immutible-safe. */
+ set->add_sorted_array (sorted_codepoints,
+ num_codepoints,
+ sizeof(hb_codepoint_t));
+}
+
+/**
* hb_set_add_range:
* @set: A set
* @first: The first element to add to @set
@@ -591,3 +614,28 @@ hb_set_previous_range (const hb_set_t *set,
{
return set->previous_range (first, last);
}
+
+/**
+ * hb_set_next_many:
+ * @set: A set
+ * @codepoint: Outputting codepoints starting after this one.
+ * Use #HB_SET_VALUE_INVALID to get started.
+ * @out: (array length=size): An array of codepoints to write to.
+ * @size: The maximum number of codepoints to write out.
+ *
+ * Finds the next element in @set that is greater than @codepoint. Writes out
+ * codepoints to @out, until either the set runs out of elements, or @size
+ * codepoints are written, whichever comes first.
+ *
+ * Return value: the number of values written.
+ *
+ * Since: 4.2.0
+ **/
+unsigned int
+hb_set_next_many (const hb_set_t *set,
+ hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size)
+{
+ return set->next_many (codepoint, out, size);
+}
diff --git a/thirdparty/harfbuzz/src/hb-set.h b/thirdparty/harfbuzz/src/hb-set.h
index 423225bf96..10ce7c10d4 100644
--- a/thirdparty/harfbuzz/src/hb-set.h
+++ b/thirdparty/harfbuzz/src/hb-set.h
@@ -111,6 +111,11 @@ hb_set_add_range (hb_set_t *set,
hb_codepoint_t last);
HB_EXTERN void
+hb_set_add_sorted_array (hb_set_t *set,
+ const hb_codepoint_t *sorted_codepoints,
+ unsigned int num_codepoints);
+
+HB_EXTERN void
hb_set_del (hb_set_t *set,
hb_codepoint_t codepoint);
@@ -180,6 +185,12 @@ hb_set_previous_range (const hb_set_t *set,
hb_codepoint_t *first,
hb_codepoint_t *last);
+/* Pass HB_SET_VALUE_INVALID in to get started. */
+HB_EXTERN unsigned int
+hb_set_next_many (const hb_set_t *set,
+ hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size);
HB_END_DECLS
diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh
index af02e9e12b..1f05407869 100644
--- a/thirdparty/harfbuzz/src/hb-set.hh
+++ b/thirdparty/harfbuzz/src/hb-set.hh
@@ -109,6 +109,7 @@ struct hb_sparseset_t
typedef bool value_t;
value_t operator [] (hb_codepoint_t k) const { return get (k); }
bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
@@ -138,6 +139,8 @@ struct hb_sparseset_t
{ return s.next_range (first, last); }
bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
{ return s.previous_range (first, last); }
+ unsigned int next_many (hb_codepoint_t codepoint, hb_codepoint_t *out, unsigned int size) const
+ { return s.next_many (codepoint, out, size); }
unsigned int get_population () const { return s.get_population (); }
hb_codepoint_t get_min () const { return s.get_min (); }
diff --git a/thirdparty/harfbuzz/src/hb-static.cc b/thirdparty/harfbuzz/src/hb-static.cc
index bd698814e8..7cc51be611 100644
--- a/thirdparty/harfbuzz/src/hb-static.cc
+++ b/thirdparty/harfbuzz/src/hb-static.cc
@@ -56,6 +56,7 @@ const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
/* hb_face_t */
+#ifndef HB_NO_BORING_EXPANSION
static inline unsigned
load_num_glyphs_from_loca (const hb_face_t *face)
{
@@ -72,6 +73,7 @@ load_num_glyphs_from_loca (const hb_face_t *face)
return ret;
}
+#endif
static inline unsigned
load_num_glyphs_from_maxp (const hb_face_t *face)
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc
index 4481758415..74b7e3977c 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc
@@ -40,6 +40,8 @@
#include "hb-ot-stat-table.hh"
#include "hb-ot-math-table.hh"
+using OT::Layout::GSUB::GSUB;
+
typedef hb_hashmap_t<unsigned, hb_set_t *> script_langsys_map;
#ifndef HB_NO_SUBSET_CFF
@@ -358,7 +360,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
#ifndef HB_NO_SUBSET_LAYOUT
if (close_over_gsub)
// closure all glyphs/lookups/features needed for GSUB substitutions.
- _closure_glyphs_lookups_features<OT::GSUB> (
+ _closure_glyphs_lookups_features<GSUB> (
plan->source,
plan->_glyphset_gsub,
plan->layout_features,
diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc
index aa8f2c6fb0..4588268b76 100644
--- a/thirdparty/harfbuzz/src/hb-subset.cc
+++ b/thirdparty/harfbuzz/src/hb-subset.cc
@@ -55,6 +55,8 @@
#include "hb-ot-math-table.hh"
#include "hb-repacker.hh"
+using OT::Layout::GSUB::GSUB;
+
/**
* SECTION:hb-subset
* @title: hb-subset
@@ -312,7 +314,7 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
#ifndef HB_NO_SUBSET_LAYOUT
case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan);
- case HB_OT_TAG_GSUB: return _subset<const OT::GSUB> (plan);
+ case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan);
case HB_OT_TAG_GPOS: return _subset<const OT::GPOS> (plan);
case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan);
case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan);
diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h
index e6bb69a0f2..39fbde45c1 100644
--- a/thirdparty/harfbuzz/src/hb-version.h
+++ b/thirdparty/harfbuzz/src/hb-version.h
@@ -47,20 +47,20 @@ HB_BEGIN_DECLS
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 0
+#define HB_VERSION_MINOR 2
/**
* HB_VERSION_MICRO:
*
* The micro component of the library version available at compile-time.
*/
-#define HB_VERSION_MICRO 1
+#define HB_VERSION_MICRO 0
/**
* HB_VERSION_STRING:
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "4.0.1"
+#define HB_VERSION_STRING "4.2.0"
/**
* HB_VERSION_ATLEAST: